From f122d1b4be999034cc2c0571f3437bbceb8b1503 Mon Sep 17 00:00:00 2001 From: Caleb Gardner Date: Wed, 28 May 2025 00:57:12 -0500 Subject: [PATCH] Fixed the final, lingering issues. Updated README --- README.md | 4 ++++ build.zig.zon | 2 +- src/inode/file.zig | 6 +++--- src/reader.zig | 34 +++++++++++++++---------------- src/readers/data_extractor.zig | 37 ++++++++++++++++++++++++---------- src/zig_unsquashfs.zig | 1 + 6 files changed, 51 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index cf72099..821e526 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ # zig-squashfs Messing around with zig via making a squashfs library. May amount to something. Or not. + +## Current state + +Everything seems to be working now, but performance is absolutely garbage. diff --git a/build.zig.zon b/build.zig.zon index 4d028e2..ed4eb92 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,6 +1,6 @@ .{ .name = .zig_squashfs, - .version = "0.0.0", + .version = "0.0.1", .fingerprint = 0x527960c72c03ffe3, // Changing this has security and trust implications. .minimum_zig_version = "0.14.0", diff --git a/src/inode/file.zig b/src/inode/file.zig index e726394..bd86862 100644 --- a/src/inode/file.zig +++ b/src/inode/file.zig @@ -2,9 +2,9 @@ const std = @import("std"); const io = std.io; pub const BlockSize = packed struct { - size: u23, + size: u24, not_compressed: bool, - _: u8, + _: u7, }; pub const FileInode = struct { @@ -15,7 +15,7 @@ pub const FileInode = struct { blocks: []const BlockSize, pub fn init(alloc: std.mem.Allocator, rdr: io.AnyReader, block_size: u32) !FileInode { - var fixed_buf = [1]u8{0} ** 16; + var fixed_buf: [16]u8 = undefined; _ = try rdr.readAll(&fixed_buf); const frag_idx = std.mem.bytesToValue(u32, fixed_buf[4..8]); const size = std.mem.bytesToValue(u32, fixed_buf[12..16]); diff --git a/src/reader.zig b/src/reader.zig index 8012647..229dcc9 100644 --- a/src/reader.zig +++ b/src/reader.zig @@ -85,8 +85,9 @@ pub const Reader = struct { } }; +const test_sfs_path = "testing/LinuxPATest.sfs"; + test "root iter" { - const test_sfs_path = "testing/LinuxPATest.sfs"; var rdr: Reader = try .init(std.testing.allocator, test_sfs_path, 0); defer rdr.deinit(); var rootIter = try rdr.root.iterator(&rdr); @@ -96,23 +97,9 @@ test "root iter" { } } -test "extract" { - const test_sfs_path = "testing/LinuxPATest.sfs"; - const extract_path = "testing/testExtract"; - std.fs.cwd().deleteTree(extract_path) catch |err| { - if (err != std.fs.Dir.DeleteFileError.FileNotFound) { - return err; - } - }; - var rdr: Reader = try .init(std.testing.allocator, test_sfs_path, 0); - defer rdr.deinit(); - try rdr.root.extract(&rdr, try .init(), extract_path); -} - test "extract single file" { - const test_sfs_path = "testing/LinuxPATest.sfs"; - const sfs_file_path = "Start.exe"; - const extract_path = "testing/Start.exe"; + const sfs_file_path = "PortableApps/Cool_Retro_Term-dac2b4f-x86_64.AppImage"; + const extract_path = "testing/Cool_Retro_Term-dac2b4f-x86_64.AppImage"; std.fs.cwd().deleteFile(extract_path) catch |err| { if (err != std.fs.Dir.DeleteFileError.FileNotFound) { return err; @@ -126,7 +113,6 @@ test "extract single file" { } test "extract single directory" { - const test_sfs_path = "testing/LinuxPATest.sfs"; const sfs_file_path = "Documents"; const extract_path = "testing/Documents"; try std.fs.cwd().deleteTree(extract_path); @@ -138,3 +124,15 @@ test "extract single directory" { config.verbose = true; try fil.extract(&rdr, config, extract_path); } + +test "full extract" { + const extract_path = "testing/testExtract"; + std.fs.cwd().deleteTree(extract_path) catch |err| { + if (err != std.fs.Dir.DeleteFileError.FileNotFound) { + return err; + } + }; + var rdr: Reader = try .init(std.testing.allocator, test_sfs_path, 0); + defer rdr.deinit(); + try rdr.root.extract(&rdr, try .init(), extract_path); +} diff --git a/src/readers/data_extractor.zig b/src/readers/data_extractor.zig index 80fa6fb..b746a40 100644 --- a/src/readers/data_extractor.zig +++ b/src/readers/data_extractor.zig @@ -76,7 +76,7 @@ pub const DataExtractor = struct { if (self.frag_data != null) self.alloc.free(self.frag_data.?); } - fn processBlockToFile(self: *DataExtractor, wg: *std.Thread.WaitGroup, errs: *std.ArrayList(anyerror), block_ind: usize, fil: *fs.File) void { + fn processBlockToFile(self: *DataExtractor, wg: *std.Thread.WaitGroup, errs: *MutexList, block_ind: usize, fil: *fs.File) void { defer wg.finish(); if (self.sizes[block_ind].not_compressed) { @branchHint(.unlikely); @@ -95,18 +95,15 @@ pub const DataExtractor = struct { return; } const dat = self.alloc.alloc(u8, self.sizes[block_ind].size) catch |err| { - std.debug.print("yo3\n", .{}); errs.append(err) catch {}; return; }; defer self.alloc.free(dat); - _ = fil.preadAll(dat, self.block_offset[block_ind]) catch |err| { - std.debug.print("yo4\n", .{}); + _ = self.holder.file.preadAll(dat, self.block_offset[block_ind]) catch |err| { errs.append(err) catch {}; return; }; fil.pwriteAll(dat, block_ind * self.block_size) catch |err| { - std.debug.print("yo5\n", .{}); errs.append(err) catch {}; }; } else { @@ -119,16 +116,14 @@ pub const DataExtractor = struct { limit.reader().any(), fil_wrtr.any(), ) catch |err| { - std.debug.print("yo6\n", .{}); errs.append(err) catch {}; }; } } - fn fragmentToFile(self: *DataExtractor, wg: *std.Thread.WaitGroup, errs: *std.ArrayList(anyerror), fil: *fs.File) void { + fn fragmentToFile(self: *DataExtractor, wg: *std.Thread.WaitGroup, errs: *MutexList, fil: *fs.File) void { defer wg.finish(); fil.pwriteAll(self.frag_data.?, self.block_size * self.sizes.len) catch |err| { - std.debug.print("yo7\n", .{}); errs.append(err) catch {}; }; } @@ -140,7 +135,7 @@ pub const DataExtractor = struct { /// Optimized for lower memory usage by using File.pwrite. pub fn writeToFile(self: *DataExtractor, pool: *std.Thread.Pool, fil: *fs.File) !void { var wg: std.Thread.WaitGroup = .{}; - var errs: std.ArrayList(anyerror) = .init(self.alloc); + var errs: MutexList = .init(self.alloc); defer errs.deinit(); for (0..self.sizes.len) |i| { wg.start(); @@ -151,9 +146,9 @@ pub const DataExtractor = struct { try pool.spawn(fragmentToFile, .{ self, &wg, &errs, fil }); } wg.wait(); - if (errs.items.len > 0) { + if (errs.list.items.len > 0) { //TODO: better handle all the errors - return errs.items[0]; + return errs.list.items[0]; } } @@ -185,3 +180,23 @@ pub const DataExtractor = struct { // wg.wait(); // } }; + +const MutexList = struct { + list: std.ArrayList(anyerror), + mut: std.Thread.Mutex = .{}, + + fn init(alloc: std.mem.Allocator) MutexList { + return .{ + .list = .init(alloc), + }; + } + fn deinit(self: *MutexList) void { + self.list.deinit(); + } + + fn append(self: *MutexList, err: anyerror) !void { + self.mut.lock(); + defer self.mut.unlock(); + try self.list.append(err); + } +}; diff --git a/src/zig_unsquashfs.zig b/src/zig_unsquashfs.zig index ae8fbc7..f2a6416 100644 --- a/src/zig_unsquashfs.zig +++ b/src/zig_unsquashfs.zig @@ -64,6 +64,7 @@ pub fn main() !void { return; }; defer args.deinit(); + _ = args.next(); while (args.next()) |arg| { if (std.mem.eql(u8, arg, "--help") or std.mem.eql(u8, arg, "-h")) { try help();