diff --git a/src/decompress.zig b/src/decompress.zig index 962afb6..253cd44 100644 --- a/src/decompress.zig +++ b/src/decompress.zig @@ -14,7 +14,7 @@ pub const CompressionType = enum(u16) { lz4, zstd, - pub fn Decompress(self: CompressionType, alloc: std.mem.Allocator, rdr: std.io.AnyReader) ![]u8 { + pub fn decompress(self: CompressionType, alloc: std.mem.Allocator, rdr: std.io.AnyReader) ![]u8 { var out = std.ArrayList(u8).init(alloc); defer out.deinit(); switch (self) { diff --git a/src/directory.zig b/src/directory.zig index fa767fe..de41ff9 100644 --- a/src/directory.zig +++ b/src/directory.zig @@ -1,5 +1,7 @@ const std = @import("std"); +const CompressionType = @import("decompress.zig").CompressionType; + const DirHeader = packed struct { count: u32, inode_block_start: u32, @@ -43,3 +45,33 @@ pub const DirEntry = struct { } }; +const MetadataHeader = @import("metadata_reader.zig").MetadataHeader; + +pub fn readDirEntries(alloc: std.mem.Allocator, comp: CompressionType, rdr: std.io.AnyReader, size: u32) ![]DirEntry { + var total_size: u32 = 3; + var meta_hdr: MetadataHeader = undefined; + var dir_hdr: DirHeader = undefined; + var buf: []u8 = undefined; + var buf_rdr: std.io.FixedBufferStream(u8) = undefined; + var i = 0; + var entries: std.ArrayList(DirEntry) = .init(alloc); + defer alloc.free(buf); + while (total_size < size) { + meta_hdr = try rdr.readStruct(MetadataHeader); + if (meta_hdr.not_compressed) { + buf = try alloc.realloc(buf, meta_hdr.size); + _ = try rdr.readAll(rdr); + } else { + alloc.free(buf); + buf = try comp.Decompress(alloc, std.io.limitedReader(rdr, meta_hdr.size)); + } + buf_rdr = std.io.fixedBufferStream(buf); + dir_hdr = try buf_rdr.reader().readStruct(DirHeader); + total_size += 12; + i = 0; + while (i < dir_hdr.count) : (i += 1) { + entries.append(try .init(try .init(buf_rdr, alloc), dir_hdr)); + } + } + return try entries.toOwnedSlice(); +} diff --git a/src/file.zig b/src/file.zig index 2f09441..149f71b 100644 --- a/src/file.zig +++ b/src/file.zig @@ -1,15 +1,23 @@ +const std = @import("std"); + const inode = @import("inode.zig"); const Reader = @import("squashfs.zig").Reader; const MetadataReader = @import("metadata_reader.zig").MetadataReader; const FileOffsetReader = @import("file_offset_reader.zig").FileOffsetReader; +const DirEntry = @import("directory.zig").DirEntry; + +const FileOpenError = error{ + NotFound, + NotDirectory, +}; pub const File = struct { rdr: *Reader, inode: inode.Inode, name: []const u8, - dir_entries: []const void = undefined, //TODO + dir_entries: []DirEntry = undefined, - pub fn fromRef(ref: inode.InodeRef, name: []const u8, rdr: *Reader) !File { + pub fn fromRef(rdr: *Reader, ref: inode.InodeRef, name: []const u8) !File { var offset_rdr: FileOffsetReader = .init(rdr.file, rdr.super.inode_table + ref.block_start); var meta_rdr: MetadataReader = .init(rdr.super.comp, offset_rdr.any(), rdr.alloc.allocator()); try meta_rdr.skip(ref.offset); @@ -20,4 +28,35 @@ pub const File = struct { .name = name, }; } + + pub fn fromDirEntry(rdr: *Reader, ent: DirEntry) !File { + var offset_rdr: FileOffsetReader = .init(rdr.file, rdr.super.inode_table + ent.inode_block_start); + var meta_rdr: MetadataReader = .init( + rdr.super.comp, + offset_rdr.any(), + rdr.alloc, + ); + try meta_rdr.skip(ent.inode_offset); + const in = try inode.readInode(meta_rdr, rdr.super.block_size, rdr.alloc.allocator()); + return .{ + .rdr = rdr, + .inode = in, + .name = ent.name, + }; + } + + pub fn open(self: File, path: []const u8) (anyerror || FileOpenError)!File { + switch (self.inode.header.inode_type) { + .dir, .ext_dir => {}, + else => return FileOpenError.NotDirectory, + } + const clean_path: []const u8 = if (std.mem.startsWith(u8, path, "/")) { + return path[1..]; + } else { + return path; + }; + const path_split = std.mem.splitAny(u8, clean_path, "/"); + } + + fn readDirEntries(self: *File) (anyerror || FileOpenError)!File {} }; diff --git a/src/metadata_reader.zig b/src/metadata_reader.zig index ccf897d..8a5f105 100644 --- a/src/metadata_reader.zig +++ b/src/metadata_reader.zig @@ -3,7 +3,7 @@ const io = std.io; const CompressionType = @import("decompress.zig").CompressionType; -const MetadataHeader = packed struct { +pub const MetadataHeader = packed struct { size: u15, not_compressed: bool, }; diff --git a/src/root.zig b/src/root.zig new file mode 100644 index 0000000..9e4b986 --- /dev/null +++ b/src/root.zig @@ -0,0 +1,3 @@ +pub const Reader = @import("squashfs.zig").Reader; + +pub const File = @import("file.zig").File;