1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-08-03 22:47:46 +00:00

Open file once for all passes, seek back to start between passes. Do not use File::create, because it truncates existing files

This commit is contained in:
Fort 2015-12-30 11:27:59 -08:00
parent 04d2134856
commit 4a42b981f9

View file

@ -15,8 +15,9 @@ extern crate rand;
use rand::{ThreadRng, Rng}; use rand::{ThreadRng, Rng};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::fs; use std::fs;
use std::fs::File; use std::fs::{File, OpenOptions};
use std::io; use std::io;
use std::io::SeekFrom;
use std::io::prelude::*; use std::io::prelude::*;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@ -367,23 +368,30 @@ fn wipe_file(path_str: &str, n_passes: usize, remove: bool,
if zero { if zero {
pass_sequence.push(PassType::Pattern(b"\x00")); pass_sequence.push(PassType::Pattern(b"\x00"));
} }
let total_passes: usize = n_passes + { if zero { 1 } else { 0 } };
for (i, pass_type) in pass_sequence.iter().enumerate() { {
if verbose { let total_passes: usize = pass_sequence.len();
let pattern_str: String = match *pass_type { let mut file: File = OpenOptions::new().write(true)
PassType::Random => String::from("random"), .truncate(false)
PassType::Pattern(p) => bytes_to_string(p) .open(path)
}; .expect("Failed to open file for writing");
if total_passes.to_string().len() == 1 {
println!("{}: {}: pass {}/{} ({})... ", NAME, path.display(), i + 1, total_passes, pattern_str); for (i, pass_type) in pass_sequence.iter().enumerate() {
} if verbose {
else { let pattern_str: String = match *pass_type {
println!("{}: {}: pass {:2.0}/{:2.0} ({})... ", NAME, path.display(), i + 1, total_passes, pattern_str); PassType::Random => String::from("random"),
PassType::Pattern(p) => bytes_to_string(p)
};
if total_passes.to_string().len() == 1 {
println!("{}: {}: pass {}/{} ({})... ", NAME, path.display(), i + 1, total_passes, pattern_str);
}
else {
println!("{}: {}: pass {:2.0}/{:2.0} ({})... ", NAME, path.display(), i + 1, total_passes, pattern_str);
}
} }
// size is an optional argument for exactly how many bytes we want to shred
do_pass(&mut file, path, *pass_type, size, exact).expect("File write pass failed"); // Ignore failed writes; just keep trying
} }
// size is an optional argument for exactly how many bytes we want to shred
do_pass(path, *pass_type, size, exact).expect("File write pass failed"); // Ignore failed writes; just keep trying
} }
if remove { if remove {
@ -391,21 +399,21 @@ fn wipe_file(path_str: &str, n_passes: usize, remove: bool,
} }
} }
fn do_pass(path: &Path, generator_type: PassType, fn do_pass(file: &mut File, path: &Path, generator_type: PassType,
given_file_size: Option<u64>, exact: bool) -> Result<(), io::Error> { given_file_size: Option<u64>, exact: bool) -> Result<(), io::Error> {
try!(file.seek(SeekFrom::Start(0)));
// Use the given size or the whole file if not specified // Use the given size or the whole file if not specified
let size: u64 = given_file_size.unwrap_or(try!(get_file_size(path))); let size: u64 = given_file_size.unwrap_or(try!(get_file_size(path)));
let generator = BytesGenerator::new(size, generator_type, exact); let generator = BytesGenerator::new(size, generator_type, exact);
let mut file: File = try!(File::create(path));
for block in generator { for block in generator {
try!(file.write_all(&*block)); try!(file.write_all(&*block));
} }
try!(file.sync_all()); try!(file.sync_data());
Ok(()) Ok(())
} }
@ -441,7 +449,7 @@ fn wipe_name(orig_path: &Path, verbose: bool) -> Option<PathBuf> {
// Sync every file rename // Sync every file rename
{ {
let new_file: File = File::create(new_path.clone()).expect("Failed to open renamed file for syncing"); let new_file: File = File::open(new_path.clone()).expect("Failed to open renamed file for syncing");
new_file.sync_all().expect("Failed to sync renamed file"); new_file.sync_all().expect("Failed to sync renamed file");
} }