From 0bb2496d920b935e140399a9276c58d7cadf1439 Mon Sep 17 00:00:00 2001 From: Bruce Leidl Date: Mon, 19 Mar 2018 15:29:57 -0400 Subject: [PATCH] Fixed /skel problem creating files/dirs as root --- citadel-tools/citadel-realms/src/realm.rs | 3 ++- citadel-tools/citadel-realms/src/util.rs | 29 ++++++++++++++++------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/citadel-tools/citadel-realms/src/realm.rs b/citadel-tools/citadel-realms/src/realm.rs index 05e6bfd..28cea1e 100644 --- a/citadel-tools/citadel-realms/src/realm.rs +++ b/citadel-tools/citadel-realms/src/realm.rs @@ -166,7 +166,8 @@ impl Realm { fn create_home_directory(&self) -> Result<()> { let home = self.base_path().join("home"); - mkdir_chown(&home, 1000, 1000)?; + fs::create_dir(&home)?; + chown(&home, 1000, 1000)?; let skel = PathBuf::from(REALMS_BASE_PATH).join("skel"); if skel.exists() { info!("Populating realm home directory with files from {}", skel.display()); diff --git a/citadel-tools/citadel-realms/src/util.rs b/citadel-tools/citadel-realms/src/util.rs index ede3671..6b34c3a 100644 --- a/citadel-tools/citadel-realms/src/util.rs +++ b/citadel-tools/citadel-realms/src/util.rs @@ -48,10 +48,7 @@ pub fn is_valid_realm_name(name: &str) -> bool { name.chars().all(is_alphanum_or_dash) } -pub fn mkdir_chown(path: &Path, uid: u32, gid: u32) -> io::Result<()> { - if !path.exists() { - fs::create_dir(path)?; - } +pub fn chown(path: &Path, uid: u32, gid: u32) -> io::Result<()> { let cstr = CString::new(path.as_os_str().as_bytes())?; unsafe { if libc::chown(cstr.as_ptr(), uid, gid) == -1 { @@ -61,15 +58,29 @@ pub fn mkdir_chown(path: &Path, uid: u32, gid: u32) -> io::Result<()> { Ok(()) } +fn copy_path(from: &Path, to: &Path) -> Result<()> { + if to.exists() { + bail!("destination path {} already exists which is not expected", to.display()); + } + + let meta = from.metadata()?; + + if from.is_dir() { + fs::create_dir(to)?; + } else { + fs::copy(&from, &to)?; + } + + chown(to, meta.uid(), meta.gid())?; + Ok(()) + +} pub fn copy_tree(from_base: &Path, to_base: &Path) -> Result<()> { for entry in WalkDir::new(from_base) { let path = entry?.path().to_owned(); let to = to_base.join(path.strip_prefix(from_base)?); - if path.is_dir() { - let meta = path.metadata()?; - mkdir_chown(&to, meta.uid(), meta.gid())?; - } else { - fs::copy(&path, &to) + if &to != to_base { + copy_path(&path, &to) .map_err(|e| format_err!("failed to copy {} to {}: {}", path.display(), to.display(), e))?; } }