Skip to content
15 changes: 7 additions & 8 deletions library/std/src/io/copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::cmp;
use crate::collections::VecDeque;
use crate::io::IoSlice;
use crate::mem::MaybeUninit;
use crate::sys::io::{CopyState, kernel_copy};

#[cfg(test)]
mod tests;
Expand Down Expand Up @@ -63,19 +64,17 @@ where
R: Read,
W: Write,
{
cfg_select! {
any(target_os = "linux", target_os = "android") => {
crate::sys::kernel_copy::copy_spec(reader, writer)
}
_ => {
generic_copy(reader, writer)
match kernel_copy(reader, writer)? {
CopyState::Ended(copied) => Ok(copied),
CopyState::Fallback(copied) => {
generic_copy(reader, writer).map(|additional| copied + additional)
}
}
}

/// The userspace read-write-loop implementation of `io::copy` that is used when
/// OS-specific specializations for copy offloading are not available or not applicable.
pub(crate) fn generic_copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> Result<u64>
fn generic_copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> Result<u64>
where
R: Read,
W: Write,
Expand Down Expand Up @@ -269,7 +268,7 @@ impl BufferedWriterSpec for Vec<u8> {
}
}

pub fn stack_buffer_copy<R: Read + ?Sized, W: Write + ?Sized>(
fn stack_buffer_copy<R: Read + ?Sized, W: Write + ?Sized>(
reader: &mut R,
writer: &mut W,
) -> Result<u64> {
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ cfg_select! {
pub use unix::chroot;
pub(crate) use unix::debug_assert_fd_is_open;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub(crate) use unix::CachedFileMetadata;
pub(super) use unix::CachedFileMetadata;
use crate::sys::common::small_c_string::run_path_with_cstr as with_native_path;
}
target_os = "windows" => {
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/fs/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2302,7 +2302,7 @@ mod cfm {
}
}
#[cfg(any(target_os = "linux", target_os = "android"))]
pub(crate) use cfm::CachedFileMetadata;
pub(in crate::sys) use cfm::CachedFileMetadata;

#[cfg(not(target_vendor = "apple"))]
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ use libc::sendfile as sendfile64;
use libc::sendfile64;
use libc::{EBADF, EINVAL, ENOSYS, EOPNOTSUPP, EOVERFLOW, EPERM, EXDEV};

use super::CopyState;
use crate::cmp::min;
use crate::fs::{File, Metadata};
use crate::io::copy::generic_copy;
use crate::io::{
BufRead, BufReader, BufWriter, Error, PipeReader, PipeWriter, Read, Result, StderrLock,
StdinLock, StdoutLock, Take, Write,
Expand All @@ -70,10 +70,10 @@ use crate::sys::weak::syscall;
#[cfg(test)]
mod tests;

pub(crate) fn copy_spec<R: Read + ?Sized, W: Write + ?Sized>(
pub fn kernel_copy<R: Read + ?Sized, W: Write + ?Sized>(
read: &mut R,
write: &mut W,
) -> Result<u64> {
) -> Result<CopyState> {
let copier = Copier { read, write };
SpecCopy::copy(copier)
}
Expand Down Expand Up @@ -176,17 +176,17 @@ struct Copier<'a, 'b, R: Read + ?Sized, W: Write + ?Sized> {
}

trait SpecCopy {
fn copy(self) -> Result<u64>;
fn copy(self) -> Result<CopyState>;
}

impl<R: Read + ?Sized, W: Write + ?Sized> SpecCopy for Copier<'_, '_, R, W> {
default fn copy(self) -> Result<u64> {
generic_copy(self.read, self.write)
default fn copy(self) -> Result<CopyState> {
Ok(CopyState::Fallback(0))
}
}

impl<R: CopyRead, W: CopyWrite> SpecCopy for Copier<'_, '_, R, W> {
fn copy(self) -> Result<u64> {
fn copy(self) -> Result<CopyState> {
let (reader, writer) = (self.read, self.write);
let r_cfg = reader.properties();
let w_cfg = writer.properties();
Expand Down Expand Up @@ -214,7 +214,9 @@ impl<R: CopyRead, W: CopyWrite> SpecCopy for Copier<'_, '_, R, W> {
result.update_take(reader);

match result {
CopyResult::Ended(bytes_copied) => return Ok(bytes_copied + written),
CopyResult::Ended(bytes_copied) => {
return Ok(CopyState::Ended(bytes_copied + written));
}
CopyResult::Error(e, _) => return Err(e),
CopyResult::Fallback(bytes) => written += bytes,
}
Expand All @@ -231,7 +233,9 @@ impl<R: CopyRead, W: CopyWrite> SpecCopy for Copier<'_, '_, R, W> {
result.update_take(reader);

match result {
CopyResult::Ended(bytes_copied) => return Ok(bytes_copied + written),
CopyResult::Ended(bytes_copied) => {
return Ok(CopyState::Ended(bytes_copied + written));
}
CopyResult::Error(e, _) => return Err(e),
CopyResult::Fallback(bytes) => written += bytes,
}
Expand All @@ -244,7 +248,9 @@ impl<R: CopyRead, W: CopyWrite> SpecCopy for Copier<'_, '_, R, W> {
result.update_take(reader);

match result {
CopyResult::Ended(bytes_copied) => return Ok(bytes_copied + written),
CopyResult::Ended(bytes_copied) => {
return Ok(CopyState::Ended(bytes_copied + written));
}
CopyResult::Error(e, _) => return Err(e),
CopyResult::Fallback(0) => { /* use the fallback below */ }
CopyResult::Fallback(_) => {
Expand All @@ -255,10 +261,7 @@ impl<R: CopyRead, W: CopyWrite> SpecCopy for Copier<'_, '_, R, W> {
}

// fallback if none of the more specialized syscalls wants to work with these file descriptors
match generic_copy(reader, writer) {
Ok(bytes) => Ok(bytes + written),
err => err,
}
Ok(CopyState::Fallback(written))
}
}

Expand Down Expand Up @@ -558,7 +561,7 @@ fn fd_to_meta<T: AsRawFd>(fd: &T) -> FdMeta {
}
}

pub(super) enum CopyResult {
enum CopyResult {
Ended(u64),
Error(Error, u64),
Fallback(u64),
Expand Down Expand Up @@ -587,7 +590,7 @@ const INVALID_FD: RawFd = -1;
/// Callers must handle fallback to a generic copy loop.
/// `Fallback` may indicate non-zero number of bytes already written
/// if one of the files' cursor +`max_len` would exceed u64::MAX (`EOVERFLOW`).
pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) -> CopyResult {
fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) -> CopyResult {
use crate::cmp;

const NOT_PROBED: u8 = 0;
Expand Down
23 changes: 23 additions & 0 deletions library/std/src/sys/io/kernel_copy/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
pub enum CopyState {
#[cfg_attr(not(any(target_os = "linux", target_os = "android")), expect(dead_code))]
Ended(u64),
Fallback(u64),
}

cfg_select! {
any(target_os = "linux", target_os = "android") => {
mod linux;
pub use linux::kernel_copy;
}
_ => {
use crate::io::{Result, Read, Write};

pub fn kernel_copy<R: ?Sized, W: ?Sized>(_reader: &mut R, _writer: &mut W) -> Result<CopyState>
where
R: Read,
W: Write,
{
Ok(CopyState::Fallback(0))
}
}
}
3 changes: 3 additions & 0 deletions library/std/src/sys/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,11 @@ mod is_terminal {
}
}

mod kernel_copy;

pub use io_slice::{IoSlice, IoSliceMut};
pub use is_terminal::is_terminal;
pub use kernel_copy::{CopyState, kernel_copy};

// Bare metal platforms usually have very small amounts of RAM
// (in the order of hundreds of KB)
Expand Down
2 changes: 0 additions & 2 deletions library/std/src/sys/pal/unix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ use crate::io::ErrorKind;
#[cfg(target_os = "fuchsia")]
pub mod fuchsia;
pub mod futex;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod kernel_copy;
#[cfg(target_os = "linux")]
pub mod linux;
pub mod os;
Expand Down
3 changes: 0 additions & 3 deletions src/tools/tidy/src/pal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,9 @@ const EXCEPTION_PATHS: &[&str] = &[
"library/std/src/os", // Platform-specific public interfaces
// Temporary `std` exceptions
// FIXME: platform-specific code should be moved to `sys`
"library/std/src/io/copy.rs",
"library/std/src/io/stdio.rs",
"library/std/src/lib.rs", // for miniz_oxide leaking docs, which itself workaround
"library/std/src/path.rs",
"library/std/src/sys_common", // Should only contain abstractions over platforms
"library/std/src/net/test.rs", // Utility helpers for tests
"library/std/src/io/error.rs", // Repr unpacked needed for UEFI
];

Expand Down