From a594261ff6224780c102a7b9da2a2f34511e32a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Audiger?= Date: Thu, 15 Jan 2026 20:31:08 +0100 Subject: [PATCH] refactor; remove the crate `bstr` from the dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérémy Audiger --- Cargo.lock | 8 -- crates/brioche-autopack/Cargo.toml | 1 - crates/brioche-autopack/src/lib.rs | 87 ++++++------------- crates/brioche-ld/Cargo.toml | 1 - crates/brioche-ld/src/main.rs | 50 ++++++----- crates/brioche-packed-plain-exec/Cargo.toml | 1 - crates/brioche-packed-plain-exec/src/main.rs | 80 ++++------------- .../brioche-packed-userland-exec/Cargo.toml | 1 - .../brioche-packed-userland-exec/src/linux.rs | 35 +++----- crates/brioche-packer/Cargo.toml | 1 - .../brioche-packer/src/autopack_template.rs | 5 +- crates/brioche-packer/src/main.rs | 12 ++- crates/brioche-resources/Cargo.toml | 1 - crates/brioche-resources/src/lib.rs | 22 ++--- crates/brioche-strip/Cargo.toml | 1 - crates/brioche-strip/src/main.rs | 60 ++++++------- crates/runnable-core/Cargo.toml | 1 - crates/runnable-core/src/lib.rs | 40 ++++----- 18 files changed, 147 insertions(+), 260 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db34207..1944631 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -185,7 +185,6 @@ version = "0.1.0" dependencies = [ "brioche-pack", "brioche-resources", - "bstr", "eyre", "globset", "goblin 0.10.4", @@ -210,7 +209,6 @@ dependencies = [ "brioche-autopack", "brioche-pack", "brioche-resources", - "bstr", "chumsky", "eyre", "thiserror", @@ -235,7 +233,6 @@ version = "0.1.1" dependencies = [ "brioche-pack", "brioche-resources", - "bstr", "libc", "runnable-core", "serde_json", @@ -249,7 +246,6 @@ dependencies = [ "bincode", "brioche-pack", "brioche-resources", - "bstr", "cfg-if", "libc", "thiserror", @@ -263,7 +259,6 @@ dependencies = [ "brioche-autopack", "brioche-pack", "brioche-resources", - "bstr", "clap", "color-eyre", "eyre", @@ -282,7 +277,6 @@ name = "brioche-resources" version = "0.1.0" dependencies = [ "blake3", - "bstr", "copy_dir", "pathdiff", "thiserror", @@ -298,7 +292,6 @@ dependencies = [ "brioche-autopack", "brioche-pack", "brioche-resources", - "bstr", "eyre", "tempfile", "thiserror", @@ -994,7 +987,6 @@ version = "0.1.0" dependencies = [ "bincode", "brioche-resources", - "bstr", "schemars 1.2.0", "serde", "serde_with", diff --git a/crates/brioche-autopack/Cargo.toml b/crates/brioche-autopack/Cargo.toml index e2ccdce..99af9eb 100644 --- a/crates/brioche-autopack/Cargo.toml +++ b/crates/brioche-autopack/Cargo.toml @@ -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" diff --git a/crates/brioche-autopack/src/lib.rs b/crates/brioche-autopack/src/lib.rs index cad3960..b449238 100644 --- a/crates/brioche-autopack/src/lib.rs +++ b/crates/brioche-autopack/src/lib.rs @@ -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( @@ -14,11 +15,9 @@ pub fn pack_source( ) -> eyre::Result { 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) } @@ -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!( @@ -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:?}"))? } }; @@ -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 = >::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, @@ -559,24 +548,18 @@ fn autopack_dynamic_binary( pending_paths, )?; - let program = >::from_path_buf(program_resource_path) - .map_err(|_| eyre::eyre!("invalid UTF-8 in path"))?; - let interpreter = >::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| { - >::from_path_buf(resource_path) - .map_err(|_| eyre::eyre!("invalid UTF-8 in path")) - }) - .collect::>>()?; + .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:?}"))?; - >::from_path_buf(path) - .map_err(|_| eyre::eyre!("invalid UTF-8 in path")) + eyre::Ok(path.into_os_string().into_vec()) }) .collect::>>()?; @@ -657,11 +640,8 @@ fn autopack_shared_library( let library_dirs = library_dir_resource_paths .into_iter() - .map(|resource_path| { - >::from_path_buf(resource_path) - .map_err(|_| eyre::eyre!("invalid UTF-8 in path")) - }) - .collect::>>()?; + .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 { @@ -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::>>()?; + 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::::from_path_buf(path).map_err(|_| eyre::eyre!("invalid resource path")) - }) - .collect::>>()?; + .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 { @@ -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); @@ -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 { @@ -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, diff --git a/crates/brioche-ld/Cargo.toml b/crates/brioche-ld/Cargo.toml index cda3c86..434bec2 100644 --- a/crates/brioche-ld/Cargo.toml +++ b/crates/brioche-ld/Cargo.toml @@ -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" diff --git a/crates/brioche-ld/src/main.rs b/crates/brioche-ld/src/main.rs index b2703f2..a886d1f 100644 --- a/crates/brioche-ld/src/main.rs +++ b/crates/brioche-ld/src/main.rs @@ -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 _}; @@ -64,32 +65,27 @@ fn run() -> eyre::Result { 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; @@ -97,7 +93,7 @@ fn run() -> eyre::Result { eyre::bail!("encountered more than {MAX_FILE_DEREFERENCES} '@file' arguments"); } - let mut file_contents = Vec::::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()) })?; @@ -118,11 +114,11 @@ fn run() -> eyre::Result { // 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()); } } @@ -205,8 +201,7 @@ fn run() -> eyre::Result { Ok(ExitCode::SUCCESS) } -fn file_args_parser<'a>() -> impl Parser<'a, &'a [u8], Vec, extra::Err>> -{ +fn file_args_parser<'a>() -> impl Parser<'a, &'a [u8], Vec>, extra::Err>> { let escape = just(b'\\').ignore_then(any()); let bare_arg = none_of(b"\\\"' \t\r\n\x0C") .or(escape) @@ -226,8 +221,7 @@ fn file_args_parser<'a>() -> impl Parser<'a, &'a [u8], Vec, extra let arg = bare_arg .or(double_quoted_arg) .or(single_quoted_arg) - .padded() - .map(bstr::BString::new); + .padded(); arg.repeated().collect() } @@ -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(), diff --git a/crates/brioche-packed-plain-exec/Cargo.toml b/crates/brioche-packed-plain-exec/Cargo.toml index 6a5acc8..b1efd66 100644 --- a/crates/brioche-packed-plain-exec/Cargo.toml +++ b/crates/brioche-packed-plain-exec/Cargo.toml @@ -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" diff --git a/crates/brioche-packed-plain-exec/src/main.rs b/crates/brioche-packed-plain-exec/src/main.rs index f1a8841..80fafc9 100644 --- a/crates/brioche-packed-plain-exec/src/main.rs +++ b/crates/brioche-packed-plain-exec/src/main.rs @@ -1,6 +1,9 @@ -use std::{ffi::OsString, os::unix::process::CommandExt as _, path::PathBuf, process::ExitCode}; - -use bstr::ByteSlice as _; +use std::{ + ffi::OsStr, + os::unix::{ffi::OsStrExt as _, process::CommandExt as _}, + path::{Path, PathBuf}, + process::ExitCode, +}; const BRIOCHE_PACKED_ERROR: u8 = 121; @@ -36,11 +39,7 @@ fn run() -> Result<(), PackedError> { } => { let mut args = std::env::args_os(); - let interpreter = interpreter - .to_path() - .map_err(|_| PackedError::InvalidPathBytes { - path: interpreter.clone().into(), - })?; + let interpreter = Path::new(OsStr::from_bytes(&interpreter)); let interpreter = brioche_resources::find_in_resource_dirs(&resource_dirs, interpreter) .ok_or_else(|| PackedError::ResourceNotFound { resource: interpreter.to_owned(), @@ -50,23 +49,13 @@ fn run() -> Result<(), PackedError> { let mut resolved_library_dirs = vec![]; for library_dir in &runtime_library_dirs { - let library_dir = - library_dir - .to_path() - .map_err(|_| PackedError::InvalidPathBytes { - path: library_dir.clone().into(), - })?; + let library_dir = Path::new(OsStr::from_bytes(library_dir)); let resolved_library_dir = program_parent_path.join(library_dir); resolved_library_dirs.push(resolved_library_dir); } for library_dir in &library_dirs { - let library_dir = - library_dir - .to_path() - .map_err(|_| PackedError::InvalidPathBytes { - path: library_dir.clone().into(), - })?; + let library_dir = Path::new(OsStr::from_bytes(library_dir)); let library_dir = brioche_resources::find_in_resource_dirs(&resource_dirs, library_dir) .ok_or_else(|| PackedError::ResourceNotFound { @@ -76,40 +65,27 @@ fn run() -> Result<(), PackedError> { } if !resolved_library_dirs.is_empty() { - let mut ld_library_path = bstr::BString::default(); + let mut ld_library_path = Vec::new(); for (n, library_dir) in resolved_library_dirs.iter().enumerate() { if n > 0 { ld_library_path.push(b':'); } - let path = - <[u8]>::from_path(library_dir).ok_or_else(|| PackedError::InvalidPath { - path: library_dir.to_owned(), - })?; - ld_library_path.extend(path); + let path = library_dir.as_os_str().as_bytes(); + ld_library_path.extend_from_slice(path); } if let Some(env_library_path) = std::env::var_os("LD_LIBRARY_PATH") { - let env_library_path = - <[u8]>::from_os_str(&env_library_path).ok_or_else(|| { - PackedError::InvalidPathOsString { - path: env_library_path.clone(), - } - })?; + let env_library_path = env_library_path.as_bytes(); if !env_library_path.is_empty() { ld_library_path.push(b':'); - ld_library_path.extend(env_library_path); + ld_library_path.extend_from_slice(env_library_path); } } command.arg("--library-path"); - let ld_library_path = - ld_library_path - .to_os_str() - .map_err(|_| PackedError::InvalidPathBytes { - path: ld_library_path.clone(), - })?; + let ld_library_path = OsStr::from_bytes(&ld_library_path); command.arg(ld_library_path); } @@ -118,11 +94,7 @@ fn run() -> Result<(), PackedError> { command.arg(arg0); } - let program = program - .to_path() - .map_err(|_| PackedError::InvalidPathBytes { - path: program.clone().into(), - })?; + let program = Path::new(OsStr::from_bytes(&program)); let program = brioche_resources::find_in_resource_dirs(&resource_dirs, program) .ok_or_else(|| PackedError::ResourceNotFound { resource: program.to_owned(), @@ -197,12 +169,7 @@ fn run() -> Result<(), PackedError> { } runnable_core::EnvValue::Prepend { value, separator } => { let mut value = value.to_os_string(&program_path, &resource_dirs)?; - let separator = - separator - .to_os_str() - .map_err(|_| PackedError::InvalidUtf8 { - bytes: separator.clone().into(), - })?; + let separator = OsStr::from_bytes(separator); let current_value = std::env::var_os(env_name); let new_value = match current_value { @@ -218,12 +185,7 @@ fn run() -> Result<(), PackedError> { } runnable_core::EnvValue::Append { value, separator } => { let value = value.to_os_string(&program_path, &resource_dirs)?; - let separator = - separator - .to_os_str() - .map_err(|_| PackedError::InvalidUtf8 { - bytes: separator.clone().into(), - })?; + let separator = OsStr::from_bytes(separator); let current_value = std::env::var_os(env_name); let new_value = match current_value { @@ -266,12 +228,6 @@ enum PackedError { RepeatedArgs, #[error("resource not found: {resource}")] ResourceNotFound { resource: PathBuf }, - #[error("invalid UTF-8: {bytes:?}")] - InvalidUtf8 { bytes: bstr::BString }, - #[error("invalid path: {path:?}")] - InvalidPathBytes { path: bstr::BString }, #[error("invalid path: {path:?}")] InvalidPath { path: PathBuf }, - #[error("unconvertible path: {path:?}")] - InvalidPathOsString { path: OsString }, } diff --git a/crates/brioche-packed-userland-exec/Cargo.toml b/crates/brioche-packed-userland-exec/Cargo.toml index 61544ae..958cb2f 100644 --- a/crates/brioche-packed-userland-exec/Cargo.toml +++ b/crates/brioche-packed-userland-exec/Cargo.toml @@ -8,7 +8,6 @@ rust-version.workspace = true bincode = "2.0.0-rc.3" brioche-pack = { workspace = true } brioche-resources = { path = "../brioche-resources" } -bstr = "1.12.1" cfg-if = "1.0.4" libc = "0.2.180" thiserror = "2.0.17" diff --git a/crates/brioche-packed-userland-exec/src/linux.rs b/crates/brioche-packed-userland-exec/src/linux.rs index f0d9b1f..bb173e7 100644 --- a/crates/brioche-packed-userland-exec/src/linux.rs +++ b/crates/brioche-packed-userland-exec/src/linux.rs @@ -1,8 +1,8 @@ #![cfg(target_os = "linux")] -use std::ffi::{CStr, CString}; - -use bstr::ByteSlice as _; +use std::ffi::{CStr, CString, OsStr}; +use std::os::unix::ffi::OsStrExt as _; +use std::path::Path; const BRIOCHE_PACKED_ERROR: u8 = 121; @@ -63,35 +63,29 @@ fn run(args: &[&CStr], env_vars: &[&CStr]) -> Result<(), PackedError> { library_dirs, runtime_library_dirs, } => { - let interpreter = interpreter - .to_path() - .map_err(|_| PackedError::InvalidPath)?; + let interpreter = Path::new(OsStr::from_bytes(&interpreter)); let interpreter = brioche_resources::find_in_resource_dirs(&resource_dirs, interpreter) .ok_or(PackedError::ResourceNotFound)?; - let program = program.to_path().map_err(|_| PackedError::InvalidPath)?; + let program = Path::new(OsStr::from_bytes(&program)); let program = brioche_resources::find_in_resource_dirs(&resource_dirs, program) .ok_or(PackedError::ResourceNotFound)?; let program = program.canonicalize()?; let mut exec = userland_execve::ExecOptions::new(&interpreter); - let interpreter = <[u8]>::from_path(&interpreter).ok_or(PackedError::InvalidPath)?; + let interpreter = interpreter.as_os_str().as_bytes(); let interpreter = CString::new(interpreter).map_err(|_| PackedError::InvalidPath)?; let mut resolved_library_dirs = vec![]; for library_dir in &runtime_library_dirs { - let library_dir = library_dir - .to_path() - .map_err(|_| PackedError::InvalidPath)?; + let library_dir = Path::new(OsStr::from_bytes(library_dir)); let resolved_library_dir = parent_path.join(library_dir); resolved_library_dirs.push(resolved_library_dir); } for library_dir in &library_dirs { - let library_dir = library_dir - .to_path() - .map_err(|_| PackedError::InvalidPath)?; + let library_dir = Path::new(OsStr::from_bytes(library_dir)); let library_dir = brioche_resources::find_in_resource_dirs(&resource_dirs, library_dir) .ok_or(PackedError::ResourceNotFound)?; @@ -102,22 +96,21 @@ fn run(args: &[&CStr], env_vars: &[&CStr]) -> Result<(), PackedError> { exec.arg(interpreter); if !resolved_library_dirs.is_empty() { - let mut ld_library_path = bstr::BString::default(); + let mut ld_library_path = Vec::new(); for (n, library_dir) in resolved_library_dirs.iter().enumerate() { if n > 0 { ld_library_path.push(b':'); } - let path = <[u8]>::from_path(library_dir).ok_or(PackedError::InvalidPath)?; - ld_library_path.extend(path); + let path = library_dir.as_os_str().as_bytes(); + ld_library_path.extend_from_slice(path); } if let Some(env_library_path) = std::env::var_os("LD_LIBRARY_PATH") { - let env_library_path = - <[u8]>::from_os_str(&env_library_path).ok_or(PackedError::InvalidPath)?; + let env_library_path = env_library_path.as_bytes(); if !env_library_path.is_empty() { ld_library_path.push(b':'); - ld_library_path.extend(env_library_path); + ld_library_path.extend_from_slice(env_library_path); } } @@ -134,7 +127,7 @@ fn run(args: &[&CStr], env_vars: &[&CStr]) -> Result<(), PackedError> { exec.arg(arg0); } - let program = <[u8]>::from_path(&program).ok_or(PackedError::InvalidPath)?; + let program = program.as_os_str().as_bytes(); let program = CString::new(program).map_err(|_| PackedError::InvalidPath)?; exec.arg(program); diff --git a/crates/brioche-packer/Cargo.toml b/crates/brioche-packer/Cargo.toml index fa73c5c..29aa6de 100644 --- a/crates/brioche-packer/Cargo.toml +++ b/crates/brioche-packer/Cargo.toml @@ -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" clap = { version = "4.5.54", features = ["derive"] } color-eyre = "0.6.5" eyre = "0.6.12" diff --git a/crates/brioche-packer/src/autopack_template.rs b/crates/brioche-packer/src/autopack_template.rs index d3511e7..8c15dee 100644 --- a/crates/brioche-packer/src/autopack_template.rs +++ b/crates/brioche-packer/src/autopack_template.rs @@ -1,9 +1,9 @@ use std::{ collections::{HashMap, HashSet}, + os::unix::ffi::OsStringExt as _, path::{Path, PathBuf}, }; -use bstr::ByteVec as _; use runnable_core::encoding::TickEncoded; pub struct AutopackConfigTemplateContext { @@ -426,8 +426,7 @@ impl EnvValueTemplateValueComponent { path, env_var, )?; - let resource = >::from_path_buf(resource) - .map_err(|_| eyre::eyre!("invalid path"))?; + let resource = resource.into_os_string().into_vec(); Ok(runnable_core::TemplateComponent::Resource { resource }) } } diff --git a/crates/brioche-packer/src/main.rs b/crates/brioche-packer/src/main.rs index cca1f36..a4ba1e8 100644 --- a/crates/brioche-packer/src/main.rs +++ b/crates/brioche-packer/src/main.rs @@ -1,11 +1,12 @@ use std::{ + ffi::OsStr, io::Seek as _, + os::unix::ffi::{OsStrExt as _, OsStringExt as _}, os::unix::fs::OpenOptionsExt as _, path::{Path, PathBuf}, process::ExitCode, }; -use bstr::{ByteSlice as _, ByteVec as _}; use clap::Parser; use eyre::{Context as _, OptionExt as _}; @@ -220,10 +221,8 @@ fn run_update_source(args: &UpdateSourceArgs) -> eyre::Result<()> { library_dirs, runtime_library_dirs, } => { - let program = program - .to_path() - .map_err(|_| eyre::eyre!("invalid program path: {}", bstr::BStr::new(&program)))?; - let program_name = program + let program_path = Path::new(OsStr::from_bytes(&program)); + let program_name = program_path .file_name() .ok_or_eyre("could not get program name from path")?; let new_name = args @@ -245,8 +244,7 @@ fn run_update_source(args: &UpdateSourceArgs) -> eyre::Result<()> { is_executable, new_name, )?; - let new_source_resource = >::from_path_buf(new_source_resource) - .map_err(|_| eyre::eyre!("invalid UTF-8 in path"))?; + let new_source_resource = new_source_resource.into_os_string().into_vec(); let new_pack = brioche_pack::Pack::LdLinux { program: new_source_resource, diff --git a/crates/brioche-resources/Cargo.toml b/crates/brioche-resources/Cargo.toml index 264f9b1..f4a7fd3 100644 --- a/crates/brioche-resources/Cargo.toml +++ b/crates/brioche-resources/Cargo.toml @@ -6,7 +6,6 @@ rust-version.workspace = true [dependencies] blake3 = "1.8.3" -bstr = "1.12.1" copy_dir = "0.1.3" pathdiff = "0.2.3" thiserror = "2.0.17" diff --git a/crates/brioche-resources/src/lib.rs b/crates/brioche-resources/src/lib.rs index 1a7a688..8dfc5be 100644 --- a/crates/brioche-resources/src/lib.rs +++ b/crates/brioche-resources/src/lib.rs @@ -1,11 +1,13 @@ use std::{ + ffi::OsStr, io::Write as _, - os::unix::fs::{OpenOptionsExt as _, PermissionsExt as _}, + os::unix::{ + ffi::OsStrExt as _, + fs::{OpenOptionsExt as _, PermissionsExt as _}, + }, path::{Path, PathBuf}, }; -use bstr::ByteSlice as _; - const SEARCH_DEPTH_LIMIT: u32 = 64; pub fn find_resource_dirs( @@ -20,16 +22,10 @@ pub fn find_resource_dirs( if include_readonly && let Some(input_resource_dirs) = std::env::var_os("BRIOCHE_INPUT_RESOURCE_DIRS") { - if let Some(input_resource_dirs) = <[u8]>::from_os_str(&input_resource_dirs) { - for input_resource_dir in input_resource_dirs.split_str(b":") { - if let Ok(path) = input_resource_dir.to_path() { - paths.push(path.to_owned()); - } - } - } - - for input_resource_dir in std::env::split_paths(&input_resource_dirs) { - paths.push(input_resource_dir); + let input_resource_dirs_bytes = input_resource_dirs.as_bytes(); + for input_resource_dir in input_resource_dirs_bytes.split(|&b| b == b':') { + let path = Path::new(OsStr::from_bytes(input_resource_dir)); + paths.push(path.to_owned()); } } diff --git a/crates/brioche-strip/Cargo.toml b/crates/brioche-strip/Cargo.toml index adc8470..c5d394b 100644 --- a/crates/brioche-strip/Cargo.toml +++ b/crates/brioche-strip/Cargo.toml @@ -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" eyre = "0.6.12" tempfile = "3.24.0" thiserror = "2.0.17" diff --git a/crates/brioche-strip/src/main.rs b/crates/brioche-strip/src/main.rs index 529fc8a..0a7f9c3 100644 --- a/crates/brioche-strip/src/main.rs +++ b/crates/brioche-strip/src/main.rs @@ -1,10 +1,11 @@ use std::{ + ffi::{OsStr, OsString}, io::{Read as _, Seek}, - path::PathBuf, + os::unix::ffi::{OsStrExt as _, OsStringExt as _}, + path::{Path, PathBuf}, process::ExitCode, }; -use bstr::{ByteSlice as _, ByteVec as _}; use eyre::{Context as _, OptionExt as _}; #[derive(Debug)] @@ -16,21 +17,18 @@ enum StripArg { } impl StripArg { - fn into_args(self) -> eyre::Result> { + fn into_args(self) -> Vec { match self { - Self::Arg(arg) => Ok(vec![arg]), + Self::Arg(arg) => vec![arg], Self::DashOPath(path) => { - let path_bytes = <[u8]>::from_path(&path).ok_or_eyre("invalid path")?; + let path_bytes = path.as_os_str().as_bytes(); let mut arg = b"-o".to_vec(); arg.extend_from_slice(path_bytes); - Ok(vec![arg.to_os_str()?.to_owned()]) + vec![OsString::from_vec(arg)] } - Self::DashOFollowedByPath(path) => Ok(vec![ - std::ffi::OsString::from("-o"), - std::ffi::OsString::from(path), - ]), - Self::InputPath(path) => Ok(vec![std::ffi::OsString::from(path)]), + Self::DashOFollowedByPath(path) => vec![OsString::from("-o"), OsString::from(path)], + Self::InputPath(path) => vec![OsString::from(path)], } } } @@ -84,10 +82,9 @@ fn run() -> eyre::Result { // Parse each argument while let Some(arg) = args.next() { - let arg_bytes = <[u8]>::from_os_str(&arg).ok_or_eyre("invalid arg")?; - let arg_bytes = bstr::BStr::new(arg_bytes); + let arg_bytes = arg.as_bytes(); - match &**arg_bytes { + match arg_bytes { b"-F" | b"--target" | b"-I" @@ -116,7 +113,7 @@ fn run() -> eyre::Result { _ => { if let Some(output) = arg_bytes.strip_prefix(b"-o") { // Support "-o" syntax - let output = output.to_path().map_err(|_| eyre::eyre!("invalid path"))?; + let output = Path::new(OsStr::from_bytes(output)); strip_args.push(StripArg::DashOPath(output.to_path_buf())); } else if arg_bytes.starts_with(b"-") { // Pass through any extra argument starting with a "-" @@ -127,9 +124,7 @@ fn run() -> eyre::Result { eyre::bail!("using @ for passing args is not supported"); } else { // Other args are treated as input files - let input_path = arg_bytes - .to_path() - .map_err(|_| eyre::eyre!("invalid path"))?; + let input_path = Path::new(OsStr::from_bytes(arg_bytes)); strip_args.push(StripArg::InputPath(input_path.to_owned())); } } @@ -141,14 +136,14 @@ fn run() -> eyre::Result { remap_files(&mut strip_args, &mut remapped_files)?; // Convert the remapped args back into an argument list - let strip_args = strip_args + let strip_args: Vec<_> = strip_args .into_iter() - .map(StripArg::into_args) - .collect::>>()?; + .flat_map(StripArg::into_args) + .collect(); // Call the original strip process let mut command = std::process::Command::new(strip); - command.args(strip_args.iter().flatten()); + command.args(strip_args); let status = command.status()?; if !status.success() { @@ -419,19 +414,19 @@ fn finish_remapped_file(remapped_file: RemapFile) -> eyre::Result<()> { runtime_library_dirs, } => { // Get the original program name - let program = program.to_path().map_err(|_| { - eyre::eyre!("invalid program path: {}", bstr::BStr::new(&program)) - })?; - let program_name = program + let program_path = Path::new(OsStr::from_bytes(&program)); + let program_name = program_path .file_name() .ok_or_eyre("could not get program name from path")?; - let program_name = std::path::Path::new(program_name); + let program_name = Path::new(program_name); // Determine if the original program was executable - let program_path = - brioche_resources::find_in_resource_dirs(&input_resource_dirs, program) - .ok_or_eyre("could not find program in resource dirs")?; - let program_metadata = std::fs::metadata(&program_path) + let program_resource_path = brioche_resources::find_in_resource_dirs( + &input_resource_dirs, + program_path, + ) + .ok_or_eyre("could not find program in resource dirs")?; + let program_metadata = std::fs::metadata(&program_resource_path) .context("could not get program metadata")?; let is_executable = is_executable(&program_metadata.permissions()); @@ -445,8 +440,7 @@ fn finish_remapped_file(remapped_file: RemapFile) -> eyre::Result<()> { is_executable, program_name, )?; - let new_source_resource = >::from_path_buf(new_source_resource) - .map_err(|_| eyre::eyre!("invalid UTF-8 in path"))?; + let new_source_resource = new_source_resource.into_os_string().into_vec(); // Re-use the same details from the pack, but with the // new resource created from the temp file diff --git a/crates/runnable-core/Cargo.toml b/crates/runnable-core/Cargo.toml index 91706c1..41a5593 100644 --- a/crates/runnable-core/Cargo.toml +++ b/crates/runnable-core/Cargo.toml @@ -7,7 +7,6 @@ rust-version.workspace = true [dependencies] bincode = "2.0.0-rc.3" brioche-resources = { path = "../brioche-resources" } -bstr = "1.12.1" schemars = "1.2.0" serde = { version = "1.0.228", features = ["derive"] } serde_with = { version = "3.16.1", features = ["schemars_1"] } diff --git a/crates/runnable-core/src/lib.rs b/crates/runnable-core/src/lib.rs index 424cecc..0e16b2b 100644 --- a/crates/runnable-core/src/lib.rs +++ b/crates/runnable-core/src/lib.rs @@ -1,6 +1,7 @@ +use std::ffi::OsStr; +use std::os::unix::ffi::{OsStrExt as _, OsStringExt as _}; use std::path::{Path, PathBuf}; -use bstr::{ByteSlice as _, ByteVec as _}; use encoding::TickEncoded; pub mod encoding; @@ -116,12 +117,12 @@ impl Template { } } - pub fn from_resource_path(resource_path: PathBuf) -> Result { - let resource = Vec::::from_path_buf(resource_path) - .map_err(|_| RunnableTemplateError::PathError)?; - Ok(Self { + #[must_use] + pub fn from_resource_path(resource_path: PathBuf) -> Self { + let resource = resource_path.into_os_string().into_vec(); + Self { components: vec![TemplateComponent::Resource { resource }], - }) + } } pub fn to_os_string( @@ -134,24 +135,23 @@ impl Template { for component in &self.components { match component { TemplateComponent::Literal { value } => { - let value = value.to_os_str()?; + let value = OsStr::from_bytes(value); os_string.push(value); } TemplateComponent::RelativePath { path } => { let program_dir = program .parent() .ok_or(RunnableTemplateError::InvalidProgramPath)?; - let path = path.to_path()?; + let path = Path::new(OsStr::from_bytes(path)); let path = program_dir.join(path); os_string.push(path); } TemplateComponent::Resource { resource } => { - let resource_subpath = resource.to_path()?; + let resource_subpath = Path::new(OsStr::from_bytes(resource)); let resource_path = brioche_resources::find_in_resource_dirs(resource_dirs, resource_subpath) - .ok_or_else(|| { - let resource = bstr::BString::new(resource.clone()); - RunnableTemplateError::ResourceNotFound { resource } + .ok_or_else(|| RunnableTemplateError::ResourceNotFound { + resource: resource.clone(), })?; os_string.push(resource_path); } @@ -231,25 +231,21 @@ pub enum RunnablePath { } impl RunnablePath { - pub fn from_resource_path(resource_path: PathBuf) -> Result { - let resource = Vec::::from_path_buf(resource_path) - .map_err(|_| RunnableTemplateError::PathError)?; - Ok(Self::Resource { resource }) + #[must_use] + pub fn from_resource_path(resource_path: PathBuf) -> Self { + let resource = resource_path.into_os_string().into_vec(); + Self::Resource { resource } } } #[derive(Debug, thiserror::Error)] pub enum RunnableTemplateError { - #[error("invalid UTF-8 in runnable template: {0}")] - Utf8Error(#[from] bstr::Utf8Error), - #[error("invalid path in runnable template")] - PathError, #[error("invalid program path")] InvalidProgramPath, #[error(transparent)] PackResourceDirError(#[from] brioche_resources::PackResourceDirError), - #[error("resource not found: {resource}")] - ResourceNotFound { resource: bstr::BString }, + #[error("resource not found: {}", String::from_utf8_lossy(.resource))] + ResourceNotFound { resource: Vec }, #[error("tried prepending and appending to env var")] PrependAndAppend, }