about summary refs log tree commit diff
path: root/library/std/src/sys
diff options
context:
space:
mode:
authorBenoît du Garreau <bdgdlm@outlook.com>2023-03-02 11:12:24 +0100
committerBenoît du Garreau <bdgdlm@outlook.com>2023-03-02 11:12:24 +0100
commit2fc23c2dfe664850231f1691ef56cde6e467aa6a (patch)
tree78918a2b88e9eb61231314aa60810e0c891dc31c /library/std/src/sys
parent351c154cb44d90b1db7e3c62aa6500e0fb472969 (diff)
downloadrust-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.rs100
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",