Skip to content

Commit

Permalink
Use object for parsing archives, and handle macOS fat archives
Browse files Browse the repository at this point in the history
  • Loading branch information
alex committed May 26, 2023
1 parent b2faf16 commit d757cc9
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 19 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

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

7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ nix = { version = "0.26.2", optional = true }
rouille = { version = "3.5", optional = true, default-features = false, features = ["ssl"] }
syslog = { version = "6", optional = true }
version-compare = { version = "0.1.1", optional = true }
object = "0.30"

[dev-dependencies]
assert_cmd = "2.0.10"
Expand Down Expand Up @@ -115,9 +116,9 @@ features = [
[features]
default = ["all"]
all = ["dist-client", "redis", "s3", "memcached", "gcs", "azure", "gha", "webdav"]
azure = ["opendal","reqsign"]
s3 = ["opendal","reqsign"]
gcs = ["opendal","reqsign", "url", "reqwest/blocking"]
azure = ["opendal", "reqsign"]
s3 = ["opendal", "reqsign"]
gcs = ["opendal", "reqsign", "url", "reqwest/blocking"]
gha = ["opendal"]
webdav = ["opendal"]
memcached = ["opendal/services-memcached"]
Expand Down
38 changes: 22 additions & 16 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
// limitations under the License.

use crate::mock_command::{CommandChild, RunCommand};
use ar::Archive;
use blake3::Hasher as blake3_Hasher;
use byteorder::{BigEndian, ByteOrder};
use fs::File;
use fs_err as fs;
use object::{macho, read::archive::ArchiveFile, read::macho::FatArch};
use serde::Serialize;
use std::ffi::{OsStr, OsString};
use std::hash::Hasher;
Expand Down Expand Up @@ -145,13 +145,22 @@ pub async fn hash_all_archives(
let path = path.clone();
pool.spawn_blocking(move || -> Result<String> {
let mut m = Digest::new();
let reader = File::open(&path)
let data = fs::read(&path)
.with_context(|| format!("Failed to open file for hashing: {:?}", path))?;
let mut archive = Archive::new(reader);
while let Some(entry) = archive.next_entry() {
let entry = entry?;
m.update(entry.header().identifier());
update_from_reader(&mut m, entry)?;

match macho::FatHeader::parse(&*data) {
Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC => {
for arch in macho::FatHeader::parse_arch32(&*data)? {
hash_regular_archive(&mut m, arch.data(&*data)?)?;
}
}
Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC_64 => {
for arch in macho::FatHeader::parse_arch64(&*data)? {
hash_regular_archive(&mut m, arch.data(&*data)?)?;
}
}
// Not a FatHeader at all, regular archive.
_ => hash_regular_archive(&mut m, &*data)?,
}
Ok(m.finish())
})
Expand All @@ -170,15 +179,12 @@ pub async fn hash_all_archives(
Ok(hashes.into_iter().map(|res| res.unwrap()).collect())
}

/// Update the digest `m` with all data from `reader`.
fn update_from_reader<R: Read>(m: &mut Digest, mut reader: R) -> Result<()> {
loop {
let mut buffer = [0; 1024];
let count = reader.read(&mut buffer[..])?;
if count == 0 {
break;
}
m.update(&buffer[..count]);
fn hash_regular_archive(m: &mut Digest, data: &[u8]) -> Result<()> {
let archive = ArchiveFile::parse(&*data)?;
for entry in archive.members() {
let entry = entry?;
m.update(entry.name());
m.update(entry.data(&*data)?);
}
Ok(())
}
Expand Down

0 comments on commit d757cc9

Please sign in to comment.