diff --git a/inode.zig b/inode.zig index 9fb4d12..74fdfed 100644 --- a/inode.zig +++ b/inode.zig @@ -4,7 +4,7 @@ pub const InodeRef = packed struct { offset: u16, }; -const InodeType = enum(u16) { +pub const InodeType = enum(u16) { dir = 1, file, symlink, @@ -30,21 +30,60 @@ pub const InodeHeader = packed struct { inode_num: u32, }; -const itypes = @import("inode_types.zig"); - -const InodeData = union(enum) { - dir: itypes.DirInode, - file: itypes.FileInode, - symlink: itypes.SymlinkInode, - block_device: itypes.DeviceInode, - char_device: itypes.DeviceInode, - fifo: itypes.FifoInode, - socket: itypes.FifoInode, - ext_dir: itypes.ExtDirInode, - ext_file: itypes.ExtFileInode, - ext_symlink: itypes.ExtSymlinkInode, - ext_block_device: itypes.ExtDeviceInode, - ext_char_device: itypes.ExtDeviceInode, - ext_fifo: itypes.ExtFifoInode, - ext_socket: itypes.ExtFifoInode, +pub const InodeData = union(enum) { + dir: dir.DirInode, + file: file.FileInode, + symlink: sym.SymlinkInode, + block_device: misc.DeviceInode, + char_device: misc.DeviceInode, + fifo: misc.IPCInode, + socket: misc.IPCInode, + ext_dir: dir.ExtDirInode, + ext_file: file.ExtFileInode, + ext_symlink: sym.ExtSymlinkInode, + ext_block_device: misc.ExtDeviceInode, + ext_char_device: misc.ExtDeviceInode, + ext_fifo: misc.IPCInode, + ext_socket: misc.IPCInode, }; + +const dir = @import("inode_types/dir.zig"); +const file = @import("inode_types/file.zig"); +const sym = @import("inode_types/sym.zig"); +const misc = @import("inode_types/misc.zig"); + +const Inode = struct { + header: InodeHeader, + data: InodeData, +}; + +const io = @import("std").io; + +pub fn readInode(rdr: io.AnyReader, block_size: u64) !Inode { + const hdr = try rdr.readStruct(InodeHeader); + const data: InodeData = undefined; + switch (hdr.inode_type) { + .dir => data = .{ + .dir = dir.readDirInode(rdr), + }, + .ext_dir => data = .{ + .ext_dir = try dir.readExtDirInode(rdr), + }, + .file => data = .{ + .file = try file.readFileInode(rdr, block_size), + }, + .ext_file => data = .{ + .ext_file = try file.readExtFileInode(rdr, block_size), + }, + .symlink => data = .{ + .block_device = try misc.readSymlinkInode(rdr), + }, + .ext_symlink => data = .{ + .ext_symlink = try sym.readExtSymlinkInode(rdr), + }, + } + return Inode{ + .header = hdr, + .data = data, + }; +} diff --git a/inode_types.zig b/inode_types.zig deleted file mode 100644 index f1bbaac..0000000 --- a/inode_types.zig +++ /dev/null @@ -1,60 +0,0 @@ -pub const DirInode = packed struct { - dir_block_start: u32, - hard_links: u32, - dir_table_size: u16, - dir_block_offset: u16, - parent_inode_num: u32, -}; - -pub const DirIndexStart = packed struct { - dir_header_offset: u32, - dir_table_offset: u32, - name_size: u32, -}; - -pub const DirIndex = struct { - start: DirIndexStart, - name: []const u8, -}; - -pub const ExtDirInodeStart = packed struct { - hard_links: u32, - dir_table_size: u32, - dir_block_start: u32, - parent_inode_num: u32, - dir_index_count: u16, - dir_block_offset: u16, - xattr_index: u32, -}; - -pub const ExtDirInode = struct { - start: ExtDirInodeStart, - indexes: []const u8, -}; - -pub const FileInodeStart = packed struct { - start: u32, - frag_index: u32, - frag_block_offset: u32, - size: u32, -}; - -pub const FileInode = struct { - start: FileInodeStart, - block_sizes: []const u32, -}; - -pub const ExtFileInodeStart = packed struct { - start: u64, - size: u64, - sparse: u64, - hard_links: u32, - frag_index: u32, - frag_block_offset: u32, - xattr_index: u32, -}; - -pub const ExtFileInode = struct { - start: ExtFileInodeStart, - block_sizes: []const u32, -}; diff --git a/inode_types/dir.zig b/inode_types/dir.zig new file mode 100644 index 0000000..309d4b7 --- /dev/null +++ b/inode_types/dir.zig @@ -0,0 +1,65 @@ +const std = @import("std"); +const io = std.io; + +pub const DirInode = packed struct { + dir_block_start: u32, + hard_links: u32, + 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 const DirIndex = struct { + dir_header_offset: u32, + dir_table_offset: u32, + name_size: u32, + name: []const u8, +}; + +fn readDirIndex(rdr: io.AnyReader) !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..]; + return out; +} + +pub const ExtDirInode = struct { + hard_links: u32, + dir_table_size: u32, + dir_block_start: u32, + parent_inode_num: u32, + dir_index_count: u16, + dir_block_offset: u16, + xattr_index: u32, + indexes: []const DirIndex, +}; + +pub fn readExtDirInode(rdr: io.AnyReader) !ExtDirInode { + const out = ExtDirInode{ + .hard_links = rdr.readInt(u32, std.builtin.Endian.little), + .dir_table_size = rdr.readInt(u32, std.builtin.Endian.little), + .dir_block_start = rdr.readInt(u32, std.builtin.Endian.little), + .parent_inode_num = rdr.readInt(u32, std.builtin.Endian.little), + .dir_index_count = rdr.readInt(u16, std.builtin.Endian.little), + .dir_block_offset = rdr.readInt(u16, std.builtin.Endian.little), + .xattr_index = rdr.readInt(u32, std.builtin.Endian.little), + .indexes = undefined, + }; + out.indexes = []const DirIndex{undefined} ** out.dir_index_count; + const i: u16 = 0; + while (i < out.dir_index_count) : (i += 1) { + out.indexes[i] = try readDirIndex(rdr); + } + return out; +} diff --git a/inode_types/file.zig b/inode_types/file.zig new file mode 100644 index 0000000..1b117df --- /dev/null +++ b/inode_types/file.zig @@ -0,0 +1,54 @@ +const std = @import("std"); + +pub const FileInode = struct { + start: u32, + frag_index: u32, + frag_block_offset: u32, + size: u32, + block_sizes: []const u32, +}; + +pub fn readFileInode(rdr: std.io.AnyReader, block_size: u32) !FileInode { + const out = FileInode{ + .start = try rdr.readInt(u32, std.builtin.Endian.little), + .frag_index = try rdr.readInt(u32, std.builtin.Endian.little), + .frag_block_offset = try rdr.readInt(u32, std.builtin.Endian.little), + .size = try rdr.readInt(u32, std.builtin.Endian.little), + .block_sizes = undefined, + }; + var block_num = out.size / block_size; + if (out.frag_index != 0xFFFFFFFF and out.size % block_size != 0) { + block_num += 1; + } + return out; +} + +pub const ExtFileInode = struct { + start: u64, + size: u64, + sparse: u64, + hard_links: u32, + frag_index: u32, + frag_block_offset: u32, + xattr_index: u32, + block_sizes: []const u32, +}; + +pub fn readExtFileInode(rdr: std.io.AnyReader, block_size: u32) !ExtFileInode { + const out = ExtFileInode{ + .start = try rdr.readInt(u64, std.builtin.Endian.little), + .size = try rdr.readInt(u64, std.builtin.Endian.little), + .sparse = try rdr.readInt(u64, std.builtin.Endian.little), + .hard_links = try rdr.readInt(u32, std.builtin.Endian.little), + .frag_index = try rdr.readInt(u32, std.builtin.Endian.little), + .frag_block_offset = try rdr.readInt(u32, std.builtin.Endian.little), + .xattr_index = try rdr.readInt(u32, std.builtin.Endian.little), + .block_sizes = undefined, + }; + var block_num = out.size / block_size; + if (out.frag_index != 0xFFFFFFFF and out.size % block_size != 0) { + block_num += 1; + } + //TODO: stuff + return out; +} diff --git a/inode_types/misc.zig b/inode_types/misc.zig new file mode 100644 index 0000000..540a7b0 --- /dev/null +++ b/inode_types/misc.zig @@ -0,0 +1,19 @@ +pub const DeviceInode = packed struct { + hard_links: u32, + device: u32, +}; + +pub const ExtDeviceInode = packed struct { + hard_links: u32, + device: u32, + xattr_index: u32, +}; + +pub const IPCInode = packed struct { + hard_links: u32, +}; + +pub const ExtIPCInode = packed struct { + hard_links: u32, + xattr_index: u32, +}; diff --git a/inode_types/sym.zig b/inode_types/sym.zig new file mode 100644 index 0000000..f7ec474 --- /dev/null +++ b/inode_types/sym.zig @@ -0,0 +1,37 @@ +const std = @import("std"); +const io = std.io; + +pub const SymlinkInode = struct { + hard_links: u32, + target_size: u32, + path: []const u8, +}; + +pub fn readSymlinkInode(rdr: io.AnyReader) !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(); + return out; +} + +pub const ExtSymlinkInode = struct { + hard_links: u32, + target_size: u32, + path: []const u8, + xattr_index: u32, +}; + +pub fn readExtSymlinkInode(rdr: io.AnyReader) !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.xattr_index = try rdr.readInt(u32, std.builtin.Endian.little); + return out; +} diff --git a/superblock.zig b/superblock.zig index 2d6173b..c303751 100644 --- a/superblock.zig +++ b/superblock.zig @@ -1,4 +1,5 @@ -const std = @import("std"); +const math = @import("std").math; +const InodeRef = @import("inode.zig").InodeRef; pub const SuperblockError = error{ InvalidMagic, @@ -31,7 +32,7 @@ pub const Superblock = packed struct { id_count: u16, ver_maj: u16, ver_min: u16, - root_inode: @import("inode.zig").InodeRef, + root_inode: InodeRef, size: u64, id_table: u64, xattr_table: u64, @@ -43,7 +44,7 @@ pub const Superblock = packed struct { pub fn valid(self: Superblock) SuperblockError!void { if (self.magic != 0x73717368) { return SuperblockError.InvalidMagic; - } else if (self.block_log != std.math.log2(self.block_size)) { + } else if (self.block_log != math.log2(self.block_size)) { return SuperblockError.InvalidLog; } else if (self.ver_maj != 4 or self.ver_min != 0) { return SuperblockError.InvalidVersion;