From 598bcdd90e38fc170c8b85ea713358adfd56ade9 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Mon, 1 Oct 2018 17:48:34 +0300 Subject: Change: restructure a bit --- src/fswalk.rs | 18 ++++++--- src/main.rs | 125 ++++++---------------------------------------------------- 2 files changed, 24 insertions(+), 119 deletions(-) diff --git a/src/fswalk.rs b/src/fswalk.rs index ac95540..d9ecb87 100644 --- a/src/fswalk.rs +++ b/src/fswalk.rs @@ -1,3 +1,4 @@ +use std::fs; use std::io; use std::path::PathBuf; use std::cmp::Ordering; @@ -6,18 +7,24 @@ use std::cmp::Ordering; #[derive(Debug)] pub struct Entry { path: PathBuf, + meta: fs::Metadata, } impl Entry { - fn new(path: &PathBuf) -> Entry { + fn new(path: &PathBuf, meta: &fs::Metadata) -> Entry { Entry { path: path.clone(), + meta: meta.clone(), } } pub fn path(&self) -> String { self.path.to_string_lossy().to_string() } + + pub fn metadata(&self) -> fs::Metadata { + self.meta.clone() + } } impl Eq for Entry {} @@ -52,7 +59,8 @@ pub struct DirTree { impl DirTree { pub fn new(path: &str) -> DirTree { let mut dt = DirTree::empty(); - dt.add_dir(&PathBuf::from(path)); + let meta = fs::symlink_metadata(path).expect("can't stat dir"); + dt.add_dir(&PathBuf::from(path), &meta); dt } @@ -63,8 +71,8 @@ impl DirTree { } } - fn add_dir(&mut self, path: &PathBuf) { - let entry = Entry::new(path); + fn add_dir(&mut self, path: &PathBuf, meta: &fs::Metadata) { + let entry = Entry::new(path, meta); self.dirs.push(entry); } @@ -74,7 +82,7 @@ impl DirTree { for dir_entry in path.read_dir()? { let dir_entry = dir_entry?; let metadata = dir_entry.metadata()?; - let entry = Entry::new(&dir_entry.path()); + let entry = Entry::new(&dir_entry.path(), &metadata); if metadata.is_dir() { dirs.push(entry); } else { diff --git a/src/main.rs b/src/main.rs index 9dfa59c..c31dd20 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,10 @@ use std::env; -use std::path::PathBuf; use std::io; -use std::cmp::Ordering; +use std::fs; +use std::os::unix::fs::PermissionsExt; + +mod fswalk; +use fswalk::DirTree; // Command line args are names of dirs, recursively list all files and // dirs them @@ -9,125 +12,19 @@ fn main() -> io::Result<()> { for dirname in env::args().skip(1) { let tree = DirTree::new(&dirname); for entry in tree { - println!("{}", entry.path()); + write_info(&entry.path(), &entry.metadata()); } } Ok(()) } -// A filesystem entry: directory, file, symlink, etc -#[derive(Debug)] -struct Entry { - path: PathBuf, -} - -impl Entry { - fn new(path: &PathBuf) -> Entry { - Entry { - path: path.clone(), - } - } - - fn path(&self) -> String { - self.path.to_string_lossy().to_string() - } -} - -impl Eq for Entry {} - -impl PartialEq for Entry { - fn eq(&self, other: &Entry) -> bool { - self.path == other.path - } -} - -impl Ord for Entry { - fn cmp(&self, other: &Entry) -> Ordering { - self.path.cmp(&other.path) - } -} - -impl PartialOrd for Entry { - fn partial_cmp(&self, other: &Entry) -> Option { - Some(self.path.cmp(&other.path)) - } -} - - -// Keep two stacks of Entry values, sorted in ascending order. The -// first stack has non-directories. When we iterate, we return a -// directory, then of its non-dirs, then recurse each of its subdirs. -#[derive(Debug)] -struct DirTree { - entries: Vec, - dirs: Vec, +fn write_info(path: &str, meta: &fs::Metadata) { + println!("{} {}", format_metadata(&meta), path); } -impl DirTree { - fn empty() -> DirTree { - DirTree { - entries: Vec::new(), - dirs: Vec::new(), - } - } - - fn new(path: &str) -> DirTree { - let mut dt = DirTree::empty(); - dt.add_dir(&PathBuf::from(path)); - dt - } - - fn add_dir(&mut self, path: &PathBuf) { - let entry = Entry::new(path); - self.dirs.push(entry); - } - - fn add_entries(&mut self, path: &PathBuf) -> io::Result<()> { - let mut entries = Vec::new(); - let mut dirs = Vec::new(); - for dir_entry in path.read_dir()? { - let dir_entry = dir_entry?; - let metadata = dir_entry.metadata()?; - let entry = Entry::new(&dir_entry.path()); - if metadata.is_dir() { - dirs.push(entry); - } else { - entries.push(entry); - } - } - - entries.sort(); - entries.reverse(); - for e in entries { - self.entries.push(e); - } - - dirs.sort(); - dirs.reverse(); - for e in dirs { - self.dirs.push(e); - } - - Ok(()) - } -} - -impl Iterator for DirTree { - type Item = Entry; - - fn next(&mut self) -> Option { - if let Some(e) = self.entries.pop() { - Some(e) - } else if let Some(e) = self.dirs.pop() { - if let Ok(_) = self.add_entries(&e.path) { - // We ignore any errors from adding entries. Boo. Not - // sure how I'd propagate errors, from a next method. - } - Some(e) - } else { - None - } - } +fn format_metadata(meta: &fs::Metadata) -> String { + let mode = meta.permissions().mode(); + format!("{:06o}", mode) } -- cgit v1.2.1