diff --git a/Cargo.toml b/Cargo.toml index 0df89a6..815cc1b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,7 @@ walkdir = "2" ignore = "0.4" # commands gethostname = "0.2" +users = "0.11" bytesize = "1" clap = { version = "3", features = ["derive"] } rpassword = "5" diff --git a/src/backend/node.rs b/src/backend/node.rs index 9089864..8c8c9dd 100644 --- a/src/backend/node.rs +++ b/src/backend/node.rs @@ -52,10 +52,10 @@ pub struct Metadata { uid: u32, #[serde(default, skip_serializing_if = "is_default")] gid: u32, - #[serde(default, skip_serializing_if = "is_default")] - user: String, - #[serde(default, skip_serializing_if = "is_default")] - group: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + user: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + group: Option, #[serde(default, skip_serializing_if = "is_default")] inode: u64, #[serde(default, skip_serializing_if = "is_default")] diff --git a/src/commands/backup.rs b/src/commands/backup.rs index 00be26e..853e3f3 100644 --- a/src/commands/backup.rs +++ b/src/commands/backup.rs @@ -2,13 +2,14 @@ use gethostname::gethostname; use std::fs::{read_link, File}; use std::io::{BufRead, BufReader}; use std::os::unix::fs::MetadataExt; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use anyhow::{anyhow, Result}; use chrono::{TimeZone, Utc}; use clap::Parser; use ignore::{DirEntry, WalkBuilder}; use path_absolutize::*; +use users::{cache::UsersCache, Groups, Users}; use crate::archiver::{Archiver, Parent}; use crate::backend::DecryptFullBackend; @@ -67,9 +68,15 @@ pub(super) fn execute(opts: Opts, be: &impl DecryptFullBackend) -> Result<()> { wb.add(path); } */ - wb.follow_links(false).hidden(false); + wb.follow_links(false) + .hidden(false) + .sort_by_file_path(Path::cmp); - let nodes = wb.build().map(|entry| map_entry(entry?, opts.with_atime)); + let cache = UsersCache::new(); + + let nodes = wb + .build() + .map(|entry| map_entry(entry?, opts.with_atime, &cache)); for res in nodes { let (path, node, r) = res?; @@ -80,10 +87,17 @@ pub(super) fn execute(opts: Opts, be: &impl DecryptFullBackend) -> Result<()> { Ok(()) } -fn map_entry(entry: DirEntry, with_atime: bool) -> Result<(PathBuf, Node, Option)> { +fn map_entry( + entry: DirEntry, + with_atime: bool, + cache: &UsersCache, +) -> Result<(PathBuf, Node, Option)> { let name = entry.file_name().to_os_string(); let m = entry.metadata()?; + let uid = m.uid(); + let gid = m.gid(); + let meta = Metadata::new( m.len(), m.modified().ok().map(|t| t.into()), @@ -95,10 +109,14 @@ fn map_entry(entry: DirEntry, with_atime: bool) -> Result<(PathBuf, Node, Option }, Some(Utc.timestamp(m.ctime(), m.ctime_nsec().try_into()?).into()), m.mode(), - m.uid(), - m.gid(), - "".to_string(), - "".to_string(), + uid, + gid, + cache + .get_user_by_uid(uid) + .map(|u| u.name().to_str().unwrap().to_string()), + cache + .get_group_by_gid(gid) + .map(|g| g.name().to_str().unwrap().to_string()), m.ino(), m.dev(), m.nlink(),