about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2024-04-21 13:30:25 +0200
committerGitHub <noreply@github.com>2024-04-21 13:30:25 +0200
commit9efd1477ac2fbe4beb2b062771dae30e10d44ce8 (patch)
treeebd22dad39c8edfc419a67ff4d530511291de6eb
parentf122a5129c465f76b30ce8f3c0aa533cea650f32 (diff)
parentfa53b9f39c23647ab25b416b1fa005e7dc7386ce (diff)
downloadrust-9efd1477ac2fbe4beb2b062771dae30e10d44ce8.tar.gz
rust-9efd1477ac2fbe4beb2b062771dae30e10d44ce8.zip
Rollup merge of #124089 - simlay:fix-preadv64-and-pwritev64-link-for-watchos-and-visionos, r=workingjubilee
Fix watchOS and visionOS for pread64 and pwrite64 calls

In #122880, links to `preadv64` and `pwritev64` were added for `watchOS` however the underlying [`weak!` macro did not include `target_os = "watchos"`](https://github.com/rust-lang/rust/blob/c45dee5efd0c042e9d1e24559ebd0d6424d8aa70/library/std/src/sys/pal/unix/weak.rs#L30-L74).

This resulted in an `xcodebuild` error when targeting `watchOS`:
```
Undefined symbols for architecture arm64:
  "_preadv64", referenced from:
      __rust_extern_with_linkage_preadv64 in libliveview_native_core.a[274](std-324fdd8d31e8eaa2.std.e18cf7e8d0336778-cgu.08.rcgu.o)
  "_pwritev64", referenced from:
      __rust_extern_with_linkage_pwritev64 in libliveview_native_core.a[274](std-324fdd8d31e8eaa2.std.e18cf7e8d0336778-cgu.08.rcgu.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
```

So I added them. I also went ahead and added the same for visionOS because it's bound to create the same issue.
-rw-r--r--library/std/src/sys/pal/unix/fd.rs100
-rw-r--r--library/std/src/sys/pal/unix/weak.rs4
2 files changed, 66 insertions, 38 deletions
diff --git a/library/std/src/sys/pal/unix/fd.rs b/library/std/src/sys/pal/unix/fd.rs
index 48e83b04ef4..203c7180001 100644
--- a/library/std/src/sys/pal/unix/fd.rs
+++ b/library/std/src/sys/pal/unix/fd.rs
@@ -45,13 +45,9 @@ const READ_LIMIT: usize = libc::ssize_t::MAX as usize;
 #[cfg(any(
     target_os = "dragonfly",
     target_os = "freebsd",
-    target_os = "ios",
-    target_os = "tvos",
-    target_os = "macos",
     target_os = "netbsd",
     target_os = "openbsd",
-    target_os = "watchos",
-    target_os = "visionos",
+    target_vendor = "apple",
 ))]
 const fn max_iov() -> usize {
     libc::IOV_MAX as usize
@@ -72,17 +68,13 @@ const fn max_iov() -> usize {
     target_os = "dragonfly",
     target_os = "emscripten",
     target_os = "freebsd",
-    target_os = "ios",
-    target_os = "tvos",
     target_os = "linux",
-    target_os = "macos",
     target_os = "netbsd",
     target_os = "nto",
     target_os = "openbsd",
     target_os = "horizon",
     target_os = "vita",
-    target_os = "watchos",
-    target_os = "visionos",
+    target_vendor = "apple",
 )))]
 const fn max_iov() -> usize {
     16 // The minimum value required by POSIX.
@@ -201,13 +193,10 @@ impl FileDesc {
         target_os = "fuchsia",
         target_os = "hurd",
         target_os = "illumos",
-        target_os = "ios",
-        target_os = "tvos",
         target_os = "linux",
-        target_os = "macos",
         target_os = "netbsd",
         target_os = "openbsd",
-        target_os = "watchos",
+        target_vendor = "apple",
     )))]
     pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
         io::default_read_vectored(|b| self.read_at(b, offset), bufs)
