mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
shred: fix random passes* (#7830)
* shred: fix random passes, update documentation, add test * shred: update tests
This commit is contained in:
parent
151b196f50
commit
b151e039ae
2 changed files with 36 additions and 12 deletions
|
@ -51,8 +51,7 @@ const PATTERN_BUFFER_SIZE: usize = BLOCK_SIZE + PATTERN_LENGTH - 1;
|
||||||
|
|
||||||
/// Patterns that appear in order for the passes
|
/// Patterns that appear in order for the passes
|
||||||
///
|
///
|
||||||
/// They are all extended to 3 bytes for consistency, even though some could be
|
/// A single-byte pattern is equivalent to a multi-byte pattern of that byte three times.
|
||||||
/// expressed as single bytes.
|
|
||||||
const PATTERNS: [Pattern; 22] = [
|
const PATTERNS: [Pattern; 22] = [
|
||||||
Pattern::Single(b'\x00'),
|
Pattern::Single(b'\x00'),
|
||||||
Pattern::Single(b'\xFF'),
|
Pattern::Single(b'\xFF'),
|
||||||
|
@ -440,9 +439,13 @@ fn wipe_file(
|
||||||
pass_sequence.push(PassType::Random);
|
pass_sequence.push(PassType::Random);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// First fill it with Patterns, shuffle it, then evenly distribute Random
|
// Add initial random to avoid O(n) operation later
|
||||||
let n_full_arrays = n_passes / PATTERNS.len(); // How many times can we go through all the patterns?
|
pass_sequence.push(PassType::Random);
|
||||||
let remainder = n_passes % PATTERNS.len(); // How many do we get through on our last time through?
|
let n_random = (n_passes / 10).max(3); // Minimum 3 random passes; ratio of 10 after
|
||||||
|
let n_fixed = n_passes - n_random;
|
||||||
|
// Fill it with Patterns and all but the first and last random, then shuffle it
|
||||||
|
let n_full_arrays = n_fixed / PATTERNS.len(); // How many times can we go through all the patterns?
|
||||||
|
let remainder = n_fixed % PATTERNS.len(); // How many do we get through on our last time through, excluding randoms?
|
||||||
|
|
||||||
for _ in 0..n_full_arrays {
|
for _ in 0..n_full_arrays {
|
||||||
for p in PATTERNS {
|
for p in PATTERNS {
|
||||||
|
@ -452,14 +455,14 @@ fn wipe_file(
|
||||||
for pattern in PATTERNS.into_iter().take(remainder) {
|
for pattern in PATTERNS.into_iter().take(remainder) {
|
||||||
pass_sequence.push(PassType::Pattern(pattern));
|
pass_sequence.push(PassType::Pattern(pattern));
|
||||||
}
|
}
|
||||||
let mut rng = rand::rng();
|
// add random passes except one each at the beginning and end
|
||||||
pass_sequence.shuffle(&mut rng); // randomize the order of application
|
for _ in 0..n_random - 2 {
|
||||||
|
pass_sequence.push(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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut rng = rand::rng();
|
||||||
|
pass_sequence[1..].shuffle(&mut rng); // randomize the order of application
|
||||||
|
pass_sequence.push(PassType::Random); // add the last random pass
|
||||||
}
|
}
|
||||||
|
|
||||||
// --zero specifies whether we want one final pass of 0x00 on our file
|
// --zero specifies whether we want one final pass of 0x00 on our file
|
||||||
|
|
|
@ -10,6 +10,12 @@ use uutests::new_ucmd;
|
||||||
use uutests::util::TestScenario;
|
use uutests::util::TestScenario;
|
||||||
use uutests::util_name;
|
use uutests::util_name;
|
||||||
|
|
||||||
|
const PATTERNS: [&str; 22] = [
|
||||||
|
"000000", "ffffff", "555555", "aaaaaa", "249249", "492492", "6db6db", "924924", "b6db6d",
|
||||||
|
"db6db6", "111111", "222222", "333333", "444444", "666666", "777777", "888888", "999999",
|
||||||
|
"bbbbbb", "cccccc", "dddddd", "eeeeee",
|
||||||
|
];
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_invalid_arg() {
|
fn test_invalid_arg() {
|
||||||
new_ucmd!().arg("--definitely-invalid").fails_with_code(1);
|
new_ucmd!().arg("--definitely-invalid").fails_with_code(1);
|
||||||
|
@ -241,3 +247,18 @@ fn test_shred_verbose_no_padding_10() {
|
||||||
.succeeds()
|
.succeeds()
|
||||||
.stderr_contains("shred: foo: pass 1/10 (random)...\n");
|
.stderr_contains("shred: foo: pass 1/10 (random)...\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_all_patterns_present() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
let file = "foo.txt";
|
||||||
|
at.write(file, "bar");
|
||||||
|
|
||||||
|
let result = scene.ucmd().arg("-vn25").arg(file).succeeds();
|
||||||
|
|
||||||
|
for pat in PATTERNS {
|
||||||
|
result.stderr_contains(pat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue