1 //! Automatically enable “large file” support features.
2
3 #[cfg(not(windows))]
4 use super::c;
5
6 #[cfg(not(any(
7 windows,
8 target_os = "android",
9 target_os = "emscripten",
10 target_os = "l4re",
11 target_os = "linux",
12 )))]
13 #[cfg(feature = "fs")]
14 pub(super) use c::{
15 fstat as libc_fstat, fstatat as libc_fstatat, ftruncate as libc_ftruncate, lseek as libc_lseek,
16 off_t as libc_off_t,
17 };
18
19 #[cfg(any(
20 target_os = "android",
21 target_os = "emscripten",
22 target_os = "l4re",
23 target_os = "linux",
24 ))]
25 #[cfg(feature = "fs")]
26 pub(super) use c::{
27 fstat64 as libc_fstat, fstatat64 as libc_fstatat, ftruncate64 as libc_ftruncate,
28 lseek64 as libc_lseek, off64_t as libc_off_t,
29 };
30
31 #[cfg(any(
32 target_os = "android",
33 target_os = "emscripten",
34 target_os = "l4re",
35 target_os = "linux",
36 ))]
37 pub(super) use c::rlimit64 as libc_rlimit;
38
39 #[cfg(not(any(
40 windows,
41 target_os = "android",
42 target_os = "emscripten",
43 target_os = "l4re",
44 target_os = "linux",
45 target_os = "wasi",
46 )))]
47 #[cfg(feature = "mm")]
48 pub(super) use c::mmap as libc_mmap;
49
50 #[cfg(not(any(
51 windows,
52 target_os = "android",
53 target_os = "emscripten",
54 target_os = "fuchsia",
55 target_os = "l4re",
56 target_os = "linux",
57 target_os = "redox",
58 target_os = "wasi",
59 )))]
60 pub(super) use c::{rlimit as libc_rlimit, RLIM_INFINITY as LIBC_RLIM_INFINITY};
61
62 #[cfg(not(any(
63 windows,
64 target_os = "android",
65 target_os = "fuchsia",
66 target_os = "emscripten",
67 target_os = "l4re",
68 target_os = "linux",
69 target_os = "wasi",
70 )))]
71 pub(super) use c::{getrlimit as libc_getrlimit, setrlimit as libc_setrlimit};
72
73 // TODO: Add `RLIM64_INFINITY` to upstream libc.
74 #[cfg(any(
75 target_os = "android",
76 target_os = "linux",
77 target_os = "emscripten",
78 target_os = "l4re",
79 ))]
80 pub(super) const LIBC_RLIM_INFINITY: u64 = !0_u64;
81
82 #[cfg(any(
83 target_os = "android",
84 target_os = "linux",
85 target_os = "emscripten",
86 target_os = "l4re",
87 ))]
88 pub(super) use c::{getrlimit64 as libc_getrlimit, setrlimit64 as libc_setrlimit};
89
90 #[cfg(any(
91 target_os = "android",
92 target_os = "linux",
93 target_os = "emscripten",
94 target_os = "l4re",
95 ))]
96 #[cfg(feature = "mm")]
97 pub(super) use c::mmap64 as libc_mmap;
98
99 // `prlimit64` wasn't supported in glibc until 2.13.
100 #[cfg(all(target_os = "linux", target_env = "gnu"))]
101 weak_or_syscall! {
102 fn prlimit64(
103 pid: c::pid_t,
104 resource: c::__rlimit_resource_t,
105 new_limit: *const c::rlimit64,
106 old_limit: *mut c::rlimit64
107 ) via SYS_prlimit64 -> c::c_int
108 }
109 #[cfg(all(target_os = "linux", target_env = "musl"))]
110 weak_or_syscall! {
111 fn prlimit64(
112 pid: c::pid_t,
113 resource: c::c_int,
114 new_limit: *const c::rlimit64,
115 old_limit: *mut c::rlimit64
116 ) via SYS_prlimit64 -> c::c_int
117 }
118 #[cfg(target_os = "android")]
119 weak_or_syscall! {
120 fn prlimit64(
121 pid: c::pid_t,
122 resource: c::c_int,
123 new_limit: *const c::rlimit64,
124 old_limit: *mut c::rlimit64
125 ) via SYS_prlimit64 -> c::c_int
126 }
127 #[cfg(all(target_os = "linux", target_env = "gnu"))]
libc_prlimit( pid: c::pid_t, resource: c::__rlimit_resource_t, new_limit: *const c::rlimit64, old_limit: *mut c::rlimit64, ) -> c::c_int128 pub(super) unsafe fn libc_prlimit(
129 pid: c::pid_t,
130 resource: c::__rlimit_resource_t,
131 new_limit: *const c::rlimit64,
132 old_limit: *mut c::rlimit64,
133 ) -> c::c_int {
134 prlimit64(pid, resource, new_limit, old_limit)
135 }
136 #[cfg(all(target_os = "linux", target_env = "musl"))]
libc_prlimit( pid: c::pid_t, resource: c::c_int, new_limit: *const c::rlimit64, old_limit: *mut c::rlimit64, ) -> c::c_int137 pub(super) unsafe fn libc_prlimit(
138 pid: c::pid_t,
139 resource: c::c_int,
140 new_limit: *const c::rlimit64,
141 old_limit: *mut c::rlimit64,
142 ) -> c::c_int {
143 prlimit64(pid, resource, new_limit, old_limit)
144 }
145 #[cfg(target_os = "android")]
libc_prlimit( pid: c::pid_t, resource: c::c_int, new_limit: *const c::rlimit64, old_limit: *mut c::rlimit64, ) -> c::c_int146 pub(super) unsafe fn libc_prlimit(
147 pid: c::pid_t,
148 resource: c::c_int,
149 new_limit: *const c::rlimit64,
150 old_limit: *mut c::rlimit64,
151 ) -> c::c_int {
152 prlimit64(pid, resource, new_limit, old_limit)
153 }
154
155 #[cfg(not(any(
156 windows,
157 target_os = "android",
158 target_os = "linux",
159 target_os = "emscripten",
160 target_os = "l4re",
161 target_os = "redox",
162 )))]
163 #[cfg(feature = "fs")]
164 pub(super) use c::openat as libc_openat;
165 #[cfg(any(
166 target_os = "android",
167 target_os = "linux",
168 target_os = "emscripten",
169 target_os = "l4re",
170 ))]
171 #[cfg(feature = "fs")]
172 pub(super) use c::openat64 as libc_openat;
173
174 #[cfg(target_os = "fuchsia")]
175 #[cfg(feature = "fs")]
176 pub(super) use c::fallocate as libc_fallocate;
177 #[cfg(any(target_os = "android", target_os = "linux"))]
178 #[cfg(feature = "fs")]
179 pub(super) use c::fallocate64 as libc_fallocate;
180 #[cfg(not(any(
181 windows,
182 target_os = "android",
183 target_os = "dragonfly",
184 target_os = "emscripten",
185 target_os = "haiku",
186 target_os = "illumos",
187 target_os = "ios",
188 target_os = "linux",
189 target_os = "l4re",
190 target_os = "macos",
191 target_os = "netbsd",
192 target_os = "openbsd",
193 target_os = "redox",
194 target_os = "solaris",
195 )))]
196 #[cfg(feature = "fs")]
197 pub(super) use c::posix_fadvise as libc_posix_fadvise;
198 #[cfg(any(
199 target_os = "android",
200 target_os = "emscripten",
201 target_os = "linux",
202 target_os = "l4re",
203 ))]
204 #[cfg(feature = "fs")]
205 pub(super) use c::posix_fadvise64 as libc_posix_fadvise;
206
207 #[cfg(all(not(any(
208 windows,
209 target_os = "android",
210 target_os = "linux",
211 target_os = "emscripten",
212 ))))]
213 pub(super) use c::{pread as libc_pread, pwrite as libc_pwrite};
214 #[cfg(any(target_os = "android", target_os = "linux", target_os = "emscripten"))]
215 pub(super) use c::{pread64 as libc_pread, pwrite64 as libc_pwrite};
216 #[cfg(not(any(
217 windows,
218 target_os = "android",
219 target_os = "emscripten",
220 target_os = "haiku",
221 target_os = "ios",
222 target_os = "linux",
223 target_os = "macos",
224 target_os = "redox",
225 target_os = "solaris",
226 )))]
227 pub(super) use c::{preadv as libc_preadv, pwritev as libc_pwritev};
228 #[cfg(any(target_os = "linux", target_os = "emscripten"))]
229 pub(super) use c::{preadv64 as libc_preadv, pwritev64 as libc_pwritev};
230
231 #[cfg(target_os = "android")]
232 mod readwrite_pv64 {
233 use super::c;
234
235 // 64-bit offsets on 32-bit platforms are passed in endianness-specific
236 // lo/hi pairs. See src/backend/linux_raw/conv.rs for details.
237 #[cfg(all(target_endian = "little", target_pointer_width = "32"))]
lo(x: u64) -> usize238 fn lo(x: u64) -> usize {
239 (x >> 32) as usize
240 }
241 #[cfg(all(target_endian = "little", target_pointer_width = "32"))]
hi(x: u64) -> usize242 fn hi(x: u64) -> usize {
243 (x & 0xffff_ffff) as usize
244 }
245 #[cfg(all(target_endian = "big", target_pointer_width = "32"))]
lo(x: u64) -> usize246 fn lo(x: u64) -> usize {
247 (x & 0xffff_ffff) as usize
248 }
249 #[cfg(all(target_endian = "big", target_pointer_width = "32"))]
hi(x: u64) -> usize250 fn hi(x: u64) -> usize {
251 (x >> 32) as usize
252 }
253
preadv64( fd: c::c_int, iov: *const c::iovec, iovcnt: c::c_int, offset: c::off64_t, ) -> c::ssize_t254 pub(in super::super) unsafe fn preadv64(
255 fd: c::c_int,
256 iov: *const c::iovec,
257 iovcnt: c::c_int,
258 offset: c::off64_t,
259 ) -> c::ssize_t {
260 // Older Android libc lacks `preadv64`, so use the `weak!` mechanism to
261 // test for it, and call back to `c::syscall`. We don't use
262 // `weak_or_syscall` here because we need to pass the 64-bit offset
263 // specially.
264 weak! {
265 fn preadv64(c::c_int, *const c::iovec, c::c_int, c::off64_t) -> c::ssize_t
266 }
267 if let Some(fun) = preadv64.get() {
268 fun(fd, iov, iovcnt, offset)
269 } else {
270 #[cfg(target_pointer_width = "32")]
271 {
272 c::syscall(
273 c::SYS_preadv,
274 fd,
275 iov,
276 iovcnt,
277 hi(offset as u64),
278 lo(offset as u64),
279 ) as c::ssize_t
280 }
281 #[cfg(target_pointer_width = "64")]
282 {
283 c::syscall(c::SYS_preadv, fd, iov, iovcnt, offset) as c::ssize_t
284 }
285 }
286 }
pwritev64( fd: c::c_int, iov: *const c::iovec, iovcnt: c::c_int, offset: c::off64_t, ) -> c::ssize_t287 pub(in super::super) unsafe fn pwritev64(
288 fd: c::c_int,
289 iov: *const c::iovec,
290 iovcnt: c::c_int,
291 offset: c::off64_t,
292 ) -> c::ssize_t {
293 // See the comments in `preadv64`.
294 weak! {
295 fn pwritev64(c::c_int, *const c::iovec, c::c_int, c::off64_t) -> c::ssize_t
296 }
297 if let Some(fun) = pwritev64.get() {
298 fun(fd, iov, iovcnt, offset)
299 } else {
300 #[cfg(target_pointer_width = "32")]
301 {
302 c::syscall(
303 c::SYS_pwritev,
304 fd,
305 iov,
306 iovcnt,
307 hi(offset as u64),
308 lo(offset as u64),
309 ) as c::ssize_t
310 }
311 #[cfg(target_pointer_width = "64")]
312 {
313 c::syscall(c::SYS_pwritev, fd, iov, iovcnt, offset) as c::ssize_t
314 }
315 }
316 }
317 }
318 #[cfg(target_os = "android")]
319 pub(super) use readwrite_pv64::{preadv64 as libc_preadv, pwritev64 as libc_pwritev};
320
321 // macOS added preadv and pwritev in version 11.0
322 #[cfg(any(target_os = "ios", target_os = "macos"))]
323 mod readwrite_pv {
324 use super::c;
325
326 weakcall! {
327 pub(in super::super) fn preadv(
328 fd: c::c_int,
329 iov: *const c::iovec,
330 iovcnt: c::c_int,
331 offset: c::off_t
332 ) -> c::ssize_t
333 }
334 weakcall! {
335 pub(in super::super) fn pwritev(
336 fd: c::c_int,
337 iov: *const c::iovec,
338 iovcnt: c::c_int, offset: c::off_t
339 ) -> c::ssize_t
340 }
341 }
342 #[cfg(any(target_os = "ios", target_os = "macos"))]
343 pub(super) use readwrite_pv::{preadv as libc_preadv, pwritev as libc_pwritev};
344
345 // GLIBC added `preadv64v2` and `pwritev64v2` in version 2.26.
346 #[cfg(all(target_os = "linux", target_env = "gnu"))]
347 mod readwrite_pv64v2 {
348 use super::c;
349
350 // 64-bit offsets on 32-bit platforms are passed in endianness-specific
351 // lo/hi pairs. See src/backend/linux_raw/conv.rs for details.
352 #[cfg(all(target_endian = "little", target_pointer_width = "32"))]
lo(x: u64) -> usize353 fn lo(x: u64) -> usize {
354 (x >> 32) as usize
355 }
356 #[cfg(all(target_endian = "little", target_pointer_width = "32"))]
hi(x: u64) -> usize357 fn hi(x: u64) -> usize {
358 (x & 0xffff_ffff) as usize
359 }
360 #[cfg(all(target_endian = "big", target_pointer_width = "32"))]
lo(x: u64) -> usize361 fn lo(x: u64) -> usize {
362 (x & 0xffff_ffff) as usize
363 }
364 #[cfg(all(target_endian = "big", target_pointer_width = "32"))]
hi(x: u64) -> usize365 fn hi(x: u64) -> usize {
366 (x >> 32) as usize
367 }
368
preadv64v2( fd: c::c_int, iov: *const c::iovec, iovcnt: c::c_int, offset: c::off64_t, flags: c::c_int, ) -> c::ssize_t369 pub(in super::super) unsafe fn preadv64v2(
370 fd: c::c_int,
371 iov: *const c::iovec,
372 iovcnt: c::c_int,
373 offset: c::off64_t,
374 flags: c::c_int,
375 ) -> c::ssize_t {
376 // Older GLIBC lacks `preadv64v2`, so use the `weak!` mechanism to
377 // test for it, and call back to `c::syscall`. We don't use
378 // `weak_or_syscall` here because we need to pass the 64-bit offset
379 // specially.
380 weak! {
381 fn preadv64v2(c::c_int, *const c::iovec, c::c_int, c::off64_t, c::c_int) -> c::ssize_t
382 }
383 if let Some(fun) = preadv64v2.get() {
384 fun(fd, iov, iovcnt, offset, flags)
385 } else {
386 #[cfg(target_pointer_width = "32")]
387 {
388 c::syscall(
389 c::SYS_preadv,
390 fd,
391 iov,
392 iovcnt,
393 hi(offset as u64),
394 lo(offset as u64),
395 flags,
396 ) as c::ssize_t
397 }
398 #[cfg(target_pointer_width = "64")]
399 {
400 c::syscall(c::SYS_preadv2, fd, iov, iovcnt, offset, flags) as c::ssize_t
401 }
402 }
403 }
pwritev64v2( fd: c::c_int, iov: *const c::iovec, iovcnt: c::c_int, offset: c::off64_t, flags: c::c_int, ) -> c::ssize_t404 pub(in super::super) unsafe fn pwritev64v2(
405 fd: c::c_int,
406 iov: *const c::iovec,
407 iovcnt: c::c_int,
408 offset: c::off64_t,
409 flags: c::c_int,
410 ) -> c::ssize_t {
411 // See the comments in `preadv64v2`.
412 weak! {
413 fn pwritev64v2(c::c_int, *const c::iovec, c::c_int, c::off64_t, c::c_int) -> c::ssize_t
414 }
415 if let Some(fun) = pwritev64v2.get() {
416 fun(fd, iov, iovcnt, offset, flags)
417 } else {
418 #[cfg(target_pointer_width = "32")]
419 {
420 c::syscall(
421 c::SYS_pwritev,
422 fd,
423 iov,
424 iovcnt,
425 hi(offset as u64),
426 lo(offset as u64),
427 flags,
428 ) as c::ssize_t
429 }
430 #[cfg(target_pointer_width = "64")]
431 {
432 c::syscall(c::SYS_pwritev2, fd, iov, iovcnt, offset, flags) as c::ssize_t
433 }
434 }
435 }
436 }
437 #[cfg(all(target_os = "linux", target_env = "gnu"))]
438 pub(super) use readwrite_pv64v2::{preadv64v2 as libc_preadv2, pwritev64v2 as libc_pwritev2};
439
440 #[cfg(not(any(
441 windows,
442 target_os = "aix",
443 target_os = "android",
444 target_os = "dragonfly",
445 target_os = "fuchsia",
446 target_os = "illumos",
447 target_os = "ios",
448 target_os = "linux",
449 target_os = "l4re",
450 target_os = "macos",
451 target_os = "netbsd",
452 target_os = "openbsd",
453 target_os = "redox",
454 target_os = "solaris",
455 )))]
456 #[cfg(feature = "fs")]
457 pub(super) use c::posix_fallocate as libc_posix_fallocate;
458 #[cfg(target_os = "l4re")]
459 #[cfg(feature = "fs")]
460 pub(super) use c::posix_fallocate64 as libc_posix_fallocate;
461 #[cfg(not(any(
462 windows,
463 target_os = "android",
464 target_os = "emscripten",
465 target_os = "haiku",
466 target_os = "illumos",
467 target_os = "linux",
468 target_os = "l4re",
469 target_os = "netbsd",
470 target_os = "redox",
471 target_os = "solaris",
472 target_os = "wasi",
473 )))]
474 #[cfg(feature = "fs")]
475 pub(super) use {c::fstatfs as libc_fstatfs, c::statfs as libc_statfs};
476 #[cfg(not(any(
477 windows,
478 target_os = "android",
479 target_os = "emscripten",
480 target_os = "haiku",
481 target_os = "illumos",
482 target_os = "linux",
483 target_os = "l4re",
484 target_os = "redox",
485 target_os = "solaris",
486 target_os = "wasi",
487 )))]
488 #[cfg(feature = "fs")]
489 pub(super) use {c::fstatvfs as libc_fstatvfs, c::statvfs as libc_statvfs};
490
491 #[cfg(any(
492 target_os = "android",
493 target_os = "linux",
494 target_os = "emscripten",
495 target_os = "l4re",
496 ))]
497 #[cfg(feature = "fs")]
498 pub(super) use {
499 c::fstatfs64 as libc_fstatfs, c::fstatvfs64 as libc_fstatvfs, c::statfs64 as libc_statfs,
500 c::statvfs64 as libc_statvfs,
501 };
502