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,
|
pol: *Pool,
|
||||||
path: []const u8,
|
path: []const u8,
|
||||||
first: bool,
|
first: bool,
|
||||||
comptime on_finish: anytype,
|
|
||||||
finish_args: anytype,
|
|
||||||
) !void {
|
) !void {
|
||||||
if (op.verbose) {
|
if (op.verbose) {
|
||||||
std.fmt.format(op.verbose_logger, "extracting inode {} \"{s}\" to {s}...\n", .{ self.inode.hdr.num, self.name, path }) catch {};
|
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) {
|
return switch (self.inode.hdr.type) {
|
||||||
.dir, .ext_dir => self.extractDir(op, errs, wg, pol, path, first),
|
.dir, .ext_dir => {},
|
||||||
.file, .ext_file => self.extractReg(op, errs, wg, pol, path, first),
|
.file, .ext_file => {},
|
||||||
.symlink, .ext_symlink => self.extractSymlink(op, errs, wg, pol, path, first),
|
.symlink, .ext_symlink => {},
|
||||||
.block_dev,
|
.block_dev, .ext_block_dev, .char_dev, .ext_char_dev, .fifo, .ext_fifo => {},
|
||||||
.ext_block_dev,
|
|
||||||
.char_dev,
|
|
||||||
.ext_char_dev,
|
|
||||||
.fifo,
|
|
||||||
.ext_fifo,
|
|
||||||
=> {
|
|
||||||
try self.extractDev(op, path);
|
|
||||||
if (!first) self.deinit();
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
else => {
|
else => {
|
||||||
if (op.verbose) {
|
if (op.verbose) {
|
||||||
std.fmt.format(
|
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 size = std.mem.readInt(u64, fixed[8..16], .little);
|
||||||
const frag_idx = std.mem.readInt(u32, fixed[28..32], .little);
|
const frag_idx = std.mem.readInt(u32, fixed[28..32], .little);
|
||||||
var blocks: u32 = @truncate(size / block_size);
|
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;
|
blocks += 1;
|
||||||
}
|
}
|
||||||
const block_sizes = try alloc.alloc(BlockSize, blocks);
|
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),
|
.rdr = .init(rdr, offset),
|
||||||
};
|
};
|
||||||
_ = try rdr.pread(std.mem.asBytes(&out.super), 0);
|
_ = try rdr.pread(std.mem.asBytes(&out.super), 0);
|
||||||
out.frag_table = .init(alloc, rdr, out.super.frag_start, out.super.frag_count);
|
out.frag_table = .init(alloc, out.rdr, out.super.comp, out.super.frag_start, out.super.frag_count);
|
||||||
out.id_table = .init(alloc, rdr, out.super.id_start, out.super.id_count);
|
out.id_table = .init(alloc, out.rdr, out.super.comp, out.super.id_start, out.super.id_count);
|
||||||
out.export_table = .init(alloc, rdr, out.super.export_start, out.super.inode_count);
|
out.export_table = .init(alloc, out.rdr, out.super.comp, out.super.export_start, out.super.inode_count);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
pub fn deinit(self: *Self) void {
|
pub fn deinit(self: *Self) void {
|
||||||
|
|||||||
+4
-9
@@ -184,7 +184,6 @@ pub fn DataReader(comptime T: type) type {
|
|||||||
self: Self,
|
self: Self,
|
||||||
errs: *std.ArrayList(anyerror),
|
errs: *std.ArrayList(anyerror),
|
||||||
writer: anytype,
|
writer: anytype,
|
||||||
wg: *std.Thread.WaitGroup,
|
|
||||||
comptime on_finish: anytype,
|
comptime on_finish: anytype,
|
||||||
on_finish_args: anytype,
|
on_finish_args: anytype,
|
||||||
) !void {
|
) !void {
|
||||||
@@ -208,9 +207,9 @@ pub fn DataReader(comptime T: type) type {
|
|||||||
},
|
},
|
||||||
blk: {
|
blk: {
|
||||||
if (comptime std.meta.hasFn(@TypeOf(writer), "pwrite")) {
|
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 {
|
} 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),
|
completed: *std.AutoArrayHashMap(usize, anyerror![]u8),
|
||||||
idx: usize,
|
idx: usize,
|
||||||
writer: anytype,
|
writer: anytype,
|
||||||
finish_wg: *std.Thread.WaitGroup,
|
|
||||||
finish_mut: *std.Thread.Mutex,
|
finish_mut: *std.Thread.Mutex,
|
||||||
comptime on_finish: anytype,
|
comptime on_finish: anytype,
|
||||||
on_finish_args: anytype,
|
on_finish_args: anytype,
|
||||||
) void {
|
) void {
|
||||||
self.writeBlockTo(mut, cur_idx, errs, completed, idx, writer);
|
self.writeBlockTo(mut, cur_idx, errs, completed, idx, writer);
|
||||||
block_wg.finish();
|
|
||||||
finish_mut.lock();
|
finish_mut.lock();
|
||||||
|
block_wg.finish();
|
||||||
defer finish_mut.unlock();
|
defer finish_mut.unlock();
|
||||||
if (block_wg.isDone()) {
|
if (block_wg.isDone()) {
|
||||||
@call(.auto, on_finish, on_finish_args);
|
@call(.auto, on_finish, on_finish_args);
|
||||||
finish_wg.finish();
|
|
||||||
completed.deinit();
|
completed.deinit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -347,18 +344,16 @@ pub fn DataReader(comptime T: type) type {
|
|||||||
errs: *std.ArrayList(anyerror),
|
errs: *std.ArrayList(anyerror),
|
||||||
idx: usize,
|
idx: usize,
|
||||||
writer: anytype,
|
writer: anytype,
|
||||||
finish_wg: *std.Thread.WaitGroup,
|
|
||||||
finish_mut: *std.Thread.Mutex,
|
finish_mut: *std.Thread.Mutex,
|
||||||
comptime on_finish: anytype,
|
comptime on_finish: anytype,
|
||||||
on_finish_args: anytype,
|
on_finish_args: anytype,
|
||||||
) void {
|
) void {
|
||||||
self.writeBlockToPWrite(errs, idx, writer);
|
self.writeBlockToPWrite(errs, idx, writer);
|
||||||
block_wg.finish();
|
|
||||||
finish_mut.lock();
|
finish_mut.lock();
|
||||||
|
block_wg.finish();
|
||||||
defer finish_mut.unlock();
|
defer finish_mut.unlock();
|
||||||
if (block_wg.isDone()) {
|
if (block_wg.isDone()) {
|
||||||
@call(.auto, on_finish, on_finish_args);
|
@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;
|
var hdr: MetaHeader = undefined;
|
||||||
_ = try self.rdr.pread(std.mem.asBytes(&hdr), self.offset);
|
_ = try self.rdr.pread(std.mem.asBytes(&hdr), self.offset);
|
||||||
self.offset += 2;
|
self.offset += 2;
|
||||||
self.block_size = try self.comp.decompress(
|
if (hdr.uncompressed) {
|
||||||
self.alloc,
|
self.block_size = try self.rdr.pread(self.block[0..hdr.size], self.offset);
|
||||||
self.rdr.readerAt(self.offset).reader(),
|
} else {
|
||||||
&self.block,
|
self.block_size = try self.comp.decompress(
|
||||||
);
|
self.alloc,
|
||||||
|
self.rdr.readerAt(self.offset).reader(),
|
||||||
|
&self.block,
|
||||||
|
);
|
||||||
|
}
|
||||||
self.offset += hdr.size;
|
self.offset += hdr.size;
|
||||||
self.block_offset = 0;
|
self.block_offset = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ test "OpenFile" {
|
|||||||
defer sfs_fil.close();
|
defer sfs_fil.close();
|
||||||
var rdr: SfsFile = try .init(std.testing.allocator, sfs_fil, 0);
|
var rdr: SfsFile = try .init(std.testing.allocator, sfs_fil, 0);
|
||||||
defer rdr.deinit();
|
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});
|
std.debug.print("{}\n", .{rdr.super});
|
||||||
const root = try rdr.root();
|
const root = try rdr.root();
|
||||||
defer root.deinit();
|
defer root.deinit();
|
||||||
|
|||||||
+10
-3
@@ -1,5 +1,9 @@
|
|||||||
const std = @import("std");
|
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{
|
pub const TableError = error{
|
||||||
InvalidIndex,
|
InvalidIndex,
|
||||||
};
|
};
|
||||||
@@ -10,7 +14,8 @@ pub fn Table(comptime T: type, comptime R: type) type {
|
|||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
rdr: R,
|
rdr: PRead(R),
|
||||||
|
comp: Compression,
|
||||||
|
|
||||||
offset: u64,
|
offset: u64,
|
||||||
table_count: u32,
|
table_count: u32,
|
||||||
@@ -18,10 +23,11 @@ pub fn Table(comptime T: type, comptime R: type) type {
|
|||||||
|
|
||||||
table: []T = &[0]T{},
|
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 .{
|
return .{
|
||||||
.alloc = alloc,
|
.alloc = alloc,
|
||||||
.rdr = rdr,
|
.rdr = rdr,
|
||||||
|
.comp = comp,
|
||||||
.offset = offset,
|
.offset = offset,
|
||||||
.table_count = table_count,
|
.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.resize(to_read);
|
||||||
_ = try self.rdr.pread(std.mem.asBytes(&offset), self.offset);
|
_ = try self.rdr.pread(std.mem.asBytes(&offset), self.offset);
|
||||||
self.offset += 8;
|
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];
|
return self.table[idx];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user