Added some doc
This commit is contained in:
+60
-12
@@ -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.
|
||||||
switch (self.inode.header.inode_type){
|
pub fn iterator(self: *File, reader: *Reader) !FileIterator {
|
||||||
.dir, ext_dir => {}
|
switch (self.inode.header.inode_type) {
|
||||||
|
.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
@@ -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
@@ -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) {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user