Skip to content

Commit

Permalink
Error handling
Browse files Browse the repository at this point in the history
Implement vast improvements in error handling.
Squashed commit of the following:

commit bdb0d105b00d854c78d4ccd0a94aec471aeed652
Author: Olivier Thornton <[email protected]>
Date:   Thu Feb 16 13:45:35 2023 -0600

    disable debug mode

commit 0dc4f9f
Author: Olivier Thornton <[email protected]>
Date:   Thu Feb 16 13:40:34 2023 -0600

    update readme

commit 9fd8f28
Author: Olivier Thornton <[email protected]>
Date:   Thu Feb 16 13:40:27 2023 -0600

    error handling

commit 8bc2fdf
Author: Olivier Thornton <[email protected]>
Date:   Thu Feb 16 13:39:59 2023 -0600

    update version info

commit 805a785
Author: Olivier Thornton <[email protected]>
Date:   Thu Feb 16 12:34:54 2023 -0600

    remove dot files from delete_all

commit 723644d
Author: Olivier Thornton <[email protected]>
Date:   Thu Feb 16 10:31:40 2023 -0600

    update error messages

commit 7d21b55
Author: Olivier Thornton <[email protected]>
Date:   Thu Feb 16 10:16:43 2023 -0600

    error handling in deleting dir

commit d1383ce
Author: Olivier Thornton <[email protected]>
Date:   Thu Feb 16 09:53:03 2023 -0600

    handle cannot read directory error

commit 4747338
Author: Olivier Thornton <[email protected]>
Date:   Thu Feb 16 09:52:47 2023 -0600

    handle cannot open file error

commit 462f48f
Author: Olivier Thornton <[email protected]>
Date:   Thu Feb 16 09:41:06 2023 -0600

    error handling for parsing number of passes

commit d4b7e28
Author: Olivier Thornton <[email protected]>
Date:   Thu Feb 16 08:42:41 2023 -0600

    really fix subtract with overflow

commit f73fcd8
Author: Olivier Thornton <[email protected]>
Date:   Wed Feb 15 11:35:00 2023 -0600

    remove unnecessary nested if statement

commit 91dc2fd
Author: Olivier Thornton <[email protected]>
Date:   Wed Feb 15 11:30:45 2023 -0600

    update constants to pull some values from Cargo.toml

commit d17e44e
Author: Olivier Thornton <[email protected]>
Date:   Wed Feb 15 11:30:31 2023 -0600

    fix subtract with overflow

    Fix a bug where if passed a single argument that was invalid, the program would attempt to subtract from the args to get a possible number of passes, resulting in overflow.
  • Loading branch information
Olivier Thornton committed Feb 16, 2023
1 parent e5b2ff4 commit 64f2665
Show file tree
Hide file tree
Showing 13 changed files with 212 additions and 118 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "secure_remove"
version = "2.2.2"
version = "2.2.3"
edition = "2021"
authors = ["Olivier Thornton <[email protected]>"]
description = "Securely remove files and directories"
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@ cargo install --path Secure-Remove

The simplest scheme of using srm is `srm [Options] [Target(s)]`.

The functions are very similar to what you can do with regular `rm`, except (for now) you cannot use wildcards inside of a path.
The functions are very similar to what you can do with regular `rm`, except (for now) you cannot use wildcards inside of a path on Windows.

So `srm ./*` would be okay, whereas `srm ./*.txt` would **not** be okay.
So `srm ./*` would be okay, whereas `srm .\*.txt` would **not** be okay.

However, because of the way that bash and zsh auto expand wildcards, on Linux and Mac `srm ./*.txt` is perfectly fine to use.

Other functions you can see by running `srm --help`.

Expand Down
12 changes: 7 additions & 5 deletions src/config/constants.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
pub const DEBUG: bool = false;
const VERSION: &str = "2.2.2";
const AUTHOR: &str = "Olivier Thornton";
const VERSION: &str = env!("CARGO_PKG_VERSION");
const AUTHOR: &str = env!("CARGO_PKG_AUTHORS");
const LICENSE: &str = "GPLV3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.";

pub fn version() {
println!("srm v{}", VERSION);
println!("Secure Remove v{}", VERSION);
println!("License {}", LICENSE);
println!("This is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.");
println!("\nWritten by {}.", AUTHOR);
}

