Skip to content

Commit f352f0e

Browse files
committed
Dynamically detect presence of p{read,write}64 on Android
1 parent b3f2644 commit f352f0e

File tree

2 files changed

+68
-23
lines changed

2 files changed

+68
-23
lines changed

src/libstd/sys/unix/android.rs

+35-6
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@
2828
2929
#![cfg(target_os = "android")]
3030

31-
use libc::{c_int, sighandler_t};
31+
use libc::{c_int, c_void, sighandler_t, size_t, ssize_t};
32+
use libc::{ftruncate, pread, pwrite};
3233

3334
use io;
34-
use sys::cvt_r;
35+
use super::{cvt, cvt_r};
3536

3637
// The `log2` and `log2f` functions apparently appeared in android-18, or at
3738
// least you can see they're not present in the android-17 header [1] and they
@@ -99,10 +100,6 @@ pub unsafe fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t {
99100
pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> {
100101
weak!(fn ftruncate64(c_int, i64) -> c_int);
101102

102-
extern {
103-
fn ftruncate(fd: c_int, off: i32) -> c_int;
104-
}
105-
106103
unsafe {
107104
match ftruncate64.get() {
108105
Some(f) => cvt_r(|| f(fd, size as i64)).map(|_| ()),
@@ -117,3 +114,35 @@ pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> {
117114
}
118115
}
119116
}
117+
118+
pub unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: size_t, offset: i64)
119+
-> io::Result<ssize_t>
120+
{
121+
weak!(fn pread64(c_int, *mut c_void, size_t, i64) -> ssize_t);
122+
unsafe {
123+
pread64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| {
124+
if offset as u64 > i32::max_value() as u64 {
125+
Err(io::Error::new(io::Error::InvalidInput,
126+
"cannot pread >2GB"))
127+
} else {
128+
cvt(pread(fd, buf, count, offset as i32))
129+
}
130+
})
131+
}
132+
}
133+
134+
pub unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: size_t, offset: i64)
135+
-> io::Result<ssize_t>
136+
{
137+
weak!(fn pwrite64(c_int, *const c_void, size_t, i64) -> ssize_t);
138+
unsafe {
139+
pwrite64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| {
140+
if offset as u64 > i32::max_value() as u64 {
141+
Err(io::Error::new(io::Error::InvalidInput,
142+
"cannot pwrite >2GB"))
143+
} else {
144+
cvt(pwrite(fd, buf, count, offset as i32))
145+
}
146+
})
147+
}
148+
}

src/libstd/sys/unix/fd.rs

+33-17
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,26 @@ use sys::cvt;
1818
use sys_common::AsInner;
1919
use sys_common::io::read_to_end_uninitialized;
2020

21-
#[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))]
22-
use libc::{pread64, pwrite64, off64_t};
21+
#[cfg(target_os = "android")]
22+
use super::android::{cvt_pread64, cvt_pwrite64};
23+
#[cfg(any(target_os = "linux", target_os = "emscripten"))]
24+
use libc::{pread64, pwrite64, off64_t, ssize_t};
2325
#[cfg(not(any(target_os = "linux", target_os = "emscripten", target_os = "android")))]
24-
use libc::{pread as pread64, pwrite as pwrite64, off_t as off64_t};
26+
use libc::{pread as pread64, pwrite as pwrite64, off_t as off64_t, ssize_t};
27+
28+
#[cfg(not(target_os = "android"))]
29+
unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: size_t, offset: off64_t)
30+
-> io::Result<ssize_t>
31+
{
32+
cvt(pread64(fd, buf, count, offset))
33+
}
34+
35+
#[cfg(not(target_os = "android"))]
36+
unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: size_t, offset: off64_t)
37+
-> io::Result<ssize_t>
38+
{
39+
cvt(pwrite64(fd, buf, count, offset))
40+
}
2541

2642
pub struct FileDesc {
2743
fd: c_int,
@@ -56,13 +72,13 @@ impl FileDesc {
5672
}
5773

5874
pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
59-
let ret = cvt(unsafe {
60-
pread64(self.fd,
61-
buf.as_mut_ptr() as *mut c_void,
62-
buf.len(),
63-
offset as off64_t)
64-
})?;
65-
Ok(ret as usize)
75+
unsafe {
76+
cvt_pread64(self.fd,
77+
buf.as_mut_ptr() as *mut c_void,
78+
buf.len(),
79+
offset as off64_t)
80+
.map(|n| n as usize)
81+
}
6682
}
6783

6884
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
@@ -75,13 +91,13 @@ impl FileDesc {
7591
}
7692

7793
pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
78-
let ret = cvt(unsafe {
79-
pwrite64(self.fd,
80-
buf.as_ptr() as *const c_void,
81-
buf.len(),
82-
offset as off64_t)
83-
})?;
84-
Ok(ret as usize)
94+
unsafe {
95+
cvt_pwrite64(self.fd,
96+
buf.as_ptr() as *const c_void,
97+
buf.len(),
98+
offset as off64_t)
99+
.map(|n| n as usize)
100+
}
85101
}
86102

87103
#[cfg(not(any(target_env = "newlib",

0 commit comments

Comments
 (0)