@@ -241,15 +230,7 @@ impl FileDesc {
         Ok(ret as usize)
     }
 
-    // We support old MacOS and iOS versions that do not have `preadv`. There is
-    // no `syscall` possible in these platform.
-    #[cfg(any(
-        all(target_os = "android", target_pointer_width = "32"),
-        target_os = "ios", // ios 14.0
-        target_os = "tvos", // tvos 14.0
-        target_os = "macos", // macos 11.0
-        target_os = "watchos", // watchos 7.0
-    ))]
+    #[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);
 
@@ -269,6 +250,35 @@ impl FileDesc {
         }
     }
 
+    // We support old MacOS, iOS, watchOS, tvOS and visionOS. `preadv` was added in the following
+    // Apple OS versions:
+    // ios 14.0
+    // tvos 14.0
+    // macos 11.0
+    // watchos 7.0
+    //
+    // These versions may be newer than the minimum supported versions of OS's we support so we must
+    // use "weak" linking.
+    #[cfg(target_vendor = "apple")]
+    pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+        super::weak::weak!(fn preadv(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
+
+        match preadv.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(
@@ -360,13 +370,10 @@ impl FileDesc {
         target_os = "fuchsia",
         target_os = "hurd",
         target_os = "illumos",
-        target_os = "ios",
-        target_os = "tvos",
         target_os = "linux",
-        target_os = "macos",
         target_os = "netbsd",
         target_os = "openbsd",
-        target_os = "watchos",
+        target_vendor = "apple",
     )))]
     pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
         io::default_write_vectored(|b| self.write_at(b, offset), bufs)
@@ -400,15 +407,7 @@ impl FileDesc {
         Ok(ret as usize)
     }
 
-    // We support old MacOS and iOS versions that do not have `pwritev`. There is
-    // no `syscall` possible in these platform.
-    #[cfg(any(
-        all(target_os = "android", target_pointer_width = "32"),
-        target_os = "ios", // ios 14.0
-        target_os = "tvos", // tvos 14.0
-        target_os = "macos", // macos 11.0
-        target_os = "watchos", // watchos 7.0
-    ))]
+    #[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);
 
@@ -428,6 +427,35 @@ impl FileDesc {
         }
     }
 
+    // We support old MacOS, iOS, watchOS, tvOS and visionOS. `pwritev` was added in the following
+    // Apple OS versions:
+    // ios 14.0
+    // tvos 14.0
+    // macos 11.0
+    // watchos 7.0
+    //
+    // These versions may be newer than the minimum supported versions of OS's we support so we must
+    // use "weak" linking.
+    #[cfg(target_vendor = "apple")]
+    pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
+        super::weak::weak!(fn pwritev(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
+
+        match pwritev.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",
diff --git a/library/std/src/sys/pal/unix/weak.rs b/library/std/src/sys/pal/unix/weak.rs
index 48cc8633e93..4765a286e6b 100644
--- a/library/std/src/sys/pal/unix/weak.rs
+++ b/library/std/src/sys/pal/unix/weak.rs
@@ -28,7 +28,7 @@ use crate::ptr;
 use crate::sync::atomic::{self, AtomicPtr, Ordering};
 
 // We can use true weak linkage on ELF targets.
-#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "tvos")))]
+#[cfg(all(unix, not(target_vendor = "apple")))]
 pub(crate) macro weak {
     (fn $name:ident($($t:ty),*) -> $ret:ty) => (
         let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = {
@@ -43,7 +43,7 @@ pub(crate) macro weak {
 }
 
 // On non-ELF targets, use the dlsym approximation of weak linkage.
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos"))]
+#[cfg(target_vendor = "apple")]
 pub(crate) use self::dlsym as weak;
 
 pub(crate) struct ExternWeak<F: Copy> {