@@ -213,8 +213,21 @@ pub(super) use c::posix_fadvise64 as libc_posix_fadvise;
213213pub ( super ) use c:: { pread as libc_pread, pwrite as libc_pwrite} ;
214214#[ cfg( any( target_os = "android" , target_os = "linux" , target_os = "emscripten" ) ) ]
215215pub ( 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} ;
216228#[ cfg( any( target_os = "linux" , target_os = "emscripten" ) ) ]
217229pub ( super ) use c:: { preadv64 as libc_preadv, pwritev64 as libc_pwritev} ;
230+
218231#[ cfg( target_os = "android" ) ]
219232mod readwrite_pv64 {
220233 use super :: c;
@@ -302,20 +315,9 @@ mod readwrite_pv64 {
302315 }
303316 }
304317}
305- #[ cfg( not( any(
306- windows,
307- target_os = "android" ,
308- target_os = "emscripten" ,
309- target_os = "haiku" ,
310- target_os = "ios" ,
311- target_os = "linux" ,
312- target_os = "macos" ,
313- target_os = "redox" ,
314- target_os = "solaris" ,
315- ) ) ) ]
316- pub ( super ) use c:: { preadv as libc_preadv, pwritev as libc_pwritev} ;
317318#[ cfg( target_os = "android" ) ]
318319pub ( super ) use readwrite_pv64:: { preadv64 as libc_preadv, pwritev64 as libc_pwritev} ;
320+
319321// macOS added preadv and pwritev in version 11.0
320322#[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
321323mod readwrite_pv {
@@ -337,11 +339,104 @@ mod readwrite_pv {
337339 ) -> c:: ssize_t
338340 }
339341}
340- #[ cfg( all( target_os = "linux" , target_env = "gnu" ) ) ]
341- pub ( super ) use c:: { preadv64v2 as libc_preadv2, pwritev64v2 as libc_pwritev2} ;
342342#[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
343343pub ( super ) use readwrite_pv:: { preadv as libc_preadv, pwritev as libc_pwritev} ;
344344
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" ) ) ]
353+ fn lo ( x : u64 ) -> usize {
354+ ( x >> 32 ) as usize
355+ }
356+ #[ cfg( all( target_endian = "little" , target_pointer_width = "32" ) ) ]
357+ fn hi ( x : u64 ) -> usize {
358+ ( x & 0xffff_ffff ) as usize
359+ }
360+ #[ cfg( all( target_endian = "big" , target_pointer_width = "32" ) ) ]
361+ fn lo ( x : u64 ) -> usize {
362+ ( x & 0xffff_ffff ) as usize
363+ }
364+ #[ cfg( all( target_endian = "big" , target_pointer_width = "32" ) ) ]
365+ fn hi ( x : u64 ) -> usize {
366+ ( x >> 32 ) as usize
367+ }
368+
369+ 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+ }
404+ 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+
345440#[ cfg( not( any(
346441 windows,
347442 target_os = "aix" ,
0 commit comments