diff --git a/src/archive.zig b/src/archive.zig index 2d3e0e6..0431c54 100644 --- a/src/archive.zig +++ b/src/archive.zig @@ -1,6 +1,10 @@ const std = @import("std"); const Io = std.Io; +const File = @import("file.zig"); +const Inode = @import("inode.zig"); +const Util = @import("util.zig"); + const Archive = @This(); map: Io.File.MemoryMap, @@ -14,7 +18,7 @@ pub fn open(io: Io, file: Io.File, offset: u64) !Archive { .protection = .{ .read = true }, }); - var super: Superblock = std.mem.bytesToValue(Superblock, map.memory[0..@sizeOf(Superblock)]); + var super = Util.readValue(Superblock, map.memory[0..@sizeOf(Superblock)]); try super.check(); return .{ @@ -23,6 +27,18 @@ pub fn open(io: Io, file: Io.File, offset: u64) !Archive { .super = super, }; } +pub fn close(self: *Archive, io: Io) void { + self.map.destroy(io); +} + +pub fn root(self: *Archive) !File { + _ = self; + return error.TODO; +} +pub fn extract(self: *Archive) !void { + _ = self; + return error.TODO; +} // Superblock @@ -40,7 +56,7 @@ pub const Superblock = extern struct { id_count: u16, version_major: u16, version_minor: u16, - root_inode_ref: u64, // TODO: Change to inode reference packed struct. + root_inode_ref: Inode.Reference, // TODO: Change to inode reference packed struct. size: u64, id_table_start: u64, xattr_table_start: u64, diff --git a/src/file.zig b/src/file.zig new file mode 100644 index 0000000..955115c --- /dev/null +++ b/src/file.zig @@ -0,0 +1,16 @@ +const std = @import("std"); +const Io = std.Io; + +const Inode = @import("inode.zig"); + +const File = @This(); + +alloc: std.mem.Allocator, + +name: []const u8, +inode: Inode, + +pub fn close(self: File) void { + self.inode.deinit(self.alloc); + self.alloc.free(self.name); +} diff --git a/src/inode.zig b/src/inode.zig index 2f1aac2..6b33594 100644 --- a/src/inode.zig +++ b/src/inode.zig @@ -6,6 +6,16 @@ const Inode = @This(); header: Header, data: Data, +pub fn deinit(self: Inode, alloc: std.mem.Allocator) void { + switch (self.data) { + .file => |f| alloc.free(f.blocks), + .ext_file => |f| alloc.free(f.blocks), + .symlink => |s| alloc.free(s.target), + .ext_symlink => |s| alloc.free(s.target), + else => {}, + } +} + // Types pub const Reference = packed struct(u64) { @@ -76,11 +86,19 @@ pub const ExtDir = extern struct { xattr_idx: u32, }; -pub const File = struct {}; -pub const ExtFile = struct {}; +pub const File = struct { + blocks: []u64, +}; +pub const ExtFile = struct { + blocks: []u64, +}; -pub const Symlink = struct {}; -pub const ExtSymlink = struct {}; +pub const Symlink = struct { + target: []const u8, +}; +pub const ExtSymlink = struct { + target: []const u8, +}; pub const Dev = extern struct {}; pub const ExtDev = extern struct {}; diff --git a/src/root.zig b/src/root.zig index 456613d..5ff572e 100644 --- a/src/root.zig +++ b/src/root.zig @@ -2,5 +2,5 @@ pub const Archive = @import("archive.zig"); pub const Options = @import("options.zig"); test { - @import("std").testing.refAllDecls(Archive); + @import("std").testing.refAllDecls(@import("tests.zig")); } diff --git a/src/tests.zig b/src/tests.zig new file mode 100644 index 0000000..5dedc13 --- /dev/null +++ b/src/tests.zig @@ -0,0 +1,20 @@ +const std = @import("std"); +const Io = std.Io; + +var alloc = std.testing.allocator; +var io = std.testing.io; + +const Archive = @import("archive.zig"); + +const TEST_ARCHIVE = "testing/LinuxPATest.sfs"; + +test "Open" { + var archive_file = try Io.Dir.cwd().openFile(io, TEST_ARCHIVE, .{}); + defer archive_file.close(io); + + var arc: Archive = try .open(io, archive_file, 0); + defer arc.close(io); + + var root = try arc.root(); + defer root.close(); +} diff --git a/src/util.zig b/src/util.zig new file mode 100644 index 0000000..a5e3a11 --- /dev/null +++ b/src/util.zig @@ -0,0 +1,16 @@ +const std = @import("std"); +const builtin = @import("builtin"); + +pub fn readValue(comptime T: type, bytes: []u8) T { + var res = std.mem.bytesToValue(T, bytes); + if (builtin.cpu.arch.endian() != .little) { + switch (@typeInfo(T)) { + .@"enum" => res = std.mem.nativeToLittle(@typeInfo(T).@"enum".tag_type, res), + .@"struct" => std.mem.byteSwapAllFields(T, &res), + .int => res = std.mem.nativeToLittle(T, res), + .array => std.mem.byteSwapAllElements(@typeInfo(T).array.child, res), + else => unreachable, + } + } + return res; +}