diff options
| author | Benoît du Garreau <bdgdlm@outlook.com> | 2023-03-02 11:12:24 +0100 |
|---|---|---|
| committer | Benoît du Garreau <bdgdlm@outlook.com> | 2023-03-02 11:12:24 +0100 |
| commit | 2fc23c2dfe664850231f1691ef56cde6e467aa6a (patch) | |
| tree | 78918a2b88e9eb61231314aa60810e0c891dc31c /library/std/src/sys | |
| parent | 351c154cb44d90b1db7e3c62aa6500e0fb472969 (diff) | |
| download | rust-2fc23c2dfe664850231f1691ef56cde6e467aa6a.tar.gz rust-2fc23c2dfe664850231f1691ef56cde6e467aa6a.zip | |
Use weak linkage on Android
Diffstat (limited to 'library/std/src/sys')
| -rw-r--r-- | library/std/src/sys/unix/fd.rs | 100 |
1 files changed, 96 insertions, 4 deletions
diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs index 3213f4bf2a0..6bfeebd9965 100644 --- a/library/std/src/sys/unix/fd.rs +++ b/library/std/src/sys/unix/fd.rs @@ -148,7 +148,6 @@ impl FileDesc { } #[cfg(any( - target_os = "android", target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", @@ -171,7 +170,6 @@ impl FileDesc { } #[cfg(not(any( - target_os = "android", target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", @@ -185,6 +183,54 @@ impl FileDesc { io::default_read_vectored(|b| self.read_at(b, offset), bufs) } + // We support some old Android versions that do not have `preadv` in libc, + // so we use weak linkage and fallback to a direct syscall if not available. + // + // On 32-bit targets, we don't want to deal with weird ABI issues around + // passing 64-bits parameters to syscalls, so we fallback to the default + // implementation. + #[cfg(all(target_os = "android", target_pointer_width = "64"))] + pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> { + super::weak::syscall! { + fn preadv( + fd: libc::c_int, + iovec: *const libc::iovec, + n_iovec: libc::c_int, + offset: off64_t + ) -> isize + } + + let ret = cvt(unsafe { + preadv( + self.as_raw_fd(), + bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec, + cmp::min(bufs.len(), max_iov()) as libc::c_int, + offset as _, + ) + })?; + Ok(ret as usize) + } + + #[cfg(all(target_os = "android", target_pointer_width = "32"))] + pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> { + super::weak::weak!(fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); + + match preadv64.get() { + Some(preadv) => { + let ret = cvt(unsafe { + preadv( + self.as_raw_fd(), + bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec, + cmp::min(bufs.len(), max_iov()) as libc::c_int, + offset as _, + ) + })?; + Ok(ret as usize) + } + None => io::default_read_vectored(|b| self.read_at(b, offset), bufs), + } + } + pub fn write(&self, buf: &[u8]) -> io::Result<usize> { let ret = cvt(unsafe { libc::write( @@ -236,7 +282,6 @@ impl FileDesc { } #[cfg(any( - target_os = "android", target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", @@ -259,7 +304,6 @@ impl FileDesc { } #[cfg(not(any( - target_os = "android", target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", @@ -273,6 +317,54 @@ impl FileDesc { io::default_write_vectored(|b| self.write_at(b, offset), bufs) } + // We support some old Android versions that do not have `pwritev` in libc, + // so we use weak linkage and fallback to a direct syscall if not available. + // + // On 32-bit targets, we don't want to deal with weird ABI issues around + // passing 64-bits parameters to syscalls, so we fallback to the default + // implementation. + #[cfg(all(target_os = "android", target_pointer_width = "64"))] + pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> { + super::weak::syscall! { + fn pwritev( + fd: libc::c_int, + iovec: *const libc::iovec, + n_iovec: libc::c_int, + offset: off64_t + ) -> isize + } + + let ret = cvt(unsafe { + pwritev( + self.as_raw_fd(), + bufs.as_ptr() as *const libc::iovec, + cmp::min(bufs.len(), max_iov()) as libc::c_int, + offset as _, + ) + })?; + Ok(ret as usize) + } + + #[cfg(all(target_os = "android", target_pointer_width = "32"))] + pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> { + super::weak::weak!(fn pwritev64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); + + match pwritev64.get() { + Some(pwritev) => { + let ret = cvt(unsafe { + pwritev( + self.as_raw_fd(), + bufs.as_ptr() as *const libc::iovec, + cmp::min(bufs.len(), max_iov()) as libc::c_int, + offset as _, + ) + })?; + Ok(ret as usize) + } + None => io::default_write_vectored(|b| self.write_at(b, offset), bufs), + } + } + #[cfg(not(any( target_env = "newlib", target_os = "solaris", |
