Skip to content

Commit 2fc23c2

Browse files
committed
Use weak linkage on Android
1 parent 351c154 commit 2fc23c2

File tree

1 file changed

+96
-4
lines changed
  • library/std/src/sys/unix

1 file changed

+96
-4
lines changed

library/std/src/sys/unix/fd.rs

+96-4
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,6 @@ impl FileDesc {
148148
}
149149

150150
#[cfg(any(
151-
target_os = "android",
152151
target_os = "emscripten",
153152
target_os = "freebsd",
154153
target_os = "fuchsia",
@@ -171,7 +170,6 @@ impl FileDesc {
171170
}
172171

173172
#[cfg(not(any(
174-
target_os = "android",
175173
target_os = "emscripten",
176174
target_os = "freebsd",
177175
target_os = "fuchsia",
@@ -185,6 +183,54 @@ impl FileDesc {
185183
io::default_read_vectored(|b| self.read_at(b, offset), bufs)
186184
}
187185

186+
// We support some old Android versions that do not have `preadv` in libc,
187+
// so we use weak linkage and fallback to a direct syscall if not available.
188+
//
189+
// On 32-bit targets, we don't want to deal with weird ABI issues around
190+
// passing 64-bits parameters to syscalls, so we fallback to the default
191+
// implementation.
192+
#[cfg(all(target_os = "android", target_pointer_width = "64"))]
193+
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
194+
super::weak::syscall! {
195+
fn preadv(
196+
fd: libc::c_int,
197+
iovec: *const libc::iovec,
198+
n_iovec: libc::c_int,
199+
offset: off64_t
200+
) -> isize
201+
}
202+
203+
let ret = cvt(unsafe {
204+
preadv(
205+
self.as_raw_fd(),
206+
bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec,
207+
cmp::min(bufs.len(), max_iov()) as libc::c_int,
208+
offset as _,
209+
)
210+
})?;
211+
Ok(ret as usize)
212+
}
213+
214+
#[cfg(all(target_os = "android", target_pointer_width = "32"))]
215+
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
216+
super::weak::weak!(fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
217+
218+
match preadv64.get() {
219+
Some(preadv) => {
220+
let ret = cvt(unsafe {
221+
preadv(
222+
self.as_raw_fd(),
223+
bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec,
224+
cmp::min(bufs.len(), max_iov()) as libc::c_int,
225+
offset as _,
226+
)
227+
})?;
228+
Ok(ret as usize)
229+
}
230+
None => io::default_read_vectored(|b| self.read_at(b, offset), bufs),
231+
}
232+
}
233+
188234
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
189235
let ret = cvt(unsafe {
190236
libc::write(
@@ -236,7 +282,6 @@ impl FileDesc {
236282
}
237283

238284
#[cfg(any(
239-
target_os = "android",
240285
target_os = "emscripten",
241286
target_os = "freebsd",
242287
target_os = "fuchsia",
@@ -259,7 +304,6 @@ impl FileDesc {
259304
}
260305

261306
#[cfg(not(any(
262-
target_os = "android",
263307
target_os = "emscripten",
264308
target_os = "freebsd",
265309
target_os = "fuchsia",
@@ -273,6 +317,54 @@ impl FileDesc {
273317
io::default_write_vectored(|b| self.write_at(b, offset), bufs)
274318
}
275319

320+
// We support some old Android versions that do not have `pwritev` in libc,
321+
// so we use weak linkage and fallback to a direct syscall if not available.
322+
//
323+
// On 32-bit targets, we don't want to deal with weird ABI issues around
324+
// passing 64-bits parameters to syscalls, so we fallback to the default
325+
// implementation.
326+
#[cfg(all(target_os = "android", target_pointer_width = "64"))]
327+
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
328+
super::weak::syscall! {
329+
fn pwritev(
330+
fd: libc::c_int,
331+
iovec: *const libc::iovec,
332+
n_iovec: libc::c_int,
333+
offset: off64_t
334+
) -> isize
335+
}
336+
337+
let ret = cvt(unsafe {
338+
pwritev(
339+
self.as_raw_fd(),
340+
bufs.as_ptr() as *const libc::iovec,
341+
cmp::min(bufs.len(), max_iov()) as libc::c_int,
342+
offset as _,
343+
)
344+
})?;
345+
Ok(ret as usize)
346+
}
347+
348+
#[cfg(all(target_os = "android", target_pointer_width = "32"))]
349+
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
350+
super::weak::weak!(fn pwritev64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
351+
352+
match pwritev64.get() {
353+
Some(pwritev) => {
354+
let ret = cvt(unsafe {
355+
pwritev(
356+
self.as_raw_fd(),
357+
bufs.as_ptr() as *const libc::iovec,
358+
cmp::min(bufs.len(), max_iov()) as libc::c_int,
359+
offset as _,
360+
)
361+
})?;
362+
Ok(ret as usize)
363+
}
364+
None => io::default_write_vectored(|b| self.write_at(b, offset), bufs),
365+
}
366+
}
367+
276368
#[cfg(not(any(
277369
target_env = "newlib",
278370
target_os = "solaris",

0 commit comments

Comments
 (0)