Working on re-doing decompression

This commit is contained in:
Caleb J. Gardner
2026-03-21 02:13:36 -05:00
parent df22cf6529
commit 54aaf30ea5
11 changed files with 213 additions and 238 deletions
+12 -9
View File
@@ -2,13 +2,13 @@ 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 false;
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");
const zig_squashfs_options = b.addOptions(); const zig_squashfs_options = b.addOptions();
zig_squashfs_options.addOption(bool, "use_zig_decomp", use_zig_decomp); zig_squashfs_options.addOption(bool, "use_zig_decomp", use_zig_decomp);
zig_squashfs_options.addOption(bool, "allow_lzo", allow_lzo); // zig_squashfs_options.addOption(bool, "allow_lzo", allow_lzo);
const target = b.standardTargetOptions(.{}); const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{}); const optimize = b.standardOptimizeOption(.{});
@@ -30,8 +30,12 @@ pub fn build(b: *std.Build) !void {
mod.linkLibrary(zlib_ng.artifact("zng")); mod.linkLibrary(zlib_ng.artifact("zng"));
mod.linkSystemLibrary("lzma", .{ .preferred_link_mode = .static }); mod.linkSystemLibrary("lzma", .{ .preferred_link_mode = .static });
if (allow_lzo == true)
mod.linkSystemLibrary("minilzo", .{ .preferred_link_mode = .static }); var minilzo = b.dependency("minilzo", .{
.target = target,
.optimize = optimize,
});
mod.linkLibrary(minilzo.artifact("minilzo"));
var lz4 = b.dependency("lz4", .{ var lz4 = b.dependency("lz4", .{
.target = target, .target = target,
@@ -85,15 +89,14 @@ pub fn build(b: *std.Build) !void {
const mod_tests = b.addTest(.{ const mod_tests = b.addTest(.{
.root_module = mod, .root_module = mod,
.test_runner = .{
.mode = .simple,
.path = b.path("src/test.zig"),
},
}); });
const run_mod_tests = b.addRunArtifact(mod_tests); const run_mod_tests = b.addRunArtifact(mod_tests);
const exe_tests = b.addTest(.{
.root_module = exe.root_module,
});
const run_exe_tests = b.addRunArtifact(exe_tests);
const test_step = b.step("test", "Run tests"); const test_step = b.step("test", "Run tests");
test_step.dependOn(&run_mod_tests.step); test_step.dependOn(&run_mod_tests.step);
test_step.dependOn(&run_exe_tests.step);
// zls build check steps // zls build check steps
const lib_check = b.addLibrary(.{ const lib_check = b.addLibrary(.{
+3
View File
@@ -16,6 +16,9 @@
.url = "git+https://github.com/allyourcodebase/lz4.git?ref=1.10.0-6#41f52ab227caf9d48cf88c89a4d2946caa12b102", .url = "git+https://github.com/allyourcodebase/lz4.git?ref=1.10.0-6#41f52ab227caf9d48cf88c89a4d2946caa12b102",
.hash = "lz4-1.10.0-6-ewyzw-4NAAAWDpY4xpiqr4LQhZQAC0x_rGnW2iPh6jk2", .hash = "lz4-1.10.0-6-ewyzw-4NAAAWDpY4xpiqr4LQhZQAC0x_rGnW2iPh6jk2",
}, },
.minilzo = .{
.path = "../zig-minilzo",
},
}, },
.paths = .{ .paths = .{
"build.zig", "build.zig",
+40 -16
View File
@@ -5,7 +5,10 @@ const std = @import("std");
const File = std.fs.File; const File = std.fs.File;
const builtin = @import("builtin"); const builtin = @import("builtin");
const Decomp = @import("decomp.zig"); const config = @import("config");
const cDecomp = @import("decomp/misc_c.zig");
const Decomp = @import("decomp/zig_decomp.zig");
const ExtractionOptions = @import("options.zig"); const ExtractionOptions = @import("options.zig");
const Inode = @import("inode.zig"); const Inode = @import("inode.zig");
const InodeRef = Inode.Ref; const InodeRef = Inode.Ref;
@@ -17,22 +20,35 @@ const MetadataReader = @import("util/metadata.zig");
const OffsetFile = @import("util/offset_file.zig"); const OffsetFile = @import("util/offset_file.zig");
const XattrTable = @import("xattr.zig"); const XattrTable = @import("xattr.zig");
const config = if (builtin.is_test) .{
.use_zig_decomp = !builtin.link_libc,
.allow_lzo = false,
} else @import("config");
const Archive = @This(); const Archive = @This();
alloc: std.mem.Allocator, alloc: std.mem.Allocator,
fil: OffsetFile, fil: OffsetFile,
decomp: Decomp.DecompFn,
super: Superblock, super: Superblock,
tables: ?Tables = null, tables: ?Tables = null,
decomp: if (config.use_zig_decomp) Decomp.DecompFn else union(enum) {
gzip: @import("decomp/gzip.zig"),
lzma: @import("decomp/lzma.zig"),
lzo: void,
xz: @import("decomp/lzma.zig"),
lz4: void,
zstd: @import("decomp/zstd.zig"),
pub fn decomp(self: @This(), in: []u8, out: []u8) !usize {
return switch (self) {
.gzip => |*g| g.decompress(in, out),
.zstd => |*z| z.decompress(in, out),
.lzma, .xz => |*d| d.decompress(in, out),
.lz4 => cDecomp.lz4(in, out),
.lzo => cDecomp.lzo(in, out),
};
}
},
/// Default settings using std.Thread.getCpuCount() threads and the minimum of 4gb or half of system memory for memory usage. /// Default settings using std.Thread.getCpuCount() threads and the minimum of 4gb or half of system memory for memory usage.
pub fn init(alloc: std.mem.Allocator, fil: File, offset: u64) !Archive { pub fn init(alloc: std.mem.Allocator, fil: File, offset: u64) !Archive {
var super: Superblock = undefined; var super: Superblock = undefined;
@@ -40,18 +56,26 @@ pub fn init(alloc: std.mem.Allocator, fil: File, offset: u64) !Archive {
std.debug.assert(red == @sizeOf(Superblock)); std.debug.assert(red == @sizeOf(Superblock));
try super.validate(); try super.validate();
const off_fil: OffsetFile = .init(fil, offset); const off_fil: OffsetFile = .init(fil, offset);
const decomp: Decomp.DecompFn = switch (super.compression) {
.gzip => Decomp.gzipDecompress,
.lzma => Decomp.lzmaDecompress,
.xz => Decomp.xzDecompress,
.zstd => Decomp.zstdDecompress,
.lz4 => if (!config.use_zig_decomp) Decomp.cLz4 else return error.Lz4Unsupported,
.lzo => if (!config.use_zig_decomp and config.allow_lzo) Decomp.lzoDecompress else return error.LzoUnsupported,
};
return .{ return .{
.alloc = alloc, .alloc = alloc,
.fil = off_fil, .fil = off_fil,
.decomp = decomp, .decomp = if (config.use_zig_decomp)
switch (super.compression) {
.lz4 => return error.Lz4Unsupported,
.lzo => return error.LzoUnsupported,
.gzip => Decomp.gzip,
.lzma => Decomp.lzma,
.xz => Decomp.xz,
.zstd => Decomp.zstd,
}
else switch (super.compression) {
.gzip => .{ .gzip = .init(alloc) },
.zstd => .{ .zstd = .init(alloc) },
.xz => .{ .xz = .init(alloc, true) },
.lzma => .{ .lzma = .init(alloc, false) },
.lzo => .{ .lzo = .{} },
.lz4 => .{ .lz4 = .{} },
},
.super = super, .super = super,
}; };
} }
-187
View File
@@ -1,187 +0,0 @@
//! Implementations for decompression.
//! TODO: change to vtable interface to allow for shared decompressors for better performance/resource usage.
const std = @import("std");
const Reader = std.Io.Reader;
const builtin = @import("builtin");
const config = if (builtin.is_test) .{
.use_zig_decomp = !builtin.link_libc,
.allow_lzo = false, // Change once LZO compilation is fixed
} else @import("config");
const c = @cImport({
@cInclude("zlib-ng.h");
@cInclude("lzma.h");
@cInclude("lz4.h");
@cInclude("zstd.h");
@cInclude("zstd_errors.h");
if (config.allow_lzo)
@cInclude("lzo/minilzo.h");
});
pub const CompressionType = enum(u16) {
gzip = 1,
lzma,
lzo,
xz,
lz4,
zstd,
};
pub const DecompFn = *const fn (alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize; // TODO: replace anyerror to definitive error types.
pub const gzipDecompress = if (!config.use_zig_decomp) cGzip else zigGzip;
fn zigGzip(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
var rdr: Reader = .fixed(in);
const buf = try alloc.alloc(u8, out.len);
defer alloc.free(buf);
var decomp = std.compress.flate.Decompress.init(&rdr, .zlib, buf);
return decomp.reader.readSliceShort(out);
}
fn cGzip(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
_ = alloc;
var out_len: usize = out.len;
const res = c.zng_uncompress(out.ptr, &out_len, in.ptr, in.len);
return switch (res) {
c.Z_OK => out_len,
c.Z_MEM_ERROR => error.NotEnoughMemory,
c.Z_BUF_ERROR => error.OutBufferTooSmall,
c.Z_DATA_ERROR => error.BadData,
else => error.UnknownResult,
};
}
pub const lzmaDecompress = if (!config.use_zig_decomp) cLzma else zigLzma;
fn zigLzma(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
var rdr: Reader = .fixed(in);
var decomp = try std.compress.lzma.decompress(alloc, rdr.adaptToOldInterface());
return decomp.read(out);
}
fn cLzma(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
_ = alloc;
var stream: c.lzma_stream = .{
.next_in = in.ptr,
.avail_in = in.len,
.next_out = out.ptr,
.avail_out = out.len,
};
var res = c.lzma_alone_decoder(&stream, in.len * 2);
switch (res) {
c.LZMA_OK => {},
c.LZMA_MEM_ERROR => return error.LzmaMemoryError,
c.LZMA_PROG_ERROR => return error.LzmaProgramError,
else => return error.UnknownResult,
}
defer c.lzma_end(&stream);
while (res == c.LZMA_OK)
res = c.lzma_code(&stream, c.LZMA_RUN);
return switch (res) {
c.LZMA_STREAM_END => stream.total_out,
c.LZMA_MEM_ERROR => error.LzmaMemoryError,
c.LZMA_MEMLIMIT_ERROR => error.LzmaMemoryLimit,
c.LZMA_FORMAT_ERROR => error.LzmaBadFormat,
c.LZMA_DATA_ERROR => error.LzmaDataCorrupt,
c.LZMA_BUF_ERROR => error.LzmaCannotProgress,
c.LZMA_PROG_ERROR => error.LzmaProgramError,
else => error.UnknownResult,
};
}
// pub const lzoDecompress = if (!config.use_zig_decomp) cLzo else zigLzo;
// fn zigLzo(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
// _ = alloc;
// _ = in;
// _ = out;
// return error.LzoUnsupported;
// }
pub fn cLzo(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
_ = alloc;
var res = c.lzo_init();
if (res != 0) return error.LzoInitFailed;
var out_len: usize = out.len;
res = c.lzo1x_decompress(in.ptr, in.len, out.ptr, &out_len, null);
return switch (res) {
c.LZO_E_OK => out_len,
c.LZO_E_ERROR => error.LzoError,
c.LZO_E_OUT_OF_MEMORY => error.LzoOutOfMemory,
c.LZO_E_NOT_COMPRESSIBLE => error.LzoNotCompressible,
c.LZO_E_INPUT_OVERRUN => error.LzoInputOverrun,
c.LZO_E_OUTPUT_OVERRUN => error.LzoOutputOverrun,
c.LZO_E_LOOKBEHIND_OVERRUN => error.LzoLookbehindOverrun,
c.LZO_E_EOF_NOT_FOUND => error.LzoEofNotFound,
c.LZO_E_INPUT_NOT_CONSUMED => error.LzoInputNotConsumed,
c.LZO_E_NOT_YET_IMPLEMENTED => error.LzoNotYetImplemented,
c.LZO_E_INVALID_ARGUMENT => error.LzoInvalidArgument,
c.LZO_E_INVALID_ALIGNMENT => error.LzoInvalidAlignment,
c.LZO_E_OUTPUT_NOT_CONSUMED => error.LzoOutputNotConsumed,
c.LZO_E_INTERNAL_ERROR => error.LzoInternalError,
else => error.UnknownResult,
};
}
pub const xzDecompress = if (!config.use_zig_decomp) cXz else zigXz;
fn zigXz(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
var rdr: Reader = .fixed(in);
var decomp = try std.compress.xz.decompress(alloc, rdr.adaptToOldInterface());
return decomp.read(out);
}
fn cXz(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
_ = alloc;
var stream: c.lzma_stream = .{
.next_in = in.ptr,
.avail_in = in.len,
.next_out = out.ptr,
.avail_out = out.len,
// .allocator = _, TODO: create a custom allocator based on alloc,
};
var res = c.lzma_stream_decoder(&stream, in.len * 2, 0);
switch (res) {
c.LZMA_OK => {},
c.LZMA_MEM_ERROR => return error.LzmaMemoryError,
c.LZMA_PROG_ERROR => return error.LzmaProgramError,
else => return error.UnknownResult,
}
defer c.lzma_end(&stream);
while (res == c.LZMA_OK)
res = c.lzma_code(&stream, c.LZMA_RUN);
return switch (res) {
c.LZMA_STREAM_END => stream.total_out,
c.LZMA_MEM_ERROR => error.LzmaMemoryError,
c.LZMA_MEMLIMIT_ERROR => error.LzmaMemoryLimit,
c.LZMA_FORMAT_ERROR => error.LzmaBadFormat,
c.LZMA_DATA_ERROR => error.LzmaDataCorrupt,
c.LZMA_BUF_ERROR => error.LzmaCannotProgress,
c.LZMA_PROG_ERROR => error.LzmaProgramError,
else => error.UnknownResult,
};
}
// pub const lz4Decompress = if (!config.use_zig_decomp) cLz4 else zigLz4;
// fn zigLz4(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
// _ = alloc;
// _ = in;
// _ = out;
// return error.Lz4Unsupported;
// }
pub fn cLz4(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
_ = alloc;
const res = c.LZ4_decompress_safe(in.ptr, out.ptr, @intCast(in.len), @intCast(out.len));
if (res > 0) return @abs(res); // TODO: Find out what error values it can return.
return error.Lz4DecompressFailed;
}
pub fn zigZstd(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
var rdr: Reader = .fixed(in);
const buf = try alloc.alloc(u8, 1024 * 1024);
defer alloc.free(buf);
var decomp = std.compress.zstd.Decompress.init(&rdr, buf, .{});
return decomp.reader.readSliceShort(out) catch |err| {
return decomp.err orelse err;
};
}
+1 -5
View File
@@ -2,10 +2,7 @@ const std = @import("std");
const Reader = std.Io.Reader; const Reader = std.Io.Reader;
const builtin = @import("builtin"); const builtin = @import("builtin");
const config = if (builtin.is_test) .{ const config = @import("config");
.use_zig_decomp = !builtin.link_libc,
.allow_lzo = false, // Change once LZO compilation is fixed
} else @import("config");
pub const c = @cImport({ pub const c = @cImport({
@cInclude("zlib-ng.h"); @cInclude("zlib-ng.h");
@@ -13,6 +10,5 @@ pub const c = @cImport({
@cInclude("lz4.h"); @cInclude("lz4.h");
@cInclude("zstd.h"); @cInclude("zstd.h");
@cInclude("zstd_errors.h"); @cInclude("zstd_errors.h");
if (config.allow_lzo)
@cInclude("lzo/minilzo.h"); @cInclude("lzo/minilzo.h");
}); });
+2 -17
View File
@@ -15,14 +15,12 @@ const ZlibErrors = error{
const Self = @This(); const Self = @This();
alloc: std.mem.Allocator, alloc: std.mem.Allocator,
window_size: i16,
streams: std.AutoHashMap(std.Thread.Id, zng_stream), streams: std.AutoHashMap(std.Thread.Id, zng_stream),
pub fn init(alloc: std.mem.Allocator, window_size: i16) !Self { pub fn init(alloc: std.mem.Allocator) !Self {
return .{ return .{
.alloc = alloc, .alloc = alloc,
.window_size = window_size,
.streams = .init(alloc), .streams = .init(alloc),
}; };
} }
@@ -40,7 +38,7 @@ pub fn decompress(self: *Self, in: []u8, out: []u8) ZlibErrors!usize {
stream.avail_in = in.len; stream.avail_in = in.len;
stream.next_out = out.ptr; stream.next_out = out.ptr;
stream.avail_out = out.len; stream.avail_out = out.len;
var res = c.zng_inflateReset2(stream, self.window_size); var res = c.zng_inflateReset(stream);
switch (res) { switch (res) {
c.Z_OK => {}, c.Z_OK => {},
c.Z_STREAM_ERROR => return ZlibErrors.StreamError, c.Z_STREAM_ERROR => return ZlibErrors.StreamError,
@@ -74,16 +72,3 @@ fn zfree(self_ptr: ?*anyopaque, alloc_ptr: ?*anyopaque) ?*anyopaque {
var self: *Self = @ptrCast(self_ptr); var self: *Self = @ptrCast(self_ptr);
self.alloc.rawFree(@ptrCast(alloc_ptr), .@"1", 0); self.alloc.rawFree(@ptrCast(alloc_ptr), .@"1", 0);
} }
pub fn stateless(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
_ = alloc;
var out_len: usize = out.len;
const res = c.zng_uncompress(out.ptr, &out_len, in.ptr, in.len);
return switch (res) {
c.Z_OK => out_len,
c.Z_MEM_ERROR => ZlibErrors.NotEnoughMemory,
c.Z_BUF_ERROR => ZlibErrors.OutputBufferTooSmall,
c.Z_DATA_ERROR => ZlibErrors.BadData,
else => ZlibErrors.Unknown,
};
}
+79
View File
@@ -0,0 +1,79 @@
const std = @import("std");
const builtin = @import("builtin");
const c = @import("c.zig").c;
const stream = c.lzma_stream;
const Self = @This();
alloc: std.mem.Allocator,
streams: std.AutoHashMap(std.Thread.Id, stream),
xz: bool,
pub fn init(alloc: std.mem.Allocator, xz: bool) !Self {
return .{
.alloc = alloc,
.streams = .init(alloc),
.xz = xz,
};
}
pub fn deinit(self: Self) void {
var iter = self.streams.keyIterator();
while (iter.next()) |key|
c.lzma_end(self.streams.getPtr(key));
self.streams.deinit();
}
pub fn decompress(self: *Self, in: []u8, out: []u8) LzmaError!usize {
var strm = try self.getOrCreate();
strm.next_in = in.ptr;
strm.avail_in = in.len;
strm.next_out = out.ptr;
strm.avail_out = out.len;
var res = if (self.xz)
c.lzma_stream_decoder(strm, in.len * 2, 0)
else
c.lzma_alone_decoder(strm, in.len * 2);
switch (res) {
c.LZMA_OK => {},
c.LZMA_MEM_ERROR => return LzmaError.LzmaMemoryError,
c.LZMA_PROG_ERROR => return LzmaError.LzmaProgramError,
else => return LzmaError.UnknownResult,
}
while (res == c.LZMA_OK)
res = c.lzma_code(strm, c.LZMA_RUN);
return switch (res) {
c.LZMA_STREAM_END => strm.total_out,
c.LZMA_MEM_ERROR => LzmaError.LzmaMemoryError,
c.LZMA_MEMLIMIT_ERROR => LzmaError.LzmaMemoryLimit,
c.LZMA_FORMAT_ERROR => LzmaError.LzmaBadFormat,
c.LZMA_DATA_ERROR => LzmaError.LzmaDataCorrupt,
c.LZMA_BUF_ERROR => LzmaError.LzmaCannotProgress,
c.LZMA_PROG_ERROR => LzmaError.LzmaProgramError,
else => LzmaError.UnknownResult,
};
}
inline fn getOrCreate(self: *Self) LzmaError!*stream {
const res = try self.streams.getOrPut(std.Thread.getCurrentId());
if (res.found_existing) return res.value_ptr;
// Ideally, the zero value should be LZMA_STREAM_INIT, but translate-c can't handle it properly.
// According to lzma, setting it to entirely zero values *should* work.
// res.value_ptr.* = c.LZMA_STREAM_INIT;
res.value_ptr.* = std.mem.zeroInit(stream, .{});
return res.value_ptr;
}
pub const LzmaError = error{
OutOfMemory,
LzmaMemoryError,
LzmaMemoryLimit,
LzmaBadFormat,
LzmaDataCorrupt,
LzmaCannotProgress,
LzmaProgramError,
Unknown,
};
+32
View File
@@ -0,0 +1,32 @@
const c = @import("c.zig").c;
pub fn lzo(in: []u8, out: []u8) anyerror!usize {
var res = c.lzo_init();
if (res != 0) return error.LzoInitFailed;
var out_len: usize = out.len;
res = c.lzo1x_decompress(in.ptr, in.len, out.ptr, &out_len, null);
return switch (res) {
c.LZO_E_OK => out_len,
c.LZO_E_ERROR => error.LzoError,
c.LZO_E_OUT_OF_MEMORY => error.LzoOutOfMemory,
c.LZO_E_NOT_COMPRESSIBLE => error.LzoNotCompressible,
c.LZO_E_INPUT_OVERRUN => error.LzoInputOverrun,
c.LZO_E_OUTPUT_OVERRUN => error.LzoOutputOverrun,
c.LZO_E_LOOKBEHIND_OVERRUN => error.LzoLookbehindOverrun,
c.LZO_E_EOF_NOT_FOUND => error.LzoEofNotFound,
c.LZO_E_INPUT_NOT_CONSUMED => error.LzoInputNotConsumed,
c.LZO_E_NOT_YET_IMPLEMENTED => error.LzoNotYetImplemented,
c.LZO_E_INVALID_ARGUMENT => error.LzoInvalidArgument,
c.LZO_E_INVALID_ALIGNMENT => error.LzoInvalidAlignment,
c.LZO_E_OUTPUT_NOT_CONSUMED => error.LzoOutputNotConsumed,
c.LZO_E_INTERNAL_ERROR => error.LzoInternalError,
else => error.UnknownResult,
};
}
pub fn lz4(in: []u8, out: []u8) anyerror!usize {
const res = c.LZ4_decompress_safe(in.ptr, out.ptr, @intCast(in.len), @intCast(out.len));
if (res > 0) return @abs(res); // TODO: Find out what error values it can return.
return error.Lz4DecompressFailed;
}
+35
View File
@@ -0,0 +1,35 @@
const std = @import("std");
const Reader = std.Io.Reader;
const builtin = @import("builtin");
pub const DecompFn = *const fn (alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize; // TODO: replace anyerror to definitive error types.
pub fn gzip(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
var rdr: Reader = .fixed(in);
const buf = try alloc.alloc(u8, out.len);
defer alloc.free(buf);
var decomp = std.compress.flate.Decompress.init(&rdr, .zlib, buf);
return decomp.reader.readSliceShort(out);
}
pub fn lzma(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
var rdr: Reader = .fixed(in);
var decomp = try std.compress.lzma.decompress(alloc, rdr.adaptToOldInterface());
return decomp.read(out);
}
pub fn xz(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
var rdr: Reader = .fixed(in);
var decomp = try std.compress.xz.decompress(alloc, rdr.adaptToOldInterface());
return decomp.read(out);
}
pub fn zstd(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
var rdr: Reader = .fixed(in);
const buf = try alloc.alloc(u8, 1024 * 1024);
defer alloc.free(buf);
var decomp = std.compress.zstd.Decompress.init(&rdr, buf, .{});
return decomp.reader.readSliceShort(out) catch |err| {
return decomp.err orelse err;
};
}
+8 -2
View File
@@ -1,7 +1,6 @@
const std = @import("std"); const std = @import("std");
const math = std.math; const math = std.math;
const CompressionType = @import("decomp.zig").CompressionType;
const InodeRef = @import("inode.zig").Ref; const InodeRef = @import("inode.zig").Ref;
const SQUASHFS_MAGIC: u32 = std.mem.readInt(u32, "hsqs", .little); const SQUASHFS_MAGIC: u32 = std.mem.readInt(u32, "hsqs", .little);
@@ -20,7 +19,14 @@ pub const Superblock = packed struct {
mod_time: u32, mod_time: u32,
block_size: u32, block_size: u32,
frag_count: u32, frag_count: u32,
compression: CompressionType, compression: enum(u16) {
gzip = 1,
lzma,
lzo,
xz,
lz4,
zstd,
},
block_log: u16, block_log: u16,
flags: packed struct { flags: packed struct {
inode_uncompressed: bool, inode_uncompressed: bool,
-1
View File
@@ -2,7 +2,6 @@ const std = @import("std");
const Mutex = std.Thread.Mutex; const Mutex = std.Thread.Mutex;
const Archive = @import("archive.zig"); const Archive = @import("archive.zig");
const DecompFn = @import("decomp.zig").DecompFn;
const BlockSize = @import("inode_data/file.zig").BlockSize; const BlockSize = @import("inode_data/file.zig").BlockSize;
const InodeRef = @import("inode.zig").Ref; const InodeRef = @import("inode.zig").Ref;
const Superblock = @import("super.zig").Superblock; const Superblock = @import("super.zig").Superblock;