From b0c71c59f88b680a3bb8fb224d72d1a91e6eaa30 Mon Sep 17 00:00:00 2001 From: Caleb Gardner Date: Wed, 14 May 2025 05:16:12 -0500 Subject: [PATCH] Inode parsing works! --- inode.zig | 8 ++--- inode_types/dir.zig | 72 ++++++++++++++++++++++----------------------- metadata_reader.zig | 18 ++++++++++-- squashfs.zig | 10 ++++--- test_squashfs.zig | 4 ++- 5 files changed, 64 insertions(+), 48 deletions(-) diff --git a/inode.zig b/inode.zig index c565ad8..6c0927d 100644 --- a/inode.zig +++ b/inode.zig @@ -1,9 +1,9 @@ const std = @import("std"); pub const InodeRef = packed struct { - _: u16, - block_start: u32, offset: u16, + block_start: u32, + _: u16, }; pub const InodeType = enum(u16) { @@ -67,10 +67,10 @@ pub fn readInode(rdr: io.AnyReader, block_size: u32, alloc: std.mem.Allocator) ! .header = hdr, .data = switch (hdr.inode_type) { .dir => .{ - .dir = try dir.readDirInode(rdr), + .dir = try .init(rdr), }, .ext_dir => .{ - .ext_dir = try dir.readExtDirInode(rdr, alloc), + .ext_dir = try .init(rdr, alloc), }, .file => .{ .file = try file.readFileInode(rdr, block_size, alloc), diff --git a/inode_types/dir.zig b/inode_types/dir.zig index 4dada6e..c993fe6 100644 --- a/inode_types/dir.zig +++ b/inode_types/dir.zig @@ -7,30 +7,30 @@ pub const DirInode = packed struct { dir_table_size: u16, dir_block_offset: u16, parent_inode_num: u32, -}; -pub fn readDirInode(rdr: io.AnyReader) !DirInode { - return try rdr.readStruct(DirInode); -} + pub fn init(rdr: io.AnyReader) !DirInode { + return try rdr.readStruct(DirInode); + } +}; pub const DirIndex = struct { dir_header_offset: u32, dir_table_offset: u32, name_size: u32, name: []u8, -}; -fn readDirIndex(rdr: io.AnyReader, alloc: std.mem.Allocator) !DirIndex { - var out = DirIndex{ - .dir_header_offset = try rdr.readInt(u32, std.builtin.Endian.little), - .dir_table_offset = try rdr.readInt(u32, std.builtin.Endian.little), - .name_size = try rdr.readInt(u32, std.builtin.Endian.little), - .name = undefined, - }; - out.name = try alloc.alloc(u8, out.name_size); - _ = try rdr.readAll(out.name); - return out; -} + pub fn init(rdr: io.AnyReader, alloc: std.mem.Allocator) !DirIndex { + var out = DirIndex{ + .dir_header_offset = try rdr.readInt(u32, std.builtin.Endian.little), + .dir_table_offset = try rdr.readInt(u32, std.builtin.Endian.little), + .name_size = try rdr.readInt(u32, std.builtin.Endian.little), + .name = undefined, + }; + out.name = try alloc.alloc(u8, out.name_size); + _ = try rdr.readAll(out.name); + return out; + } +}; pub const ExtDirInode = struct { hard_links: u32, @@ -41,25 +41,25 @@ pub const ExtDirInode = struct { dir_block_offset: u16, xattr_index: u32, indexes: []DirIndex, -}; -pub fn readExtDirInode(rdr: io.AnyReader, alloc: std.mem.Allocator) !ExtDirInode { - var out = ExtDirInode{ - .hard_links = try rdr.readInt(u32, std.builtin.Endian.little), - .dir_table_size = try rdr.readInt(u32, std.builtin.Endian.little), - .dir_block_start = try rdr.readInt(u32, std.builtin.Endian.little), - .parent_inode_num = try rdr.readInt(u32, std.builtin.Endian.little), - .dir_index_count = try rdr.readInt(u16, std.builtin.Endian.little), - .dir_block_offset = try rdr.readInt(u16, std.builtin.Endian.little), - .xattr_index = try rdr.readInt(u32, std.builtin.Endian.little), - .indexes = undefined, - }; - var tmp = std.ArrayList(DirIndex).init(alloc); - try tmp.resize(out.dir_index_count); - var i: u16 = 0; - while (i < out.dir_index_count) : (i += 1) { - tmp.items[i] = try readDirIndex(rdr, alloc); + pub fn init(rdr: io.AnyReader, alloc: std.mem.Allocator) !ExtDirInode { + var out = ExtDirInode{ + .hard_links = try rdr.readInt(u32, std.builtin.Endian.little), + .dir_table_size = try rdr.readInt(u32, std.builtin.Endian.little), + .dir_block_start = try rdr.readInt(u32, std.builtin.Endian.little), + .parent_inode_num = try rdr.readInt(u32, std.builtin.Endian.little), + .dir_index_count = try rdr.readInt(u16, std.builtin.Endian.little), + .dir_block_offset = try rdr.readInt(u16, std.builtin.Endian.little), + .xattr_index = try rdr.readInt(u32, std.builtin.Endian.little), + .indexes = undefined, + }; + var tmp = std.ArrayList(DirIndex).init(alloc); + try tmp.resize(out.dir_index_count); + var i: u16 = 0; + while (i < out.dir_index_count) : (i += 1) { + tmp.items[i] = try .init(rdr, alloc); + } + out.indexes = tmp.items; + return out; } - out.indexes = tmp.items; - return out; -} +}; diff --git a/metadata_reader.zig b/metadata_reader.zig index 7689854..ccf897d 100644 --- a/metadata_reader.zig +++ b/metadata_reader.zig @@ -4,8 +4,8 @@ const io = std.io; const CompressionType = @import("decompress.zig").CompressionType; const MetadataHeader = packed struct { - not_compressed: bool, size: u15, + not_compressed: bool, }; pub const MetadataReader = struct { @@ -14,6 +14,7 @@ pub const MetadataReader = struct { decomp: CompressionType, curBlock: []u8, curOffset: u16, + free: bool = false, pub fn init(decomp: CompressionType, rdr: io.AnyReader, alloc: std.mem.Allocator) !MetadataReader { var out: MetadataReader = .{ @@ -26,12 +27,25 @@ pub const MetadataReader = struct { try out.readNextBlock(); return out; } + pub fn deinit(self: *MetadataReader) void { + self.alloc.free(self.curBlock); + } pub fn any(self: *MetadataReader) io.AnyReader { return .{ .context = @ptrCast(self), .readFn = readOpaque, }; } + pub fn skip(self: *MetadataReader, offset: u16) !void { + var to_skip = offset; + var cur_left = self.curBlock.len - self.curOffset; + while (to_skip > cur_left) { + to_skip -= @intCast(cur_left); + try self.readNextBlock(); + cur_left = self.curBlock.len; + } + self.curOffset = to_skip; + } fn readNextBlock(self: *MetadataReader) !void { if (self.curBlock.len != 0) { @@ -52,12 +66,10 @@ pub const MetadataReader = struct { var cur_read: usize = 0; var to_read: usize = 0; while (cur_read < bytes.len) { - std.debug.print("hello there!, {}\n", .{cur_read}); if (self.curOffset + 1 == self.curBlock.len) { try self.readNextBlock(); } to_read = @min(bytes.len - cur_read, self.curBlock.len - self.curOffset); - std.debug.print("{} {} {}\n", .{ cur_read, to_read, self.curOffset }); std.mem.copyForwards(u8, bytes[cur_read..], self.curBlock[self.curOffset .. self.curOffset + to_read]); self.curOffset += @truncate(to_read); cur_read += to_read; diff --git a/squashfs.zig b/squashfs.zig index df990fd..b72f645 100644 --- a/squashfs.zig +++ b/squashfs.zig @@ -9,23 +9,25 @@ pub const Reader = struct { super: Superblock, rdr: fs.File, root: inode.Inode, - alloc: std.heap.GeneralPurposeAllocator(.{}), + alloc: std.heap.ArenaAllocator, - pub fn close(self: *Reader) void { + pub fn deinit(self: *Reader) void { self.rdr.close(); - _ = self.alloc.deinit(); + self.alloc.deinit(); } }; pub fn newReader(filename: []const u8) !Reader { const file = try std.fs.cwd().openFile(filename, .{}); errdefer file.close(); - var alloc: std.heap.GeneralPurposeAllocator(.{}) = .init; + var alloc: std.heap.ArenaAllocator = .init(std.heap.page_allocator); errdefer _ = alloc.deinit(); const super = try file.reader().readStruct(Superblock); try super.valid(); try file.seekTo(super.inode_table + super.root_inode.block_start); var root_reader: MetadataReader = try .init(super.comp, file.reader().any(), alloc.allocator()); + defer root_reader.deinit(); + try root_reader.skip(super.root_inode.offset); const root_inode = try inode.readInode(root_reader.any(), super.block_size, alloc.allocator()); return Reader{ .super = super, diff --git a/test_squashfs.zig b/test_squashfs.zig index e472e01..bc36829 100644 --- a/test_squashfs.zig +++ b/test_squashfs.zig @@ -1,10 +1,12 @@ const std = @import("std"); const debug = std.debug; const squashfs = @import("squashfs.zig"); +const print = std.debug.print; const testFileName = "testing/LinuxPATest.sfs"; test "open test file" { var reader = try squashfs.newReader(testFileName); - defer reader.close(); + defer reader.deinit(); + print("{}\n", .{reader.root}); }