From c7c44029c965f310f0be6c5be84f083129a99469 Mon Sep 17 00:00:00 2001 From: "Caleb J. Gardner" Date: Sat, 4 Apr 2026 14:17:50 -0500 Subject: [PATCH] Started working on Archive functions Started working on File --- src/archive.zig | 56 ++++++++++++++++++++++++++++ src/directory.zig | 2 +- src/file.zig | 20 ++++++++++ src/{tables.zig => lookup_table.zig} | 2 +- 4 files changed, 78 insertions(+), 2 deletions(-) rename src/{tables.zig => lookup_table.zig} (98%) diff --git a/src/archive.zig b/src/archive.zig index f69b7d3..eb6befc 100644 --- a/src/archive.zig +++ b/src/archive.zig @@ -3,7 +3,12 @@ const std = @import("std"); const DecompTypes = @import("decomp/types.zig"); const Decompressor = @import("decomp.zig"); const ExtractionOptions = @import("options.zig"); +const File = @import("file.zig"); const Inode = @import("inode.zig"); +const BlockSize = @import("inode/file.zig").BlockSize; +const LookupTable = @import("lookup_table.zig"); +const MetadataReader = @import("util/metadata.zig"); +const OffsetFile = @import("util/offset_file.zig"); pub const Error = error{ BadMagic, @@ -14,6 +19,8 @@ pub const Error = error{ const Archive = @This(); +file: OffsetFile, + super: Superblock, stateless_decomp: Decompressor, @@ -28,6 +35,7 @@ pub fn init(fil: std.fs.File, offset: u64) !Archive { try super.validate(); return .{ + .file = .{ .fil = fil, .offset = offset }, .super = super, .stateless_decomp = .{ .vtable = &.{ .stateless = try DecompTypes.getStatelessFn(super.compression) } }, }; @@ -41,6 +49,34 @@ pub fn extract(self: Archive, alloc: std.mem.Allocator, path: []const u8, option return error.TODO; } +pub fn root(self: Archive, alloc: std.mem.Allocator) !File { + return .{ + .alloc = alloc, + + .inode = try self.refToInode(alloc, self.super.root_ref), + .name = "", + }; +} +pub fn open(self: Archive, alloc: std.mem.Allocator, path: []const u8) !File {} + +pub fn fragEntry(self: Archive, idx: u32) !FragEntry { + return LookupTable.stateless(FragEntry, self.fil, &self.stateless_decomp, self.super.frag_start, idx); +} +pub fn id(self: Archive, idx: u32) !u16 { + return LookupTable.stateless(u16, self.fil, &self.stateless_decomp, self.super.id_start, idx); +} +pub fn inode(self: Archive, alloc: std.mem.Allocator, inode_num: u32) !Inode { + const ref = try LookupTable.stateless(Inode.Ref, self.file, &self.stateless_decomp, self.super.export_start, inode_num - 1); + return self.refToInode(alloc, ref); +} + +inline fn refToInode(self: Archive, alloc: std.mem.Allocator, ref: Inode.Ref) !Inode { + var rdr = self.file.readerAt(self.super.inode_start + ref.block_start, &[0]u8{}); + var meta: MetadataReader = .init(&rdr.interface, &self.stateless_decomp); + try meta.interface.discardAll(ref.block_offset); + return .read(alloc, &meta.interface, self.super.block_size); +} + // Superblock const SQUASHFS_MAGIC: u32 = std.mem.readInt(u32, "hsqs", .little); @@ -92,3 +128,23 @@ pub const Superblock = packed struct { return Error.BadBlockLog; } }; + +pub const MinimalSuperblock = struct { + block_size: u32, + frag_count: u32, + id_count: u16, + id_start: u64, + xattr_start: u64, + inode_start: u64, + dir_start: u64, + frag_start: u64, + export_start: u64, +}; + +// Frag Entry + +pub const FragEntry = packed struct { + block_start: u64, + size: BlockSize, + _: u32, +}; diff --git a/src/directory.zig b/src/directory.zig index 380be52..cb714e0 100644 --- a/src/directory.zig +++ b/src/directory.zig @@ -36,7 +36,7 @@ pub fn readDirectory(alloc: std.mem.Allocator, rdr: *Reader, size: u32) []Entry // Types -const Entry = struct { +pub const Entry = struct { block_start: u32, block_offset: u16, num: u32, diff --git a/src/file.zig b/src/file.zig index 312a350..6979a87 100644 --- a/src/file.zig +++ b/src/file.zig @@ -1,6 +1,26 @@ const std = @import("std"); +const Archive = @import("archive.zig"); +const Directory = @import("directory.zig"); const Inode = @import("inode.zig"); +const MetadataReader = @import("util/metadata.zig"); + +const File = @This(); + +alloc: std.mem.Allocator, + +archive: Archive, name: []const u8, inode: Inode, + +pub fn init(alloc: std.mem.Allocator, archive: Archive, entry: Directory.Entry) !File { + const new_name = try alloc.alloc(u8, entry.name.len); + errdefer alloc.free(new_name); + @memcpy(new_name, entry.name); + var rdr = archive.file.readerAt(archive.super.inode_start + entry.block_start, &[0]u8{}); + var meta +} +pub fn deinit(self: File) void { + self.alloc.free(self.name); +} diff --git a/src/tables.zig b/src/lookup_table.zig similarity index 98% rename from src/tables.zig rename to src/lookup_table.zig index e05e66f..04ea094 100644 --- a/src/tables.zig +++ b/src/lookup_table.zig @@ -20,7 +20,7 @@ pub fn stateless(comptime T: anytype, fil: OffsetFile, decomp: *const Decompress return out; } -pub fn Table(comptime T: anytype) type { +pub fn CachedTable(comptime T: anytype) type { return struct { const Self = @This();