@@ -9,6 +9,7 @@ use clap::{Arg, ArgAction, Command};
99#[ cfg( unix) ]
1010use libc:: S_IWUSR ;
1111use rand:: { Rng , SeedableRng , rngs:: StdRng , seq:: SliceRandom } ;
12+ use std:: cell:: RefCell ;
1213use std:: ffi:: OsString ;
1314use std:: fs:: { self , File , OpenOptions } ;
1415use std:: io:: { self , Read , Seek , SeekFrom , Write } ;
@@ -183,18 +184,18 @@ enum BytesWriter {
183184impl 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
501502fn 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
600603fn 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