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 MetadataReader = @import("utils/meta.zig");
|
||||||
const Decomp = @import("decomp.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 {
|
return struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
const ITEMS_PER_BLOCK = 8192 / @sizeOf(T);
|
const ITEMS_PER_BLOCK = 8192 / @sizeOf(T);
|
||||||
|
|
||||||
alloc: std.mem.Allocator,
|
|
||||||
|
|
||||||
data: []u8,
|
data: []u8,
|
||||||
decomp: Decomp.Fn,
|
decomp: Decomp.Fn,
|
||||||
|
|
||||||
@@ -33,18 +32,18 @@ pub fn Table(comptime T: type) type {
|
|||||||
|
|
||||||
.start = start,
|
.start = start,
|
||||||
.count = count,
|
.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();
|
var iter = self.table.valueIterator();
|
||||||
while (iter.next()) |block|
|
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);
|
const init_get = self.table.get(idx);
|
||||||
if (init_get != null) return init_get.?;
|
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 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);
|
const new_block = try alloc.alloc(T, len);
|
||||||
errdefer self.alloc.free(new_block);
|
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 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;
|
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;
|
if (idx >= self.count) return error.InvalidIndex;
|
||||||
|
|
||||||
const block_idx = idx / ITEMS_PER_BLOCK;
|
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];
|
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 Directory = @import("../dir.zig");
|
||||||
const MetadataReader = @import("meta.zig");
|
const MetadataReader = @import("meta.zig");
|
||||||
const DataReader = @import("data_reader.zig");
|
const DataReader = @import("data_reader.zig");
|
||||||
|
const Table = @import("../table.zig");
|
||||||
const Super = @import("../archive.zig").Super;
|
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 {
|
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, "/");
|
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 {
|
defer {
|
||||||
while (pool.pop()) |in|
|
while (pool.pop()) |in|
|
||||||
in.deinit(in);
|
in.deinit(in);
|
||||||
@@ -55,7 +60,11 @@ pub fn single(alloc: std.mem.Allocator, io: Io, data: []const u8, decomp: Decomp
|
|||||||
return err;
|
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);
|
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
|
// TODO: apply permissions & xattrs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn multi() !void {}
|
||||||
|
|
||||||
|
// Utils
|
||||||
|
|
||||||
const InodeAndPath = struct {
|
const InodeAndPath = struct {
|
||||||
inode: Inode,
|
inode: Inode,
|
||||||
path: []const u8,
|
path: []const u8,
|
||||||
|
root: bool,
|
||||||
|
|
||||||
fn deinit(self: InodeAndPath, alloc: std.mem.Allocator) void {
|
fn deinit(self: InodeAndPath, alloc: std.mem.Allocator) void {
|
||||||
|
if (self.root) return;
|
||||||
self.inode.deinit(alloc);
|
self.inode.deinit(alloc);
|
||||||
alloc.free(self.path);
|
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