mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
dd: replace nix by rustix (#12567)
Co-authored-by: Sylvestre Ledru <sylvestre@debian.org>
This commit is contained in:
Generated
+1
-1
@@ -3419,7 +3419,7 @@ dependencies = [
|
||||
"fluent",
|
||||
"gcd",
|
||||
"libc",
|
||||
"nix",
|
||||
"rustix",
|
||||
"tempfile",
|
||||
"thiserror 2.0.18",
|
||||
"uucore",
|
||||
|
||||
@@ -33,7 +33,7 @@ thiserror = { workspace = true }
|
||||
fluent = { workspace = true }
|
||||
|
||||
[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies]
|
||||
nix = { workspace = true, features = ["fs", "signal"] }
|
||||
rustix = { workspace = true, features = ["fs"] }
|
||||
|
||||
[[bin]]
|
||||
name = "dd"
|
||||
|
||||
@@ -39,7 +39,7 @@ impl<'a> BufferedOutput<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn discard_cache(&self, offset: libc::off_t, len: libc::off_t) {
|
||||
pub(crate) fn discard_cache(&self, offset: u64, len: u64) {
|
||||
self.inner.discard_cache(offset, len);
|
||||
}
|
||||
|
||||
|
||||
+38
-42
@@ -3,7 +3,7 @@
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
// spell-checker:ignore fname, ftype, tname, fpath, specfile, testfile, unspec, ifile, ofile, outfile, fullblock, urand, fileio, atoe, atoibm, behaviour, bmax, bremain, cflags, creat, ctable, ctty, datastructures, doesnt, etoa, fileout, fname, gnudd, iconvflags, iseek, nocache, noctty, noerror, nofollow, nolinks, nonblock, oconvflags, oseek, outfile, parseargs, rlen, rmax, rremain, rsofar, rstat, sigusr, wlen, wstat oconv canonicalized Fadvise FADV DONTNEED ESPIPE bufferedoutput, SETFL
|
||||
// spell-checker:ignore fname, ftype, tname, fpath, specfile, testfile, unspec, ifile, ofile, outfile, fullblock, urand, fileio, atoe, atoibm, behaviour, bmax, bremain, cflags, creat, ctable, ctty, datastructures, doesnt, etoa, fileout, fname, gnudd, iconvflags, iseek, nocache, noctty, noerror, nofollow, nolinks, nonblock, oconvflags, oseek, outfile, parseargs, rlen, rmax, rremain, rsofar, rstat, sigusr, wlen, wstat oconv canonicalized FADV DONTNEED ESPIPE SPIPE bufferedoutput, SETFL
|
||||
|
||||
mod blocks;
|
||||
mod bufferedoutput;
|
||||
@@ -16,10 +16,6 @@ mod progress;
|
||||
use crate::bufferedoutput::BufferedOutput;
|
||||
use blocks::conv_block_unblock_helper;
|
||||
use datastructures::{ConversionMode, IConvFlags, IFlags, OConvFlags, OFlags, options};
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
use nix::fcntl::FcntlArg;
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
use nix::fcntl::OFlag;
|
||||
use parseargs::Parser;
|
||||
use progress::ProgUpdateType;
|
||||
use progress::{ProgUpdate, ReadStat, StatusLevel, WriteStat, gen_prog_updater};
|
||||
@@ -36,8 +32,6 @@ use std::fs::Metadata;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::{self, Read, Seek, SeekFrom, Write};
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
use std::os::fd::AsFd;
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
use std::os::unix::fs::OpenOptionsExt;
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::{
|
||||
@@ -54,11 +48,6 @@ use std::time::{Duration, Instant};
|
||||
|
||||
use clap::{Arg, Command};
|
||||
use gcd::Gcd;
|
||||
#[cfg(target_os = "linux")]
|
||||
use nix::{
|
||||
errno::Errno,
|
||||
fcntl::{PosixFadviseAdvice, posix_fadvise},
|
||||
};
|
||||
use uucore::display::Quotable;
|
||||
use uucore::error::{FromIo, UResult};
|
||||
#[cfg(unix)]
|
||||
@@ -317,14 +306,16 @@ impl Source {
|
||||
/// portion of the source is no longer needed. If not possible,
|
||||
/// then this function returns an error.
|
||||
#[cfg(target_os = "linux")]
|
||||
fn discard_cache(&self, offset: libc::off_t, len: libc::off_t) -> nix::Result<()> {
|
||||
fn discard_cache(&self, offset: u64, len: u64) -> io::Result<()> {
|
||||
#[allow(clippy::match_wildcard_for_single_variants)]
|
||||
match self {
|
||||
Self::File(f) => {
|
||||
let advice = PosixFadviseAdvice::POSIX_FADV_DONTNEED;
|
||||
posix_fadvise(f.as_fd(), offset, len, advice)
|
||||
use rustix::fs::{Advice::DontNeed, fadvise};
|
||||
fadvise(f, offset, std::num::NonZeroU64::new(len), DontNeed)?;
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(Errno::ESPIPE), // "Illegal seek"
|
||||
// fadvise for nonseekable returns this error. We manually do that...
|
||||
_ => Err(rustix::io::Errno::SPIPE.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -502,7 +493,7 @@ impl Input<'_> {
|
||||
/// function prints an error message to stderr and sets the exit
|
||||
/// status code to 1.
|
||||
#[cfg_attr(not(target_os = "linux"), allow(clippy::unused_self, unused_variables))]
|
||||
fn discard_cache(&self, offset: libc::off_t, len: libc::off_t) {
|
||||
fn discard_cache(&self, offset: u64, len: u64) {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let file = self
|
||||
@@ -703,13 +694,15 @@ impl Dest {
|
||||
/// specified portion of the destination is no longer needed. If
|
||||
/// not possible, then this function returns an error.
|
||||
#[cfg(target_os = "linux")]
|
||||
fn discard_cache(&self, offset: libc::off_t, len: libc::off_t) -> nix::Result<()> {
|
||||
fn discard_cache(&self, offset: u64, len: u64) -> io::Result<()> {
|
||||
match self {
|
||||
Self::File(f, _) => {
|
||||
let advice = PosixFadviseAdvice::POSIX_FADV_DONTNEED;
|
||||
posix_fadvise(f.as_fd(), offset, len, advice)
|
||||
use rustix::fs::{Advice::DontNeed, fadvise};
|
||||
fadvise(f, offset, std::num::NonZeroU64::new(len), DontNeed)?;
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(Errno::ESPIPE), // "Illegal seek"
|
||||
// fadvise for nonseekable returns this error. We manually do that...
|
||||
_ => Err(rustix::io::Errno::SPIPE.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -723,31 +716,33 @@ fn is_sparse(buf: &[u8]) -> bool {
|
||||
/// This follows GNU dd behavior for partial block writes with O_DIRECT.
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
fn handle_o_direct_write(f: &mut File, buf: &[u8], original_error: io::Error) -> io::Result<usize> {
|
||||
use nix::fcntl::{FcntlArg, OFlag, fcntl};
|
||||
use rustix::fs::{OFlags, fcntl_getfl, fcntl_setfl};
|
||||
|
||||
// Get current flags using nix
|
||||
let oflags = match fcntl(&mut *f, FcntlArg::F_GETFL) {
|
||||
Ok(flags) => OFlag::from_bits_retain(flags),
|
||||
Err(_) => return Err(original_error),
|
||||
// Get current flags
|
||||
let Ok(oflags) = fcntl_getfl(&*f) else {
|
||||
return Err(original_error);
|
||||
};
|
||||
|
||||
// If O_DIRECT is set, try removing it temporarily
|
||||
if oflags.contains(OFlag::O_DIRECT) {
|
||||
let flags_without_direct = oflags - OFlag::O_DIRECT;
|
||||
if oflags.contains(OFlags::DIRECT) {
|
||||
let flags_without_direct = oflags & !OFlags::DIRECT;
|
||||
|
||||
// Remove O_DIRECT flag using nix
|
||||
if fcntl(&mut *f, FcntlArg::F_SETFL(flags_without_direct)).is_err() {
|
||||
// Remove O_DIRECT flag
|
||||
if fcntl_setfl(&*f, flags_without_direct).is_err() {
|
||||
return Err(original_error);
|
||||
}
|
||||
|
||||
// Retry the write without O_DIRECT
|
||||
let write_result = f.write(buf);
|
||||
|
||||
// Restore O_DIRECT flag using nix (GNU doesn't restore it, but we'll be safer)
|
||||
// Restore O_DIRECT flag (GNU doesn't restore it, but we'll be safer)
|
||||
// Log any restoration errors without failing the operation
|
||||
if let Err(os_err) = fcntl(&mut *f, FcntlArg::F_SETFL(oflags)) {
|
||||
if let Err(os_err) = fcntl_setfl(&*f, oflags) {
|
||||
// Just log the error, don't fail the whole operation
|
||||
show_error!("Failed to restore O_DIRECT flag: {os_err}");
|
||||
show_error!(
|
||||
"Failed to restore O_DIRECT flag: {}",
|
||||
io::Error::from(os_err)
|
||||
);
|
||||
}
|
||||
|
||||
write_result
|
||||
@@ -894,10 +889,11 @@ impl<'a> Output<'a> {
|
||||
let fx = OwnedFileDescriptorOrHandle::from(io::stdout())?;
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
if let Some(libc_flags) = make_linux_oflags(&settings.oflags) {
|
||||
nix::fcntl::fcntl(
|
||||
fx.as_raw().as_fd(),
|
||||
FcntlArg::F_SETFL(OFlag::from_bits_retain(libc_flags)),
|
||||
)?;
|
||||
rustix::fs::fcntl_setfl(
|
||||
fx.as_raw(),
|
||||
rustix::fs::OFlags::from_bits_retain(libc_flags as _),
|
||||
)
|
||||
.map_err(|e| uucore::error::UIoError::from(io::Error::from(e)))?;
|
||||
}
|
||||
|
||||
Self::prepare_file(fx.into_file(), settings)
|
||||
@@ -940,7 +936,7 @@ impl<'a> Output<'a> {
|
||||
/// this function prints an error message to stderr and sets the
|
||||
/// exit status code to 1.
|
||||
#[cfg_attr(not(target_os = "linux"), allow(clippy::unused_self, unused_variables))]
|
||||
fn discard_cache(&self, offset: libc::off_t, len: libc::off_t) {
|
||||
fn discard_cache(&self, offset: u64, len: u64) {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let file = self
|
||||
@@ -1046,7 +1042,7 @@ enum BlockWriter<'a> {
|
||||
}
|
||||
|
||||
impl BlockWriter<'_> {
|
||||
fn discard_cache(&self, offset: libc::off_t, len: libc::off_t) {
|
||||
fn discard_cache(&self, offset: u64, len: u64) {
|
||||
match self {
|
||||
Self::Unbuffered(o) => o.discard_cache(offset, len),
|
||||
Self::Buffered(o) => o.discard_cache(offset, len),
|
||||
@@ -1228,7 +1224,7 @@ fn dd_copy(mut i: Input, o: Output) -> io::Result<()> {
|
||||
let rstat_update = read_helper(&mut i, &mut buf, loop_bsize)?;
|
||||
if rstat_update.is_empty() {
|
||||
if input_nocache {
|
||||
i.discard_cache(read_offset.try_into().unwrap(), 0);
|
||||
i.discard_cache(read_offset, 0);
|
||||
}
|
||||
if output_nocache || output_direct {
|
||||
o.discard_cache(write_offset.try_into().unwrap(), 0);
|
||||
@@ -1243,8 +1239,8 @@ fn dd_copy(mut i: Input, o: Output) -> io::Result<()> {
|
||||
// TODO Better error handling for overflowing `offset` and `len`.
|
||||
let read_len = rstat_update.bytes_total;
|
||||
if input_nocache {
|
||||
let offset = read_offset.try_into().unwrap();
|
||||
let len = read_len.try_into().unwrap();
|
||||
let offset = read_offset;
|
||||
let len = read_len;
|
||||
i.discard_cache(offset, len);
|
||||
}
|
||||
read_offset += read_len;
|
||||
|
||||
@@ -459,11 +459,9 @@ extern "C" fn sigusr1_handler(_: std::os::raw::c_int) {
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub(crate) fn install_sigusr1_handler() -> Result<(), nix::errno::Errno> {
|
||||
uucore::signals::install_signal_handler(
|
||||
nix::sys::signal::Signal::SIGUSR1 as libc::c_int,
|
||||
sigusr1_handler,
|
||||
)
|
||||
pub(crate) fn install_sigusr1_handler() -> std::io::Result<()> {
|
||||
uucore::signals::install_signal_handler(libc::SIGUSR1, sigusr1_handler)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Return a closure that can be used in its own thread to print progress info.
|
||||
|
||||
Reference in New Issue
Block a user