Skip to content

Commit f5fcfcf

Browse files
authored
Rollup merge of rust-lang#89518 - a1phyr:unix_file_vectored_at, r=workingjubilee
Add vectored positioned I/O on Unix Add methods for vectored I/O with an offset on `File` for `unix` under `#![feature(unix_file_vectored_at)]`. The new methods are wrappers around `preadv` and `pwritev`. Tracking issue: rust-lang#89517
2 parents fd1f1fa + 351c154 commit f5fcfcf

File tree

3 files changed

+121
-3
lines changed

3 files changed

+121
-3
lines changed

library/std/src/os/unix/fs.rs

+34
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,20 @@ pub trait FileExt {
5454
#[stable(feature = "file_offset", since = "1.15.0")]
5555
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
5656

57+
/// Like `read_at`, except that it reads into a slice of buffers.
58+
///
59+
/// Data is copied to fill each buffer in order, with the final buffer
60+
/// written to possibly being only partially filled. This method must behave
61+
/// equivalently to a single call to read with concatenated buffers.
62+
#[unstable(feature = "unix_file_vectored_at", issue = "89517")]
63+
fn read_vectored_at(
64+
&mut self,
65+
bufs: &mut [io::IoSliceMut<'_>],
66+
offset: u64,
67+
) -> io::Result<usize> {
68+
io::default_read_vectored(|b| self.read_at(b, offset), bufs)
69+
}
70+
5771
/// Reads the exact number of byte required to fill `buf` from the given offset.
5872
///
5973
/// The offset is relative to the start of the file and thus independent
@@ -155,6 +169,16 @@ pub trait FileExt {
155169
#[stable(feature = "file_offset", since = "1.15.0")]
156170
fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
157171

172+
/// Like `write_at`, except that it writes from a slice of buffers.
173+
///
174+
/// Data is copied from each buffer in order, with the final buffer read
175+
/// from possibly being only partially consumed. This method must behave as
176+
/// a call to `write_at` with the buffers concatenated would.
177+
#[unstable(feature = "unix_file_vectored_at", issue = "89517")]
178+
fn write_vectored_at(&mut self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result<usize> {
179+
io::default_write_vectored(|b| self.write_at(b, offset), bufs)
180+
}
181+
158182
/// Attempts to write an entire buffer starting from a given offset.
159183
///
160184
/// The offset is relative to the start of the file and thus independent
@@ -218,9 +242,19 @@ impl FileExt for fs::File {
218242
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
219243
self.as_inner().read_at(buf, offset)
220244
}
245+
fn read_vectored_at(
246+
&mut self,
247+
bufs: &mut [io::IoSliceMut<'_>],
248+
offset: u64,
249+
) -> io::Result<usize> {
250+
self.as_inner().read_vectored_at(bufs, offset)
251+
}
221252
fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
222253
self.as_inner().write_at(buf, offset)
223254
}
255+
fn write_vectored_at(&mut self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result<usize> {
256+
self.as_inner().write_vectored_at(bufs, offset)
257+
}
224258
}
225259

226260
/// Unix-specific extensions to [`fs::Permissions`].

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

+79-3
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ impl FileDesc {
9292
let ret = cvt(unsafe {
9393
libc::readv(
9494
self.as_raw_fd(),
95-
bufs.as_ptr() as *const libc::iovec,
95+
bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec,
9696
cmp::min(bufs.len(), max_iov()) as libc::c_int,
9797
)
9898
})?;
@@ -101,7 +101,7 @@ impl FileDesc {
101101

102102
#[cfg(any(target_os = "espidf", target_os = "horizon"))]
103103
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
104-
return crate::io::default_read_vectored(|b| self.read(b), bufs);
104+
io::default_read_vectored(|b| self.read(b), bufs)
105105
}
106106

107107
#[inline]
@@ -147,6 +147,44 @@ impl FileDesc {
147147
Ok(())
148148
}
149149

150+
#[cfg(any(
151+
target_os = "android",
152+
target_os = "emscripten",
153+
target_os = "freebsd",
154+
target_os = "fuchsia",
155+
target_os = "illumos",
156+
target_os = "ios",
157+
target_os = "linux",
158+
target_os = "macos",
159+
target_os = "netbsd",
160+
))]
161+
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
162+
let ret = cvt(unsafe {
163+
libc::preadv(
164+
self.as_raw_fd(),
165+
bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec,
166+
cmp::min(bufs.len(), max_iov()) as libc::c_int,
167+
offset as _,
168+
)
169+
})?;
170+
Ok(ret as usize)
171+
}
172+
173+
#[cfg(not(any(
174+
target_os = "android",
175+
target_os = "emscripten",
176+
target_os = "freebsd",
177+
target_os = "fuchsia",
178+
target_os = "illumos",
179+
target_os = "ios",
180+
target_os = "linux",
181+
target_os = "macos",
182+
target_os = "netbsd",
183+
)))]
184+
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
185+
io::default_read_vectored(|b| self.read_at(b, offset), bufs)
186+
}
187+
150188
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
151189
let ret = cvt(unsafe {
152190
libc::write(
@@ -172,7 +210,7 @@ impl FileDesc {
172210

173211
#[cfg(any(target_os = "espidf", target_os = "horizon"))]
174212
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
175-
return crate::io::default_write_vectored(|b| self.write(b), bufs);
213+
io::default_write_vectored(|b| self.write(b), bufs)
176214
}
177215

178216
#[inline]
@@ -197,6 +235,44 @@ impl FileDesc {
197235
}
198236
}
199237

238+
#[cfg(any(
239+
target_os = "android",
240+
target_os = "emscripten",
241+
target_os = "freebsd",
242+
target_os = "fuchsia",
243+
target_os = "illumos",
244+
target_os = "ios",
245+
target_os = "linux",
246+
target_os = "macos",
247+
target_os = "netbsd",
248+
))]
249+
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
250+
let ret = cvt(unsafe {
251+
libc::pwritev(
252+
self.as_raw_fd(),
253+
bufs.as_ptr() as *const libc::iovec,
254+
cmp::min(bufs.len(), max_iov()) as libc::c_int,
255+
offset as _,
256+
)
257+
})?;
258+
Ok(ret as usize)
259+
}
260+
261+
#[cfg(not(any(
262+
target_os = "android",
263+
target_os = "emscripten",
264+
target_os = "freebsd",
265+
target_os = "fuchsia",
266+
target_os = "illumos",
267+
target_os = "ios",
268+
target_os = "linux",
269+
target_os = "macos",
270+
target_os = "netbsd",
271+
)))]
272+
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
273+
io::default_write_vectored(|b| self.write_at(b, offset), bufs)
274+
}
275+
200276
#[cfg(not(any(
201277
target_env = "newlib",
202278
target_os = "solaris",

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

+8
Original file line numberDiff line numberDiff line change
@@ -1098,6 +1098,10 @@ impl File {
10981098
self.0.read_buf(cursor)
10991099
}
11001100

1101+
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
1102+
self.0.read_vectored_at(bufs, offset)
1103+
}
1104+
11011105
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
11021106
self.0.write(buf)
11031107
}
@@ -1115,6 +1119,10 @@ impl File {
11151119
self.0.write_at(buf, offset)
11161120
}
11171121

1122+
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
1123+
self.0.write_vectored_at(bufs, offset)
1124+
}
1125+
11181126
pub fn flush(&self) -> io::Result<()> {
11191127
Ok(())
11201128
}

0 commit comments

Comments
 (0)