Compare commits

..

10 Commits

@ -1,6 +1,8 @@
build a minimal chroot/container/vm filesystem by taking a list of files and build a minimal chroot/container/vm filesystem by taking a list of files and
putting them and their necessary libs into a target rootfs directory putting them and their necessary libs into a target rootfs directory
this is linux only
example: example:
``` ```

@ -0,0 +1,2 @@
#!/bin/bash
find src -type f -name '*.rs' -exec rustfmt {} +

@ -2,7 +2,8 @@ use std::fs::read_dir;
use std::path::PathBuf; use std::path::PathBuf;
use crate::config::Config; use crate::config::Config;
use crate::error::*; use crate::result::Result;
use crate::serr;
use crate::util::mkdir; use crate::util::mkdir;
static DIRS: &[&str] = &[ static DIRS: &[&str] = &[
@ -10,7 +11,7 @@ static DIRS: &[&str] = &[
"usr", "var", "usr/bin", "usr", "var", "usr/bin",
]; ];
pub fn check(config: &Config) -> MkrootResult<()> { pub fn check(config: &Config) -> Result<()> {
if !&config.root_dir.exists() { if !&config.root_dir.exists() {
return Ok(()); return Ok(());
} }
@ -26,24 +27,25 @@ pub fn check(config: &Config) -> MkrootResult<()> {
Ok(()) Ok(())
} }
fn open(dir: &PathBuf, verbose: bool) -> MkrootResult<()> { fn open(dir: &PathBuf, verbose: bool) -> Result<()> {
if dir.exists() { if dir.exists() {
if verbose { if verbose {
println!("Checking directory {}", &dir.display()); println!("Checking directory {}", &dir.display());
} }
if let Err(e) = read_dir(&dir) { if let Err(e) = read_dir(&dir) {
return Err(MkrootError::from(format!( return serr!(
"Error opening directory {}: {}", "Error opening directory ",
&dir.display(), &dir.display().to_string(),
e ": ",
))); &e.to_string()
);
} }
} }
Ok(()) Ok(())
} }
pub fn create(config: &Config) -> MkrootResult<()> { pub fn create(config: &Config) -> Result<()> {
if config.verbose { if config.verbose {
println!("Creating directory {}", &config.root_dir.display()); println!("Creating directory {}", &config.root_dir.display());
} }

@ -1,49 +0,0 @@
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::io::Error as IoError;
use regex::Error as RegexError;
pub type MkrootResult<T> = Result<T, MkrootError>;
#[derive(Debug)]
pub enum MkrootError {
Io(IoError),
Regex(RegexError),
Custom(String),
Empty,
}
impl From<IoError> for MkrootError {
fn from(e: IoError) -> MkrootError {
MkrootError::Io(e)
}
}
impl From<RegexError> for MkrootError {
fn from(e: RegexError) -> MkrootError {
MkrootError::Regex(e)
}
}
impl From<String> for MkrootError {
fn from(e: String) -> MkrootError {
MkrootError::Custom(e)
}
}
impl From<()> for MkrootError {
fn from(_: ()) -> MkrootError {
MkrootError::Empty
}
}
impl Display for MkrootError {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
match *self {
MkrootError::Io(ref e) => Display::fmt(e, f),
MkrootError::Regex(ref e) => Display::fmt(e, f),
MkrootError::Custom(ref e) => Display::fmt(e, f),
MkrootError::Empty => Display::fmt("Empty", f),
}
}
}

@ -6,7 +6,8 @@ use std::process::Command;
use regex::Regex; use regex::Regex;
use crate::config::Config; use crate::config::Config;
use crate::error::*; use crate::result::Result;
use crate::serr;
use crate::util::{copy_file, set_perms}; use crate::util::{copy_file, set_perms};
pub struct Files { pub struct Files {
@ -17,7 +18,7 @@ pub struct Files {
} }
impl Files { impl Files {
pub fn gather(config: &Config) -> MkrootResult<Files> { pub fn gather(config: &Config) -> Result<Files> {
let mut myfiles = Files { let mut myfiles = Files {
bins: Vec::new(), bins: Vec::new(),
sbins: Vec::new(), sbins: Vec::new(),
@ -55,7 +56,7 @@ impl Files {
Ok(myfiles) Ok(myfiles)
} }
pub fn copy(&self, config: &Config) -> MkrootResult<()> { pub fn copy(&self, config: &Config) -> Result<()> {
let mut target = PathBuf::from(&config.root_dir); let mut target = PathBuf::from(&config.root_dir);
target.push("bin"); target.push("bin");
copy_files(&self.bins, &target, 0o755, config.verbose)?; copy_files(&self.bins, &target, 0o755, config.verbose)?;
@ -76,11 +77,7 @@ impl Files {
} }
} }
pub fn set_linker_permissions( pub fn set_linker_permissions(libs: &[PathBuf], dir: &PathBuf, verbose: bool) -> Result<()> {
libs: &[PathBuf],
dir: &PathBuf,
verbose: bool,
) -> MkrootResult<()> {
for lib in libs { for lib in libs {
if let Some(fn_osstr) = &lib.file_name() { if let Some(fn_osstr) = &lib.file_name() {
if let Some(fn_str) = fn_osstr.to_str() { if let Some(fn_str) = fn_osstr.to_str() {
@ -101,21 +98,19 @@ pub fn set_linker_permissions(
Ok(()) Ok(())
} }
fn open(p: &PathBuf) -> MkrootResult<()> { fn open(p: &PathBuf) -> Result<()> {
if let Err(e) = File::open(&p) { if let Err(e) = File::open(&p) {
return Err(MkrootError::from(format!( return serr!(
"Error opening file ({}): {}", "Error opening file (",
&p.display(), &p.display().to_string(),
e "): ",
))); &e.to_string()
);
} }
Ok(()) Ok(())
} }
fn libs_from_ldd( fn libs_from_ldd(file: &PathBuf, config: &Config) -> Result<(Vec<PathBuf>, Vec<PathBuf>)> {
file: &PathBuf,
config: &Config,
) -> MkrootResult<(Vec<PathBuf>, Vec<PathBuf>)> {
let ldd = ldd(&file, &config)?; let ldd = ldd(&file, &config)?;
let mut libs: Vec<PathBuf> = Vec::new(); let mut libs: Vec<PathBuf> = Vec::new();
@ -150,12 +145,7 @@ fn libs_from_ldd(
Ok((libs, lib64s)) Ok((libs, lib64s))
} }
fn copy_files( fn copy_files(files: &[PathBuf], target: &PathBuf, mode: u32, verbose: bool) -> Result<()> {
files: &[PathBuf],
target: &PathBuf,
mode: u32,
verbose: bool,
) -> MkrootResult<()> {
for f in files { for f in files {
let mut t = PathBuf::from(&target); let mut t = PathBuf::from(&target);
if let Some(filename) = &f.file_name() { if let Some(filename) = &f.file_name() {
@ -175,7 +165,7 @@ fn copy_files(
Ok(()) Ok(())
} }
fn ldd(file: &PathBuf, config: &Config) -> MkrootResult<String> { fn ldd(file: &PathBuf, config: &Config) -> Result<String> {
match Command::new(&config.ldd).arg(file).output() { match Command::new(&config.ldd).arg(file).output() {
Ok(output) => { Ok(output) => {
if output.status.success() { if output.status.success() {
@ -199,11 +189,12 @@ fn ldd(file: &PathBuf, config: &Config) -> MkrootResult<String> {
Ok(String::new()) Ok(String::new())
} }
} }
Err(e) => Err(MkrootError::from(format!( Err(e) => serr!(
"Error running ldd ({}): {}", "Error running ldd (",
&config.ldd.display(), &config.ldd.display().to_string(),
e "): ",
))), &e.to_string()
),
} }
} }

@ -1,3 +0,0 @@
mod mkroot_files;
pub use mkroot_files::*;

@ -0,0 +1,6 @@
#[macro_export]
macro_rules! serr {
($($arg:tt)*) => {
Err(Box::from([$($arg)*].concat()))
};
}

@ -3,9 +3,11 @@ extern crate structopt;
mod config; mod config;
mod dirs; mod dirs;
mod error;
mod files; mod files;
#[macro_use]
mod macros;
mod os_release; mod os_release;
mod result;
mod skel; mod skel;
mod util; mod util;
@ -14,8 +16,9 @@ use std::path::PathBuf;
use structopt::StructOpt; use structopt::StructOpt;
use config::Config; use config::Config;
use result::Result;
fn main() -> error::MkrootResult<()> { fn main() -> Result<()> {
let config: Config = StructOpt::from_args(); let config: Config = StructOpt::from_args();
if config.verbose { if config.verbose {
@ -40,10 +43,7 @@ fn main() -> error::MkrootResult<()> {
files::set_linker_permissions(&mkrootfiles.lib64s, &d, config.verbose)?; files::set_linker_permissions(&mkrootfiles.lib64s, &d, config.verbose)?;
if let Err(e) = os_release::os_release(&config) { if let Err(e) = os_release::os_release(&config) {
return Err(error::MkrootError::from(format!( return serr!("Error creating etc/os-release: ", &e.to_string());
"Error creating etc/os-release: {}",
e
)));
} }
if config.skel != PathBuf::new() { if config.skel != PathBuf::new() {

@ -4,9 +4,10 @@ use std::os::unix::fs::PermissionsExt;
use std::path::PathBuf; use std::path::PathBuf;
use crate::config::Config; use crate::config::Config;
use crate::error::{MkrootError, MkrootResult}; use crate::result::Result;
use crate::serr;
pub fn os_release(config: &Config) -> MkrootResult<()> { pub fn os_release(config: &Config) -> Result<()> {
let mut path = PathBuf::from(&config.root_dir); let mut path = PathBuf::from(&config.root_dir);
path.push("etc/os-release"); path.push("etc/os-release");
@ -28,19 +29,21 @@ pub fn os_release(config: &Config) -> MkrootResult<()> {
let mut perms = meta.permissions(); let mut perms = meta.permissions();
perms.set_mode(0o644); perms.set_mode(0o644);
if let Err(e) = set_permissions(&path, perms) { if let Err(e) = set_permissions(&path, perms) {
return Err(MkrootError::from(format!( return serr!(
"Error setting permissions {}: {}", "Error setting permissions ",
&path.display(), &path.display().to_string(),
e ": ",
))); &e.to_string()
);
} }
} }
Err(e) => { Err(e) => {
return Err(MkrootError::from(format!( return serr!(
"Error reading metadata {}: {}", "Error reading metadata ",
&path.display(), &path.display().to_string(),
e ": ",
))) &e.to_string()
);
} }
} }

@ -0,0 +1 @@
pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;

@ -3,10 +3,10 @@ use std::os::unix::fs::PermissionsExt;
use std::path::PathBuf; use std::path::PathBuf;
use crate::config::Config; use crate::config::Config;
use crate::error::*; use crate::result::Result;
use crate::util::{copy_file, get_perms, mkdir, set_perms}; use crate::util::{copy_file, get_perms, mkdir, set_perms};
pub fn copy(config: &Config) -> MkrootResult<()> { pub fn copy(config: &Config) -> Result<()> {
if config.verbose { if config.verbose {
println!( println!(
"Copying skel {} to {}", "Copying skel {} to {}",
@ -18,7 +18,7 @@ pub fn copy(config: &Config) -> MkrootResult<()> {
copy_dir(&config.skel, &config.root_dir, config.verbose) copy_dir(&config.skel, &config.root_dir, config.verbose)
} }
fn copy_dir(src: &PathBuf, dst: &PathBuf, verbose: bool) -> MkrootResult<()> { fn copy_dir(src: &PathBuf, dst: &PathBuf, verbose: bool) -> Result<()> {
match read_dir(&src) { match read_dir(&src) {
Ok(src_dir) => { Ok(src_dir) => {
for entry in src_dir { for entry in src_dir {
@ -45,11 +45,13 @@ fn copy_dir(src: &PathBuf, dst: &PathBuf, verbose: bool) -> MkrootResult<()> {
} }
mkdir(&new_dst)?; mkdir(&new_dst)?;
} else if !new_dst.is_dir() { } else if !new_dst.is_dir() {
return Err(MkrootError::from(format!( return serr!(
"Error: skel {} is a directory but target {} isn't", "Error: skel ",
&entry_path.display(), &entry_path.display().to_string(),
&new_dst.display() " is a directory but target ",
))); &new_dst.display().to_string(),
" isn't"
);
} }
let entry_perms = get_perms(&entry_path)?; let entry_perms = get_perms(&entry_path)?;
@ -71,21 +73,23 @@ fn copy_dir(src: &PathBuf, dst: &PathBuf, verbose: bool) -> MkrootResult<()> {
} }
} }
Err(e) => { Err(e) => {
return Err(MkrootError::from(format!( return serr!(
"Error getting directory entry in {}: {}", "Error getting directory entry in ",
&src.display(), &src.display().to_string(),
e ": ",
))) &e.to_string()
);
} }
} }
} }
} }
Err(e) => { Err(e) => {
return Err(MkrootError::from(format!( return serr!(
"Error opening directory {}: {}", "Error opening directory ",
&src.display(), &src.display().to_string(),
e ": ",
))) &e.to_string()
);
} }
}; };

@ -0,0 +1,58 @@
use std::fs::{copy, create_dir, metadata, set_permissions, Permissions};
use std::path::PathBuf;
use crate::result::Result;
use crate::serr;
pub fn get_perms(path: &PathBuf) -> Result<Permissions> {
match metadata(path) {
Ok(meta) => Ok(meta.permissions()),
Err(e) => serr!(
"Error retrieving metadata ",
&path.display().to_string(),
": ",
&e.to_string()
),
}
}
pub fn set_perms(path: &PathBuf, perms: Permissions) -> Result<()> {
if let Err(e) = set_permissions(path, perms) {
return serr!(
"Error setting permissions ",
&path.display().to_string(),
": ",
&e.to_string(),
);
}
Ok(())
}
pub fn mkdir(dir: &PathBuf) -> Result<()> {
if let Err(e) = create_dir(&dir) {
return serr!(
"Error creating directory ",
&dir.display().to_string(),
": ",
&e.to_string()
);
}
Ok(())
}
pub fn copy_file(src: &PathBuf, dst: &PathBuf) -> Result<()> {
if let Err(e) = copy(&src, &dst) {
return serr!(
"Error copying file from ",
&src.display().to_string(),
" to ",
&dst.display().to_string(),
": ",
&e.to_string()
);
}
Ok(())
}

@ -1,17 +0,0 @@
use std::fs::copy;
use std::path::PathBuf;
use crate::error::*;
pub fn copy_file(src: &PathBuf, dst: &PathBuf) -> MkrootResult<()> {
if let Err(e) = copy(&src, &dst) {
return Err(MkrootError::from(format!(
"Error copying file from {} to {}: {}",
&src.display(),
&dst.display(),
e
)));
}
Ok(())
}

@ -1,16 +0,0 @@
use std::fs::create_dir;
use std::path::PathBuf;
use crate::error::*;
pub fn mkdir(dir: &PathBuf) -> MkrootResult<()> {
if let Err(e) = create_dir(&dir) {
return Err(MkrootError::from(format!(
"Error creating directory {}: {}",
&dir.display(),
e
)));
}
Ok(())
}

@ -1,7 +0,0 @@
mod copy_file;
mod mkdir;
mod perms;
pub use crate::util::copy_file::copy_file;
pub use crate::util::mkdir::mkdir;
pub use crate::util::perms::*;

@ -1,27 +0,0 @@
use std::fs::{metadata, set_permissions, Permissions};
use std::path::PathBuf;
use crate::error::*;
pub fn get_perms(path: &PathBuf) -> MkrootResult<Permissions> {
match metadata(path) {
Ok(meta) => Ok(meta.permissions()),
Err(e) => Err(MkrootError::from(format!(
"Error retrieving metadata {}: {}",
path.display(),
e
))),
}
}
pub 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(())
}
Loading…
Cancel
Save