diff --git a/Cargo.lock b/Cargo.lock index f7136e1..6f03f10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -316,6 +316,40 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38fcc2979eff34a4b84e1cf9a1e3da42a7d44b3b690a40cdcb23e3d556cfb2e5" +[[package]] +name = "cached" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b195e4fbc4b6862bbd065b991a34750399c119797efff72492f28a5864de8700" +dependencies = [ + "cached_proc_macro", + "cached_proc_macro_types", + "hashbrown 0.13.2", + "instant", + "once_cell", + "thiserror", + "tokio", +] + +[[package]] +name = "cached_proc_macro" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b48814962d2fd604c50d2b9433c2a41a0ab567779ee2c02f7fba6eca1221f082" +dependencies = [ + "cached_proc_macro_types", + "darling 0.14.4", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "cached_proc_macro_types" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a4f925191b4367301851c6d99b09890311d74b0d43f274c0b34c86d308a3663" + [[package]] name = "cachedir" version = "0.3.0" @@ -705,14 +739,38 @@ dependencies = [ "cipher 0.3.0", ] +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + [[package]] name = "darling" version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0558d22a7b463ed0241e993f76f09f30b126687447751a8638587b864e4b3944" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.1", + "darling_macro 0.20.1", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", ] [[package]] @@ -729,13 +787,24 @@ dependencies = [ "syn 2.0.18", ] +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core 0.14.4", + "quote", + "syn 1.0.109", +] + [[package]] name = "darling_macro" version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a" dependencies = [ - "darling_core", + "darling_core 0.20.1", "quote", "syn 2.0.18", ] @@ -1202,6 +1271,12 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" + [[package]] name = "heck" version = "0.4.1" @@ -1387,7 +1462,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", "serde", ] @@ -2304,7 +2379,6 @@ dependencies = [ "tracing-appender", "tracing-error", "tracing-subscriber", - "users", "walkdir", "xattr 1.0.0", "zstd", @@ -2320,6 +2394,7 @@ dependencies = [ "binrw", "bytes", "bytesize", + "cached", "cachedir", "chrono", "clap", @@ -2367,7 +2442,6 @@ dependencies = [ "sha2", "thiserror", "url", - "users", "walkdir", "xattr 1.0.0", "zstd", @@ -2662,7 +2736,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edc7d5d3932fb12ce722ee5e64dd38c504efba37567f0c402f6ca728c3b8b070" dependencies = [ - "darling", + "darling 0.20.1", "proc-macro2", "quote", "syn 2.0.18", @@ -3010,11 +3084,24 @@ dependencies = [ "libc", "mio", "num_cpus", + "parking_lot", "pin-project-lite", "socket2", + "tokio-macros", "windows-sys 0.48.0", ] +[[package]] +name = "tokio-macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + [[package]] name = "tokio-rustls" version = "0.24.0" @@ -3251,16 +3338,6 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9" -[[package]] -name = "users" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032" -dependencies = [ - "libc", - "log", -] - [[package]] name = "utf8parse" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index e24be80..03fe5fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -132,7 +132,6 @@ toml = { workspace = true } [target.'cfg(not(windows))'.dependencies] sha2 = { version = "0.10", features = ["asm"] } -users = "0.11" libc = "0.2.146" [target.'cfg(windows)'.dependencies] @@ -189,6 +188,7 @@ serde-aux = "4" # local backend walkdir = "2" ignore = "0.4" +cached = {version = "0.44", default-features = false, features = ["proc_macro"]} nix = "0.26" filetime = "0.2" aho-corasick = "1" diff --git a/crates/rustic_core/Cargo.toml b/crates/rustic_core/Cargo.toml index eb209e5..f66a2c7 100644 --- a/crates/rustic_core/Cargo.toml +++ b/crates/rustic_core/Cargo.toml @@ -72,6 +72,7 @@ enum-map-derive = { workspace = true } # local backend walkdir = { workspace = true } ignore = { workspace = true } +cached = { workspace = true } nix = { workspace = true } filetime = { workspace = true } aho-corasick = { workspace = true } @@ -105,7 +106,6 @@ humantime = { workspace = true } [target.'cfg(not(windows))'.dependencies] sha2 = { version = "0.10", features = ["asm"] } -users = "0.11" [target.'cfg(windows)'.dependencies] # unfortunately, the asm extensions do not build on MSVC, see https://github.com/RustCrypto/asm-hashes/issues/17 diff --git a/crates/rustic_core/src/backend/ignore.rs b/crates/rustic_core/src/backend/ignore.rs index cbfea1c..f9f1df3 100644 --- a/crates/rustic_core/src/backend/ignore.rs +++ b/crates/rustic_core/src/backend/ignore.rs @@ -10,12 +10,14 @@ use serde_with::{serde_as, DisplayFromStr}; use bytesize::ByteSize; #[cfg(not(windows))] +use cached::proc_macro::cached; +#[cfg(not(windows))] use chrono::TimeZone; use chrono::{DateTime, Local, Utc}; use ignore::{overrides::OverrideBuilder, DirEntry, Walk, WalkBuilder}; use log::warn; #[cfg(not(windows))] -use users::{Groups, Users, UsersCache}; +use nix::unistd::{Gid, Group, Uid, User}; #[cfg(not(any(windows, target_os = "openbsd")))] use crate::backend::node::ExtendedAttribute; @@ -35,8 +37,6 @@ pub struct LocalSource { builder: WalkBuilder, walker: Walk, save_opts: LocalSourceSaveOptions, - #[cfg(not(windows))] - cache: UsersCache, } #[serde_as] @@ -207,8 +207,6 @@ impl LocalSource { builder, walker, save_opts, - #[cfg(not(windows))] - cache: UsersCache::new(), }) } } @@ -262,8 +260,6 @@ impl Iterator for LocalSource { e.map_err(IgnoreErrorKind::GenericError)?, self.save_opts.with_atime, self.save_opts.ignore_devid, - #[cfg(not(windows))] - &self.cache, ) .map_err(std::convert::Into::into) }) @@ -347,26 +343,46 @@ fn map_entry( Ok(ReadSourceEntry { path, node, open }) } +#[cfg(not(windows))] +#[cached] +fn get_user_by_uid(uid: u32) -> Option { + match User::from_uid(Uid::from_raw(uid)) { + Ok(Some(user)) => Some(user.name), + Ok(None) => None, + Err(err) => { + warn!("error getting user from uid {uid}: {err}"); + None + } + } +} + +#[cfg(not(windows))] +#[cached] +fn get_group_by_gid(gid: u32) -> Option { + match Group::from_gid(Gid::from_raw(gid)) { + Ok(Some(group)) => Some(group.name), + Ok(None) => None, + Err(err) => { + warn!("error getting group from gid {gid}: {err}"); + None + } + } +} + #[cfg(not(windows))] // map_entry: turn entry into (Path, Node) fn map_entry( entry: DirEntry, with_atime: bool, ignore_devid: bool, - cache: &UsersCache, ) -> RusticResult> { let name = entry.file_name(); let m = entry.metadata().map_err(IgnoreErrorKind::GenericError)?; let uid = m.uid(); let gid = m.gid(); - let user = cache - .get_user_by_uid(uid) - .map(|u| u.name().to_str().unwrap().to_string()); - - let group = cache - .get_group_by_gid(gid) - .map(|g| g.name().to_str().unwrap().to_string()); + let user = get_user_by_uid(uid); + let group = get_group_by_gid(gid); let mtime = m .modified()