1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

Merge pull request #4428 from jfinkels/dd-copy-function

dd: move dd_out() function up to module level
This commit is contained in:
Sylvestre Ledru 2023-02-24 08:59:44 +01:00 committed by GitHub
commit 999ee8e848
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -138,7 +138,7 @@ impl Read for Source {
/// ///
/// Use the [`Input::new_stdin`] or [`Input::new_file`] functions to /// Use the [`Input::new_stdin`] or [`Input::new_file`] functions to
/// construct a new instance of this struct. Then pass the instance to /// construct a new instance of this struct. Then pass the instance to
/// the [`Output::dd_out`] function to execute the main copy operation /// the [`dd_copy`] function to execute the main copy operation
/// for `dd`. /// for `dd`.
struct Input<'a> { struct Input<'a> {
/// The source from which bytes will be read. /// The source from which bytes will be read.
@ -449,7 +449,7 @@ impl Write for Dest {
/// ///
/// Use the [`Output::new_stdout`] or [`Output::new_file`] functions /// Use the [`Output::new_stdout`] or [`Output::new_file`] functions
/// to construct a new instance of this struct. Then use the /// to construct a new instance of this struct. Then use the
/// [`Output::dd_out`] function to execute the main copy operation for /// [`dd_copy`] function to execute the main copy operation for
/// `dd`. /// `dd`.
struct Output<'a> { struct Output<'a> {
/// The destination to which bytes will be written. /// The destination to which bytes will be written.
@ -579,6 +579,7 @@ impl<'a> Output<'a> {
Ok(()) Ok(())
} }
} }
}
/// Copy the given input data to this output, consuming both. /// Copy the given input data to this output, consuming both.
/// ///
@ -591,7 +592,7 @@ impl<'a> Output<'a> {
/// ///
/// If there is a problem reading from the input or writing to /// If there is a problem reading from the input or writing to
/// this output. /// this output.
fn dd_out(mut self, mut i: Input) -> std::io::Result<()> { fn dd_copy(mut i: Input, mut o: Output) -> std::io::Result<()> {
// The read and write statistics. // The read and write statistics.
// //
// These objects are counters, initialized to zero. After each // These objects are counters, initialized to zero. After each
@ -613,7 +614,7 @@ impl<'a> Output<'a> {
// //
// This is an educated guess about a good buffer size based on // This is an educated guess about a good buffer size based on
// the input and output block sizes. // the input and output block sizes.
let bsize = calc_bsize(i.settings.ibs, self.settings.obs); let bsize = calc_bsize(i.settings.ibs, o.settings.obs);
// Start a thread that reports transfer progress. // Start a thread that reports transfer progress.
// //
@ -632,7 +633,7 @@ impl<'a> Output<'a> {
// Optimization: if no blocks are to be written, then don't // Optimization: if no blocks are to be written, then don't
// bother allocating any buffers. // bother allocating any buffers.
if let Some(Num::Blocks(0) | Num::Bytes(0)) = i.settings.count { if let Some(Num::Blocks(0) | Num::Bytes(0)) = i.settings.count {
return self.finalize(rstat, wstat, start, &prog_tx, output_thread); return finalize(&mut o, rstat, wstat, start, &prog_tx, output_thread);
}; };
// Create a common buffer with a capacity of the block size. // Create a common buffer with a capacity of the block size.
@ -651,13 +652,12 @@ impl<'a> Output<'a> {
// As an optimization, make an educated guess about the // As an optimization, make an educated guess about the
// best buffer size for reading based on the number of // best buffer size for reading based on the number of
// blocks already read and the number of blocks remaining. // blocks already read and the number of blocks remaining.
let loop_bsize = let loop_bsize = calc_loop_bsize(&i.settings.count, &rstat, &wstat, i.settings.ibs, bsize);
calc_loop_bsize(&i.settings.count, &rstat, &wstat, i.settings.ibs, bsize);
let rstat_update = read_helper(&mut i, &mut buf, loop_bsize)?; let rstat_update = read_helper(&mut i, &mut buf, loop_bsize)?;
if rstat_update.is_empty() { if rstat_update.is_empty() {
break; break;
} }
let wstat_update = self.write_blocks(&buf)?; let wstat_update = o.write_blocks(&buf)?;
// Update the read/write stats and inform the progress thread once per second. // Update the read/write stats and inform the progress thread once per second.
// //
@ -673,12 +673,12 @@ impl<'a> Output<'a> {
prog_tx.send(prog_update).unwrap_or(()); prog_tx.send(prog_update).unwrap_or(());
} }
} }
self.finalize(rstat, wstat, start, &prog_tx, output_thread) finalize(&mut o, rstat, wstat, start, &prog_tx, output_thread)
} }
/// Flush output, print final stats, and join with the progress thread. /// Flush output, print final stats, and join with the progress thread.
fn finalize<T>( fn finalize<T>(
&mut self, output: &mut Output,
rstat: ReadStat, rstat: ReadStat,
wstat: WriteStat, wstat: WriteStat,
start: time::Instant, start: time::Instant,
@ -686,7 +686,7 @@ impl<'a> Output<'a> {
output_thread: thread::JoinHandle<T>, output_thread: thread::JoinHandle<T>,
) -> std::io::Result<()> { ) -> std::io::Result<()> {
// Flush the output, if configured to do so. // Flush the output, if configured to do so.
self.sync()?; output.sync()?;
// Truncate the file to the final cursor location. // Truncate the file to the final cursor location.
// //
@ -696,8 +696,8 @@ impl<'a> Output<'a> {
// suppress the error by calling `Result::ok()`. This matches // suppress the error by calling `Result::ok()`. This matches
// the behavior of GNU `dd` when given the command-line // the behavior of GNU `dd` when given the command-line
// argument `of=/dev/null`. // argument `of=/dev/null`.
if !self.settings.oconv.notrunc { if !output.settings.oconv.notrunc {
self.dst.truncate().ok(); output.dst.truncate().ok();
} }
// Print the final read/write statistics. // Print the final read/write statistics.
@ -709,7 +709,6 @@ impl<'a> Output<'a> {
.expect("Failed to join with the output thread."); .expect("Failed to join with the output thread.");
Ok(()) Ok(())
} }
}
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
fn make_linux_oflags(oflags: &OFlags) -> Option<libc::c_int> { fn make_linux_oflags(oflags: &OFlags) -> Option<libc::c_int> {
@ -925,7 +924,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
} }
None => Output::new_stdout(&settings)?, None => Output::new_stdout(&settings)?,
}; };
o.dd_out(i).map_err_context(|| "IO error".to_string()) dd_copy(i, o).map_err_context(|| "IO error".to_string())
} }
pub fn uu_app() -> Command { pub fn uu_app() -> Command {