Skip to content

Commit

Permalink
shred: if the file is empty, don't run passes on it
Browse files Browse the repository at this point in the history
  • Loading branch information
sylvestre committed Mar 23, 2024
1 parent 322c2b4 commit f410d09
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 25 deletions.
53 changes: 28 additions & 25 deletions src/uu/shred/src/shred.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,9 +406,10 @@ fn wipe_file(
));
}

let metadata = fs::metadata(path).map_err_context(String::new)?;

// If force is true, set file permissions to not-readonly.
if force {
let metadata = fs::metadata(path).map_err_context(String::new)?;
let mut perms = metadata.permissions();
#[cfg(unix)]
#[allow(clippy::useless_conversion, clippy::unnecessary_cast)]
Expand All @@ -428,35 +429,37 @@ fn wipe_file(

// Fill up our pass sequence
let mut pass_sequence = Vec::new();
if metadata.len() != 0 {
// Only add passes if the file is non-empty

if n_passes <= 3 {
// Only random passes if n_passes <= 3
for _ in 0..n_passes {
pass_sequence.push(PassType::Random);
}
} else {
// First fill it with Patterns, shuffle it, then evenly distribute Random
let n_full_arrays = n_passes / PATTERNS.len(); // How many times can we go through all the patterns?
let remainder = n_passes % PATTERNS.len(); // How many do we get through on our last time through?

for _ in 0..n_full_arrays {
for p in PATTERNS {
pass_sequence.push(PassType::Pattern(p));
if n_passes <= 3 {
// Only random passes if n_passes <= 3
for _ in 0..n_passes {
pass_sequence.push(PassType::Random);
}
}
for pattern in PATTERNS.into_iter().take(remainder) {
pass_sequence.push(PassType::Pattern(pattern));
}
let mut rng = rand::thread_rng();
pass_sequence.shuffle(&mut rng); // randomize the order of application
} else {
// First fill it with Patterns, shuffle it, then evenly distribute Random
let n_full_arrays = n_passes / PATTERNS.len(); // How many times can we go through all the patterns?
let remainder = n_passes % PATTERNS.len(); // How many do we get through on our last time through?

for _ in 0..n_full_arrays {
for p in PATTERNS {
pass_sequence.push(PassType::Pattern(p));
}
}
for pattern in PATTERNS.into_iter().take(remainder) {
pass_sequence.push(PassType::Pattern(pattern));
}
let mut rng = rand::thread_rng();
pass_sequence.shuffle(&mut rng); // randomize the order of application

let n_random = 3 + n_passes / 10; // Minimum 3 random passes; ratio of 10 after
// Evenly space random passes; ensures one at the beginning and end
for i in 0..n_random {
pass_sequence[i * (n_passes - 1) / (n_random - 1)] = PassType::Random;
let n_random = 3 + n_passes / 10; // Minimum 3 random passes; ratio of 10 after
// Evenly space random passes; ensures one at the beginning and end
for i in 0..n_random {
pass_sequence[i * (n_passes - 1) / (n_random - 1)] = PassType::Random;
}
}
}

// --zero specifies whether we want one final pass of 0x00 on our file
if zero {
pass_sequence.push(PassType::Pattern(PATTERNS[0]));
Expand Down
20 changes: 20 additions & 0 deletions tests/by-util/test_shred.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,23 @@ fn test_hex() {

ucmd.arg("--size=0x10").arg(file).succeeds();
}

#[test]
fn test_shred_empty() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;

let file_a = "test_shred_remove_a";

at.touch(file_a);

// Shred file_a and verify that, as it is empty, it doesn't have "pass 1/3 (random)"
scene
.ucmd()
.arg("-uv")
.arg(file_a)
.succeeds()
.stdout_does_not_contain("pass 1/3 (random)");

assert!(!at.file_exists(file_a));
}

0 comments on commit f410d09

Please sign in to comment.