Skip to content

Commit

Permalink
Add vectored positioned I/O on Unix
Browse files Browse the repository at this point in the history
  • Loading branch information
a1phyr committed Oct 4, 2021
1 parent d25de31 commit a1061d7
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 0 deletions.
34 changes: 34 additions & 0 deletions library/std/src/os/unix/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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`].
Expand Down
36 changes: 36 additions & 0 deletions library/std/src/sys/unix/fd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,24 @@ impl FileDesc {
}
}

#[cfg(not(target_os = "espidf"))]
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_ptr() as *const libc::iovec,
cmp::min(bufs.len(), max_iov()) as c_int,
offset as i64,
)
})?;
Ok(ret as usize)
}

#[cfg(target_os = "espidf")]
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
return crate::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(
Expand Down Expand Up @@ -189,6 +207,24 @@ impl FileDesc {
}
}

#[cfg(not(target_os = "espidf"))]
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 c_int,
offset as i64,
)
})?;
Ok(ret as usize)
}

#[cfg(target_os = "espidf")]
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
return crate::io::default_write_vectored(|b| self.write_at(b, offset), bufs);
}

#[cfg(target_os = "linux")]
pub fn get_cloexec(&self) -> io::Result<bool> {
unsafe { Ok((cvt(libc::fcntl(self.as_raw_fd(), libc::F_GETFD))? & libc::FD_CLOEXEC) != 0) }
Expand Down
8 changes: 8 additions & 0 deletions library/std/src/sys/unix/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,10 @@ impl File {
self.0.read_at(buf, offset)
}

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)
}
Expand All @@ -881,6 +885,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(())
}
Expand Down

0 comments on commit a1061d7

Please sign in to comment.