summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2018-10-01 17:48:34 +0300
committerLars Wirzenius <liw@liw.fi>2018-10-01 17:48:34 +0300
commit598bcdd90e38fc170c8b85ea713358adfd56ade9 (patch)
tree14b1d02209a28740b238b33cbd7a64d2dd08d6b1
parent72af75c035e6ae459914654c654243b435ace255 (diff)
downloadsummainrs-598bcdd90e38fc170c8b85ea713358adfd56ade9.tar.gz
Change: restructure a bit
-rw-r--r--src/fswalk.rs18
-rw-r--r--src/main.rs125
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<Ordering> {
- 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<Entry>,
- dirs: Vec<Entry>,
+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<Entry> {
- 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)
}