@@ -98,7 +98,7 @@ impl FileDesc {
9898 let ret = cvt ( unsafe {
9999 libc:: readv (
100100 self . as_raw_fd ( ) ,
101- bufs. as_ptr ( ) as * const libc:: iovec ,
101+ bufs. as_mut_ptr ( ) as * mut libc :: iovec as * const libc:: iovec ,
102102 cmp:: min ( bufs. len ( ) , max_iov ( ) ) as libc:: c_int ,
103103 )
104104 } ) ?;
@@ -107,7 +107,7 @@ impl FileDesc {
107107
108108 #[ cfg( any( target_os = "espidf" , target_os = "horizon" ) ) ]
109109 pub fn read_vectored ( & self , bufs : & mut [ IoSliceMut < ' _ > ] ) -> io:: Result < usize > {
110- return crate :: io:: default_read_vectored ( |b| self . read ( b) , bufs) ;
110+ io:: default_read_vectored ( |b| self . read ( b) , bufs)
111111 }
112112
113113 #[ inline]
@@ -153,6 +153,95 @@ impl FileDesc {
153153 Ok ( ( ) )
154154 }
155155
156+ #[ cfg( any(
157+ target_os = "emscripten" ,
158+ target_os = "freebsd" ,
159+ target_os = "fuchsia" ,
160+ target_os = "illumos" ,
161+ target_os = "linux" ,
162+ target_os = "netbsd" ,
163+ ) ) ]
164+ pub fn read_vectored_at ( & self , bufs : & mut [ IoSliceMut < ' _ > ] , offset : u64 ) -> io:: Result < usize > {
165+ let ret = cvt ( unsafe {
166+ libc:: preadv (
167+ self . as_raw_fd ( ) ,
168+ bufs. as_mut_ptr ( ) as * mut libc:: iovec as * const libc:: iovec ,
169+ cmp:: min ( bufs. len ( ) , max_iov ( ) ) as libc:: c_int ,
170+ offset as _ ,
171+ )
172+ } ) ?;
173+ Ok ( ret as usize )
174+ }
175+
176+ #[ cfg( not( any(
177+ target_os = "android" ,
178+ target_os = "emscripten" ,
179+ target_os = "freebsd" ,
180+ target_os = "fuchsia" ,
181+ target_os = "illumos" ,
182+ target_os = "ios" ,
183+ target_os = "linux" ,
184+ target_os = "macos" ,
185+ target_os = "netbsd" ,
186+ ) ) ) ]
187+ pub fn read_vectored_at ( & self , bufs : & mut [ IoSliceMut < ' _ > ] , offset : u64 ) -> io:: Result < usize > {
188+ io:: default_read_vectored ( |b| self . read_at ( b, offset) , bufs)
189+ }
190+
191+ // We support some old Android versions that do not have `preadv` in libc,
192+ // so we use weak linkage and fallback to a direct syscall if not available.
193+ //
194+ // On 32-bit targets, we don't want to deal with weird ABI issues around
195+ // passing 64-bits parameters to syscalls, so we fallback to the default
196+ // implementation if `preadv` is not available.
197+ #[ cfg( all( target_os = "android" , target_pointer_width = "64" ) ) ]
198+ pub fn read_vectored_at ( & self , bufs : & mut [ IoSliceMut < ' _ > ] , offset : u64 ) -> io:: Result < usize > {
199+ super :: weak:: syscall! {
200+ fn preadv(
201+ fd: libc:: c_int,
202+ iovec: * const libc:: iovec,
203+ n_iovec: libc:: c_int,
204+ offset: off64_t
205+ ) -> isize
206+ }
207+
208+ let ret = cvt ( unsafe {
209+ preadv (
210+ self . as_raw_fd ( ) ,
211+ bufs. as_mut_ptr ( ) as * mut libc:: iovec as * const libc:: iovec ,
212+ cmp:: min ( bufs. len ( ) , max_iov ( ) ) as libc:: c_int ,
213+ offset as _ ,
214+ )
215+ } ) ?;
216+ Ok ( ret as usize )
217+ }
218+
219+ // We support old MacOS and iOS versions that do not have `preadv`. There is
220+ // no `syscall` possible in these platform.
221+ #[ cfg( any(
222+ all( target_os = "android" , target_pointer_width = "32" ) ,
223+ target_os = "ios" ,
224+ target_os = "macos" ,
225+ ) ) ]
226+ pub fn read_vectored_at ( & self , bufs : & mut [ IoSliceMut < ' _ > ] , offset : u64 ) -> io:: Result < usize > {
227+ super :: weak:: weak!( fn preadv64( libc:: c_int, * const libc:: iovec, libc:: c_int, off64_t) -> isize ) ;
228+
229+ match preadv64. get ( ) {
230+ Some ( preadv) => {
231+ let ret = cvt ( unsafe {
232+ preadv (
233+ self . as_raw_fd ( ) ,
234+ bufs. as_mut_ptr ( ) as * mut libc:: iovec as * const libc:: iovec ,
235+ cmp:: min ( bufs. len ( ) , max_iov ( ) ) as libc:: c_int ,
236+ offset as _ ,
237+ )
238+ } ) ?;
239+ Ok ( ret as usize )
240+ }
241+ None => io:: default_read_vectored ( |b| self . read_at ( b, offset) , bufs) ,
242+ }
243+ }
244+
156245 pub fn write ( & self , buf : & [ u8 ] ) -> io:: Result < usize > {
157246 let ret = cvt ( unsafe {
158247 libc:: write (
@@ -178,7 +267,7 @@ impl FileDesc {
178267
179268 #[ cfg( any( target_os = "espidf" , target_os = "horizon" ) ) ]
180269 pub fn write_vectored ( & self , bufs : & [ IoSlice < ' _ > ] ) -> io:: Result < usize > {
181- return crate :: io:: default_write_vectored ( |b| self . write ( b) , bufs) ;
270+ io:: default_write_vectored ( |b| self . write ( b) , bufs)
182271 }
183272
184273 #[ inline]
@@ -203,6 +292,95 @@ impl FileDesc {
203292 }
204293 }
205294
295+ #[ cfg( any(
296+ target_os = "emscripten" ,
297+ target_os = "freebsd" ,
298+ target_os = "fuchsia" ,
299+ target_os = "illumos" ,
300+ target_os = "linux" ,
301+ target_os = "netbsd" ,
302+ ) ) ]
303+ pub fn write_vectored_at ( & self , bufs : & [ IoSlice < ' _ > ] , offset : u64 ) -> io:: Result < usize > {
304+ let ret = cvt ( unsafe {
305+ libc:: pwritev (
306+ self . as_raw_fd ( ) ,
307+ bufs. as_ptr ( ) as * const libc:: iovec ,
308+ cmp:: min ( bufs. len ( ) , max_iov ( ) ) as libc:: c_int ,
309+ offset as _ ,
310+ )
311+ } ) ?;
312+ Ok ( ret as usize )
313+ }
314+
315+ #[ cfg( not( any(
316+ target_os = "android" ,
317+ target_os = "emscripten" ,
318+ target_os = "freebsd" ,
319+ target_os = "fuchsia" ,
320+ target_os = "illumos" ,
321+ target_os = "ios" ,
322+ target_os = "linux" ,
323+ target_os = "macos" ,
324+ target_os = "netbsd" ,
325+ ) ) ) ]
326+ pub fn write_vectored_at ( & self , bufs : & [ IoSlice < ' _ > ] , offset : u64 ) -> io:: Result < usize > {
327+ io:: default_write_vectored ( |b| self . write_at ( b, offset) , bufs)
328+ }
329+
330+ // We support some old Android versions that do not have `pwritev` in libc,
331+ // so we use weak linkage and fallback to a direct syscall if not available.
332+ //
333+ // On 32-bit targets, we don't want to deal with weird ABI issues around
334+ // passing 64-bits parameters to syscalls, so we fallback to the default
335+ // implementation if `pwritev` is not available.
336+ #[ cfg( all( target_os = "android" , target_pointer_width = "64" ) ) ]
337+ pub fn write_vectored_at ( & self , bufs : & [ IoSlice < ' _ > ] , offset : u64 ) -> io:: Result < usize > {
338+ super :: weak:: syscall! {
339+ fn pwritev(
340+ fd: libc:: c_int,
341+ iovec: * const libc:: iovec,
342+ n_iovec: libc:: c_int,
343+ offset: off64_t
344+ ) -> isize
345+ }
346+
347+ let ret = cvt ( unsafe {
348+ pwritev (
349+ self . as_raw_fd ( ) ,
350+ bufs. as_ptr ( ) as * const libc:: iovec ,
351+ cmp:: min ( bufs. len ( ) , max_iov ( ) ) as libc:: c_int ,
352+ offset as _ ,
353+ )
354+ } ) ?;
355+ Ok ( ret as usize )
356+ }
357+
358+ // We support old MacOS and iOS versions that do not have `pwritev`. There is
359+ // no `syscall` possible in these platform.
360+ #[ cfg( any(
361+ all( target_os = "android" , target_pointer_width = "32" ) ,
362+ target_os = "ios" ,
363+ target_os = "macos" ,
364+ ) ) ]
365+ pub fn write_vectored_at ( & self , bufs : & [ IoSlice < ' _ > ] , offset : u64 ) -> io:: Result < usize > {
366+ super :: weak:: weak!( fn pwritev64( libc:: c_int, * const libc:: iovec, libc:: c_int, off64_t) -> isize ) ;
367+
368+ match pwritev64. get ( ) {
369+ Some ( pwritev) => {
370+ let ret = cvt ( unsafe {
371+ pwritev (
372+ self . as_raw_fd ( ) ,
373+ bufs. as_ptr ( ) as * const libc:: iovec ,
374+ cmp:: min ( bufs. len ( ) , max_iov ( ) ) as libc:: c_int ,
375+ offset as _ ,
376+ )
377+ } ) ?;
378+ Ok ( ret as usize )
379+ }
380+ None => io:: default_write_vectored ( |b| self . write_at ( b, offset) , bufs) ,
381+ }
382+ }
383+
206384 #[ cfg( not( any(
207385 target_env = "newlib" ,
208386 target_os = "solaris" ,
0 commit comments