Things are working (though slowly)

This commit is contained in:
Caleb Gardner
2025-07-22 05:13:34 -05:00
parent d5c50b19f2
commit a96ad46a6c
5 changed files with 207 additions and 58 deletions
+1 -1
View File
@@ -31,7 +31,7 @@ pub fn build(b: *std.Build) !void {
exe_mod.addOptions("config", opt); exe_mod.addOptions("config", opt);
const exe = b.addExecutable(.{ const exe = b.addExecutable(.{
.linkage = .static, .linkage = .static,
.name = "zig-unsquashfs", .name = "unsquashfs",
.root_module = exe_mod, .root_module = exe_mod,
.version = sem_ver, .version = sem_ver,
}); });
+19 -5
View File
@@ -51,10 +51,10 @@ const ListTypes = enum {
}; };
pub fn main() !void { pub fn main() !void {
var alloc: std.heap.GeneralPurposeAllocator(.{}) = .init; const alloc = std.heap.smp_allocator;
extr_files = .init(alloc.allocator()); extr_files = .init(alloc);
defer extr_files.deinit(); defer extr_files.deinit();
var args = std.process.argsWithAllocator(alloc.allocator()) catch { var args = std.process.argsWithAllocator(alloc) catch {
_ = try stdout.writeAll("Unable to allocate memory"); _ = try stdout.writeAll("Unable to allocate memory");
return; return;
}; };
@@ -119,8 +119,10 @@ pub fn main() !void {
return; return;
} }
const fil = try std.fs.cwd().openFile(filename, .{}); const fil = try std.fs.cwd().openFile(filename, .{});
defer fil.close();
var th_alloc: std.heap.ThreadSafeAllocator = .{ .child_allocator = std.heap.smp_allocator };
var rdr = squashfs.SfsFile.init( var rdr = squashfs.SfsFile.init(
alloc.allocator(), th_alloc.allocator(),
fil, fil,
offset, offset,
) catch |err| { ) catch |err| {
@@ -128,5 +130,17 @@ pub fn main() !void {
return; return;
}; };
defer rdr.deinit(); defer rdr.deinit();
//TODO //TODO: list and extr_files;
var op: squashfs.ExtractionOptions = squashfs.ExtractionOptions.init() catch |err| {
try std.fmt.format(stdout.writer(), "Error setting extraction options: {any}\n", .{err});
return;
};
op.verbose = verbose;
op.dereference_symlinks = deref;
op.unbreak_symlinks = unbreak;
if (processors != 0) op.thread_count = processors;
rdr.extract(op, extr_location) catch |err| {
try std.fmt.format(stdout.writer(), "Error extracting archive: {any}\n", .{err});
return;
};
} }
+173 -44
View File
@@ -219,7 +219,7 @@ pub fn File(comptime T: type) type {
defer pol.deinit(); defer pol.deinit();
var errs: std.ArrayList(anyerror) = .init(self.rdr.alloc); var errs: std.ArrayList(anyerror) = .init(self.rdr.alloc);
defer errs.deinit(); defer errs.deinit();
try self.extractReal(op, path, &errs, &wg, &pol, true); self.extractReal(op, path, &errs, &wg, &pol, true);
wg.wait(); wg.wait();
if (errs.items.len > 0) return errs.items[0]; if (errs.items.len > 0) return errs.items[0];
} }
@@ -231,7 +231,7 @@ pub fn File(comptime T: type) type {
wg: *WaitGroup, wg: *WaitGroup,
pol: *Pool, pol: *Pool,
first: bool, first: bool,
) !void { ) void {
if (errs.items.len > 0) return; if (errs.items.len > 0) return;
if (op.verbose) { if (op.verbose) {
std.fmt.format( std.fmt.format(
@@ -242,18 +242,22 @@ pub fn File(comptime T: type) type {
} }
return switch (self.inode.hdr.type) { return switch (self.inode.hdr.type) {
.dir, .ext_dir => { .dir, .ext_dir => {
var complete = false;
wg.start(); wg.start();
defer std.debug.print("{}\n", .{wg.state.raw}); defer if (!complete) wg.finish();
errdefer wg.finish();
std.fs.cwd().makeDir(path) catch |err| { std.fs.cwd().makeDir(path) catch |err| {
if (err != std.fs.Dir.MakeError.PathAlreadyExists) { if (err != std.fs.Dir.MakeError.PathAlreadyExists) {
return err; errs.append(err) catch {};
return;
} }
}; };
var dir_wg = try self.rdr.alloc.create(WaitGroup); const dir_wg = self.rdr.alloc.create(WaitGroup) catch |err| {
errs.append(err) catch {};
return;
};
dir_wg.* = .{}; dir_wg.* = .{};
for (self.entries.?) |ent| { for (self.entries.?) |ent| {
var fil = initFromEntry(self.rdr, ent) catch |err| { const fil = initFromEntry(self.rdr, ent) catch |err| {
std.fmt.format( std.fmt.format(
op.verbose_logger, op.verbose_logger,
"error extracting inode {} \"{s}\": {}\n", "error extracting inode {} \"{s}\": {}\n",
@@ -285,39 +289,109 @@ pub fn File(comptime T: type) type {
) catch {}; ) catch {};
continue; continue;
}; };
fil.extractReal(op, ext_path, errs, dir_wg, pol, false) catch |err| { var thr = std.Thread.spawn(.{ .allocator = self.rdr.alloc }, extractReal, .{
std.fmt.format( fil,
op.verbose_logger, op,
"error extracting inode {} \"{s}\": {}\n", ext_path,
.{ ent.num, path, err }, errs,
) catch {}; dir_wg,
pol,
false,
}) catch |err| {
self.rdr.alloc.free(ext_path);
if (op.verbose) {
std.fmt.format(
op.verbose_logger,
"error extracting inode {} \"{s}\": {}\n",
.{ ent.num, path, err },
) catch {};
}
continue; continue;
}; };
thr.detach();
} }
dir_wg.wait(); var thr = std.Thread.spawn(
wg.finish(); .{ .allocator = self.rdr.alloc },
std.debug.print("finished: {s}\n", .{path}); extractDirWait,
.{
self,
op,
path,
dir_wg,
wg,
first,
},
) catch |err| {
if (op.verbose) {
std.fmt.format(
op.verbose_logger,
"error spawning wait thread for \"{s}\": {}\n",
.{ path, err },
) catch {};
}
self.extractDirWait(op, path, dir_wg, wg, first);
return;
};
thr.detach();
complete = true;
}, },
.file, .ext_file => { .file, .ext_file => {
var complete = false;
wg.start(); wg.start();
errdefer wg.finish(); defer if (!complete) wg.finish();
var ext_fil = try std.fs.cwd().createFile(path, .{}); var ext_fil = std.fs.cwd().createFile(path, .{}) catch |err| {
errdefer ext_fil.close(); if (op.verbose) {
var fil_errs = try self.rdr.alloc.create(std.ArrayList(anyerror)); std.fmt.format(
errdefer self.rdr.alloc.destroy(fil_errs); op.verbose_logger,
"error creating file \"{s}\": {}\n",
.{ path, err },
) catch {};
}
errs.append(err) catch {};
return;
};
defer if (!complete) ext_fil.close();
var fil_errs = self.rdr.alloc.create(std.ArrayList(anyerror)) catch |err| {
if (op.verbose) {
std.fmt.format(
op.verbose_logger,
"error allocating memory: {}\n",
.{err},
) catch {};
}
errs.append(err) catch {};
return;
};
defer if (!complete) self.rdr.alloc.destroy(fil_errs);
fil_errs.* = .init(self.rdr.alloc); fil_errs.* = .init(self.rdr.alloc);
errdefer fil_errs.deinit(); defer if (!complete) fil_errs.deinit();
@constCast(&self.data_reader.?).setPool(pol); @constCast(&self.data_reader.?).setPool(pol);
try self.data_reader.?.writeToNoBlock(errs, ext_fil, extractRegFinish, .{ self.data_reader.?.writeToNoBlock(
self,
op,
path,
fil_errs,
errs, errs,
wg,
ext_fil, ext_fil,
first, extractRegFinish,
}); .{
self,
op,
path,
fil_errs,
errs,
wg,
ext_fil,
first,
},
) catch |err| {
if (op.verbose) {
std.fmt.format(
op.verbose_logger,
"error extracting file \"{s}\": {}\n",
.{ path, err },
) catch {};
}
errs.append(err) catch {};
return;
};
complete = true;
}, },
.symlink, .ext_symlink => {}, .symlink, .ext_symlink => {},
.block_dev, .ext_block_dev, .char_dev, .ext_char_dev, .fifo, .ext_fifo => { .block_dev, .ext_block_dev, .char_dev, .ext_char_dev, .fifo, .ext_fifo => {
@@ -334,14 +408,66 @@ pub fn File(comptime T: type) type {
}, },
}; };
} }
// fn extractFileFinish( fn extractDirWait(
// self: Self, self: Self,
// op: ExtractionOptions, op: ExtractionOptions,
// path: []const u8, path: []const u8,
// dir_wg: *WaitGroup, dir_wg: *WaitGroup,
// dir_wg_mut: *Mutex, wg: *WaitGroup,
// wg: *WaitGroup, first: bool,
// ) void {} ) void {
dir_wg.wait();
self.rdr.alloc.destroy(dir_wg);
defer {
wg.finish();
if (!first) {
self.rdr.alloc.free(path);
self.deinit();
}
}
if (op.ignore_permissions) return;
const dir_uid = self.uid() catch |err| {
std.fmt.format(
op.verbose_logger,
"error getting uid for inode {} \"{s}\": {}\n",
.{ self.inode.hdr.num, path, err },
) catch {};
return;
};
const dir_gid = self.gid() catch |err| {
std.fmt.format(
op.verbose_logger,
"error getting gid for inode {} \"{s}\": {}\n",
.{ self.inode.hdr.num, path, err },
) catch {};
return;
};
var ext_dir = std.fs.cwd().openFile(path, .{}) catch |err| {
std.fmt.format(
op.verbose_logger,
"error setting owner & permissions for \"{s}\": {}\n",
.{ path, err },
) catch {};
return;
};
defer ext_dir.close();
ext_dir.chmod(self.inode.hdr.perm) catch |err| {
std.fmt.format(
op.verbose_logger,
"error setting permissions for inode {} \"{s}\": {}\n",
.{ self.inode.hdr.num, path, err },
) catch {};
return;
};
ext_dir.chown(dir_uid, dir_gid) catch |err| {
std.fmt.format(
op.verbose_logger,
"error setting owner for inode {} \"{s}\": {}\n",
.{ self.inode.hdr.num, path, err },
) catch {};
return;
};
}
fn extractRegFinish( fn extractRegFinish(
self: Self, self: Self,
op: ExtractionOptions, op: ExtractionOptions,
@@ -352,12 +478,15 @@ pub fn File(comptime T: type) type {
fil: std.fs.File, fil: std.fs.File,
first: bool, first: bool,
) void { ) void {
defer std.debug.print("{}\n", .{wg.state.raw}); defer {
defer wg.finish(); wg.finish();
defer fil.close(); fil.close();
defer self.rdr.alloc.destroy(fil_errs); self.rdr.alloc.destroy(fil_errs);
defer if (!first) self.deinit(); if (!first) {
defer if (!first) self.rdr.alloc.free(path); self.deinit();
self.rdr.alloc.free(path);
}
}
if (fil_errs.items.len > 0) { if (fil_errs.items.len > 0) {
if (op.verbose) { if (op.verbose) {
std.fmt.format( std.fmt.format(
+10 -4
View File
@@ -188,6 +188,10 @@ pub fn DataReader(comptime T: type) type {
on_finish_args: anytype, on_finish_args: anytype,
) !void { ) !void {
if (self.pool == null) return DataReaderError.ThreadPoolNotSet; if (self.pool == null) return DataReaderError.ThreadPoolNotSet;
if (self.numBlocks() == 0) {
@call(.auto, on_finish, on_finish_args);
return;
}
var mut: std.Thread.Mutex = .{}; var mut: std.Thread.Mutex = .{};
var cur_idx: usize = 0; var cur_idx: usize = 0;
var block_wg = try self.alloc.create(std.Thread.WaitGroup); var block_wg = try self.alloc.create(std.Thread.WaitGroup);
@@ -200,7 +204,8 @@ pub fn DataReader(comptime T: type) type {
} }
block_wg.startMany(self.numBlocks()); block_wg.startMany(self.numBlocks());
for (0..self.numBlocks()) |i| { for (0..self.numBlocks()) |i| {
try self.pool.?.spawn( var thr = try std.Thread.spawn(
.{ .allocator = self.alloc },
comptime blk: { comptime blk: {
if (std.meta.hasFn(@TypeOf(writer), "pwrite")) { if (std.meta.hasFn(@TypeOf(writer), "pwrite")) {
break :blk noBlockThreadPWrite; break :blk noBlockThreadPWrite;
@@ -215,6 +220,7 @@ pub fn DataReader(comptime T: type) type {
} }
}, },
); );
thr.detach();
} }
} }
@@ -353,12 +359,12 @@ pub fn DataReader(comptime T: type) type {
self.writeBlockToPWrite(errs, idx, writer); self.writeBlockToPWrite(errs, idx, writer);
finish_mut.lock(); finish_mut.lock();
block_wg.finish(); block_wg.finish();
const isDone = block_wg.isDone();
defer { defer {
const done = block_wg.isDone();
finish_mut.unlock(); finish_mut.unlock();
if (done) self.alloc.destroy(finish_mut); if (isDone) self.alloc.destroy(finish_mut);
} }
if (block_wg.isDone()) { if (isDone) {
self.alloc.destroy(block_wg); self.alloc.destroy(block_wg);
@call(.auto, on_finish, on_finish_args); @call(.auto, on_finish, on_finish_args);
} }
+4 -4
View File
@@ -26,8 +26,8 @@ test "OpenFile" {
} }
test "ExtractSingleFile" { test "ExtractSingleFile" {
const single_file = "Start.exe"; const single_file = "PortableApps/Notepad++Portable/App/Notepad++/doLocalConf.xml";
const single_file_extr_loc = "testing/Start.exe"; const single_file_extr_loc = "testing/doLocalConf.xml";
std.fs.cwd().deleteFile(single_file_extr_loc) catch {}; std.fs.cwd().deleteFile(single_file_extr_loc) catch {};
const sfs_fil = try std.fs.cwd().openFile(test_archive, .{}); const sfs_fil = try std.fs.cwd().openFile(test_archive, .{});
@@ -49,7 +49,7 @@ test "ExtractAll" {
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();
var op: ExtractionOptions = try .init(); const op: ExtractionOptions = try .init();
op.verbose = true; // op.verbose = true;
try rdr.extract(op, extr_dir); try rdr.extract(op, extr_dir);
} }