Fixed a handful of errors when extracting.
Fixed issues with unsquashfs
This commit is contained in:
@@ -34,6 +34,7 @@ pub fn main() !void {
|
|||||||
fn handleArgs(alloc: std.mem.Allocator, out: *Writer) !void {
|
fn handleArgs(alloc: std.mem.Allocator, out: *Writer) !void {
|
||||||
var args = try std.process.argsWithAllocator(alloc);
|
var args = try std.process.argsWithAllocator(alloc);
|
||||||
defer args.deinit();
|
defer args.deinit();
|
||||||
|
_ = args.next(); // args[0] is the application launch command.
|
||||||
while (args.next()) |arg| {
|
while (args.next()) |arg| {
|
||||||
if (std.mem.eql(u8, arg, "-o")) {
|
if (std.mem.eql(u8, arg, "-o")) {
|
||||||
const nxt = args.next();
|
const nxt = args.next();
|
||||||
@@ -45,6 +46,7 @@ fn handleArgs(alloc: std.mem.Allocator, out: *Writer) !void {
|
|||||||
try out.print("-o must be followed by a number\n", .{});
|
try out.print("-o must be followed by a number\n", .{});
|
||||||
return errors.InvalidArguments;
|
return errors.InvalidArguments;
|
||||||
};
|
};
|
||||||
|
continue;
|
||||||
} else if (std.mem.eql(u8, arg, "-d")) {
|
} else if (std.mem.eql(u8, arg, "-d")) {
|
||||||
const nxt = args.next();
|
const nxt = args.next();
|
||||||
if (nxt == null or nxt.?.len == 0) {
|
if (nxt == null or nxt.?.len == 0) {
|
||||||
@@ -52,6 +54,7 @@ fn handleArgs(alloc: std.mem.Allocator, out: *Writer) !void {
|
|||||||
return errors.InvalidArguments;
|
return errors.InvalidArguments;
|
||||||
}
|
}
|
||||||
extLoc = nxt.?;
|
extLoc = nxt.?;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if (archive.len > 0) {
|
if (archive.len > 0) {
|
||||||
try out.print("you can only provide one file at a time\n", .{});
|
try out.print("you can only provide one file at a time\n", .{});
|
||||||
|
|||||||
+9
-5
@@ -18,9 +18,10 @@ pub const DecompFn = *const fn (alloc: std.mem.Allocator, in: []u8, out: []u8) a
|
|||||||
// };
|
// };
|
||||||
|
|
||||||
pub fn gzipDecompress(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
|
pub fn gzipDecompress(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
|
||||||
_ = alloc;
|
|
||||||
var rdr: Reader = .fixed(in);
|
var rdr: Reader = .fixed(in);
|
||||||
var decomp = std.compress.flate.Decompress.init(&rdr, .zlib, &[0]u8{});
|
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);
|
return decomp.reader.readSliceShort(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,8 +38,11 @@ pub fn xzDecompress(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usiz
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn zstdDecompress(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
|
pub fn zstdDecompress(alloc: std.mem.Allocator, in: []u8, out: []u8) anyerror!usize {
|
||||||
_ = alloc;
|
|
||||||
var rdr: Reader = .fixed(in);
|
var rdr: Reader = .fixed(in);
|
||||||
var decomp = std.compress.zstd.Decompress.init(&rdr, &[0]u8{}, .{});
|
const buf = try alloc.alloc(u8, std.compress.zstd.default_window_len + std.compress.zstd.block_size_max);
|
||||||
return decomp.reader.readSliceShort(out);
|
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;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-7
@@ -30,17 +30,13 @@ pub fn readDir(alloc: std.mem.Allocator, rdr: *Reader, size: u32) ![]Entry {
|
|||||||
var cur_red: u32 = 3; // start at 3 due to "." & ".." being counted in the dir size.
|
var cur_red: u32 = 3; // start at 3 due to "." & ".." being counted in the dir size.
|
||||||
var hdr: Header = undefined;
|
var hdr: Header = undefined;
|
||||||
var raw: RawEntry = undefined;
|
var raw: RawEntry = undefined;
|
||||||
var out: std.ArrayList(Entry) = try .initCapacity(alloc, 25); // Start out with capacity instead of needing to allocate per header.
|
var out: std.ArrayList(Entry) = try .initCapacity(alloc, 100); // Start out with a decent capacity instead of needing to allocate per header.
|
||||||
errdefer out.deinit(alloc);
|
errdefer out.deinit(alloc);
|
||||||
while (cur_red < size) {
|
while (cur_red < size) {
|
||||||
try rdr.readSliceEndian(Header, @ptrCast(&hdr), .little);
|
try rdr.readSliceEndian(Header, @ptrCast(&hdr), .little);
|
||||||
cur_red += @sizeOf(Header);
|
cur_red += @sizeOf(Header);
|
||||||
const count = hdr.count + 1;
|
try out.ensureUnusedCapacity(alloc, hdr.count + 1);
|
||||||
if (out.capacity < count) {
|
for (0..hdr.count + 1) |_| {
|
||||||
// Make sure we have at least 25 capacity past current count.
|
|
||||||
try out.ensureUnusedCapacity(alloc, ((count % 25) + 2) * 25);
|
|
||||||
}
|
|
||||||
for (0..count) |_| {
|
|
||||||
try rdr.readSliceEndian(RawEntry, @ptrCast(&raw), .little);
|
try rdr.readSliceEndian(RawEntry, @ptrCast(&raw), .little);
|
||||||
const name = try alloc.alloc(u8, raw.name_size + 1);
|
const name = try alloc.alloc(u8, raw.name_size + 1);
|
||||||
errdefer alloc.free(name);
|
errdefer alloc.free(name);
|
||||||
|
|||||||
+1
-1
@@ -42,7 +42,7 @@ pub fn init(archive: *Archive, inode: Inode, name: []const u8) !SfsFile {
|
|||||||
}
|
}
|
||||||
pub fn fromEntry(archive: *Archive, entry: DirEntry) !SfsFile {
|
pub fn fromEntry(archive: *Archive, entry: DirEntry) !SfsFile {
|
||||||
var rdr = try archive.fil.readerAt(entry.block_start + archive.super.inode_start, &[0]u8{});
|
var rdr = try archive.fil.readerAt(entry.block_start + archive.super.inode_start, &[0]u8{});
|
||||||
var meta: MetadataReader = .init(archive.allocator(), &rdr.interface, &archive.decomp);
|
var meta: MetadataReader = .init(archive.allocator(), &rdr.interface, archive.decomp);
|
||||||
try meta.interface.discardAll(entry.block_offset);
|
try meta.interface.discardAll(entry.block_offset);
|
||||||
const inode: Inode = try .read(archive.allocator(), &meta.interface, archive.super.block_size);
|
const inode: Inode = try .read(archive.allocator(), &meta.interface, archive.super.block_size);
|
||||||
errdefer inode.deinit(archive.allocator());
|
errdefer inode.deinit(archive.allocator());
|
||||||
|
|||||||
+4
-1
@@ -138,6 +138,9 @@ pub fn extractTo(self: Inode, archive: *Archive, path: []const u8, options: Extr
|
|||||||
.dir, .ext_dir => {
|
.dir, .ext_dir => {
|
||||||
// Removing any trailing separators since that's the easiest path forward.
|
// Removing any trailing separators since that's the easiest path forward.
|
||||||
if (path[path.len - 1] == '/') return self.extractTo(archive, path[0 .. path.len - 1], options);
|
if (path[path.len - 1] == '/') return self.extractTo(archive, path[0 .. path.len - 1], options);
|
||||||
|
std.fs.cwd().makeDir(path) catch |err| {
|
||||||
|
if (err != std.fs.Dir.MakeError.PathAlreadyExists) return err;
|
||||||
|
};
|
||||||
var alloc = archive.allocator();
|
var alloc = archive.allocator();
|
||||||
const entries = try self.dirEntries(archive);
|
const entries = try self.dirEntries(archive);
|
||||||
defer {
|
defer {
|
||||||
@@ -218,7 +221,7 @@ fn extractRegFile(self: Inode, archive: *Archive, path: []const u8, options: Ext
|
|||||||
_ = try dat_rdr.interface.streamRemaining(&wrt.interface);
|
_ = try dat_rdr.interface.streamRemaining(&wrt.interface);
|
||||||
try wrt.interface.flush();
|
try wrt.interface.flush();
|
||||||
// updateTime is in nanoseconds (a billionth of a second). mod_time is in seconds.
|
// updateTime is in nanoseconds (a billionth of a second). mod_time is in seconds.
|
||||||
try fil.updateTimes(self.hdr.mod_time * (10 ^ 9), self.hdr.mod_time * (10 ^ 9));
|
try fil.updateTimes(self.hdr.mod_time, self.hdr.mod_time);
|
||||||
if (!options.ignore_permissions) {
|
if (!options.ignore_permissions) {
|
||||||
try fil.chmod(self.hdr.permissions);
|
try fil.chmod(self.hdr.permissions);
|
||||||
try fil.chown(try archive.id(self.hdr.uid_idx), try archive.id(self.hdr.gid_idx));
|
try fil.chown(try archive.id(self.hdr.uid_idx), try archive.id(self.hdr.gid_idx));
|
||||||
|
|||||||
+2
-2
@@ -28,7 +28,7 @@ test "ExtractSingleFile" {
|
|||||||
defer sfs.deinit();
|
defer sfs.deinit();
|
||||||
var test_fil = try sfs.open(TestFile);
|
var test_fil = try sfs.open(TestFile);
|
||||||
defer test_fil.deinit();
|
defer test_fil.deinit();
|
||||||
try test_fil.extract(TestFileExtractLocation, .VerboseDefault);
|
try test_fil.extract(TestFileExtractLocation, .Default);
|
||||||
//TODO: validate extracted file.
|
//TODO: validate extracted file.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ test "ExtractCompleteArchive" {
|
|||||||
defer fil.close();
|
defer fil.close();
|
||||||
var sfs: Archive = try .init(std.testing.allocator, fil);
|
var sfs: Archive = try .init(std.testing.allocator, fil);
|
||||||
defer sfs.deinit();
|
defer sfs.deinit();
|
||||||
try sfs.extract(TestFullExtractLocation, .VerboseDefault);
|
try sfs.extract(TestFullExtractLocation, .Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
const LinuxPATestCorrectSuperblock: Superblock = .{
|
const LinuxPATestCorrectSuperblock: Superblock = .{
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ fn advance(self: *DataReader) !void {
|
|||||||
}
|
}
|
||||||
const tmp_buf = try self.alloc.alloc(u8, block.size);
|
const tmp_buf = try self.alloc.alloc(u8, block.size);
|
||||||
defer self.alloc.free(tmp_buf);
|
defer self.alloc.free(tmp_buf);
|
||||||
|
try rdr.interface.readSliceAll(tmp_buf);
|
||||||
_ = try self.decomp(self.alloc, tmp_buf, self.interface.buffer);
|
_ = try self.decomp(self.alloc, tmp_buf, self.interface.buffer);
|
||||||
}
|
}
|
||||||
/// Does not guarentee that data currently in the buffer is retained.
|
/// Does not guarentee that data currently in the buffer is retained.
|
||||||
|
|||||||
Reference in New Issue
Block a user