parent
f9900daeef
commit
23a5c25726
@ -0,0 +1,228 @@
|
||||
use std::fs::{File, Permissions};
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::error::*;
|
||||
use crate::util::{copy_file, set_perms};
|
||||
|
||||
pub struct Files {
|
||||
pub bins: Vec<PathBuf>,
|
||||
pub sbins: Vec<PathBuf>,
|
||||
pub libs: Vec<PathBuf>,
|
||||
pub lib64s: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
impl Files {
|
||||
pub fn gather(config: &Config) -> MkrootResult<Files> {
|
||||
let mut myfiles = Files {
|
||||
bins: Vec::new(),
|
||||
sbins: Vec::new(),
|
||||
libs: Vec::new(),
|
||||
lib64s: Vec::new(),
|
||||
};
|
||||
|
||||
for file in &config.files {
|
||||
if config.verbose {
|
||||
println!("Checking {}", &file.display());
|
||||
}
|
||||
|
||||
open(&file)?;
|
||||
|
||||
let (libs, lib64s) = libs_from_ldd(&file, &config)?;
|
||||
myfiles.libs.extend(libs);
|
||||
myfiles.lib64s.extend(lib64s);
|
||||
|
||||
if check_sbin(&file) {
|
||||
myfiles.sbins.push(file.to_owned());
|
||||
} else {
|
||||
myfiles.bins.push(file.to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
myfiles.bins.sort();
|
||||
myfiles.bins.dedup();
|
||||
myfiles.sbins.sort();
|
||||
myfiles.sbins.dedup();
|
||||
myfiles.libs.sort();
|
||||
myfiles.libs.dedup();
|
||||
myfiles.lib64s.sort();
|
||||
myfiles.lib64s.dedup();
|
||||
|
||||
Ok(myfiles)
|
||||
}
|
||||
|
||||
pub fn copy(&self, config: &Config) -> MkrootResult<()> {
|
||||
let mut target = PathBuf::from(&config.root_dir);
|
||||
target.push("bin");
|
||||
copy_files(&self.bins, &target, 0o755, config.verbose)?;
|
||||
|
||||
let mut target = PathBuf::from(&config.root_dir);
|
||||
target.push("sbin");
|
||||
copy_files(&self.sbins, &target, 0o755, config.verbose)?;
|
||||
|
||||
let mut target = PathBuf::from(&config.root_dir);
|
||||
target.push("libs");
|
||||
copy_files(&self.libs, &target, 0o644, config.verbose)?;
|
||||
|
||||
let mut target = PathBuf::from(&config.root_dir);
|
||||
target.push("lib64");
|
||||
copy_files(&self.lib64s, &target, 0o644, config.verbose)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_linker_permissions(
|
||||
libs: &[PathBuf],
|
||||
dir: &PathBuf,
|
||||
verbose: bool,
|
||||
) -> MkrootResult<()> {
|
||||
for lib in libs {
|
||||
if let Some(fn_osstr) = &lib.file_name() {
|
||||
if let Some(fn_str) = fn_osstr.to_str() {
|
||||
if fn_str.starts_with("ld-linux") {
|
||||
let mut lib = PathBuf::from(&dir);
|
||||
lib.push(&fn_str);
|
||||
|
||||
if verbose {
|
||||
println!("Setting linker {} to mode 0o755", &lib.display());
|
||||
}
|
||||
|
||||
set_perms(&lib, Permissions::from_mode(0o755))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn open(p: &PathBuf) -> MkrootResult<()> {
|
||||
if let Err(e) = File::open(&p) {
|
||||
return Err(MkrootError::from(format!(
|
||||
"Error opening file ({}): {}",
|
||||
&p.display(),
|
||||
e
|
||||
)));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn libs_from_ldd(
|
||||
file: &PathBuf,
|
||||
config: &Config,
|
||||
) -> MkrootResult<(Vec<PathBuf>, Vec<PathBuf>)> {
|
||||
let ldd = ldd(&file, &config)?;
|
||||
|
||||
let mut libs: Vec<PathBuf> = Vec::new();
|
||||
let mut lib64s: Vec<PathBuf> = Vec::new();
|
||||
|
||||
if ldd.is_empty() {
|
||||
return Ok((libs, lib64s));
|
||||
}
|
||||
|
||||
let re = Regex::new(r"(^|.* )(?P<path>/.*) \(0x[[:xdigit:]]{16}\)$")?;
|
||||
|
||||
for line in ldd.lines() {
|
||||
let line = String::from(line.trim());
|
||||
|
||||
if let Some(caps) = re.captures(&line) {
|
||||
if let Some(rematch) = caps.name("path") {
|
||||
let match_path = PathBuf::from(rematch.as_str());
|
||||
|
||||
if config.verbose {
|
||||
println!("Adding {}", &match_path.display());
|
||||
}
|
||||
|
||||
if check_lib64(&match_path) {
|
||||
lib64s.push(match_path);
|
||||
} else {
|
||||
libs.push(match_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok((libs, lib64s))
|
||||
}
|
||||
|
||||
fn copy_files(
|
||||
files: &[PathBuf],
|
||||
target: &PathBuf,
|
||||
mode: u32,
|
||||
verbose: bool,
|
||||
) -> MkrootResult<()> {
|
||||
for f in files {
|
||||
let mut t = PathBuf::from(&target);
|
||||
if let Some(filename) = &f.file_name() {
|
||||
t.push(filename);
|
||||
|
||||
if verbose {
|
||||
println!("Copying {} to {}", &f.display(), &t.display());
|
||||
}
|
||||
|
||||
copy_file(&f, &t)?;
|
||||
set_perms(&t, Permissions::from_mode(mode))?;
|
||||
} else if verbose {
|
||||
println!("Skipping {}", &f.display());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ldd(file: &PathBuf, config: &Config) -> MkrootResult<String> {
|
||||
match Command::new(&config.ldd).arg(file).output() {
|
||||
Ok(output) => {
|
||||
if output.status.success() {
|
||||
Ok(String::from_utf8(output.stdout).unwrap_or_default())
|
||||
} else if config.verbose {
|
||||
let mut out = String::from("ldd failed: ");
|
||||
let stdout = String::from_utf8(output.stdout).unwrap_or_default();
|
||||
let stderr = String::from_utf8(output.stderr).unwrap_or_default();
|
||||
|
||||
if !stdout.is_empty() {
|
||||
out = out + "stdout: " + &stdout + " ";
|
||||
}
|
||||
if !stderr.is_empty() {
|
||||
out = out + "stderr: " + &stderr;
|
||||
}
|
||||
|
||||
println!("{}", out.trim());
|
||||
|
||||
Ok(String::new())
|
||||
} else {
|
||||
Ok(String::new())
|
||||
}
|
||||
}
|
||||
Err(e) => Err(MkrootError::from(format!(
|
||||
"Error running ldd ({}): {}",
|
||||
&config.ldd.display(),
|
||||
e
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
fn check_lib64(path: &PathBuf) -> bool {
|
||||
for c in path.components() {
|
||||
if c.as_os_str() == "lib64" {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn check_sbin(path: &PathBuf) -> bool {
|
||||
for c in path.components() {
|
||||
if c.as_os_str() == "sbin" {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
Loading…
Reference in new issue