Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion crates/brioche-autopack/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ rust-version.workspace = true
[dependencies]
brioche-pack = { workspace = true }
brioche-resources = { path = "../brioche-resources" }
bstr = "1.12.1"
eyre = "0.6.12"
globset = "0.4.18"
goblin = "0.10.4"
Expand Down
87 changes: 28 additions & 59 deletions crates/brioche-autopack/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::{
collections::{BTreeMap, HashMap, HashSet, VecDeque},
ffi::OsStr,
io::{BufRead as _, Read as _, Write as _},
os::unix::ffi::{OsStrExt as _, OsStringExt as _},
path::{Path, PathBuf},
};

use bstr::{ByteSlice as _, ByteVec as _};
use eyre::{Context as _, ContextCompat as _, OptionExt as _};

pub fn pack_source(
Expand All @@ -14,11 +15,9 @@ pub fn pack_source(
) -> eyre::Result<PackSource> {
let source = match pack {
brioche_pack::Pack::LdLinux { program, .. } => {
let program = program
.to_path()
.map_err(|_| eyre::eyre!("invalid program path: {}", bstr::BStr::new(&program)))?;
let program = brioche_resources::find_in_resource_dirs(all_resource_dirs, program)
.ok_or_else(|| eyre::eyre!("resource not found: {}", program.display()))?;
let program_path = Path::new(OsStr::from_bytes(program));
let program = brioche_resources::find_in_resource_dirs(all_resource_dirs, program_path)
.ok_or_else(|| eyre::eyre!("resource not found: {}", program_path.display()))?;

PackSource::Path(program)
}
Expand All @@ -39,9 +38,7 @@ pub fn pack_source(

let runnable_source_path = match runnable_source.path {
runnable_core::RunnablePath::RelativePath { path } => {
let path = path
.to_path()
.map_err(|_| eyre::eyre!("invalid relative path: {path:?}"))?;
let path = Path::new(OsStr::from_bytes(&path));
let new_source_path = source_path.join(path);

eyre::ensure!(
Expand All @@ -53,10 +50,8 @@ pub fn pack_source(
new_source_path
}
runnable_core::RunnablePath::Resource { resource } => {
let resource = resource
.to_path()
.map_err(|_| eyre::eyre!("invalid resource path: {resource:?}"))?;
brioche_resources::find_in_resource_dirs(all_resource_dirs, resource)
let resource_path = Path::new(OsStr::from_bytes(&resource));
brioche_resources::find_in_resource_dirs(all_resource_dirs, resource_path)
.ok_or_else(|| eyre::eyre!("resource not found: {resource:?}"))?
}
};
Expand Down Expand Up @@ -198,18 +193,12 @@ fn relative_template(
// TODO: Handle path resolution in a cross-platform way.
// This could change based on the host platform

let path = path
.to_path()
.with_context(|| format!("failed to parse path {path:?}"))?;
let path = Path::new(OsStr::from_bytes(path));

let full_path = base_path.join(path);
let new_relative_path = pathdiff::diff_paths(full_path, output_dir)
.context("failed to get path relative to output dir")?;
let new_relative_path = <Vec<u8>>::from_path_buf(new_relative_path).map_err(
|new_relative_path| {
eyre::eyre!("failed to convert path {new_relative_path:?}")
},
)?;
let new_relative_path = new_relative_path.into_os_string().into_vec();

eyre::Ok(runnable_core::TemplateComponent::RelativePath {
path: new_relative_path,
Expand Down Expand Up @@ -559,24 +548,18 @@ fn autopack_dynamic_binary(
pending_paths,
)?;

let program = <Vec<u8>>::from_path_buf(program_resource_path)
.map_err(|_| eyre::eyre!("invalid UTF-8 in path"))?;
let interpreter = <Vec<u8>>::from_path_buf(interpreter_resource_path)
.map_err(|_| eyre::eyre!("invalid UTF-8 in path"))?;
let program = program_resource_path.into_os_string().into_vec();
let interpreter = interpreter_resource_path.into_os_string().into_vec();
let library_dirs = library_dir_resource_paths
.into_iter()
.map(|resource_path| {
<Vec<u8>>::from_path_buf(resource_path)
.map_err(|_| eyre::eyre!("invalid UTF-8 in path"))
})
.collect::<eyre::Result<Vec<_>>>()?;
.map(|resource_path| resource_path.into_os_string().into_vec())
.collect();
let runtime_library_dirs = dynamic_binary_config
.extra_runtime_library_paths
.iter()
.map(|path| {
let path = pathdiff::diff_paths(path, output_path_parent).ok_or_else(|| eyre::eyre!("failed to get relative path from output path {output_path_parent:?} to runtime library path {path:?}"))?;
<Vec<u8>>::from_path_buf(path)
.map_err(|_| eyre::eyre!("invalid UTF-8 in path"))
eyre::Ok(path.into_os_string().into_vec())
})
.collect::<eyre::Result<Vec<_>>>()?;

Expand Down Expand Up @@ -657,11 +640,8 @@ fn autopack_shared_library(

let library_dirs = library_dir_resource_paths
.into_iter()
.map(|resource_path| {
<Vec<u8>>::from_path_buf(resource_path)
.map_err(|_| eyre::eyre!("invalid UTF-8 in path"))
})
.collect::<eyre::Result<Vec<_>>>()?;
.map(|resource_path| resource_path.into_os_string().into_vec())
.collect();
let pack = brioche_pack::Pack::Static { library_dirs };

if !pack.should_add_to_executable() && !shared_library_config.allow_empty {
Expand Down Expand Up @@ -756,27 +736,18 @@ fn autopack_script(
.filter_map(|component| match component {
runnable_core::TemplateComponent::Literal { .. }
| runnable_core::TemplateComponent::RelativePath { .. } => None,
runnable_core::TemplateComponent::Resource { resource } => Some(
resource
.to_path()
.map_err(|_| eyre::eyre!("invalid resource path")),
),
})
.collect::<eyre::Result<Vec<_>>>()?;
runnable_core::TemplateComponent::Resource { resource } => {
Some(PathBuf::from(OsStr::from_bytes(resource)))
}
});

let resource_paths = [command_resource.clone(), script_resource.clone()]
.into_iter()
.chain(
env_resource_paths
.into_iter()
.map(std::borrow::ToOwned::to_owned),
)
.map(|path| {
Vec::<u8>::from_path_buf(path).map_err(|_| eyre::eyre!("invalid resource path"))
})
.collect::<eyre::Result<Vec<_>>>()?;
.chain(env_resource_paths)
.map(|path| path.into_os_string().into_vec())
.collect();

let command = runnable_core::Template::from_resource_path(command_resource)?;
let command = runnable_core::Template::from_resource_path(command_resource);

let mut args = vec![];
if let Some(arg) = arg {
Expand All @@ -785,7 +756,7 @@ fn autopack_script(
});
}
args.push(runnable_core::ArgValue::Arg {
value: runnable_core::Template::from_resource_path(script_resource.clone())?,
value: runnable_core::Template::from_resource_path(script_resource.clone()),
});
args.push(runnable_core::ArgValue::Rest);

Expand All @@ -799,7 +770,7 @@ fn autopack_script(
env,
clear_env: script_config.clear_env,
source: Some(runnable_core::RunnableSource {
path: runnable_core::RunnablePath::from_resource_path(script_resource)?,
path: runnable_core::RunnablePath::from_resource_path(script_resource),
}),
};
let pack = brioche_pack::Pack::Metadata {
Expand Down Expand Up @@ -1001,9 +972,7 @@ fn collect_all_library_dirs(
};

for library_dir in library_dirs {
let Ok(library_dir) = library_dir.to_path() else {
continue;
};
let library_dir = Path::new(OsStr::from_bytes(library_dir));
let Some(library_dir_path) = brioche_resources::find_in_resource_dirs(
&ctx.config.all_resource_dirs,
library_dir,
Expand Down
1 change: 0 additions & 1 deletion crates/brioche-ld/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ rust-version.workspace = true
brioche-autopack = { path = "../brioche-autopack" }
brioche-pack = { workspace = true }
brioche-resources = { path = "../brioche-resources" }
bstr = "1.12.1"
chumsky = "0.12.0"
eyre = "0.6.12"
thiserror = "2.0.17"
Expand Down
50 changes: 26 additions & 24 deletions crates/brioche-ld/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use std::{
collections::{HashSet, VecDeque},
ffi::{OsStr, OsString},
io::Read,
path::PathBuf,
os::unix::ffi::{OsStrExt as _, OsStringExt as _},
path::{Path, PathBuf},
process::ExitCode,
};

use bstr::{ByteSlice as _, ByteVec as _};
use chumsky::prelude::*;
use eyre::{Context as _, OptionExt as _};

Expand Down Expand Up @@ -64,40 +65,35 @@ fn run() -> eyre::Result<ExitCode> {

let mut args: VecDeque<_> = std::env::args_os().skip(1).collect();
while let Some(arg) = args.pop_front() {
let arg = <[u8]>::from_os_str(&arg).ok_or_eyre("invalid arg")?;
let arg = bstr::BStr::new(arg);
let arg = arg.as_bytes();

if &**arg == b"-o" {
if arg == b"-o" {
let output = args.pop_front().ok_or_eyre("invalid arg")?;
output_path = Some(PathBuf::from(output));
} else if let Some(output) = arg.strip_prefix(b"-o") {
let output = output.to_path().map_err(|_| eyre::eyre!("invalid path"))?;
let output = Path::new(OsStr::from_bytes(output));
output_path = Some(output.to_path_buf());
} else if &**arg == b"-L" {
} else if arg == b"-L" {
let lib_path = args.pop_front().ok_or_eyre("invalid arg")?;
library_search_paths.push(PathBuf::from(lib_path));
} else if let Some(lib_path) = arg.strip_prefix(b"-L") {
let lib_path = lib_path
.to_path()
.map_err(|_| eyre::eyre!("invalid path"))?;
let lib_path = Path::new(OsStr::from_bytes(lib_path));
library_search_paths.push(lib_path.to_owned());
} else if &**arg == b"--help" || &**arg == b"--version" || &**arg == b"-v" {
} else if arg == b"--help" || arg == b"--version" || arg == b"-v" {
// Skip packing if we're just showing help or version info
output_path = None;
} else if arg.starts_with(b"-") {
// Ignore other arguments
} else if let Some(arg_file_path) = arg.strip_prefix(b"@") {
let arg_file_path = arg_file_path
.to_path()
.map_err(|_| eyre::eyre!("invalid path"))?;
let arg_file_path = Path::new(OsStr::from_bytes(arg_file_path));

// `@file` arg. Arguments are parsed and read from `file`
file_dereferences += 1;
if file_dereferences > MAX_FILE_DEREFERENCES {
eyre::bail!("encountered more than {MAX_FILE_DEREFERENCES} '@file' arguments");
}

let mut file_contents = Vec::<u8>::new();
let mut file_contents = Vec::new();
let mut file = std::fs::File::open(arg_file_path).wrap_err_with(|| {
format!("failed to read args from path {}", arg_file_path.display())
})?;
Expand All @@ -118,11 +114,11 @@ fn run() -> eyre::Result<ExitCode> {
// Add each parsed arg to the start of `args`, so they will get
// processed in place of the `@file` arg
for new_arg in args_from_file.into_iter().rev() {
let new_arg = Vec::from(new_arg).into_os_string()?;
let new_arg = OsString::from_vec(new_arg);
args.push_front(new_arg);
}
} else {
let input_path = arg.to_path().map_err(|_| eyre::eyre!("invalid path"))?;
let input_path = Path::new(OsStr::from_bytes(arg));
input_paths.push(input_path.to_owned());
}
}
Expand Down Expand Up @@ -205,8 +201,7 @@ fn run() -> eyre::Result<ExitCode> {
Ok(ExitCode::SUCCESS)
}

fn file_args_parser<'a>() -> impl Parser<'a, &'a [u8], Vec<bstr::BString>, extra::Err<Rich<'a, u8>>>
{
fn file_args_parser<'a>() -> impl Parser<'a, &'a [u8], Vec<Vec<u8>>, extra::Err<Rich<'a, u8>>> {
let escape = just(b'\\').ignore_then(any());
let bare_arg = none_of(b"\\\"' \t\r\n\x0C")
.or(escape)
Expand All @@ -226,8 +221,7 @@ fn file_args_parser<'a>() -> impl Parser<'a, &'a [u8], Vec<bstr::BString>, extra
let arg = bare_arg
.or(double_quoted_arg)
.or(single_quoted_arg)
.padded()
.map(bstr::BString::new);
.padded();
arg.repeated().collect()
}

Expand All @@ -243,15 +237,23 @@ mod tests {
fn test_file_args_parser() {
let parser = file_args_parser();
assert_eq!(parser.parse(b"").unwrap(), EMPTY_OUTPUT);
assert_eq!(parser.parse(b"foo").unwrap(), ["foo"]);
assert_eq!(parser.parse(b"foo bar baz").unwrap(), ["foo", "bar", "baz"]);
assert_eq!(parser.parse(b"foo").unwrap(), [b"foo"]);
assert_eq!(
parser.parse(b"foo bar baz").unwrap(),
[b"foo", b"bar", b"baz"]
);
assert_eq!(parser.parse(b"\"\"").unwrap(), [b""]);
assert_eq!(parser.parse(b"''").unwrap(), [b""]);
assert_eq!(
parser
.parse(b"a \"bcd'ef'\\\\\\\"gh\" \r\n 'ijk\\'' \"lmn \t opq\\\"\"")
.unwrap(),
["a", "bcd'ef'\\\"gh", "ijk'", "lmn \t opq\""],
[
&b"a"[..],
&b"bcd'ef'\\\"gh"[..],
&b"ijk'"[..],
&b"lmn \t opq\""[..]
],
);
assert_eq!(
parser.parse(b"a \x00\xFF b").unwrap(),
Expand Down
1 change: 0 additions & 1 deletion crates/brioche-packed-plain-exec/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ rust-version.workspace = true
[dependencies]
brioche-pack = { workspace = true }
brioche-resources = { path = "../brioche-resources" }
bstr = "1.12.1"
libc = "0.2.180"
runnable-core = { path = "../runnable-core" }
serde_json = "1.0.149"
Expand Down
Loading