mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
uucore/buf-copy: delete redundant functions
This commit is contained in:
parent
2cdf30938d
commit
35a044b532
3 changed files with 8 additions and 213 deletions
|
@ -38,7 +38,7 @@ mod tests {
|
|||
};
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
use {nix::unistd, std::os::fd::AsRawFd};
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
use std::io::{Read, Write};
|
||||
|
||||
|
@ -53,67 +53,6 @@ mod tests {
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
#[test]
|
||||
fn test_file_is_pipe() {
|
||||
let temp_file = new_temp_file();
|
||||
let (pipe_read, pipe_write) = pipes::pipe().unwrap();
|
||||
|
||||
assert!(is_pipe(&pipe_read).unwrap());
|
||||
assert!(is_pipe(&pipe_write).unwrap());
|
||||
assert!(!is_pipe(&temp_file).unwrap());
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
#[test]
|
||||
fn test_valid_splice_errs() {
|
||||
use nix::errno::Errno;
|
||||
use nix::Error;
|
||||
|
||||
let err = Error::from(Errno::EINVAL);
|
||||
assert_eq!(maybe_unsupported(err).unwrap(), (0, true));
|
||||
|
||||
let err = Error::from(Errno::ENOSYS);
|
||||
assert_eq!(maybe_unsupported(err).unwrap(), (0, true));
|
||||
|
||||
let err = Error::from(Errno::EBADF);
|
||||
assert_eq!(maybe_unsupported(err).unwrap(), (0, true));
|
||||
|
||||
let err = Error::from(Errno::EPERM);
|
||||
assert!(maybe_unsupported(err).is_err());
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
#[test]
|
||||
fn test_splice_data_to_pipe() {
|
||||
let (pipe_read, pipe_write) = pipes::pipe().unwrap();
|
||||
let data = b"Hello, world!";
|
||||
let (bytes, _) = splice_data_to_pipe(data, &pipe_write).unwrap();
|
||||
let mut buf = [0; 1024];
|
||||
let n = unistd::read(pipe_read.as_raw_fd(), &mut buf).unwrap();
|
||||
assert_eq!(&buf[..n], data);
|
||||
assert_eq!(bytes as usize, data.len());
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
#[test]
|
||||
fn test_splice_data_to_file() {
|
||||
use std::io::{Read, Seek, SeekFrom};
|
||||
|
||||
let mut temp_file = new_temp_file();
|
||||
let (pipe_read, pipe_write) = pipes::pipe().unwrap();
|
||||
let data = b"Hello, world!";
|
||||
let (bytes, _) = splice_data_to_fd(data, &pipe_read, &pipe_write, &temp_file).unwrap();
|
||||
assert_eq!(bytes as usize, data.len());
|
||||
|
||||
// We would have been at the end already, so seek again to the start.
|
||||
temp_file.seek(SeekFrom::Start(0)).unwrap();
|
||||
|
||||
let mut buf = Vec::new();
|
||||
temp_file.read_to_end(&mut buf).unwrap();
|
||||
assert_eq!(buf, data);
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
#[test]
|
||||
fn test_copy_exact() {
|
||||
|
@ -176,32 +115,4 @@ mod tests {
|
|||
assert_eq!(bytes_copied as usize, data.len());
|
||||
assert_eq!(buf, data);
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
#[test]
|
||||
fn test_splice_write() {
|
||||
use std::{
|
||||
io::{Read, Seek, SeekFrom, Write},
|
||||
thread,
|
||||
};
|
||||
|
||||
let (pipe_read, mut pipe_write) = pipes::pipe().unwrap();
|
||||
let mut dest_file = new_temp_file();
|
||||
let data = b"Hello, world!";
|
||||
let thread = thread::spawn(move || {
|
||||
pipe_write.write_all(data).unwrap();
|
||||
});
|
||||
let (bytes, _) = splice_write(&pipe_read, &dest_file).unwrap();
|
||||
thread.join().unwrap();
|
||||
|
||||
assert!(bytes == data.len() as u64);
|
||||
|
||||
// We would have been at the end already, so seek again to the start.
|
||||
dest_file.seek(SeekFrom::Start(0)).unwrap();
|
||||
|
||||
let mut buf = Vec::new();
|
||||
dest_file.read_to_end(&mut buf).unwrap();
|
||||
|
||||
assert_eq!(buf, data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,20 +3,15 @@
|
|||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
use nix::sys::stat::fstat;
|
||||
use nix::{errno::Errno, libc::S_IFIFO};
|
||||
//! Buffer-based copying implementation for Linux and Android.
|
||||
|
||||
type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// Buffer-based copying utilities for Linux and Android.
|
||||
use crate::{
|
||||
error::UResult,
|
||||
pipes::{pipe, splice, splice_exact, vmsplice},
|
||||
pipes::{pipe, splice, splice_exact},
|
||||
};
|
||||
|
||||
/// Buffer-based copying utilities for unix (excluding Linux).
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{Read, Write},
|
||||
os::fd::{AsFd, AsRawFd, RawFd},
|
||||
};
|
||||
|
@ -51,8 +46,9 @@ impl From<nix::Error> for Error {
|
|||
/// not use any intermediate user-space buffer. It falls backs to
|
||||
/// `std::io::copy` when the call fails and is still recoverable.
|
||||
///
|
||||
/// # Arguments * `source` - `Read` implementor to copy data from. * `dest` -
|
||||
/// `Write` implementor to copy data to.
|
||||
/// # Arguments
|
||||
/// * `source` - `Read` implementor to copy data from.
|
||||
/// * `dest` - `Write` implementor to copy data to.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
|
@ -146,117 +142,3 @@ pub(crate) fn copy_exact(
|
|||
}
|
||||
Ok(written)
|
||||
}
|
||||
|
||||
// The generalization of this function (and other splice_data functions) is not trivial as most
|
||||
// utilities will just write data finitely. However, `yes`, which is the sole crate using these
|
||||
// functions as of now, continuously loops the data write. Coupling the `is_pipe` check together
|
||||
// with the data write logic means that the check has to be done for every single write, which adds
|
||||
// unnecessary overhead.
|
||||
//
|
||||
/// Helper function to determine whether a given handle (such as a file) is a pipe or not. Can be
|
||||
/// used to determine whether to use the `splice_data_to_pipe` or the `splice_data_to_fd` function.
|
||||
/// This function is available exclusively to Linux and Android as it is meant to be used at the
|
||||
/// scope of splice operations.
|
||||
///
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `out` - path of handle
|
||||
///
|
||||
/// # Returns
|
||||
/// A `bool` indicating whether the given handle is a pipe or not.
|
||||
#[inline]
|
||||
pub fn is_pipe<P>(path: &P) -> Result<bool>
|
||||
where
|
||||
P: AsRawFd,
|
||||
{
|
||||
Ok(fstat(path.as_raw_fd())?.st_mode as nix::libc::mode_t & S_IFIFO != 0)
|
||||
}
|
||||
|
||||
/// Write input `bytes` to a handle using a temporary pipe. A `vmsplice()` call
|
||||
/// is issued to write to the temporary pipe, which then gets written to the
|
||||
/// final destination using `splice()`.
|
||||
///
|
||||
/// # Arguments * `bytes` - data to be written * `dest` - destination handle
|
||||
///
|
||||
/// # Returns When write succeeds, the amount of bytes written is returned as a
|
||||
/// `u64`. The `bool` indicates if we need to fall back to normal copying or
|
||||
/// not. `true` means we need to fall back, `false` means we don't have to.
|
||||
///
|
||||
/// A `UError` error is returned when the operation is not supported or when an
|
||||
/// I/O error occurs.
|
||||
pub fn splice_data_to_fd<T: AsFd>(
|
||||
bytes: &[u8],
|
||||
read_pipe: &File,
|
||||
write_pipe: &File,
|
||||
dest: &T,
|
||||
) -> UResult<(u64, bool)> {
|
||||
let mut n_bytes: u64 = 0;
|
||||
let mut bytes = bytes;
|
||||
while !bytes.is_empty() {
|
||||
let len = match vmsplice(&write_pipe, bytes) {
|
||||
Ok(n) => n,
|
||||
Err(e) => return Ok(maybe_unsupported(e)?),
|
||||
};
|
||||
if let Err(e) = splice_exact(&read_pipe, dest, len) {
|
||||
return Ok(maybe_unsupported(e)?);
|
||||
}
|
||||
bytes = &bytes[len..];
|
||||
n_bytes += len as u64;
|
||||
}
|
||||
Ok((n_bytes, false))
|
||||
}
|
||||
|
||||
/// Write input `bytes` to a file descriptor. This uses the Linux-specific
|
||||
/// `vmsplice()` call to write into a file descriptor directly, which only works
|
||||
/// if the destination is a pipe.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `bytes` - data to be written
|
||||
/// * `dest` - destination handle
|
||||
///
|
||||
/// # Returns
|
||||
/// When write succeeds, the amount of bytes written is returned as a
|
||||
/// `u64`. The `bool` indicates if we need to fall back to normal copying or
|
||||
/// not. `true` means we need to fall back, `false` means we don't have to.
|
||||
///
|
||||
/// A `UError` error is returned when the operation is not supported or when an
|
||||
/// I/O error occurs.
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn splice_data_to_pipe<T>(bytes: &[u8], dest: &T) -> UResult<(u64, bool)>
|
||||
where
|
||||
T: AsRawFd + AsFd,
|
||||
{
|
||||
let mut n_bytes: u64 = 0;
|
||||
let mut bytes = bytes;
|
||||
while !bytes.is_empty() {
|
||||
let len = match vmsplice(dest, bytes) {
|
||||
Ok(n) => n,
|
||||
// The maybe_unsupported call below may emit an error, when the
|
||||
// error is considered as unrecoverable error (ones that won't make
|
||||
// us fall back to other method)
|
||||
Err(e) => return Ok(maybe_unsupported(e)?),
|
||||
};
|
||||
bytes = &bytes[len..];
|
||||
n_bytes += len as u64;
|
||||
}
|
||||
Ok((n_bytes, false))
|
||||
}
|
||||
|
||||
/// Several error values from `nix::Error` (`EINVAL`, `ENOSYS`, and `EBADF`) get
|
||||
/// treated as errors indicating that the `splice` call is not available, i.e we
|
||||
/// can still recover from the error. Thus, return the final result of the call
|
||||
/// as `Result` and indicate that we have to fall back using other write method.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `error` - the `nix::Error` received
|
||||
///
|
||||
/// # Returns
|
||||
/// Result with tuple containing a `u64` `0` indicating that no data had been
|
||||
/// written and a `true` indicating we have to fall back, if error is still
|
||||
/// recoverable. Returns an `Error` implementing `UError` otherwise.
|
||||
pub(crate) fn maybe_unsupported(error: nix::Error) -> Result<(u64, bool)> {
|
||||
match error {
|
||||
Errno::EINVAL | Errno::ENOSYS | Errno::EBADF => Ok((0, true)),
|
||||
_ => Err(error.into()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
//
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
//!
|
||||
//! Buffer-based copying implementation for other platforms.
|
||||
|
||||
use std::io::{Read, Write};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue