Reset on extraction logic

Fixed not using MetadataReader for Tables
Fixed MetadataReaders not respecting uncompressed blocks
This commit is contained in:
Caleb Gardner
2025-07-19 06:30:24 -05:00
parent eb214feefa
commit 9c1d90f60b
7 changed files with 34 additions and 174 deletions
+4 -153
View File
@@ -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);
}
};
}
+1 -1
View File
@@ -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);
+3 -3
View File
@@ -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 {
+4 -9
View File
@@ -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();
}
}
};
+9 -5
View File
@@ -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;
}
+3
View File
@@ -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();
+10 -3
View File
@@ -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];
}