1 use crate::backend::c;
2 use bitflags::bitflags;
3 
4 #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
5 bitflags! {
6     /// `*_OK` constants for use with [`accessat`].
7     ///
8     /// [`accessat`]: fn.accessat.html
9     #[repr(transparent)]
10     #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
11     pub struct Access: c::c_int {
12         /// `R_OK`
13         const READ_OK = c::R_OK;
14 
15         /// `W_OK`
16         const WRITE_OK = c::W_OK;
17 
18         /// `X_OK`
19         const EXEC_OK = c::X_OK;
20 
21         /// `F_OK`
22         const EXISTS = c::F_OK;
23 
24         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
25         const _ = !0;
26     }
27 }
28 
29 #[cfg(not(any(target_os = "espidf", target_os = "redox")))]
30 bitflags! {
31     /// `AT_*` constants for use with [`openat`], [`statat`], and other `*at`
32     /// functions.
33     ///
34     /// [`openat`]: crate::fs::openat
35     /// [`statat`]: crate::fs::statat
36     #[repr(transparent)]
37     #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
38     pub struct AtFlags: u32 {
39         /// `AT_SYMLINK_NOFOLLOW`
40         const SYMLINK_NOFOLLOW = bitcast!(c::AT_SYMLINK_NOFOLLOW);
41 
42         /// `AT_EACCESS`
43         #[cfg(not(any(target_os = "emscripten", target_os = "android")))]
44         const EACCESS = bitcast!(c::AT_EACCESS);
45 
46         /// `AT_REMOVEDIR`
47         const REMOVEDIR = bitcast!(c::AT_REMOVEDIR);
48 
49         /// `AT_SYMLINK_FOLLOW`
50         const SYMLINK_FOLLOW = bitcast!(c::AT_SYMLINK_FOLLOW);
51 
52         /// `AT_NO_AUTOMOUNT`
53         #[cfg(any(linux_like, target_os = "fuchsia"))]
54         const NO_AUTOMOUNT = bitcast!(c::AT_NO_AUTOMOUNT);
55 
56         /// `AT_EMPTY_PATH`
57         #[cfg(any(
58             linux_kernel,
59             target_os = "freebsd",
60             target_os = "fuchsia",
61         ))]
62         const EMPTY_PATH = bitcast!(c::AT_EMPTY_PATH);
63 
64         /// `AT_RESOLVE_BENEATH`
65         #[cfg(target_os = "freebsd")]
66         const RESOLVE_BENEATH = bitcast!(c::AT_RESOLVE_BENEATH);
67 
68         /// `AT_STATX_SYNC_AS_STAT`
69         #[cfg(all(target_os = "linux", target_env = "gnu"))]
70         const STATX_SYNC_AS_STAT = bitcast!(c::AT_STATX_SYNC_AS_STAT);
71 
72         /// `AT_STATX_FORCE_SYNC`
73         #[cfg(all(target_os = "linux", target_env = "gnu"))]
74         const STATX_FORCE_SYNC = bitcast!(c::AT_STATX_FORCE_SYNC);
75 
76         /// `AT_STATX_DONT_SYNC`
77         #[cfg(all(target_os = "linux", target_env = "gnu"))]
78         const STATX_DONT_SYNC = bitcast!(c::AT_STATX_DONT_SYNC);
79 
80         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
81         const _ = !0;
82     }
83 }
84 
85 bitflags! {
86     /// `S_I*` constants for use with [`openat`], [`chmodat`], and [`fchmod`].
87     ///
88     /// [`openat`]: crate::fs::openat
89     /// [`chmodat`]: crate::fs::chmodat
90     /// [`fchmod`]: crate::fs::fchmod
91     #[repr(transparent)]
92     #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
93     pub struct Mode: RawMode {
94         /// `S_IRWXU`
95         #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
96         const RWXU = c::S_IRWXU as RawMode;
97 
98         /// `S_IRUSR`
99         #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
100         const RUSR = c::S_IRUSR as RawMode;
101 
102         /// `S_IWUSR`
103         #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
104         const WUSR = c::S_IWUSR as RawMode;
105 
106         /// `S_IXUSR`
107         #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
108         const XUSR = c::S_IXUSR as RawMode;
109 
110         /// `S_IRWXG`
111         #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
112         const RWXG = c::S_IRWXG as RawMode;
113 
114         /// `S_IRGRP`
115         #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
116         const RGRP = c::S_IRGRP as RawMode;
117 
118         /// `S_IWGRP`
119         #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
120         const WGRP = c::S_IWGRP as RawMode;
121 
122         /// `S_IXGRP`
123         #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
124         const XGRP = c::S_IXGRP as RawMode;
125 
126         /// `S_IRWXO`
127         #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
128         const RWXO = c::S_IRWXO as RawMode;
129 
130         /// `S_IROTH`
131         #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
132         const ROTH = c::S_IROTH as RawMode;
133 
134         /// `S_IWOTH`
135         #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
136         const WOTH = c::S_IWOTH as RawMode;
137 
138         /// `S_IXOTH`
139         #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
140         const XOTH = c::S_IXOTH as RawMode;
141 
142         /// `S_ISUID`
143         #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
144         const SUID = c::S_ISUID as RawMode;
145 
146         /// `S_ISGID`
147         #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
148         const SGID = c::S_ISGID as RawMode;
149 
150         /// `S_ISVTX`
151         #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
152         const SVTX = c::S_ISVTX as RawMode;
153 
154         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
155         const _ = !0;
156     }
157 }
158 
159 #[cfg(not(target_os = "espidf"))]
160 impl Mode {
161     /// Construct a `Mode` from the mode bits of the `st_mode` field of a
162     /// `Mode`.
163     #[inline]
from_raw_mode(st_mode: RawMode) -> Self164     pub const fn from_raw_mode(st_mode: RawMode) -> Self {
165         Self::from_bits_truncate(st_mode)
166     }
167 
168     /// Construct an `st_mode` value from a `Mode`.
169     #[inline]
as_raw_mode(self) -> RawMode170     pub const fn as_raw_mode(self) -> RawMode {
171         self.bits()
172     }
173 }
174 
175 #[cfg(not(target_os = "espidf"))]
176 impl From<RawMode> for Mode {
177     /// Support conversions from raw mode values to `Mode`.
178     ///
179     /// ```
180     /// use rustix::fs::{Mode, RawMode};
181     /// assert_eq!(Mode::from(0o700), Mode::RWXU);
182     /// ```
183     #[inline]
from(st_mode: RawMode) -> Self184     fn from(st_mode: RawMode) -> Self {
185         Self::from_raw_mode(st_mode)
186     }
187 }
188 
189 #[cfg(not(target_os = "espidf"))]
190 impl From<Mode> for RawMode {
191     /// Support conversions from `Mode` to raw mode values.
192     ///
193     /// ```
194     /// use rustix::fs::{Mode, RawMode};
195     /// assert_eq!(RawMode::from(Mode::RWXU), 0o700);
196     /// ```
197     #[inline]
from(mode: Mode) -> Self198     fn from(mode: Mode) -> Self {
199         mode.as_raw_mode()
200     }
201 }
202 
203 bitflags! {
204     /// `O_*` constants for use with [`openat`].
205     ///
206     /// [`openat`]: crate::fs::openat
207     #[repr(transparent)]
208     #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
209     pub struct OFlags: u32 {
210         /// `O_ACCMODE`
211         const ACCMODE = bitcast!(c::O_ACCMODE);
212 
213         /// Similar to `ACCMODE`, but just includes the read/write flags, and
214         /// no other flags.
215         ///
216         /// On some platforms, `PATH` may be included in `ACCMODE`, when
217         /// sometimes we really just want the read/write bits. Caution is
218         /// indicated, as the presence of `PATH` may mean that the read/write
219         /// bits don't have their usual meaning.
220         const RWMODE = bitcast!(c::O_RDONLY | c::O_WRONLY | c::O_RDWR);
221 
222         /// `O_APPEND`
223         const APPEND = bitcast!(c::O_APPEND);
224 
225         /// `O_CREAT`
226         #[doc(alias = "CREAT")]
227         const CREATE = bitcast!(c::O_CREAT);
228 
229         /// `O_DIRECTORY`
230         #[cfg(not(target_os = "espidf"))]
231         const DIRECTORY = bitcast!(c::O_DIRECTORY);
232 
233         /// `O_DSYNC`
234         #[cfg(not(any(target_os = "dragonfly", target_os = "espidf", target_os = "l4re", target_os = "redox", target_os = "vita")))]
235         const DSYNC = bitcast!(c::O_DSYNC);
236 
237         /// `O_EXCL`
238         const EXCL = bitcast!(c::O_EXCL);
239 
240         /// `O_FSYNC`
241         #[cfg(any(
242             bsd,
243             all(target_os = "linux", not(target_env = "musl")),
244         ))]
245         const FSYNC = bitcast!(c::O_FSYNC);
246 
247         /// `O_NOFOLLOW`
248         #[cfg(not(target_os = "espidf"))]
249         const NOFOLLOW = bitcast!(c::O_NOFOLLOW);
250 
251         /// `O_NONBLOCK`
252         const NONBLOCK = bitcast!(c::O_NONBLOCK);
253 
254         /// `O_RDONLY`
255         const RDONLY = bitcast!(c::O_RDONLY);
256 
257         /// `O_WRONLY`
258         const WRONLY = bitcast!(c::O_WRONLY);
259 
260         /// `O_RDWR`
261         ///
262         /// This is not equal to `RDONLY | WRONLY`. It's a distinct flag.
263         const RDWR = bitcast!(c::O_RDWR);
264 
265         /// `O_NOCTTY`
266         #[cfg(not(any(target_os = "espidf", target_os = "l4re", target_os = "redox", target_os = "vita")))]
267         const NOCTTY = bitcast!(c::O_NOCTTY);
268 
269         /// `O_RSYNC`
270         #[cfg(any(
271             linux_kernel,
272             netbsdlike,
273             target_os = "emscripten",
274             target_os = "wasi",
275         ))]
276         const RSYNC = bitcast!(c::O_RSYNC);
277 
278         /// `O_SYNC`
279         #[cfg(not(any(target_os = "l4re", target_os = "redox")))]
280         const SYNC = bitcast!(c::O_SYNC);
281 
282         /// `O_TRUNC`
283         const TRUNC = bitcast!(c::O_TRUNC);
284 
285         /// `O_PATH`
286         #[cfg(any(
287             linux_kernel,
288             target_os = "emscripten",
289             target_os = "freebsd",
290             target_os = "fuchsia",
291             target_os = "redox",
292         ))]
293         const PATH = bitcast!(c::O_PATH);
294 
295         /// `O_CLOEXEC`
296         const CLOEXEC = bitcast!(c::O_CLOEXEC);
297 
298         /// `O_TMPFILE`
299         #[cfg(any(
300             linux_kernel,
301             target_os = "emscripten",
302             target_os = "fuchsia",
303         ))]
304         const TMPFILE = bitcast!(c::O_TMPFILE);
305 
306         /// `O_NOATIME`
307         #[cfg(any(
308             linux_kernel,
309             target_os = "fuchsia",
310         ))]
311         const NOATIME = bitcast!(c::O_NOATIME);
312 
313         /// `O_DIRECT`
314         #[cfg(any(
315             linux_kernel,
316             target_os = "emscripten",
317             target_os = "freebsd",
318             target_os = "fuchsia",
319             target_os = "netbsd",
320         ))]
321         const DIRECT = bitcast!(c::O_DIRECT);
322 
323         /// `O_RESOLVE_BENEATH`
324         #[cfg(target_os = "freebsd")]
325         const RESOLVE_BENEATH = bitcast!(c::O_RESOLVE_BENEATH);
326 
327         /// `O_EMPTY_PATH`
328         #[cfg(target_os = "freebsd")]
329         const EMPTY_PATH = bitcast!(c::O_EMPTY_PATH);
330 
331         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
332         const _ = !0;
333     }
334 }
335 
336 #[cfg(apple)]
337 bitflags! {
338     /// `CLONE_*` constants for use with [`fclonefileat`].
339     ///
340     /// [`fclonefileat`]: crate::fs::fclonefileat
341     #[repr(transparent)]
342     #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
343     pub struct CloneFlags: u32 {
344         /// `CLONE_NOFOLLOW`
345         const NOFOLLOW = 1;
346 
347         /// `CLONE_NOOWNERCOPY`
348         const NOOWNERCOPY = 2;
349 
350         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
351         const _ = !0;
352     }
353 }
354 
355 #[cfg(apple)]
356 mod copyfile {
357     pub(super) const ACL: u32 = 1 << 0;
358     pub(super) const STAT: u32 = 1 << 1;
359     pub(super) const XATTR: u32 = 1 << 2;
360     pub(super) const DATA: u32 = 1 << 3;
361     pub(super) const SECURITY: u32 = STAT | ACL;
362     pub(super) const METADATA: u32 = SECURITY | XATTR;
363     pub(super) const ALL: u32 = METADATA | DATA;
364 }
365 
366 #[cfg(apple)]
367 bitflags! {
368     /// `COPYFILE_*` constants for use with [`fcopyfile`].
369     ///
370     /// [`fcopyfile`]: crate::fs::fcopyfile
371     #[repr(transparent)]
372     #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
373     pub struct CopyfileFlags: c::c_uint {
374         /// `COPYFILE_ACL`
375         const ACL = copyfile::ACL;
376 
377         /// `COPYFILE_STAT`
378         const STAT = copyfile::STAT;
379 
380         /// `COPYFILE_XATTR`
381         const XATTR = copyfile::XATTR;
382 
383         /// `COPYFILE_DATA`
384         const DATA = copyfile::DATA;
385 
386         /// `COPYFILE_SECURITY`
387         const SECURITY = copyfile::SECURITY;
388 
389         /// `COPYFILE_METADATA`
390         const METADATA = copyfile::METADATA;
391 
392         /// `COPYFILE_ALL`
393         const ALL = copyfile::ALL;
394 
395         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
396         const _ = !0;
397     }
398 }
399 
400 #[cfg(linux_kernel)]
401 bitflags! {
402     /// `RESOLVE_*` constants for use with [`openat2`].
403     ///
404     /// [`openat2`]: crate::fs::openat2
405     #[repr(transparent)]
406     #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
407     pub struct ResolveFlags: u64 {
408         /// `RESOLVE_NO_XDEV`
409         const NO_XDEV = 0x01;
410 
411         /// `RESOLVE_NO_MAGICLINKS`
412         const NO_MAGICLINKS = 0x02;
413 
414         /// `RESOLVE_NO_SYMLINKS`
415         const NO_SYMLINKS = 0x04;
416 
417         /// `RESOLVE_BENEATH`
418         const BENEATH = 0x08;
419 
420         /// `RESOLVE_IN_ROOT`
421         const IN_ROOT = 0x10;
422 
423         /// `RESOLVE_CACHED` (since Linux 5.12)
424         const CACHED = 0x20;
425 
426         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
427         const _ = !0;
428     }
429 }
430 
431 #[cfg(linux_kernel)]
432 bitflags! {
433     /// `RENAME_*` constants for use with [`renameat_with`].
434     ///
435     /// [`renameat_with`]: crate::fs::renameat_with
436     #[repr(transparent)]
437     #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
438     pub struct RenameFlags: c::c_uint {
439         /// `RENAME_EXCHANGE`
440         const EXCHANGE = bitcast!(c::RENAME_EXCHANGE);
441 
442         /// `RENAME_NOREPLACE`
443         const NOREPLACE = bitcast!(c::RENAME_NOREPLACE);
444 
445         /// `RENAME_WHITEOUT`
446         const WHITEOUT = bitcast!(c::RENAME_WHITEOUT);
447 
448         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
449         const _ = !0;
450     }
451 }
452 
453 /// `S_IF*` constants for use with [`mknodat`] and [`Stat`]'s `st_mode` field.
454 ///
455 /// [`mknodat`]: crate::fs::mknodat
456 /// [`Stat`]: crate::fs::Stat
457 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
458 pub enum FileType {
459     /// `S_IFREG`
460     RegularFile = c::S_IFREG as isize,
461 
462     /// `S_IFDIR`
463     Directory = c::S_IFDIR as isize,
464 
465     /// `S_IFLNK`
466     Symlink = c::S_IFLNK as isize,
467 
468     /// `S_IFIFO`
469     #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `S_IFIFO`.
470     #[doc(alias = "IFO")]
471     Fifo = c::S_IFIFO as isize,
472 
473     /// `S_IFSOCK`
474     #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `S_IFSOCK`.
475     Socket = c::S_IFSOCK as isize,
476 
477     /// `S_IFCHR`
478     CharacterDevice = c::S_IFCHR as isize,
479 
480     /// `S_IFBLK`
481     BlockDevice = c::S_IFBLK as isize,
482 
483     /// An unknown filesystem object.
484     Unknown,
485 }
486 
487 impl FileType {
488     /// Construct a `FileType` from the `S_IFMT` bits of the `st_mode` field of
489     /// a `Stat`.
490     #[inline]
from_raw_mode(st_mode: RawMode) -> Self491     pub const fn from_raw_mode(st_mode: RawMode) -> Self {
492         match (st_mode as c::mode_t) & c::S_IFMT {
493             c::S_IFREG => Self::RegularFile,
494             c::S_IFDIR => Self::Directory,
495             c::S_IFLNK => Self::Symlink,
496             #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `S_IFIFO`.
497             c::S_IFIFO => Self::Fifo,
498             #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `S_IFSOCK`.
499             c::S_IFSOCK => Self::Socket,
500             c::S_IFCHR => Self::CharacterDevice,
501             c::S_IFBLK => Self::BlockDevice,
502             _ => Self::Unknown,
503         }
504     }
505 
506     /// Construct an `st_mode` value from a `FileType`.
507     #[inline]
as_raw_mode(self) -> RawMode508     pub const fn as_raw_mode(self) -> RawMode {
509         match self {
510             Self::RegularFile => c::S_IFREG as RawMode,
511             Self::Directory => c::S_IFDIR as RawMode,
512             Self::Symlink => c::S_IFLNK as RawMode,
513             #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `S_IFIFO`.
514             Self::Fifo => c::S_IFIFO as RawMode,
515             #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `S_IFSOCK`.
516             Self::Socket => c::S_IFSOCK as RawMode,
517             Self::CharacterDevice => c::S_IFCHR as RawMode,
518             Self::BlockDevice => c::S_IFBLK as RawMode,
519             Self::Unknown => c::S_IFMT as RawMode,
520         }
521     }
522 
523     /// Construct a `FileType` from the `d_type` field of a `c::dirent`.
524     #[cfg(not(any(
525         solarish,
526         target_os = "aix",
527         target_os = "espidf",
528         target_os = "haiku",
529         target_os = "nto",
530         target_os = "redox",
531         target_os = "vita"
532     )))]
533     #[inline]
from_dirent_d_type(d_type: u8) -> Self534     pub(crate) const fn from_dirent_d_type(d_type: u8) -> Self {
535         match d_type {
536             c::DT_REG => Self::RegularFile,
537             c::DT_DIR => Self::Directory,
538             c::DT_LNK => Self::Symlink,
539             #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `DT_SOCK`.
540             c::DT_SOCK => Self::Socket,
541             #[cfg(not(target_os = "wasi"))] // TODO: Use WASI's `DT_FIFO`.
542             c::DT_FIFO => Self::Fifo,
543             c::DT_CHR => Self::CharacterDevice,
544             c::DT_BLK => Self::BlockDevice,
545             // c::DT_UNKNOWN |
546             _ => Self::Unknown,
547         }
548     }
549 }
550 
551 /// `POSIX_FADV_*` constants for use with [`fadvise`].
552 ///
553 /// [`fadvise`]: crate::fs::fadvise
554 #[cfg(not(any(
555     apple,
556     netbsdlike,
557     solarish,
558     target_os = "dragonfly",
559     target_os = "espidf",
560     target_os = "haiku",
561     target_os = "redox",
562     target_os = "vita",
563 )))]
564 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
565 #[repr(u32)]
566 pub enum Advice {
567     /// `POSIX_FADV_NORMAL`
568     Normal = c::POSIX_FADV_NORMAL as c::c_uint,
569 
570     /// `POSIX_FADV_SEQUENTIAL`
571     Sequential = c::POSIX_FADV_SEQUENTIAL as c::c_uint,
572 
573     /// `POSIX_FADV_RANDOM`
574     Random = c::POSIX_FADV_RANDOM as c::c_uint,
575 
576     /// `POSIX_FADV_NOREUSE`
577     NoReuse = c::POSIX_FADV_NOREUSE as c::c_uint,
578 
579     /// `POSIX_FADV_WILLNEED`
580     WillNeed = c::POSIX_FADV_WILLNEED as c::c_uint,
581 
582     /// `POSIX_FADV_DONTNEED`
583     DontNeed = c::POSIX_FADV_DONTNEED as c::c_uint,
584 }
585 
586 #[cfg(any(linux_kernel, target_os = "freebsd"))]
587 bitflags! {
588     /// `MFD_*` constants for use with [`memfd_create`].
589     ///
590     /// [`memfd_create`]: crate::fs::memfd_create
591     #[repr(transparent)]
592     #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
593     pub struct MemfdFlags: c::c_uint {
594         /// `MFD_CLOEXEC`
595         const CLOEXEC = c::MFD_CLOEXEC;
596 
597         /// `MFD_ALLOW_SEALING`
598         const ALLOW_SEALING = c::MFD_ALLOW_SEALING;
599 
600         /// `MFD_HUGETLB` (since Linux 4.14)
601         const HUGETLB = c::MFD_HUGETLB;
602 
603         /// `MFD_HUGE_64KB`
604         const HUGE_64KB = c::MFD_HUGE_64KB;
605         /// `MFD_HUGE_512JB`
606         const HUGE_512KB = c::MFD_HUGE_512KB;
607         /// `MFD_HUGE_1MB`
608         const HUGE_1MB = c::MFD_HUGE_1MB;
609         /// `MFD_HUGE_2MB`
610         const HUGE_2MB = c::MFD_HUGE_2MB;
611         /// `MFD_HUGE_8MB`
612         const HUGE_8MB = c::MFD_HUGE_8MB;
613         /// `MFD_HUGE_16MB`
614         const HUGE_16MB = c::MFD_HUGE_16MB;
615         /// `MFD_HUGE_32MB`
616         const HUGE_32MB = c::MFD_HUGE_32MB;
617         /// `MFD_HUGE_256MB`
618         const HUGE_256MB = c::MFD_HUGE_256MB;
619         /// `MFD_HUGE_512MB`
620         const HUGE_512MB = c::MFD_HUGE_512MB;
621         /// `MFD_HUGE_1GB`
622         const HUGE_1GB = c::MFD_HUGE_1GB;
623         /// `MFD_HUGE_2GB`
624         const HUGE_2GB = c::MFD_HUGE_2GB;
625         /// `MFD_HUGE_16GB`
626         const HUGE_16GB = c::MFD_HUGE_16GB;
627 
628         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
629         const _ = !0;
630     }
631 }
632 
633 #[cfg(any(linux_kernel, target_os = "freebsd", target_os = "fuchsia"))]
634 bitflags! {
635     /// `F_SEAL_*` constants for use with [`fcntl_add_seals`] and
636     /// [`fcntl_get_seals`].
637     ///
638     /// [`fcntl_add_seals`]: crate::fs::fcntl_add_seals
639     /// [`fcntl_get_seals`]: crate::fs::fcntl_get_seals
640     #[repr(transparent)]
641     #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
642     pub struct SealFlags: u32 {
643         /// `F_SEAL_SEAL`
644         const SEAL = bitcast!(c::F_SEAL_SEAL);
645         /// `F_SEAL_SHRINK`
646         const SHRINK = bitcast!(c::F_SEAL_SHRINK);
647         /// `F_SEAL_GROW`
648         const GROW = bitcast!(c::F_SEAL_GROW);
649         /// `F_SEAL_WRITE`
650         const WRITE = bitcast!(c::F_SEAL_WRITE);
651         /// `F_SEAL_FUTURE_WRITE` (since Linux 5.1)
652         #[cfg(linux_kernel)]
653         const FUTURE_WRITE = bitcast!(c::F_SEAL_FUTURE_WRITE);
654 
655         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
656         const _ = !0;
657     }
658 }
659 
660 #[cfg(all(target_os = "linux", target_env = "gnu"))]
661 bitflags! {
662     /// `STATX_*` constants for use with [`statx`].
663     ///
664     /// [`statx`]: crate::fs::statx
665     #[repr(transparent)]
666     #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
667     pub struct StatxFlags: u32 {
668         /// `STATX_TYPE`
669         const TYPE = c::STATX_TYPE;
670 
671         /// `STATX_MODE`
672         const MODE = c::STATX_MODE;
673 
674         /// `STATX_NLINK`
675         const NLINK = c::STATX_NLINK;
676 
677         /// `STATX_UID`
678         const UID = c::STATX_UID;
679 
680         /// `STATX_GID`
681         const GID = c::STATX_GID;
682 
683         /// `STATX_ATIME`
684         const ATIME = c::STATX_ATIME;
685 
686         /// `STATX_MTIME`
687         const MTIME = c::STATX_MTIME;
688 
689         /// `STATX_CTIME`
690         const CTIME = c::STATX_CTIME;
691 
692         /// `STATX_INO`
693         const INO = c::STATX_INO;
694 
695         /// `STATX_SIZE`
696         const SIZE = c::STATX_SIZE;
697 
698         /// `STATX_BLOCKS`
699         const BLOCKS = c::STATX_BLOCKS;
700 
701         /// `STATX_BASIC_STATS`
702         const BASIC_STATS = c::STATX_BASIC_STATS;
703 
704         /// `STATX_BTIME`
705         const BTIME = c::STATX_BTIME;
706 
707         /// `STATX_MNT_ID` (since Linux 5.8)
708         const MNT_ID = c::STATX_MNT_ID;
709 
710         /// `STATX_DIOALIGN` (since Linux 6.1)
711         const DIOALIGN = c::STATX_DIOALIGN;
712 
713         /// `STATX_ALL`
714         const ALL = c::STATX_ALL;
715 
716         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
717         const _ = !0;
718     }
719 }
720 
721 #[cfg(any(
722     target_os = "android",
723     all(target_os = "linux", not(target_env = "gnu")),
724 ))]
725 bitflags! {
726     /// `STATX_*` constants for use with [`statx`].
727     ///
728     /// [`statx`]: crate::fs::statx
729     #[repr(transparent)]
730     #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
731     pub struct StatxFlags: u32 {
732         /// `STATX_TYPE`
733         const TYPE = 0x0001;
734 
735         /// `STATX_MODE`
736         const MODE = 0x0002;
737 
738         /// `STATX_NLINK`
739         const NLINK = 0x0004;
740 
741         /// `STATX_UID`
742         const UID = 0x0008;
743 
744         /// `STATX_GID`
745         const GID = 0x0010;
746 
747         /// `STATX_ATIME`
748         const ATIME = 0x0020;
749 
750         /// `STATX_MTIME`
751         const MTIME = 0x0040;
752 
753         /// `STATX_CTIME`
754         const CTIME = 0x0080;
755 
756         /// `STATX_INO`
757         const INO = 0x0100;
758 
759         /// `STATX_SIZE`
760         const SIZE = 0x0200;
761 
762         /// `STATX_BLOCKS`
763         const BLOCKS = 0x0400;
764 
765         /// `STATX_BASIC_STATS`
766         const BASIC_STATS = 0x07ff;
767 
768         /// `STATX_BTIME`
769         const BTIME = 0x800;
770 
771         /// `STATX_MNT_ID` (since Linux 5.8)
772         const MNT_ID = 0x1000;
773 
774         /// `STATX_ALL`
775         const ALL = 0xfff;
776 
777         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
778         const _ = !0;
779     }
780 }
781 
782 #[cfg(not(any(
783     netbsdlike,
784     solarish,
785     target_os = "aix",
786     target_os = "espidf",
787     target_os = "nto",
788     target_os = "redox",
789     target_os = "vita"
790 )))]
791 bitflags! {
792     /// `FALLOC_FL_*` constants for use with [`fallocate`].
793     ///
794     /// [`fallocate`]: crate::fs::fallocate
795     #[repr(transparent)]
796     #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
797     pub struct FallocateFlags: u32 {
798         /// `FALLOC_FL_KEEP_SIZE`
799         #[cfg(not(any(
800             bsd,
801             target_os = "aix",
802             target_os = "haiku",
803             target_os = "hurd",
804             target_os = "wasi",
805         )))]
806         const KEEP_SIZE = bitcast!(c::FALLOC_FL_KEEP_SIZE);
807         /// `FALLOC_FL_PUNCH_HOLE`
808         #[cfg(not(any(
809             bsd,
810             target_os = "aix",
811             target_os = "haiku",
812             target_os = "hurd",
813             target_os = "wasi",
814         )))]
815         const PUNCH_HOLE = bitcast!(c::FALLOC_FL_PUNCH_HOLE);
816         /// `FALLOC_FL_NO_HIDE_STALE`
817         #[cfg(not(any(
818             bsd,
819             target_os = "aix",
820             target_os = "emscripten",
821             target_os = "fuchsia",
822             target_os = "haiku",
823             target_os = "hurd",
824             target_os = "l4re",
825             target_os = "linux",
826             target_os = "wasi",
827         )))]
828         const NO_HIDE_STALE = bitcast!(c::FALLOC_FL_NO_HIDE_STALE);
829         /// `FALLOC_FL_COLLAPSE_RANGE`
830         #[cfg(not(any(
831             bsd,
832             target_os = "aix",
833             target_os = "haiku",
834             target_os = "hurd",
835             target_os = "emscripten",
836             target_os = "wasi",
837         )))]
838         const COLLAPSE_RANGE = bitcast!(c::FALLOC_FL_COLLAPSE_RANGE);
839         /// `FALLOC_FL_ZERO_RANGE`
840         #[cfg(not(any(
841             bsd,
842             target_os = "aix",
843             target_os = "haiku",
844             target_os = "hurd",
845             target_os = "emscripten",
846             target_os = "wasi",
847         )))]
848         const ZERO_RANGE = bitcast!(c::FALLOC_FL_ZERO_RANGE);
849         /// `FALLOC_FL_INSERT_RANGE`
850         #[cfg(not(any(
851             bsd,
852             target_os = "aix",
853             target_os = "haiku",
854             target_os = "hurd",
855             target_os = "emscripten",
856             target_os = "wasi",
857         )))]
858         const INSERT_RANGE = bitcast!(c::FALLOC_FL_INSERT_RANGE);
859         /// `FALLOC_FL_UNSHARE_RANGE`
860         #[cfg(not(any(
861             bsd,
862             target_os = "aix",
863             target_os = "haiku",
864             target_os = "hurd",
865             target_os = "emscripten",
866             target_os = "wasi",
867         )))]
868         const UNSHARE_RANGE = bitcast!(c::FALLOC_FL_UNSHARE_RANGE);
869 
870         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
871         const _ = !0;
872     }
873 }
874 
875 #[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))]
876 bitflags! {
877     /// `ST_*` constants for use with [`StatVfs`].
878     #[repr(transparent)]
879     #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
880     pub struct StatVfsMountFlags: u64 {
881         /// `ST_MANDLOCK`
882         #[cfg(any(linux_kernel, target_os = "emscripten", target_os = "fuchsia"))]
883         const MANDLOCK = c::ST_MANDLOCK as u64;
884 
885         /// `ST_NOATIME`
886         #[cfg(any(linux_kernel, target_os = "emscripten", target_os = "fuchsia"))]
887         const NOATIME = c::ST_NOATIME as u64;
888 
889         /// `ST_NODEV`
890         #[cfg(any(
891             linux_kernel,
892             target_os = "aix",
893             target_os = "emscripten",
894             target_os = "fuchsia"
895         ))]
896         const NODEV = c::ST_NODEV as u64;
897 
898         /// `ST_NODIRATIME`
899         #[cfg(any(linux_kernel, target_os = "emscripten", target_os = "fuchsia"))]
900         const NODIRATIME = c::ST_NODIRATIME as u64;
901 
902         /// `ST_NOEXEC`
903         #[cfg(any(linux_kernel, target_os = "emscripten", target_os = "fuchsia"))]
904         const NOEXEC = c::ST_NOEXEC as u64;
905 
906         /// `ST_NOSUID`
907         #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
908         const NOSUID = c::ST_NOSUID as u64;
909 
910         /// `ST_RDONLY`
911         #[cfg(not(any(target_os = "espidf", target_os = "vita")))]
912         const RDONLY = c::ST_RDONLY as u64;
913 
914         /// `ST_RELATIME`
915         #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))]
916         const RELATIME = c::ST_RELATIME as u64;
917 
918         /// `ST_SYNCHRONOUS`
919         #[cfg(any(linux_kernel, target_os = "emscripten", target_os = "fuchsia"))]
920         const SYNCHRONOUS = c::ST_SYNCHRONOUS as u64;
921 
922         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
923         const _ = !0;
924     }
925 }
926 
927 /// `LOCK_*` constants for use with [`flock`] and [`fcntl_lock`].
928 ///
929 /// [`flock`]: crate::fs::flock
930 /// [`fcntl_lock`]: crate::fs::fcntl_lock
931 #[cfg(not(any(target_os = "espidf", target_os = "vita", target_os = "wasi")))]
932 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
933 #[repr(u32)]
934 pub enum FlockOperation {
935     /// `LOCK_SH`
936     LockShared = bitcast!(c::LOCK_SH),
937     /// `LOCK_EX`
938     LockExclusive = bitcast!(c::LOCK_EX),
939     /// `LOCK_UN`
940     Unlock = bitcast!(c::LOCK_UN),
941     /// `LOCK_SH | LOCK_NB`
942     NonBlockingLockShared = bitcast!(c::LOCK_SH | c::LOCK_NB),
943     /// `LOCK_EX | LOCK_NB`
944     NonBlockingLockExclusive = bitcast!(c::LOCK_EX | c::LOCK_NB),
945     /// `LOCK_UN | LOCK_NB`
946     NonBlockingUnlock = bitcast!(c::LOCK_UN | c::LOCK_NB),
947 }
948 
949 /// `struct stat` for use with [`statat`] and [`fstat`].
950 ///
951 /// [`statat`]: crate::fs::statat
952 /// [`fstat`]: crate::fs::fstat
953 #[cfg(not(any(linux_like, target_os = "hurd")))]
954 pub type Stat = c::stat;
955 
956 /// `struct stat` for use with [`statat`] and [`fstat`].
957 ///
958 /// [`statat`]: crate::fs::statat
959 /// [`fstat`]: crate::fs::fstat
960 #[cfg(any(
961     all(linux_kernel, target_pointer_width = "64"),
962     target_os = "hurd",
963     target_os = "emscripten",
964     target_os = "l4re",
965 ))]
966 pub type Stat = c::stat64;
967 
968 /// `struct stat` for use with [`statat`] and [`fstat`].
969 ///
970 /// [`statat`]: crate::fs::statat
971 /// [`fstat`]: crate::fs::fstat
972 // On 32-bit, Linux's `struct stat64` has a 32-bit `st_mtime` and friends, so
973 // we use our own struct, populated from `statx` where possible, to avoid the
974 // y2038 bug.
975 #[cfg(all(linux_kernel, target_pointer_width = "32"))]
976 #[repr(C)]
977 #[derive(Debug, Copy, Clone)]
978 #[allow(missing_docs)]
979 pub struct Stat {
980     pub st_dev: u64,
981     pub st_mode: u32,
982     pub st_nlink: u32,
983     pub st_uid: u32,
984     pub st_gid: u32,
985     pub st_rdev: u64,
986     pub st_size: i64,
987     pub st_blksize: u32,
988     pub st_blocks: u64,
989     #[deprecated(note = "Use `rustix::fs::StatExt::atime` instead.")]
990     pub st_atime: u64,
991     pub st_atime_nsec: u32,
992     #[deprecated(note = "Use `rustix::fs::StatExt::mtime` instead.")]
993     pub st_mtime: u64,
994     pub st_mtime_nsec: u32,
995     #[deprecated(note = "Use `rustix::fs::StatExt::ctime` instead.")]
996     pub st_ctime: u64,
997     pub st_ctime_nsec: u32,
998     pub st_ino: u64,
999 }
1000 
1001 /// `struct statfs` for use with [`statfs`] and [`fstatfs`].
1002 ///
1003 /// [`statfs`]: crate::fs::statfs
1004 /// [`fstatfs`]: crate::fs::fstatfs
1005 #[cfg(not(any(
1006     linux_like,
1007     solarish,
1008     target_os = "espidf",
1009     target_os = "haiku",
1010     target_os = "netbsd",
1011     target_os = "nto",
1012     target_os = "redox",
1013     target_os = "vita",
1014     target_os = "wasi",
1015 )))]
1016 #[allow(clippy::module_name_repetitions)]
1017 pub type StatFs = c::statfs;
1018 
1019 /// `struct statfs` for use with [`statfs`] and [`fstatfs`].
1020 ///
1021 /// [`statfs`]: crate::fs::statfs
1022 /// [`fstatfs`]: crate::fs::fstatfs
1023 #[cfg(linux_like)]
1024 pub type StatFs = c::statfs64;
1025 
1026 /// `struct statvfs` for use with [`statvfs`] and [`fstatvfs`].
1027 ///
1028 /// [`statvfs`]: crate::fs::statvfs
1029 /// [`fstatvfs`]: crate::fs::fstatvfs
1030 #[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))]
1031 #[allow(missing_docs)]
1032 pub struct StatVfs {
1033     pub f_bsize: u64,
1034     pub f_frsize: u64,
1035     pub f_blocks: u64,
1036     pub f_bfree: u64,
1037     pub f_bavail: u64,
1038     pub f_files: u64,
1039     pub f_ffree: u64,
1040     pub f_favail: u64,
1041     pub f_fsid: u64,
1042     pub f_flag: StatVfsMountFlags,
1043     pub f_namemax: u64,
1044 }
1045 
1046 /// `struct statx` for use with [`statx`].
1047 ///
1048 /// [`statx`]: crate::fs::statx
1049 #[cfg(all(target_os = "linux", target_env = "gnu"))]
1050 // Use the glibc `struct statx`.
1051 pub type Statx = c::statx;
1052 
1053 /// `struct statx_timestamp` for use with [`Statx`].
1054 #[cfg(all(target_os = "linux", target_env = "gnu"))]
1055 // Use the glibc `struct statx_timestamp`.
1056 pub type StatxTimestamp = c::statx;
1057 
1058 /// `struct statx` for use with [`statx`].
1059 ///
1060 /// [`statx`]: crate::fs::statx
1061 // Non-glibc ABIs don't currently declare a `struct statx`, so we declare it
1062 // ourselves.
1063 #[cfg(any(
1064     target_os = "android",
1065     all(target_os = "linux", not(target_env = "gnu")),
1066 ))]
1067 #[repr(C)]
1068 #[allow(missing_docs)]
1069 pub struct Statx {
1070     pub stx_mask: u32,
1071     pub stx_blksize: u32,
1072     pub stx_attributes: u64,
1073     pub stx_nlink: u32,
1074     pub stx_uid: u32,
1075     pub stx_gid: u32,
1076     pub stx_mode: u16,
1077     __statx_pad1: [u16; 1],
1078     pub stx_ino: u64,
1079     pub stx_size: u64,
1080     pub stx_blocks: u64,
1081     pub stx_attributes_mask: u64,
1082     pub stx_atime: StatxTimestamp,
1083     pub stx_btime: StatxTimestamp,
1084     pub stx_ctime: StatxTimestamp,
1085     pub stx_mtime: StatxTimestamp,
1086     pub stx_rdev_major: u32,
1087     pub stx_rdev_minor: u32,
1088     pub stx_dev_major: u32,
1089     pub stx_dev_minor: u32,
1090     pub stx_mnt_id: u64,
1091     __statx_pad2: u64,
1092     __statx_pad3: [u64; 12],
1093 }
1094 
1095 /// `struct statx_timestamp` for use with [`Statx`].
1096 // Non-glibc ABIs don't currently declare a `struct statx_timestamp`, so we
1097 // declare it ourselves.
1098 #[cfg(any(
1099     target_os = "android",
1100     all(target_os = "linux", not(target_env = "gnu")),
1101 ))]
1102 #[repr(C)]
1103 #[allow(missing_docs)]
1104 pub struct StatxTimestamp {
1105     pub tv_sec: i64,
1106     pub tv_nsec: u32,
1107     pub __statx_timestamp_pad1: [i32; 1],
1108 }
1109 
1110 /// `mode_t`
1111 #[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
1112 pub type RawMode = c::mode_t;
1113 
1114 /// `mode_t`
1115 #[cfg(all(target_os = "android", target_pointer_width = "32"))]
1116 pub type RawMode = c::c_uint;
1117 
1118 /// `dev_t`
1119 #[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
1120 pub type Dev = c::dev_t;
1121 
1122 /// `dev_t`
1123 #[cfg(all(target_os = "android", target_pointer_width = "32"))]
1124 pub type Dev = c::c_ulonglong;
1125 
1126 /// `__fsword_t`
1127 #[cfg(all(
1128     target_os = "linux",
1129     not(target_env = "musl"),
1130     not(target_arch = "s390x"),
1131 ))]
1132 pub type FsWord = c::__fsword_t;
1133 
1134 /// `__fsword_t`
1135 #[cfg(all(
1136     any(target_os = "android", all(target_os = "linux", target_env = "musl")),
1137     target_pointer_width = "32",
1138 ))]
1139 pub type FsWord = u32;
1140 
1141 /// `__fsword_t`
1142 #[cfg(all(
1143     any(target_os = "android", all(target_os = "linux", target_env = "musl")),
1144     not(target_arch = "s390x"),
1145     target_pointer_width = "64",
1146 ))]
1147 pub type FsWord = u64;
1148 
1149 /// `__fsword_t`
1150 // s390x uses `u32` for `statfs` entries on glibc, even though `__fsword_t` is
1151 // `u64`.
1152 #[cfg(all(target_os = "linux", target_arch = "s390x", target_env = "gnu"))]
1153 pub type FsWord = u32;
1154 
1155 /// `__fsword_t`
1156 // s390x uses `u64` for `statfs` entries on musl.
1157 #[cfg(all(target_os = "linux", target_arch = "s390x", target_env = "musl"))]
1158 pub type FsWord = u64;
1159 
1160 /// `copyfile_state_t`—State for use with [`fcopyfile`].
1161 ///
1162 /// [`fcopyfile`]: crate::fs::fcopyfile
1163 #[cfg(apple)]
1164 #[allow(non_camel_case_types)]
1165 #[repr(transparent)]
1166 #[derive(Copy, Clone)]
1167 pub struct copyfile_state_t(pub(crate) *mut c::c_void);
1168