1#![no_std]
2#![allow(unsafe_code)]
3
4#[cfg(feature = "std")]
5extern crate std;
6
7#[cfg(feature = "std")]
8pub mod exports;
9
10pub const EVENT_OPENAT: u32 = 1;
11pub const EVENT_CONNECT: u32 = 2;
12pub const EVENT_FORK: u32 = 3;
13pub const EVENT_EXEC: u32 = 4;
14pub const EVENT_EXIT: u32 = 5;
15
16pub const KEY_MONITOR_ALL: u32 = 100;
17
18pub const EVENT_FILE_BLOCKED: u32 = 10;
19pub const EVENT_CONNECT_BLOCKED: u32 = 20;
20
21pub const DATA_LEN: usize = 512;
22
23#[repr(C)]
24#[derive(Clone, Copy, Debug, Eq, PartialEq)]
25pub struct MonitorEvent {
26 pub pid: u32,
27 pub event_type: u32,
28 pub data: [u8; DATA_LEN],
29}
30
31#[repr(C)]
45#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
46pub struct InodeKey {
47 pub ino: u64,
48 pub dev: u32,
49 pub gen: u32,
50}
51
52#[repr(C)]
56#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
57pub struct InodeKeyMap {
58 pub ino: u64,
59 pub dev: u32,
60 pub gen: u32,
61}
62
63#[cfg(target_os = "linux")]
67pub fn encode_kernel_dev(dev: u64) -> u32 {
68 let major = ((dev >> 8) & 0xfff) as u32;
72 let minor = ((dev & 0xff) | ((dev >> 12) & 0xfff00)) as u32;
73
74 (minor & 0xff) | ((major & 0xfff) << 8) | ((minor & 0xfffff00) << 12)
77}
78
79pub const EVENT_INODE_RESOLVED: u32 = 112;
81
82#[repr(C)]
84#[derive(Clone, Copy, Debug)]
85pub struct InodeResolved {
86 pub dev: u64, pub ino: u64, pub gen: u32, pub _pad: u32,
90}
91
92#[cfg(all(target_os = "linux", feature = "user"))]
93unsafe impl aya::Pod for InodeResolved {}
94
95#[cfg(all(target_os = "linux", feature = "user"))]
96unsafe impl aya::Pod for InodeKeyMap {}
97
98#[cfg(all(target_os = "linux", feature = "user"))]
99unsafe impl aya::Pod for InodeKey {}
100
101#[cfg(all(target_os = "linux", feature = "user"))]
102const _: () = {
103 fn _assert_pod<T: aya::Pod>() {}
104 fn _check() {
105 _assert_pod::<InodeKeyMap>();
106 }
107};
108
109impl MonitorEvent {
110 pub const fn zeroed() -> Self {
111 Self {
112 pid: 0,
113 event_type: 0,
114 data: [0u8; DATA_LEN],
115 }
116 }
117}
118
119impl Default for MonitorEvent {
120 fn default() -> Self {
121 Self::zeroed()
122 }
123}
124
125const _: [(); 520] = [(); core::mem::size_of::<MonitorEvent>()];
131
132const _: [(); 4] = [(); core::mem::align_of::<MonitorEvent>()];
134
135#[cfg(all(target_os = "linux", feature = "std"))]
136pub fn get_inode_generation(fd: std::os::fd::RawFd) -> std::io::Result<u32> {
137 use nix::libc;
138 use nix::request_code_read;
139
140 const fn fs_ioc_getversion() -> libc::c_ulong {
146 request_code_read!(b'v', 1, core::mem::size_of::<libc::c_long>()) as libc::c_ulong
147 }
148
149 let mut out: libc::c_long = 0;
150 let rc = unsafe { libc::ioctl(fd, fs_ioc_getversion() as _, &mut out) };
153 if rc < 0 {
154 return Err(std::io::Error::last_os_error());
155 }
156 Ok(out as u32)
157}
158
159#[cfg(all(target_os = "linux", feature = "std"))]
160pub mod strict_open {
161 use libc::c_long;
162 use std::{ffi::CStr, mem::size_of};
163
164 #[repr(C)]
165 pub struct OpenHow {
166 pub flags: u64,
167 pub mode: u64,
168 pub resolve: u64,
169 }
170
171 pub const RESOLVE_NO_SYMLINKS: u64 = 0x04;
173 pub fn openat2_strict(path: &CStr) -> std::io::Result<i32> {
176 let how = OpenHow {
177 flags: (libc::O_RDONLY | libc::O_NONBLOCK | libc::O_CLOEXEC) as u64,
178 mode: 0,
179 resolve: RESOLVE_NO_SYMLINKS, };
181
182 let fd = unsafe {
183 libc::syscall(
184 libc::SYS_openat2,
185 libc::AT_FDCWD,
186 path.as_ptr(),
187 &how as *const OpenHow,
188 size_of::<OpenHow>(),
189 ) as c_long
190 };
191
192 if fd < 0 {
193 return Err(std::io::Error::last_os_error());
194 }
195 Ok(fd as i32)
196 }
197}