diff --git a/src/inode/dir.zig b/src/inode/dir.zig index 1b4ba2f..b1afc21 100644 --- a/src/inode/dir.zig +++ b/src/inode/dir.zig @@ -14,8 +14,11 @@ pub const DirInode = packed struct { }; const DirIndex = struct { - -} + offset: u32, + block_start: u32, + name_size: u32, + name: []const u8, +}; pub const ExtDirInode = packed struct { hard_links: u32, diff --git a/src/inode/file.zig b/src/inode/file.zig index e69de29..90b4a3f 100644 --- a/src/inode/file.zig +++ b/src/inode/file.zig @@ -0,0 +1,72 @@ +const std = @import("std"); +const io = std.io; + +pub const BlockSize = packed struct { size: u23, not_compressed: bool, _: u8 }; + +pub const FileInode = struct { + data_start: u32, + frag_idx: u32, + frag_offset: u32, + size: u32, + blocks: []const BlockSize, + + pub fn init(alloc: std.mem.Allocator, rdr: io.AnyReader, block_size: u32) !FileInode { + const fixed_buf = [_]u8{0} ** 16; + _ = try rdr.readAll(&fixed_buf); + const frag_idx = std.mem.bytesToValue(u32, fixed_buf[4..8]); + const size = std.mem.bytesToValue(u32, fixed_buf[12..16]); + var block_num = size / block_size; + if (frag_idx != 0xFFFFFFFF) { + block_num += 1; + } + const blocks = try alloc.alloc(BlockSize, block_num); + _ = try rdr.readAll(std.mem.asBytes(blocks)); + return .{ + .data_start = std.mem.bytesToValue(u32, fixed_buf[0..4]), + .frag_idx = frag_idx, + .frag_offset = std.mem.bytesToValue(u32, fixed_buf[8..12]), + .size = size, + .blocks = blocks, + }; + } + pub fn deinit(self: FileInode, alloc: std.mem.Allocator) void { + alloc.free(self.blocks); + } +}; + +pub const ExtFileInode = struct { + data_start: u64, + size: u64, + sparse: u64, + hard_links: u32, + frag_idx: u32, + frag_offset: u32, + xattr_idx: u32, + blocks: []const BlockSize, + + pub fn init(alloc: std.mem.Allocator, rdr: io.AnyReader, block_size: u32) !ExtFileInode { + const fixed_buf = [_]u8{0} ** 40; + _ = try rdr.readAll(&fixed_buf); + const size = std.mem.bytesToValue(u64, fixed_buf[8..16]); + const frag_idx = std.mem.bytesToValue(u32, fixed_buf[28..32]); + var block_num = size / block_size; + if (frag_idx != 0xFFFFFFFF) { + block_num += 1; + } + const blocks = try alloc.alloc(BlockSize, block_num); + _ = try rdr.readAll(std.mem.asBytes(blocks)); + return .{ + .data_start = std.mem.bytesToValue(u64, fixed_buf[0..8]), + .size = size, + .sparse = std.mem.bytesToValue(u64, fixed_buf[16..24]), + .hard_links = std.mem.bytesToValue(u32, fixed_buf[24..28]), + .frag_idx = frag_idx, + .frag_offset = std.mem.bytesToValue(u32, fixed_buf[32..36]), + .xattr_idx = std.mem.bytesToValue(u32, fixed_buf[36..40]), + .blocks = blocks, + }; + } + pub fn deinit(self: ExtFileInode, alloc: std.mem.Allocator) void { + alloc.free(self.blocks); + } +}; diff --git a/src/inode/inode.zig b/src/inode/inode.zig index b1c5a0b..b704a35 100644 --- a/src/inode/inode.zig +++ b/src/inode/inode.zig @@ -56,8 +56,41 @@ pub const InodeHeader = packed struct { }; pub const Inode = struct { + alloc: std.mem.Allocator, header: InodeHeader, - data: InodeData, //TODO + data: InodeData, - pub fn init(rdr: io.AnyReader) !Inode {} + pub fn init(alloc: std.mem.Allocator, rdr: io.AnyReader, block_size: u32) !Inode { + const hdr = try rdr.readStruct(InodeHeader); + const data: InodeData = switch (hdr.inode_type) { + .dir => .{ .dir = try .init(rdr) }, + .file => .{ .file = try .init(alloc, rdr, block_size) }, + .sym => .{ .sym = try .init(alloc, rdr) }, + .block => .{ .block = try .init(rdr) }, + .char => .{ .char = try .init(rdr) }, + .fifo => .{ .fifo = try .init(rdr) }, + .sock => .{ .sock = try .init(rdr) }, + .ext_dir => .{ .ext_dir = try .init(rdr) }, + .ext_file => .{ .ext_file = try .init(alloc, rdr, block_size) }, + .ext_sym => .{ .ext_sym = try .init(alloc, rdr) }, + .ext_block => .{ .ext_block = try .init(rdr) }, + .ext_char => .{ .ext_char = try .init(rdr) }, + .ext_fifo => .{ .ext_fifo = try .init(rdr) }, + .ext_sock => .{ .ext_sock = try .init(rdr) }, + }; + return .{ + .alloc = alloc, + .header = hdr, + .data = data, + }; + } + pub fn deinit(self: Inode) void { + switch (self.data) { + .file => |d| d.deinit(self.alloc), + .sym => |d| d.deinit(self.alloc), + .ext_file => |d| d.deinit(self.alloc), + .ext_sym => |d| d.deinit(self.alloc), + else => {}, + } + } }; diff --git a/src/inode/misc.zig b/src/inode/misc.zig index e69de29..940a0a0 100644 --- a/src/inode/misc.zig +++ b/src/inode/misc.zig @@ -0,0 +1,38 @@ +const std = @import("std"); +const io = std.io; + +pub const DeviceInode = packed struct { + hard_links: u32, + device: u32, + + pub fn init(rdr: io.AnyReader) !DeviceInode { + return rdr.readStruct(DeviceInode); + } +}; + +pub const ExtDeviceInode = packed struct { + hard_links: u32, + device: u32, + xattr_idx: u32, + + pub fn init(rdr: io.AnyReader) !ExtDeviceInode { + return rdr.readStruct(ExtDeviceInode); + } +}; + +pub const IPCInode = packed struct { + hard_links: u32, + + pub fn init(rdr: io.AnyReader) !IPCInode { + return rdr.readStruct(IPCInode); + } +}; + +pub const ExtIPCInode = packed struct { + hard_links: u32, + xattr_idx: u32, + + pub fn init(rdr: io.AnyReader) !ExtIPCInode { + return rdr.readStruct(ExtIPCInode); + } +}; diff --git a/src/inode/sym.zig b/src/inode/sym.zig index e69de29..5c3bebf 100644 --- a/src/inode/sym.zig +++ b/src/inode/sym.zig @@ -0,0 +1,48 @@ +const std = @import("std"); +const io = std.io; + +pub const SymInode = struct { + hard_links: u32, + size: u32, + target: []const u8, + + pub fn init(alloc: std.mem.Allocator, rdr: io.AnyReader) !SymInode { + const fixed_buf = [_]u8{0} ** 8; + _ = try rdr.readAll(&fixed_buf); + const size = std.mem.bytesToValue(u32, fixed_buf[4..]); + const target = try alloc.alloc(u8, size); + _ = try rdr.readAll(target); + return .{ + .hard_links = std.mem.bytesToValue(u32, fixed_buf[0..4]), + .size = size, + .target = target, + }; + } + pub fn deinit(self: SymInode, alloc: std.mem.Allocator) void { + alloc.free(self.target); + } +}; + +pub const ExtSymInode = struct { + hard_links: u32, + size: u32, + target: []const u8, + xattr_idx: u32, + + pub fn init(alloc: std.mem.Allocator, rdr: io.AnyReader) !ExtSymInode { + const fixed_buf = [_]u8{0} ** 8; + _ = try rdr.readAll(&fixed_buf); + const size = std.mem.bytesToValue(u32, fixed_buf[4..]); + const target = try alloc.alloc(u8, size); + _ = try rdr.readAll(target); + return .{ + .hard_links = std.mem.bytesToValue(u32, fixed_buf[0..4]), + .size = size, + .target = target, + .xattr_idx = rdr.readInt(u32, std.builtin.Endian.little), + }; + } + pub fn deinit(self: ExtSymInode, alloc: std.mem.Allocator) void { + alloc.free(self.target); + } +};