Extract PKG payload using apple-flat-package
Closed this issue · 2 comments
bonigarcia commented
Hello. I need a pure Rust implementation to extract the content of a PKG file. As recommended in #90, the apple-flat-package
crate in this repo should support this decoding.
I've been trying the apple-flat-package
, but so far, I only managed to list the Payload content (i.e., a cpio archive). My current solution is the following:
use apple_flat_package::reader::PkgReader;
use std::error::Error;
use std::fs::File;
fn main() -> Result<(), Box<dyn Error>> {
// Source file obtained from
// https://msedge.sf.dl.delivery.mp.microsoft.com/filestreamingservice/files/61b13da3-c921-482a-9166-743689310b71/MicrosoftEdge-122.0.2365.92.pkg
let source = r#"C:\Users\boni\Downloads\MicrosoftEdge-122.0.2365.92.pkg"#;
let mut reader = PkgReader::new(File::open(source)?)?;
let packages = reader.component_packages()?;
println!("Number of components: {}", packages.len());
for package in packages.iter() {
if let Some(cpio_reader) = package.payload_reader()? {
for entry in cpio_reader {
let e = entry?;
let name = e.name();
println!("---> {}", name);
}
}
}
Ok(())
}
Instead of simply listing the content, I need to extract the content of the Payload to a target path in my file system. I believe I'm close, but I don't know how to do it.
Can you please guide me? I really appreciate any help you can provide.
roblabla commented
The interface for cpio_reader
is... awkward. It's both an Iterator
and a Read
er for the current archive. So you can do something like this:
for package in packages.iter() {
if let Some(cpio_reader) = package.payload_reader()? {
while let Some(e) = cpio_reader.next() {
let e = entry?;
let name = e.name();
let mut contents = Vec::new();
cpio_reader.read_to_end(&mut contents)?;
// Write contents somewhere.
println!("---> {}", name);
}
}
}
bonigarcia commented