Started work on xattr table reading
This commit is contained in:
+91
-14
@@ -5,15 +5,14 @@ const util = @import("utils/util.zig");
|
||||
|
||||
const MetadataReader = @import("utils/meta.zig");
|
||||
const Decomp = @import("decomp.zig");
|
||||
const Reference = @import("inode.zig").Reference;
|
||||
|
||||
pub fn Table(comptime T: type) type {
|
||||
pub fn Lookup(comptime T: type) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
|
||||
const ITEMS_PER_BLOCK = 8192 / @sizeOf(T);
|
||||
|
||||
alloc: std.mem.Allocator,
|
||||
|
||||
data: []u8,
|
||||
decomp: Decomp.Fn,
|
||||
|
||||
@@ -33,18 +32,18 @@ pub fn Table(comptime T: type) type {
|
||||
|
||||
.start = start,
|
||||
.count = count,
|
||||
.block_count = std.math.divCeil(u32, count, ITEMS_PER_BLOCK),
|
||||
.block_count = try std.math.divCeil(u32, count, ITEMS_PER_BLOCK),
|
||||
};
|
||||
}
|
||||
pub fn deinit(self: *Self) void {
|
||||
pub fn deinit(self: *Self, alloc: std.mem.Allocator) void {
|
||||
var iter = self.table.valueIterator();
|
||||
while (iter.next()) |block|
|
||||
self.alloc.free(block);
|
||||
alloc.free(block);
|
||||
|
||||
self.table.deinit(self.alloc);
|
||||
self.table.deinit(alloc);
|
||||
}
|
||||
|
||||
fn getBlock(self: *Self, io: Io, idx: u32) ![]T {
|
||||
fn getBlock(self: *Self, alloc: std.mem.Allocator, io: Io, idx: u32) ![]T {
|
||||
const init_get = self.table.get(idx);
|
||||
if (init_get != null) return init_get.?;
|
||||
|
||||
@@ -55,26 +54,104 @@ pub fn Table(comptime T: type) type {
|
||||
|
||||
const len = if (idx == self.block_count - 1) self.count % ITEMS_PER_BLOCK else ITEMS_PER_BLOCK;
|
||||
|
||||
const new_block = try self.alloc.alloc(T, len);
|
||||
errdefer self.alloc.free(new_block);
|
||||
const new_block = try alloc.alloc(T, len);
|
||||
errdefer alloc.free(new_block);
|
||||
|
||||
var meta: MetadataReader = .init(self.alloc, self.data[start..], self.decomp);
|
||||
var meta: MetadataReader = .init(alloc, self.data[start..], self.decomp);
|
||||
|
||||
try meta.interface.readSliceEndian(T, new_block, .little);
|
||||
|
||||
try self.table.put(self.alloc, idx, new_block);
|
||||
try self.table.put(alloc, idx, new_block);
|
||||
|
||||
return new_block;
|
||||
}
|
||||
|
||||
pub fn get(self: *Self, io: Io, idx: u32) !T {
|
||||
pub fn get(self: *Self, alloc: std.mem.Allocator, io: Io, idx: u32) !T {
|
||||
if (idx >= self.count) return error.InvalidIndex;
|
||||
|
||||
const block_idx = idx / ITEMS_PER_BLOCK;
|
||||
|
||||
const block = self.getBlock(io, block_idx);
|
||||
const block = self.getBlock(io, alloc, block_idx);
|
||||
|
||||
return block[idx % ITEMS_PER_BLOCK];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub const Xattr = struct {
|
||||
kv_start: u64,
|
||||
lookup: Lookup(XattrLookup),
|
||||
|
||||
pub fn init(alloc: std.mem.Allocator, data: []u8, decomp: Decomp.Fn, start: u64) !Xattr {
|
||||
const kv_start = util.readValue(u64, data[start..][0..8]);
|
||||
const count = util.readValue(u32, data[start..][8..12]);
|
||||
|
||||
return .{
|
||||
.kv_start = kv_start,
|
||||
.lookup = try .init(alloc, data, decomp, start + 16, count),
|
||||
};
|
||||
}
|
||||
pub fn deinit(self: *Xattr, alloc: std.mem.Allocator) void {
|
||||
self.lookup.deinit(alloc);
|
||||
}
|
||||
|
||||
pub fn get(self: *Xattr, alloc: std.mem.Allocator, io: Io, idx: u32) !KV {
|
||||
const lookup = try self.lookup.get(alloc, io, idx);
|
||||
|
||||
var meta: MetadataReader = .init(alloc, self.lookup.data[self.kv_start + lookup.ref.start ..], self.lookup.decomp);
|
||||
try meta.interface.discardAll(lookup.ref.offset);
|
||||
|
||||
const kvs = try alloc.alloc(KV, lookup.count);
|
||||
errdefer alloc.free(kvs);
|
||||
|
||||
for (kvs) |*kv| {
|
||||
const entry = try util.readValueRdr(KeyEntry, &meta.interface);
|
||||
|
||||
const prefix = switch (entry.type.type) {
|
||||
.user => "user.",
|
||||
.trusted => "trusted.",
|
||||
.security => "security.",
|
||||
};
|
||||
|
||||
kv.name = try alloc.allocSentinel(u8, entry.name_size + prefix.len, 0);
|
||||
errdefer alloc.free(kv.name);
|
||||
|
||||
try meta.interface.readSliceEndian(u8, kv.name[prefix.len..], .little);
|
||||
|
||||
@memcpy(kv.name[0..prefix.len], prefix);
|
||||
|
||||
if (entry.type.out_of_line) {}
|
||||
}
|
||||
}
|
||||
|
||||
//types
|
||||
|
||||
pub const KV = struct {
|
||||
name: [:0]u8,
|
||||
value: []u8,
|
||||
|
||||
pub fn deinit(self: KV, alloc: std.mem.Allocator) void {
|
||||
alloc.free(self.name);
|
||||
alloc.free(self.value);
|
||||
}
|
||||
};
|
||||
|
||||
const XattrLookup = extern struct {
|
||||
ref: Reference,
|
||||
count: u32,
|
||||
size: u32,
|
||||
};
|
||||
|
||||
const KeyEntry = extern struct {
|
||||
type: packed struct(u16) {
|
||||
type: enum(u8) {
|
||||
user,
|
||||
trusted,
|
||||
security,
|
||||
},
|
||||
out_of_line: bool,
|
||||
_: u7,
|
||||
},
|
||||
name_size: u16,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -7,12 +7,17 @@ const Decomp = @import("../decomp.zig");
|
||||
const Directory = @import("../dir.zig");
|
||||
const MetadataReader = @import("meta.zig");
|
||||
const DataReader = @import("data_reader.zig");
|
||||
const Table = @import("../table.zig");
|
||||
const Super = @import("../archive.zig").Super;
|
||||
|
||||
pub fn single(alloc: std.mem.Allocator, io: Io, data: []const u8, decomp: Decomp.Fn, super: Super, inode: Inode, filepath: []const u8, options: Options) !void {
|
||||
const path = std.mem.trim(u8, filepath, "/");
|
||||
|
||||
var pool: std.ArrayList(InodeAndPath) = .initBuffer(&.{.{ .inode = inode, .path = path }});
|
||||
var pool: std.ArrayList(InodeAndPath) = .initBuffer(&.{.{
|
||||
.inode = inode,
|
||||
.path = path,
|
||||
.root = true,
|
||||
}});
|
||||
defer {
|
||||
while (pool.pop()) |in|
|
||||
in.deinit(in);
|
||||
@@ -55,7 +60,11 @@ pub fn single(alloc: std.mem.Allocator, io: Io, data: []const u8, decomp: Decomp
|
||||
return err;
|
||||
};
|
||||
|
||||
try pool.append(alloc, .{ .inode = new_inode, .path = new_path });
|
||||
try pool.append(alloc, .{
|
||||
.inode = new_inode,
|
||||
.path = new_path,
|
||||
.root = false,
|
||||
});
|
||||
}
|
||||
|
||||
try dirs.append(alloc, in);
|
||||
@@ -136,13 +145,20 @@ pub fn single(alloc: std.mem.Allocator, io: Io, data: []const u8, decomp: Decomp
|
||||
// TODO: apply permissions & xattrs
|
||||
}
|
||||
}
|
||||
pub fn multi() !void {}
|
||||
|
||||
// Utils
|
||||
|
||||
const InodeAndPath = struct {
|
||||
inode: Inode,
|
||||
path: []const u8,
|
||||
root: bool,
|
||||
|
||||
fn deinit(self: InodeAndPath, alloc: std.mem.Allocator) void {
|
||||
if (self.root) return;
|
||||
self.inode.deinit(alloc);
|
||||
alloc.free(self.path);
|
||||
}
|
||||
};
|
||||
pub fn multi() !void {}
|
||||
|
||||
inline fn applyPermissions(alloc: std.mem.Allocator, io: Io, id_table: Table.Lookup(u16), xattr_table: Table.Xattr, inode: Inode, path: []const u8, options: Options) !void {}
|
||||
|
||||
Reference in New Issue
Block a user