From bdcab7e3088703806e38f0ce2a6a41f71cbb85dd Mon Sep 17 00:00:00 2001 From: Dennis Schwerdel Date: Wed, 22 Mar 2017 19:58:56 +0100 Subject: [PATCH] Chown --- Cargo.lock | 10 ++++++++++ Cargo.toml | 1 + README.md | 5 +++++ src/main.rs | 1 + src/repository/metadata.rs | 26 ++++++++++++++++++++++---- src/util/fs.rs | 19 +++++++++++++++++++ src/util/mod.rs | 2 ++ 7 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 src/util/fs.rs diff --git a/Cargo.lock b/Cargo.lock index c5e36e0..0e2f42f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,6 +7,7 @@ dependencies = [ "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "mmap 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -89,6 +90,14 @@ name = "constant_time_eq" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "filetime" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -340,6 +349,7 @@ dependencies = [ "checksum chrono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "158b0bd7d75cbb6bf9c25967a48a2e9f77da95876b858eadfabaa99cd069de6e" "checksum clap 2.21.2 (registry+https://github.com/rust-lang/crates.io-index)" = "58ad5e8142f3a5eab0c1cba5011aa383e009842936107fe4d94f1a8d380a1aec" "checksum constant_time_eq 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "07dcb7959f0f6f1cf662f9a7ff389bcb919924d99ac41cf31f10d611d8721323" +"checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122" "checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135" diff --git a/Cargo.toml b/Cargo.toml index 1bf0804..5db004b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ log = "0.3" byteorder = "1.0" ansi_term = "0.9" sodiumoxide = "0.0.14" +filetime = "0.1" libc = "*" [build-dependencies] diff --git a/README.md b/README.md index 0200479..9acc6bd 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,11 @@ Recommended: Brotli/2-7 - Options for creating backups (same filesystem, exclude/include patterns) - Recompress & combine bundles - Allow to use tar files for backup and restore (--tar, http://alexcrichton.com/tar-rs/tar/index.html) +- File attributes + - xattrs https://crates.io/crates/xattr + - gid/uid + - http://mahkoh.github.io/posix/doc/posix/unistd/fn.lchown.html + - http://mahkoh.github.io/posix/doc/posix/sys/time/fn.utimes.html ### CLI functionality - Remove backup subtrees diff --git a/src/main.rs b/src/main.rs index df5ed62..507781d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,6 +15,7 @@ extern crate chrono; extern crate byteorder; extern crate sodiumoxide; extern crate ansi_term; +extern crate filetime; extern crate libc; pub mod util; diff --git a/src/repository/metadata.rs b/src/repository/metadata.rs index f8b5efc..4b655ca 100644 --- a/src/repository/metadata.rs +++ b/src/repository/metadata.rs @@ -1,5 +1,7 @@ use ::prelude::*; +use filetime::{self, FileTime}; + use std::collections::HashMap; use std::path::{Path, PathBuf}; use std::fs::{self, Metadata, File, Permissions}; @@ -35,6 +37,16 @@ quick_error!{ description("Failed to set permissions") display("Inode error: failed to set permissions to {:3o} on {:?}\n\tcaused by: {}", mode, path, err) } + SetTimes(err: io::Error, path: PathBuf) { + cause(err) + description("Failed to set file times") + display("Inode error: failed to set file times on {:?}\n\tcaused by: {}", path, err) + } + SetOwnership(err: io::Error, path: PathBuf) { + cause(err) + description("Failed to set file ownership") + display("Inode error: failed to set file ownership on {:?}\n\tcaused by: {}", path, err) + } Integrity(reason: &'static str) { description("Integrity error") display("Inode error: inode integrity error: {}", reason) @@ -186,15 +198,21 @@ impl Inode { } } } - try!(fs::set_permissions(&full_path, Permissions::from_mode(self.mode)).map_err(|e| InodeError::SetPermissions(e, full_path.clone(), self.mode))); - //FIXME: set times and gid/uid - // https://crates.io/crates/filetime + try!(fs::set_permissions( + &full_path, + Permissions::from_mode(self.mode) + ).map_err(|e| InodeError::SetPermissions(e, full_path.clone(), self.mode))); + try!(filetime::set_file_times( + &full_path, + FileTime::from_seconds_since_1970(self.access_time as u64, 0), + FileTime::from_seconds_since_1970(self.modify_time as u64, 0) + ).map_err(|e| InodeError::SetTimes(e, full_path.clone()))); + try!(chown(&full_path, self.user, self.group).map_err(|e| InodeError::SetOwnership(e, full_path.clone()))); Ok(file) } pub fn is_unchanged(&self, other: &Inode) -> bool { self.modify_time == other.modify_time - && self.create_time == other.create_time && self.file_type == other.file_type } diff --git a/src/util/fs.rs b/src/util/fs.rs new file mode 100644 index 0000000..e640151 --- /dev/null +++ b/src/util/fs.rs @@ -0,0 +1,19 @@ +mod linux { + use libc; + + use std::path::Path; + use std::io; + use std::ffi::CString; + use std::os::unix::ffi::OsStringExt; + + pub fn chown>(path: P, uid: libc::uid_t, gid: libc::gid_t) -> Result<(), io::Error> { + let path = CString::new(path.as_ref().to_path_buf().into_os_string().into_vec()).unwrap(); + let result = unsafe { libc::chown((&path).as_ptr(), uid, gid) }; + match result { + 0 => Ok(()), + err => Err(io::Error::from_raw_os_error(err)) + } + } +} + +pub use self::linux::*; diff --git a/src/util/mod.rs b/src/util/mod.rs index adf72ee..4fa6553 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -8,8 +8,10 @@ mod bitmap; mod hex; mod cli; mod hostname; +mod fs; pub mod msgpack; +pub use self::fs::*; pub use self::chunk::*; pub use self::compression::*; pub use self::encryption::*;