diff --git a/src/archive.zig b/src/archive.zig index 3f96367..2038ce0 100644 --- a/src/archive.zig +++ b/src/archive.zig @@ -70,10 +70,7 @@ pub fn extract(self: Archive, alloc: std.mem.Allocator, io: Io, extract_dir: []c self.super.block_size, self.super.root_ref, ); - _ = root_inode; - _ = extract_dir; - _ = options; - return error.TODO; + return root_inode.extract(alloc, io, self.file, self.super, extract_dir, options); } /// Returns the inode with the given inode number. diff --git a/src/bin/unsquashfs.zig b/src/bin/unsquashfs.zig index 6e4d810..69f4df3 100644 --- a/src/bin/unsquashfs.zig +++ b/src/bin/unsquashfs.zig @@ -18,7 +18,7 @@ const help_mgs = \\ -dx Don't set xattr values \\ -dp Don't set permissions (includes setting uid & gid owner) \\ - \\ -p Specify how many threads to use. If no present or zero, the system's logical cores count is used. + \\ -p Specify how many threads to use. If not present or zero, the system's logical cores count is used. \\ -v Verbose \\ \\ --force Force extraction. If the destination already exists, it will be deleted. @@ -42,18 +42,23 @@ var force: bool = false; pub fn main(init: std.process.Init) !void { const alloc = init.gpa; const io = init.io; + var stdout = std.Io.File.stdout(); + defer stdout.close(io); var out = stdout.writer(io, &[0]u8{}); defer out.interface.flush() catch {}; + try handleArgs(init.minimal.args, &out.interface); if (archive.len == 0) { try out.interface.print("You must provide a squashfs archive\n", .{}); try out.interface.print(help_mgs, .{}); return; } + var fil = try Io.Dir.cwd().openFile(io, archive, .{}); //TODO: Handle error gracefully. defer fil.close(io); - var arc: squashfs.Archive = try .init(io, fil, offset); //TODO: Update when memory size matters. //TODO: Handle error gracefully. + + var arc: squashfs.Archive = try .init(io, fil, offset); //TODO: Handle error gracefully. const options: squashfs.ExtractionOptions = .{ .threads = if (threads == 0) try std.Thread.getCpuCount() else threads, .verbose = verbose, @@ -61,6 +66,7 @@ pub fn main(init: std.process.Init) !void { .ignore_xattr = ignore_xattrs, .ignore_permissions = ignore_permissions, }; + if (force) try Io.Dir.cwd().deleteTree(io, extLoc); try arc.extract(alloc, io, extLoc, options); //TODO: Handle error gracefully. diff --git a/src/decomp.zig b/src/decomp.zig new file mode 100644 index 0000000..cb218bf --- /dev/null +++ b/src/decomp.zig @@ -0,0 +1,32 @@ +const std = @import("std"); + +const Decompressor = @import("util/decompressor.zig"); + +pub const Decomp = union(enum) { + gzip: @import("decomp/zlib.zig"), + lzma: @import("decomp/lzma.zig"), + lzo: void, + xz: @import("decomp/xz.zig"), + lz4: void, + zstd: @import("decomp/zstd.zig"), + + pub fn deinit(self: *Decomp) void { + switch (self.*) { + .gzip => self.gzip.deinit(), + .lzma => self.lzma.deinit(), + .xz => self.xz.deinit(), + .zstd => self.zstd.deinit(), + else => unreachable, + } + } + + pub fn decompressor(self: *Decomp) *Decompressor { + return switch (self.*) { + .gzip => &self.gzip.interface, + .lzma => &self.lzma.interface, + .xz => &self.xz.interface, + .zstd => &self.zstd.interface, + else => unreachable, + }; + } +}; diff --git a/src/decomp/lzma.zig b/src/decomp/lzma.zig index 4a720ce..fa8a74f 100644 --- a/src/decomp/lzma.zig +++ b/src/decomp/lzma.zig @@ -29,9 +29,9 @@ pub fn init(alloc: std.mem.Allocator, block_size: u32) !Self { .buffers = try .initCapacity(alloc, 5), }; } -pub fn deinit(self: Self) void { - for (self.buffers) |buf| - self.alloc.free(buf); +pub fn deinit(self: *Self) void { + for (self.buffers.items) |buf| + self.alloc.free(buf.buf); self.buffers.deinit(self.alloc); } diff --git a/src/decomp/xz.zig b/src/decomp/xz.zig index aef9ecd..d13ff3e 100644 --- a/src/decomp/xz.zig +++ b/src/decomp/xz.zig @@ -29,9 +29,9 @@ pub fn init(alloc: std.mem.Allocator, block_size: u32) !Self { .buffers = try .initCapacity(alloc, 5), }; } -pub fn deinit(self: Self) void { - for (self.buffers) |buf| - self.alloc.free(buf); +pub fn deinit(self: *Self) void { + for (self.buffers.items) |buf| + self.alloc.free(buf.buf); self.buffers.deinit(self.alloc); } diff --git a/src/decomp/zlib.zig b/src/decomp/zlib.zig index d155b13..8f11a7b 100644 --- a/src/decomp/zlib.zig +++ b/src/decomp/zlib.zig @@ -29,9 +29,9 @@ pub fn init(alloc: std.mem.Allocator, block_size: u32) !Self { .buffers = try .initCapacity(alloc, 5), }; } -pub fn deinit(self: Self) void { - for (self.buffers) |buf| - self.alloc.free(buf); +pub fn deinit(self: *Self) void { + for (self.buffers.items) |buf| + self.alloc.free(buf.buf); self.buffers.deinit(self.alloc); } diff --git a/src/decomp/zstd.zig b/src/decomp/zstd.zig index 8b675c1..33998bc 100644 --- a/src/decomp/zstd.zig +++ b/src/decomp/zstd.zig @@ -29,9 +29,9 @@ pub fn init(alloc: std.mem.Allocator, block_size: u32) !Self { .buffers = try .initCapacity(alloc, 5), }; } -pub fn deinit(self: Self) void { - for (self.buffers) |buf| - self.alloc.free(buf); +pub fn deinit(self: *Self) void { + for (self.buffers.items) |buf| + self.alloc.free(buf.buf); self.buffers.deinit(self.alloc); } diff --git a/src/inode.zig b/src/inode.zig index 0d3035e..934a6ad 100644 --- a/src/inode.zig +++ b/src/inode.zig @@ -5,6 +5,7 @@ const Reader = std.Io.Reader; const Io = std.Io; const Archive = @import("archive.zig"); +const Decomp = @import("decomp.zig").Decomp; const DirEntry = @import("directory.zig"); const ExtractionOptions = @import("options.zig"); const FragEntry = @import("frag.zig").FragEntry; @@ -163,7 +164,7 @@ pub const Error = error{ pub const Ref = packed struct(u64) { block_offset: u16, block_start: u32, - _: u16, + _: u16 = 0, }; pub const Type = enum(u16) { @@ -222,60 +223,73 @@ const Tables = struct { }; pub fn extract(self: Inode, alloc: std.mem.Allocator, io: Io, fil: OffsetFile, super: Archive.Superblock, path: []const u8, options: ExtractionOptions) !void { - var decomp = switch (super.compression) { - .gzip => try @import("decomp/zlib.zig").init(alloc, super.block_size), - .lzma => try @import("decomp/lzma.zig").init(alloc, super.block_size), - .xz => try @import("decomp/xz.zig").init(alloc, super.block_size), - .zstd => try @import("decomp/zstd.zig").init(alloc, super.block_size), + var decomp: Decomp = switch (super.compression) { + .gzip => .{ .gzip = try @import("decomp/zlib.zig").init(alloc, super.block_size) }, + .lzma => .{ .lzma = try @import("decomp/lzma.zig").init(alloc, super.block_size) }, + .xz => .{ .xz = try @import("decomp/xz.zig").init(alloc, super.block_size) }, + .zstd => .{ .zstd = try @import("decomp/zstd.zig").init(alloc, super.block_size) }, else => unreachable, }; defer decomp.deinit(); - var frag_table: LookupTable.CachedTable(FragEntry) = .init(alloc, fil, &decomp.interface, super.frag_start, super.frag_count); + var frag_table: LookupTable.CachedTable(FragEntry) = .init(alloc, fil, decomp.decompressor(), super.frag_start, super.frag_count); defer frag_table.deinit(io); - var group: Io.Group = .init; - defer group.cancel(io); - var que: Io.Queue(FileRet) = .init(&[1]FileRet{undefined} ** 12); + // var group: Io.Group = .init; + // defer group.cancel(io); + + var que_arr = [1]FileRet{undefined} ** 12; + var que: Io.Queue(FileRet) = .init(&que_arr); defer que.close(io); + const cache_buf = try alloc.alloc([1024 * 1024]u8, 12); + defer alloc.free(cache_buf); + var cache: Io.Queue([1024 * 1024]u8) = .init(cache_buf); + defer cache.close(io); + + const sel_buf: []anyerror!FileRet = try alloc.alloc(anyerror!FileRet, 10); + var group: Io.Select(anyerror!FileRet) = .init(io, sel_buf); + defer group.cancelDiscard(); + switch (self.hdr.inode_type) { - .dir, .ext_dir => group.async(io, extractDir, .{ + .dir, .ext_dir => group.async(FileRet, extractDir, .{ self, alloc, io, fil, - &decomp.interface, + decomp.decompressor(), &frag_table, super.block_size, super.dir_start, + super.inode_start, path, options, &que, + &cache, }), .file, .ext_file => group.async(io, extractRegFile, .{ self, alloc, io, - file, - &decomp.interface, + fil, + decomp.decompressor(), &frag_table, super.block_size, path, - options, &que, + &cache, }), - .symlink, .ext_symlink => group.async(Io, extractSymlink, .{ self, io, path, options, &que }), - else => group.async(io, extractDevice, .{ self, alloc, io, super, path, options, &que }), + .symlink, .ext_symlink => group.async(io, extractSymlink, .{ self, alloc, io, path, options, &que }), + else => group.async(io, extractDevice, .{ self, alloc, io, path, options, &que }), } - var id_table: LookupTable.CachedTable(u16) = .init(alloc, fil, decomp, super.id_start, super.id_count); + var id_table: LookupTable.CachedTable(u16) = .init(alloc, fil, decomp.decompressor(), super.id_start, super.id_count); defer id_table.deinit(io); - var xattr_table: XattrTable = try .init(alloc, io, fil, decomp, super.xattr_start); + var xattr_table: XattrTable = try .init(alloc, io, fil, decomp.decompressor(), super.xattr_start); defer xattr_table.deinit(io); - for (que.getOne(io)) |res| { - const ret = res catch break; + while (true) { + const ret = que.getOne(io) catch break; const inode: Inode = ret.inode; defer inode.deinit(alloc); @@ -284,23 +298,25 @@ pub fn extract(self: Inode, alloc: std.mem.Allocator, io: Io, fil: OffsetFile, s if (!options.ignore_xattr) { if (inode.xattrIndex()) |idx| { - const xattrs = try xattr_table.get(io, idx); + const xattrs = try xattr_table.get(alloc, io, idx); for (xattrs) |x| { // TODO: Check error. const xattr_res = std.os.linux.fsetxattr(ret_file.handle, x.key, x.value.ptr, x.value.len, 0); if (xattr_res != 0 and options.verbose) options.verbose_writer.?.print("setxattr failed with code: {}\n", .{xattr_res}) catch {}; + alloc.free(x.key); } - } + alloc.free(xattrs); + } else |_| {} } if (!options.ignore_permissions) { - try ret_file.setPermissions(io, inode.hdr.permissions); + try ret_file.setPermissions(io, @enumFromInt(inode.hdr.permissions)); try ret_file.setOwner(io, try id_table.get(io, inode.hdr.uid_idx), try id_table.get(io, inode.hdr.gid_idx)); } if (!que.type_erased.closed and group.token.raw == null) que.close(io); } } -pub fn extractDir( +fn extractDir( self: Inode, alloc: std.mem.Allocator, io: Io, @@ -313,6 +329,7 @@ pub fn extractDir( path: []const u8, options: ExtractionOptions, que: *Io.Queue(FileRet), + cache: *Io.Queue([1024 * 1024]u8), ) !void { defer alloc.free(path); @@ -341,28 +358,30 @@ pub fn extractDir( alloc, io, fil, - &decomp.interface, - &frag, + decomp, + frag, block_size, dir_start, + inode_start, new_path, options, - &que, + que, + cache, }), .file, .ext_file => group.async(io, extractRegFile, .{ self, alloc, io, - file, - &decomp.interface, - &frag, + fil, + decomp, + frag, block_size, new_path, - options, - &que, + que, + cache, }), - .symlink, .ext_symlink => group.async(Io, extractSymlink, .{ self, alloc, io, new_path, options, &que }), - else => group.async(io, extractDevice, .{ self, alloc, io, new_path, options, &que }), + .symlink, .ext_symlink => group.async(io, extractSymlink, .{ self, alloc, io, new_path, options, que }), + else => group.async(io, extractDevice, .{ self, alloc, io, new_path, options, que }), } } @@ -370,7 +389,7 @@ pub fn extractDir( try que.putOne(io, .{ .file = try Io.Dir.cwd().openFile(io, path, .{}), .inode = self }); } -pub fn extractRegFile( +fn extractRegFile( self: Inode, alloc: std.mem.Allocator, io: Io, @@ -379,13 +398,12 @@ pub fn extractRegFile( frag: *LookupTable.CachedTable(FragEntry), block_size: u32, path: []const u8, - options: ExtractionOptions, que: *Io.Queue(FileRet), + cache: *Io.Queue([1024 * 1024]u8), ) !void { - _ = options; defer alloc.free(path); - const atom = try Io.Dir.cwd().createFileAtomic(io, path, .{}); + var atom = try Io.Dir.cwd().createFileAtomic(io, path, .{}); defer atom.deinit(io); var size: u64 = undefined; @@ -411,7 +429,7 @@ pub fn extractRegFile( else => unreachable, } - const ext: DataExtractor = .init(fil, decomp, block_size, size, start, blocks); + var ext: DataExtractor = .init(fil, decomp, cache, block_size, size, start, blocks); ext.addFrag(frag_offset, try frag.get(io, frag_idx)); var group: Io.Group = .init; @@ -425,7 +443,7 @@ pub fn extractRegFile( try que.putOne(io, .{ .file = atom.file, .inode = self }); } -pub fn extractSymlink( +fn extractSymlink( self: Inode, alloc: std.mem.Allocator, io: Io, @@ -444,7 +462,7 @@ pub fn extractSymlink( // TODO: On Linux you can't set permission & xattrs on symlinks (they inherit from their target), but on Mac you can. } -pub fn extractDevice( +fn extractDevice( self: Inode, alloc: std.mem.Allocator, io: Io, @@ -481,7 +499,7 @@ pub fn extractDevice( const sentinel_path = try std.mem.concatMaybeSentinel(alloc, u8, &[1][]const u8{path}, 0); defer alloc.free(sentinel_path); - const res = std.os.linux.mknod(sentinel_path, mode, dev); + const res = std.os.linux.mknod(@ptrCast(sentinel_path), mode, dev); if (res != 0 and options.verbose) options.verbose_writer.?.print("mknod failed with code: {}\n", .{res}) catch {}; diff --git a/src/inode_data/dir.zig b/src/inode_data/dir.zig index 6b45db0..2538dc7 100644 --- a/src/inode_data/dir.zig +++ b/src/inode_data/dir.zig @@ -21,7 +21,7 @@ pub const ExtDir = extern struct { parent_num: u32, idx_count: u16, block_offset: u16, - xattr_id: u32, + xattr_idx: u32, // index: []DirIndex pub fn read(rdr: *Reader) !ExtDir { diff --git a/src/lookup_table.zig b/src/lookup_table.zig index f2480b4..e60a476 100644 --- a/src/lookup_table.zig +++ b/src/lookup_table.zig @@ -75,14 +75,17 @@ pub fn CachedTable(comptime T: anytype) type { try rdr.interface.readSliceEndian(u64, @ptrCast(&offset), .little); const len: u16 = if (self.total_num % T_PER_BLOCK != 0 and block == (self.total_num - 1) / T_PER_BLOCK) - self.total_num % T_PER_BLOCK + @truncate(self.total_num % T_PER_BLOCK) else T_PER_BLOCK; rdr = try self.fil.readerAt(io, offset, &[0]u8{}); - var meta: MetadataReader = .init(self.alloc, &rdr, self.decomp); + var meta: MetadataReader = .init(self.alloc, &rdr.interface, self.decomp); - try self.table.put(block, try meta.interface.readSliceEndianAlloc(self.alloc, T, len, .little)); + const slice = try meta.interface.readSliceEndianAlloc(self.alloc, T, len, .little); + try self.table.put(block, slice); + + return slice[block_offset]; } }; } diff --git a/src/options.zig b/src/options.zig index c139c62..44cb816 100644 --- a/src/options.zig +++ b/src/options.zig @@ -6,7 +6,7 @@ const Writer = std.Io.Writer; const ExtractionOptions = @This(); /// The number of threads used for extraction. 0 implies single threaded. -threads: usize = 1, +threads: usize = 1, // TODO: Update to better integrate with zig 0.16 Io. Maybe limit to only single or multi-threaded. /// Don't set the file's owner & permissions after extraction ignore_permissions: bool = false, /// Don't set xattr values. Currently xattrs are never set anyway. diff --git a/src/util/data_extractor.zig b/src/util/data_extractor.zig index eb0bbdc..a3fff8b 100644 --- a/src/util/data_extractor.zig +++ b/src/util/data_extractor.zig @@ -7,13 +7,14 @@ const FragEntry = @import("../frag.zig").FragEntry; const BlockSize = @import("../inode_data/file.zig").BlockSize; const Decompressor = @import("decompressor.zig"); const OffsetFile = @import("offset_file.zig"); -const SharedCache = @import("shared_cache.zig"); + +// const SharedCache = @import("shared_cache.zig"); const DataExtractor = @This(); fil: OffsetFile, -// cache: *SharedCache, decomp: *const Decompressor, +cache: *Io.Queue([1024 * 1024]u8), block_size: u32, file_size: u64, @@ -23,11 +24,11 @@ blocks: []BlockSize, frag_offset: u32 = 0, frag_entry: ?FragEntry = null, -pub fn init(fil: OffsetFile, decomp: *const Decompressor, block_size: u32, file_size: u64, data_start: u64, blocks: []BlockSize) DataExtractor { +pub fn init(fil: OffsetFile, decomp: *const Decompressor, cache: *Io.Queue([1024 * 1024]u8), block_size: u32, file_size: u64, data_start: u64, blocks: []BlockSize) DataExtractor { return .{ .fil = fil, - // .cache = cache, .decomp = decomp, + .cache = cache, .block_size = block_size, .file_size = file_size, @@ -57,7 +58,7 @@ pub fn extractAsync(self: DataExtractor, alloc: std.mem.Allocator, io: Io, group group.async(io, fragThread, .{ self, alloc, io, fil }); } -fn blockThread(self: DataExtractor, alloc: std.mem.Allocator, io: Io, fil: Io.File, read_offset: u64, idx: u32) !void { +fn blockThread(self: DataExtractor, alloc: std.mem.Allocator, io: Io, fil: Io.File, read_offset: u64, idx: usize) !void { const block = self.blocks[idx]; const cur_block_size = if (idx == self.numBlocks() - 1) @@ -76,19 +77,19 @@ fn blockThread(self: DataExtractor, alloc: std.mem.Allocator, io: Io, fil: Io.Fi var rdr = try self.fil.readerAt(io, read_offset, &[0]u8{}); if (block.uncompressed) { - try rdr.interface.streamExact(&wrt, cur_block_size); + try rdr.interface.streamExact(&wrt.interface, cur_block_size); return; } else { @branchHint(.likely); - var cache = try self.cache.getCache(io); - defer self.cache.returnCache(cache); + var cache = try self.cache.getOne(io); + defer self.cache.putOne(io, cache) catch {}; - var tmp = try self.cache.getCache(io); - defer self.cache.returnCache(tmp); + var tmp = try self.cache.getOne(io); + defer self.cache.putOne(io, tmp) catch {}; - try rdr.interface.readSliceAll(cache.cache[0..block.size]); - _ = try self.decomp.Decompress(alloc, cache.cache[0..block.size], tmp.cache[0..cur_block_size]); - try wrt.interface.writeAll(tmp.cache[0..cur_block_size]); + try rdr.interface.readSliceAll(cache[0..block.size]); + _ = try self.decomp.Decompress(alloc, cache[0..block.size], tmp[0..cur_block_size]); + try wrt.interface.writeAll(tmp[0..cur_block_size]); } } fn fragThread(self: DataExtractor, alloc: std.mem.Allocator, io: Io, fil: Io.File) !void { @@ -102,18 +103,18 @@ fn fragThread(self: DataExtractor, alloc: std.mem.Allocator, io: Io, fil: Io.Fil var rdr = try self.fil.readerAt(io, frag.start, &[0]u8{}); if (frag.size.uncompressed) { try rdr.interface.discardAll(self.frag_offset); - try rdr.interface.streamExact(&wrt, cur_block_size); + try rdr.interface.streamExact(&wrt.interface, cur_block_size); return; } else { @branchHint(.likely); - var cache = try self.cache.getCache(io); - defer self.cache.returnCache(cache); + var cache = try self.cache.getOne(io); + defer self.cache.putOne(io, cache) catch {}; - var tmp = try self.cache.getCache(io); - defer self.cache.returnCache(tmp); + var tmp = try self.cache.getOne(io); + defer self.cache.putOne(io, tmp) catch {}; - try rdr.interface.readSliceAll(cache.cache[0..frag.size.size]); - _ = try self.decomp.Decompress(alloc, cache.cache[0..frag.size.size], tmp.cache[0..self.block_size]); - try wrt.interface.writeAll(tmp.cache[0..cur_block_size]); + try rdr.interface.readSliceAll(cache[0..frag.size.size]); + _ = try self.decomp.Decompress(alloc, cache[0..frag.size.size], tmp[0..self.block_size]); + try wrt.interface.writeAll(tmp[0..cur_block_size]); } } diff --git a/src/util/data_reader.zig b/src/util/data_reader.zig index 3a04e8f..09983ec 100644 --- a/src/util/data_reader.zig +++ b/src/util/data_reader.zig @@ -10,7 +10,8 @@ const FragEntry = @import("../frag.zig").FragEntry; const BlockSize = @import("../inode_data/file.zig").BlockSize; const Decompressor = @import("decompressor.zig"); const OffsetFile = @import("offset_file.zig"); -const SharedCache = @import("shared_cache.zig"); + +// const SharedCache = @import("shared_cache.zig"); const DataReader = @This(); @@ -18,8 +19,8 @@ alloc: std.mem.Allocator, fil: OffsetFile, io: Io, -// cache: *SharedCache, decomp: *const Decompressor, +cache: *Io.Queue([]u8), block_size: u32, file_size: u64, @@ -34,13 +35,14 @@ sparse_block: bool = false, interface: Io.Reader, -pub fn init(alloc: std.mem.Allocator, io: Io, fil: OffsetFile, decomp: *const Decompressor, block_size: u32, file_size: u64, data_start: u64, blocks: []BlockSize) !DataReader { +pub fn init(alloc: std.mem.Allocator, io: Io, fil: OffsetFile, decomp: *const Decompressor, cache: *Io.Queue([]u8), block_size: u32, file_size: u64, data_start: u64, blocks: []BlockSize) !DataReader { return .{ .alloc = alloc, .fil = fil, .io = io, .decomp = decomp, + .cache = cache, .block_size = block_size, .file_size = file_size, @@ -91,8 +93,8 @@ fn advanceBuffer(self: *DataReader) !void { try rdr.interface.readSliceAll(self.interface.buffer[0..self.interface.end]); } else { @branchHint(.likely); - const tmp = try self.cache.getCache(self.io); - defer self.cache.returnCache(tmp); + const tmp = try self.cache.getOne(self.io); + defer self.cache.putOne(tmp) catch {}; var rdr = try self.fil.readerAt(self.io, entry.start, &[0]u8{}); try rdr.interface.readSliceAll(tmp.cache[0..entry.size.size]); @@ -117,8 +119,8 @@ fn advanceBuffer(self: *DataReader) !void { self.cur_offset += self.interface.end; } else { @branchHint(.likely); - const tmp = try self.cache.getCache(self.io); - defer self.cache.returnCache(tmp); + const tmp = try self.cache.getOne(self.io); + defer self.cache.putOne(tmp) catch {}; var rdr = try self.fil.readerAt(self.io, self.cur_offset, &[0]u8{}); try rdr.interface.readSliceAll(tmp.cache[0..block.size]); diff --git a/src/xattr_table.zig b/src/xattr_table.zig index e97cb91..c12cc0a 100644 --- a/src/xattr_table.zig +++ b/src/xattr_table.zig @@ -18,7 +18,7 @@ kv_start: u64, table: LookupTable.CachedTable(TableValue), value_cache: std.AutoHashMap(InodeRef, []const u8), -value_mut: Io.Mutex, +value_mut: Io.Mutex = .init, pub fn init(alloc: std.mem.Allocator, io: Io, fil: OffsetFile, decomp: *const Decompressor, xattr_start: u64) !XattrCachedTable { var rdr = try fil.readerAt(io, xattr_start, &[0]u8{}); @@ -36,7 +36,7 @@ pub fn init(alloc: std.mem.Allocator, io: Io, fil: OffsetFile, decomp: *const De .kv_start = start, - .table = .init(alloc, fil, xattr_start + 16, num), + .table = .init(alloc, fil, decomp, xattr_start + 16, num), .value_cache = .init(alloc), }; } @@ -56,37 +56,39 @@ pub fn get(self: *XattrCachedTable, alloc: std.mem.Allocator, io: Io, idx: u32) errdefer alloc.free(out); for (0..lookup.count) |i| { - const key_entry: KeyEntry = undefined; + var key_entry: KeyEntry = undefined; try meta.interface.readSliceEndian(KeyEntry, @ptrCast(&key_entry), .little); - const key = switch (key_entry.type.namespace) { + const key: [:0]u8 = switch (key_entry.type.namespace) { .user => blk: { const tmp = try alloc.alloc(u8, key_entry.name_size + 1 + 5); errdefer alloc.free(tmp); try meta.interface.readSliceEndian(u8, tmp[5 .. tmp.len - 1], .little); - @memset(tmp[0..5], "user."); - break :blk tmp; + @memcpy(tmp[0..5], "user."); + tmp[tmp.len - 1] = 0; + break :blk @ptrCast(tmp); }, .trusted => blk: { const tmp = try alloc.alloc(u8, key_entry.name_size + 1 + 8); errdefer alloc.free(tmp); try meta.interface.readSliceEndian(u8, tmp[8 .. tmp.len - 1], .little); - @memset(tmp[0..8], "trusted."); - break :blk tmp; + @memcpy(tmp[0..8], "trusted."); + tmp[tmp.len - 1] = 0; + break :blk @ptrCast(tmp); }, .security => blk: { const tmp = try alloc.alloc(u8, key_entry.name_size + 1 + 9); errdefer alloc.free(tmp); try meta.interface.readSliceEndian(u8, tmp[9 .. tmp.len - 1], .little); - @memset(tmp[0..9], "security."); - break :blk tmp; + @memcpy(tmp[0..9], "security."); + tmp[tmp.len - 1] = 0; + break :blk @ptrCast(tmp); }, }; - key[key.len - 1] = 0; errdefer alloc.free(key); if (key_entry.type.out_of_line) { - const value: ValueOutOfLineEntry = undefined; + var value: ValueOutOfLineEntry = undefined; try meta.interface.readSliceEndian(ValueOutOfLineEntry, @ptrCast(&value), .little); out[i] = .{ @@ -95,7 +97,7 @@ pub fn get(self: *XattrCachedTable, alloc: std.mem.Allocator, io: Io, idx: u32) }; continue; } - const val_ref: InodeRef = .{ .block_start = meta.cur_block_start, .block_offset = meta.interface.seek }; + const val_ref: InodeRef = .{ .block_start = meta.cur_block_start, .block_offset = @truncate(meta.interface.seek) }; try self.value_mut.lock(io); defer self.value_mut.unlock(io); @@ -108,7 +110,7 @@ pub fn get(self: *XattrCachedTable, alloc: std.mem.Allocator, io: Io, idx: u32) } var val_size: u32 = undefined; - try meta.interface.readSliceEndian(val_size, @ptrCast(&val_size), .little); + try meta.interface.readSliceEndian(u32, @ptrCast(&val_size), .little); const val = try self.alloc.alloc(u8, val_size); errdefer alloc.free(val); @@ -134,7 +136,7 @@ fn valueAt(self: *XattrCachedTable, io: Io, ref: InodeRef) ![]const u8 { try meta.interface.discardAll(ref.block_offset); var val_size: u32 = undefined; - try meta.interface.readSliceEndian(val_size, @ptrCast(&val_size), .little); + try meta.interface.readSliceEndian(u32, @ptrCast(&val_size), .little); const val = try self.alloc.alloc(u8, val_size); errdefer self.alloc.free(val);