about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorTobias Bucher <tobiasbucher5991@gmail.com>2016-10-08 14:32:57 +0200
committerTobias Bucher <tobiasbucher5991@gmail.com>2016-10-09 10:48:07 +0200
commitf352f0eec010ff2814ca27ac0e5a84cd533f2918 (patch)
tree958c4e7aa408fbed0f53e76cd066fad8d1974a71 /src/libstd
parentb3f2644b66647d47338051d783cae8e661312472 (diff)
downloadrust-f352f0eec010ff2814ca27ac0e5a84cd533f2918.tar.gz
rust-f352f0eec010ff2814ca27ac0e5a84cd533f2918.zip
Dynamically detect presence of `p{read,write}64` on Android
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/sys/unix/android.rs41
-rw-r--r--src/libstd/sys/unix/fd.rs50
2 files changed, 68 insertions, 23 deletions
diff --git a/src/libstd/sys/unix/android.rs b/src/libstd/sys/unix/android.rs
index abbe3fc1846..08e6b45dcd3 100644
--- a/src/libstd/sys/unix/android.rs
+++ b/src/libstd/sys/unix/android.rs
@@ -28,10 +28,11 @@
 
 #![cfg(target_os = "android")]
 
-use libc::{c_int, sighandler_t};
+use libc::{c_int, c_void, sighandler_t, size_t, ssize_t};
+use libc::{ftruncate, pread, pwrite};
 
 use io;
-use sys::cvt_r;
+use super::{cvt, cvt_r};
 
 // The `log2` and `log2f` functions apparently appeared in android-18, or at
 // 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 {
 pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> {
     weak!(fn ftruncate64(c_int, i64) -> c_int);
 
-    extern {
-        fn ftruncate(fd: c_int, off: i32) -> c_int;
-    }
-
     unsafe {
         match ftruncate64.get() {
             Some(f) => cvt_r(|| f(fd, size as i64)).map(|_| ()),
@@ -117,3 +114,35 @@ pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> {
         }
     }
 }
+
+pub unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: size_t, offset: i64)
+    -> io::Result<ssize_t>
+{
+    weak!(fn pread64(c_int, *mut c_void, size_t, i64) -> ssize_t);
+    unsafe {
+        pread64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| {
+            if offset as u64 > i32::max_value() as u64 {
+                Err(io::Error::new(io::Error::InvalidInput,
+                                   "cannot pread >2GB"))
+            } else {
+                cvt(pread(fd, buf, count, offset as i32))
+            }
+        })
+    }
+}
+
+pub unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: size_t, offset: i64)
+    -> io::Result<ssize_t>
+{
+    weak!(fn pwrite64(c_int, *const c_void, size_t, i64) -> ssize_t);
+    unsafe {
+        pwrite64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| {
+            if offset as u64 > i32::max_value() as u64 {
+                Err(io::Error::new(io::Error::InvalidInput,
+                                   "cannot pwrite >2GB"))
+            } else {
+                cvt(pwrite(fd, buf, count, offset as i32))
+            }
+        })
+    }
+}
diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs
index 4f92c3274d2..30573d695aa 100644
--- a/src/libstd/sys/unix/fd.rs
+++ b/src/libstd/sys/unix/fd.rs
@@ -18,10 +18,26 @@ use sys::cvt;
 use sys_common::AsInner;
 use sys_common::io::read_to_end_uninitialized;
 
-#[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))]
-use libc::{pread64, pwrite64, off64_t};
+#[cfg(target_os = "android")]
+use super::android::{cvt_pread64, cvt_pwrite64};
+#[cfg(any(target_os = "linux", target_os = "emscripten"))]
+use libc::{pread64, pwrite64, off64_t, ssize_t};
 #[cfg(not(any(target_os = "linux", target_os = "emscripten", target_os = "android")))]
-use libc::{pread as pread64, pwrite as pwrite64, off_t as off64_t};
+use libc::{pread as pread64, pwrite as pwrite64, off_t as off64_t, ssize_t};
+
+#[cfg(not(target_os = "android"))]
+unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: size_t, offset: off64_t)
+    -> io::Result<ssize_t>
+{
+    cvt(pread64(fd, buf, count, offset))
+}
+
+#[cfg(not(target_os = "android"))]
+unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: size_t, offset: off64_t)
+    -> io::Result<ssize_t>
+{
+    cvt(pwrite64(fd, buf, count, offset))
+}
 
 pub struct FileDesc {
     fd: c_int,
@@ -56,13 +72,13 @@ impl FileDesc {
     }
 
     pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
-        let ret = cvt(unsafe {
-            pread64(self.fd,
-                    buf.as_mut_ptr() as *mut c_void,
-                    buf.len(),
-                    offset as off64_t)
-        })?;
-        Ok(ret as usize)
+        unsafe {
+            cvt_pread64(self.fd,
+                        buf.as_mut_ptr() as *mut c_void,
+                        buf.len(),
+                        offset as off64_t)
+                .map(|n| n as usize)
+        }
     }
 
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
@@ -75,13 +91,13 @@ impl FileDesc {
     }
 
     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
-        let ret = cvt(unsafe {
-            pwrite64(self.fd,
-                     buf.as_ptr() as *const c_void,
-                     buf.len(),
-                     offset as off64_t)
-        })?;
-        Ok(ret as usize)
+        unsafe {
+            cvt_pwrite64(self.fd,
+                         buf.as_ptr() as *const c_void,
+                         buf.len(),
+                         offset as off64_t)
+                .map(|n| n as usize)
+        }
     }
 
     #[cfg(not(any(target_env = "newlib",