Skip to content

Commit

Permalink
fix(bin): semi-preserve file modes and make binaries executable (#259)
Browse files Browse the repository at this point in the history
Fixes: #250

This makes sure that:

1. All files extracted are writable.
2. The mode that was set on the tarball files is preserved (while ensuring rw perms for owner)
3. Any files being used as package bins are executable
  • Loading branch information
zkat committed Apr 24, 2023
1 parent 3c1cd69 commit f01ed09
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 30 deletions.
89 changes: 89 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -111,6 +111,7 @@ regex = "1.7.2"
reqwest = "0.11.14"
reqwest-middleware = "0.2.0"
resvg = "0.29.0"
rkyv = "0.7.41"
serde = "1.0.152"
serde_json = "1.0.93"
serde-wasm-bindgen = "0.4.5"
Expand Down
1 change: 1 addition & 0 deletions crates/nassun/Cargo.toml
Expand Up @@ -49,6 +49,7 @@ backon = { workspace = true }
cacache = { workspace = true }
flate2 = { workspace = true }
io_tee = { workspace = true }
rkyv = { workspace = true, features = ["validation"] }
tar = { workspace = true }
tempfile = { workspace = true }
which = { workspace = true }
Expand Down
10 changes: 10 additions & 0 deletions crates/nassun/src/error.rs
Expand Up @@ -69,6 +69,11 @@ pub enum NassunError {
#[diagnostic(code(nassun::cache::extract), url(docsrs))]
ExtractCacheError(#[source] cacache::Error, Option<PathBuf>),

#[cfg(not(target_arch = "wasm32"))]
#[error("Missing file index for cache entry for {0}.")]
#[diagnostic(code(nassun::cache::missing_index), url(docsrs))]
CacheMissingIndexError(String),

/// A generic IO error occurred. Refer tot he error message for more
/// details.
#[error(transparent)]
Expand Down Expand Up @@ -155,6 +160,11 @@ pub enum NassunError {
#[diagnostic(code(nassun::dummy_no_name), url(docsrs))]
DummyNoName,

/// An error occurred while serializing tarball metadata to cache.
#[error("Failed to serialize tarball metadata to cache: {0}")]
#[diagnostic(code(nassun::cache::serialize), url(docsrs))]
SerializeCacheError(String),

/// A miscellaneous, usually internal error. This is used mainly to wrap
/// either manual InternalErrors, or those using external errors that
/// don't implement std::error::Error.
Expand Down
39 changes: 30 additions & 9 deletions crates/nassun/src/package.rs
Expand Up @@ -15,6 +15,8 @@ use crate::error::Result;
use crate::fetch::PackageFetcher;
use crate::resolver::PackageResolution;
use crate::tarball::Tarball;
#[cfg(not(target_arch = "wasm32"))]
use crate::tarball::TarballIndex;

/// A resolved package. A concrete version has been determined from its
/// PackageSpec by the version resolver.
Expand Down Expand Up @@ -254,20 +256,26 @@ impl Package {
dir: &Path,
cache: &Path,
entry: cacache::Metadata,
prefer_copy: bool,
mut prefer_copy: bool,
validate: bool,
) -> Result<()> {
let dir = PathBuf::from(dir);
let cache = PathBuf::from(cache);
let name = self.name().to_owned();
async_std::task::spawn_blocking(move || {
let mut created = std::collections::HashSet::new();
let map = entry
.metadata
.as_object()
.expect("how is this not an object?");
for (path, sri) in map {
let sri: Integrity = sri.as_str().expect("how is this not a string?").parse()?;
let path = dir.join(path);
let index = unsafe {
rkyv::util::archived_root::<TarballIndex>(
entry
.raw_metadata
.as_ref()
.ok_or_else(|| NassunError::CacheMissingIndexError(name))?,
)
};
prefer_copy = index.should_copy || prefer_copy;
for (path, (sri, mode)) in index.files.iter() {
let sri: Integrity = sri.parse()?;
let path = dir.join(&path[..]);
let parent = PathBuf::from(path.parent().expect("this will always have a parent"));
if !created.contains(&parent) {
std::fs::create_dir_all(path.parent().expect("this will always have a parent"))
Expand All @@ -281,7 +289,20 @@ impl Package {
created.insert(parent);
}

crate::tarball::extract_from_cache(&cache, &sri, &path, prefer_copy, validate)?;
crate::tarball::extract_from_cache(
&cache,
&sri,
&path,
prefer_copy,
validate,
*mode,
)?;
}
#[cfg(unix)]
for binpath in index.bin_paths.iter() {
{
crate::tarball::set_bin_mode(&dir.join(&binpath[..]))?;
}
}
Ok::<_, NassunError>(())
})
Expand Down

0 comments on commit f01ed09

Please sign in to comment.