diff options
-rw-r--r-- | src/fsentry.rs | 35 | ||||
-rw-r--r-- | src/fsiter.rs | 23 | ||||
-rw-r--r-- | src/generation.rs | 9 |
3 files changed, 38 insertions, 29 deletions
diff --git a/src/fsentry.rs b/src/fsentry.rs index 9f40fd0..90afd70 100644 --- a/src/fsentry.rs +++ b/src/fsentry.rs @@ -8,6 +8,7 @@ use std::fs::{FileType, Metadata}; use std::os::unix::ffi::OsStringExt; use std::os::unix::fs::FileTypeExt; use std::path::{Path, PathBuf}; +use users::{Groups, Users, UsersCache}; #[cfg(target_os = "linux")] use std::os::linux::fs::MetadataExt; @@ -69,7 +70,11 @@ pub enum FsEntryError { #[allow(clippy::len_without_is_empty)] impl FilesystemEntry { /// Create an `FsEntry` from a file's metadata. - pub fn from_metadata(path: &Path, meta: &Metadata) -> Result<Self, FsEntryError> { + pub fn from_metadata( + path: &Path, + meta: &Metadata, + cache: &mut UsersCache, + ) -> Result<Self, FsEntryError> { let kind = FilesystemKind::from_file_type(meta.file_type()); let symlink_target = if kind == FilesystemKind::Symlink { debug!("reading symlink target for {:?}", path); @@ -82,6 +87,16 @@ impl FilesystemEntry { let uid = meta.st_uid(); let gid = meta.st_gid(); + let user: String = if let Some(user) = cache.get_user_by_uid(uid) { + user.name().to_string_lossy().to_string() + } else { + "".to_string() + }; + let group = if let Some(group) = cache.get_group_by_gid(gid) { + group.name().to_string_lossy().to_string() + } else { + "".to_string() + }; Ok(Self { path: path.to_path_buf().into_os_string().into_vec(), @@ -95,8 +110,8 @@ impl FilesystemEntry { symlink_target, uid, gid, - user: get_username(uid), - group: get_groupname(gid), + user, + group, }) } @@ -152,20 +167,6 @@ impl FilesystemEntry { } } -fn get_username(uid: u32) -> String { - match users::get_user_by_uid(uid) { - None => "".to_string(), - Some(user) => user.name().to_os_string().to_string_lossy().into_owned(), - } -} - -fn get_groupname(gid: u32) -> String { - match users::get_group_by_gid(gid) { - None => "".to_string(), - Some(group) => group.name().to_os_string().to_string_lossy().into_owned(), - } -} - /// Different types of file system entries. #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] pub enum FilesystemKind { diff --git a/src/fsiter.rs b/src/fsiter.rs index 2747cce..8b231c1 100644 --- a/src/fsiter.rs +++ b/src/fsiter.rs @@ -1,8 +1,9 @@ //! Iterate over directory tree. use crate::fsentry::{FilesystemEntry, FsEntryError}; -use log::{debug, warn}; +use log::warn; use std::path::{Path, PathBuf}; +use users::UsersCache; use walkdir::{DirEntry, IntoIter, WalkDir}; /// Filesystem entry along with additional info about it. @@ -56,6 +57,7 @@ impl Iterator for FsIterator { /// Cachedir-aware adaptor for WalkDir: it skips the contents of dirs that contain CACHEDIR.TAG, /// but still yields entries for the dir and the tag themselves. struct SkipCachedirs { + cache: UsersCache, iter: IntoIter, exclude_cache_tag_directories: bool, // This is the last tag we've found. `next()` will yield it before asking `iter` for more @@ -66,6 +68,7 @@ struct SkipCachedirs { impl SkipCachedirs { fn new(iter: IntoIter, exclude_cache_tag_directories: bool) -> Self { Self { + cache: UsersCache::new(), iter, exclude_cache_tag_directories, cachedir_tag: None, @@ -109,7 +112,7 @@ impl SkipCachedirs { if content == CACHEDIR_TAG { self.iter.skip_current_dir(); - self.cachedir_tag = Some(new_entry(&tag_path, true)); + self.cachedir_tag = Some(new_entry(&tag_path, true, &mut self.cache)); } } } @@ -120,22 +123,26 @@ impl Iterator for SkipCachedirs { fn next(&mut self) -> Option<Self::Item> { self.cachedir_tag.take().or_else(|| { let next = self.iter.next(); - debug!("walkdir found: {:?}", next); + // debug!("walkdir found: {:?}", next); match next { None => None, Some(Err(err)) => Some(Err(FsIterError::WalkDir(err))), Some(Ok(entry)) => { self.try_enqueue_cachedir_tag(&entry); - Some(new_entry(entry.path(), false)) + Some(new_entry(entry.path(), false, &mut self.cache)) } } }) } } -fn new_entry(path: &Path, is_cachedir_tag: bool) -> Result<AnnotatedFsEntry, FsIterError> { +fn new_entry( + path: &Path, + is_cachedir_tag: bool, + cache: &mut UsersCache, +) -> Result<AnnotatedFsEntry, FsIterError> { let meta = std::fs::symlink_metadata(path); - debug!("metadata for {:?}: {:?}", path, meta); + // debug!("metadata for {:?}: {:?}", path, meta); let meta = match meta { Ok(meta) => meta, Err(err) => { @@ -143,8 +150,8 @@ fn new_entry(path: &Path, is_cachedir_tag: bool) -> Result<AnnotatedFsEntry, FsI return Err(FsIterError::Metadata(path.to_path_buf(), err)); } }; - let entry = FilesystemEntry::from_metadata(path, &meta)?; - debug!("FileSystemEntry for {:?}: {:?}", path, entry); + let entry = FilesystemEntry::from_metadata(path, &meta, cache)?; + // debug!("FileSystemEntry for {:?}: {:?}", path, entry); let annotated = AnnotatedFsEntry { inner: entry, is_cachedir_tag, diff --git a/src/generation.rs b/src/generation.rs index 3950a0c..05163be 100644 --- a/src/generation.rs +++ b/src/generation.rs @@ -446,16 +446,17 @@ mod test { let tag_path2 = Path::new("/another_dir/a_tag"); let mut gen = NascentGeneration::create(&dbfile).unwrap(); + let mut cache = users::UsersCache::new(); gen.insert( - FilesystemEntry::from_metadata(nontag_path1, &metadata).unwrap(), + FilesystemEntry::from_metadata(nontag_path1, &metadata, &mut cache).unwrap(), &[], Reason::IsNew, false, ) .unwrap(); gen.insert( - FilesystemEntry::from_metadata(tag_path1, &metadata).unwrap(), + FilesystemEntry::from_metadata(tag_path1, &metadata, &mut cache).unwrap(), &[], Reason::IsNew, true, @@ -464,13 +465,13 @@ mod test { let entries = vec![ FsEntryBackupOutcome { - entry: FilesystemEntry::from_metadata(nontag_path2, &metadata).unwrap(), + entry: FilesystemEntry::from_metadata(nontag_path2, &metadata, &mut cache).unwrap(), ids: vec![], reason: Reason::IsNew, is_cachedir_tag: false, }, FsEntryBackupOutcome { - entry: FilesystemEntry::from_metadata(tag_path2, &metadata).unwrap(), + entry: FilesystemEntry::from_metadata(tag_path2, &metadata, &mut cache).unwrap(), ids: vec![], reason: Reason::IsNew, is_cachedir_tag: true, |