1use num_enum::{IntoPrimitive, TryFromPrimitive};
2
3use crate::{bindings, const_conversions};
4
5pub const LINUX_O_ASYNC: u32 = 0x2000;
12const _: () = const { assert!(LINUX_O_ASYNC == bindings::LINUX_FASYNC) };
13
14bitflags::bitflags! {
15 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
17 pub struct OFlag: i32 {
18 const O_ACCMODE = const_conversions::i32_from_u32(bindings::LINUX_O_ACCMODE);
19 const O_RDONLY = const_conversions::i32_from_u32(bindings::LINUX_O_RDONLY);
20 const O_WRONLY = const_conversions::i32_from_u32(bindings::LINUX_O_WRONLY);
21 const O_RDWR = const_conversions::i32_from_u32(bindings::LINUX_O_RDWR);
22 const O_CREAT = const_conversions::i32_from_u32(bindings::LINUX_O_CREAT);
23 const O_EXCL = const_conversions::i32_from_u32(bindings::LINUX_O_EXCL);
24 const O_NOCTTY = const_conversions::i32_from_u32(bindings::LINUX_O_NOCTTY);
25 const O_TRUNC = const_conversions::i32_from_u32(bindings::LINUX_O_TRUNC);
26 const O_APPEND = const_conversions::i32_from_u32(bindings::LINUX_O_APPEND);
27 const O_NONBLOCK = const_conversions::i32_from_u32(bindings::LINUX_O_NONBLOCK);
28 const O_DSYNC = const_conversions::i32_from_u32(bindings::LINUX_O_DSYNC);
29 const O_DIRECT = const_conversions::i32_from_u32(bindings::LINUX_O_DIRECT);
30 const O_LARGEFILE = const_conversions::i32_from_u32(bindings::LINUX_O_LARGEFILE);
31 const O_DIRECTORY = const_conversions::i32_from_u32(bindings::LINUX_O_DIRECTORY);
32 const O_NOFOLLOW = const_conversions::i32_from_u32(bindings::LINUX_O_NOFOLLOW);
33 const O_NOATIME = const_conversions::i32_from_u32(bindings::LINUX_O_NOATIME);
34 const O_CLOEXEC = const_conversions::i32_from_u32(bindings::LINUX_O_CLOEXEC);
35 const O_SYNC = const_conversions::i32_from_u32(bindings::LINUX_O_SYNC);
36 const O_PATH = const_conversions::i32_from_u32(bindings::LINUX_O_PATH);
37 const O_TMPFILE = const_conversions::i32_from_u32(bindings::LINUX_O_TMPFILE);
38 const O_NDELAY = const_conversions::i32_from_u32(bindings::LINUX_O_NDELAY);
39 const O_ASYNC = const_conversions::i32_from_u32(LINUX_O_ASYNC);
40 }
41}
42
43impl OFlag {
44 pub fn access_mode_flags(&self) -> AccessModeOFlag {
45 AccessModeOFlag::from_bits_truncate(self.bits())
46 }
47
48 pub fn file_creation_flags(&self) -> FileCreationOFlag {
49 FileCreationOFlag::from_bits_truncate(self.bits())
50 }
51
52 pub fn file_status_flags(&self) -> FileStatusOFlag {
53 FileStatusOFlag::from_bits_truncate(self.bits())
54 }
55
56 pub fn partition(&self) -> (AccessModeOFlag, FileCreationOFlag, FileStatusOFlag) {
58 (
59 self.access_mode_flags(),
60 self.file_creation_flags(),
61 self.file_status_flags(),
62 )
63 }
64}
65
66impl From<AccessModeOFlag> for OFlag {
67 fn from(value: AccessModeOFlag) -> Self {
68 Self::from_bits(value.bits()).unwrap()
69 }
70}
71
72impl From<FileCreationOFlag> for OFlag {
73 fn from(value: FileCreationOFlag) -> Self {
74 Self::from_bits(value.bits()).unwrap()
75 }
76}
77
78impl From<FileStatusOFlag> for OFlag {
79 fn from(value: FileStatusOFlag) -> Self {
80 Self::from_bits(value.bits()).unwrap()
81 }
82}
83
84bitflags::bitflags! {
85 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
87 pub struct AccessModeOFlag: i32 {
88 const O_RDONLY = OFlag::O_RDONLY.bits();
89 const O_WRONLY = OFlag::O_WRONLY.bits();
90 const O_RDWR = OFlag::O_RDWR.bits();
91 }
92}
93
94bitflags::bitflags! {
95 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
97 pub struct FileCreationOFlag : i32 {
98 const O_CLOEXEC = OFlag::O_CLOEXEC.bits();
99 const O_CREAT= OFlag::O_CREAT.bits();
100 const O_DIRECTORY= OFlag::O_DIRECTORY.bits();
101 const O_EXCL= OFlag::O_EXCL.bits();
102 const O_NOCTTY= OFlag::O_NOCTTY.bits();
103 const O_NOFOLLOW= OFlag::O_NOFOLLOW.bits();
104 const O_TMPFILE= OFlag::O_TMPFILE.bits();
105 const O_TRUNC= OFlag::O_TRUNC.bits();
106 }
107}
108
109bitflags::bitflags! {
110 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
118 pub struct FileStatusOFlag: i32 {
119 const O_APPEND= OFlag::O_APPEND.bits();
120 const O_ASYNC= OFlag::O_ASYNC.bits();
121 const O_DIRECT= OFlag::O_DIRECT.bits();
122 const O_NOATIME= OFlag::O_NOATIME.bits();
123 const O_NONBLOCK= OFlag::O_NONBLOCK.bits();
124 const O_DSYNC= OFlag::O_DSYNC.bits();
125 const O_SYNC= OFlag::O_SYNC.bits();
126 const O_LARGEFILE= OFlag::O_LARGEFILE.bits();
127 const O_PATH= OFlag::O_PATH.bits();
128 }
129}
130
131impl FileStatusOFlag {
132 pub fn as_o_flags(&self) -> OFlag {
133 OFlag::from_bits(self.bits()).unwrap()
134 }
135
136 pub fn from_o_flags(flags: OFlag) -> (Self, OFlag) {
138 let status = Self::from_bits_truncate(flags.bits());
139 let remaining = flags.bits() & !status.bits();
140 (status, OFlag::from_bits(remaining).unwrap())
141 }
142}
143
144#[derive(Debug, Copy, Clone, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)]
146#[repr(u32)]
147#[allow(non_camel_case_types)]
148pub enum FcntlCommand {
149 F_DUPFD = bindings::LINUX_F_DUPFD,
150 F_GETFD = bindings::LINUX_F_GETFD,
151 F_SETFD = bindings::LINUX_F_SETFD,
152 F_GETFL = bindings::LINUX_F_GETFL,
153 F_SETFL = bindings::LINUX_F_SETFL,
154 F_GETLK = bindings::LINUX_F_GETLK,
155 F_SETLK = bindings::LINUX_F_SETLK,
156 F_SETLKW = bindings::LINUX_F_SETLKW,
157 F_SETOWN = bindings::LINUX_F_SETOWN,
158 F_GETOWN = bindings::LINUX_F_GETOWN,
159 F_SETSIG = bindings::LINUX_F_SETSIG,
160 F_GETSIG = bindings::LINUX_F_GETSIG,
161 F_SETOWN_EX = bindings::LINUX_F_SETOWN_EX,
162 F_GETOWN_EX = bindings::LINUX_F_GETOWN_EX,
163 F_GETOWNER_UIDS = bindings::LINUX_F_GETOWNER_UIDS,
164 F_OFD_GETLK = bindings::LINUX_F_OFD_GETLK,
165 F_OFD_SETLK = bindings::LINUX_F_OFD_SETLK,
166 F_OFD_SETLKW = bindings::LINUX_F_OFD_SETLKW,
167 F_SETLEASE = bindings::LINUX_F_SETLEASE,
168 F_GETLEASE = bindings::LINUX_F_GETLEASE,
169 F_NOTIFY = bindings::LINUX_F_NOTIFY,
170 F_DUPFD_QUERY = bindings::LINUX_F_DUPFD_QUERY,
171 F_CREATED_QUERY = bindings::LINUX_F_CREATED_QUERY,
172 F_DUPFD_CLOEXEC = bindings::LINUX_F_DUPFD_CLOEXEC,
173 F_SETPIPE_SZ = bindings::LINUX_F_SETPIPE_SZ,
174 F_GETPIPE_SZ = bindings::LINUX_F_GETPIPE_SZ,
175 F_ADD_SEALS = bindings::LINUX_F_ADD_SEALS,
176 F_GET_SEALS = bindings::LINUX_F_GET_SEALS,
177 F_CANCELLK = bindings::LINUX_F_CANCELLK,
178 F_GET_RW_HINT = bindings::LINUX_F_GET_RW_HINT,
179 F_SET_RW_HINT = bindings::LINUX_F_SET_RW_HINT,
180 F_GET_FILE_RW_HINT = bindings::LINUX_F_GET_FILE_RW_HINT,
181 F_SET_FILE_RW_HINT = bindings::LINUX_F_SET_FILE_RW_HINT,
182 F_GETDELEG = bindings::LINUX_F_GETDELEG,
183 F_SETDELEG = bindings::LINUX_F_SETDELEG,
184}
185
186pub use bindings::linux_flock as flock;
187unsafe impl shadow_pod::Pod for flock {}
188
189#[derive(Debug, Copy, Clone, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)]
191#[repr(i16)]
192#[allow(non_camel_case_types)]
193pub enum FlockWhence {
194 SEEK_SET = const_conversions::i16_from_u32(bindings::LINUX_SEEK_SET),
195 SEEK_CUR = const_conversions::i16_from_u32(bindings::LINUX_SEEK_CUR),
196 SEEK_END = const_conversions::i16_from_u32(bindings::LINUX_SEEK_END),
197}
198
199#[derive(Debug, Copy, Clone, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)]
201#[repr(u32)]
202#[allow(non_camel_case_types)]
203pub enum FcntlOwner {
204 F_OWNER_TID = bindings::LINUX_F_OWNER_TID,
205 F_OWNER_PID = bindings::LINUX_F_OWNER_PID,
206 F_OWNER_PGRP = bindings::LINUX_F_OWNER_PGRP,
207}
208
209#[derive(Debug, Copy, Clone, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)]
211#[repr(u32)]
212#[allow(non_camel_case_types)]
213pub enum FcntlLeaseType {
214 F_RDLCK = bindings::LINUX_F_RDLCK,
215 F_WRLCK = bindings::LINUX_F_WRLCK,
216 F_UNLCK = bindings::LINUX_F_UNLCK,
217 F_EXLCK = bindings::LINUX_F_EXLCK,
218 F_SHLCK = bindings::LINUX_F_SHLCK,
219}
220
221#[derive(Debug, Copy, Clone, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)]
224#[repr(i16)]
225#[allow(non_camel_case_types)]
226pub enum FlockType {
227 F_RDLCK = const_conversions::i16_from_u32(bindings::LINUX_F_RDLCK),
228 F_WRLCK = const_conversions::i16_from_u32(bindings::LINUX_F_WRLCK),
229 F_UNLCK = const_conversions::i16_from_u32(bindings::LINUX_F_UNLCK),
230}
231
232#[derive(Debug, Copy, Clone, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)]
234#[repr(u32)]
235#[allow(non_camel_case_types)]
236pub enum FcntlSealType {
237 F_SEAL_SEAL = bindings::LINUX_F_SEAL_SEAL,
238 F_SEAL_SHRINK = bindings::LINUX_F_SEAL_SHRINK,
239 F_SEAL_GROW = bindings::LINUX_F_SEAL_GROW,
240 F_SEAL_WRITE = bindings::LINUX_F_SEAL_WRITE,
241 F_SEAL_FUTURE_WRITE = bindings::LINUX_F_SEAL_FUTURE_WRITE,
242 F_SEAL_EXEC = bindings::LINUX_F_SEAL_EXEC,
243}
244
245#[derive(Debug, Copy, Clone, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)]
247#[repr(u32)]
248#[allow(non_camel_case_types)]
249pub enum FcntlRwHint {
250 RWH_WRITE_LIFE_NOT_SET = bindings::LINUX_RWH_WRITE_LIFE_NOT_SET,
251 RWH_WRITE_LIFE_NONE = bindings::LINUX_RWH_WRITE_LIFE_NONE,
252 RWH_WRITE_LIFE_SHORT = bindings::LINUX_RWH_WRITE_LIFE_SHORT,
253 RWH_WRITE_LIFE_MEDIUM = bindings::LINUX_RWH_WRITE_LIFE_MEDIUM,
254 RWH_WRITE_LIFE_LONG = bindings::LINUX_RWH_WRITE_LIFE_LONG,
255 RWH_WRITE_LIFE_EXTREME = bindings::LINUX_RWH_WRITE_LIFE_EXTREME,
256}
257
258bitflags::bitflags! {
259 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
261 pub struct DescriptorFlags: i32 {
262 const FD_CLOEXEC = const_conversions::i32_from_u32(bindings::LINUX_FD_CLOEXEC);
263 }
264}
265
266impl DescriptorFlags {
267 pub fn as_o_flags(&self) -> OFlag {
268 let mut flags = OFlag::empty();
269 if self.contains(Self::FD_CLOEXEC) {
270 flags.insert(OFlag::O_CLOEXEC);
271 }
272 flags
273 }
274
275 pub fn from_o_flags(flags: OFlag) -> (Self, OFlag) {
277 let mut remaining = flags;
278 let mut flags = Self::empty();
279
280 if remaining.contains(OFlag::O_CLOEXEC) {
281 remaining.remove(OFlag::O_CLOEXEC);
282 flags.insert(Self::FD_CLOEXEC);
283 }
284
285 (flags, remaining)
286 }
287}
288
289bitflags::bitflags! {
290 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
292 pub struct ExecveAtFlags: i32 {
293 const AT_EMPTY_PATH = const_conversions::i32_from_u32(bindings::LINUX_AT_EMPTY_PATH);
294 const AT_SYMLINK_NOFOLLOW = const_conversions::i32_from_u32(bindings::LINUX_AT_SYMLINK_NOFOLLOW);
295 const AT_EXECVE_CHECK = const_conversions::i32_from_u32(bindings::LINUX_AT_EXECVE_CHECK);
296 }
297}
298
299#[cfg(test)]
300mod test {
301 use super::*;
302
303 #[test]
304 fn test_partition_oflags() {
305 let all_o_flags = OFlag::all();
306 let (access_mode, creation, status) = all_o_flags.partition();
307
308 assert_eq!(access_mode, AccessModeOFlag::all());
310 assert_eq!(creation, FileCreationOFlag::all());
311 assert_eq!(status, FileStatusOFlag::all());
312
313 let access_mode = OFlag::from(access_mode);
315 let creation = OFlag::from(creation);
316 let status = OFlag::from(status);
317
318 assert_eq!(access_mode & creation, OFlag::empty());
320 assert_eq!(access_mode & status, OFlag::empty());
321 assert_eq!(creation & status, OFlag::empty());
322
323 assert_eq!(
325 OFlag::all() - (access_mode | creation | status),
326 OFlag::empty()
327 );
328 }
329}
330
331mod export {
332 #[unsafe(no_mangle)]
336 pub extern "C-unwind" fn linux_file_creation_oflags() -> core::ffi::c_int {
337 super::FileCreationOFlag::all().bits()
338 }
339
340 #[unsafe(no_mangle)]
344 pub extern "C-unwind" fn linux_access_mode_oflags() -> core::ffi::c_int {
345 super::AccessModeOFlag::all().bits()
346 }
347
348 #[unsafe(no_mangle)]
352 pub extern "C-unwind" fn linux_file_status_oflags() -> core::ffi::c_int {
353 super::FileStatusOFlag::all().bits()
354 }
355}