makeInitrdNGTool: better errors

It's extremely frustrating seeing "Error: Os { code: 13, kind:
PermissionDenied, message: "Permission denied" }" without any hint as to
where exactly that occurred.

This commit fixes that by adding context to most errors.
This commit is contained in:
Cole Helbling 2023-05-15 13:50:24 -07:00
parent ddd54024ce
commit 3e63608c7b
3 changed files with 68 additions and 23 deletions

View File

@ -8,6 +8,16 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "eyre"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb"
dependencies = [
"indenter",
"once_cell",
]
[[package]]
name = "goblin"
version = "0.5.3"
@ -19,6 +29,12 @@ dependencies = [
"scroll",
]
[[package]]
name = "indenter"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
[[package]]
name = "log"
version = "0.4.17"
@ -32,9 +48,16 @@ dependencies = [
name = "make-initrd-ng"
version = "0.1.0"
dependencies = [
"eyre",
"goblin",
]
[[package]]
name = "once_cell"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "plain"
version = "0.2.3"

View File

@ -7,4 +7,5 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
eyre = "0.6.8"
goblin = "0.5.0"

View File

@ -3,12 +3,13 @@ use std::env;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::hash::Hash;
use std::io::{BufRead, BufReader};
use std::iter::FromIterator;
use std::io::{BufRead, BufReader, Error};
use std::os::unix;
use std::path::{Component, Path, PathBuf};
use std::process::Command;
use eyre::Context;
use goblin::{elf::Elf, Object};
struct NonRepeatingQueue<T> {
@ -87,22 +88,30 @@ fn add_dependencies<P: AsRef<Path> + AsRef<OsStr>>(
}
}
fn copy_file<P: AsRef<Path> + AsRef<OsStr>, S: AsRef<Path> + AsRef<OsStr>>(
fn copy_file<
P: AsRef<Path> + AsRef<OsStr> + std::fmt::Debug,
S: AsRef<Path> + AsRef<OsStr> + std::fmt::Debug,
>(
source: P,
target: S,
queue: &mut NonRepeatingQueue<Box<Path>>,
) -> Result<(), Error> {
fs::copy(&source, &target)?;
) -> eyre::Result<()> {
fs::copy(&source, &target)
.wrap_err_with(|| format!("failed to copy {:?} to {:?}", source, target))?;
let contents = fs::read(&source)?;
let contents =
fs::read(&source).wrap_err_with(|| format!("failed to read from {:?}", source))?;
if let Ok(Object::Elf(e)) = Object::parse(&contents) {
add_dependencies(source, e, queue);
// Make file writable to strip it
let mut permissions = fs::metadata(&target)?.permissions();
let mut permissions = fs::metadata(&target)
.wrap_err_with(|| format!("failed to get metadata for {:?}", target))?
.permissions();
permissions.set_readonly(false);
fs::set_permissions(&target, permissions)?;
fs::set_permissions(&target, permissions)
.wrap_err_with(|| format!("failed to set readonly flag to false for {:?}", target))?;
// Strip further than normal
if let Ok(strip) = env::var("STRIP") {
@ -121,11 +130,13 @@ fn copy_file<P: AsRef<Path> + AsRef<OsStr>, S: AsRef<Path> + AsRef<OsStr>>(
Ok(())
}
fn queue_dir<P: AsRef<Path>>(
fn queue_dir<P: AsRef<Path> + std::fmt::Debug>(
source: P,
queue: &mut NonRepeatingQueue<Box<Path>>,
) -> Result<(), Error> {
for entry in fs::read_dir(source)? {
) -> eyre::Result<()> {
for entry in
fs::read_dir(&source).wrap_err_with(|| format!("failed to read dir {:?}", source))?
{
let entry = entry?;
// No need to recurse. The queue will bring us back round here on its own.
queue.push_back(Box::from(entry.path().as_path()));
@ -138,7 +149,7 @@ fn handle_path(
root: &Path,
p: &Path,
queue: &mut NonRepeatingQueue<Box<Path>>,
) -> Result<(), Error> {
) -> eyre::Result<()> {
let mut source = PathBuf::new();
let mut target = Path::new(root).to_path_buf();
let mut iter = p.components().peekable();
@ -161,15 +172,17 @@ fn handle_path(
Component::Normal(name) => {
target.push(name);
source.push(name);
let typ = fs::symlink_metadata(&source)?.file_type();
let typ = fs::symlink_metadata(&source)
.wrap_err_with(|| format!("failed to get symlink metadata for {:?}", source))?
.file_type();
if typ.is_file() && !target.exists() {
copy_file(&source, &target, queue)?;
if let Some(filename) = source.file_name() {
source.set_file_name(OsString::from_iter([
OsStr::new("."),
filename,
OsStr::new("-wrapped"),
OsStr::new("."),
filename,
OsStr::new("-wrapped"),
]));
let wrapped_path = source.as_path();
@ -178,11 +191,14 @@ fn handle_path(
}
}
} else if typ.is_symlink() {
let link_target = fs::read_link(&source)?;
let link_target = fs::read_link(&source)
.wrap_err_with(|| format!("failed to resolve symlink of {:?}", source))?;
// Create the link, then push its target to the queue
if !target.exists() {
unix::fs::symlink(&link_target, &target)?;
unix::fs::symlink(&link_target, &target).wrap_err_with(|| {
format!("failed to symlink {:?} to {:?}", link_target, target)
})?;
}
source.pop();
source.push(link_target);
@ -196,12 +212,14 @@ fn handle_path(
break;
} else if typ.is_dir() {
if !target.exists() {
fs::create_dir(&target)?;
fs::create_dir(&target)
.wrap_err_with(|| format!("failed to create dir {:?}", target))?;
}
// Only recursively copy if the directory is the target object
if iter.peek().is_none() {
queue_dir(&source, queue)?;
queue_dir(&source, queue)
.wrap_err_with(|| format!("failed to queue dir {:?}", source))?;
}
}
}
@ -211,9 +229,10 @@ fn handle_path(
Ok(())
}
fn main() -> Result<(), Error> {
fn main() -> eyre::Result<()> {
let args: Vec<String> = env::args().collect();
let input = fs::File::open(&args[1])?;
let input =
fs::File::open(&args[1]).wrap_err_with(|| format!("failed to open file {:?}", &args[1]))?;
let output = &args[2];
let out_path = Path::new(output);
@ -235,8 +254,10 @@ fn main() -> Result<(), Error> {
let link_path = Path::new(&link_string);
let mut link_parent = link_path.to_path_buf();
link_parent.pop();
fs::create_dir_all(link_parent)?;
unix::fs::symlink(obj_path, link_path)?;
fs::create_dir_all(&link_parent)
.wrap_err_with(|| format!("failed to create directories to {:?}", link_parent))?;
unix::fs::symlink(obj_path, link_path)
.wrap_err_with(|| format!("failed to symlink {:?} to {:?}", obj_path, link_path))?;
}
}
while let Some(obj) = queue.pop_front() {