improve append file handling + misc change

This commit is contained in:
theubusu
2026-02-24 21:07:37 +01:00
parent a6567ae532
commit 4d86513bab
9 changed files with 56 additions and 35 deletions
+4 -3
View File
@@ -45,6 +45,10 @@ pub fn extract_android_ota_payload(app_ctx: &AppContext, _ctx: Box<dyn Any>) ->
println!("\n#{} - {}, Size: {}, Operations: {}",
i + 1, partition.partition_name, partition.new_partition_info.unwrap().size.unwrap(), operation_count);
fs::create_dir_all(&app_ctx.output_dir)?;
let output_path = Path::new(&app_ctx.output_dir).join(format!("{}.bin", partition.partition_name));
let mut out_file = OpenOptions::new().write(true).create(true).truncate(true).open(output_path)?;
for (i, operation) in partition.operations.into_iter().enumerate() {
let operation_name_str = match install_operation::Type::try_from(operation.r#type) {
Ok(t) => t.as_str_name(),
@@ -76,9 +80,6 @@ pub fn extract_android_ota_payload(app_ctx: &AppContext, _ctx: Box<dyn Any>) ->
break
}
fs::create_dir_all(&app_ctx.output_dir)?;
let output_path = Path::new(&app_ctx.output_dir).join(format!("{}.bin", partition.partition_name));
let mut out_file = OpenOptions::new().append(true).create(true).open(output_path)?;
out_file.write_all(&out_data)?;
}
println!("\n-- Saved!");
+6
View File
@@ -1,6 +1,12 @@
use crate::utils::common;
use binrw::BinRead;
#[derive(PartialEq)]
pub enum Epk1Type {
LittleEndian,
BigEndian,
}
#[derive(BinRead)]
pub struct CommonHeader {
_magic_bytes: [u8; 4],
+6 -6
View File
@@ -25,16 +25,16 @@ pub fn is_epk1_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dy
pub fn extract_epk1(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
//check type of epk1
let epk1_type;
let epk1_type: Epk1Type;
let init_pak_count_bytes = common::read_file(&file, 8, 4)?;
let init_pak_count = u32::from_le_bytes(init_pak_count_bytes.try_into().unwrap());
if init_pak_count > 256 {
println!("\nBig endian EPK1 detected.");
epk1_type = "be";
epk1_type = Epk1Type::BigEndian;
} else if init_pak_count < 33 {
println!("\nLittle endian EPK1 detected.");
epk1_type = "le";
epk1_type = Epk1Type::LittleEndian;
} else {
return Err("Unknown EPK1 variant!".into());
}
@@ -43,7 +43,7 @@ pub fn extract_epk1(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<
let mut paks: Vec<Pak> = Vec::new();
if epk1_type == "be" {
if epk1_type == Epk1Type::BigEndian {
let header: CommonHeader = file.read_be()?;
for _i in 0..10 { //header can fit max 10 pak entries
@@ -63,7 +63,7 @@ pub fn extract_epk1(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<
println!("EPK info -\nData size: {}\nPak count: {}\nVersion: {:02x?}.{:02x?}.{:02x?}",
header.file_size, header.pak_count, version[1], version[2], version[3]);
} else if epk1_type == "le" {
} else if epk1_type == Epk1Type::LittleEndian {
let header: CommonHeader = file.read_le()?;
//this is to make an odd variant with 32 max pak entries work
@@ -97,7 +97,7 @@ pub fn extract_epk1(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<
for (i, pak) in paks.iter().enumerate() {
file.seek(SeekFrom::Start(pak.offset as u64))?;
let pak_header: PakHeader = if epk1_type == "be" {file.read_be()?} else {file.read_le()?};
let pak_header: PakHeader = if epk1_type == Epk1Type::BigEndian {file.read_be()?} else {file.read_le()?};
println!("\n({}/{}) - {}, Offset: {}, Size: {}, Platform: {}",
i + 1, paks.len(), pak_header.pak_name(), pak.offset, pak_header.image_size, pak_header.platform_id());
+4 -3
View File
@@ -98,6 +98,10 @@ pub fn extract_epk2(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<
println!("\n({}/{}) - {}, Size: {}, Segment count: {}, Platform: {}",
pak_n + 1, paks.len(), pak.name, pak_header.image_size, pak_header.segment_count, pak_header.platform_id());
let output_path = Path::new(&app_ctx.output_dir).join(format!("{}.bin", pak.name));
fs::create_dir_all(&app_ctx.output_dir)?;
let mut out_file = OpenOptions::new().write(true).create(true).truncate(true).open(output_path)?;
for i in 0..pak_header.segment_count {
// for first segment we already read the header so skip doing that for it
if i > 0 {
@@ -137,9 +141,6 @@ pub fn extract_epk2(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<
let segment_data = common::read_exact(&mut file, actual_segment_size as usize)?;
let out_data = decrypt_aes_ecb_auto(&matching_key_bytes, &segment_data)?;
let output_path = Path::new(&app_ctx.output_dir).join(format!("{}.bin", pak.name));
fs::create_dir_all(&app_ctx.output_dir)?;
let mut out_file = OpenOptions::new().append(true).create(true).open(output_path)?;
out_file.write_all(&out_data)?;
println!("-- Saved to file!");
+4 -3
View File
@@ -52,6 +52,10 @@ pub fn extract_epk2b(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box
println!("\n({}/{}) - {}, Size: {}, Segment count: {}, Platform: {}",
i + 1, paks.len(), pak_header.pak_name(), pak_header.image_size, pak_header.segment_count, pak_header.platform_id());
let output_path = Path::new(&app_ctx.output_dir).join(format!("{}.bin", pak_header.pak_name()));
fs::create_dir_all(&app_ctx.output_dir)?;
let mut out_file = OpenOptions::new().write(true).create(true).truncate(true).open(output_path)?;
for i in 0..pak_header.segment_count {
// for first segment we already read the header so skip doing that for it
if i > 0 {
@@ -74,9 +78,6 @@ pub fn extract_epk2b(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box
pak_header.segment_size
};
let output_path = Path::new(&app_ctx.output_dir).join(format!("{}.bin", pak_header.pak_name()));
fs::create_dir_all(&app_ctx.output_dir)?;
let mut out_file = OpenOptions::new().append(true).create(true).open(output_path)?;
out_file.write_all(&out_data[..segment_limit as usize])?;
println!("-- Saved to file!");
+4 -3
View File
@@ -92,6 +92,10 @@ pub fn extract_epk3(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<
println!("\n({}) - {}, Size: {}, Segments: {}",
pak_i, entry.package_name(), entry.package_size, entry.segment_count);
let output_path = Path::new(&app_ctx.output_dir).join(format!("{}.bin", entry.package_name()));
fs::create_dir_all(&app_ctx.output_dir)?;
let mut out_file = OpenOptions::new().write(true).create(true).truncate(true).open(output_path)?;
for i in 0..entry.segment_count {
if i > 0 {
entry = pkg_info_reader.read_le()?;
@@ -104,9 +108,6 @@ pub fn extract_epk3(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<
let encrypted_data = common::read_exact(&mut file, entry.segment_size as usize + extra_segment_size)?;
let out_data = decrypt_aes_ecb_auto(matching_key_bytes, &encrypted_data)?;
let output_path = Path::new(&app_ctx.output_dir).join(format!("{}.bin", entry.package_name()));
fs::create_dir_all(&app_ctx.output_dir)?;
let mut out_file = OpenOptions::new().append(true).create(true).open(output_path)?;
out_file.write_all(&out_data[extra_segment_size..])?;
println!("-- Saved to file!");
+11
View File
@@ -1,3 +1,14 @@
#[derive(PartialEq)]
pub enum CompressionType {
None,
Lzma,
DoubleLzma,
Lz4,
Lzo,
Sparse,
}
pub fn parse_number(s: &str) -> Option<u64> {
if let Some(hex_str) = s.strip_prefix("0x") {
u64::from_str_radix(hex_str, 16).ok()
+13 -13
View File
@@ -69,7 +69,7 @@ pub fn extract_mstar(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box
// "unknown"
//};
let mut partname = "unknown";
let mut compression = "none";
let mut compression: CompressionType = CompressionType::None;
let mut lz4_expect_size = 0;
let mut j = i + 1;
@@ -77,20 +77,20 @@ pub fn extract_mstar(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box
while j < lines.len() && !lines[j].starts_with("filepartload") {
//get compression method
if lines[j].starts_with("mscompress7"){
if compression == "none" {
compression = "lzma";
} else if compression == "lzma" {
if compression == CompressionType::None {
compression = CompressionType::Lzma;
} else if compression == CompressionType::Lzma {
//thank the turks
compression = "double_lzma";
compression = CompressionType::DoubleLzma;
}
}
if lines[j].starts_with("lz4"){
compression = "lz4";
compression = CompressionType::Lz4;
let parts: Vec<&str> = lines[j].split_whitespace().collect();
lz4_expect_size = parse_number(parts[5]).unwrap_or(0);
}
if lines[j].starts_with("mmc unlzo"){
compression = "lzo";
compression = CompressionType::Lzo;
let parts: Vec<&str> = lines[j].split_whitespace().collect();
// get part name from mmc unlzo
if partname == "unknown" {
@@ -98,7 +98,7 @@ pub fn extract_mstar(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box
}
}
if lines[j].starts_with("sparse_write"){
compression = "sparse"; //its not really compression but anyway
compression = CompressionType::Sparse; //its not really compression but anyway
let parts: Vec<&str> = lines[j].split_whitespace().collect();
// get part name from sparse_write
if partname == "unknown" {
@@ -133,24 +133,24 @@ pub fn extract_mstar(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box
let out_data;
let output_path = Path::new(&app_ctx.output_dir).join(format!("{}.bin", partname));
if compression == "lzma" {
if compression == CompressionType::Lzma {
println!("- Decompressing LZMA...");
out_data = decompress_lzma(&data)?;
} else if compression == "double_lzma" {
} else if compression == CompressionType::DoubleLzma {
println!("- Decompressing LZMA (Pass 1)...");
let pass_1 = decompress_lzma(&data)?;
println!("- Decompressing LZMA (Pass 2)...");
out_data = decompress_lzma(&pass_1)?;
} else if compression == "lz4" {
} else if compression == CompressionType::Lz4 {
println!("- Decompressing lz4, expected size: {}", lz4_expect_size);
out_data = decompress_lz4(&data, lz4_expect_size.try_into().unwrap())?;
} else if compression == "lzo" {
} else if compression == CompressionType::Lzo {
println!("- Decompessing LZO..");
unlzop_to_file(&data, output_path)?;
println!("-- Saved file!");
i += 1;
continue
} else if compression == "sparse" {
} else if compression == CompressionType::Sparse {
println!("- Unsparsing...");
unsparse_to_file(&data, output_path)?;
println!("-- Saved file!");
+2 -2
View File
@@ -196,6 +196,7 @@ fn extract_main(file_reader: &mut Cursor<Vec<u8>>, key: [u8; 8], output_path: &P
}
let mut maine_i = 0;
let mut main_out_file = OpenOptions::new().write(true).create(true).truncate(true).open(&output_path)?;
for entry in &main_entries {
maine_i += 1;
let mut data = common::read_exact(file_reader, entry.size as usize)?;
@@ -216,8 +217,7 @@ fn extract_main(file_reader: &mut Cursor<Vec<u8>>, key: [u8; 8], output_path: &P
print!("\nMAIN ({}/{}) - ", maine_i, main_entries.len());
let decompressed_data = decompress_data(&data)?;
let mut out_file = OpenOptions::new().append(true).create(true).open(&output_path)?;
out_file.write_all(&decompressed_data)?;
main_out_file.write_all(&decompressed_data)?;
println!("-- Saved to MAIN!");
}