Skip to main content

rustix/backend/libc/
c.rs

1//! Libc and supplemental types and constants.
2
3#![allow(unused_imports)]
4
5// Import everything from libc, but we'll add some stuff and override some
6// things below.
7pub(crate) use libc::*;
8
9/// `PROC_SUPER_MAGIC`—The magic number for the procfs filesystem.
10#[cfg(all(linux_kernel, target_env = "musl"))]
11pub(crate) const PROC_SUPER_MAGIC: u32 = 0x0000_9fa0;
12
13/// `NFS_SUPER_MAGIC`—The magic number for the NFS filesystem.
14#[cfg(all(linux_kernel, target_env = "musl"))]
15pub(crate) const NFS_SUPER_MAGIC: u32 = 0x0000_6969;
16
17#[cfg(feature = "process")]
18#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
19pub(crate) const EXIT_SIGNALED_SIGABRT: c_int = 128 + SIGABRT as c_int;
20
21// TODO: Upstream these.
22#[cfg(all(linux_raw_dep, feature = "net"))]
23pub(crate) const ETH_P_TSN: c_int = linux_raw_sys::if_ether::ETH_P_TSN as _;
24#[cfg(all(linux_raw_dep, feature = "net"))]
25pub(crate) const ETH_P_ERSPAN2: c_int = linux_raw_sys::if_ether::ETH_P_ERSPAN2 as _;
26#[cfg(all(linux_raw_dep, feature = "net"))]
27pub(crate) const ETH_P_ERSPAN: c_int = linux_raw_sys::if_ether::ETH_P_ERSPAN as _;
28#[cfg(all(linux_raw_dep, feature = "net"))]
29pub(crate) const ETH_P_PROFINET: c_int = linux_raw_sys::if_ether::ETH_P_PROFINET as _;
30#[cfg(all(linux_raw_dep, feature = "net"))]
31pub(crate) const ETH_P_REALTEK: c_int = linux_raw_sys::if_ether::ETH_P_REALTEK as _;
32#[cfg(all(linux_raw_dep, feature = "net"))]
33pub(crate) const ETH_P_ETHERCAT: c_int = linux_raw_sys::if_ether::ETH_P_ETHERCAT as _;
34#[cfg(all(linux_raw_dep, feature = "net"))]
35pub(crate) const ETH_P_PREAUTH: c_int = linux_raw_sys::if_ether::ETH_P_PREAUTH as _;
36#[cfg(all(linux_raw_dep, feature = "net"))]
37pub(crate) const ETH_P_LLDP: c_int = linux_raw_sys::if_ether::ETH_P_LLDP as _;
38#[cfg(all(linux_raw_dep, feature = "net"))]
39pub(crate) const ETH_P_MRP: c_int = linux_raw_sys::if_ether::ETH_P_MRP as _;
40#[cfg(all(linux_raw_dep, feature = "net"))]
41pub(crate) const ETH_P_NCSI: c_int = linux_raw_sys::if_ether::ETH_P_NCSI as _;
42#[cfg(all(linux_raw_dep, feature = "net"))]
43pub(crate) const ETH_P_CFM: c_int = linux_raw_sys::if_ether::ETH_P_CFM as _;
44#[cfg(all(linux_raw_dep, feature = "net"))]
45pub(crate) const ETH_P_IBOE: c_int = linux_raw_sys::if_ether::ETH_P_IBOE as _;
46#[cfg(all(linux_raw_dep, feature = "net"))]
47pub(crate) const ETH_P_HSR: c_int = linux_raw_sys::if_ether::ETH_P_HSR as _;
48#[cfg(all(linux_raw_dep, feature = "net"))]
49pub(crate) const ETH_P_NSH: c_int = linux_raw_sys::if_ether::ETH_P_NSH as _;
50#[cfg(all(linux_raw_dep, feature = "net"))]
51pub(crate) const ETH_P_DSA_8021Q: c_int = linux_raw_sys::if_ether::ETH_P_DSA_8021Q as _;
52#[cfg(all(linux_raw_dep, feature = "net"))]
53pub(crate) const ETH_P_DSA_A5PSW: c_int = linux_raw_sys::if_ether::ETH_P_DSA_A5PSW as _;
54#[cfg(all(linux_raw_dep, feature = "net"))]
55pub(crate) const ETH_P_IFE: c_int = linux_raw_sys::if_ether::ETH_P_IFE as _;
56#[cfg(all(linux_raw_dep, feature = "net"))]
57pub(crate) const ETH_P_CAN: c_int = linux_raw_sys::if_ether::ETH_P_CAN as _;
58#[cfg(all(linux_raw_dep, feature = "net"))]
59pub(crate) const ETH_P_CANXL: c_int = linux_raw_sys::if_ether::ETH_P_CANXL as _;
60#[cfg(all(linux_raw_dep, feature = "net"))]
61pub(crate) const ETH_P_XDSA: c_int = linux_raw_sys::if_ether::ETH_P_XDSA as _;
62#[cfg(all(linux_raw_dep, feature = "net"))]
63pub(crate) const ETH_P_MAP: c_int = linux_raw_sys::if_ether::ETH_P_MAP as _;
64#[cfg(all(linux_raw_dep, feature = "net"))]
65pub(crate) const ETH_P_MCTP: c_int = linux_raw_sys::if_ether::ETH_P_MCTP as _;
66#[cfg(all(linux_raw_dep, feature = "mount"))]
67pub(crate) const MS_NOSYMFOLLOW: c_ulong = linux_raw_sys::general::MS_NOSYMFOLLOW as _;
68
69// TODO: Upstream these.
70#[cfg(all(linux_raw_dep, feature = "termios"))]
71pub(crate) const IUCLC: tcflag_t = linux_raw_sys::general::IUCLC as _;
72#[cfg(all(linux_raw_dep, feature = "termios"))]
73pub(crate) const XCASE: tcflag_t = linux_raw_sys::general::XCASE as _;
74
75#[cfg(target_os = "aix")]
76pub(crate) const MSG_DONTWAIT: c_int = MSG_NONBLOCK;
77
78// `O_LARGEFILE` can be automatically set by the kernel on Linux:
79// <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/open.c?h=v6.13#n1423>
80// so libc implementations may leave it undefined or defined to zero.
81#[cfg(linux_raw_dep)]
82pub(crate) const O_LARGEFILE: c_int = linux_raw_sys::general::O_LARGEFILE as _;
83
84// Gated under `_LARGEFILE_SOURCE` but automatically set by the kernel.
85// <https://github.com/illumos/illumos-gate/blob/fb2cb638e5604b214d8ea8d4f01ad2e77b437c17/usr/src/ucbhead/sys/fcntl.h#L64>
86#[cfg(solarish)]
87pub(crate) const O_LARGEFILE: c_int = 0x2000;
88
89// On PowerPC, the regular `termios` has the `termios2` fields and there is no
90// `termios2`, so we define aliases.
91#[cfg(all(
92    linux_kernel,
93    feature = "termios",
94    any(target_arch = "powerpc", target_arch = "powerpc64")
95))]
96pub(crate) use {
97    termios as termios2, TCGETS as TCGETS2, TCSETS as TCSETS2, TCSETSF as TCSETSF2,
98    TCSETSW as TCSETSW2,
99};
100
101// And PowerPC doesn't define `CIBAUD`, but it does define `IBSHIFT`, so we can
102// compute `CIBAUD` ourselves.
103#[cfg(all(
104    linux_kernel,
105    feature = "termios",
106    any(target_arch = "powerpc", target_arch = "powerpc64")
107))]
108pub(crate) const CIBAUD: u32 = CBAUD << IBSHIFT;
109
110// Automatically enable “large file” support (LFS) features.
111
112#[cfg(target_os = "vxworks")]
113pub(super) use _Vx_ticks64_t as _Vx_ticks_t;
114#[cfg(linux_kernel)]
115pub(super) use fallocate64 as fallocate;
116#[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
117#[cfg(any(linux_like, target_os = "aix"))]
118pub(super) use open64 as open;
119#[cfg(any(
120    linux_kernel,
121    target_os = "aix",
122    target_os = "hurd",
123    target_os = "l4re"
124))]
125pub(super) use posix_fallocate64 as posix_fallocate;
126#[cfg(any(all(linux_like, not(target_os = "android")), target_os = "aix"))]
127pub(super) use {blkcnt64_t as blkcnt_t, rlim64_t as rlim_t};
128// TODO: AIX has `stat64x`, `fstat64x`, `lstat64x`, and `stat64xat`; add them
129// to the upstream libc crate and implement rustix's `statat` etc. with them.
130#[cfg(target_os = "aix")]
131pub(super) use {
132    blksize64_t as blksize_t, fstat64 as fstat, fstatfs64 as fstatfs, fstatvfs64 as fstatvfs,
133    ftruncate64 as ftruncate, getrlimit64 as getrlimit, ino_t, lseek64 as lseek, mmap,
134    off64_t as off_t, openat, posix_fadvise64 as posix_fadvise, preadv, pwritev,
135    rlimit64 as rlimit, setrlimit64 as setrlimit, stat64at as fstatat, statfs64 as statfs,
136    statvfs64 as statvfs, RLIM_INFINITY,
137};
138#[cfg(any(linux_like, target_os = "hurd"))]
139pub(super) use {
140    fstat64 as fstat, fstatat64 as fstatat, fstatfs64 as fstatfs, fstatvfs64 as fstatvfs,
141    ftruncate64 as ftruncate, getrlimit64 as getrlimit, ino64_t as ino_t, lseek64 as lseek,
142    mmap64 as mmap, off64_t as off_t, openat64 as openat, posix_fadvise64 as posix_fadvise,
143    rlimit64 as rlimit, setrlimit64 as setrlimit, statfs64 as statfs, statvfs64 as statvfs,
144    RLIM64_INFINITY as RLIM_INFINITY,
145};
146#[cfg(apple)]
147pub(super) use {
148    host_info64_t as host_info_t, host_statistics64 as host_statistics,
149    vm_statistics64_t as vm_statistics_t,
150};
151#[cfg(not(all(
152    linux_kernel,
153    any(
154        target_pointer_width = "32",
155        target_arch = "mips64",
156        target_arch = "mips64r6"
157    )
158)))]
159#[cfg(any(linux_like, target_os = "aix", target_os = "hurd"))]
160pub(super) use {lstat64 as lstat, stat64 as stat};
161#[cfg(any(
162    linux_kernel,
163    target_os = "aix",
164    target_os = "hurd",
165    target_os = "emscripten"
166))]
167pub(super) use {pread64 as pread, pwrite64 as pwrite};
168#[cfg(any(target_os = "linux", target_os = "hurd", target_os = "emscripten"))]
169pub(super) use {preadv64 as preadv, pwritev64 as pwritev};
170
171#[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]
172pub(super) unsafe fn prlimit(
173    pid: pid_t,
174    resource: __rlimit_resource_t,
175    new_limit: *const rlimit64,
176    old_limit: *mut rlimit64,
177) -> c_int {
178    // `prlimit64` wasn't supported in glibc until 2.13.
179    weak_or_syscall! {
180        fn prlimit64(
181            pid: pid_t,
182            resource: __rlimit_resource_t,
183            new_limit: *const rlimit64,
184            old_limit: *mut rlimit64
185        ) via SYS_prlimit64 -> c_int
186    }
187
188    prlimit64(pid, resource, new_limit, old_limit)
189}
190
191#[cfg(all(target_os = "linux", target_env = "musl"))]
192pub(super) unsafe fn prlimit(
193    pid: pid_t,
194    resource: c_int,
195    new_limit: *const rlimit64,
196    old_limit: *mut rlimit64,
197) -> c_int {
198    weak_or_syscall! {
199        fn prlimit64(
200            pid: pid_t,
201            resource: c_int,
202            new_limit: *const rlimit64,
203            old_limit: *mut rlimit64
204        ) via SYS_prlimit64 -> c_int
205    }
206
207    prlimit64(pid, resource, new_limit, old_limit)
208}
209
210#[cfg(target_os = "android")]
211pub(super) unsafe fn prlimit(
212    pid: pid_t,
213    resource: c_int,
214    new_limit: *const rlimit64,
215    old_limit: *mut rlimit64,
216) -> c_int {
217    weak_or_syscall! {
218        fn prlimit64(
219            pid: pid_t,
220            resource: c_int,
221            new_limit: *const rlimit64,
222            old_limit: *mut rlimit64
223        ) via SYS_prlimit64 -> c_int
224    }
225
226    prlimit64(pid, resource, new_limit, old_limit)
227}
228
229#[cfg(target_os = "android")]
230mod readwrite_pv64 {
231    use super::*;
232
233    pub(in super::super) unsafe fn preadv64(
234        fd: c_int,
235        iov: *const iovec,
236        iovcnt: c_int,
237        offset: off64_t,
238    ) -> ssize_t {
239        // Older Android libc lacks `preadv64`, so use the `weak!` mechanism to
240        // test for it, and call back to `syscall`. We don't use
241        // `weak_or_syscall` here because we need to pass the 64-bit offset
242        // specially.
243        weak! {
244            fn preadv64(c_int, *const iovec, c_int, off64_t) -> ssize_t
245        }
246        if let Some(fun) = preadv64.get() {
247            fun(fd, iov, iovcnt, offset)
248        } else {
249            // Unlike the plain "p" functions, the "pv" functions pass their
250            // offset in an endian-independent way, and always in two
251            // registers.
252            syscall! {
253                fn preadv(
254                    fd: c_int,
255                    iov: *const iovec,
256                    iovcnt: c_int,
257                    offset_lo: usize,
258                    offset_hi: usize
259                ) via SYS_preadv -> ssize_t
260            }
261            preadv(fd, iov, iovcnt, offset as usize, (offset >> 32) as usize)
262        }
263    }
264    pub(in super::super) unsafe fn pwritev64(
265        fd: c_int,
266        iov: *const iovec,
267        iovcnt: c_int,
268        offset: off64_t,
269    ) -> ssize_t {
270        // See the comments in `preadv64`.
271        weak! {
272            fn pwritev64(c_int, *const iovec, c_int, off64_t) -> ssize_t
273        }
274        if let Some(fun) = pwritev64.get() {
275            fun(fd, iov, iovcnt, offset)
276        } else {
277            // Unlike the plain "p" functions, the "pv" functions pass their
278            // offset in an endian-independent way, and always in two
279            // registers.
280            syscall! {
281                fn pwritev(
282                    fd: c_int,
283                    iov: *const iovec,
284                    iovcnt: c_int,
285                    offset_lo: usize,
286                    offset_hi: usize
287                ) via SYS_pwritev -> ssize_t
288            }
289            pwritev(fd, iov, iovcnt, offset as usize, (offset >> 32) as usize)
290        }
291    }
292}
293#[cfg(target_os = "android")]
294pub(super) use readwrite_pv64::{preadv64 as preadv, pwritev64 as pwritev};
295
296// macOS added `preadv` and `pwritev` in version 11.0.
297#[cfg(apple)]
298mod readwrite_pv {
299    use super::*;
300    weakcall! {
301        pub(in super::super) fn preadv(
302            fd: c_int,
303            iov: *const iovec,
304            iovcnt: c_int,
305            offset: off_t
306        ) -> ssize_t
307    }
308    weakcall! {
309        pub(in super::super) fn pwritev(
310            fd: c_int,
311            iov: *const iovec,
312            iovcnt: c_int, offset: off_t
313        ) -> ssize_t
314    }
315}
316#[cfg(apple)]
317pub(super) use readwrite_pv::{preadv, pwritev};
318
319// glibc added `preadv64v2` and `pwritev64v2` in version 2.26.
320#[cfg(all(target_os = "linux", target_env = "gnu"))]
321mod readwrite_pv64v2 {
322    use super::*;
323
324    pub(in super::super) unsafe fn preadv64v2(
325        fd: c_int,
326        iov: *const iovec,
327        iovcnt: c_int,
328        offset: off64_t,
329        flags: c_int,
330    ) -> ssize_t {
331        // Older glibc lacks `preadv64v2`, so use the `weak!` mechanism to
332        // test for it, and call back to `syscall`. We don't use
333        // `weak_or_syscall` here because we need to pass the 64-bit offset
334        // specially.
335        weak! {
336            fn preadv64v2(c_int, *const iovec, c_int, off64_t, c_int) -> ssize_t
337        }
338        if let Some(fun) = preadv64v2.get() {
339            fun(fd, iov, iovcnt, offset, flags)
340        } else {
341            // Unlike the plain "p" functions, the "pv" functions pass their
342            // offset in an endian-independent way, and always in two
343            // registers.
344            syscall! {
345                fn preadv2(
346                    fd: c_int,
347                    iov: *const iovec,
348                    iovcnt: c_int,
349                    offset_lo: usize,
350                    offset_hi: usize,
351                    flags: c_int
352                ) via SYS_preadv2 -> ssize_t
353            }
354            preadv2(
355                fd,
356                iov,
357                iovcnt,
358                offset as usize,
359                (offset >> 32) as usize,
360                flags,
361            )
362        }
363    }
364    pub(in super::super) unsafe fn pwritev64v2(
365        fd: c_int,
366        iov: *const iovec,
367        iovcnt: c_int,
368        offset: off64_t,
369        flags: c_int,
370    ) -> ssize_t {
371        // See the comments in `preadv64v2`.
372        weak! {
373            fn pwritev64v2(c_int, *const iovec, c_int, off64_t, c_int) -> ssize_t
374        }
375        if let Some(fun) = pwritev64v2.get() {
376            fun(fd, iov, iovcnt, offset, flags)
377        } else {
378            // Unlike the plain "p" functions, the "pv" functions pass their
379            // offset in an endian-independent way, and always in two
380            // registers.
381            syscall! {
382                fn pwritev2(
383                    fd: c_int,
384                    iov: *const iovec,
385                    iovec: c_int,
386                    offset_lo: usize,
387                    offset_hi: usize,
388                    flags: c_int
389                ) via SYS_pwritev2 -> ssize_t
390            }
391            pwritev2(
392                fd,
393                iov,
394                iovcnt,
395                offset as usize,
396                (offset >> 32) as usize,
397                flags,
398            )
399        }
400    }
401}
402#[cfg(all(target_os = "linux", target_env = "gnu"))]
403pub(super) use readwrite_pv64v2::{preadv64v2 as preadv2, pwritev64v2 as pwritev2};
404
405// On non-glibc, assume we don't have `pwritev2`/`preadv2` in libc and use
406// `c::syscall` instead.
407#[cfg(any(
408    target_os = "android",
409    all(target_os = "linux", not(target_env = "gnu")),
410))]
411mod readwrite_pv64v2 {
412    use super::*;
413
414    pub(in super::super) unsafe fn preadv64v2(
415        fd: c_int,
416        iov: *const iovec,
417        iovcnt: c_int,
418        offset: off64_t,
419        flags: c_int,
420    ) -> ssize_t {
421        // Unlike the plain "p" functions, the "pv" functions pass their offset
422        // in an endian-independent way, and always in two registers.
423        syscall! {
424            fn preadv2(
425                fd: c_int,
426                iov: *const iovec,
427                iovcnt: c_int,
428                offset_lo: usize,
429                offset_hi: usize,
430                flags: c_int
431            ) via SYS_preadv2 -> ssize_t
432        }
433        preadv2(
434            fd,
435            iov,
436            iovcnt,
437            offset as usize,
438            (offset >> 32) as usize,
439            flags,
440        )
441    }
442    pub(in super::super) unsafe fn pwritev64v2(
443        fd: c_int,
444        iov: *const iovec,
445        iovcnt: c_int,
446        offset: off64_t,
447        flags: c_int,
448    ) -> ssize_t {
449        // Unlike the plain "p" functions, the "pv" functions pass their offset
450        // in an endian-independent way, and always in two registers.
451        syscall! {
452            fn pwritev2(
453                fd: c_int,
454                iov: *const iovec,
455                iovcnt: c_int,
456                offset_lo: usize,
457                offset_hi: usize,
458                flags: c_int
459            ) via SYS_pwritev2 -> ssize_t
460        }
461        pwritev2(
462            fd,
463            iov,
464            iovcnt,
465            offset as usize,
466            (offset >> 32) as usize,
467            flags,
468        )
469    }
470}
471#[cfg(any(
472    target_os = "android",
473    all(target_os = "linux", not(target_env = "gnu")),
474))]
475pub(super) use readwrite_pv64v2::{preadv64v2 as preadv2, pwritev64v2 as pwritev2};
476
477// Rust's libc crate lacks statx for Non-glibc targets.
478#[cfg(feature = "fs")]
479#[cfg(all(
480    linux_like,
481    linux_raw_dep,
482    not(any(
483        target_os = "emscripten",
484        target_env = "gnu",
485        all(target_arch = "loongarch64", target_env = "musl")
486    ))
487))]
488mod statx_flags {
489    pub(crate) use linux_raw_sys::general::{
490        STATX_ALL, STATX_ATIME, STATX_BASIC_STATS, STATX_BLOCKS, STATX_BTIME, STATX_CTIME,
491        STATX_DIOALIGN, STATX_GID, STATX_INO, STATX_MNT_ID, STATX_MODE, STATX_MTIME, STATX_NLINK,
492        STATX_SIZE, STATX_TYPE, STATX_UID,
493    };
494
495    pub(crate) use linux_raw_sys::general::{
496        STATX_ATTR_APPEND, STATX_ATTR_AUTOMOUNT, STATX_ATTR_COMPRESSED, STATX_ATTR_DAX,
497        STATX_ATTR_ENCRYPTED, STATX_ATTR_IMMUTABLE, STATX_ATTR_MOUNT_ROOT, STATX_ATTR_NODUMP,
498        STATX_ATTR_VERITY,
499    };
500}
501#[cfg(feature = "fs")]
502#[cfg(all(
503    linux_like,
504    linux_raw_dep,
505    not(any(
506        target_os = "android",
507        target_os = "emscripten",
508        target_env = "gnu",
509        all(target_arch = "loongarch64", target_env = "musl")
510    ))
511))]
512pub(crate) use statx_flags::*;
513
514#[cfg(feature = "fs")]
515#[cfg(target_os = "android")]
516pub(crate) use __fsid_t as fsid_t;
517
518// FreeBSD added `timerfd_*` in FreeBSD 14. NetBSD added then in NetBSD 10.
519#[cfg(all(feature = "time", any(target_os = "freebsd", target_os = "netbsd")))]
520syscall!(pub(crate) fn timerfd_create(
521    clockid: c_int,
522    flags: c_int
523) via SYS_timerfd_create -> c_int);
524#[cfg(all(feature = "time", any(target_os = "freebsd", target_os = "netbsd")))]
525syscall!(pub(crate) fn timerfd_gettime(
526    fd: c_int,
527    curr_value: *mut itimerspec
528) via SYS_timerfd_gettime -> c_int);
529#[cfg(all(feature = "time", any(target_os = "freebsd", target_os = "netbsd")))]
530syscall!(pub(crate) fn timerfd_settime(
531    fd: c_int,
532    flags: c_int,
533    new_value: *const itimerspec,
534    old_value: *mut itimerspec
535) via SYS_timerfd_settime -> c_int);
536
537#[cfg(all(feature = "time", target_os = "illumos"))]
538extern "C" {
539    pub(crate) fn timerfd_create(clockid: c_int, flags: c_int) -> c_int;
540    pub(crate) fn timerfd_gettime(fd: c_int, curr_value: *mut itimerspec) -> c_int;
541    pub(crate) fn timerfd_settime(
542        fd: c_int,
543        flags: c_int,
544        new_value: *const itimerspec,
545        old_value: *mut itimerspec,
546    ) -> c_int;
547}
548
549// illumos and NetBSD timerfd support.
550// Submitted upstream in <https://github.com/rust-lang/libc/pull/4333>.
551
552// <https://code.illumos.org/plugins/gitiles/illumos-gate/+/refs/heads/master/usr/src/uts/common/sys/timerfd.h#34>
553#[cfg(all(feature = "time", target_os = "illumos"))]
554pub(crate) const TFD_CLOEXEC: i32 = 0o2000000;
555#[cfg(all(feature = "time", target_os = "illumos"))]
556pub(crate) const TFD_NONBLOCK: i32 = 0o4000;
557#[cfg(all(feature = "time", target_os = "illumos"))]
558pub(crate) const TFD_TIMER_ABSTIME: i32 = 1 << 0;
559#[cfg(all(feature = "time", target_os = "illumos"))]
560pub(crate) const TFD_TIMER_CANCEL_ON_SET: i32 = 1 << 1;
561
562// <https://nxr.netbsd.org/xref/src/sys/sys/timerfd.h#44>
563#[cfg(all(feature = "time", target_os = "netbsd"))]
564pub(crate) const TFD_CLOEXEC: i32 = O_CLOEXEC;
565#[cfg(all(feature = "time", target_os = "netbsd"))]
566pub(crate) const TFD_NONBLOCK: i32 = O_NONBLOCK;
567#[cfg(all(feature = "time", target_os = "netbsd"))]
568pub(crate) const TFD_TIMER_ABSTIME: i32 = O_WRONLY;
569#[cfg(all(feature = "time", target_os = "netbsd"))]
570pub(crate) const TFD_TIMER_CANCEL_ON_SET: i32 = O_RDWR;
571
572#[cfg(test)]
573mod tests {
574    use super::*;
575
576    #[test]
577    #[cfg(linux_kernel)]
578    fn test_flags() {
579        // libc may publicly define `O_LARGEFILE` to 0, but we want the real
580        // non-zero value.
581        assert_ne!(O_LARGEFILE, 0);
582    }
583}