Use weak linkage on Android

This commit is contained in:
Benoît du Garreau 2023-03-02 11:12:24 +01:00
parent 351c154cb4
commit 2fc23c2dfe

View File

@ -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",