Fixed a couple decompressor issues.
Re-added ExtractionOptions
This commit is contained in:
+18
-8
@@ -3,13 +3,22 @@ const std = @import("std");
|
||||
const DecompTypes = @import("decomp/types.zig");
|
||||
const Decompressor = @import("decomp.zig");
|
||||
const Inode = @import("inode.zig");
|
||||
const ExtractionOptions = @import("options.zig");
|
||||
|
||||
pub const Error = error{
|
||||
BadMagic,
|
||||
BadBlockLog,
|
||||
BadVersion,
|
||||
BadCheck,
|
||||
};
|
||||
|
||||
const Archive = @This();
|
||||
|
||||
super: Superblock,
|
||||
|
||||
stateless_decomp: Decompressor.StatelessDecomp,
|
||||
stateless_decomp: Decompressor,
|
||||
|
||||
/// Create an Archive from a File.
|
||||
pub fn init(fil: std.fs.File, offset: u64) !Archive {
|
||||
var super: Superblock = undefined;
|
||||
var fil_rdr = fil.reader(&[0]u8{});
|
||||
@@ -20,16 +29,17 @@ pub fn init(fil: std.fs.File, offset: u64) !Archive {
|
||||
|
||||
return .{
|
||||
.super = super,
|
||||
.stateless_decomp = DecompTypes.getStatelessFn(super.compression),
|
||||
.stateless_decomp = .{ .vtable = &.{ .stateless = try DecompTypes.getStatelessFn(super.compression) } },
|
||||
};
|
||||
}
|
||||
|
||||
pub const Error = error{
|
||||
BadMagic,
|
||||
BadBlockLog,
|
||||
BadVersion,
|
||||
BadCheck,
|
||||
};
|
||||
pub fn extract(self: Archive, alloc: std.mem.Allocator, path: []const u8, options: ExtractionOptions) !void{
|
||||
_ = self;
|
||||
_ = alloc;
|
||||
_ = path;
|
||||
_ = options;
|
||||
return error.TODO;
|
||||
}
|
||||
|
||||
// Superblock
|
||||
|
||||
|
||||
+11
-12
@@ -51,18 +51,17 @@ pub fn main() !void {
|
||||
}
|
||||
var fil: std.fs.File = try std.fs.cwd().openFile(archive, .{}); //TODO: Handle error gracefully.
|
||||
defer fil.close();
|
||||
// var arc: squashfs.Archive = try .init(fil, offset); //TODO: Update when memory size matters. //TODO: Handle error gracefully.
|
||||
// defer arc.deinit();
|
||||
// const options: squashfs.ExtractionOptions = .{
|
||||
// .threads = if (threads == 0) try std.Thread.getCpuCount() else threads,
|
||||
// .verbose = verbose,
|
||||
// .verbose_writer = if (verbose) &out.interface else null,
|
||||
// .ignore_xattr = ignore_xattrs,
|
||||
// .ignore_permissions = ignore_permissions,
|
||||
// };
|
||||
// if (force)
|
||||
// try std.fs.cwd().deleteTree(extLoc);
|
||||
// try arc.extract(alloc, extLoc, options); //TODO: Handle error gracefully.
|
||||
var arc: squashfs.Archive = try .init(fil, offset); //TODO: Handle error gracefully.
|
||||
const options: squashfs.ExtractionOptions = .{
|
||||
.threads = if (threads == 0) try std.Thread.getCpuCount() else threads,
|
||||
.verbose = verbose,
|
||||
.verbose_writer = if (verbose) &out.interface else null,
|
||||
.ignore_xattr = ignore_xattrs,
|
||||
.ignore_permissions = ignore_permissions,
|
||||
};
|
||||
if (force)
|
||||
try std.fs.cwd().deleteTree(extLoc);
|
||||
try arc.extract(alloc, extLoc, options); //TODO: Handle error gracefully.
|
||||
}
|
||||
|
||||
fn handleArgs(alloc: std.mem.Allocator, out: *Writer) !void {
|
||||
|
||||
+2
-5
@@ -11,8 +11,8 @@ pub const Error = error{
|
||||
|
||||
const Decompressor = @This();
|
||||
|
||||
alloc: std.mem.Allocator = std.heap.page_allocator,
|
||||
vtable: *struct {
|
||||
alloc: std.mem.Allocator = std.heap.smp_allocator,
|
||||
vtable: *const struct {
|
||||
decompress: *const fn (*const Decompressor, in: []u8, out: []u8) Error!usize = defaultDecompress,
|
||||
stateless: StatelessDecomp,
|
||||
},
|
||||
@@ -20,9 +20,6 @@ vtable: *struct {
|
||||
pub fn decompress(self: *const Decompressor, in: []u8, out: []u8) Error!usize {
|
||||
return self.vtable.decompress(self, in, out);
|
||||
}
|
||||
pub fn stateless(self: Decompressor, alloc: std.mem.Allocator, in: []u8, out: []u8) Error!usize {
|
||||
return self.vtable.stateless(alloc, in, out);
|
||||
}
|
||||
|
||||
fn defaultDecompress(self: *const Decompressor, in: []u8, out: []u8) Error!usize {
|
||||
return self.vtable.stateless(self.alloc, in, out);
|
||||
|
||||
@@ -3,10 +3,10 @@ const std = @import("std");
|
||||
const c = @import("../../c_libs.zig").c;
|
||||
const Decompressor = @import("../../decomp.zig");
|
||||
|
||||
interface: Decompressor = .{ .vtable = .{ .stateless = stateless } },
|
||||
interface: Decompressor = .{ .vtable = &.{ .stateless = stateless } },
|
||||
|
||||
pub fn stateless(_: std.mem.Allocator, in: []u8, out: []u8) Decompressor.Error!usize {
|
||||
const res = c.LZ4_decompress_safe(in.ptr, out.ptr, in.len, out.len);
|
||||
const res = c.LZ4_decompress_safe(in.ptr, out.ptr, @intCast(in.len), @intCast(out.len));
|
||||
if (res > 0) return @abs(res);
|
||||
return Decompressor.Error.ReadFailed; // TOOD: Find out what errors can be returned.
|
||||
}
|
||||
|
||||
+12
-12
@@ -49,10 +49,10 @@ fn decompress(decomp: *const Decompressor, in: []u8, out: []u8) Decompressor.Err
|
||||
stream.avail_in = in.len;
|
||||
stream.next_out = out.ptr;
|
||||
stream.avail_out = out.len;
|
||||
var res = c.lzma_alone_decoder(stream, out.len, 0);
|
||||
var res = c.lzma_alone_decoder(stream, out.len);
|
||||
decodeResult(res) catch |err| {
|
||||
self.err = err;
|
||||
lzmaErrorToDecompError(err);
|
||||
return lzmaErrorToDecompError(err);
|
||||
};
|
||||
while (true) {
|
||||
res = c.lzma_code(&stream, c.LZMA_RUN);
|
||||
@@ -60,7 +60,7 @@ fn decompress(decomp: *const Decompressor, in: []u8, out: []u8) Decompressor.Err
|
||||
if (res == c.LZMA_STREAM_END) break;
|
||||
decodeResult(res) catch |err| {
|
||||
self.err = err;
|
||||
lzmaErrorToDecompError(err);
|
||||
return lzmaErrorToDecompError(err);
|
||||
};
|
||||
}
|
||||
return stream.total_out;
|
||||
@@ -71,19 +71,19 @@ pub fn stateless(alloc: std.mem.Allocator, in: []u8, out: []u8) Decompressor.Err
|
||||
.avail_in = in.len,
|
||||
.next_out = out.ptr,
|
||||
.avail_out = out.len,
|
||||
.allocator = .{
|
||||
.allocator = &.{
|
||||
.alloc = lzmaAlloc,
|
||||
.free = lzmaFree,
|
||||
.@"opaque" = &alloc,
|
||||
.@"opaque" = @ptrCast(@constCast(&alloc)),
|
||||
},
|
||||
};
|
||||
var res = c.lzma_alone_decoder(&stream, out.len, 0);
|
||||
decodeResult(res) catch |err| lzmaErrorToDecompError(err);
|
||||
var res = c.lzma_alone_decoder(&stream, out.len);
|
||||
decodeResult(res) catch |err| return lzmaErrorToDecompError(err);
|
||||
while (true) {
|
||||
res = c.lzma_code(&stream, c.LZMA_RUN);
|
||||
if (res == c.LZMA_OK) continue;
|
||||
if (res == c.LZMA_STREAM_END) break;
|
||||
decodeResult(res) catch |err| lzmaErrorToDecompError(err);
|
||||
decodeResult(res) catch |err| return lzmaErrorToDecompError(err);
|
||||
}
|
||||
return stream.total_out;
|
||||
}
|
||||
@@ -107,7 +107,7 @@ inline fn decodeResult(res: c_uint) Error!void {
|
||||
}
|
||||
fn lzmaErrorToDecompError(err: Error) Decompressor.Error {
|
||||
switch (err) {
|
||||
Error.OutOfMemory => return err,
|
||||
Error.OutOfMemory => return Decompressor.Error.OutOfMemory,
|
||||
Error.UnsupportedCheck => return Decompressor.Error.ReadFailed,
|
||||
Error.Format => return Decompressor.Error.ReadFailed,
|
||||
Error.Options => return Decompressor.Error.ReadFailed,
|
||||
@@ -120,12 +120,12 @@ fn lzmaErrorToDecompError(err: Error) Decompressor.Error {
|
||||
}
|
||||
|
||||
fn lzmaAlloc(ptr: ?*anyopaque, _: usize, size: usize) callconv(.c) ?*anyopaque {
|
||||
var alloc: *std.mem.Allocator = @ptrCast(ptr);
|
||||
return alloc.rawAlloc(size, .@"1", 0) catch return null;
|
||||
var alloc: *std.mem.Allocator = @alignCast(@ptrCast(ptr));
|
||||
return alloc.rawAlloc(size, .@"1", 0);
|
||||
}
|
||||
fn lzmaFree(ptr: ?*anyopaque, alloc_ptr: ?*anyopaque) callconv(.c) void {
|
||||
if (alloc_ptr == null) return;
|
||||
var alloc: *std.mem.Allocator = @ptrCast(ptr);
|
||||
var alloc: *std.mem.Allocator = @alignCast(@ptrCast(ptr));
|
||||
alloc.rawFree(@ptrCast(alloc_ptr), .@"1", 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ const std = @import("std");
|
||||
const c = @import("../../c_libs.zig").c;
|
||||
const Decompressor = @import("../../decomp.zig");
|
||||
|
||||
interface: Decompressor = .{ .vtable = .{ .stateless = stateless } },
|
||||
interface: Decompressor = .{ .vtable = &.{ .stateless = stateless } },
|
||||
|
||||
pub fn stateless(_: std.mem.Allocator, in: []u8, out: []u8) Decompressor.Error!usize {
|
||||
var out_len = out.len;
|
||||
|
||||
+14
-14
@@ -23,12 +23,12 @@ pub fn init(alloc: std.mem.Allocator) !Xz {
|
||||
pub fn deinit(self: *Xz) void {
|
||||
var values = self.streams.valueIterator();
|
||||
while (values.next()) |val| {
|
||||
c.lzma_end(val);
|
||||
c.xz_end(val);
|
||||
}
|
||||
self.streams.deinit();
|
||||
}
|
||||
|
||||
fn getOrCreate(self: *Xz) !*c.lzma_stream {
|
||||
fn getOrCreate(self: *Xz) !*c.xz_stream {
|
||||
const res = try self.streams.getOrPut(std.Thread.getCurrentId());
|
||||
if (res.found_existing) return res.value_ptr;
|
||||
res.value_ptr.* = .{
|
||||
@@ -49,10 +49,10 @@ fn decompress(decomp: *const Decompressor, in: []u8, out: []u8) Decompressor.Err
|
||||
stream.avail_in = in.len;
|
||||
stream.next_out = out.ptr;
|
||||
stream.avail_out = out.len;
|
||||
var res = c.lzma_stream_decoder(stream, out.len, 0);
|
||||
var res = c.lzma_alone_decoder(stream, out.len);
|
||||
decodeResult(res) catch |err| {
|
||||
self.err = err;
|
||||
xzErrorToDecompError(err);
|
||||
return xzErrorToDecompError(err);
|
||||
};
|
||||
while (true) {
|
||||
res = c.lzma_code(&stream, c.LZMA_RUN);
|
||||
@@ -60,7 +60,7 @@ fn decompress(decomp: *const Decompressor, in: []u8, out: []u8) Decompressor.Err
|
||||
if (res == c.LZMA_STREAM_END) break;
|
||||
decodeResult(res) catch |err| {
|
||||
self.err = err;
|
||||
xzErrorToDecompError(err);
|
||||
return xzErrorToDecompError(err);
|
||||
};
|
||||
}
|
||||
return stream.total_out;
|
||||
@@ -71,19 +71,19 @@ pub fn stateless(alloc: std.mem.Allocator, in: []u8, out: []u8) Decompressor.Err
|
||||
.avail_in = in.len,
|
||||
.next_out = out.ptr,
|
||||
.avail_out = out.len,
|
||||
.allocator = .{
|
||||
.allocator = &.{
|
||||
.alloc = lzmaAlloc,
|
||||
.free = lzmaFree,
|
||||
.@"opaque" = &alloc,
|
||||
.@"opaque" = @ptrCast(@constCast(&alloc)),
|
||||
},
|
||||
};
|
||||
var res = c.lzma_stream_decoder(&stream, out.len, 0);
|
||||
decodeResult(res) catch |err| xzErrorToDecompError(err);
|
||||
var res = c.lzma_alone_decoder(&stream, out.len);
|
||||
decodeResult(res) catch |err| return xzErrorToDecompError(err);
|
||||
while (true) {
|
||||
res = c.lzma_code(&stream, c.LZMA_RUN);
|
||||
if (res == c.LZMA_OK) continue;
|
||||
if (res == c.LZMA_STREAM_END) break;
|
||||
decodeResult(res) catch |err| xzErrorToDecompError(err);
|
||||
decodeResult(res) catch |err| return xzErrorToDecompError(err);
|
||||
}
|
||||
return stream.total_out;
|
||||
}
|
||||
@@ -107,7 +107,7 @@ inline fn decodeResult(res: c_uint) Error!void {
|
||||
}
|
||||
fn xzErrorToDecompError(err: Error) Decompressor.Error {
|
||||
switch (err) {
|
||||
Error.OutOfMemory => return err,
|
||||
Error.OutOfMemory => return Decompressor.Error.OutOfMemory,
|
||||
Error.UnsupportedCheck => return Decompressor.Error.ReadFailed,
|
||||
Error.Format => return Decompressor.Error.ReadFailed,
|
||||
Error.Options => return Decompressor.Error.ReadFailed,
|
||||
@@ -120,12 +120,12 @@ fn xzErrorToDecompError(err: Error) Decompressor.Error {
|
||||
}
|
||||
|
||||
fn lzmaAlloc(ptr: ?*anyopaque, _: usize, size: usize) callconv(.c) ?*anyopaque {
|
||||
var alloc: *std.mem.Allocator = @ptrCast(ptr);
|
||||
return alloc.rawAlloc(size, .@"1", 0) catch return null;
|
||||
var alloc: *std.mem.Allocator = @alignCast(@ptrCast(ptr));
|
||||
return alloc.rawAlloc(size, .@"1", 0);
|
||||
}
|
||||
fn lzmaFree(ptr: ?*anyopaque, alloc_ptr: ?*anyopaque) callconv(.c) void {
|
||||
if (alloc_ptr == null) return;
|
||||
var alloc: *std.mem.Allocator = @ptrCast(ptr);
|
||||
var alloc: *std.mem.Allocator = @alignCast(@ptrCast(ptr));
|
||||
alloc.rawFree(@ptrCast(alloc_ptr), .@"1", 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,6 @@ pub fn stateless(alloc: std.mem.Allocator, in: []u8, out: []u8) Decompressor.Err
|
||||
inline fn decodeError(res: usize) Error!void {
|
||||
if (c.ZSTD_isError(res) == 0) return;
|
||||
return switch (c.ZSTD_getErrorCode(res)) {
|
||||
c.ZSTD_error_GENERIC => Error.Generic,
|
||||
c.ZSTD_error_prefix_unknown => Error.PrefixUnknown,
|
||||
c.ZSTD_error_version_unsupported => Error.VersionUnsupported,
|
||||
c.ZSTD_error_frameParameter_unsupported => Error.FrameParameterUnsupported,
|
||||
@@ -91,11 +90,12 @@ inline fn decodeError(res: usize) Error!void {
|
||||
c.ZSTD_error_srcBuffer_wrong => Error.SrcBufferWrong,
|
||||
c.ZSTD_error_sequenceProducer_failed => Error.SequenceProducerFailed,
|
||||
c.ZSTD_error_externalSequences_invalid => Error.ExternalSequencesInvalid,
|
||||
else => Error.Generic,
|
||||
};
|
||||
}
|
||||
inline fn ZstdErrorToDecompError(err: Error) Decompressor.Error {
|
||||
return switch (err) {
|
||||
Error.OutOfMemory => err,
|
||||
Error.OutOfMemory => Decompressor.Error.OutOfMemory,
|
||||
Error.Generic => Decompressor.Error.ReadFailed,
|
||||
Error.PrefixUnknown => Decompressor.Error.ReadFailed,
|
||||
Error.VersionUnsupported => Decompressor.Error.ReadFailed,
|
||||
|
||||
@@ -4,7 +4,7 @@ const Reader = std.Io.Reader;
|
||||
|
||||
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 {
|
||||
var rdr: Reader = .static(in);
|
||||
|
||||
@@ -4,7 +4,7 @@ const Reader = std.Io.Reader;
|
||||
|
||||
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 {
|
||||
var rdr: Reader = .static(in);
|
||||
|
||||
@@ -4,7 +4,7 @@ const Reader = std.Io.Reader;
|
||||
|
||||
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 {
|
||||
const buf = try alloc.alloc(u8, out.len);
|
||||
|
||||
@@ -4,7 +4,7 @@ const Reader = std.Io.Reader;
|
||||
|
||||
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 {
|
||||
const buf = try alloc.alloc(u8, out.len * 2);
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
//! Options for file/directory extraction.
|
||||
|
||||
const std = @import("std");
|
||||
const Writer = std.Io.Writer;
|
||||
|
||||
const ExtractionOptions = @This();
|
||||
|
||||
/// The number of threads used for extraction. 0 implies single threaded.
|
||||
threads: usize = 1,
|
||||
/// Don't set the file's owner & permissions after extraction
|
||||
ignore_permissions: bool = false,
|
||||
/// Don't set xattr values. Currently xattrs are never set anyway.
|
||||
ignore_xattr: bool = false,
|
||||
/// Replace symlinks with their target.
|
||||
dereference_symlinks: bool = false,
|
||||
/// Verbose logging. If true, verbose_writer must be set
|
||||
verbose: bool = false,
|
||||
/// Where to print verbose log.
|
||||
verbose_writer: ?*Writer = null,
|
||||
|
||||
pub const SingleThreadedDefault: ExtractionOptions = .{};
|
||||
pub fn Default() !ExtractionOptions {
|
||||
return .{
|
||||
.threads = try std.Thread.getCpuCount(),
|
||||
};
|
||||
}
|
||||
pub fn VerboseDefault(wrt: *Writer) !ExtractionOptions {
|
||||
return .{
|
||||
.verbose = true,
|
||||
.verbose_writer = wrt,
|
||||
.threads = try std.Thread.getCpuCount(),
|
||||
};
|
||||
}
|
||||
@@ -1 +1,3 @@
|
||||
pub const Archive = @import("archive.zig");
|
||||
|
||||
pub const ExtractionOptions = @import("options.zig");
|
||||
Reference in New Issue
Block a user