use std::fs::{copy as fscopy, create_dir, read_dir}; use std::os::unix::fs::PermissionsExt; use std::path::PathBuf; use crate::config::Config; use crate::error::*; use crate::util::{get_perms, set_perms}; pub fn copy(config: &Config) -> MkrootResult<()> { if config.verbose { println!( "Copying skel {} to {}", &config.skel.display(), &config.root_dir.display() ); } copy_dir(&config.skel, &config.root_dir, config.verbose) } fn copy_dir(src: &PathBuf, dst: &PathBuf, verbose: bool) -> MkrootResult<()> { match read_dir(&src) { Ok(src_dir) => { for entry in src_dir { match entry { Ok(entry_match) => { let entry_path = entry_match.path(); let mut new_dst = PathBuf::from(&dst); new_dst.push(&entry_match.file_name()); if entry_path.is_file() { if verbose { println!( "Copying {} to {}", &entry_path.display(), &new_dst.display() ); copy_file(&entry_path, &new_dst)?; } } else if entry_path.is_dir() { if !new_dst.exists() { if verbose { println!("Creating directory {}", &new_dst.display()); } mkdir(&new_dst)?; } else if !new_dst.is_dir() { return Err(MkrootError::from(format!( "Error: skel {} is a directory but target {} isn't", &entry_path.display(), &new_dst.display() ))); } let entry_perms = get_perms(&entry_path)?; let dst_perms = get_perms(&new_dst)?; if entry_perms != dst_perms { if verbose { println!( "Setting permissions {:o} on {}", &entry_perms.mode(), &new_dst.display() ); } set_perms(&new_dst, entry_perms)?; } copy_dir(&entry_path, &new_dst, verbose)?; } } Err(e) => { return Err(MkrootError::from(format!( "Error getting directory entry in {}: {}", &src.display(), e ))) } } } } Err(e) => { return Err(MkrootError::from(format!( "Error opening directory {}: {}", &src.display(), e ))) } }; Ok(()) } fn copy_file(src: &PathBuf, dst: &PathBuf) -> MkrootResult<()> { if let Err(e) = fscopy(src, dst) { return Err(MkrootError::from(format!( "Error copying file from {} to {}: {}", src.display(), dst.display(), e ))); } Ok(()) } fn mkdir(path: &PathBuf) -> MkrootResult<()> { if let Err(e) = create_dir(path) { return Err(MkrootError::from(format!( "Error creating directory {}: {}", path.display(), e ))); } Ok(()) }