You can now set when building to use c or zig libraries.
This commit is contained in:
@@ -1,29 +1,44 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const static = b.option(bool, "static_build", "Build static");
|
||||
pub fn build(b: *std.Build) !void {
|
||||
const static_option = b.option(bool, "static_build", "Build static");
|
||||
const use_c_libs_option = b.option(bool, "use_c_libs", "Use C versions of decompression libraries instead of the Zig standard library ones");
|
||||
const version_string_option = b.option([]const u8, "version", "Version of the library/binary");
|
||||
|
||||
const zig_squashfs_options = b.addOptions();
|
||||
zig_squashfs_options.addOption(bool, "use_c_libs", use_c_libs_option orelse false);
|
||||
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{ .preferred_optimize_mode = .ReleaseFast });
|
||||
const linkage: std.builtin.LinkMode = .static; // TODO: Add argument to set link mode.
|
||||
const use_c_libs: bool = false;
|
||||
_ = use_c_libs;
|
||||
const mod = b.addModule("zig_squashfs", .{
|
||||
.root_source_file = b.path("src/root.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.link_libc = if (use_c_libs_option == true) true else false,
|
||||
});
|
||||
mod.addOptions("config", zig_squashfs_options);
|
||||
if (use_c_libs_option == true)
|
||||
mod.linkSystemLibrary("zstd", .{});
|
||||
|
||||
const unsquashfs_options = b.addOptions();
|
||||
unsquashfs_options.addOption(std.SemanticVersion, "version_string", try std.SemanticVersion.parse(version_string_option orelse "0.0.0-testing"));
|
||||
|
||||
var exe_mod = b.createModule(.{
|
||||
.root_source_file = b.path("src/bin/unsquashfs.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.link_libc = if (use_c_libs_option == true) true else false,
|
||||
.imports = &.{
|
||||
.{ .name = "zig_squashfs", .module = mod },
|
||||
},
|
||||
});
|
||||
exe_mod.addOptions("config", unsquashfs_options);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "unsquashfs",
|
||||
.linkage = linkage,
|
||||
.root_module = b.createModule(.{
|
||||
.root_source_file = b.path("src/bin/unsquashfs.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.imports = &.{
|
||||
.{ .name = "zig_squashfs", .module = mod },
|
||||
},
|
||||
}),
|
||||
.linkage = if (static_option == true) .static else .dynamic,
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
|
||||
b.installArtifact(exe);
|
||||
const run_step = b.step("run", "Run the app");
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
|
||||
+15
-1
@@ -1,6 +1,7 @@
|
||||
const std = @import("std");
|
||||
const Writer = std.Io.Writer;
|
||||
|
||||
const config = @import("config");
|
||||
const squashfs = @import("zig_squashfs");
|
||||
|
||||
//TODO: Add more options
|
||||
@@ -8,8 +9,11 @@ const help_mgs =
|
||||
\\Usage: unsquashfs [options] <archive>
|
||||
\\
|
||||
\\Options:
|
||||
\\ -o <offset> Start reading the archive at the given offset.
|
||||
\\ -d <location> Extract to the given location instead of "squashfs-root"
|
||||
\\
|
||||
\\ -o <offset> Start reading the archive at the given offset.
|
||||
\\
|
||||
\\ --version Display the version
|
||||
;
|
||||
|
||||
const errors = error{InvalidArguments};
|
||||
@@ -24,6 +28,10 @@ pub fn main() !void {
|
||||
var out = stdout.writer(&[0]u8{});
|
||||
defer out.interface.flush() catch {};
|
||||
try handleArgs(alloc, &out.interface);
|
||||
if (archive.len == 0) {
|
||||
try out.interface.print("You must provide a squashfs archive\n", .{});
|
||||
return;
|
||||
}
|
||||
var fil: std.fs.File = try std.fs.cwd().openFile(archive, .{}); //TODO: Handle error gracefully.
|
||||
defer fil.close();
|
||||
var arc: squashfs.Archive = try .initAdvanced(alloc, fil, offset, try std.Thread.getCpuCount(), 0); //TODO: Update when memory size matters. //TODO: Handle error gracefully.
|
||||
@@ -55,6 +63,12 @@ fn handleArgs(alloc: std.mem.Allocator, out: *Writer) !void {
|
||||
}
|
||||
extLoc = nxt.?;
|
||||
continue;
|
||||
} else if (std.mem.eql(u8, arg, "--version")) {
|
||||
_ = try out.write("v");
|
||||
try config.version_string.format(out);
|
||||
_ = try out.write("\n");
|
||||
std.process.cleanExit();
|
||||
return;
|
||||
}
|
||||
if (archive.len > 0) {
|
||||
try out.print("you can only provide one file at a time\n", .{});
|
||||
|
||||
+118
-8
@@ -1,6 +1,15 @@
|
||||
//! 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 config = @import("config");
|
||||
|
||||
const c = @cImport({
|
||||
@cInclude("zstd.h");
|
||||
});
|
||||
|
||||
pub const CompressionType = enum(u16) {
|
||||
gzip = 1,
|
||||
lzma,
|
||||
@@ -12,32 +21,53 @@ pub const CompressionType = enum(u16) {
|
||||
|
||||
pub const DecompFn = *const fn (alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize; // TODO: replace anyerror to definitive error types.
|
||||
|
||||
// pub const DecompressError = error{
|
||||
// ReadFailed,
|
||||
// anyerror,
|
||||
// };
|
||||
pub const gzipDecompress = if (config.use_c_libs) cGzip else zigGzip;
|
||||
|
||||
pub fn gzipDecompress(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
|
||||
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;
|
||||
_ = in;
|
||||
_ = out;
|
||||
return error.TODO;
|
||||
}
|
||||
|
||||
pub fn lzmaDecompress(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
|
||||
pub const lzmaDecompress = if (config.use_c_libs) 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;
|
||||
_ = in;
|
||||
_ = out;
|
||||
return error.TODO;
|
||||
}
|
||||
|
||||
pub fn xzDecompress(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
|
||||
pub const xzDecompress = if (config.use_c_libs) 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;
|
||||
_ = in;
|
||||
_ = out;
|
||||
return error.TODO;
|
||||
}
|
||||
|
||||
pub fn zstdDecompress(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
|
||||
pub const zstdDecompress = if (config.use_c_libs) cZstd else zigZstd;
|
||||
|
||||
pub fn zigZstd(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
|
||||
var rdr: Reader = .fixed(in);
|
||||
const buf = try alloc.alloc(u8, std.compress.zstd.default_window_len + std.compress.zstd.block_size_max);
|
||||
defer alloc.free(buf);
|
||||
@@ -46,3 +76,83 @@ pub fn zstdDecompress(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!us
|
||||
return decomp.err orelse err;
|
||||
};
|
||||
}
|
||||
fn cZstd(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
|
||||
_ = alloc;
|
||||
const res = c.ZSTD_decompress(out.ptr, out.len, in.ptr, in.len);
|
||||
if (c.ZSTD_isError(res) == 0) return res;
|
||||
return switch (c.ZSTD_getErrorCode(res)) {
|
||||
c.ZSTD_error_prefix_unknown => cZstdError.PrefixUnknown,
|
||||
c.ZSTD_error_version_unsupported => cZstdError.VersionUnsupported,
|
||||
c.ZSTD_error_frameParameter_unsupported => cZstdError.FrameParameterUnsupported,
|
||||
c.ZSTD_error_frameParameter_windowTooLarge => cZstdError.FrameParameterWindowTooLarge,
|
||||
c.ZSTD_error_corruption_detected => cZstdError.CorruptionDetected,
|
||||
c.ZSTD_error_checksum_wrong => cZstdError.ChecksumWrong,
|
||||
c.ZSTD_error_literals_headerWrong => cZstdError.LiteralsHeaderWrong,
|
||||
c.ZSTD_error_dictionary_corrupted => cZstdError.DictionaryCorrupted,
|
||||
c.ZSTD_error_dictionary_wrong => cZstdError.DictionaryWrong,
|
||||
c.ZSTD_error_dictionaryCreation_failed => cZstdError.DictionaryCreationFailed,
|
||||
c.ZSTD_error_parameter_unsupported => cZstdError.ParameterUnsupported,
|
||||
c.ZSTD_error_parameter_combination_unsupported => cZstdError.ParameterCombinationUnsupported,
|
||||
c.ZSTD_error_parameter_outOfBound => cZstdError.ParameterOutOfBound,
|
||||
c.ZSTD_error_tableLog_tooLarge => cZstdError.TableLogTooLarge,
|
||||
c.ZSTD_error_maxSymbolValue_tooLarge => cZstdError.MaxSymbolValueTooLarge,
|
||||
c.ZSTD_error_maxSymbolValue_tooSmall => cZstdError.MaxSymbolValueTooSmall,
|
||||
c.ZSTD_error_cannotProduce_uncompressedBlock => cZstdError.CannotProduceUncompressedBlock,
|
||||
c.ZSTD_error_stabilityCondition_notRespected => cZstdError.StabilityConditionNotRespected,
|
||||
c.ZSTD_error_stage_wrong => cZstdError.StageWrong,
|
||||
c.ZSTD_error_init_missing => cZstdError.InitMissing,
|
||||
c.ZSTD_error_memory_allocation => cZstdError.MemoryAllocation,
|
||||
c.ZSTD_error_workSpace_tooSmall => cZstdError.WorkSpaceTooSmall,
|
||||
c.ZSTD_error_dstSize_tooSmall => cZstdError.DstSizeTooSmall,
|
||||
c.ZSTD_error_srcSize_wrong => cZstdError.SrcSizeWrong,
|
||||
c.ZSTD_error_dstBuffer_null => cZstdError.DstBufferNull,
|
||||
c.ZSTD_error_noForwardProgress_destFull => cZstdError.NoForwardProgressDestFull,
|
||||
c.ZSTD_error_noForwardProgress_inputEmpty => cZstdError.NoForwardProgressInputEmpty,
|
||||
c.ZSTD_error_frameIndex_tooLarge => cZstdError.FrameIndexTooLarge,
|
||||
c.ZSTD_error_seekableIO => cZstdError.SeekableIo,
|
||||
c.ZSTD_error_dstBuffer_wrong => cZstdError.DstBufferWrong,
|
||||
c.ZSTD_error_srcBuffer_wrong => cZstdError.SrcBufferWrong,
|
||||
c.ZSTD_error_sequenceProducer_failed => cZstdError.SequenceProducerFailed,
|
||||
c.ZSTD_error_externalSequences_invalid => cZstdError.ExternalSequencesInvalid,
|
||||
c.ZSTD_error_maxCode => cZstdError.MaxCode,
|
||||
else => cZstdError.Generic,
|
||||
};
|
||||
}
|
||||
|
||||
pub const cZstdError = error{
|
||||
Generic,
|
||||
PrefixUnknown,
|
||||
VersionUnsupported,
|
||||
FrameParameterUnsupported,
|
||||
FrameParameterWindowTooLarge,
|
||||
CorruptionDetected,
|
||||
ChecksumWrong,
|
||||
LiteralsHeaderWrong,
|
||||
DictionaryCorrupted,
|
||||
DictionaryWrong,
|
||||
DictionaryCreationFailed,
|
||||
ParameterUnsupported,
|
||||
ParameterCombinationUnsupported,
|
||||
ParameterOutOfBound,
|
||||
TableLogTooLarge,
|
||||
MaxSymbolValueTooLarge,
|
||||
MaxSymbolValueTooSmall,
|
||||
CannotProduceUncompressedBlock,
|
||||
StabilityConditionNotRespected,
|
||||
StageWrong,
|
||||
InitMissing,
|
||||
MemoryAllocation,
|
||||
WorkSpaceTooSmall,
|
||||
DstSizeTooSmall,
|
||||
SrcSizeWrong,
|
||||
DstBufferNull,
|
||||
NoForwardProgressDestFull,
|
||||
NoForwardProgressInputEmpty,
|
||||
FrameIndexTooLarge,
|
||||
SeekableIo,
|
||||
DstBufferWrong,
|
||||
SrcBufferWrong,
|
||||
SequenceProducerFailed,
|
||||
ExternalSequencesInvalid,
|
||||
MaxCode,
|
||||
};
|
||||
|
||||
+2
-2
@@ -92,10 +92,10 @@ fn advance(self: *DataReader) !void {
|
||||
const tmp_buf = try self.alloc.alloc(u8, self.frag.?.size.size);
|
||||
defer self.alloc.free(tmp_buf);
|
||||
try rdr.interface.readSliceAll(tmp_buf);
|
||||
const needed_block = try self.alloc.alloc(u8, self.frag_offset + cur_block_size);
|
||||
const needed_block = try self.alloc.alloc(u8, self.block_size);
|
||||
defer self.alloc.free(needed_block);
|
||||
_ = try self.decomp(self.alloc, tmp_buf, needed_block);
|
||||
@memcpy(self.interface.buffer, needed_block[self.frag_offset..]);
|
||||
@memcpy(self.interface.buffer, needed_block[self.frag_offset .. self.frag_offset + cur_block_size]);
|
||||
return;
|
||||
}
|
||||
const block = self.blocks[self.block_idx];
|
||||
|
||||
Reference in New Issue
Block a user