1use bitflags::bitflags;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10#[repr(i32)]
11pub enum FcntlCmd {
12 DupFd = 0,
15
16 GetFd = 1,
18
19 SetFd = 2,
21
22 GetFl = 3,
24
25 SetFl = 4,
27
28 GetLk = 5,
31
32 SetLk = 6,
34
35 SetLkW = 7,
37
38 SetOwn = 8,
41
42 GetOwn = 9,
44
45 SetSig = 10,
47
48 GetSig = 11,
50
51 DupFdCloexec = 1030,
54
55 SetPipeSz = 1031,
57
58 GetPipeSz = 1032,
60}
61
62impl FcntlCmd {
63 pub fn from_raw(cmd: i32) -> Option<Self> {
69 match cmd {
70 0 => Some(Self::DupFd),
71 1 => Some(Self::GetFd),
72 2 => Some(Self::SetFd),
73 3 => Some(Self::GetFl),
74 4 => Some(Self::SetFl),
75 5 => Some(Self::GetLk),
76 6 => Some(Self::SetLk),
77 7 => Some(Self::SetLkW),
78 8 => Some(Self::SetOwn),
79 9 => Some(Self::GetOwn),
80 10 => Some(Self::SetSig),
81 11 => Some(Self::GetSig),
82 1030 => Some(Self::DupFdCloexec),
83 1031 => Some(Self::SetPipeSz),
84 1032 => Some(Self::GetPipeSz),
85 _ => None,
86 }
87 }
88}
89
90bitflags! {
91 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
95 pub struct FdFlags: u32 {
96 const CLOEXEC = 1;
98 }
99}
100
101bitflags! {
102 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
107 pub struct FileStatusFlags: u32 {
108 const APPEND = 0o2000;
110
111 const NONBLOCK = 0o4000;
113
114 const ASYNC = 0o20000;
116
117 const DIRECT = 0o40000;
119
120 const NOATIME = 0o1000000;
122 }
123}
124
125impl FileStatusFlags {
126 pub fn is_modifiable(self) -> bool {
130 let modifiable = Self::APPEND | Self::NONBLOCK | Self::ASYNC | Self::DIRECT | Self::NOATIME;
132 (self & !modifiable).is_empty()
133 }
134}
135
136#[derive(Debug, Clone, Copy, PartialEq, Eq)]
138#[repr(i16)]
139pub enum LockType {
140 Read = 0,
142
143 Write = 1,
145
146 Unlock = 2,
148}
149
150impl LockType {
151 pub fn from_raw(val: i16) -> Option<Self> {
152 match val {
153 0 => Some(Self::Read),
154 1 => Some(Self::Write),
155 2 => Some(Self::Unlock),
156 _ => None,
157 }
158 }
159}
160
161#[repr(C)]
165#[derive(Debug, Clone, Copy)]
166pub struct Flock {
167 pub l_type: i16,
169
170 pub l_whence: i16,
172
173 pub l_start: i64,
175
176 pub l_len: i64,
178
179 pub l_pid: i32,
181
182 _pad: i32,
184}
185
186impl Flock {
187 pub fn new(lock_type: LockType, whence: i16, start: i64, len: i64) -> Self {
189 Self {
190 l_type: lock_type as i16,
191 l_whence: whence,
192 l_start: start,
193 l_len: len,
194 l_pid: 0,
195 _pad: 0,
196 }
197 }
198
199 pub fn to_absolute_range(
205 &self,
206 current_offset: usize,
207 file_size: usize,
208 ) -> Result<(usize, usize), ()> {
209 let start = match self.l_whence as i32 {
210 SEEK_SET => self.l_start,
211 SEEK_CUR => current_offset as i64 + self.l_start,
212 SEEK_END => file_size as i64 + self.l_start,
213 _ => return Err(()),
214 };
215
216 if start < 0 {
217 return Err(());
218 }
219
220 let start = start as usize;
221 let len = if self.l_len == 0 {
222 usize::MAX - start
224 } else if self.l_len > 0 {
225 self.l_len as usize
226 } else {
227 return Err(());
228 };
229
230 Ok((start, len))
231 }
232}
233
234bitflags! {
235 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
240 pub struct OpenFlags: u32 {
241 const O_RDONLY = 0o0;
243
244 const O_WRONLY = 0o1;
246
247 const O_RDWR = 0o2;
249
250 const O_ACCMODE = 0o3;
252
253 const O_CREAT = 0o100;
255
256 const O_EXCL = 0o200;
258
259 const O_TRUNC = 0o1000;
261
262 const O_APPEND = 0o2000;
264
265 const O_NONBLOCK = 0o4000;
267
268 const O_DIRECTORY = 0o200000;
270
271 const O_CLOEXEC = 0o2000000;
273
274 const O_LARGEFILE = 0o100000;
276 }
277}
278
279impl OpenFlags {
280 pub fn readable(&self) -> bool {
282 let mode = self.bits() & Self::O_ACCMODE.bits();
283 mode == Self::O_RDONLY.bits() || mode == Self::O_RDWR.bits()
284 }
285
286 pub fn writable(&self) -> bool {
288 let mode = self.bits() & Self::O_ACCMODE.bits();
289 mode == Self::O_WRONLY.bits() || mode == Self::O_RDWR.bits()
290 }
291}
292
293#[derive(Debug, Clone, Copy, PartialEq, Eq)]
299#[repr(i32)]
300pub enum SeekWhence {
301 Set = 0,
303
304 Cur = 1,
306
307 End = 2,
309}
310
311impl SeekWhence {
312 pub fn from_i32(value: i32) -> Option<Self> {
321 match value {
322 0 => Some(Self::Set),
323 1 => Some(Self::Cur),
324 2 => Some(Self::End),
325 _ => None,
326 }
327 }
328
329 pub fn from_usize(value: usize) -> Option<Self> {
331 Self::from_i32(value as i32)
332 }
333}
334
335pub const SEEK_SET: i32 = 0;
337pub const SEEK_CUR: i32 = 1;
338pub const SEEK_END: i32 = 2;