Starting work on inode decoding

This commit is contained in:
Caleb Gardner
2025-05-12 13:46:46 -05:00
parent 58e89c0981
commit b3a5ff8f94
7 changed files with 236 additions and 81 deletions
+57 -18
View File
@@ -4,7 +4,7 @@ pub const InodeRef = packed struct {
offset: u16, offset: u16,
}; };
const InodeType = enum(u16) { pub const InodeType = enum(u16) {
dir = 1, dir = 1,
file, file,
symlink, symlink,
@@ -30,21 +30,60 @@ pub const InodeHeader = packed struct {
inode_num: u32, inode_num: u32,
}; };
const itypes = @import("inode_types.zig"); pub const InodeData = union(enum) {
dir: dir.DirInode,
const InodeData = union(enum) { file: file.FileInode,
dir: itypes.DirInode, symlink: sym.SymlinkInode,
file: itypes.FileInode, block_device: misc.DeviceInode,
symlink: itypes.SymlinkInode, char_device: misc.DeviceInode,
block_device: itypes.DeviceInode, fifo: misc.IPCInode,
char_device: itypes.DeviceInode, socket: misc.IPCInode,
fifo: itypes.FifoInode, ext_dir: dir.ExtDirInode,
socket: itypes.FifoInode, ext_file: file.ExtFileInode,
ext_dir: itypes.ExtDirInode, ext_symlink: sym.ExtSymlinkInode,
ext_file: itypes.ExtFileInode, ext_block_device: misc.ExtDeviceInode,
ext_symlink: itypes.ExtSymlinkInode, ext_char_device: misc.ExtDeviceInode,
ext_block_device: itypes.ExtDeviceInode, ext_fifo: misc.IPCInode,
ext_char_device: itypes.ExtDeviceInode, ext_socket: misc.IPCInode,
ext_fifo: itypes.ExtFifoInode,
ext_socket: itypes.ExtFifoInode,
}; };
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,
};
}
-60
View File
@@ -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,
};
+65
View File
@@ -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;
}
+54
View File
@@ -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;
}
+19
View File
@@ -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,
};
+37
View File
@@ -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;
}
+4 -3
View File
@@ -1,4 +1,5 @@
const std = @import("std"); const math = @import("std").math;
const InodeRef = @import("inode.zig").InodeRef;
pub const SuperblockError = error{ pub const SuperblockError = error{
InvalidMagic, InvalidMagic,
@@ -31,7 +32,7 @@ pub const Superblock = packed struct {
id_count: u16, id_count: u16,
ver_maj: u16, ver_maj: u16,
ver_min: u16, ver_min: u16,
root_inode: @import("inode.zig").InodeRef, root_inode: InodeRef,
size: u64, size: u64,
id_table: u64, id_table: u64,
xattr_table: u64, xattr_table: u64,
@@ -43,7 +44,7 @@ pub const Superblock = packed struct {
pub fn valid(self: Superblock) SuperblockError!void { pub fn valid(self: Superblock) SuperblockError!void {
if (self.magic != 0x73717368) { if (self.magic != 0x73717368) {
return SuperblockError.InvalidMagic; 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; return SuperblockError.InvalidLog;
} else if (self.ver_maj != 4 or self.ver_min != 0) { } else if (self.ver_maj != 4 or self.ver_min != 0) {
return SuperblockError.InvalidVersion; return SuperblockError.InvalidVersion;