Added some doc

This commit is contained in:
Caleb Gardner
2025-05-21 21:38:05 -05:00
parent 213dfa8b92
commit af06021b1b
4 changed files with 80 additions and 25 deletions
+59 -11
View File
@@ -9,6 +9,8 @@ const Reader = @import("reader.zig").Reader;
const DirEntry = @import("directory.zig").DirEntry; const DirEntry = @import("directory.zig").DirEntry;
const MetadataReader = @import("readers/metadata.zig").MetadataReader; const MetadataReader = @import("readers/metadata.zig").MetadataReader;
/// A file or directory inside of a squashfs.
/// Make sure to call deinit();
pub const File = struct { pub const File = struct {
name: []const u8, name: []const u8,
inode: inode.Inode, inode: inode.Inode,
@@ -23,23 +25,25 @@ pub const File = struct {
NotFound, NotFound,
}; };
fn fromDirEntry(read: *Reader, ent: DirEntry) !File { fn fromDirEntry(reader: *Reader, ent: DirEntry) !File {
var offset_rdr = read.holder.readerAt(ent.block_start + read.super.inode_table_start); var offset_rdr = reader.holder.readerAt(ent.block_start + reader.super.inode_table_start);
var meta_rdr: MetadataReader = try .init( var meta_rdr: MetadataReader = .init(
read.alloc, reader.alloc,
reader.super.decomp,
offset_rdr.any(), offset_rdr.any(),
read.super.decomp,
); );
defer meta_rdr.deinit(); defer meta_rdr.deinit();
try meta_rdr.skip(ent.offset); try meta_rdr.skip(ent.offset);
return .{ const out: File = .{
.name = ent.name, .name = try reader.alloc.alloc(u8, ent.name.len),
.inode = try .init( .inode = try .init(
read.alloc, reader.alloc,
meta_rdr.any(), meta_rdr.any(),
read.super.block_size, reader.super.block_size,
), ),
}; };
std.mem.copyForwards(u8, @constCast(out.name), ent.name);
return out;
} }
pub fn deinit(self: *File, alloc: std.mem.Allocator) void { pub fn deinit(self: *File, alloc: std.mem.Allocator) void {
@@ -54,6 +58,14 @@ pub const File = struct {
} }
} }
pub fn isDir(self: File) bool {
return switch (self.inode.header.inode_type) {
.dir, .ext_dir => true,
else => false,
};
}
/// If the File is a directory, tries to return the file at path.
pub fn open(self: *File, reader: *Reader, path: []const u8) !File { pub fn open(self: *File, reader: *Reader, path: []const u8) !File {
return self.realOpen(reader, path, true); return self.realOpen(reader, path, true);
} }
@@ -79,6 +91,7 @@ pub const File = struct {
return fil.realOpen(reader, clean_path[split_idx..], false); return fil.realOpen(reader, clean_path[split_idx..], false);
} }
/// If the File is a symlink, returns the symlink's target path.
pub fn symPath(self: File) ![]const u8 { pub fn symPath(self: File) ![]const u8 {
return switch (self.inode.data) { return switch (self.inode.data) {
.sym => |s| s.target, .sym => |s| s.target,
@@ -87,11 +100,23 @@ pub const File = struct {
}; };
} }
pub fn iterator(self: *File, read: *Reader) !FileIterator { /// If the File is a directory, returns an iterator that iterates over it's children.
pub fn iterator(self: *File, reader: *Reader) !FileIterator {
switch (self.inode.header.inode_type) { switch (self.inode.header.inode_type) {
.dir, ext_dir => {} .dir, .ext_dir => {},
else => return FileError.NotDirectory, else => return FileError.NotDirectory,
} }
try self.readDirEntries(reader);
var files = try reader.alloc.alloc(File, self.dirEntries.?.count());
var dirEntryIter = self.dirEntries.?.valueIterator();
var i: u32 = 0;
while (dirEntryIter.next()) |ent| : (i += 1) {
files[i] = try .fromDirEntry(reader, ent.*);
}
return .{
.alloc = reader.alloc,
.files = files,
};
} }
fn readDirEntries(self: *File, reader: *Reader) !void { fn readDirEntries(self: *File, reader: *Reader) !void {
@@ -123,6 +148,7 @@ pub const File = struct {
self.dirEntries = try directory.readDirectory(reader.alloc, meta_rdr.any(), size); self.dirEntries = try directory.readDirectory(reader.alloc, meta_rdr.any(), size);
} }
/// If the file is a normal file, reads it's data.
pub fn read(self: *File, bytes: []u8) !usize { pub fn read(self: *File, bytes: []u8) !usize {
if (self.data_rdr == null) { if (self.data_rdr == null) {
return FileError.NotNormalFile; return FileError.NotNormalFile;
@@ -130,3 +156,25 @@ pub const File = struct {
return self.data_rdr.?.read(bytes); return self.data_rdr.?.read(bytes);
} }
}; };
const FileIterator = struct {
alloc: std.mem.Allocator,
files: []File,
curIndex: u32 = 0,
pub fn next(self: *FileIterator) ?File {
if (self.curIndex >= self.files.len) return null;
defer self.curIndex += 1;
return self.files[self.curIndex];
}
pub fn reset(self: *FileIterator) void {
self.curIndex = 0;
}
pub fn deinit(self: *FileIterator) void {
for (self.files) |*f| {
f.deinit(self.alloc);
}
self.alloc.free(self.files);
}
};
+9 -6
View File
@@ -10,6 +10,8 @@ const MetadataReader = @import("readers/metadata.zig").MetadataReader;
const DirEntry = @import("directory.zig").DirEntry; const DirEntry = @import("directory.zig").DirEntry;
const FragEntry = @import("readers/data.zig").FragEntry; const FragEntry = @import("readers/data.zig").FragEntry;
/// A squashfs archive reader. Make sure to call deinit().
/// For most actions, you'll want to use the Reader.root File.
pub const Reader = struct { pub const Reader = struct {
alloc: std.mem.Allocator, alloc: std.mem.Allocator,
holder: FileHolder, holder: FileHolder,
@@ -76,14 +78,15 @@ pub const Reader = struct {
} }
}; };
test "reader" { test "root iter" {
const test_sfs_path = "testing/LinuxPATest.sfs"; const test_sfs_path = "testing/LinuxPATest.sfs";
const test_file_path = "PortableApps/PortableApps.com/Data/PortableAppsMenu.ini"; // const test_file_path = "PortableApps/PortableApps.com/Data/PortableAppsMenu.ini";
var rdr: Reader = try .init(std.testing.allocator, test_sfs_path, 0); var rdr: Reader = try .init(std.testing.allocator, test_sfs_path, 0);
defer rdr.deinit(); defer rdr.deinit();
var fil = try rdr.root.open(&rdr, test_file_path); var rootIter = try rdr.root.iterator(&rdr);
defer fil.deinit(rdr.alloc); defer rootIter.deinit();
while (rootIter.next()) |f| {
std.debug.print("{s}\n", .{fil.name}); std.debug.print("{s}\n", .{f.name});
}
} }
+10 -7
View File
@@ -19,7 +19,7 @@ pub const DataReader = struct {
rdr: FileOffsetReader, rdr: FileOffsetReader,
block_size: u32, block_size: u32,
sizes: []BlockSize, sizes: []BlockSize,
frag_rdr: ?DataReader = null, frag_data: ?[]u8 = null,
next_block_num: u32 = 0, next_block_num: u32 = 0,
cur_bloc: []u8 = undefined, cur_bloc: []u8 = undefined,
@@ -60,8 +60,11 @@ pub const DataReader = struct {
errdefer out.deinit(); errdefer out.deinit();
if (frag_idx != 0xFFFFFFFF) { if (frag_idx != 0xFFFFFFFF) {
const frag_entry = try reader.frag_table.getValue(frag_idx); const frag_entry = try reader.frag_table.getValue(frag_idx);
out.frag_rdr = try .fromFragEntry(reader, frag_entry); var frag_rdr = try .fromFragEntry(reader, frag_entry);
try out.frag_rdr.?.skip(frag_offset); defer frag_rdr.deinit();
try frag_rdr.skip(frag_offset);
out.frag_data = try reader.alloc.alloc(u8, size % out.block_size);
_ = try frag_rdr.any().readAll(out.frag_data);
} }
return out; return out;
} }
@@ -80,7 +83,7 @@ pub const DataReader = struct {
pub fn deinit(self: *DataReader) void { pub fn deinit(self: *DataReader) void {
self.alloc.free(self.sizes); self.alloc.free(self.sizes);
if (self.cur_bloc.len > 0) self.alloc.free(self.cur_bloc); if (self.cur_bloc.len > 0) self.alloc.free(self.cur_bloc);
if (self.frag_rdr != null) self.frag_rdr.?.deinit(); if (self.frag_data != null) self.alloc.free(self.frag_data);
} }
pub fn skip(self: *DataReader, offset: u32) !void { pub fn skip(self: *DataReader, offset: u32) !void {
@@ -101,9 +104,9 @@ pub const DataReader = struct {
} }
const siz = self.sizes[self.next_block_num]; const siz = self.sizes[self.next_block_num];
self.next_block_num += 1; self.next_block_num += 1;
if (self.next_block_num == self.sizes.len - 1 and self.frag_rdr != null) { if (self.next_block_num == self.sizes.len - 1 and self.frag_data != null) {
try self.sizeBlock(self.sizes % self.block_size); try self.sizeBlock(self.frag_data.len);
_ = try self.frag_rdr.?.readAll(self.cur_bloc); @memcpy(self.cur_bloc, self.frag_data);
return; return;
} }
if (siz.size == 0) { if (siz.size == 0) {
+1
View File
@@ -8,6 +8,7 @@ const MetadataReader = @import("readers/metadata.zig").MetadataReader;
const TableError = error{InvalidIndex}; const TableError = error{InvalidIndex};
/// A lazily read squashfs table.
pub fn Table( pub fn Table(
comptime T: type, comptime T: type,
) type { ) type {