Finished (?) extraction
Fixed missing zlib_compat (updated library)
This commit is contained in:
@@ -68,10 +68,7 @@ pub fn build(b: *std.Build) !void {
|
|||||||
.target = target,
|
.target = target,
|
||||||
.root_source_file = b.path("src/bin/unsquashfs.zig"),
|
.root_source_file = b.path("src/bin/unsquashfs.zig"),
|
||||||
.valgrind = debug,
|
.valgrind = debug,
|
||||||
.imports = &.{
|
.imports = &.{ .{ .name = "config", .module = exe_config.createModule() }, .{ .name = "squashfs", .module = lib.root_module } },
|
||||||
.{ .name = "config", .module = exe_config.createModule() },
|
|
||||||
.{ .name = "squashfs", .module = lib.root_module }
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -104,7 +101,7 @@ fn getDependencies(b: *Build, optimize: std.builtin.OptimizeMode, target: Build.
|
|||||||
|
|
||||||
var list: std.ArrayList(*Build.Step.Compile) = .empty;
|
var list: std.ArrayList(*Build.Step.Compile) = .empty;
|
||||||
|
|
||||||
const zlib_ng = b.dependency("zlib_ng", .{ .optimize = optimize, .target = target });
|
const zlib_ng = b.dependency("zlib_ng", .{ .optimize = optimize, .target = target, .zlib_compat = true });
|
||||||
try list.append(alloc, zlib_ng.artifact("zng"));
|
try list.append(alloc, zlib_ng.artifact("zng"));
|
||||||
|
|
||||||
const xz = b.dependency("xz", .{ .optimize = optimize, .target = target });
|
const xz = b.dependency("xz", .{ .optimize = optimize, .target = target });
|
||||||
|
|||||||
+2
-2
@@ -5,8 +5,8 @@
|
|||||||
.minimum_zig_version = "0.16.0",
|
.minimum_zig_version = "0.16.0",
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.zlib_ng = .{
|
.zlib_ng = .{
|
||||||
.url = "git+https://github.com/CalebQ42/zig-zlib-ng#5f2f02dfb28acca2517dacbbd09e9b987f57b133",
|
.url = "git+https://github.com/CalebQ42/zig-zlib-ng#915db2dbd4a540d8a933336d67520b786f168f01",
|
||||||
.hash = "zlib_ng-2.3.3-pre1-2HYS4ClFAABW8KlHMyBHtlNKE3V7kCS8wqfxawG7xeaa",
|
.hash = "zlib_ng-2.3.3-pre1-2HYS4MlFAADc-eSZv4_xjkxZRCdGUVOYZKdtqhybstgk",
|
||||||
},
|
},
|
||||||
.zstd = .{
|
.zstd = .{
|
||||||
.url = "git+https://github.com/allyourcodebase/zstd.git?ref=1.5.7-1#e1a501be57f42c541e8a5597e4b59a074dfd09a3",
|
.url = "git+https://github.com/allyourcodebase/zstd.git?ref=1.5.7-1#e1a501be57f42c541e8a5597e4b59a074dfd09a3",
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ pub fn addFragment(self: *Extractor, data: []u8, offset: u32) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn asyncExtract(self: Extractor, io: Io, fil: Io.File) Error!void {
|
pub fn asyncExtract(self: Extractor, io: Io, fil: Io.File) Error!void {
|
||||||
try fil.writePositionalAll(io, &.{&.{0}}, self.size - 1);
|
try fil.writePositionalAll(io, &.{0}, self.size - 1);
|
||||||
|
|
||||||
var map = try fil.createMemoryMap(io, .{ .len = self.size, .protection = .{ .write = true } });
|
var map = try fil.createMemoryMap(io, .{ .len = self.size, .protection = .{ .write = true } });
|
||||||
defer map.destroy(io);
|
defer map.destroy(io);
|
||||||
@@ -59,7 +59,7 @@ pub fn asyncExtract(self: Extractor, io: Io, fil: Io.File) Error!void {
|
|||||||
|
|
||||||
fn blockThread(self: Extractor, io: Io, map: Io.File.MemoryMap, read_offset: u64, idx: usize, ret_err: *?Error) error{Canceled}!void {
|
fn blockThread(self: Extractor, io: Io, map: Io.File.MemoryMap, read_offset: u64, idx: usize, ret_err: *?Error) error{Canceled}!void {
|
||||||
const write_pos = idx * self.block_size;
|
const write_pos = idx * self.block_size;
|
||||||
const size = if (self.frag_data == null and idx == self.block_size.len - 1)
|
const size = if (self.frag_data == null and idx == self.blocks.len - 1)
|
||||||
self.size % self.block_size
|
self.size % self.block_size
|
||||||
else
|
else
|
||||||
self.block_size;
|
self.block_size;
|
||||||
@@ -70,10 +70,10 @@ fn blockThread(self: Extractor, io: Io, map: Io.File.MemoryMap, read_offset: u64
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (block.uncompressed) {
|
if (block.uncompressed) {
|
||||||
@memcpy(map[write_pos..][0..size], self.cache.map.memory[read_offset..][0..size]);
|
@memcpy(map.memory[write_pos..][0..size], self.cache.map.memory[read_offset..][0..size]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const data = self.cache.get(io, read_offset, block.size, size) catch |err| switch (err) {
|
const data = self.cache.get(io, read_offset, block.size, @truncate(size)) catch |err| switch (err) {
|
||||||
error.Canceled => {
|
error.Canceled => {
|
||||||
io.recancel();
|
io.recancel();
|
||||||
return error.Canceled;
|
return error.Canceled;
|
||||||
@@ -86,9 +86,10 @@ fn blockThread(self: Extractor, io: Io, map: Io.File.MemoryMap, read_offset: u64
|
|||||||
defer self.cache.finished(io, read_offset);
|
defer self.cache.finished(io, read_offset);
|
||||||
if (data.len != size) {
|
if (data.len != size) {
|
||||||
std.debug.print("Size of decompression at {} is {} and should be {}\n", .{ read_offset, data.len, size });
|
std.debug.print("Size of decompression at {} is {} and should be {}\n", .{ read_offset, data.len, size });
|
||||||
return Error.BadDecompressionSize;
|
ret_err.* = Error.BadDecompressionSize;
|
||||||
|
return error.Canceled;
|
||||||
}
|
}
|
||||||
@memcpy(map[write_pos..][0..size], data);
|
@memcpy(map.memory[write_pos..][0..size], data);
|
||||||
}
|
}
|
||||||
fn fragThread(self: Extractor, map: Io.File.MemoryMap) error{Canceled}!void {
|
fn fragThread(self: Extractor, map: Io.File.MemoryMap) error{Canceled}!void {
|
||||||
const write_pos = self.blocks.len * self.block_size;
|
const write_pos = self.blocks.len * self.block_size;
|
||||||
@@ -99,4 +100,4 @@ fn fragThread(self: Extractor, map: Io.File.MemoryMap) error{Canceled}!void {
|
|||||||
|
|
||||||
// Types
|
// Types
|
||||||
|
|
||||||
pub const Error = error{BadDecompressionSize} || Io.File.WritePositionalError || Io.File.MemoryMap.CreateError;
|
pub const Error = error{BadDecompressionSize} || Io.File.WritePositionalError || Io.File.MemoryMap.CreateError || DecompCache.Error;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ pub fn deinit(self: *DecompCache, io: Io) void {
|
|||||||
self.cache.deinit();
|
self.cache.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(self: *DecompCache, io: Io, offset: u64, compressed_size: u32, max_size: u32) ![]u8 {
|
pub fn get(self: *DecompCache, io: Io, offset: u64, compressed_size: u32, max_size: u32) Error![]u8 {
|
||||||
{
|
{
|
||||||
try self.mut.lockShared(io);
|
try self.mut.lockShared(io);
|
||||||
defer self.mut.unlockShared(io);
|
defer self.mut.unlockShared(io);
|
||||||
@@ -110,6 +110,8 @@ fn ensureSpace(self: *DecompCache, io: Io, size: u64) !void {
|
|||||||
|
|
||||||
// Types
|
// Types
|
||||||
|
|
||||||
|
pub const Error = error{ Canceled, OutOfMemory, ReadFailed };
|
||||||
|
|
||||||
const Cache = struct {
|
const Cache = struct {
|
||||||
data: []u8,
|
data: []u8,
|
||||||
usage: Atomic(u32),
|
usage: Atomic(u32),
|
||||||
|
|||||||
+41
-6
@@ -11,6 +11,7 @@ const Directory = @import("directory.zig");
|
|||||||
const DataExtractor = @import("data/extractor.zig");
|
const DataExtractor = @import("data/extractor.zig");
|
||||||
const DataReader = @import("data/reader.zig");
|
const DataReader = @import("data/reader.zig");
|
||||||
const Lookup = @import("lookup.zig");
|
const Lookup = @import("lookup.zig");
|
||||||
|
const XattrTable = @import("xattr.zig");
|
||||||
|
|
||||||
pub fn extract(alloc: std.mem.Allocator, io: Io, inode: Inode, cache: *DecompCache, super: Superblock, ext_loc: []const u8, options: ExtractionOptions) !void {
|
pub fn extract(alloc: std.mem.Allocator, io: Io, inode: Inode, cache: *DecompCache, super: Superblock, ext_loc: []const u8, options: ExtractionOptions) !void {
|
||||||
const path = std.mem.trim(u8, ext_loc, "/");
|
const path = std.mem.trim(u8, ext_loc, "/");
|
||||||
@@ -34,11 +35,17 @@ pub fn extract(alloc: std.mem.Allocator, io: Io, inode: Inode, cache: *DecompCac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var id_table: Lookup.Table(u16) = .init(alloc, cache, super.id_start, super.id_count);
|
||||||
|
defer id_table.deinit();
|
||||||
|
|
||||||
|
var xattr_table: XattrTable = try .init(alloc, cache, super.xattr_start);
|
||||||
|
defer xattr_table.deinit();
|
||||||
|
|
||||||
|
var ret_loop = io.async(returnLoop, .{ alloc, io, &id_table, &xattr_table, &sel, options });
|
||||||
|
|
||||||
var frag_table: Lookup.Table(Lookup.FragmentEntry) = .init(alloc, cache, super.frag_start, super.frag_count);
|
var frag_table: Lookup.Table(Lookup.FragmentEntry) = .init(alloc, cache, super.frag_start, super.frag_count);
|
||||||
defer frag_table.deinit();
|
defer frag_table.deinit();
|
||||||
|
|
||||||
var ret_loop = io.async(returnLoop, .{ alloc, io, &sel, options });
|
|
||||||
|
|
||||||
try extractReal(alloc, io, cache, super, &sel, &frag_table, path, inode, null, false);
|
try extractReal(alloc, io, cache, super, &sel, &frag_table, path, inode, null, false);
|
||||||
|
|
||||||
try ret_loop.await(io);
|
try ret_loop.await(io);
|
||||||
@@ -311,7 +318,7 @@ fn extractNod(alloc: std.mem.Allocator, path: []const u8, inode: Inode, parent:
|
|||||||
|
|
||||||
// Loop
|
// Loop
|
||||||
|
|
||||||
fn returnLoop(alloc: std.mem.Allocator, io: Io, id_table: Lookup.Table(u16), xattr_table: Lookup.Table(Lookup.XattrEntry), sel: *Io.Select(ReturnUnion), options: ExtractionOptions) !void {
|
fn returnLoop(alloc: std.mem.Allocator, io: Io, id_table: *Lookup.Table(u16), xattr_table: *XattrTable, sel: *Io.Select(ReturnUnion), options: ExtractionOptions) !void {
|
||||||
while (true) {
|
while (true) {
|
||||||
const finished = try sel.await();
|
const finished = try sel.await();
|
||||||
|
|
||||||
@@ -339,15 +346,43 @@ fn returnLoop(alloc: std.mem.Allocator, io: Io, id_table: Lookup.Table(u16), xat
|
|||||||
try file.setPermissions(io, @enumFromInt(ret.permissions));
|
try file.setPermissions(io, @enumFromInt(ret.permissions));
|
||||||
try file.setOwner(io, try id_table.get(io, ret.uid_idx), try id_table.get(io, ret.gid_idx));
|
try file.setOwner(io, try id_table.get(io, ret.uid_idx), try id_table.get(io, ret.gid_idx));
|
||||||
}
|
}
|
||||||
if (!options.ignore_xattr and ret.xattr_idx != null) {}
|
if (!options.ignore_xattr and ret.xattr_idx != null) {
|
||||||
|
const xattrs = try xattr_table.get(alloc, io, ret.xattr_idx.?);
|
||||||
|
defer xattrs.deinit(alloc);
|
||||||
|
|
||||||
|
for (xattrs.xattrs) |x| {
|
||||||
|
const res = std.os.linux.fsetxattr(file.handle, x.key, x.value.ptr, x.value.len, 0);
|
||||||
|
if (res != 0)
|
||||||
|
return error.SetXattrFailed;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.file_ret => |f| {
|
.file_ret => |f| {
|
||||||
const ret = try f;
|
const ret = try f;
|
||||||
if (!ret.origin) alloc.free(ret.path);
|
if (!ret.origin) alloc.free(ret.path);
|
||||||
|
|
||||||
if (!options.ignore_permissions and !options.ignore_xattr) {
|
if (!options.ignore_permissions and (!options.ignore_xattr and ret.xattr_idx != null)) {
|
||||||
// TODO: set permissions & xattr.
|
const file = try Io.Dir.cwd().openFile(io, ret.path, .{});
|
||||||
|
defer file.close(io);
|
||||||
|
|
||||||
|
if (!options.ignore_permissions) {
|
||||||
|
try file.setTimestamps(io, .{
|
||||||
|
.modify_timestamp = .init(.{ .nanoseconds = @as(i96, @intCast(ret.mod_time)) * std.time.ns_per_s }),
|
||||||
|
});
|
||||||
|
try file.setPermissions(io, @enumFromInt(ret.permissions));
|
||||||
|
try file.setOwner(io, try id_table.get(io, ret.uid_idx), try id_table.get(io, ret.gid_idx));
|
||||||
|
}
|
||||||
|
if (!options.ignore_xattr and ret.xattr_idx != null) {
|
||||||
|
const xattrs = try xattr_table.get(alloc, io, ret.xattr_idx.?);
|
||||||
|
defer xattrs.deinit(alloc);
|
||||||
|
|
||||||
|
for (xattrs.xattrs) |x| {
|
||||||
|
const res = std.os.linux.fsetxattr(file.handle, x.key, x.value.ptr, x.value.len, 0);
|
||||||
|
if (res != 0)
|
||||||
|
return error.SetXattrFailed;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.void_ret => |v| try v,
|
.void_ret => |v| try v,
|
||||||
|
|||||||
+5
-9
@@ -64,7 +64,7 @@ pub fn deinit(self: SfsFile) void {
|
|||||||
|
|
||||||
/// Attempts to open the filepath if the SfsFile is a directory.
|
/// Attempts to open the filepath if the SfsFile is a directory.
|
||||||
/// If the given path refers to itself (such as "" or "."), a copied SfsFile is returned.
|
/// If the given path refers to itself (such as "" or "."), a copied SfsFile is returned.
|
||||||
pub fn open(self: SfsFile, alloc: std.mem.Allocator, io: Io, filepath: []const u8) !SfsFile {
|
pub fn open(self: *SfsFile, alloc: std.mem.Allocator, io: Io, filepath: []const u8) !SfsFile {
|
||||||
const path = std.mem.trim(u8, filepath, "/");
|
const path = std.mem.trim(u8, filepath, "/");
|
||||||
|
|
||||||
const first_element: []const u8 = std.mem.sliceTo(path, '/');
|
const first_element: []const u8 = std.mem.sliceTo(path, '/');
|
||||||
@@ -86,17 +86,13 @@ pub fn open(self: SfsFile, alloc: std.mem.Allocator, io: Io, filepath: []const u
|
|||||||
}
|
}
|
||||||
if (first_element.len == path.len) 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;
|
if (cur_slice[idx].type != .dir) return error.NotFound;
|
||||||
const tmp_file: SfsFile = try .initDirEntry(alloc, io, self.archive, cur_slice[idx]);
|
var tmp_file: SfsFile = try .initDirEntry(alloc, io, self.archive, cur_slice[idx]);
|
||||||
defer tmp_file.deinit();
|
defer tmp_file.deinit();
|
||||||
|
|
||||||
return tmp_file.open(alloc, io, path[first_element.len..]);
|
return tmp_file.open(alloc, io, path[first_element.len..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract(self: SfsFile, alloc: std.mem.Allocator, io: Io, ext_dir: []const u8, options: ExtractionOptions) !void {
|
const Extract = @import("extract.zig");
|
||||||
_ = self;
|
pub fn extract(self: *SfsFile, alloc: std.mem.Allocator, io: Io, ext_dir: []const u8, options: ExtractionOptions) !void {
|
||||||
_ = alloc;
|
return Extract.extract(alloc, io, self.inode, &self.archive.cache, self.archive.super, ext_dir, options);
|
||||||
_ = io;
|
|
||||||
_ = ext_dir;
|
|
||||||
_ = options;
|
|
||||||
return error.TODO;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -52,7 +52,7 @@ pub fn Table(comptime T: anytype) type {
|
|||||||
pub fn deinit(self: *LookupTable) void {
|
pub fn deinit(self: *LookupTable) void {
|
||||||
var iter = self.values.valueIterator();
|
var iter = self.values.valueIterator();
|
||||||
while (iter.next()) |v|
|
while (iter.next()) |v|
|
||||||
self.alloc.free(v);
|
self.alloc.free(v.*);
|
||||||
self.values.deinit();
|
self.values.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ pub fn Table(comptime T: anytype) type {
|
|||||||
defer self.mut.unlockShared(io);
|
defer self.mut.unlockShared(io);
|
||||||
|
|
||||||
const val = self.values.get(block);
|
const val = self.values.get(block);
|
||||||
if (val != null) return val.*[block_idx];
|
if (val != null) return val.?[block_idx];
|
||||||
}
|
}
|
||||||
try self.mut.lock(io);
|
try self.mut.lock(io);
|
||||||
defer self.mut.unlock(io);
|
defer self.mut.unlock(io);
|
||||||
@@ -75,7 +75,7 @@ pub fn Table(comptime T: anytype) type {
|
|||||||
errdefer self.values.removeByPtr(val.key_ptr);
|
errdefer self.values.removeByPtr(val.key_ptr);
|
||||||
|
|
||||||
const offset_offset = self.table_start + (block * 8);
|
const offset_offset = self.table_start + (block * 8);
|
||||||
const offset: u64 = std.mem.readInt(u64, self.cache.map.memory[offset_offset..][0..2], .little);
|
const offset: u64 = std.mem.readInt(u64, self.cache.map.memory[offset_offset..][0..8], .little);
|
||||||
|
|
||||||
var meta: MetadataReader = .init(io, self.cache, offset);
|
var meta: MetadataReader = .init(io, self.cache, offset);
|
||||||
defer meta.deinit(io);
|
defer meta.deinit(io);
|
||||||
@@ -98,7 +98,7 @@ pub fn Table(comptime T: anytype) type {
|
|||||||
|
|
||||||
// Types
|
// Types
|
||||||
|
|
||||||
pub const Error = error{} || std.mem.Allocator.Error;
|
pub const Error = error{Canceled} || std.mem.Allocator.Error || Io.Reader.Error;
|
||||||
|
|
||||||
pub const FragmentEntry = extern struct {
|
pub const FragmentEntry = extern struct {
|
||||||
start: u64,
|
start: u64,
|
||||||
|
|||||||
+4
-1
@@ -21,8 +21,11 @@ pub fn init(alloc: std.mem.Allocator, cache: *DecompCache, xattr_start: u64) !Xa
|
|||||||
.table = .init(alloc, cache, xattr_start + 16, num),
|
.table = .init(alloc, cache, xattr_start + 16, num),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
pub fn deinit(self: *XattrTable) void {
|
||||||
|
self.table.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get(self: XattrTable, alloc: std.mem.Allocator, io: Io, idx: u32) !XattrKVs {
|
pub fn get(self: *XattrTable, alloc: std.mem.Allocator, io: Io, idx: u32) !XattrKVs {
|
||||||
const entry = try self.table.get(io, idx);
|
const entry = try self.table.get(io, idx);
|
||||||
|
|
||||||
var meta: MetadataReader = .init(io, self.table.cache, self.table_start + entry.ref.block_start);
|
var meta: MetadataReader = .init(io, self.table.cache, self.table_start + entry.ref.block_start);
|
||||||
|
|||||||
Reference in New Issue
Block a user