Added Zig-unsquashfs arg parsing.

Tweaks to build, including the ability to specifiy version
This commit is contained in:
Caleb Gardner
2025-05-26 04:05:53 -05:00
parent b0ecbe16bd
commit 7a4105bebd
3 changed files with 165 additions and 22 deletions
+15 -2
View File
@@ -1,6 +1,13 @@
const std = @import("std");
pub fn build(b: *std.Build) void {
/// version if version isn't provided during build
const def_version = "0.0.0+testing";
pub fn build(b: *std.Build) !void {
const opt = b.addOptions();
const ver = b.option([]const u8, "version", "sematic version") orelse def_version;
const sem_ver = try std.SemanticVersion.parse(ver);
opt.addOption(std.SemanticVersion, "version", sem_ver);
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const lib_mod = b.createModule(.{
@@ -12,19 +19,25 @@ pub fn build(b: *std.Build) void {
.linkage = .static,
.name = "zig_squashfs",
.root_module = lib_mod,
.version = sem_ver,
});
const exe_mod = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.root_source_file = b.path("src/zig_unsquashfs.zig"),
.target = target,
.optimize = optimize,
});
exe_mod.addOptions("config", opt);
const exe = b.addExecutable(.{
.linkage = .static,
.name = "zig-unsquashfs",
.root_module = exe_mod,
.version = sem_ver,
});
b.installArtifact(lib);
b.installArtifact(exe);
const lib_unit_tests = b.addTest(.{
.root_module = lib_mod,
});
-20
View File
@@ -1,20 +0,0 @@
const std = @import("std");
const Reader = @import("reader.zig");
const stdout = std.io.getStdOut();
pub fn main() !void {
var alloc: std.heap.GeneralPurposeAllocator(.{}) = .init;
var args = try std.process.argsWithAllocator(alloc.allocator());
defer args.deinit();
while (args.next()) |arg| {
if (std.mem.eql(u8, arg, "--help")) {
help();
return;
}
}
//TODO
}
fn help() void {}
+150
View File
@@ -0,0 +1,150 @@
const std = @import("std");
const config = @import("config");
const Reader = @import("reader.zig").Reader;
const stdout = std.io.getStdOut();
var extr_files: std.ArrayList([]const u8) = undefined;
var offset: u64 = 0;
var verbose: bool = false;
var unbreak: bool = false;
var deref: bool = false;
var processors: u16 = 0;
var list: ListTypes = .None;
var filename: []const u8 = "";
var extr_location: []const u8 = "";
const ListTypes = enum {
None,
List,
ListAttr,
ListNumeric,
};
fn help() !void {
const help_msg =
\\Basic Usage: zig-unsquashfs [Options] SQUASHFS_FILE EXTRACT_LOCATION
\\
\\General options:
\\ -e <path> Path to a file or directory inside the archive to extract instead of the whole archive.
\\ Can be given multiple times.
\\ -o <bytes> Skip <bytes> before reading from the archive.
\\ -v Verbose output.
\\ --help Prints this help message.
\\ -h Same as --help
\\
\\Extraction options:
\\ --unbreak-symlinks Attempt extract symlink targets along with symlinks. Will not place files outside of the extraction location.
\\ -us Same as --unbreak-symlinks
\\ --deref-symlinks Replace symlink files with their target.
\\ -ds Same as --deref-symlinks
\\ -p <#> Use at most # of processors. Defaults to logical core count.
\\
\\Listing Options:
\\ -l List files instead of extracting. When used, you do not need to specify an extraction location.
\\ -ll Like -l, but with file attributes.
\\ -lln Like -ll, but with numeric uids and gids.
\\
\\Other:
\\ --version Print version number.
\\
;
_ = try stdout.writeAll(help_msg);
}
pub fn main() !void {
var alloc: std.heap.GeneralPurposeAllocator(.{}) = .init;
extr_files = .init(alloc.allocator());
defer extr_files.deinit();
var args = std.process.argsWithAllocator(alloc.allocator()) catch {
_ = try stdout.writeAll("Unable allocate memory");
return;
};
defer args.deinit();
while (args.next()) |arg| {
if (std.mem.eql(u8, arg, "--help") or std.mem.eql(u8, arg, "-h")) {
try help();
return;
} else if (std.mem.eql(u8, arg, "-v")) {
verbose = true;
} else if (std.mem.eql(u8, arg, "--unbreak-symlinks") or std.mem.eql(u8, arg, "-us")) {
unbreak = true;
} else if (std.mem.eql(u8, arg, "--deref-symlinks") or std.mem.eql(u8, arg, "-ds")) {
deref = true;
} else if (std.mem.eql(u8, arg, "-l")) {
list = .List;
} else if (std.mem.eql(u8, arg, "-ll")) {
list = .ListAttr;
} else if (std.mem.eql(u8, arg, "-lln")) {
list = .ListNumeric;
} else if (std.mem.eql(u8, arg, "-e")) {
const next = args.next();
if (next == null) {
_ = try stdout.writeAll("path required after -e\n");
return;
}
try extr_files.append(next.?);
} else if (std.mem.eql(u8, arg, "-o")) {
const next = args.next();
if (next == null) {
_ = try stdout.writeAll("offset required after -o\n");
return;
}
offset = try std.fmt.parseInt(u64, next.?, 10);
} else if (std.mem.eql(u8, arg, "-p")) {
const next = args.next();
if (next == null) {
_ = try stdout.writeAll("number required after -p\n");
return;
}
processors = try std.fmt.parseInt(u16, next.?, 10);
} else if (std.mem.eql(u8, arg, "--version")) {
try config.version.format("", .{}, stdout.writer());
_ = try stdout.write("\n");
return;
} else if (filename.len == 0) {
filename = arg;
} else if (extr_location.len == 0) {
extr_location = arg;
} else {
_ = try stdout.writeAll("invalid or too many arguments\n");
return;
}
}
if (filename.len == 0) {
_ = try stdout.writeAll("no archive given\n");
return;
}
if (list == .None and extr_location.len == 0) {
_ = try stdout.writeAll("no extract location given\n");
return;
}
var rdr: Reader = .init(
alloc.allocator(),
filename,
offset,
) catch |err| {
try std.fmt.format(stdout.writer(), "Error opening {s} as squashfs: {any}", "\n", .{ filename, err });
};
if (list == .None) {
if (extr_files.items.len == 0) {
rdr.root.extract(&rdr, extr_location) catch |err| {
try std.fmt.format(stdout.writer(), "Error extracting archive: {any}", "\n", .{err});
};
} else {
for (extr_files.items) |path| {
var fil = rdr.root.open(&rdr, path) catch |err| {
try std.fmt.format(stdout.writer(), "Error extracting {s}: {any}", "\n", .{ path, err });
};
defer fil.deinit(alloc.allocator());
fil.extract(&rdr, extr_location) catch |err| {
try std.fmt.format(stdout.writer(), "Error extracting {s}: {any}", "\n", .{ path, err });
};
}
}
return;
}
//TODO: listing
}