Reset on extraction logic
Fixed not using MetadataReader for Tables Fixed MetadataReaders not respecting uncompressed blocks
This commit is contained in:
+4
-153
@@ -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
@@ -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
@@ -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
@@ -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();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user