about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
authorBenoît du Garreau <bdgdlm@outlook.com>2021-10-04 12:55:50 +0200
committerBenoît du Garreau <bdgdlm@outlook.com>2023-02-27 10:10:13 +0100
commit351c154cb44d90b1db7e3c62aa6500e0fb472969 (patch)
tree3c90e95ae8f594fe61db7ee324eae1d05fcd4a67 /library/std/src
parent58136ffa92c81ec9e6ac1f91773254914da2ca01 (diff)
downloadrust-351c154cb44d90b1db7e3c62aa6500e0fb472969.tar.gz
rust-351c154cb44d90b1db7e3c62aa6500e0fb472969.zip
Add vectored positioned I/O on Unix
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/os/unix/fs.rs34
-rw-r--r--library/std/src/sys/unix/fd.rs82
-rw-r--r--library/std/src/sys/unix/fs.rs8
3 files changed, 121 insertions, 3 deletions
diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs
index 3fc6cc44ce4..edd77c824ad 100644
--- a/library/std/src/os/unix/fs.rs
+++ b/library/std/src/os/unix/fs.rs
@@ -54,6 +54,20 @@ pub trait FileExt {
     #[stable(feature = "file_offset", since = "1.15.0")]
     fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
 
+    /// Like `read_at`, except that it reads into a slice of buffers.
+    ///
+    /// Data is copied to fill each buffer in order, with the final buffer
+    /// written to possibly being only partially filled. This method must behave
+    /// equivalently to a single call to read with concatenated buffers.
+    #[unstable(feature = "unix_file_vectored_at", issue = "89517")]
+    fn read_vectored_at(
+        &mut self,
+        bufs: &mut [io::IoSliceMut<'_>],
+        offset: u64,
+    ) -> io::Result<usize> {
+        io::default_read_vectored(|b| self.read_at(b, offset), bufs)
+    }
+
     /// Reads the exact number of byte required to fill `buf` from the given offset.
     ///
     /// The offset is relative to the start of the file and thus independent
@@ -155,6 +169,16 @@ pub trait FileExt {
     #[stable(feature = "file_offset", since = "1.15.0")]
     fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
 
+    /// Like `write_at`, except that it writes from a slice of buffers.
+    ///
+    /// Data is copied from each buffer in order, with the final buffer read
+    /// from possibly being only partially consumed. This method must behave as
+    /// a call to `write_at` with the buffers concatenated would.
+    #[unstable(feature = "unix_file_vectored_at", issue = "89517")]
+    fn write_vectored_at(&mut self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result<usize> {
+        io::default_write_vectored(|b| self.write_at(b, offset), bufs)
+    }
+
     /// Attempts to write an entire buffer starting from a given offset.
     ///
     /// The offset is relative to the start of the file and thus independent
@@ -218,9 +242,19 @@ impl FileExt for fs::File {
     fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
         self.as_inner().read_at(buf, offset)
     }
+    fn read_vectored_at(
+        &mut self,
+        bufs: &mut [io::IoSliceMut<'_>],
+        offset: u64,
+    ) -> io::Result<usize> {
+        self.as_inner().read_vectored_at(bufs, offset)
+    }
     fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
         self.as_inner().write_at(buf, offset)
     }
+    fn write_vectored_at(&mut self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result<usize> {
+        self.as_inner().write_vectored_at(bufs, offset)
+    }
 }
 
 /// Unix-specific extensions to [`fs::Permissions`].
diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs
index 66c33d58d6c..3213f4bf2a0 100644
--- a/library/std/src/sys/unix/fd.rs
+++ b/library/std/src/sys/unix/fd.rs
@@ -92,7 +92,7 @@ impl FileDesc {
         let ret = cvt(unsafe {
             libc::readv(
                 self.as_raw_fd(),
-                bufs.as_ptr() as *const libc::iovec,
+                bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec,
                 cmp::min(bufs.len(), max_iov()) as libc::c_int,
             )
         })?;
@@ -101,7 +101,7 @@ impl FileDesc {
 
     #[cfg(any(target_os = "espidf", target_os = "horizon"))]
     pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        return crate::io::default_read_vectored(|b| self.read(b), bufs);
+        io::default_read_vectored(|b| self.read(b), bufs)
     }
 
     #[inline]
@@ -147,6 +147,44 @@ impl FileDesc {
         Ok(())
     }
 
+    #[cfg(any(
+        target_os = "android",
+        target_os = "emscripten",
+        target_os = "freebsd",
+        target_os = "fuchsia",
+        target_os = "illumos",
+        target_os = "ios",
+        target_os = "linux",
+        target_os = "macos",
+        target_os = "netbsd",
+    ))]
+    pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+        let ret = cvt(unsafe {
+            libc::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(not(any(
+        target_os = "android",
+        target_os = "emscripten",
+        target_os = "freebsd",
+        target_os = "fuchsia",
+        target_os = "illumos",
+        target_os = "ios",
+        target_os = "linux",
+        target_os = "macos",
+        target_os = "netbsd",
+    )))]
+    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)
+    }
+
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         let ret = cvt(unsafe {
             libc::write(
@@ -172,7 +210,7 @@ impl FileDesc {
 
     #[cfg(any(target_os = "espidf", target_os = "horizon"))]
     pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        return crate::io::default_write_vectored(|b| self.write(b), bufs);
+        io::default_write_vectored(|b| self.write(b), bufs)
     }
 
     #[inline]
@@ -197,6 +235,44 @@ impl FileDesc {
         }
     }
 
+    #[cfg(any(
+        target_os = "android",
+        target_os = "emscripten",
+        target_os = "freebsd",
+        target_os = "fuchsia",
+        target_os = "illumos",
+        target_os = "ios",
+        target_os = "linux",
+        target_os = "macos",
+        target_os = "netbsd",
+    ))]
+    pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
+        let ret = cvt(unsafe {
+            libc::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(not(any(
+        target_os = "android",
+        target_os = "emscripten",
+        target_os = "freebsd",
+        target_os = "fuchsia",
+        target_os = "illumos",
+        target_os = "ios",
+        target_os = "linux",
+        target_os = "macos",
+        target_os = "netbsd",
+    )))]
+    pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
+        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/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 8e1f35d6cc9..ec674801a8f 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -1098,6 +1098,10 @@ impl File {
         self.0.read_buf(cursor)
     }
 
+    pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+        self.0.read_vectored_at(bufs, offset)
+    }
+
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         self.0.write(buf)
     }
@@ -1115,6 +1119,10 @@ impl File {
         self.0.write_at(buf, offset)
     }
 
+    pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
+        self.0.write_vectored_at(bufs, offset)
+    }
+
     pub fn flush(&self) -> io::Result<()> {
         Ok(())
     }