diff --git a/src/config.rs b/src/config.rs index fbee890..f8236b2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -13,19 +13,23 @@ pub struct Config { #[structopt(long, name = "OSVERSION", default_value = "1.0")] pub osversion: String, + /// Optional skel directory to be copied after rootfs has been made + #[structopt(long, name = "SKEL", default_value = "")] + pub skel: PathBuf, + /// Verbose #[structopt(short, long)] pub verbose: bool, /// Path to LDD - #[structopt(long, name = "LDD", default_value = "/usr/bin/ldd", parse(from_os_str))] + #[structopt(long, name = "LDD", default_value = "/usr/bin/ldd")] pub ldd: PathBuf, /// Directory for root filesystem - #[structopt(required = true, name = "DIR", parse(from_os_str))] + #[structopt(required = true, name = "DIR")] pub root_dir: PathBuf, /// Files to parse - #[structopt(required = true, name = "FILES", parse(from_os_str))] + #[structopt(required = true, name = "FILES")] pub files: Vec, } diff --git a/src/main.rs b/src/main.rs index 20a7810..fb9d6eb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ mod config; mod dirs; mod error; mod files; +mod skel; use std::path::PathBuf; @@ -43,7 +44,9 @@ fn main() -> error::MkrootResult<()> { ))); } - // cp skel + if config.skel != PathBuf::new() { + skel::copy(&config)?; + } Ok(()) } diff --git a/src/skel.rs b/src/skel.rs new file mode 100644 index 0000000..3e3b88b --- /dev/null +++ b/src/skel.rs @@ -0,0 +1,137 @@ +use std::fs::{copy as fscopy, create_dir, metadata, read_dir, set_permissions, Permissions}; +use std::os::unix::fs::PermissionsExt; +use std::path::PathBuf; + +use crate::config::Config; +use crate::error::*; + +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() { + let perms = get_perms(&entry_path)?; + + 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() + ))); + } + + if verbose { + println!( + "Setting permissions {:o} on {}", + &perms.mode(), + &new_dst.display() + ); + } + set_perms(&new_dst, 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 get_perms(path: &PathBuf) -> MkrootResult { + match metadata(path) { + Ok(meta) => Ok(meta.permissions()), + Err(e) => Err(MkrootError::from(format!( + "Error retrieving metadata {}: {}", + path.display(), + e + ))), + } +} + +fn set_perms(path: &PathBuf, perms: Permissions) -> MkrootResult<()> { + if let Err(e) = set_permissions(path, perms) { + return Err(MkrootError::from(format!( + "Error setting permissions {}: {}", + path.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(()) +}