Started changes to Zig 0.16.0

This commit is contained in:
Caleb Gardner
2026-04-29 02:20:46 -05:00
parent cfc0e58905
commit 21f1a304ca
19 changed files with 91 additions and 72 deletions
+1
View File
@@ -2,3 +2,4 @@ testing/
.zig-cache/ .zig-cache/
zig-out/ zig-out/
zig-pkg/
+10 -2
View File
@@ -1,7 +1,7 @@
const std = @import("std"); const std = @import("std");
pub fn build(b: *std.Build) !void { pub fn build(b: *std.Build) !void {
const use_zig_decomp = b.option(bool, "use_zig_decomp", "Use zig standard library for decompression.") orelse false; const use_zig_decomp = b.option(bool, "use_zig_decomp", "Use zig standard library for decompression.") orelse true;
// const allow_lzo = b.option(bool, "allow_lzo", "Compile with lzo support") orelse false; // const allow_lzo = b.option(bool, "allow_lzo", "Compile with lzo support") orelse false;
const debug = b.option(bool, "debug", "Enable options to make debugging easier.") orelse false; const debug = b.option(bool, "debug", "Enable options to make debugging easier.") orelse false;
const version_string_option = b.option([]const u8, "version", "Version of the library/binary"); const version_string_option = b.option([]const u8, "version", "Version of the library/binary");
@@ -16,13 +16,21 @@ pub fn build(b: *std.Build) !void {
.root_source_file = b.path("src/root.zig"), .root_source_file = b.path("src/root.zig"),
.target = target, .target = target,
.optimize = if (debug == true) .Debug else optimize, .optimize = if (debug == true) .Debug else optimize,
.link_libc = !use_zig_decomp,
.valgrind = debug, .valgrind = debug,
.error_tracing = debug, .error_tracing = debug,
.strip = if (debug == true) false else null, .strip = if (debug == true) false else null,
}); });
mod.addOptions("config", zig_squashfs_options); mod.addOptions("config", zig_squashfs_options);
if (!use_zig_decomp) { if (!use_zig_decomp) {
mod.link_libc = true;
const c_imports = b.addTranslateC(.{
.optimize = optimize,
.target = target,
.root_source_file = b.path("src/imports.c"),
});
mod.addImport("c", c_imports.createModule());
var zlib_ng = b.dependency("zlib_ng", .{ var zlib_ng = b.dependency("zlib_ng", .{
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
+5 -5
View File
@@ -2,7 +2,7 @@
.name = .squashfs, .name = .squashfs,
.version = "0.0.6", .version = "0.0.6",
.fingerprint = 0x37ba29474b87f145, // Changing this has security and trust implications. .fingerprint = 0x37ba29474b87f145, // Changing this has security and trust implications.
.minimum_zig_version = "0.15.2", .minimum_zig_version = "0.16.0",
.dependencies = .{ .dependencies = .{
.zlib_ng = .{ .zlib_ng = .{
// .url = "git+https://github.com/CalebQ42/zig-zlib-ng#5f2f02dfb28acca2517dacbbd09e9b987f57b133", // .url = "git+https://github.com/CalebQ42/zig-zlib-ng#5f2f02dfb28acca2517dacbbd09e9b987f57b133",
@@ -22,10 +22,10 @@
// .hash = "minilzo-2.10.0-Ij7BO8wLAADeWI4Pe4jp8XTDsDaquZR14oZ7_9yKKDWP", // .hash = "minilzo-2.10.0-Ij7BO8wLAADeWI4Pe4jp8XTDsDaquZR14oZ7_9yKKDWP",
.path = "../zig-minilzo", .path = "../zig-minilzo",
}, },
.fastlzma2 = .{ // .fastlzma2 = .{
.url = "git+https://github.com/allyourcodebase/fast-lzma2#d7615e0c957a62fcd6691b3fe9519a091885bfa2", // .url = "git+https://github.com/allyourcodebase/fast-lzma2#d7615e0c957a62fcd6691b3fe9519a091885bfa2",
.hash = "fastlzma2-0.0.0-gNWHgVeLAAD0Tlak3xhNcgpPSYcjyJppq0tlGmPKCC_V", // .hash = "fastlzma2-0.0.0-gNWHgVeLAAD0Tlak3xhNcgpPSYcjyJppq0tlGmPKCC_V",
}, // },
}, },
.paths = .{ .paths = .{
"build.zig", "build.zig",
+3 -2
View File
@@ -1,4 +1,5 @@
const std = @import("std"); const std = @import("std");
const Io = std.Io;
const DecompTypes = @import("decomp/types.zig"); const DecompTypes = @import("decomp/types.zig");
const Decompressor = @import("decomp.zig"); const Decompressor = @import("decomp.zig");
@@ -27,9 +28,9 @@ super: Superblock,
stateless_decomp: Decompressor, stateless_decomp: Decompressor,
/// Create an Archive from a File. /// Create an Archive from a File.
pub fn init(fil: std.fs.File, offset: u64) !Archive { pub fn init(io: Io, fil: Io.File, offset: u64) !Archive {
var super: Superblock = undefined; var super: Superblock = undefined;
var fil_rdr = fil.reader(&[0]u8{}); var fil_rdr = fil.reader(io, &[0]u8{});
if (offset > 0) if (offset > 0)
try fil_rdr.seekTo(offset); try fil_rdr.seekTo(offset);
try fil_rdr.interface.readSliceEndian(Superblock, @ptrCast(&super), .little); try fil_rdr.interface.readSliceEndian(Superblock, @ptrCast(&super), .little);
+21 -18
View File
@@ -1,5 +1,6 @@
const std = @import("std"); const std = @import("std");
const Writer = std.Io.Writer; const Io = std.Io;
const Writer = Io.Writer;
const builtin = @import("builtin"); const builtin = @import("builtin");
const config = @import("config"); const config = @import("config");
@@ -38,20 +39,22 @@ var ignore_xattrs: bool = false;
var ignore_permissions: bool = false; var ignore_permissions: bool = false;
var force: bool = false; var force: bool = false;
pub fn main() !void { pub fn main(init: std.process.Init) !void {
const alloc = std.heap.smp_allocator; const alloc = init.gpa;
var stdout = std.fs.File.stdout(); const io = init.io;
var out = stdout.writer(&[0]u8{});
var stdout = std.Io.File.stdout();
var out = stdout.writer(io, &[0]u8{});
defer out.interface.flush() catch {}; defer out.interface.flush() catch {};
try handleArgs(alloc, &out.interface); try handleArgs(init.minimal.args, &out.interface);
if (archive.len == 0) { if (archive.len == 0) {
try out.interface.print("You must provide a squashfs archive\n", .{}); try out.interface.print("You must provide a squashfs archive\n", .{});
try out.interface.print(help_mgs, .{}); try out.interface.print(help_mgs, .{});
return; return;
} }
var fil: std.fs.File = try std.fs.cwd().openFile(archive, .{}); //TODO: Handle error gracefully. var fil: Io.File = try Io.Dir.cwd().openFile(io, archive, .{}); //TODO: Handle error gracefully.
defer fil.close(); defer fil.close(io);
var arc: squashfs.Archive = try .init(fil, offset); //TODO: Handle error gracefully. var arc: squashfs.Archive = try .init(io, fil, offset); //TODO: Handle error gracefully.
const options: squashfs.ExtractionOptions = .{ const options: squashfs.ExtractionOptions = .{
.threads = if (threads == 0) try std.Thread.getCpuCount() else threads, .threads = if (threads == 0) try std.Thread.getCpuCount() else threads,
.verbose = verbose, .verbose = verbose,
@@ -60,17 +63,17 @@ pub fn main() !void {
.ignore_permissions = ignore_permissions, .ignore_permissions = ignore_permissions,
}; };
if (force) if (force)
try std.fs.cwd().deleteTree(extLoc); try Io.Dir.cwd().deleteTree(io, extLoc);
try arc.extract(alloc, extLoc, options); //TODO: Handle error gracefully. try arc.extract(alloc, extLoc, options); //TODO: Handle error gracefully.
} }
fn handleArgs(alloc: std.mem.Allocator, out: *Writer) !void { fn handleArgs(args: std.process.Args, out: *Writer) !void {
var args = try std.process.argsWithAllocator(alloc); var arg_iter = args.iterate();
defer args.deinit(); defer arg_iter.deinit();
_ = args.next(); // args[0] is the application launch command. _ = arg_iter.next(); // args[0] is the application launch command.
while (args.next()) |arg| { while (arg_iter.next()) |arg| {
if (std.mem.eql(u8, arg, "-o")) { if (std.mem.eql(u8, arg, "-o")) {
const nxt = args.next(); const nxt = arg_iter.next();
if (nxt == null or nxt.?.len == 0) { if (nxt == null or nxt.?.len == 0) {
try out.print("-o must be followed by a number\n", .{}); try out.print("-o must be followed by a number\n", .{});
return errors.InvalidArguments; return errors.InvalidArguments;
@@ -81,7 +84,7 @@ fn handleArgs(alloc: std.mem.Allocator, out: *Writer) !void {
}; };
continue; continue;
} else if (std.mem.eql(u8, arg, "-d")) { } else if (std.mem.eql(u8, arg, "-d")) {
const nxt = args.next(); const nxt = arg_iter.next();
if (nxt == null or nxt.?.len == 0) { if (nxt == null or nxt.?.len == 0) {
try out.print("-d must be followed by a location\n", .{}); try out.print("-d must be followed by a location\n", .{});
return errors.InvalidArguments; return errors.InvalidArguments;
@@ -89,7 +92,7 @@ fn handleArgs(alloc: std.mem.Allocator, out: *Writer) !void {
extLoc = nxt.?; extLoc = nxt.?;
continue; continue;
} else if (std.mem.eql(u8, arg, "-p")) { } else if (std.mem.eql(u8, arg, "-p")) {
const nxt = args.next(); const nxt = arg_iter.next();
if (nxt == null or nxt.?.len == 0) { if (nxt == null or nxt.?.len == 0) {
try out.print("-p must be followed by a number\n", .{}); try out.print("-p must be followed by a number\n", .{});
return errors.InvalidArguments; return errors.InvalidArguments;
-7
View File
@@ -1,7 +0,0 @@
pub const c = @cImport({
@cInclude("zlib-ng.h");
@cInclude("lzo/minilzo.h");
@cInclude("lz4.h");
@cInclude("zstd.h");
@cInclude("lzma.h");
});
+1 -1
View File
@@ -1,6 +1,6 @@
const std = @import("std"); const std = @import("std");
const c = @import("../../c_libs.zig").c; const c = @import("c");
const Decompressor = @import("../../decomp.zig"); const Decompressor = @import("../../decomp.zig");
interface: Decompressor = .{ .vtable = &.{ .stateless = stateless } }, interface: Decompressor = .{ .vtable = &.{ .stateless = stateless } },
+3 -3
View File
@@ -1,6 +1,6 @@
const std = @import("std"); const std = @import("std");
const c = @import("../../c_libs.zig").c; const c = @import("c");
const Decompressor = @import("../../decomp.zig"); const Decompressor = @import("../../decomp.zig");
const Lzma = @This(); const Lzma = @This();
@@ -120,12 +120,12 @@ fn lzmaErrorToDecompError(err: Error) Decompressor.Error {
} }
fn lzmaAlloc(ptr: ?*anyopaque, _: usize, size: usize) callconv(.c) ?*anyopaque { fn lzmaAlloc(ptr: ?*anyopaque, _: usize, size: usize) callconv(.c) ?*anyopaque {
var alloc: *std.mem.Allocator = @alignCast(@ptrCast(ptr)); var alloc: *std.mem.Allocator = @ptrCast(@alignCast(ptr));
return alloc.rawAlloc(size, .@"1", 0); return alloc.rawAlloc(size, .@"1", 0);
} }
fn lzmaFree(ptr: ?*anyopaque, alloc_ptr: ?*anyopaque) callconv(.c) void { fn lzmaFree(ptr: ?*anyopaque, alloc_ptr: ?*anyopaque) callconv(.c) void {
if (alloc_ptr == null) return; if (alloc_ptr == null) return;
var alloc: *std.mem.Allocator = @alignCast(@ptrCast(ptr)); var alloc: *std.mem.Allocator = @ptrCast(@alignCast(ptr));
alloc.rawFree(@ptrCast(alloc_ptr), .@"1", 0); alloc.rawFree(@ptrCast(alloc_ptr), .@"1", 0);
} }
+1 -1
View File
@@ -1,6 +1,6 @@
const std = @import("std"); const std = @import("std");
const c = @import("../../c_libs.zig").c; const c = @import("c");
const Decompressor = @import("../../decomp.zig"); const Decompressor = @import("../../decomp.zig");
interface: Decompressor = .{ .vtable = &.{ .stateless = stateless } }, interface: Decompressor = .{ .vtable = &.{ .stateless = stateless } },
+3 -3
View File
@@ -1,6 +1,6 @@
const std = @import("std"); const std = @import("std");
const c = @import("../../c_libs.zig").c; const c = @import("c");
const Decompressor = @import("../../decomp.zig"); const Decompressor = @import("../../decomp.zig");
const Xz = @This(); const Xz = @This();
@@ -120,12 +120,12 @@ fn xzErrorToDecompError(err: Error) Decompressor.Error {
} }
fn lzmaAlloc(ptr: ?*anyopaque, _: usize, size: usize) callconv(.c) ?*anyopaque { fn lzmaAlloc(ptr: ?*anyopaque, _: usize, size: usize) callconv(.c) ?*anyopaque {
var alloc: *std.mem.Allocator = @alignCast(@ptrCast(ptr)); var alloc: *std.mem.Allocator = @ptrCast(@alignCast(ptr));
return alloc.rawAlloc(size, .@"1", 0); return alloc.rawAlloc(size, .@"1", 0);
} }
fn lzmaFree(ptr: ?*anyopaque, alloc_ptr: ?*anyopaque) callconv(.c) void { fn lzmaFree(ptr: ?*anyopaque, alloc_ptr: ?*anyopaque) callconv(.c) void {
if (alloc_ptr == null) return; if (alloc_ptr == null) return;
var alloc: *std.mem.Allocator = @alignCast(@ptrCast(ptr)); var alloc: *std.mem.Allocator = @ptrCast(@alignCast(ptr));
alloc.rawFree(@ptrCast(alloc_ptr), .@"1", 0); alloc.rawFree(@ptrCast(alloc_ptr), .@"1", 0);
} }
+1 -1
View File
@@ -1,6 +1,6 @@
const std = @import("std"); const std = @import("std");
const c = @import("../../c_libs.zig").c; const c = @import("c");
const Decompressor = @import("../../decomp.zig"); const Decompressor = @import("../../decomp.zig");
const Zlib = @This(); const Zlib = @This();
+1 -1
View File
@@ -1,6 +1,6 @@
const std = @import("std"); const std = @import("std");
const c = @import("../../c_libs.zig").c; const c = @import("c");
const Decompressor = @import("../../decomp.zig"); const Decompressor = @import("../../decomp.zig");
const Zstd = @This(); const Zstd = @This();
+12 -7
View File
@@ -7,12 +7,17 @@ const Decompressor = @import("../../decomp.zig");
interface: Decompressor = .{ .vtable = &.{ .stateless = stateless } }, interface: Decompressor = .{ .vtable = &.{ .stateless = stateless } },
pub fn stateless(alloc: std.mem.Allocator, in: []u8, out: []u8) Decompressor.Error!usize { pub fn stateless(alloc: std.mem.Allocator, in: []u8, out: []u8) Decompressor.Error!usize {
var rdr: Reader = .static(in); var rdr: Reader = .fixed(in);
var decomp = try lzma.decompress(alloc, rdr.adaptToOldInterface()); const buf = try alloc.alloc(u8, in.len);
defer decomp.deinit(); defer alloc.free(buf);
const len = decomp.read(out) catch |err| return switch (err) {
error.CorruptInput, error.EndOfStream, error.Overflow => Decompressor.Error.ReadFailed, var decomp = lzma.Decompress.initOptions(&rdr, alloc, buf, .{}, out.len) catch |err|
else => err, return switch (err) {
error.Overflow => Decompressor.Error.ReadFailed,
error.CorruptInput => Decompressor.Error.ReadFailed,
error.InvalidRangeCode => Decompressor.Error.ReadFailed,
else => @errorCast(err),
}; };
return len; defer decomp.deinit();
return decomp.reader.readSliceShort(out);
} }
+10 -11
View File
@@ -7,17 +7,16 @@ const Decompressor = @import("../../decomp.zig");
interface: Decompressor = .{ .vtable = &.{ .stateless = stateless } }, interface: Decompressor = .{ .vtable = &.{ .stateless = stateless } },
pub fn stateless(alloc: std.mem.Allocator, in: []u8, out: []u8) Decompressor.Error!usize { pub fn stateless(alloc: std.mem.Allocator, in: []u8, out: []u8) Decompressor.Error!usize {
var rdr: Reader = .static(in); var rdr: Reader = .fixed(in);
var decomp = try xz.decompress(alloc, rdr.adaptToOldInterface()); const buf = try alloc.alloc(u8, in.len);
defer decomp.deinit(); defer alloc.free(buf);
const len = decomp.read(out) catch |err| return switch (err) {
error.CorruptInput => Decompressor.Error.ReadFailed, var decomp = xz.Decompress.init(&rdr, alloc, buf) catch |err|
error.EndOfStream => Decompressor.Error.ReadFailed, return switch (err) {
error.EndOfStreamWithNoError => Decompressor.Error.ReadFailed,
error.WrongChecksum => Decompressor.Error.ReadFailed, error.WrongChecksum => Decompressor.Error.ReadFailed,
error.Unsupported => Decompressor.Error.ReadFailed, error.NotXzStream => Decompressor.Error.ReadFailed,
error.Overflow => Decompressor.Error.WriteFailed, else => @errorCast(err),
else => err,
}; };
return len; defer decomp.deinit();
return decomp.reader.readSliceShort(out);
} }
+2 -1
View File
@@ -7,9 +7,10 @@ const Decompressor = @import("../../decomp.zig");
interface: Decompressor = .{ .vtable = &.{ .stateless = stateless } }, interface: Decompressor = .{ .vtable = &.{ .stateless = stateless } },
pub fn stateless(alloc: std.mem.Allocator, in: []u8, out: []u8) Decompressor.Error!usize { pub fn stateless(alloc: std.mem.Allocator, in: []u8, out: []u8) Decompressor.Error!usize {
var rdr: Reader = .fixed(in);
const buf = try alloc.alloc(u8, out.len); const buf = try alloc.alloc(u8, out.len);
defer alloc.free(buf); defer alloc.free(buf);
var rdr: Reader = .static(in);
var decomp = flate.Decompress.init(&rdr, .zlib, buf); var decomp = flate.Decompress.init(&rdr, .zlib, buf);
return decomp.reader.readSliceShort(out); return decomp.reader.readSliceShort(out);
} }
+3 -2
View File
@@ -7,9 +7,10 @@ const Decompressor = @import("../../decomp.zig");
interface: Decompressor = .{ .vtable = &.{ .stateless = stateless } }, interface: Decompressor = .{ .vtable = &.{ .stateless = stateless } },
pub fn stateless(alloc: std.mem.Allocator, in: []u8, out: []u8) Decompressor.Error!usize { pub fn stateless(alloc: std.mem.Allocator, in: []u8, out: []u8) Decompressor.Error!usize {
var rdr: Reader = .fixed(in);
const buf = try alloc.alloc(u8, out.len * 2); const buf = try alloc.alloc(u8, out.len * 2);
defer alloc.free(buf); defer alloc.free(buf);
var rdr: Reader = .static(in);
var decomp = zstd.Decompress.init(&rdr, buf, .{ .window_len = out.len * 2 }); var decomp = zstd.Decompress.init(&rdr, buf, .{ .window_len = @truncate(out.len) });
return decomp.reader.readSliceShort(out); return decomp.reader.readSliceShort(out);
} }
+1
View File
@@ -1,4 +1,5 @@
const std = @import("std"); const std = @import("std");
const Io = std.Io;
const Archive = @import("archive.zig"); const Archive = @import("archive.zig");
const Decompressor = @import("decomp.zig"); const Decompressor = @import("decomp.zig");
+5
View File
@@ -0,0 +1,5 @@
#include <zlib-ng.h>
#include <lzo/minilzo.h>
#include <lz4.h>
#include <zstd.h>
#include <lzma.h>
+7 -6
View File
@@ -1,18 +1,19 @@
const std = @import("std"); const std = @import("std");
const FileReader = std.fs.File.Reader; const Io = std.Io;
const FileReader = Io.File.Reader;
const OffsetFile = @This(); const OffsetFile = @This();
fil: std.fs.File, fil: Io.File,
offset: u64 = 0, offset: u64 = 0,
pub fn readerAt(self: OffsetFile, offset: u64, buf: []u8) !FileReader { pub fn readerAt(self: OffsetFile, io: Io, offset: u64, buf: []u8) !FileReader {
var rdr = self.fil.reader(buf); var rdr = self.fil.reader(io, buf);
try rdr.seekTo(self.offset + offset); try rdr.seekTo(self.offset + offset);
return rdr; return rdr;
} }
pub fn valueAt(self: OffsetFile, comptime T: type, offset: u64) !T { pub fn valueAt(self: OffsetFile, comptime T: type, io: Io, offset: u64) !T {
var rdr = self.fil.reader(&[0]u8{}); var rdr = self.fil.reader(io, &[0]u8{});
try rdr.seekTo(self.offset + offset); try rdr.seekTo(self.offset + offset);
var new: T = undefined; var new: T = undefined;
try rdr.interface.readSliceEndian(T, @ptrCast(&new), .little); try rdr.interface.readSliceEndian(T, @ptrCast(&new), .little);