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