From 9c1d90f60b182ea8cb0a2d1d0aeb7cbbc644d072 Mon Sep 17 00:00:00 2001 From: Caleb Gardner Date: Sat, 19 Jul 2025 06:30:24 -0500 Subject: [PATCH] Reset on extraction logic Fixed not using MetadataReader for Tables Fixed MetadataReaders not respecting uncompressed blocks --- src/file.zig | 157 +--------------------------------------- src/inode/file.zig | 2 +- src/reader.zig | 6 +- src/reader/data.zig | 13 +--- src/reader/metadata.zig | 14 ++-- src/root.zig | 3 + src/table.zig | 13 +++- 7 files changed, 34 insertions(+), 174 deletions(-) diff --git a/src/file.zig b/src/file.zig index 6e70e70..8e3ef4e 100644 --- a/src/file.zig +++ b/src/file.zig @@ -232,27 +232,15 @@ pub fn File(comptime T: type) type { pol: *Pool, path: []const u8, first: bool, - comptime on_finish: anytype, - finish_args: anytype, ) !void { if (op.verbose) { std.fmt.format(op.verbose_logger, "extracting inode {} \"{s}\" to {s}...\n", .{ self.inode.hdr.num, self.name, path }) catch {}; } return switch (self.inode.hdr.type) { - .dir, .ext_dir => self.extractDir(op, errs, wg, pol, path, first), - .file, .ext_file => self.extractReg(op, errs, wg, pol, path, first), - .symlink, .ext_symlink => self.extractSymlink(op, errs, wg, pol, path, first), - .block_dev, - .ext_block_dev, - .char_dev, - .ext_char_dev, - .fifo, - .ext_fifo, - => { - try self.extractDev(op, path); - if (!first) self.deinit(); - return; - }, + .dir, .ext_dir => {}, + .file, .ext_file => {}, + .symlink, .ext_symlink => {}, + .block_dev, .ext_block_dev, .char_dev, .ext_char_dev, .fifo, .ext_fifo => {}, else => { if (op.verbose) { std.fmt.format( @@ -264,142 +252,5 @@ pub fn File(comptime T: type) type { }, }; } - fn extractDir( - self: Self, - op: ExtractionOptions, - errs: *std.ArrayList(anyerror), - wg: *WaitGroup, - pol: *Pool, - path: []const u8, - comptime on_finish: anytype, - finish_args: anytype, - ) !void { - if (errs.items.len > 0) return; - wg.start(); - var dir_wg: WaitGroup = .{}; - dir_wg.startMany(self.entries.?.len); - for (self.entries.?) |e| { - const fil: Self = try .initFromEntry(self.rdr, e); - } - return error{TODO}.TODO; - } - fn extractReg( - self: Self, - op: ExtractionOptions, - errs: *std.ArrayList(anyerror), - wg: *WaitGroup, - pol: *Pool, - path: []const u8, - first: bool, - comptime on_finish: anytype, - finish_args: anytype, - ) !void { - if (errs.items.len > 0) return; - const fil = try std.fs.cwd().createFile(path, .{}); - @constCast(&self.data_reader.?).setPool(pol); - wg.start(); - var fil_errs: std.ArrayList(anyerror) = .init(self.rdr.alloc); - try self.data_reader.?.writeToNoBlock(fil_errs, fil, wg, extractRegFinish, .{ self, op, fil, &fil_errs, first }); - return; - } - fn extractRegFinish( - self: Self, - op: ExtractionOptions, - fil: std.fs.File, - errs: *std.ArrayList(anyerror), - fil_errs: *std.ArrayList(anyerror), - first: bool, - comptime on_finish: anytype, - finish_args: anytype, - ) void { - defer fil.close(); - defer fil_errs.deinit(); - defer if (!first) self.deinit(); - if (fil_errs.items.len > 0) { - if (op.verbose) { - for (fil_errs.items) |err| { - std.fmt.format(op.verbose_logger, "error extracting inode {} \"{s}\": {}\n", .{ self.inode.num, self.name, err }) catch {}; - } - } - errs.append(fil_errs.items[0]) catch {}; - return; - } - if (!op.ignore_permissions) { - const fil_uid = self.uid() catch |err| { - if (op.verbose) { - std.fmt.format(op.verbose_logger, "error getting uid: {}\n", .{err}) catch {}; - return; - } - }; - const fil_gid = self.gid() catch |err| { - if (op.verbose) { - std.fmt.format(op.verbose_logger, "error getting gid: {}\n", .{err}) catch {}; - return; - } - }; - fil.chmod(self.inode.hdr.perm) catch |err| { - if (op.verbose) { - std.fmt.format(op.verbose_logger, "error setting permissions: {}\n", .{err}) catch {}; - return; - } - }; - fil.chown(fil_uid, fil_gid) catch |err| { - if (op.verbose) { - std.fmt.format(op.verbose_logger, "error setting owners: {}\n", .{err}) catch {}; - return; - } - }; - } - } - fn extractSymlink( - self: Self, - op: ExtractionOptions, - errs: *std.ArrayList(anyerror), - wg: *WaitGroup, - pol: *Pool, - path: []const u8, - first: bool, - comptime on_finish: anytype, - finish_args: anytype, - ) !void { - if (errs.items.len > 0) return; - _ = self; - _ = op; - _ = wg; - _ = pol; - _ = path; - return error{TODO}.TODO; - } - fn extractDev( - self: Self, - op: ExtractionOptions, - path: []const u8, - comptime on_finish: anytype, - finish_args: anytype, - ) !void { - if (comptime builtin.os.tag != .linux) { - if (op.verbose) { - std.fmt.format( - op.verbose_logger, - "inode {} \"{s}\" is a device/fifo file and the OS is not Linux. Ignoring.\n", - .{ self.inode.hdr.num, self.name }, - ) catch {}; - } - return; - } - const mode: u32 = switch (self.inode.hdr.type) { - .block_dev, .ext_block_dev => std.posix.S.IFBLK, - .char_dev, .ext_char_dev => std.posix.S.IFCHR, - .fifo, .ext_fifo => std.posix.S.IFIFO, - else => unreachable, - }; - const dev = switch (self.inode.data) { - .block_dev, .char_dev => |b| b.device, - .ext_block_dev, .ext_char_dev => |b| b.device, - .fifo, .ext_fifo => 0, - else => unreachable, - }; - _ = std.os.linux.mknod(@ptrCast(path), mode, dev); - } }; } diff --git a/src/inode/file.zig b/src/inode/file.zig index 86af63b..4f70051 100644 --- a/src/inode/file.zig +++ b/src/inode/file.zig @@ -54,7 +54,7 @@ pub const ExtFile = struct { const size = std.mem.readInt(u64, fixed[8..16], .little); const frag_idx = std.mem.readInt(u32, fixed[28..32], .little); var blocks: u32 = @truncate(size / block_size); - if (size % block_size > 0 and frag_idx != 0xffffffff) { + if (size % block_size > 0 and frag_idx == 0xffffffff) { blocks += 1; } const block_sizes = try alloc.alloc(BlockSize, blocks); diff --git a/src/reader.zig b/src/reader.zig index b0f69e2..71e1096 100644 --- a/src/reader.zig +++ b/src/reader.zig @@ -37,9 +37,9 @@ pub fn SfsReader(comptime T: type) type { .rdr = .init(rdr, offset), }; _ = try rdr.pread(std.mem.asBytes(&out.super), 0); - out.frag_table = .init(alloc, rdr, out.super.frag_start, out.super.frag_count); - out.id_table = .init(alloc, rdr, out.super.id_start, out.super.id_count); - out.export_table = .init(alloc, rdr, out.super.export_start, out.super.inode_count); + out.frag_table = .init(alloc, out.rdr, out.super.comp, out.super.frag_start, out.super.frag_count); + out.id_table = .init(alloc, out.rdr, out.super.comp, out.super.id_start, out.super.id_count); + out.export_table = .init(alloc, out.rdr, out.super.comp, out.super.export_start, out.super.inode_count); return out; } pub fn deinit(self: *Self) void { diff --git a/src/reader/data.zig b/src/reader/data.zig index 2cffe48..4462138 100644 --- a/src/reader/data.zig +++ b/src/reader/data.zig @@ -184,7 +184,6 @@ pub fn DataReader(comptime T: type) type { self: Self, errs: *std.ArrayList(anyerror), writer: anytype, - wg: *std.Thread.WaitGroup, comptime on_finish: anytype, on_finish_args: anytype, ) !void { @@ -208,9 +207,9 @@ pub fn DataReader(comptime T: type) type { }, blk: { if (comptime std.meta.hasFn(@TypeOf(writer), "pwrite")) { - break :blk .{ self, &block_wg, errs, i, writer, wg, &finish_mut, on_finish, on_finish_args }; + break :blk .{ self, &block_wg, errs, i, writer, &finish_mut, on_finish, on_finish_args }; } else { - break :blk .{ self, &block_wg, &mut, &cur_idx, errs, &completed.?, i, writer, wg, &finish_mut, on_finish, on_finish_args }; + break :blk .{ self, &block_wg, &mut, &cur_idx, errs, &completed.?, i, writer, &finish_mut, on_finish, on_finish_args }; } }, ); @@ -326,18 +325,16 @@ pub fn DataReader(comptime T: type) type { completed: *std.AutoArrayHashMap(usize, anyerror![]u8), idx: usize, writer: anytype, - finish_wg: *std.Thread.WaitGroup, finish_mut: *std.Thread.Mutex, comptime on_finish: anytype, on_finish_args: anytype, ) void { self.writeBlockTo(mut, cur_idx, errs, completed, idx, writer); - block_wg.finish(); finish_mut.lock(); + block_wg.finish(); defer finish_mut.unlock(); if (block_wg.isDone()) { @call(.auto, on_finish, on_finish_args); - finish_wg.finish(); completed.deinit(); } } @@ -347,18 +344,16 @@ pub fn DataReader(comptime T: type) type { errs: *std.ArrayList(anyerror), idx: usize, writer: anytype, - finish_wg: *std.Thread.WaitGroup, finish_mut: *std.Thread.Mutex, comptime on_finish: anytype, on_finish_args: anytype, ) void { self.writeBlockToPWrite(errs, idx, writer); - block_wg.finish(); finish_mut.lock(); + block_wg.finish(); defer finish_mut.unlock(); if (block_wg.isDone()) { @call(.auto, on_finish, on_finish_args); - finish_wg.finish(); } } }; diff --git a/src/reader/metadata.zig b/src/reader/metadata.zig index 89d74ff..289ebe0 100644 --- a/src/reader/metadata.zig +++ b/src/reader/metadata.zig @@ -35,11 +35,15 @@ pub fn MetadataReader(comptime T: type) type { var hdr: MetaHeader = undefined; _ = try self.rdr.pread(std.mem.asBytes(&hdr), self.offset); self.offset += 2; - self.block_size = try self.comp.decompress( - self.alloc, - self.rdr.readerAt(self.offset).reader(), - &self.block, - ); + if (hdr.uncompressed) { + self.block_size = try self.rdr.pread(self.block[0..hdr.size], self.offset); + } else { + self.block_size = try self.comp.decompress( + self.alloc, + self.rdr.readerAt(self.offset).reader(), + &self.block, + ); + } self.offset += hdr.size; self.block_offset = 0; } diff --git a/src/root.zig b/src/root.zig index 48e3049..df3b4b4 100644 --- a/src/root.zig +++ b/src/root.zig @@ -14,6 +14,9 @@ test "OpenFile" { defer sfs_fil.close(); var rdr: SfsFile = try .init(std.testing.allocator, sfs_fil, 0); defer rdr.deinit(); + _ = try rdr.frag_table.get(rdr.super.frag_count - 1); + _ = try rdr.id_table.get(rdr.super.id_count - 1); + _ = try rdr.export_table.get(rdr.super.inode_count - 1); std.debug.print("{}\n", .{rdr.super}); const root = try rdr.root(); defer root.deinit(); diff --git a/src/table.zig b/src/table.zig index 2f857d0..c60761d 100644 --- a/src/table.zig +++ b/src/table.zig @@ -1,5 +1,9 @@ const std = @import("std"); +const PRead = @import("reader/p_read.zig").PRead; +const Compression = @import("superblock.zig").Compression; +const MetadataReader = @import("reader/metadata.zig").MetadataReader; + pub const TableError = error{ InvalidIndex, }; @@ -10,7 +14,8 @@ pub fn Table(comptime T: type, comptime R: type) type { const Self = @This(); alloc: std.mem.Allocator, - rdr: R, + rdr: PRead(R), + comp: Compression, offset: u64, table_count: u32, @@ -18,10 +23,11 @@ pub fn Table(comptime T: type, comptime R: type) type { table: []T = &[0]T{}, - pub fn init(alloc: std.mem.Allocator, rdr: R, offset: u64, table_count: u32) Self { + pub fn init(alloc: std.mem.Allocator, rdr: PRead(R), comp: Compression, offset: u64, table_count: u32) Self { return .{ .alloc = alloc, .rdr = rdr, + .comp = comp, .offset = offset, .table_count = table_count, }; @@ -60,7 +66,8 @@ pub fn Table(comptime T: type, comptime R: type) type { try self.resize(to_read); _ = try self.rdr.pread(std.mem.asBytes(&offset), self.offset); self.offset += 8; - _ = try self.rdr.pread(std.mem.sliceAsBytes(self.table[self.table.len - to_read ..]), offset); + var meta: MetadataReader(R) = .init(self.alloc, self.comp, self.rdr, offset); + _ = try meta.read(std.mem.sliceAsBytes(self.table[self.table.len - to_read ..])); } return self.table[idx]; }