|
71 | 71 |
|
72 | 72 | use std::io::prelude::*;
|
73 | 73 |
|
74 |
| -use embedded_sdmmc::{Error as EsError, RawDirectory, RawVolume, VolumeIdx, VolumeManager}; |
| 74 | +use embedded_sdmmc::{ |
| 75 | + Error as EsError, RawDirectory, RawVolume, ShortFileName, VolumeIdx, VolumeManager, |
| 76 | +}; |
75 | 77 |
|
76 | 78 | use crate::linux::{Clock, LinuxBlockDevice};
|
77 | 79 |
|
@@ -200,6 +202,7 @@ impl Context {
|
200 | 202 | println!("\t<volume>: -> change volume/partition");
|
201 | 203 | println!("\tstat -> print volume manager status");
|
202 | 204 | println!("\tdir [<path>] -> do a directory listing");
|
| 205 | + println!("\ttree [<path>] -> do a recursive directory listing"); |
203 | 206 | println!("\tcd .. -> go up a level");
|
204 | 207 | println!("\tcd <path> -> change into directory <path>");
|
205 | 208 | println!("\tcat <path> -> print a text file");
|
@@ -235,6 +238,54 @@ impl Context {
|
235 | 238 | Ok(())
|
236 | 239 | }
|
237 | 240 |
|
| 241 | + /// Print a recursive directory listing for the given path |
| 242 | + fn tree(&mut self, path: &Path) -> Result<(), Error> { |
| 243 | + println!("Directory listing of {:?}", path); |
| 244 | + let dir = self.resolve_existing_directory(path)?; |
| 245 | + // tree_dir will close this directory, always |
| 246 | + self.tree_dir(dir) |
| 247 | + } |
| 248 | + |
| 249 | + /// Print a recursive directory listing for the given open directory. |
| 250 | + /// |
| 251 | + /// Will close the given directory. |
| 252 | + fn tree_dir(&mut self, dir: RawDirectory) -> Result<(), Error> { |
| 253 | + let mut dir = dir.to_directory(&mut self.volume_mgr); |
| 254 | + let mut children = Vec::new(); |
| 255 | + dir.iterate_dir(|entry| { |
| 256 | + println!( |
| 257 | + "{:12} {:9} {} {} {:08X?} {:?}", |
| 258 | + entry.name, entry.size, entry.ctime, entry.mtime, entry.cluster, entry.attributes |
| 259 | + ); |
| 260 | + if entry.attributes.is_directory() |
| 261 | + && entry.name != ShortFileName::this_dir() |
| 262 | + && entry.name != ShortFileName::parent_dir() |
| 263 | + { |
| 264 | + children.push(entry.name.clone()); |
| 265 | + } |
| 266 | + })?; |
| 267 | + // Be sure to close this, no matter what happens |
| 268 | + let dir = dir.to_raw_directory(); |
| 269 | + for child in children { |
| 270 | + println!("Entering {}", child); |
| 271 | + let child_dir = match self.volume_mgr.open_dir(dir, &child) { |
| 272 | + Ok(child_dir) => child_dir, |
| 273 | + Err(e) => { |
| 274 | + self.volume_mgr.close_dir(dir).expect("close open dir"); |
| 275 | + return Err(e); |
| 276 | + } |
| 277 | + }; |
| 278 | + let result = self.tree_dir(child_dir); |
| 279 | + println!("Returning from {}", child); |
| 280 | + if let Err(e) = result { |
| 281 | + self.volume_mgr.close_dir(dir).expect("close open dir"); |
| 282 | + return Err(e); |
| 283 | + } |
| 284 | + } |
| 285 | + self.volume_mgr.close_dir(dir).expect("close open dir"); |
| 286 | + Ok(()) |
| 287 | + } |
| 288 | + |
238 | 289 | /// Change into `<dir>`
|
239 | 290 | ///
|
240 | 291 | /// * An arg of `..` goes up one level
|
@@ -346,6 +397,10 @@ impl Context {
|
346 | 397 | self.dir(Path::new("."))?;
|
347 | 398 | } else if let Some(path) = line.strip_prefix("dir ") {
|
348 | 399 | self.dir(Path::new(path.trim()))?;
|
| 400 | + } else if line == "tree" { |
| 401 | + self.tree(Path::new("."))?; |
| 402 | + } else if let Some(path) = line.strip_prefix("tree ") { |
| 403 | + self.tree(Path::new(path.trim()))?; |
349 | 404 | } else if line == "stat" {
|
350 | 405 | self.stat()?;
|
351 | 406 | } else if let Some(path) = line.strip_prefix("cd ") {
|
|
0 commit comments