@@ -148,7 +148,6 @@ impl FileDesc {
148148 }
149149
150150 #[ cfg( any(
151- target_os = "android" ,
152151 target_os = "emscripten" ,
153152 target_os = "freebsd" ,
154153 target_os = "fuchsia" ,
@@ -171,7 +170,6 @@ impl FileDesc {
171170 }
172171
173172 #[ cfg( not( any(
174- target_os = "android" ,
175173 target_os = "emscripten" ,
176174 target_os = "freebsd" ,
177175 target_os = "fuchsia" ,
@@ -185,6 +183,54 @@ impl FileDesc {
185183 io:: default_read_vectored ( |b| self . read_at ( b, offset) , bufs)
186184 }
187185
186+ // We support some old Android versions that do not have `preadv` in libc,
187+ // so we use weak linkage and fallback to a direct syscall if not available.
188+ //
189+ // On 32-bit targets, we don't want to deal with weird ABI issues around
190+ // passing 64-bits parameters to syscalls, so we fallback to the default
191+ // implementation.
192+ #[ cfg( all( target_os = "android" , target_pointer_width = "64" ) ) ]
193+ pub fn read_vectored_at ( & self , bufs : & mut [ IoSliceMut < ' _ > ] , offset : u64 ) -> io:: Result < usize > {
194+ super :: weak:: syscall! {
195+ fn preadv(
196+ fd: libc:: c_int,
197+ iovec: * const libc:: iovec,
198+ n_iovec: libc:: c_int,
199+ offset: off64_t
200+ ) -> isize
201+ }
202+
203+ let ret = cvt ( unsafe {
204+ preadv (
205+ self . as_raw_fd ( ) ,
206+ bufs. as_mut_ptr ( ) as * mut libc:: iovec as * const libc:: iovec ,
207+ cmp:: min ( bufs. len ( ) , max_iov ( ) ) as libc:: c_int ,
208+ offset as _ ,
209+ )
210+ } ) ?;
211+ Ok ( ret as usize )
212+ }
213+
214+ #[ cfg( all( target_os = "android" , target_pointer_width = "32" ) ) ]
215+ pub fn read_vectored_at ( & self , bufs : & mut [ IoSliceMut < ' _ > ] , offset : u64 ) -> io:: Result < usize > {
216+ super :: weak:: weak!( fn preadv64( libc:: c_int, * const libc:: iovec, libc:: c_int, off64_t) -> isize ) ;
217+
218+ match preadv64. get ( ) {
219+ Some ( preadv) => {
220+ let ret = cvt ( unsafe {
221+ preadv (
222+ self . as_raw_fd ( ) ,
223+ bufs. as_mut_ptr ( ) as * mut libc:: iovec as * const libc:: iovec ,
224+ cmp:: min ( bufs. len ( ) , max_iov ( ) ) as libc:: c_int ,
225+ offset as _ ,
226+ )
227+ } ) ?;
228+ Ok ( ret as usize )
229+ }
230+ None => io:: default_read_vectored ( |b| self . read_at ( b, offset) , bufs) ,
231+ }
232+ }
233+
188234 pub fn write ( & self , buf : & [ u8 ] ) -> io:: Result < usize > {
189235 let ret = cvt ( unsafe {
190236 libc:: write (
@@ -236,7 +282,6 @@ impl FileDesc {
236282 }
237283
238284 #[ cfg( any(
239- target_os = "android" ,
240285 target_os = "emscripten" ,
241286 target_os = "freebsd" ,
242287 target_os = "fuchsia" ,
@@ -259,7 +304,6 @@ impl FileDesc {
259304 }
260305
261306 #[ cfg( not( any(
262- target_os = "android" ,
263307 target_os = "emscripten" ,
264308 target_os = "freebsd" ,
265309 target_os = "fuchsia" ,
@@ -273,6 +317,54 @@ impl FileDesc {
273317 io:: default_write_vectored ( |b| self . write_at ( b, offset) , bufs)
274318 }
275319
320+ // We support some old Android versions that do not have `pwritev` in libc,
321+ // so we use weak linkage and fallback to a direct syscall if not available.
322+ //
323+ // On 32-bit targets, we don't want to deal with weird ABI issues around
324+ // passing 64-bits parameters to syscalls, so we fallback to the default
325+ // implementation.
326+ #[ cfg( all( target_os = "android" , target_pointer_width = "64" ) ) ]
327+ pub fn write_vectored_at ( & self , bufs : & [ IoSlice < ' _ > ] , offset : u64 ) -> io:: Result < usize > {
328+ super :: weak:: syscall! {
329+ fn pwritev(
330+ fd: libc:: c_int,
331+ iovec: * const libc:: iovec,
332+ n_iovec: libc:: c_int,
333+ offset: off64_t
334+ ) -> isize
335+ }
336+
337+ let ret = cvt ( unsafe {
338+ pwritev (
339+ self . as_raw_fd ( ) ,
340+ bufs. as_ptr ( ) as * const libc:: iovec ,
341+ cmp:: min ( bufs. len ( ) , max_iov ( ) ) as libc:: c_int ,
342+ offset as _ ,
343+ )
344+ } ) ?;
345+ Ok ( ret as usize )
346+ }
347+
348+ #[ cfg( all( target_os = "android" , target_pointer_width = "32" ) ) ]
349+ pub fn write_vectored_at ( & self , bufs : & [ IoSlice < ' _ > ] , offset : u64 ) -> io:: Result < usize > {
350+ super :: weak:: weak!( fn pwritev64( libc:: c_int, * const libc:: iovec, libc:: c_int, off64_t) -> isize ) ;
351+
352+ match pwritev64. get ( ) {
353+ Some ( pwritev) => {
354+ let ret = cvt ( unsafe {
355+ pwritev (
356+ self . as_raw_fd ( ) ,
357+ bufs. as_ptr ( ) as * const libc:: iovec ,
358+ cmp:: min ( bufs. len ( ) , max_iov ( ) ) as libc:: c_int ,
359+ offset as _ ,
360+ )
361+ } ) ?;
362+ Ok ( ret as usize )
363+ }
364+ None => io:: default_write_vectored ( |b| self . write_at ( b, offset) , bufs) ,
365+ }
366+ }
367+
276368 #[ cfg( not( any(
277369 target_env = "newlib" ,
278370 target_os = "solaris" ,
0 commit comments