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.
7 pub(crate) use libc::*;
8 
9 /// `PROC_SUPER_MAGIC`—The magic number for the procfs filesystem.
10 #[cfg(all(linux_kernel, target_env = "musl"))]
11 pub(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"))]
15 pub(crate) const NFS_SUPER_MAGIC: u32 = 0x0000_6969;
16 
17 #[cfg(feature = "process")]
18 #[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
19 pub(crate) const EXIT_SIGNALED_SIGABRT: c_int = 128 + SIGABRT as c_int;
20 
21 // TODO: Upstream these.
22 #[cfg(all(linux_kernel, feature = "net"))]
23 pub(crate) const ETH_P_TSN: c_int = linux_raw_sys::if_ether::ETH_P_TSN as _;
24 #[cfg(all(linux_kernel, feature = "net"))]
25 pub(crate) const ETH_P_ERSPAN2: c_int = linux_raw_sys::if_ether::ETH_P_ERSPAN2 as _;
26 #[cfg(all(linux_kernel, feature = "net"))]
27 pub(crate) const ETH_P_ERSPAN: c_int = linux_raw_sys::if_ether::ETH_P_ERSPAN as _;
28 #[cfg(all(linux_kernel, feature = "net"))]
29 pub(crate) const ETH_P_PROFINET: c_int = linux_raw_sys::if_ether::ETH_P_PROFINET as _;
30 #[cfg(all(linux_kernel, feature = "net"))]
31 pub(crate) const ETH_P_REALTEK: c_int = linux_raw_sys::if_ether::ETH_P_REALTEK as _;
32 #[cfg(all(linux_kernel, feature = "net"))]
33 pub(crate) const ETH_P_ETHERCAT: c_int = linux_raw_sys::if_ether::ETH_P_ETHERCAT as _;
34 #[cfg(all(linux_kernel, feature = "net"))]
35 pub(crate) const ETH_P_PREAUTH: c_int = linux_raw_sys::if_ether::ETH_P_PREAUTH as _;
36 #[cfg(all(linux_kernel, feature = "net"))]
37 pub(crate) const ETH_P_LLDP: c_int = linux_raw_sys::if_ether::ETH_P_LLDP as _;
38 #[cfg(all(linux_kernel, feature = "net"))]
39 pub(crate) const ETH_P_MRP: c_int = linux_raw_sys::if_ether::ETH_P_MRP as _;
40 #[cfg(all(linux_kernel, feature = "net"))]
41 pub(crate) const ETH_P_NCSI: c_int = linux_raw_sys::if_ether::ETH_P_NCSI as _;
42 #[cfg(all(linux_kernel, feature = "net"))]
43 pub(crate) const ETH_P_CFM: c_int = linux_raw_sys::if_ether::ETH_P_CFM as _;
44 #[cfg(all(linux_kernel, feature = "net"))]
45 pub(crate) const ETH_P_IBOE: c_int = linux_raw_sys::if_ether::ETH_P_IBOE as _;
46 #[cfg(all(linux_kernel, feature = "net"))]
47 pub(crate) const ETH_P_HSR: c_int = linux_raw_sys::if_ether::ETH_P_HSR as _;
48 #[cfg(all(linux_kernel, feature = "net"))]
49 pub(crate) const ETH_P_NSH: c_int = linux_raw_sys::if_ether::ETH_P_NSH as _;
50 #[cfg(all(linux_kernel, feature = "net"))]
51 pub(crate) const ETH_P_DSA_8021Q: c_int = linux_raw_sys::if_ether::ETH_P_DSA_8021Q as _;
52 #[cfg(all(linux_kernel, feature = "net"))]
53 pub(crate) const ETH_P_DSA_A5PSW: c_int = linux_raw_sys::if_ether::ETH_P_DSA_A5PSW as _;
54 #[cfg(all(linux_kernel, feature = "net"))]
55 pub(crate) const ETH_P_IFE: c_int = linux_raw_sys::if_ether::ETH_P_IFE as _;
56 #[cfg(all(linux_kernel, feature = "net"))]
57 pub(crate) const ETH_P_CAN: c_int = linux_raw_sys::if_ether::ETH_P_CAN as _;
58 #[cfg(all(linux_kernel, feature = "net"))]
59 pub(crate) const ETH_P_CANXL: c_int = linux_raw_sys::if_ether::ETH_P_CANXL as _;
60 #[cfg(all(linux_kernel, feature = "net"))]
61 pub(crate) const ETH_P_XDSA: c_int = linux_raw_sys::if_ether::ETH_P_XDSA as _;
62 #[cfg(all(linux_kernel, feature = "net"))]
63 pub(crate) const ETH_P_MAP: c_int = linux_raw_sys::if_ether::ETH_P_MAP as _;
64 #[cfg(all(linux_kernel, feature = "net"))]
65 pub(crate) const ETH_P_MCTP: c_int = linux_raw_sys::if_ether::ETH_P_MCTP as _;
66 
67 #[cfg(all(
68     linux_kernel,
69     any(
70         target_arch = "mips",
71         target_arch = "mips32r6",
72         target_arch = "mips64",
73         target_arch = "mips64r6",
74         target_arch = "sparc",
75         target_arch = "sparc64"
76     )
77 ))]
78 pub(crate) const SIGEMT: c_int = linux_raw_sys::general::SIGEMT as _;
79 
80 // TODO: Upstream these.
81 #[cfg(all(linux_kernel, feature = "termios"))]
82 pub(crate) const IUCLC: tcflag_t = linux_raw_sys::general::IUCLC as _;
83 #[cfg(all(linux_kernel, feature = "termios"))]
84 pub(crate) const XCASE: tcflag_t = linux_raw_sys::general::XCASE as _;
85 
86 #[cfg(target_os = "aix")]
87 pub(crate) const MSG_DONTWAIT: c_int = libc::MSG_NONBLOCK;
88 
89 // TODO: Remove once https://github.com/rust-lang/libc/pull/3377 is merged and released.
90 #[cfg(target_os = "netbsd")]
91 #[cfg(feature = "net")]
92 pub(crate) const SO_NOSIGPIPE: c_int = 0x0800;
93 
94 // On PowerPC, the regular `termios` has the `termios2` fields and there is no
95 // `termios2`. linux-raw-sys has aliases `termios2` to `termios` to cover this
96 // difference, but we still need to manually import it since `libc` doesn't
97 // have this.
98 #[cfg(all(
99     linux_kernel,
100     feature = "termios",
101     any(target_arch = "powerpc", target_arch = "powerpc64")
102 ))]
103 pub(crate) use {
104     linux_raw_sys::general::{termios2, CIBAUD},
105     linux_raw_sys::ioctl::{TCGETS2, TCSETS2, TCSETSF2, TCSETSW2},
106 };
107 
108 // Automatically enable “large file” support (LFS) features.
109 
110 #[cfg(target_os = "vxworks")]
111 pub(super) use libc::_Vx_ticks64_t as _Vx_ticks_t;
112 #[cfg(linux_kernel)]
113 pub(super) use libc::fallocate64 as fallocate;
114 #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
115 #[cfg(any(linux_like, target_os = "aix"))]
116 pub(super) use libc::open64 as open;
117 #[cfg(any(
118     linux_kernel,
119     target_os = "aix",
120     target_os = "hurd",
121     target_os = "l4re"
122 ))]
123 pub(super) use libc::posix_fallocate64 as posix_fallocate;
124 #[cfg(any(all(linux_like, not(target_os = "android")), target_os = "aix"))]
125 pub(super) use libc::{blkcnt64_t as blkcnt_t, rlim64_t as rlim_t};
126 // TODO: AIX has `stat64x`, `fstat64x`, `lstat64x`, and `stat64xat`; add them
127 // to the upstream libc crate and implement rustix's `statat` etc. with them.
128 #[cfg(target_os = "aix")]
129 pub(super) use libc::{
130     blksize64_t as blksize_t, fstat64 as fstat, fstatfs64 as fstatfs, fstatvfs64 as fstatvfs,
131     ftruncate64 as ftruncate, getrlimit64 as getrlimit, ino_t, lseek64 as lseek, mmap,
132     off64_t as off_t, openat, posix_fadvise64 as posix_fadvise, preadv, pwritev,
133     rlimit64 as rlimit, setrlimit64 as setrlimit, stat64at as fstatat, statfs64 as statfs,
134     statvfs64 as statvfs, RLIM_INFINITY,
135 };
136 #[cfg(any(linux_like, target_os = "hurd"))]
137 pub(super) use libc::{
138     fstat64 as fstat, fstatat64 as fstatat, fstatfs64 as fstatfs, fstatvfs64 as fstatvfs,
139     ftruncate64 as ftruncate, getrlimit64 as getrlimit, ino64_t as ino_t, lseek64 as lseek,
140     mmap64 as mmap, off64_t as off_t, openat64 as openat, posix_fadvise64 as posix_fadvise,
141     rlimit64 as rlimit, setrlimit64 as setrlimit, statfs64 as statfs, statvfs64 as statvfs,
142     RLIM64_INFINITY as RLIM_INFINITY,
143 };
144 #[cfg(apple)]
145 pub(super) use libc::{
146     host_info64_t as host_info_t, host_statistics64 as host_statistics,
147     vm_statistics64_t as vm_statistics_t,
148 };
149 #[cfg(not(all(
150     linux_kernel,
151     any(
152         target_pointer_width = "32",
153         target_arch = "mips64",
154         target_arch = "mips64r6"
155     )
156 )))]
157 #[cfg(any(linux_like, target_os = "aix", target_os = "hurd"))]
158 pub(super) use libc::{lstat64 as lstat, stat64 as stat};
159 #[cfg(any(
160     linux_kernel,
161     target_os = "aix",
162     target_os = "hurd",
163     target_os = "emscripten"
164 ))]
165 pub(super) use libc::{pread64 as pread, pwrite64 as pwrite};
166 #[cfg(any(target_os = "linux", target_os = "hurd", target_os = "emscripten"))]
167 pub(super) use libc::{preadv64 as preadv, pwritev64 as pwritev};
168 
169 #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]
prlimit( pid: libc::pid_t, resource: libc::__rlimit_resource_t, new_limit: *const libc::rlimit64, old_limit: *mut libc::rlimit64, ) -> libc::c_int170 pub(super) unsafe fn prlimit(
171     pid: libc::pid_t,
172     resource: libc::__rlimit_resource_t,
173     new_limit: *const libc::rlimit64,
174     old_limit: *mut libc::rlimit64,
175 ) -> libc::c_int {
176     // `prlimit64` wasn't supported in glibc until 2.13.
177     weak_or_syscall! {
178         fn prlimit64(
179             pid: libc::pid_t,
180             resource: libc::__rlimit_resource_t,
181             new_limit: *const libc::rlimit64,
182             old_limit: *mut libc::rlimit64
183         ) via SYS_prlimit64 -> libc::c_int
184     }
185 
186     prlimit64(pid, resource, new_limit, old_limit)
187 }
188 
189 #[cfg(all(target_os = "linux", target_env = "musl"))]
prlimit( pid: libc::pid_t, resource: libc::c_int, new_limit: *const libc::rlimit64, old_limit: *mut libc::rlimit64, ) -> libc::c_int190 pub(super) unsafe fn prlimit(
191     pid: libc::pid_t,
192     resource: libc::c_int,
193     new_limit: *const libc::rlimit64,
194     old_limit: *mut libc::rlimit64,
195 ) -> libc::c_int {
196     weak_or_syscall! {
197         fn prlimit64(
198             pid: libc::pid_t,
199             resource: libc::c_int,
200             new_limit: *const libc::rlimit64,
201             old_limit: *mut libc::rlimit64
202         ) via SYS_prlimit64 -> libc::c_int
203     }
204 
205     prlimit64(pid, resource, new_limit, old_limit)
206 }
207 
208 #[cfg(target_os = "android")]
prlimit( pid: libc::pid_t, resource: libc::c_int, new_limit: *const libc::rlimit64, old_limit: *mut libc::rlimit64, ) -> libc::c_int209 pub(super) unsafe fn prlimit(
210     pid: libc::pid_t,
211     resource: libc::c_int,
212     new_limit: *const libc::rlimit64,
213     old_limit: *mut libc::rlimit64,
214 ) -> libc::c_int {
215     weak_or_syscall! {
216         fn prlimit64(
217             pid: libc::pid_t,
218             resource: libc::c_int,
219             new_limit: *const libc::rlimit64,
220             old_limit: *mut libc::rlimit64
221         ) via SYS_prlimit64 -> libc::c_int
222     }
223 
224     prlimit64(pid, resource, new_limit, old_limit)
225 }
226 
227 #[cfg(target_os = "android")]
228 mod readwrite_pv64 {
229     use super::*;
230 
preadv64( fd: libc::c_int, iov: *const libc::iovec, iovcnt: libc::c_int, offset: libc::off64_t, ) -> libc::ssize_t231     pub(in super::super) unsafe fn preadv64(
232         fd: libc::c_int,
233         iov: *const libc::iovec,
234         iovcnt: libc::c_int,
235         offset: libc::off64_t,
236     ) -> libc::ssize_t {
237         // Older Android libc lacks `preadv64`, so use the `weak!` mechanism to
238         // test for it, and call back to `libc::syscall`. We don't use
239         // `weak_or_syscall` here because we need to pass the 64-bit offset
240         // specially.
241         weak! {
242             fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, libc::off64_t) -> libc::ssize_t
243         }
244         if let Some(fun) = preadv64.get() {
245             fun(fd, iov, iovcnt, offset)
246         } else {
247             // Unlike the plain "p" functions, the "pv" functions pass their
248             // offset in an endian-independent way, and always in two registers.
249             syscall! {
250                 fn preadv(
251                     fd: libc::c_int,
252                     iov: *const libc::iovec,
253                     iovcnt: libc::c_int,
254                     offset_lo: usize,
255                     offset_hi: usize
256                 ) via SYS_preadv -> libc::ssize_t
257             }
258             preadv(fd, iov, iovcnt, offset as usize, (offset >> 32) as usize)
259         }
260     }
pwritev64( fd: libc::c_int, iov: *const libc::iovec, iovcnt: libc::c_int, offset: libc::off64_t, ) -> libc::ssize_t261     pub(in super::super) unsafe fn pwritev64(
262         fd: libc::c_int,
263         iov: *const libc::iovec,
264         iovcnt: libc::c_int,
265         offset: libc::off64_t,
266     ) -> libc::ssize_t {
267         // See the comments in `preadv64`.
268         weak! {
269             fn pwritev64(libc::c_int, *const libc::iovec, libc::c_int, libc::off64_t) -> libc::ssize_t
270         }
271         if let Some(fun) = pwritev64.get() {
272             fun(fd, iov, iovcnt, offset)
273         } else {
274             // Unlike the plain "p" functions, the "pv" functions pass their
275             // offset in an endian-independent way, and always in two registers.
276             syscall! {
277                 fn pwritev(
278                     fd: libc::c_int,
279                     iov: *const libc::iovec,
280                     iovcnt: libc::c_int,
281                     offset_lo: usize,
282                     offset_hi: usize
283                 ) via SYS_pwritev -> libc::ssize_t
284             }
285             pwritev(fd, iov, iovcnt, offset as usize, (offset >> 32) as usize)
286         }
287     }
288 }
289 #[cfg(target_os = "android")]
290 pub(super) use readwrite_pv64::{preadv64 as preadv, pwritev64 as pwritev};
291 
292 // macOS added `preadv` and `pwritev` in version 11.0.
293 #[cfg(apple)]
294 mod readwrite_pv {
295     weakcall! {
296         pub(in super::super) fn preadv(
297             fd: libc::c_int,
298             iov: *const libc::iovec,
299             iovcnt: libc::c_int,
300             offset: libc::off_t
301         ) -> libc::ssize_t
302     }
303     weakcall! {
304         pub(in super::super) fn pwritev(
305             fd: libc::c_int,
306             iov: *const libc::iovec,
307             iovcnt: libc::c_int, offset: libc::off_t
308         ) -> libc::ssize_t
309     }
310 }
311 #[cfg(apple)]
312 pub(super) use readwrite_pv::{preadv, pwritev};
313 
314 // glibc added `preadv64v2` and `pwritev64v2` in version 2.26.
315 #[cfg(all(target_os = "linux", target_env = "gnu"))]
316 mod readwrite_pv64v2 {
317     use super::*;
318 
preadv64v2( fd: libc::c_int, iov: *const libc::iovec, iovcnt: libc::c_int, offset: libc::off64_t, flags: libc::c_int, ) -> libc::ssize_t319     pub(in super::super) unsafe fn preadv64v2(
320         fd: libc::c_int,
321         iov: *const libc::iovec,
322         iovcnt: libc::c_int,
323         offset: libc::off64_t,
324         flags: libc::c_int,
325     ) -> libc::ssize_t {
326         // Older glibc lacks `preadv64v2`, so use the `weak!` mechanism to
327         // test for it, and call back to `libc::syscall`. We don't use
328         // `weak_or_syscall` here because we need to pass the 64-bit offset
329         // specially.
330         weak! {
331             fn preadv64v2(libc::c_int, *const libc::iovec, libc::c_int, libc::off64_t, libc::c_int) -> libc::ssize_t
332         }
333         if let Some(fun) = preadv64v2.get() {
334             fun(fd, iov, iovcnt, offset, flags)
335         } else {
336             // Unlike the plain "p" functions, the "pv" functions pass their
337             // offset in an endian-independent way, and always in two registers.
338             syscall! {
339                 fn preadv2(
340                     fd: libc::c_int,
341                     iov: *const libc::iovec,
342                     iovcnt: libc::c_int,
343                     offset_lo: usize,
344                     offset_hi: usize,
345                     flags: libc::c_int
346                 ) via SYS_preadv2 -> libc::ssize_t
347             }
348             preadv2(
349                 fd,
350                 iov,
351                 iovcnt,
352                 offset as usize,
353                 (offset >> 32) as usize,
354                 flags,
355             )
356         }
357     }
pwritev64v2( fd: libc::c_int, iov: *const libc::iovec, iovcnt: libc::c_int, offset: libc::off64_t, flags: libc::c_int, ) -> libc::ssize_t358     pub(in super::super) unsafe fn pwritev64v2(
359         fd: libc::c_int,
360         iov: *const libc::iovec,
361         iovcnt: libc::c_int,
362         offset: libc::off64_t,
363         flags: libc::c_int,
364     ) -> libc::ssize_t {
365         // See the comments in `preadv64v2`.
366         weak! {
367             fn pwritev64v2(libc::c_int, *const libc::iovec, libc::c_int, libc::off64_t, libc::c_int) -> libc::ssize_t
368         }
369         if let Some(fun) = pwritev64v2.get() {
370             fun(fd, iov, iovcnt, offset, flags)
371         } else {
372             // Unlike the plain "p" functions, the "pv" functions pass their
373             // offset in an endian-independent way, and always in two registers.
374             syscall! {
375                 fn pwritev2(
376                     fd: libc::c_int,
377                     iov: *const libc::iovec,
378                     iovec: libc::c_int,
379                     offset_lo: usize,
380                     offset_hi: usize,
381                     flags: libc::c_int
382                 ) via SYS_pwritev2 -> libc::ssize_t
383             }
384             pwritev2(
385                 fd,
386                 iov,
387                 iovcnt,
388                 offset as usize,
389                 (offset >> 32) as usize,
390                 flags,
391             )
392         }
393     }
394 }
395 #[cfg(all(target_os = "linux", target_env = "gnu"))]
396 pub(super) use readwrite_pv64v2::{preadv64v2 as preadv2, pwritev64v2 as pwritev2};
397 
398 // On non-glibc, assume we don't have `pwritev2`/`preadv2` in libc and use
399 // `c::syscall` instead.
400 #[cfg(any(
401     target_os = "android",
402     all(target_os = "linux", not(target_env = "gnu")),
403 ))]
404 mod readwrite_pv64v2 {
405     use super::*;
406 
preadv64v2( fd: libc::c_int, iov: *const libc::iovec, iovcnt: libc::c_int, offset: libc::off64_t, flags: libc::c_int, ) -> libc::ssize_t407     pub(in super::super) unsafe fn preadv64v2(
408         fd: libc::c_int,
409         iov: *const libc::iovec,
410         iovcnt: libc::c_int,
411         offset: libc::off64_t,
412         flags: libc::c_int,
413     ) -> libc::ssize_t {
414         // Unlike the plain "p" functions, the "pv" functions pass their offset
415         // in an endian-independent way, and always in two registers.
416         syscall! {
417             fn preadv2(
418                 fd: libc::c_int,
419                 iov: *const libc::iovec,
420                 iovcnt: libc::c_int,
421                 offset_lo: usize,
422                 offset_hi: usize,
423                 flags: libc::c_int
424             ) via SYS_preadv2 -> libc::ssize_t
425         }
426         preadv2(
427             fd,
428             iov,
429             iovcnt,
430             offset as usize,
431             (offset >> 32) as usize,
432             flags,
433         )
434     }
pwritev64v2( fd: libc::c_int, iov: *const libc::iovec, iovcnt: libc::c_int, offset: libc::off64_t, flags: libc::c_int, ) -> libc::ssize_t435     pub(in super::super) unsafe fn pwritev64v2(
436         fd: libc::c_int,
437         iov: *const libc::iovec,
438         iovcnt: libc::c_int,
439         offset: libc::off64_t,
440         flags: libc::c_int,
441     ) -> libc::ssize_t {
442         // Unlike the plain "p" functions, the "pv" functions pass their offset
443         // in an endian-independent way, and always in two registers.
444         syscall! {
445             fn pwritev2(
446                 fd: libc::c_int,
447                 iov: *const libc::iovec,
448                 iovcnt: libc::c_int,
449                 offset_lo: usize,
450                 offset_hi: usize,
451                 flags: libc::c_int
452             ) via SYS_pwritev2 -> libc::ssize_t
453         }
454         pwritev2(
455             fd,
456             iov,
457             iovcnt,
458             offset as usize,
459             (offset >> 32) as usize,
460             flags,
461         )
462     }
463 }
464 #[cfg(any(
465     target_os = "android",
466     all(target_os = "linux", not(target_env = "gnu")),
467 ))]
468 pub(super) use readwrite_pv64v2::{preadv64v2 as preadv2, pwritev64v2 as pwritev2};
469