From e4a6c325281a01329c26bb093c79bdf243b666d6 Mon Sep 17 00:00:00 2001 From: Caleb Gardner Date: Tue, 27 May 2025 22:26:58 -0500 Subject: [PATCH] So close yet so far away --- src/fragment.zig | 16 ++++++++++++++-- src/reader.zig | 24 ++++++++++++------------ src/readers/data_extractor.zig | 20 +++++++++++--------- src/readers/data_reader.zig | 24 +++++++++++++----------- 4 files changed, 50 insertions(+), 34 deletions(-) diff --git a/src/fragment.zig b/src/fragment.zig index 606e109..8ac1336 100644 --- a/src/fragment.zig +++ b/src/fragment.zig @@ -1,3 +1,5 @@ +const std = @import("std"); + const BlockSize = @import("inode/file.zig").BlockSize; const Reader = @import("reader.zig").Reader; @@ -6,9 +8,19 @@ pub const FragEntry = packed struct { size: BlockSize, _: u32, - pub fn getData(self: FragEntry, rdr: *Reader, offset: u32) ![]u8 { + pub fn getData(self: FragEntry, rdr: *Reader, offset: u32, frag_size: u32) ![]u8 { + var offset_rdr = rdr.holder.readerAt(self.start); if (self.size.not_compressed) { - //TODO + const buf = try rdr.alloc.alloc(u8, frag_size); + _ = try offset_rdr.read(buf); + return buf; } + var limit_rdr = std.io.limitedReader(offset_rdr, self.size.size); + var decomp = try rdr.super.decomp.decompress(rdr.alloc, limit_rdr.reader().any()); + var frag_all = try decomp.toOwnedSlice(); + defer rdr.alloc.free(frag_all); + const out = try rdr.alloc.alloc(u8, frag_size); + @memcpy(out, frag_all[offset .. offset + frag_size]); + return out; } }; diff --git a/src/reader.zig b/src/reader.zig index fedfe52..8012647 100644 --- a/src/reader.zig +++ b/src/reader.zig @@ -96,18 +96,18 @@ test "root iter" { } } -// test "extract" { -// const test_sfs_path = "testing/LinuxPATest.sfs"; -// const extract_path = "testing/testExtract"; -// std.fs.cwd().deleteTree(extract_path) catch |err| { -// if (err != std.fs.Dir.DeleteFileError.FileNotFound) { -// return err; -// } -// }; -// var rdr: Reader = try .init(std.testing.allocator, test_sfs_path, 0); -// defer rdr.deinit(); -// try rdr.root.extract(&rdr, try .init(), extract_path); -// } +test "extract" { + const test_sfs_path = "testing/LinuxPATest.sfs"; + const extract_path = "testing/testExtract"; + std.fs.cwd().deleteTree(extract_path) catch |err| { + if (err != std.fs.Dir.DeleteFileError.FileNotFound) { + return err; + } + }; + var rdr: Reader = try .init(std.testing.allocator, test_sfs_path, 0); + defer rdr.deinit(); + try rdr.root.extract(&rdr, try .init(), extract_path); +} test "extract single file" { const test_sfs_path = "testing/LinuxPATest.sfs"; diff --git a/src/readers/data_extractor.zig b/src/readers/data_extractor.zig index 1cfc863..80fa6fb 100644 --- a/src/readers/data_extractor.zig +++ b/src/readers/data_extractor.zig @@ -64,13 +64,8 @@ pub const DataExtractor = struct { offset += out.sizes[i].size; } if (frag_idx != 0xFFFFFFFF) { - const frag_entry = try reader.frag_table.getValue(reader, frag_idx); - var frag_rdr: DataReader = try .fromFragEntry(reader, frag_entry); - std.debug.print("{} {}\n", .{ frag_offset, frag_entry }); - defer frag_rdr.deinit(); - try frag_rdr.skip(frag_offset); - out.frag_data = try reader.alloc.alloc(u8, file_size % out.block_size); - _ = try frag_rdr.any().readAll(out.frag_data.?); + const frag_ent = try reader.frag_table.getValue(reader, frag_idx); + out.frag_data = try frag_ent.getData(reader, frag_offset, @truncate(file_size % reader.super.block_size)); } return out; } @@ -83,35 +78,40 @@ pub const DataExtractor = struct { fn processBlockToFile(self: *DataExtractor, wg: *std.Thread.WaitGroup, errs: *std.ArrayList(anyerror), block_ind: usize, fil: *fs.File) void { defer wg.finish(); - var offset_rdr = self.holder.readerAt(self.block_offset[block_ind]); if (self.sizes[block_ind].not_compressed) { @branchHint(.unlikely); if (self.sizes[block_ind].size == 0) { if (block_ind == self.sizes.len - 1) { fil.pwriteAll(&[1]u8{0}, self.file_size - 1) catch |err| { + std.debug.print("yo1\n", .{}); errs.append(err) catch {}; }; } else { fil.pwriteAll(&[1]u8{0}, ((block_ind + 1) * self.block_size) - 1) catch |err| { + std.debug.print("yo2\n", .{}); errs.append(err) catch {}; }; } return; } const dat = self.alloc.alloc(u8, self.sizes[block_ind].size) catch |err| { + std.debug.print("yo3\n", .{}); errs.append(err) catch {}; return; }; defer self.alloc.free(dat); - _ = offset_rdr.any().readAll(dat) catch |err| { + _ = fil.preadAll(dat, self.block_offset[block_ind]) catch |err| { + std.debug.print("yo4\n", .{}); errs.append(err) catch {}; return; }; fil.pwriteAll(dat, block_ind * self.block_size) catch |err| { + std.debug.print("yo5\n", .{}); errs.append(err) catch {}; }; } else { @branchHint(.likely); + const offset_rdr = self.holder.readerAt(self.block_offset[block_ind]); var fil_wrtr: FileOffsetWriter = .init(fil, block_ind * self.block_size); var limit = std.io.limitedReader(offset_rdr, self.sizes[block_ind].size); self.decomp.decompressTo( @@ -119,6 +119,7 @@ pub const DataExtractor = struct { limit.reader().any(), fil_wrtr.any(), ) catch |err| { + std.debug.print("yo6\n", .{}); errs.append(err) catch {}; }; } @@ -127,6 +128,7 @@ pub const DataExtractor = struct { fn fragmentToFile(self: *DataExtractor, wg: *std.Thread.WaitGroup, errs: *std.ArrayList(anyerror), fil: *fs.File) void { defer wg.finish(); fil.pwriteAll(self.frag_data.?, self.block_size * self.sizes.len) catch |err| { + std.debug.print("yo7\n", .{}); errs.append(err) catch {}; }; } diff --git a/src/readers/data_reader.zig b/src/readers/data_reader.zig index b91e82a..5264f16 100644 --- a/src/readers/data_reader.zig +++ b/src/readers/data_reader.zig @@ -18,6 +18,7 @@ pub const DataReader = struct { decomp: DecompressionType, rdr: FileOffsetReader, block_size: u32, + file_size: u64, sizes: []BlockSize, frag_data: ?[]u8 = null, @@ -28,7 +29,7 @@ pub const DataReader = struct { pub fn init(fil: *File, reader: *Reader) !DataReader { var data_start: u64 = 0; var sizes: []BlockSize = undefined; - var size: u64 = 0; + var file_size: u64 = 0; var frag_idx: u32 = 0; var frag_offset: u32 = 0; switch (fil.inode.data) { @@ -36,7 +37,7 @@ pub const DataReader = struct { sizes = try reader.alloc.alloc(BlockSize, f.blocks.len); @memcpy(sizes, f.blocks); data_start = f.data_start; - size = f.size; + file_size = f.size; frag_idx = f.frag_idx; frag_offset = f.frag_offset; }, @@ -44,7 +45,7 @@ pub const DataReader = struct { sizes = try reader.alloc.alloc(BlockSize, f.blocks.len); @memcpy(sizes, f.blocks); data_start = f.data_start; - size = f.size; + file_size = f.size; frag_idx = f.frag_idx; frag_offset = f.frag_offset; }, @@ -55,16 +56,13 @@ pub const DataReader = struct { .decomp = reader.super.decomp, .rdr = reader.holder.readerAt(data_start), .block_size = reader.super.block_size, + .file_size = file_size, .sizes = sizes, }; errdefer out.deinit(); if (frag_idx != 0xFFFFFFFF) { - const frag_entry = try reader.frag_table.getValue(frag_idx); - var frag_rdr = try .fromFragEntry(reader, frag_entry); - defer frag_rdr.deinit(); - try frag_rdr.skip(frag_offset); - out.frag_data = try reader.alloc.alloc(u8, size % out.block_size); - _ = try frag_rdr.any().readAll(out.frag_data); + const frag_ent = try reader.frag_table.getValue(reader, frag_idx); + out.frag_data = try frag_ent.getData(reader, frag_offset, @truncate(file_size % reader.super.block_size)); } return out; } @@ -104,13 +102,17 @@ pub const DataReader = struct { } const siz = self.sizes[self.next_block_num]; self.next_block_num += 1; - if (self.next_block_num == self.sizes.len - 1 and self.frag_data != null) { + if (self.next_block_num == self.sizes.len and self.frag_data != null) { try self.sizeBlock(self.frag_data.?.len); @memcpy(self.cur_bloc, self.frag_data.?); return; } if (siz.size == 0) { - try self.sizeBlock(self.block_size); + if (self.next_block_num == self.sizes.len) { + try self.sizeBlock(@truncate(self.file_size % self.block_size)); + } else { + try self.sizeBlock(self.block_size); + } @memset(self.cur_bloc, 0); return; }