Skip to content

Commit

Permalink
cp: Error handling and refactoring
Browse files Browse the repository at this point in the history
- Handled clippy warnings
- Handling errors now
- Default size for normal copy is now configurable via std::env

#4528
  • Loading branch information
jp-systango committed Oct 14, 2023
1 parent 18b9946 commit 888935c
Showing 1 changed file with 39 additions and 12 deletions.
51 changes: 39 additions & 12 deletions src/uu/cp/src/cp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,12 +354,22 @@ fn show_debug(copy_debug: &CopyDebug) {
const ABOUT: &str = help_about!("cp.md");
const USAGE: &str = help_usage!("cp.md");
const AFTER_HELP: &str = help_section!("after help", "cp.md");
const SIZE_LIMIT_FOR_NORMAL_COPY: u64 = 524288000;
// Considering 4 Kb as block size for a standard file system, multiply it by 4 to make it 16 kb
const BUFFER_SIZE: usize = 4096 * 4;
const BUFFER_SIZE_U64: u64 = BUFFER_SIZE as u64;

static EXIT_ERR: i32 = 1;

fn get_size_limit_for_normal_copy() -> u64 {
const DEFAULT_SIZE_LIMIT_FOR_NORMAL_COPY: u64 = 524288000; // 500 Mb
match std::env::var("CP_SIZE_LIMIT_FOR_NORMAL_COPY") {
Ok(val) => val
.parse::<u64>()
.unwrap_or(DEFAULT_SIZE_LIMIT_FOR_NORMAL_COPY),
Err(_) => DEFAULT_SIZE_LIMIT_FOR_NORMAL_COPY,
}
}

// Argument constants
mod options {
pub const ARCHIVE: &str = "archive";
Expand Down Expand Up @@ -1750,13 +1760,14 @@ fn copy_file(

let source_size = source_metadata.len();
let mut use_copy_with_intermediate_progress = false;
if source_size >= SIZE_LIMIT_FOR_NORMAL_COPY
if source_size >= get_size_limit_for_normal_copy()
&& !source_is_symlink
&& !source_is_fifo
&& symlinked_files.len() == 0
&& symlinked_files.is_empty()
&& matches!(options.copy_mode, CopyMode::Copy)
&& progress_bar.is_some()
{
// When we are dealing with a large file with a progress bar, show the progress of its copy too
use_copy_with_intermediate_progress = true;
}

Expand Down Expand Up @@ -1784,7 +1795,7 @@ fn copy_file(
}
CopyMode::Copy => {
if use_copy_with_intermediate_progress {
copy_with_intermediate_progress(source, dest, progress_bar);
copy_with_intermediate_progress(source, dest, progress_bar)?;
} else {
copy_helper(
source,
Expand Down Expand Up @@ -1931,14 +1942,15 @@ fn copy_helper(
}

/// Copy the file from `source` to `dest` by reading into and writing from a buffer.
/// Increment the progress bar on each write to show the intermediate progress.
/// Increment the progress bar on each write to show the intermediate progress
/// and show any errors that will occur because this is a large file.
pub fn copy_with_intermediate_progress(
source: &Path,
dest: &Path,
progress_bar: &Option<ProgressBar>,
) {
let metadata = fs::metadata(source).unwrap();
let source_file = OpenOptions::new().read(true).open(source).unwrap();
) -> CopyResult<()> {
let metadata = fs::metadata(source)?;
let source_file = OpenOptions::new().read(true).open(source)?;
let dest_file = OpenOptions::new()
.append(true)
.write(true)
Expand All @@ -1951,12 +1963,27 @@ pub fn copy_with_intermediate_progress(
while written < source_size {
let mut buffer = [0; BUFFER_SIZE];
let written_u64 = written as u64;
let read = source_file.read_at(&mut buffer, written_u64).unwrap();
written += dest_file
.write_at(&buffer.get(0..read).unwrap(), written_u64)
.unwrap();
let read = source_file.read_at(&mut buffer, written_u64)?;
match buffer.get(0..read) {
Some(bytes_read) => {
match dest_file.write_at(bytes_read, written_u64) {
Ok(bytes_written) => {
written += bytes_written;
}
Err(err) => {
return Err(Error::IoErr(err));
}
};
}
None => {
return Err("No bytes to read".to_string().into());
}
};

progress_bar.as_ref().unwrap().inc(BUFFER_SIZE_U64);
}

Ok(())
}

// "Copies" a FIFO by creating a new one. This workaround is because Rust's
Expand Down

0 comments on commit 888935c

Please sign in to comment.