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