pub fn help() {
println!("Usage: srm [OPTION]... FILE...");
println!("Usage: srm [OPTION]... FILE(s)...");
println!("Securely remove files or directories.\n");
println!(" -r, --recursive\tremove directories and their contents recursively");
println!(" -p, --passes\t\tset the number of passes (default: 10)");
println!(" -p, --passes\t\tset the number of passes (default: 40)");
println!(" -v, --verbose\t\texplain what is being done");
println!(" --help\t\tdisplay this help and exit");
println!(" --version\t\toutput version information and exit");
println!("\nBy default, srm does not remove directories. Use the --recursive (-r)");
println!("option to remove each listed directory, too, along with all of its contents.")
}
60 changes: 39 additions & 21 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use crate::{
config::constants,
util::{delete_all::delete_all, delete_folder::delete_folder, shred_file::shred_file},
shred::{delete_all::delete_all, delete_folder::delete_folder, shred_file::shred_file},
util::funcs,
};
use std::{fs, path::Path};

mod config;
mod shred;
mod util;

fn main() {
fn main() -> Result<(), std::io::Error> {
// get passed arguments
let args: Vec<String> = std::env::args().collect();

Expand Down Expand Up @@ -36,17 +38,17 @@ fn main() {
}

// check if the argument is a path
let (exists, is_dir) = (Path::new(arg).exists(), Path::new(arg).is_dir());
let exists = Path::new(arg).exists();
if arg == "*" || arg == "./*" || arg == ".\\*" {
paths.push(arg.to_string());
continue;
} else if exists || is_dir {
} else if exists {
paths.push(arg.to_string());
} else {
match arg.as_str() {
"-r" | "--recursive" => recursive = true,
"-v" | "--verbose" => verbose = true,
"-p" | "--passes" => passes = args[counter + 1].parse::<u32>().unwrap(),
"-p" | "--passes" => passes = funcs::parse_passes(args, counter),
"--version" => {
constants::version();
std::process::exit(0);
Expand All @@ -56,15 +58,13 @@ fn main() {
std::process::exit(0);
}
_ => {
if match args[counter - 1].as_str() {
"-p" | "--passes" => continue,
_ => false,
} {
} else if arg.contains('-') && !arg.contains('/') && !arg.contains('\\') {
if counter > 0 && ["-p", "--passes"].contains(&args[counter - 1].as_str()) {
continue;
} else if arg.starts_with('-') && !arg.contains('/') && !arg.contains('\\') {
// if the argument is not a valid argument
println!(
"srm: invalid option '{}'\nTry 'srm --help' for more information.",
arg
"srm: invalid option -- '{}'\nTry 'srm --help' for more information.",
arg.replace('-', "")
);
std::process::exit(0);
} else {
Expand All @@ -88,11 +88,14 @@ fn main() {
println!("srm: missing operand\nTry 'srm --help' for more information.");
std::process::exit(0);
}

for path in paths {
if ["/", "c", "c:", "c:\\", "c:/"].contains(&path.to_lowercase().as_str()) {
println!("'{}': Cannot delete root directory.", path);
continue;
} else if path == "*" || path == "./*" || path == ".\\*" {
// this is only really a thing on windows it seems
// bash auto expands wildcards
delete_all(passes, verbose, recursive);
break;
}
Expand All @@ -101,15 +104,29 @@ fn main() {
if is_file {
shred_file(&path, passes, verbose);
} else if is_dir {
if recursive {
delete_folder(&path, passes, verbose);
if verbose {
print!("Deleting directory '{}' . . .\t\t", path);
}
fs::remove_dir_all(&path).unwrap();
if verbose {
println!("Done");
}
if recursive && !path.ends_with('.') && !path.ends_with("..") {
match delete_folder(&path, passes, verbose) {
Ok(_) => {
if verbose {
print!("Deleting directory '{}' . . .\t\t", path);
}
match fs::remove_dir_all(&path) {
Ok(_) => {
if verbose {
println!("Done");
}
}
Err(e) => {
println!("'{}': {}", path, e);
continue;
}
};
}
Err(e) => {
println!("'{}': {}", path, e);
continue;
}
};
} else {
println!("'{}': Is a directory", path);
}
Expand All @@ -119,4 +136,5 @@ fn main() {
if constants::DEBUG {
println!("- DEBUG - Done.");
}
Ok(())
}
57 changes: 57 additions & 0 deletions src/shred/delete_all.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use crate::shred::{delete_folder::delete_folder, shred_file::shred_file};
use std::{fs, path::Path};

pub fn delete_all(passes: u32, verbose: bool, recursive: bool) {
// get all files and folders in the working directory as a vector of strings
let entries_raw = match fs::read_dir(".") {
Ok(entries) => entries,
Err(_) => {
println!(
"'{}': failed to read directory",
std::env::current_dir().unwrap().to_string_lossy()
);
std::process::exit(0);
}
};
let mut entries: Vec<String> = Vec::new();
for entry in entries_raw {
let temp = entry.unwrap().file_name().to_string_lossy().to_string();
// if the entry does not begin with a dot, add it to the vector
if !temp.starts_with('.') {
entries.push(temp);
}
}

for entry in entries {
let path = Path::new(&entry);
if path.is_file() {
shred_file(&entry, passes, verbose);
} else if path.is_dir() && recursive {
match delete_folder(&entry, passes, verbose) {
Ok(_) => {
if verbose {
print!("Deleting directory '{}' . . .\t\t", entry);
}
// delete the directory
match fs::remove_dir_all(&entry) {
Ok(_) => {
if verbose {
println!("Done");
}
}
Err(e) => {
println!("'{}': {}", entry, e);
continue;
}
};
}
Err(_) => {
println!("'{}': Failed to delete directory", entry);
continue;
}
};
} else if path.is_dir() && !recursive {
println!("srm: cannot remove '{}': Is a directory", entry);
}
}
}
64 changes: 64 additions & 0 deletions src/shred/delete_folder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use crate::{config::constants, shred::shred_file::shred_file};
use std::fs;

pub fn delete_folder(path: &String, passes: u32, verbose: bool) -> Result<(), std::io::Error> {
if constants::DEBUG {
println!("- DEBUG - Deleting folder: '{}'", path);
}

// get all files and folders in the directory
let entries = match fs::read_dir(path) {
Ok(entries) => entries,
Err(_) => {
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
"Failed to read directory",
));
}
};

// loop through the files
for entry in entries {
let object = entry?;

if constants::DEBUG {
println!("- DEBUG - File: {}", &object.file_name().to_string_lossy());
}

if object.file_type()?.is_dir() {
// create the full path to the directory
let new_path = path.to_string() + "/" + &object.file_name().to_string_lossy();

match delete_folder(&new_path, passes, verbose) {
Ok(_) => {
if verbose {
print!("Deleting directory '{}' . . .\t\t", new_path);
}

// delete the directory
match fs::remove_dir_all(&new_path) {
Ok(_) => {
if verbose {
println!("Done");
}
}
Err(e) => {
println!("'{}': {}", new_path, e);
continue;
}
};
}
Err(_) => {
println!("'{}': Failed to delete directory", new_path);
continue;
}
}
} else if object.file_type().unwrap().is_file() {
// create the full path to the file
let new_path = path.to_string() + "/" + &object.file_name().to_string_lossy();

shred_file(&new_path, passes, verbose);
}
}
Ok(())
}
3 changes: 3 additions & 0 deletions src/shred/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod delete_all;
pub mod delete_folder;
pub mod shred_file;
18 changes: 12 additions & 6 deletions src/util/shred_file.rs → src/shred/shred_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,23 @@ pub fn shred_file(path: &String, passes: u32, verbose: bool) {
println!("- DEBUG - Deleting file: '{}'", path);
}

if verbose {
print!("Deleting file '{}' . . .\t\t", path);
}

// open the file for reading and overwriting
let mut file = fs::OpenOptions::new()
let mut file = match fs::OpenOptions::new()
.read(true)
.write(true)
.append(false)
.open(path)
.unwrap();
{
Ok(file) => file,
Err(_) => {
println!("'{}': Failed to open file", path);
return;
}
};

if verbose {
print!("Deleting file '{}' . . .\t\t", path);
}

// create a buffer to hold the data
let size = file.metadata().unwrap().len();
Expand Down
31 changes: 0 additions & 31 deletions src/util/delete_all.rs

This file was deleted.

Loading

0 comments on commit 64f2665

Please sign in to comment.