Updated unsquashfs for zig 0.16.0
Fixed a couple bugs Added scaffold for extraction
This commit is contained in:
@@ -56,6 +56,9 @@ pub fn build(b: *std.Build) !void {
|
||||
|
||||
b.installArtifact(lib);
|
||||
|
||||
const exe_config = b.addOptions();
|
||||
exe_config.addOption(std.SemanticVersion,"version", version);
|
||||
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "unsquashfs",
|
||||
.use_llvm = debug,
|
||||
@@ -65,9 +68,12 @@ pub fn build(b: *std.Build) !void {
|
||||
.target = target,
|
||||
.root_source_file = b.path("src/bin/unsquashfs.zig"),
|
||||
.valgrind = debug,
|
||||
.imports = &.{
|
||||
.{ .name = "config", .module = exe_config.createModule() },
|
||||
.{ .name = "squashfs", .module = lib.root_module }
|
||||
},
|
||||
}),
|
||||
});
|
||||
exe.root_module.linkLibrary(lib);
|
||||
|
||||
b.installArtifact(exe);
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
.name = .squashfs,
|
||||
.version = "0.0.6",
|
||||
.fingerprint = 0x37ba29474b87f145, // Changing this has security and trust implications.
|
||||
.minimum_zig_version = "0.15.2",
|
||||
.minimum_zig_version = "0.16.0",
|
||||
.dependencies = .{
|
||||
.zlib_ng = .{
|
||||
.url = "git+https://github.com/CalebQ42/zig-zlib-ng#5f2f02dfb28acca2517dacbbd09e9b987f57b133",
|
||||
|
||||
+31
-13
@@ -5,6 +5,7 @@ const MemoryMap = File.MemoryMap;
|
||||
|
||||
const Decomp = @import("decomp.zig");
|
||||
const DecompCache = @import("decomp_cache.zig");
|
||||
const Extract = @import("extract.zig");
|
||||
const ExtractionOptions = @import("options.zig");
|
||||
const Inode = @import("inode.zig");
|
||||
const SfsFile = @import("file.zig");
|
||||
@@ -36,7 +37,7 @@ pub fn initAdvanced(alloc: std.mem.Allocator, io: Io, fil: File, offset: u64, ca
|
||||
return .{
|
||||
.super = super,
|
||||
|
||||
.cache = .init(
|
||||
.cache = try .init(
|
||||
alloc,
|
||||
map,
|
||||
super.compression,
|
||||
@@ -74,12 +75,15 @@ pub fn open(self: *Archive, alloc: std.mem.Allocator, io: Io, filepath: []const
|
||||
}
|
||||
|
||||
pub fn extract(self: *Archive, alloc: std.mem.Allocator, io: Io, ext_loc: []const u8, options: ExtractionOptions) !void {
|
||||
_ = self;
|
||||
_ = alloc;
|
||||
_ = io;
|
||||
_ = ext_loc;
|
||||
_ = options;
|
||||
return error.TODO;
|
||||
const root_inode: Inode = try .initRef(
|
||||
alloc,
|
||||
io,
|
||||
&self.cache,
|
||||
self.super.inode_start,
|
||||
self.super.block_size,
|
||||
self.super.root_ref,
|
||||
);
|
||||
return Extract.extract(alloc, io, root_inode, &self.cache, self.super, ext_loc, options);
|
||||
}
|
||||
|
||||
// Superblock
|
||||
@@ -93,7 +97,19 @@ pub const Superblock = extern struct {
|
||||
compression: Decomp.Enum,
|
||||
block_log: u16,
|
||||
flags: packed struct(u16) {
|
||||
TODO: u16,
|
||||
inode_uncompressed: bool,
|
||||
data_uncompressed: bool,
|
||||
check: bool,
|
||||
frag_uncompressed: bool,
|
||||
frag_never: bool,
|
||||
frag_always: bool,
|
||||
de_dupe: bool,
|
||||
exportable: bool,
|
||||
xattr_uncompressed: bool,
|
||||
xattr_never: bool,
|
||||
compression_options: bool,
|
||||
id_uncompressed: bool,
|
||||
_: u4,
|
||||
},
|
||||
id_count: u16,
|
||||
ver_maj: u16,
|
||||
@@ -114,6 +130,8 @@ pub const Superblock = extern struct {
|
||||
return error.InvalidVersion;
|
||||
if (self.block_log != std.math.log2(self.block_size))
|
||||
return error.BadBlockLog;
|
||||
if (self.flags.check)
|
||||
return error.BadCheckFlag;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -127,10 +145,10 @@ test "Basics" {
|
||||
|
||||
var archive_file = try Io.Dir.cwd().openFile(io, TestArchive, .{});
|
||||
defer archive_file.close(io);
|
||||
var arc: Archive = try .init(io, archive_file);
|
||||
var arc: Archive = try .init(alloc, io, archive_file);
|
||||
defer arc.deinit(io);
|
||||
|
||||
var root_file = try arc.root(alloc);
|
||||
var root_file = try arc.root(alloc, io);
|
||||
defer root_file.deinit();
|
||||
}
|
||||
|
||||
@@ -143,10 +161,10 @@ test "SingleFileExtraction" {
|
||||
|
||||
var archive_file = try Io.Dir.cwd().openFile(io, TestArchive, .{});
|
||||
defer archive_file.close(io);
|
||||
var arc: Archive = try .init(io, archive_file);
|
||||
var arc: Archive = try .init(alloc, io, archive_file);
|
||||
defer arc.deinit(io);
|
||||
|
||||
var ext_file = try arc.open(alloc, TestFile);
|
||||
var ext_file = try arc.open(alloc, io, TestFile);
|
||||
defer ext_file.deinit();
|
||||
|
||||
try ext_file.extract(alloc, io, TestFileExtractLocation, .default);
|
||||
@@ -160,7 +178,7 @@ test "FullExtraction" {
|
||||
|
||||
var archive_file = try Io.Dir.cwd().openFile(io, TestArchive, .{});
|
||||
defer archive_file.close(io);
|
||||
var arc: Archive = try .init(io, archive_file);
|
||||
var arc: Archive = try .init(alloc, io, archive_file);
|
||||
defer arc.deinit(io);
|
||||
|
||||
try arc.extract(alloc, io, TestFullExtractLocation, .default);
|
||||
|
||||
+25
-22
@@ -1,9 +1,11 @@
|
||||
const std = @import("std");
|
||||
const Writer = std.Io.Writer;
|
||||
const Io = std.Io;
|
||||
const Writer = Io.Writer;
|
||||
const File = Io.File;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const config = @import("config");
|
||||
const squashfs = @import("zig_squashfs");
|
||||
const squashfs = @import("squashfs");
|
||||
|
||||
//TODO: Add more options
|
||||
const help_mgs =
|
||||
@@ -38,40 +40,41 @@ var ignore_xattrs: bool = false;
|
||||
var ignore_permissions: bool = false;
|
||||
var force: bool = false;
|
||||
|
||||
pub fn main() !void {
|
||||
const alloc = std.heap.smp_allocator;
|
||||
var stdout = std.fs.File.stdout();
|
||||
var out = stdout.writer(&[0]u8{});
|
||||
pub fn main(init: std.process.Init) !void {
|
||||
const alloc = init.gpa;
|
||||
const io = init.io;
|
||||
|
||||
var stdout = File.stdout();
|
||||
var out = stdout.writer(io, &[0]u8{});
|
||||
defer out.interface.flush() catch {};
|
||||
try handleArgs(alloc, &out.interface);
|
||||
try handleArgs(init.minimal.args, &out.interface);
|
||||
if (archive.len == 0) {
|
||||
try out.interface.print("You must provide a squashfs archive\n", .{});
|
||||
try out.interface.print(help_mgs, .{});
|
||||
return;
|
||||
}
|
||||
var fil: std.fs.File = try std.fs.cwd().openFile(archive, .{}); //TODO: Handle error gracefully.
|
||||
defer fil.close();
|
||||
var arc: squashfs.Archive = try .init(alloc, fil, offset); //TODO: Update when memory size matters. //TODO: Handle error gracefully.
|
||||
defer arc.deinit();
|
||||
var fil: File = try Io.Dir.cwd().openFile(io, archive, .{}); //TODO: Handle error gracefully.
|
||||
defer fil.close(io);
|
||||
var arc: squashfs.Archive = try .initAdvanced(alloc, io, fil, offset, 0); //TODO: Update when memory size matters. //TODO: Handle error gracefully.
|
||||
defer arc.deinit(io);
|
||||
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.
|
||||
try Io.Dir.cwd().deleteTree(io, extLoc);
|
||||
try arc.extract(alloc, io, extLoc, options); //TODO: Handle error gracefully.
|
||||
}
|
||||
|
||||
fn handleArgs(alloc: std.mem.Allocator, out: *Writer) !void {
|
||||
var args = try std.process.argsWithAllocator(alloc);
|
||||
defer args.deinit();
|
||||
_ = args.next(); // args[0] is the application launch command.
|
||||
while (args.next()) |arg| {
|
||||
fn handleArgs(args: std.process.Args, out: *Writer) !void {
|
||||
var arg_iter = args.iterate();
|
||||
defer arg_iter.deinit();
|
||||
_ = arg_iter.skip(); // args[0] is the application launch command.
|
||||
while (arg_iter.next()) |arg| {
|
||||
if (std.mem.eql(u8, arg, "-o")) {
|
||||
const nxt = args.next();
|
||||
const nxt = arg_iter.next();
|
||||
if (nxt == null or nxt.?.len == 0) {
|
||||
try out.print("-o must be followed by a number\n", .{});
|
||||
return errors.InvalidArguments;
|
||||
@@ -82,7 +85,7 @@ fn handleArgs(alloc: std.mem.Allocator, out: *Writer) !void {
|
||||
};
|
||||
continue;
|
||||
} else if (std.mem.eql(u8, arg, "-d")) {
|
||||
const nxt = args.next();
|
||||
const nxt = arg_iter.next();
|
||||
if (nxt == null or nxt.?.len == 0) {
|
||||
try out.print("-d must be followed by a location\n", .{});
|
||||
return errors.InvalidArguments;
|
||||
@@ -90,7 +93,7 @@ fn handleArgs(alloc: std.mem.Allocator, out: *Writer) !void {
|
||||
extLoc = nxt.?;
|
||||
continue;
|
||||
} else if (std.mem.eql(u8, arg, "-p")) {
|
||||
const nxt = args.next();
|
||||
const nxt = arg_iter.next();
|
||||
if (nxt == null or nxt.?.len == 0) {
|
||||
try out.print("-p must be followed by a number\n", .{});
|
||||
return errors.InvalidArguments;
|
||||
|
||||
+4
-4
@@ -5,17 +5,17 @@ const c = @import("c");
|
||||
const Error = @import("decomp.zig").Error;
|
||||
|
||||
pub fn zlibDecompress(_: std.mem.Allocator, in: []u8, out: []u8) Error!usize {
|
||||
var strem: c.zng_stream = .{
|
||||
var strem: c.z_stream = .{
|
||||
.next_in = in.ptr,
|
||||
.avail_in = @truncate(in.len),
|
||||
.next_out = out.ptr,
|
||||
.avail_out = @truncate(out.len),
|
||||
};
|
||||
var res = c.zng_inflateInit(&strem);
|
||||
var res = c.inflateInit(&strem);
|
||||
if (res != c.Z_OK) return Error.ReadFailed;
|
||||
defer _ = c.zng_inflateEnd(&strem);
|
||||
defer _ = c.inflateEnd(&strem);
|
||||
|
||||
res = c.zng_inflate(&strem, c.Z_FULL_FLUSH);
|
||||
res = c.inflate(&strem, c.Z_FULL_FLUSH);
|
||||
if (res != c.Z_OK) return Error.ReadFailed;
|
||||
|
||||
return strem.total_out;
|
||||
|
||||
@@ -19,7 +19,7 @@ cond: std.Io.Condition = .init,
|
||||
max_mem: u64,
|
||||
cur_mem: u64 = 0,
|
||||
|
||||
pub fn init(alloc: std.mem.Allocator, map: MemoryMap, compression: Decomp.Enum, max_mem: u64) DecompCache {
|
||||
pub fn init(alloc: std.mem.Allocator, map: MemoryMap, compression: Decomp.Enum, max_mem: u64) !DecompCache {
|
||||
return .{
|
||||
.alloc = alloc,
|
||||
.map = map,
|
||||
@@ -55,8 +55,8 @@ pub fn get(self: *DecompCache, io: Io, offset: u64, compressed_size: u32, max_si
|
||||
|
||||
const cache = try self.cache.getOrPut(offset);
|
||||
if (cache.found_existing) {
|
||||
_ = cache.?.usage.fetchAdd(1, .acquire);
|
||||
return cache.?.data;
|
||||
_ = cache.value_ptr.usage.fetchAdd(1, .acquire);
|
||||
return cache.value_ptr.data;
|
||||
}
|
||||
errdefer self.cache.removeByPtr(cache.key_ptr);
|
||||
|
||||
@@ -104,7 +104,7 @@ fn ensureSpace(self: *DecompCache, io: Io, size: u64) !void {
|
||||
}
|
||||
}
|
||||
if (self.cur_mem + size <= self.max_mem) return;
|
||||
try self.cond.wait(io, self.mut.mutex);
|
||||
try self.cond.wait(io, &self.mut.mutex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ pub fn init(alloc: std.mem.Allocator, rdr: *Reader, size: u32) !Directory {
|
||||
}
|
||||
}
|
||||
|
||||
return entries.toOwnedSlice(alloc);
|
||||
return .{ .entries = try entries.toOwnedSlice(alloc) };
|
||||
}
|
||||
pub fn deinit(self: Directory, alloc: std.mem.Allocator) void {
|
||||
for (self.entries) |entry|
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
const std = @import("std");
|
||||
const Io = std.Io;
|
||||
|
||||
const DecompCache = @import("decomp_cache.zig");
|
||||
const ExtractionOptions = @import("options.zig");
|
||||
const Inode = @import("inode.zig");
|
||||
const Superblock = @import("archive.zig").Superblock;
|
||||
|
||||
pub fn extract(alloc: std.mem.Allocator, io: Io, inode: Inode, cache: *DecompCache, super: Superblock, ext_loc: []const u8, options: ExtractionOptions) !void {
|
||||
_ = alloc;
|
||||
_ = io;
|
||||
_ = inode;
|
||||
_ = cache;
|
||||
_ = super;
|
||||
_ = ext_loc;
|
||||
_ = options;
|
||||
return error.TODO;
|
||||
}
|
||||
|
||||
pub fn extractDir(alloc: std.mem.Allocator, io: Io, path: []const u8, d: anytype) Error!PathReturn {}
|
||||
pub fn extractFile(alloc: std.mem.Allocator, io: Io, path: []const u8, d: anytype) Error!PathReturn {
|
||||
const atomic = try Io.Dir.cwd().createFileAtomic(io, path, .{});
|
||||
defer atomic.deinit(io);
|
||||
|
||||
// TODO
|
||||
|
||||
try atomic.link(io);
|
||||
// return .{
|
||||
// .path = path,
|
||||
// };
|
||||
return error.TODO;
|
||||
}
|
||||
|
||||
// Utility types
|
||||
|
||||
const ReturnUnion = union {
|
||||
path_ret: Error!PathReturn,
|
||||
};
|
||||
|
||||
const Error = error{};
|
||||
|
||||
const PathReturn = struct {
|
||||
path: []const u8,
|
||||
|
||||
uid_idx: u32,
|
||||
gid_idx: u32,
|
||||
mod_time: u32,
|
||||
permission: u16,
|
||||
|
||||
xattr_idx: ?u32,
|
||||
};
|
||||
+19
-9
@@ -1,3 +1,11 @@
|
||||
const std = @import("std");
|
||||
const Io = std.Io;
|
||||
|
||||
const Archive = @import("archive.zig");
|
||||
const Directory = @import("directory.zig");
|
||||
const ExtractionOptions = @import("options.zig");
|
||||
const Inode = @import("inode.zig");
|
||||
|
||||
const SfsFile = @This();
|
||||
|
||||
alloc: std.mem.Allocator,
|
||||
@@ -28,7 +36,7 @@ pub fn initDirEntry(alloc: std.mem.Allocator, io: Io, archive: *Archive, entry:
|
||||
.inode = try .initDirEntry(
|
||||
alloc,
|
||||
io,
|
||||
archive.cache,
|
||||
&archive.cache,
|
||||
archive.super.inode_start,
|
||||
archive.super.block_size,
|
||||
entry,
|
||||
@@ -61,7 +69,7 @@ pub fn open(self: SfsFile, alloc: std.mem.Allocator, io: Io, filepath: []const u
|
||||
|
||||
const first_element: []const u8 = std.mem.sliceTo(path, '/');
|
||||
|
||||
const dir: Directory = try self.inode.directory(alloc, io, self.archive.cache, self.archive.super.dir_start);
|
||||
const dir: Directory = try self.inode.directory(alloc, io, &self.archive.cache, self.archive.super.dir_start);
|
||||
defer dir.deinit(alloc);
|
||||
|
||||
var cur_slice = dir.entries;
|
||||
@@ -76,7 +84,7 @@ pub fn open(self: SfsFile, alloc: std.mem.Allocator, io: Io, filepath: []const u
|
||||
} else {
|
||||
return error.NotFound;
|
||||
}
|
||||
if (first_element.len == path) return .initDirEntry(alloc, io, self.archive, cur_slice[idx]);
|
||||
if (first_element.len == path.len) return .initDirEntry(alloc, io, self.archive, cur_slice[idx]);
|
||||
if (cur_slice[idx].type != .dir) return error.NotFound;
|
||||
const tmp_file: SfsFile = try .initDirEntry(alloc, io, self.archive, cur_slice[idx]);
|
||||
defer tmp_file.deinit();
|
||||
@@ -84,9 +92,11 @@ pub fn open(self: SfsFile, alloc: std.mem.Allocator, io: Io, filepath: []const u
|
||||
return tmp_file.open(alloc, io, path[first_element.len..]);
|
||||
}
|
||||
|
||||
const std = @import("std");
|
||||
const Io = std.Io;
|
||||
|
||||
const Archive = @import("archive.zig");
|
||||
const Directory = @import("directory.zig");
|
||||
const Inode = @import("inode.zig");
|
||||
pub fn extract(self: SfsFile, alloc: std.mem.Allocator, io: Io, ext_dir: []const u8, options: ExtractionOptions) !void {
|
||||
_ = self;
|
||||
_ = alloc;
|
||||
_ = io;
|
||||
_ = ext_dir;
|
||||
_ = options;
|
||||
return error.TODO;
|
||||
}
|
||||
|
||||
+2
-2
@@ -280,7 +280,7 @@ const ExtFile = struct {
|
||||
.blocks = blocks,
|
||||
};
|
||||
}
|
||||
pub fn deinit(self: File, alloc: std.mem.Allocator) void {
|
||||
pub fn deinit(self: ExtFile, alloc: std.mem.Allocator) void {
|
||||
alloc.free(self.blocks);
|
||||
}
|
||||
};
|
||||
@@ -342,7 +342,7 @@ const ExtSymlink = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: Symlink, alloc: std.mem.Allocator) void {
|
||||
pub fn deinit(self: ExtSymlink, alloc: std.mem.Allocator) void {
|
||||
alloc.free(self.target);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user