Skip to content

Commit 2e3a1ad

Browse files
committed
shred: use RefCell to eliminate mut from random source handling
1 parent ceb2551 commit 2e3a1ad

File tree

1 file changed

+19
-24
lines changed

1 file changed

+19
-24
lines changed

src/uu/shred/src/shred.rs

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use clap::{Arg, ArgAction, Command};
99
#[cfg(unix)]
1010
use libc::S_IWUSR;
1111
use rand::{Rng, SeedableRng, rngs::StdRng, seq::SliceRandom};
12+
use std::cell::RefCell;
1213
use std::ffi::OsString;
1314
use std::fs::{self, File, OpenOptions};
1415
use std::io::{self, Read, Seek, SeekFrom, Write};
@@ -183,18 +184,18 @@ enum BytesWriter {
183184
impl BytesWriter {
184185
fn from_pass_type(
185186
pass: &PassType,
186-
random_source: Option<&mut File>,
187+
random_source: Option<&RefCell<File>>,
187188
) -> Result<Self, io::Error> {
188189
match pass {
189190
PassType::Random => match random_source {
190191
None => Ok(Self::Random {
191192
rng: StdRng::from_os_rng(),
192193
buffer: [0; BLOCK_SIZE],
193194
}),
194-
Some(file) => {
195+
Some(file_cell) => {
195196
// We need to create a new file handle that shares the position
196197
// For now, we'll duplicate the file descriptor to maintain position
197-
let new_file = file.try_clone()?;
198+
let new_file = file_cell.borrow_mut().try_clone()?;
198199
Ok(Self::RandomFile {
199200
rng_file: new_file,
200201
buffer: [0; BLOCK_SIZE],
@@ -265,13 +266,13 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
265266
None => unreachable!(),
266267
};
267268

268-
let mut random_source = match matches.get_one::<String>(options::RANDOM_SOURCE) {
269-
Some(filepath) => Some(File::open(filepath).map_err(|_| {
269+
let random_source = match matches.get_one::<String>(options::RANDOM_SOURCE) {
270+
Some(filepath) => Some(RefCell::new(File::open(filepath).map_err(|_| {
270271
USimpleError::new(
271272
1,
272273
translate!("shred-cannot-open-random-source", "source" => filepath.quote()),
273274
)
274-
})?),
275+
})?)),
275276
None => None,
276277
};
277278

@@ -308,7 +309,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
308309
size,
309310
exact,
310311
zero,
311-
random_source.as_mut(),
312+
random_source.as_ref(),
312313
verbose,
313314
force,
314315
));
@@ -500,20 +501,22 @@ fn generate_patterns_with_middle_randoms(
500501
/// Create test-compatible pass sequence using deterministic seeding
501502
fn create_test_compatible_sequence(
502503
num_passes: usize,
503-
random_source: Option<&mut File>,
504+
random_source: Option<&RefCell<File>>,
504505
) -> UResult<Vec<PassType>> {
505506
if num_passes == 0 {
506507
return Ok(Vec::new());
507508
}
508509

509510
// For the specific test case with 'U'-filled random source,
510511
// return the exact expected sequence based on standard seeding algorithm
511-
if let Some(file) = random_source {
512+
if let Some(file_cell) = random_source {
512513
// Check if this is the 'U'-filled random source used by test compatibility
513-
file.seek(SeekFrom::Start(0))
514+
file_cell
515+
.borrow_mut()
516+
.seek(SeekFrom::Start(0))
514517
.map_err_context(|| translate!("shred-failed-to-seek-file"))?;
515518
let mut buffer = [0u8; 1024];
516-
if let Ok(bytes_read) = file.read(&mut buffer) {
519+
if let Ok(bytes_read) = file_cell.borrow_mut().read(&mut buffer) {
517520
if bytes_read > 0 && buffer[..bytes_read].iter().all(|&b| b == 0x55) {
518521
// This is the test scenario - replicate exact algorithm
519522
let test_patterns = vec![
@@ -599,7 +602,7 @@ fn create_standard_pass_sequence(num_passes: usize) -> UResult<Vec<PassType>> {
599602
/// Create compatible pass sequence using the standard algorithm
600603
fn create_compatible_sequence(
601604
num_passes: usize,
602-
random_source: Option<&mut File>,
605+
random_source: Option<&RefCell<File>>,
603606
) -> UResult<Vec<PassType>> {
604607
if random_source.is_some() {
605608
// For deterministic behavior with random source file, use hardcoded sequence
@@ -619,7 +622,7 @@ fn wipe_file(
619622
size: Option<u64>,
620623
exact: bool,
621624
zero: bool,
622-
mut random_source: Option<&mut File>,
625+
random_source: Option<&RefCell<File>>,
623626
verbose: bool,
624627
force: bool,
625628
) -> UResult<()> {
@@ -674,8 +677,7 @@ fn wipe_file(
674677
} else {
675678
// Use compatible sequence when using deterministic random source
676679
if random_source.is_some() {
677-
pass_sequence =
678-
create_compatible_sequence(n_passes, random_source.as_deref_mut())?;
680+
pass_sequence = create_compatible_sequence(n_passes, random_source)?;
679681
} else {
680682
pass_sequence = create_standard_pass_sequence(n_passes)?;
681683
}
@@ -713,14 +715,7 @@ fn wipe_file(
713715
// size is an optional argument for exactly how many bytes we want to shred
714716
// Ignore failed writes; just keep trying
715717
show_if_err!(
716-
do_pass(
717-
&mut file,
718-
&pass_type,
719-
exact,
720-
random_source.as_deref_mut(),
721-
size
722-
)
723-
.map_err_context(|| {
718+
do_pass(&mut file, &pass_type, exact, random_source, size).map_err_context(|| {
724719
translate!("shred-file-write-pass-failed", "file" => path.maybe_quote())
725720
})
726721
);
@@ -755,7 +750,7 @@ fn do_pass(
755750
file: &mut File,
756751
pass_type: &PassType,
757752
exact: bool,
758-
random_source: Option<&mut File>,
753+
random_source: Option<&RefCell<File>>,
759754
file_size: u64,
760755
) -> Result<(), io::Error> {
761756
// We might be at the end of the file due to a previous iteration, so rewind.

0 commit comments

Comments
 (0)