69
69
//! | `B:/BACKUP.000/NAMES.CSV` | `B:` | Yes | `[BACKUP.000]` | `NAMES.CSV` | `B:/BACKUP.000/NAMES.CSV` |
70
70
//! | `B:../BACKUP.000/NAMES.CSV` | `B:` | No | `[.., BACKUP.000]` | `NAMES.CSV` | `B:/BACKUP.000/NAMES.CSV` |
71
71
72
- use std:: io:: prelude:: * ;
72
+ use std:: { cell :: RefCell , io:: prelude:: * } ;
73
73
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 > ;
77
78
78
79
use crate :: linux:: { Clock , LinuxBlockDevice } ;
79
80
@@ -182,21 +183,21 @@ struct VolumeState {
182
183
}
183
184
184
185
struct 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 ] > ,
187
188
current_volume : usize ,
188
189
}
189
190
190
191
impl Context {
191
192
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 {
193
194
return vec ! [ ] ;
194
195
} ;
195
196
s. path . clone ( )
196
197
}
197
198
198
199
/// Print some help text
199
- fn help ( & mut self ) -> Result < ( ) , Error > {
200
+ fn help ( & self ) -> Result < ( ) , Error > {
200
201
println ! ( "Commands:" ) ;
201
202
println ! ( "\t help -> this help text" ) ;
202
203
println ! ( "\t <volume>: -> change volume/partition" ) ;
@@ -219,16 +220,15 @@ impl Context {
219
220
}
220
221
221
222
/// Print volume manager status
222
- fn stat ( & mut self ) -> Result < ( ) , Error > {
223
+ fn stat ( & self ) -> Result < ( ) , Error > {
223
224
println ! ( "Status:\n {:#?}" , self . volume_mgr) ;
224
225
Ok ( ( ) )
225
226
}
226
227
227
228
/// Print a directory listing
228
- fn dir ( & mut self , path : & Path ) -> Result < ( ) , Error > {
229
+ fn dir ( & self , path : & Path ) -> Result < ( ) , Error > {
229
230
println ! ( "Directory listing of {:?}" , path) ;
230
231
let dir = self . resolve_existing_directory ( path) ?;
231
- let dir = dir. to_directory ( & mut self . volume_mgr ) ;
232
232
dir. iterate_dir ( |entry| {
233
233
if !entry. attributes . is_volume ( ) && !entry. attributes . is_lfn ( ) {
234
234
println ! (
@@ -246,7 +246,7 @@ impl Context {
246
246
}
247
247
248
248
/// 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 > {
250
250
println ! ( "Directory listing of {:?}" , path) ;
251
251
let dir = self . resolve_existing_directory ( path) ?;
252
252
// tree_dir will close this directory, always
@@ -256,8 +256,7 @@ impl Context {
256
256
/// Print a recursive directory listing for the given open directory.
257
257
///
258
258
/// 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 > {
261
260
let mut children = Vec :: new ( ) ;
262
261
dir. iterate_dir ( |entry| {
263
262
println ! (
@@ -271,25 +270,20 @@ impl Context {
271
270
children. push ( entry. name . clone ( ) ) ;
272
271
}
273
272
} ) ?;
274
- // Be sure to close this, no matter what happens
275
- let dir = dir. to_raw_directory ( ) ;
276
273
for child in children {
277
274
println ! ( "Entering {}" , child) ;
278
- let child_dir = match self . volume_mgr . open_dir ( dir , & child) {
275
+ let child_dir = match dir . open_dir ( & child) {
279
276
Ok ( child_dir) => child_dir,
280
277
Err ( e) => {
281
- self . volume_mgr . close_dir ( dir) . expect ( "close open dir" ) ;
282
278
return Err ( e) ;
283
279
}
284
280
} ;
285
281
let result = self . tree_dir ( child_dir) ;
286
282
println ! ( "Returning from {}" , child) ;
287
283
if let Err ( e) = result {
288
- self . volume_mgr . close_dir ( dir) . expect ( "close open dir" ) ;
289
284
return Err ( e) ;
290
285
}
291
286
}
292
- self . volume_mgr . close_dir ( dir) . expect ( "close open dir" ) ;
293
287
Ok ( ( ) )
294
288
}
295
289
@@ -300,17 +294,17 @@ impl Context {
300
294
/// sub-folder, starting from the current directory on the current volume
301
295
/// * An absolute path like `B:/FOO` changes the CWD on Volume 1 to path
302
296
/// `/FOO`
303
- fn cd ( & mut self , full_path : & Path ) -> Result < ( ) , Error > {
297
+ fn cd ( & self , full_path : & Path ) -> Result < ( ) , Error > {
304
298
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 {
308
302
return Err ( Error :: NoSuchVolume ) ;
309
303
} ;
310
304
self . volume_mgr
311
305
. close_dir ( s. directory )
312
306
. expect ( "close open dir" ) ;
313
- s. directory = d;
307
+ s. directory = d. to_raw_directory ( ) ;
314
308
if full_path. is_absolute ( ) {
315
309
s. path . clear ( ) ;
316
310
}
@@ -327,9 +321,8 @@ impl Context {
327
321
}
328
322
329
323
/// print a text file
330
- fn cat ( & mut self , filename : & Path ) -> Result < ( ) , Error > {
324
+ fn cat ( & self , filename : & Path ) -> Result < ( ) , Error > {
331
325
let ( dir, filename) = self . resolve_filename ( filename) ?;
332
- let dir = dir. to_directory ( & mut self . volume_mgr ) ;
333
326
let f = dir. open_file_in_dir ( filename, embedded_sdmmc:: Mode :: ReadOnly ) ?;
334
327
let mut data = Vec :: new ( ) ;
335
328
while !f. is_eof ( ) {
@@ -348,9 +341,8 @@ impl Context {
348
341
}
349
342
350
343
/// print a binary file
351
- fn hexdump ( & mut self , filename : & Path ) -> Result < ( ) , Error > {
344
+ fn hexdump ( & self , filename : & Path ) -> Result < ( ) , Error > {
352
345
let ( dir, filename) = self . resolve_filename ( filename) ?;
353
- let dir = dir. to_directory ( & mut self . volume_mgr ) ;
354
346
let f = dir. open_file_in_dir ( filename, embedded_sdmmc:: Mode :: ReadOnly ) ?;
355
347
let mut data = Vec :: new ( ) ;
356
348
while !f. is_eof ( ) {
@@ -385,9 +377,8 @@ impl Context {
385
377
}
386
378
387
379
/// create a directory
388
- fn mkdir ( & mut self , dir_name : & Path ) -> Result < ( ) , Error > {
380
+ fn mkdir ( & self , dir_name : & Path ) -> Result < ( ) , Error > {
389
381
let ( dir, filename) = self . resolve_filename ( dir_name) ?;
390
- let dir = dir. to_directory ( & mut self . volume_mgr ) ;
391
382
dir. make_dir_in_dir ( filename)
392
383
}
393
384
@@ -435,11 +426,10 @@ impl Context {
435
426
/// * Relative names, like `../SOMEDIR` or `./SOMEDIR`, traverse
436
427
/// starting at the current volume and directory.
437
428
/// * 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)
443
433
}
444
434
445
435
/// Either get the volume from the path, or pick the current volume.
@@ -464,33 +454,30 @@ impl Context {
464
454
/// * Relative names, like `../SOMEDIR/SOMEFILE` or `./SOMEDIR/SOMEFILE`, traverse
465
455
/// starting at the current volume and directory.
466
456
/// * 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 ,
469
459
full_path : & ' path Path ,
470
- ) -> Result < ( RawDirectory , & ' path str ) , Error > {
460
+ ) -> Result < ( Directory < ' a > , & ' path str ) , Error > {
471
461
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 {
473
463
return Err ( Error :: NoSuchVolume ) ;
474
464
} ;
475
465
let mut work_dir = if full_path. is_absolute ( ) {
476
466
// relative to root
477
467
self . volume_mgr
478
468
. open_root_dir ( s. volume ) ?
479
- . to_directory ( & mut self . volume_mgr )
469
+ . to_directory ( & self . volume_mgr )
480
470
} else {
481
471
// relative to CWD
482
472
self . volume_mgr
483
473
. open_dir ( s. directory , "." ) ?
484
- . to_directory ( & mut self . volume_mgr )
474
+ . to_directory ( & self . volume_mgr )
485
475
} ;
486
476
487
477
for fragment in full_path. iterate_dirs ( ) {
488
478
work_dir. change_dir ( fragment) ?;
489
479
}
490
- Ok ( (
491
- work_dir. to_raw_directory ( ) ,
492
- full_path. basename ( ) . unwrap_or ( "." ) ,
493
- ) )
480
+ Ok ( ( work_dir, full_path. basename ( ) . unwrap_or ( "." ) ) )
494
481
}
495
482
496
483
/// Convert a volume index to a letter
@@ -507,7 +494,7 @@ impl Context {
507
494
508
495
impl Drop for Context {
509
496
fn drop ( & mut self ) {
510
- for v in self . volumes . iter_mut ( ) {
497
+ for v in self . volumes . borrow_mut ( ) . iter_mut ( ) {
511
498
if let Some ( v) = v {
512
499
println ! ( "Closing directory {:?}" , v. directory) ;
513
500
self . volume_mgr
@@ -534,7 +521,7 @@ fn main() -> Result<(), Error> {
534
521
535
522
let mut ctx = Context {
536
523
volume_mgr : VolumeManager :: new_with_limits ( lbd, Clock , 100 ) ,
537
- volumes : [ None , None , None , None ] ,
524
+ volumes : RefCell :: new ( [ None , None , None , None ] ) ,
538
525
current_volume : 0 ,
539
526
} ;
540
527
@@ -549,7 +536,7 @@ fn main() -> Result<(), Error> {
549
536
) ;
550
537
match ctx. volume_mgr . open_root_dir ( volume) {
551
538
Ok ( root_dir) => {
552
- ctx. volumes [ volume_no] = Some ( VolumeState {
539
+ ctx. volumes . borrow_mut ( ) [ volume_no] = Some ( VolumeState {
553
540
directory : root_dir,
554
541
volume,
555
542
path : vec ! [ ] ,
0 commit comments