6969//! | `B:/BACKUP.000/NAMES.CSV` | `B:` | Yes | `[BACKUP.000]` | `NAMES.CSV` | `B:/BACKUP.000/NAMES.CSV` |
7070//! | `B:../BACKUP.000/NAMES.CSV` | `B:` | No | `[.., BACKUP.000]` | `NAMES.CSV` | `B:/BACKUP.000/NAMES.CSV` |
7171
72- use std:: io:: prelude:: * ;
72+ use std:: { cell :: RefCell , io:: prelude:: * } ;
7373
74- use embedded_sdmmc:: {
75- Error as EsError , RawDirectory , RawVolume , ShortFileName , VolumeIdx , VolumeManager ,
76- } ;
74+ use embedded_sdmmc:: { Error as EsError , RawDirectory , RawVolume , ShortFileName , VolumeIdx } ;
75+
76+ type VolumeManager = embedded_sdmmc:: VolumeManager < LinuxBlockDevice , Clock , 8 , 8 , 4 > ;
77+ type Directory < ' a > = embedded_sdmmc:: Directory < ' a , LinuxBlockDevice , Clock , 8 , 8 , 4 > ;
7778
7879use crate :: linux:: { Clock , LinuxBlockDevice } ;
7980
@@ -182,21 +183,21 @@ struct VolumeState {
182183}
183184
184185struct Context {
185- volume_mgr : VolumeManager < LinuxBlockDevice , Clock , 8 , 8 , 4 > ,
186- volumes : [ Option < VolumeState > ; 4 ] ,
186+ volume_mgr : VolumeManager ,
187+ volumes : RefCell < [ Option < VolumeState > ; 4 ] > ,
187188 current_volume : usize ,
188189}
189190
190191impl Context {
191192 fn current_path ( & self ) -> Vec < String > {
192- let Some ( s) = & self . volumes [ self . current_volume ] else {
193+ let Some ( s) = & self . volumes . borrow ( ) [ self . current_volume ] else {
193194 return vec ! [ ] ;
194195 } ;
195196 s. path . clone ( )
196197 }
197198
198199 /// Print some help text
199- fn help ( & mut self ) -> Result < ( ) , Error > {
200+ fn help ( & self ) -> Result < ( ) , Error > {
200201 println ! ( "Commands:" ) ;
201202 println ! ( "\t help -> this help text" ) ;
202203 println ! ( "\t <volume>: -> change volume/partition" ) ;
@@ -219,16 +220,15 @@ impl Context {
219220 }
220221
221222 /// Print volume manager status
222- fn stat ( & mut self ) -> Result < ( ) , Error > {
223+ fn stat ( & self ) -> Result < ( ) , Error > {
223224 println ! ( "Status:\n {:#?}" , self . volume_mgr) ;
224225 Ok ( ( ) )
225226 }
226227
227228 /// Print a directory listing
228- fn dir ( & mut self , path : & Path ) -> Result < ( ) , Error > {
229+ fn dir ( & self , path : & Path ) -> Result < ( ) , Error > {
229230 println ! ( "Directory listing of {:?}" , path) ;
230231 let dir = self . resolve_existing_directory ( path) ?;
231- let dir = dir. to_directory ( & mut self . volume_mgr ) ;
232232 dir. iterate_dir ( |entry| {
233233 if !entry. attributes . is_volume ( ) && !entry. attributes . is_lfn ( ) {
234234 println ! (
@@ -246,7 +246,7 @@ impl Context {
246246 }
247247
248248 /// Print a recursive directory listing for the given path
249- fn tree ( & mut self , path : & Path ) -> Result < ( ) , Error > {
249+ fn tree ( & self , path : & Path ) -> Result < ( ) , Error > {
250250 println ! ( "Directory listing of {:?}" , path) ;
251251 let dir = self . resolve_existing_directory ( path) ?;
252252 // tree_dir will close this directory, always
@@ -256,8 +256,7 @@ impl Context {
256256 /// Print a recursive directory listing for the given open directory.
257257 ///
258258 /// Will close the given directory.
259- fn tree_dir ( & mut self , dir : RawDirectory ) -> Result < ( ) , Error > {
260- let dir = dir. to_directory ( & mut self . volume_mgr ) ;
259+ fn tree_dir < ' a > ( & ' a self , dir : Directory < ' a > ) -> Result < ( ) , Error > {
261260 let mut children = Vec :: new ( ) ;
262261 dir. iterate_dir ( |entry| {
263262 println ! (
@@ -271,25 +270,20 @@ impl Context {
271270 children. push ( entry. name . clone ( ) ) ;
272271 }
273272 } ) ?;
274- // Be sure to close this, no matter what happens
275- let dir = dir. to_raw_directory ( ) ;
276273 for child in children {
277274 println ! ( "Entering {}" , child) ;
278- let child_dir = match self . volume_mgr . open_dir ( dir , & child) {
275+ let child_dir = match dir . open_dir ( & child) {
279276 Ok ( child_dir) => child_dir,
280277 Err ( e) => {
281- self . volume_mgr . close_dir ( dir) . expect ( "close open dir" ) ;
282278 return Err ( e) ;
283279 }
284280 } ;
285281 let result = self . tree_dir ( child_dir) ;
286282 println ! ( "Returning from {}" , child) ;
287283 if let Err ( e) = result {
288- self . volume_mgr . close_dir ( dir) . expect ( "close open dir" ) ;
289284 return Err ( e) ;
290285 }
291286 }
292- self . volume_mgr . close_dir ( dir) . expect ( "close open dir" ) ;
293287 Ok ( ( ) )
294288 }
295289
@@ -300,17 +294,17 @@ impl Context {
300294 /// sub-folder, starting from the current directory on the current volume
301295 /// * An absolute path like `B:/FOO` changes the CWD on Volume 1 to path
302296 /// `/FOO`
303- fn cd ( & mut self , full_path : & Path ) -> Result < ( ) , Error > {
297+ fn cd ( & self , full_path : & Path ) -> Result < ( ) , Error > {
304298 let volume_idx = self . resolve_volume ( full_path) ?;
305- let d = self . resolve_existing_directory ( full_path) ?;
306- let Some ( s ) = & mut self . volumes [ volume_idx ] else {
307- self . volume_mgr . close_dir ( d ) . expect ( "close open dir" ) ;
299+ let ( mut d , fragment ) = self . resolve_filename ( full_path) ?;
300+ d . change_dir ( fragment ) ? ;
301+ let Some ( s ) = & mut self . volumes . borrow_mut ( ) [ volume_idx ] else {
308302 return Err ( Error :: NoSuchVolume ) ;
309303 } ;
310304 self . volume_mgr
311305 . close_dir ( s. directory )
312306 . expect ( "close open dir" ) ;
313- s. directory = d;
307+ s. directory = d. to_raw_directory ( ) ;
314308 if full_path. is_absolute ( ) {
315309 s. path . clear ( ) ;
316310 }
@@ -327,9 +321,8 @@ impl Context {
327321 }
328322
329323 /// print a text file
330- fn cat ( & mut self , filename : & Path ) -> Result < ( ) , Error > {
324+ fn cat ( & self , filename : & Path ) -> Result < ( ) , Error > {
331325 let ( dir, filename) = self . resolve_filename ( filename) ?;
332- let dir = dir. to_directory ( & mut self . volume_mgr ) ;
333326 let f = dir. open_file_in_dir ( filename, embedded_sdmmc:: Mode :: ReadOnly ) ?;
334327 let mut data = Vec :: new ( ) ;
335328 while !f. is_eof ( ) {
@@ -348,9 +341,8 @@ impl Context {
348341 }
349342
350343 /// print a binary file
351- fn hexdump ( & mut self , filename : & Path ) -> Result < ( ) , Error > {
344+ fn hexdump ( & self , filename : & Path ) -> Result < ( ) , Error > {
352345 let ( dir, filename) = self . resolve_filename ( filename) ?;
353- let dir = dir. to_directory ( & mut self . volume_mgr ) ;
354346 let f = dir. open_file_in_dir ( filename, embedded_sdmmc:: Mode :: ReadOnly ) ?;
355347 let mut data = Vec :: new ( ) ;
356348 while !f. is_eof ( ) {
@@ -385,9 +377,8 @@ impl Context {
385377 }
386378
387379 /// create a directory
388- fn mkdir ( & mut self , dir_name : & Path ) -> Result < ( ) , Error > {
380+ fn mkdir ( & self , dir_name : & Path ) -> Result < ( ) , Error > {
389381 let ( dir, filename) = self . resolve_filename ( dir_name) ?;
390- let dir = dir. to_directory ( & mut self . volume_mgr ) ;
391382 dir. make_dir_in_dir ( filename)
392383 }
393384
@@ -435,11 +426,10 @@ impl Context {
435426 /// * Relative names, like `../SOMEDIR` or `./SOMEDIR`, traverse
436427 /// starting at the current volume and directory.
437428 /// * Absolute, like `B:/SOMEDIR/OTHERDIR` start at the given volume.
438- fn resolve_existing_directory ( & mut self , full_path : & Path ) -> Result < RawDirectory , Error > {
439- let ( dir, fragment) = self . resolve_filename ( full_path) ?;
440- let mut work_dir = dir. to_directory ( & mut self . volume_mgr ) ;
441- work_dir. change_dir ( fragment) ?;
442- Ok ( work_dir. to_raw_directory ( ) )
429+ fn resolve_existing_directory < ' a > ( & ' a self , full_path : & Path ) -> Result < Directory < ' a > , Error > {
430+ let ( mut dir, fragment) = self . resolve_filename ( full_path) ?;
431+ dir. change_dir ( fragment) ?;
432+ Ok ( dir)
443433 }
444434
445435 /// Either get the volume from the path, or pick the current volume.
@@ -464,33 +454,30 @@ impl Context {
464454 /// * Relative names, like `../SOMEDIR/SOMEFILE` or `./SOMEDIR/SOMEFILE`, traverse
465455 /// starting at the current volume and directory.
466456 /// * Absolute, like `B:/SOMEDIR/SOMEFILE` start at the given volume.
467- fn resolve_filename < ' path > (
468- & mut self ,
457+ fn resolve_filename < ' a , ' path > (
458+ & ' a self ,
469459 full_path : & ' path Path ,
470- ) -> Result < ( RawDirectory , & ' path str ) , Error > {
460+ ) -> Result < ( Directory < ' a > , & ' path str ) , Error > {
471461 let volume_idx = self . resolve_volume ( full_path) ?;
472- let Some ( s) = & mut self . volumes [ volume_idx] else {
462+ let Some ( s) = & self . volumes . borrow ( ) [ volume_idx] else {
473463 return Err ( Error :: NoSuchVolume ) ;
474464 } ;
475465 let mut work_dir = if full_path. is_absolute ( ) {
476466 // relative to root
477467 self . volume_mgr
478468 . open_root_dir ( s. volume ) ?
479- . to_directory ( & mut self . volume_mgr )
469+ . to_directory ( & self . volume_mgr )
480470 } else {
481471 // relative to CWD
482472 self . volume_mgr
483473 . open_dir ( s. directory , "." ) ?
484- . to_directory ( & mut self . volume_mgr )
474+ . to_directory ( & self . volume_mgr )
485475 } ;
486476
487477 for fragment in full_path. iterate_dirs ( ) {
488478 work_dir. change_dir ( fragment) ?;
489479 }
490- Ok ( (
491- work_dir. to_raw_directory ( ) ,
492- full_path. basename ( ) . unwrap_or ( "." ) ,
493- ) )
480+ Ok ( ( work_dir, full_path. basename ( ) . unwrap_or ( "." ) ) )
494481 }
495482
496483 /// Convert a volume index to a letter
@@ -507,7 +494,7 @@ impl Context {
507494
508495impl Drop for Context {
509496 fn drop ( & mut self ) {
510- for v in self . volumes . iter_mut ( ) {
497+ for v in self . volumes . borrow_mut ( ) . iter_mut ( ) {
511498 if let Some ( v) = v {
512499 println ! ( "Closing directory {:?}" , v. directory) ;
513500 self . volume_mgr
@@ -534,7 +521,7 @@ fn main() -> Result<(), Error> {
534521
535522 let mut ctx = Context {
536523 volume_mgr : VolumeManager :: new_with_limits ( lbd, Clock , 100 ) ,
537- volumes : [ None , None , None , None ] ,
524+ volumes : RefCell :: new ( [ None , None , None , None ] ) ,
538525 current_volume : 0 ,
539526 } ;
540527
@@ -549,7 +536,7 @@ fn main() -> Result<(), Error> {
549536 ) ;
550537 match ctx. volume_mgr . open_root_dir ( volume) {
551538 Ok ( root_dir) => {
552- ctx. volumes [ volume_no] = Some ( VolumeState {
539+ ctx. volumes . borrow_mut ( ) [ volume_no] = Some ( VolumeState {
553540 directory : root_dir,
554541 volume,
555542 path : vec ! [ ] ,
0 commit comments