Basic extraction complete

This commit is contained in:
Caleb J. Gardner
2025-08-16 01:25:38 -05:00
parent 99e3b81100
commit 451e53264d
3 changed files with 113 additions and 11 deletions
+110 -7
View File
@@ -201,13 +201,10 @@ pub fn File(comptime T: type) type {
inode: Inode, inode: Inode,
path: []const u8, path: []const u8,
) !void { ) !void {
_ = errs;
_ = pol;
wg.start(); wg.start();
defer wg.finish(); //TODO: When everthing is threaded, this will need to be handled by the threads, not here. defer wg.finish(); //TODO: When everthing is threaded, this will need to be handled by the threads, not here.
switch (inode.hdr.type) { switch (inode.hdr.type) {
.file => { .file, .ext_file => {
var fil = try std.fs.cwd().createFile(path, .{}); var fil = try std.fs.cwd().createFile(path, .{});
defer fil.close(); defer fil.close();
var data: DataReader(T) = try .init(self.rdr, inode); var data: DataReader(T) = try .init(self.rdr, inode);
@@ -239,10 +236,116 @@ pub fn File(comptime T: type) type {
}; };
//TODO: update mtime. //TODO: update mtime.
}, },
.dir => { .dir, .ext_dir => {
std.fs.cwd().makeDir(path); //TODO: Check existence std.fs.cwd().makeDir(path) catch |err| {
if (err != std.fs.Dir.MakeError.PathAlreadyExists) {
return err;
}
};
var dir_block: u32 = 0;
var dir_offset: u16 = 0;
var dir_size: u32 = 0;
switch (inode.data) {
.dir => |d| {
dir_block = d.block;
dir_offset = d.offset;
dir_size = d.size;
},
.ext_dir => |d| {
dir_block = d.block;
dir_offset = d.offset;
dir_size = d.size;
},
else => unreachable,
}
var meta: MetadataReader(T) = .init(self.rdr.alloc, self.rdr.super.comp, self.rdr.rdr, dir_block + self.rdr.super.dir_start);
try meta.skip(dir_offset);
const entries = try dir.readDirectory(self.rdr.alloc, &meta, dir_size);
defer self.rdr.alloc.free(entries);
for (entries) |ent| {
defer ent.deinit(self.rdr.alloc);
var new_path: []u8 = undefined;
if (path[path.len - 1] == '/') {
new_path = self.rdr.alloc.alloc(u8, path.len + ent.name.len) catch |err| {
if (op.verbose) {
std.fmt.format(op.verbose_logger, "error allocating memory: {}\n", .{err}) catch {};
}
errs.append(err) catch {};
continue;
};
@memcpy(new_path[0..path.len], path);
@memcpy(new_path[path.len..], ent.name);
} else {
new_path = self.rdr.alloc.alloc(u8, path.len + ent.name.len + 1) catch |err| {
if (op.verbose) {
std.fmt.format(op.verbose_logger, "error allocating memory: {}\n", .{err}) catch {};
}
errs.append(err) catch {};
continue;
};
@memcpy(new_path[0..path.len], path);
new_path[path.len] = '/';
@memcpy(new_path[path.len + 1 ..], ent.name);
}
defer self.rdr.alloc.free(new_path);
meta = .init(self.rdr.alloc, self.rdr.super.comp, self.rdr.rdr, ent.block + self.rdr.super.inode_start);
meta.skip(ent.offset) catch |err| {
if (op.verbose) {
std.fmt.format(op.verbose_logger, "error reading inode: {}\n", .{err}) catch {};
}
errs.append(err) catch {};
continue;
};
const new_inode = Inode.init(&meta, self.rdr.alloc, self.rdr.super.block_size) catch |err| {
if (op.verbose) {
std.fmt.format(op.verbose_logger, "error reading inode: {}\n", .{err}) catch {};
}
errs.append(err) catch {};
continue;
};
defer new_inode.deinit(self.rdr.alloc);
self.extractInode(op, wg, errs, pol, new_inode, new_path) catch |err| {
if (op.verbose) {
std.fmt.format(op.verbose_logger, "error extracting {s}: {}\n", .{ new_path, err }) catch {};
}
errs.append(err) catch {};
continue;
};
}
var fil = std.fs.cwd().openDir(path, .{ .iterate = true }) catch |err| {
if (op.verbose) {
std.fmt.format(op.verbose_logger, "error openning {s} to set permissions: {}\n", .{ path, err }) catch {};
}
return;
};
const fil_uid = self.rdr.id_table.get(inode.hdr.uid_idx) catch |err| {
if (op.verbose) {
std.fmt.format(op.verbose_logger, "error getting uid {} from table: {}\n", .{ inode.hdr.uid_idx, err }) catch {};
}
return;
};
const fil_gid = self.rdr.id_table.get(inode.hdr.gid_idx) catch |err| {
if (op.verbose) {
std.fmt.format(op.verbose_logger, "error getting gid {} from table: {}\n", .{ inode.hdr.gid_idx, err }) catch {};
}
return;
};
fil.chmod(inode.hdr.perm) catch |err| {
if (op.verbose) {
std.fmt.format(op.verbose_logger, "error chmod {s}: {}\n", .{ path, err }) catch {};
}
return;
};
fil.chown(fil_uid, fil_gid) catch |err| {
if (op.verbose) {
std.fmt.format(op.verbose_logger, "error chmod {s}: {}\n", .{ path, err }) catch {};
}
return;
};
}, },
.symlink => {}, // .symlink, .ext_symlink => {},
else => { else => {
std.debug.print("TODO: {}\n", .{inode.hdr.type}); std.debug.print("TODO: {}\n", .{inode.hdr.type});
}, },
+2 -3
View File
@@ -51,8 +51,6 @@ const DecompCompletion = struct {
} }
fn getBlock(self: *DecompCompletion, idx: usize) ?[]u8 { fn getBlock(self: *DecompCompletion, idx: usize) ?[]u8 {
self.mut.lock();
defer self.mut.unlock();
const res = self.map.fetchSwapRemove(idx); const res = self.map.fetchSwapRemove(idx);
if (res == null) return null; if (res == null) return null;
return res.?.value; return res.?.value;
@@ -216,7 +214,8 @@ pub fn DataReader(comptime T: type) type {
self.completion.condWait(); self.completion.condWait();
if (self.completion.hasErrs()) break; if (self.completion.hasErrs()) break;
if (comptime std.meta.hasFn(@TypeOf(wrt), "pwrite")) { if (comptime std.meta.hasFn(@TypeOf(wrt), "pwrite")) {
for (self.completion.map.keys()) |k| { for (self.completion.map.keys()) |_| {
const k = self.completion.map.keys()[0];
const blk = self.completion.getBlock(k).?; const blk = self.completion.getBlock(k).?;
defer self.alloc.free(blk); defer self.alloc.free(blk);
if (blk.len > 0) { if (blk.len > 0) {
+1 -1
View File
@@ -25,7 +25,7 @@ test "OpenFile" {
defer f.?.deinit(); defer f.?.deinit();
std.debug.print("{s}\n", .{f.?.name}); std.debug.print("{s}\n", .{f.?.name});
} }
std.debug.print("Finished OpenFile test", .{}); std.debug.print("Finished OpenFile test\n", .{});
} }
test "ExtractSingleFile" { test "ExtractSingleFile" {