diff --git a/inode.zig b/inode.zig index 74fdfed..bb2eaba 100644 --- a/inode.zig +++ b/inode.zig @@ -1,3 +1,5 @@ +const std = @import("std"); + pub const InodeRef = packed struct { _: u16, block_start: u32, @@ -52,14 +54,14 @@ const file = @import("inode_types/file.zig"); const sym = @import("inode_types/sym.zig"); const misc = @import("inode_types/misc.zig"); -const Inode = struct { +pub const Inode = struct { header: InodeHeader, data: InodeData, }; const io = @import("std").io; -pub fn readInode(rdr: io.AnyReader, block_size: u64) !Inode { +pub fn readInode(rdr: io.AnyReader, block_size: u64, alloc: std.heap.Allocator) !Inode { const hdr = try rdr.readStruct(InodeHeader); const data: InodeData = undefined; switch (hdr.inode_type) { @@ -67,19 +69,19 @@ pub fn readInode(rdr: io.AnyReader, block_size: u64) !Inode { .dir = dir.readDirInode(rdr), }, .ext_dir => data = .{ - .ext_dir = try dir.readExtDirInode(rdr), + .ext_dir = try dir.readExtDirInode(rdr, alloc), }, .file => data = .{ - .file = try file.readFileInode(rdr, block_size), + .file = try file.readFileInode(rdr, block_size, alloc), }, .ext_file => data = .{ - .ext_file = try file.readExtFileInode(rdr, block_size), + .ext_file = try file.readExtFileInode(rdr, block_size, alloc), }, .symlink => data = .{ - .block_device = try misc.readSymlinkInode(rdr), + .block_device = try misc.readSymlinkInode(rdr, alloc), }, .ext_symlink => data = .{ - .ext_symlink = try sym.readExtSymlinkInode(rdr), + .ext_symlink = try sym.readExtSymlinkInode(rdr, alloc), }, } return Inode{ diff --git a/inode_types/dir.zig b/inode_types/dir.zig index 309d4b7..e9b7cfe 100644 --- a/inode_types/dir.zig +++ b/inode_types/dir.zig @@ -20,17 +20,15 @@ pub const DirIndex = struct { name: []const u8, }; -fn readDirIndex(rdr: io.AnyReader) !DirIndex { +fn readDirIndex(rdr: io.AnyReader, alloc: std.heap.Allocator) !DirIndex { const 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, }; - const buf = try std.heap.page_allocator.alloc(u8, out.name_size); - defer std.heap.page_allocator.free(buf); - try rdr.read(buf); - out.name = buf[0..]; + out.name = try alloc.alloc(u8, out.name_size); + try rdr.read(out.name); return out; } @@ -45,7 +43,7 @@ pub const ExtDirInode = struct { indexes: []const DirIndex, }; -pub fn readExtDirInode(rdr: io.AnyReader) !ExtDirInode { +pub fn readExtDirInode(rdr: io.AnyReader, alloc: std.heap.Allocator) !ExtDirInode { const out = ExtDirInode{ .hard_links = rdr.readInt(u32, std.builtin.Endian.little), .dir_table_size = rdr.readInt(u32, std.builtin.Endian.little), @@ -56,10 +54,12 @@ pub fn readExtDirInode(rdr: io.AnyReader) !ExtDirInode { .xattr_index = rdr.readInt(u32, std.builtin.Endian.little), .indexes = undefined, }; - out.indexes = []const DirIndex{undefined} ** out.dir_index_count; + const tmp = std.ArrayList(DirIndex).init(alloc); + try tmp.resize(out.dir_index_count); const i: u16 = 0; while (i < out.dir_index_count) : (i += 1) { - out.indexes[i] = try readDirIndex(rdr); + tmp.items[i] = try readDirIndex(rdr, alloc); } + out.indexes = tmp.items; return out; } diff --git a/inode_types/file.zig b/inode_types/file.zig index 1b117df..e5407cd 100644 --- a/inode_types/file.zig +++ b/inode_types/file.zig @@ -8,7 +8,7 @@ pub const FileInode = struct { block_sizes: []const u32, }; -pub fn readFileInode(rdr: std.io.AnyReader, block_size: u32) !FileInode { +pub fn readFileInode(rdr: std.io.AnyReader, block_size: u32, alloc: std.heap.Allocator) !FileInode { const out = FileInode{ .start = try rdr.readInt(u32, std.builtin.Endian.little), .frag_index = try rdr.readInt(u32, std.builtin.Endian.little), @@ -17,9 +17,11 @@ pub fn readFileInode(rdr: std.io.AnyReader, block_size: u32) !FileInode { .block_sizes = undefined, }; var block_num = out.size / block_size; - if (out.frag_index != 0xFFFFFFFF and out.size % block_size != 0) { + if (out.frag_index != 0xFFFFFFFF) { block_num += 1; } + out.block_sizes = try alloc.alloc(u32, block_num); + try rdr.read(std.mem.asBytes(&out.block_sizes)); return out; } @@ -34,7 +36,7 @@ pub const ExtFileInode = struct { block_sizes: []const u32, }; -pub fn readExtFileInode(rdr: std.io.AnyReader, block_size: u32) !ExtFileInode { +pub fn readExtFileInode(rdr: std.io.AnyReader, block_size: u32, alloc: std.heap.Allocator) !ExtFileInode { const out = ExtFileInode{ .start = try rdr.readInt(u64, std.builtin.Endian.little), .size = try rdr.readInt(u64, std.builtin.Endian.little), @@ -49,6 +51,7 @@ pub fn readExtFileInode(rdr: std.io.AnyReader, block_size: u32) !ExtFileInode { if (out.frag_index != 0xFFFFFFFF and out.size % block_size != 0) { block_num += 1; } - //TODO: stuff + out.block_sizes = try alloc.alloc(u32, block_num); + try rdr.read(std.mem.asBytes(&out.block_sizes)); return out; } diff --git a/inode_types/sym.zig b/inode_types/sym.zig index f7ec474..fd9a44a 100644 --- a/inode_types/sym.zig +++ b/inode_types/sym.zig @@ -7,13 +7,14 @@ pub const SymlinkInode = struct { path: []const u8, }; -pub fn readSymlinkInode(rdr: io.AnyReader) !SymlinkInode { +pub fn readSymlinkInode(rdr: io.AnyReader, alloc: std.heap.Allocator) !SymlinkInode { const out = SymlinkInode{ .hard_links = try rdr.readInt(u32, std.builtin.Endian.little), .target_size = try rdr.readInt(u32, std.builtin.Endian.little), .path = undefined, }; - out.path = (try rdr.readBoundedBytes(out.target_size + 1)).constSlice(); + out.path = try alloc.alloc(u8, out.target_size + 1); + try rdr.read(out.path); return out; } @@ -24,14 +25,15 @@ pub const ExtSymlinkInode = struct { xattr_index: u32, }; -pub fn readExtSymlinkInode(rdr: io.AnyReader) !SymlinkInode { +pub fn readExtSymlinkInode(rdr: io.AnyReader, alloc: std.heap.Allocator) !SymlinkInode { const out = ExtSymlinkInode{ .hard_links = try rdr.readInt(u32, std.builtin.Endian.little), .target_size = try rdr.readInt(u32, std.builtin.Endian.little), .path = undefined, .xattr_index = undefined, }; - out.path = (try rdr.readBoundedBytes(out.target_size + 1)).constSlice(); + out.path = try alloc.alloc(u8, out.target_size + 1); + try rdr.read(out.path); out.xattr_index = try rdr.readInt(u32, std.builtin.Endian.little); return out; } diff --git a/squashfs.zig b/squashfs.zig index 2399282..15c74ce 100644 --- a/squashfs.zig +++ b/squashfs.zig @@ -1,17 +1,32 @@ const std = @import("std"); -const io = std.io; +const fs = std.fs; + const Superblock = @import("superblock.zig").Superblock; +const Inode = @import("inode.zig").Inode; pub const Reader = struct { super: Superblock, - rdr: io.AnyReader, + rdr: fs.File, + root: Inode, + alloc: std.heap.GeneralPurposeAllocator(.{}), + + pub fn close(self: Reader) void { + self.rdr.close(); + self.alloc.deinit(); + } }; -pub fn newReader(rdr: io.AnyReader) !Reader { - const super = try rdr.readStruct(Superblock); +pub fn newReader(filename: []const u8) !Reader { + const file = try std.fs.cwd().openFile(filename, .{}); + errdefer file.close(); + const alloc = std.heap.GeneralPurposeAllocator(.{}); + errdefer alloc.deinit(); + const super = try file.reader().readStruct(Superblock); try super.valid(); + return Reader{ .super = super, - .rdr = rdr, + .rdr = file, + .alloc = alloc, }; -} \ No newline at end of file +} diff --git a/test_squashfs.zig b/test_squashfs.zig index 0128133..1b4cd0e 100644 --- a/test_squashfs.zig +++ b/test_squashfs.zig @@ -5,11 +5,6 @@ const squashfs = @import("squashfs.zig"); const testFileName = "testing/LinuxPATest.sfs"; test "open test file" { - const testFile = try std.fs.cwd().openFile( - testFileName, - .{}, - ); - defer testFile.close(); - const reader = try squashfs.newReader(testFile.reader().any()); - _ = reader; + const reader = try squashfs.newReader(testFileName); + defer reader.close(); }