Further work on extraction

This commit is contained in:
Caleb Gardner
2026-05-16 23:41:28 -05:00
parent 3c57a2d1e4
commit 10e9b66ac6
+34 -26
View File
@@ -108,7 +108,7 @@ fn getExtractorFromData(fil: OffsetFile, cache: *SharedCache, decomp: *const Dec
} }
return ext; return ext;
} }
// Get a symlink's target path /// Get a symlink's target path
pub fn symlinkTarget(self: Inode) ![]const u8 { pub fn symlinkTarget(self: Inode) ![]const u8 {
return switch (self.data) { return switch (self.data) {
.symlink => |s| s.target, .symlink => |s| s.target,
@@ -116,28 +116,17 @@ pub fn symlinkTarget(self: Inode) ![]const u8 {
else => Error.NotSymlink, else => Error.NotSymlink,
}; };
} }
// Get inode's gid /// Get inode's gid
pub fn gid(self: Inode, alloc: std.mem.Allocator, io: Io, fil: OffsetFile, decomp: *const Decompressor, id_table_start: u64) !u16 { pub fn gid(self: Inode, alloc: std.mem.Allocator, io: Io, fil: OffsetFile, decomp: *const Decompressor, id_table_start: u64) !u16 {
return LookupTable.lookupValue(u16, alloc, io, decomp, fil, id_table_start, self.hdr.gid_idx); return LookupTable.lookupValue(u16, alloc, io, decomp, fil, id_table_start, self.hdr.gid_idx);
} }
// Get inode's uid /// Get inode's uid
pub fn uid(self: Inode, alloc: std.mem.Allocator, io: Io, fil: OffsetFile, decomp: *const Decompressor, id_table_start: u64) !u16 { pub fn uid(self: Inode, alloc: std.mem.Allocator, io: Io, fil: OffsetFile, decomp: *const Decompressor, id_table_start: u64) !u16 {
return LookupTable.lookupValue(u16, alloc, io, decomp, fil, id_table_start, self.hdr.uid_idx); return LookupTable.lookupValue(u16, alloc, io, decomp, fil, id_table_start, self.hdr.uid_idx);
} }
/// Get the inode's xattr values as an index into the Archive's xattr table.
/// Returns error.NoXattr if the inode doesn't have extended attributes.
pub fn xattrIndex(self: Inode) !u32 { pub fn xattrIndex(self: Inode) !u32 {
return switch (self.data) {
.ext_dir => |e| e.xattr_idx,
.ext_file => |e| e.xattr_idx,
.ext_symlink => |e| e.xattr_idx,
.ext_block_dev => |e| e.xattr_idx,
.ext_char_dev => |e| e.xattr_idx,
.ext_fifo => |e| e.xattr_idx,
.ext_socket => |e| e.xattr_idx,
else => Error.NotExtended,
};
}
// Get an inode's xattr values. If the inode does not have xattr values (including if the inode is not an extended type), an empty slice is returned.
pub fn xattrValues(self: Inode, alloc: std.mem.Allocator, io: Io, fil: OffsetFile, decomp: *const Decompressor, xattr_table_start: u64) ![]XattrTable.XattrOwned {
const idx = switch (self.data) { const idx = switch (self.data) {
.ext_dir => |e| e.xattr_idx, .ext_dir => |e| e.xattr_idx,
.ext_file => |e| e.xattr_idx, .ext_file => |e| e.xattr_idx,
@@ -146,9 +135,14 @@ pub fn xattrValues(self: Inode, alloc: std.mem.Allocator, io: Io, fil: OffsetFil
.ext_char_dev => |e| e.xattr_idx, .ext_char_dev => |e| e.xattr_idx,
.ext_fifo => |e| e.xattr_idx, .ext_fifo => |e| e.xattr_idx,
.ext_socket => |e| e.xattr_idx, .ext_socket => |e| e.xattr_idx,
else => return &[0]XattrTable.XattrOwned{}, else => Error.NoXattr,
}; };
if (idx == 0xFFFFFFFF) return &[0]XattrTable.XattrOwned{}; if (idx == 0xFFFFFFFF) return Error.NoXattr;
return idx;
}
// Get an inode's xattr values. If the inode does not have xattr values (including if the inode is not an extended type), an empty slice is returned.
pub fn xattrValues(self: Inode, alloc: std.mem.Allocator, io: Io, fil: OffsetFile, decomp: *const Decompressor, xattr_table_start: u64) ![]XattrTable.XattrOwned {
const idx = self.xattrIndex() catch &[0]XattrTable.XattrOwned{};
return XattrTable.statelessLookup(alloc, io, decomp, fil, xattr_table_start, idx); return XattrTable.statelessLookup(alloc, io, decomp, fil, xattr_table_start, idx);
} }
@@ -214,7 +208,21 @@ pub const Header = extern struct {
const FileRet = struct { const FileRet = struct {
file: Io.File, file: Io.File,
inode: Inode, permissions: u16,
uid_idx: u16,
gid_idx: u16,
xattr_idx: ?u32,
};
const PathRet = struct {
path: []const u8,
permissions: u16,
uid_idx: u16,
gid_idx: u16,
xattr_idx: ?u32,
};
const ReturnUnion = union(enum) {
file_ret: anyerror!FileRet,
path_ret: anyerror!PathRet,
}; };
const Tables = struct { const Tables = struct {
id: LookupTable.CachedTable(u16), id: LookupTable.CachedTable(u16),
@@ -247,12 +255,12 @@ pub fn extract(self: Inode, alloc: std.mem.Allocator, io: Io, fil: OffsetFile, s
var cache: Io.Queue([1024 * 1024]u8) = .init(cache_buf); var cache: Io.Queue([1024 * 1024]u8) = .init(cache_buf);
defer cache.close(io); defer cache.close(io);
const sel_buf: []anyerror!FileRet = try alloc.alloc(anyerror!FileRet, 10); const sel_buf: []ReturnUnion = try alloc.alloc(ReturnUnion, 10);
var group: Io.Select(anyerror!FileRet) = .init(io, sel_buf); var group: Io.Select(ReturnUnion) = .init(io, sel_buf);
defer group.cancelDiscard(); defer group.cancelDiscard();
switch (self.hdr.inode_type) { switch (self.hdr.inode_type) {
.dir, .ext_dir => group.async(FileRet, extractDir, .{ .dir, .ext_dir => group.async(.file_ret, extractDir, .{
self, self,
alloc, alloc,
io, io,
@@ -267,7 +275,7 @@ pub fn extract(self: Inode, alloc: std.mem.Allocator, io: Io, fil: OffsetFile, s
&que, &que,
&cache, &cache,
}), }),
.file, .ext_file => group.async(io, extractRegFile, .{ .file, .ext_file => group.async(.file_ret, extractRegFile, .{
self, self,
alloc, alloc,
io, io,
@@ -279,8 +287,8 @@ pub fn extract(self: Inode, alloc: std.mem.Allocator, io: Io, fil: OffsetFile, s
&que, &que,
&cache, &cache,
}), }),
.symlink, .ext_symlink => group.async(io, extractSymlink, .{ self, alloc, io, path, options, &que }), .symlink, .ext_symlink => group.async(.file_ret, extractSymlink, .{ self, alloc, io, path, options, &que }),
else => group.async(io, extractDevice, .{ self, alloc, io, path, options, &que }), else => group.async(.file_ret, extractDevice, .{ self, alloc, io, path, options, &que }),
} }
var id_table: LookupTable.CachedTable(u16) = .init(alloc, fil, decomp.decompressor(), super.id_start, super.id_count); var id_table: LookupTable.CachedTable(u16) = .init(alloc, fil, decomp.decompressor(), super.id_start, super.id_count);
@@ -340,7 +348,7 @@ fn extractDir(
alloc.free(dirs); alloc.free(dirs);
} }
var group: Io.Group = .init; var group: Io.Select() = .init;
defer group.cancel(io); defer group.cancel(io);
for (dirs) |d| { for (dirs) |d| {