Fix shred to handle non-UTF-8 filenames

This commit is contained in:
Sylvestre Ledru 2025-08-08 14:45:01 +02:00
parent 1056ebe0d5
commit 0e4ed4d462
2 changed files with 30 additions and 5 deletions

View file

@ -9,6 +9,7 @@ use clap::{Arg, ArgAction, Command};
#[cfg(unix)]
use libc::S_IWUSR;
use rand::{Rng, SeedableRng, rngs::StdRng, seq::SliceRandom};
use std::ffi::OsString;
use std::fs::{self, File, OpenOptions};
use std::io::{self, Read, Seek, Write};
#[cfg(unix)]
@ -297,7 +298,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let zero = matches.get_flag(options::ZERO);
let verbose = matches.get_flag(options::VERBOSE);
for path_str in matches.get_many::<String>(options::FILE).unwrap() {
for path_str in matches.get_many::<OsString>(options::FILE).unwrap() {
show_if_err!(wipe_file(
path_str,
iterations,
@ -396,7 +397,8 @@ pub fn uu_app() -> Command {
.arg(
Arg::new(options::FILE)
.action(ArgAction::Append)
.value_hint(clap::ValueHint::FilePath),
.value_hint(clap::ValueHint::FilePath)
.value_parser(clap::value_parser!(OsString)),
)
}
@ -428,7 +430,7 @@ fn pass_name(pass_type: &PassType) -> String {
#[allow(clippy::too_many_arguments)]
#[allow(clippy::cognitive_complexity)]
fn wipe_file(
path_str: &str,
path_str: &OsString,
n_passes: usize,
remove_method: RemoveMethod,
size: Option<u64>,
@ -605,7 +607,7 @@ fn do_pass(
/// Repeatedly renames the file with strings of decreasing length (most likely all 0s)
/// Return the path of the file after its last renaming or None in case of an error
fn wipe_name(orig_path: &Path, verbose: bool, remove_method: RemoveMethod) -> Option<PathBuf> {
let file_name_len = orig_path.file_name().unwrap().to_str().unwrap().len();
let file_name_len = orig_path.file_name().unwrap().len();
let mut last_path = PathBuf::from(orig_path);
@ -657,7 +659,7 @@ fn wipe_name(orig_path: &Path, verbose: bool, remove_method: RemoveMethod) -> Op
fn do_remove(
path: &Path,
orig_filename: &str,
orig_filename: &OsString,
verbose: bool,
remove_method: RemoveMethod,
) -> Result<(), io::Error> {

View file

@ -316,3 +316,26 @@ fn test_shred_rename_exhaustion() {
assert!(!at.file_exists("test"));
}
#[test]
#[cfg(target_os = "linux")]
fn test_shred_non_utf8_paths() {
use std::fs;
let ts = TestScenario::new(util_name!());
let at = &ts.fixtures;
// Create test file with non-UTF-8 name
at.write("temp.txt", "test content");
#[cfg(unix)]
{
use std::os::unix::ffi::OsStrExt;
let file_name = std::ffi::OsStr::from_bytes(b"test_\xFF\xFE.txt");
fs::rename(at.subdir.join("temp.txt"), at.subdir.join(file_name)).unwrap();
// Test that shred can handle non-UTF-8 filenames
ts.ucmd().arg(file_name).succeeds();
}
}