Added basic test
Fixed various bugs
This commit is contained in:
@@ -119,7 +119,7 @@ pub fn main() !void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const fil = try std.fs.cwd().openFile(filename, .{});
|
const fil = try std.fs.cwd().openFile(filename, .{});
|
||||||
var rdr = squashfs.FileReader.init(
|
var rdr = squashfs.SfsFile.init(
|
||||||
alloc.allocator(),
|
alloc.allocator(),
|
||||||
fil,
|
fil,
|
||||||
offset,
|
offset,
|
||||||
|
|||||||
+5
-5
@@ -17,7 +17,7 @@ const RawEntry = struct {
|
|||||||
name: []const u8,
|
name: []const u8,
|
||||||
|
|
||||||
pub fn init(alloc: std.mem.Allocator, rdr: anytype) !RawEntry {
|
pub fn init(alloc: std.mem.Allocator, rdr: anytype) !RawEntry {
|
||||||
const fixed: [8]u8 = undefined;
|
var fixed: [8]u8 = undefined;
|
||||||
_ = try rdr.read(&fixed);
|
_ = try rdr.read(&fixed);
|
||||||
const size = std.mem.readInt(u16, fixed[6..8], .little);
|
const size = std.mem.readInt(u16, fixed[6..8], .little);
|
||||||
const name = try alloc.alloc(u8, size + 1);
|
const name = try alloc.alloc(u8, size + 1);
|
||||||
@@ -25,7 +25,7 @@ const RawEntry = struct {
|
|||||||
return .{
|
return .{
|
||||||
.offset = std.mem.readInt(u16, fixed[0..2], .little),
|
.offset = std.mem.readInt(u16, fixed[0..2], .little),
|
||||||
.num_offset = std.mem.readInt(i16, fixed[2..4], .little),
|
.num_offset = std.mem.readInt(i16, fixed[2..4], .little),
|
||||||
.type = std.mem.readInt(u16, fixed[4..6], .little),
|
.type = @enumFromInt(std.mem.readInt(u16, fixed[4..6], .little)),
|
||||||
.size = size,
|
.size = size,
|
||||||
.name = name,
|
.name = name,
|
||||||
};
|
};
|
||||||
@@ -44,8 +44,8 @@ pub const Entry = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn readDirectory(alloc: std.mem.Allocator, rdr: anytype, size: u32) []Entry {
|
pub fn readDirectory(alloc: std.mem.Allocator, rdr: anytype, size: u32) ![]Entry {
|
||||||
const entries: std.ArrayList(Entry) = .init(alloc);
|
var entries: std.ArrayList(Entry) = .init(alloc);
|
||||||
errdefer entries.deinit();
|
errdefer entries.deinit();
|
||||||
var cur_red: u32 = 3; // dir size includes "." & "..", so its actual size is off by 3.
|
var cur_red: u32 = 3; // dir size includes "." & "..", so its actual size is off by 3.
|
||||||
var hdr: Header = undefined;
|
var hdr: Header = undefined;
|
||||||
@@ -60,7 +60,7 @@ pub fn readDirectory(alloc: std.mem.Allocator, rdr: anytype, size: u32) []Entry
|
|||||||
entries.appendAssumeCapacity(.{
|
entries.appendAssumeCapacity(.{
|
||||||
.block = hdr.block,
|
.block = hdr.block,
|
||||||
.offset = raw_ent.offset,
|
.offset = raw_ent.offset,
|
||||||
.num = hdr.num + raw_ent.num_offset,
|
.num = @truncate(@abs(@as(i64, hdr.num) + raw_ent.num_offset)),
|
||||||
.type = raw_ent.type,
|
.type = raw_ent.type,
|
||||||
.name = raw_ent.name,
|
.name = raw_ent.name,
|
||||||
});
|
});
|
||||||
|
|||||||
+44
-12
@@ -7,6 +7,7 @@ const Inode = @import("inode.zig");
|
|||||||
const SfsReader = @import("reader.zig").SfsReader;
|
const SfsReader = @import("reader.zig").SfsReader;
|
||||||
const ToReader = @import("reader/to_read.zig").ToRead;
|
const ToReader = @import("reader/to_read.zig").ToRead;
|
||||||
const ExtractionOptions = @import("extract_options.zig");
|
const ExtractionOptions = @import("extract_options.zig");
|
||||||
|
const DataReader = @import("reader/data.zig").DataReader;
|
||||||
const Compression = @import("superblock.zig").Compression;
|
const Compression = @import("superblock.zig").Compression;
|
||||||
const MetadataReader = @import("reader/metadata.zig").MetadataReader;
|
const MetadataReader = @import("reader/metadata.zig").MetadataReader;
|
||||||
|
|
||||||
@@ -27,7 +28,7 @@ pub fn File(comptime T: type) type {
|
|||||||
/// Directory entries. Only populated on directories.
|
/// Directory entries. Only populated on directories.
|
||||||
entries: ?[]DirEntry = null,
|
entries: ?[]DirEntry = null,
|
||||||
/// File reader. Only populated on regular files.
|
/// File reader. Only populated on regular files.
|
||||||
// data_reader: ?DataReader
|
data_reader: ?DataReader(T) = null,
|
||||||
|
|
||||||
pub fn init(rdr: *SfsReader(T), inode: Inode, name: []const u8) !Self {
|
pub fn init(rdr: *SfsReader(T), inode: Inode, name: []const u8) !Self {
|
||||||
var out = Self{
|
var out = Self{
|
||||||
@@ -37,33 +38,60 @@ pub fn File(comptime T: type) type {
|
|||||||
};
|
};
|
||||||
switch (inode.data) {
|
switch (inode.data) {
|
||||||
.dir => |d| {
|
.dir => |d| {
|
||||||
const meta = MetadataReader(T).init(
|
var meta = MetadataReader(T).init(
|
||||||
rdr.alloc,
|
rdr.alloc,
|
||||||
rdr.super.comp,
|
rdr.super.comp,
|
||||||
rdr.rdr,
|
rdr.rdr,
|
||||||
d.block + rdr.super.dir_start,
|
d.block + rdr.super.dir_start,
|
||||||
);
|
);
|
||||||
try meta.skip(d.offset);
|
try meta.skip(d.offset);
|
||||||
out.entries = try dir.readDirectory(rdr.alloc, meta, d.size);
|
out.entries = try dir.readDirectory(rdr.alloc, &meta, d.size);
|
||||||
},
|
},
|
||||||
.ext_dir => |d| {
|
.ext_dir => |d| {
|
||||||
const meta = MetadataReader(T).init(
|
var meta = MetadataReader(T).init(
|
||||||
rdr.alloc,
|
rdr.alloc,
|
||||||
rdr.super.comp,
|
rdr.super.comp,
|
||||||
rdr.rdr,
|
rdr.rdr,
|
||||||
d.block + rdr.super.dir_start,
|
d.block + rdr.super.dir_start,
|
||||||
);
|
);
|
||||||
try meta.skip(d.offset);
|
try meta.skip(d.offset);
|
||||||
out.entries = try dir.readDirectory(rdr.alloc, meta, d.size);
|
out.entries = try dir.readDirectory(rdr.alloc, &meta, d.size);
|
||||||
},
|
},
|
||||||
.file => |f| {
|
.file => |f| {
|
||||||
_ = f;
|
out.data_reader = try .init(
|
||||||
//TODO
|
rdr.alloc,
|
||||||
|
rdr.rdr,
|
||||||
|
rdr.super.comp,
|
||||||
|
f.block,
|
||||||
|
f.size,
|
||||||
|
f.block_sizes,
|
||||||
|
rdr.super.block_size,
|
||||||
|
);
|
||||||
|
if (f.hasFragment()) {
|
||||||
|
try out.data_reader.?.addFragment(
|
||||||
|
try rdr.frag_table.get(f.frag_idx),
|
||||||
|
f.frag_offset,
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
.ext_file => |f| {
|
.ext_file => |f| {
|
||||||
_ = f;
|
out.data_reader = try .init(
|
||||||
//TODO
|
rdr.alloc,
|
||||||
|
rdr.rdr,
|
||||||
|
rdr.super.comp,
|
||||||
|
f.block,
|
||||||
|
f.size,
|
||||||
|
f.block_sizes,
|
||||||
|
rdr.super.block_size,
|
||||||
|
);
|
||||||
|
if (f.hasFragment()) {
|
||||||
|
try out.data_reader.?.addFragment(
|
||||||
|
try rdr.frag_table.get(f.frag_idx),
|
||||||
|
f.frag_offset,
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
else => {},
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -76,9 +104,13 @@ pub fn File(comptime T: type) type {
|
|||||||
}
|
}
|
||||||
self.rdr.alloc.free(self.entries.?);
|
self.rdr.alloc.free(self.entries.?);
|
||||||
}
|
}
|
||||||
// if(self.data_reader != null){
|
if (self.data_reader != null) {
|
||||||
// self.data_reader.?.deinit();
|
self.data_reader.?.deinit();
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(self: Self) !void {
|
||||||
|
_ = self;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-21
@@ -4,12 +4,6 @@ const dir = @import("inode/dir.zig");
|
|||||||
const file = @import("inode/file.zig");
|
const file = @import("inode/file.zig");
|
||||||
const misc = @import("inode/misc.zig");
|
const misc = @import("inode/misc.zig");
|
||||||
|
|
||||||
const Reader = @import("reader.zig");
|
|
||||||
const DirEntry = @import("directory.zig").Entry;
|
|
||||||
const ToRead = @import("reader/to_read.zig").ToRead;
|
|
||||||
const Compression = @import("superblock.zig").Compression;
|
|
||||||
const MetadataReader = @import("reader/metadata.zig").MetadataReader;
|
|
||||||
|
|
||||||
pub const Ref = packed struct {
|
pub const Ref = packed struct {
|
||||||
offset: u16,
|
offset: u16,
|
||||||
block: u32,
|
block: u32,
|
||||||
@@ -67,21 +61,21 @@ data: Data,
|
|||||||
pub fn init(rdr: anytype, alloc: std.mem.Allocator, block_size: u32) !Self {
|
pub fn init(rdr: anytype, alloc: std.mem.Allocator, block_size: u32) !Self {
|
||||||
var hdr: Header = undefined;
|
var hdr: Header = undefined;
|
||||||
_ = try rdr.read(std.mem.asBytes(&hdr));
|
_ = try rdr.read(std.mem.asBytes(&hdr));
|
||||||
const data = switch (hdr.type) {
|
const data: Data = switch (hdr.type) {
|
||||||
.dir => .{ .dir = .init(rdr) },
|
.dir => .{ .dir = try .init(rdr) },
|
||||||
.file => .{ .file = .init(rdr, alloc, block_size) },
|
.file => .{ .file = try .init(rdr, alloc, block_size) },
|
||||||
.symlink => .{ .symlink = .init(rdr, alloc) },
|
.symlink => .{ .symlink = try .init(rdr, alloc) },
|
||||||
.block_dev => .{ .block_dev = .init(rdr) },
|
.block_dev => .{ .block_dev = try .init(rdr) },
|
||||||
.char_dev => .{ .char_dev = .init(rdr) },
|
.char_dev => .{ .char_dev = try .init(rdr) },
|
||||||
.fifo => .{ .fifo = .init(rdr) },
|
.fifo => .{ .fifo = try .init(rdr) },
|
||||||
.socket => .{ .socket = .init(rdr) },
|
.socket => .{ .socket = try .init(rdr) },
|
||||||
.ext_dir => .{ .ext_dir = .init(rdr) },
|
.ext_dir => .{ .ext_dir = try .init(rdr) },
|
||||||
.ext_file => .{ .ext_file = .init(rdr, alloc, block_size) },
|
.ext_file => .{ .ext_file = try .init(rdr, alloc, block_size) },
|
||||||
.ext_symlink => .{ .ext_symlink = .init(rdr, alloc) },
|
.ext_symlink => .{ .ext_symlink = try .init(rdr, alloc) },
|
||||||
.ext_block_dev => .{ .ext_block_dev = .init(rdr) },
|
.ext_block_dev => .{ .ext_block_dev = try .init(rdr) },
|
||||||
.ext_char_dev => .{ .ext_char_dev = .init(rdr) },
|
.ext_char_dev => .{ .ext_char_dev = try .init(rdr) },
|
||||||
.ext_fifo => .{ .ext_fifo = .init(rdr) },
|
.ext_fifo => .{ .ext_fifo = try .init(rdr) },
|
||||||
.ext_socket => .{ .ext_socket = .init(rdr) },
|
.ext_socket => .{ .ext_socket = try .init(rdr) },
|
||||||
};
|
};
|
||||||
return .{
|
return .{
|
||||||
.hdr = hdr,
|
.hdr = hdr,
|
||||||
|
|||||||
+4
-4
@@ -8,8 +8,8 @@ pub const Dir = packed struct {
|
|||||||
parent_num: u32,
|
parent_num: u32,
|
||||||
|
|
||||||
pub fn init(rdr: anytype) !Dir {
|
pub fn init(rdr: anytype) !Dir {
|
||||||
const out: Dir = undefined;
|
var out: Dir = undefined;
|
||||||
_ = rdr.read(std.mem.asBytes(&out));
|
_ = try rdr.read(std.mem.asBytes(&out));
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -24,8 +24,8 @@ pub const ExtDir = packed struct {
|
|||||||
xattr_idx: u32,
|
xattr_idx: u32,
|
||||||
|
|
||||||
pub fn init(rdr: anytype) !ExtDir {
|
pub fn init(rdr: anytype) !ExtDir {
|
||||||
const out: ExtDir = undefined;
|
var out: ExtDir = undefined;
|
||||||
_ = rdr.read(std.mem.asBytes(&out));
|
_ = try rdr.read(std.mem.asBytes(&out));
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+14
-8
@@ -9,7 +9,7 @@ pub const BlockSize = packed struct {
|
|||||||
pub const File = struct {
|
pub const File = struct {
|
||||||
block: u32,
|
block: u32,
|
||||||
frag_idx: u32,
|
frag_idx: u32,
|
||||||
offset: u32,
|
frag_offset: u32,
|
||||||
size: u32,
|
size: u32,
|
||||||
block_sizes: []BlockSize,
|
block_sizes: []BlockSize,
|
||||||
|
|
||||||
@@ -22,17 +22,20 @@ pub const File = struct {
|
|||||||
if (size % block_size > 0 and frag_idx != 0xffffffff) {
|
if (size % block_size > 0 and frag_idx != 0xffffffff) {
|
||||||
blocks += 1;
|
blocks += 1;
|
||||||
}
|
}
|
||||||
const block_sizes = alloc.alloc(BlockSize, blocks);
|
const block_sizes = try alloc.alloc(BlockSize, blocks);
|
||||||
errdefer alloc.free(block_sizes);
|
errdefer alloc.free(block_sizes);
|
||||||
_ = try rdr.read(std.mem.sliceAsBytes(block_sizes));
|
_ = try rdr.read(std.mem.sliceAsBytes(block_sizes));
|
||||||
return .{
|
return .{
|
||||||
.block = std.mem.readInt(u32, fixed[0..4], .little),
|
.block = std.mem.readInt(u32, fixed[0..4], .little),
|
||||||
.frag_idx = frag_idx,
|
.frag_idx = frag_idx,
|
||||||
.offset = std.mem.readInt(u32, fixed[8..12], .little),
|
.frag_offset = std.mem.readInt(u32, fixed[8..12], .little),
|
||||||
.size = size,
|
.size = size,
|
||||||
.block_sizes = block_sizes,
|
.block_sizes = block_sizes,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
pub fn hasFragment(self: File) bool {
|
||||||
|
return self.frag_idx != 0xffffffff;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ExtFile = struct {
|
pub const ExtFile = struct {
|
||||||
@@ -41,7 +44,7 @@ pub const ExtFile = struct {
|
|||||||
sparse: u64,
|
sparse: u64,
|
||||||
hard_link: u32,
|
hard_link: u32,
|
||||||
frag_idx: u32,
|
frag_idx: u32,
|
||||||
offset: u32,
|
frag_offset: u32,
|
||||||
xattr_idx: u32,
|
xattr_idx: u32,
|
||||||
block_sizes: []BlockSize,
|
block_sizes: []BlockSize,
|
||||||
|
|
||||||
@@ -50,11 +53,11 @@ pub const ExtFile = struct {
|
|||||||
_ = try rdr.read(&fixed);
|
_ = try rdr.read(&fixed);
|
||||||
const size = std.mem.readInt(u64, fixed[8..16], .little);
|
const size = std.mem.readInt(u64, fixed[8..16], .little);
|
||||||
const frag_idx = std.mem.readInt(u32, fixed[28..32], .little);
|
const frag_idx = std.mem.readInt(u32, fixed[28..32], .little);
|
||||||
var blocks: u32 = size / block_size;
|
var blocks: u32 = @truncate(size / block_size);
|
||||||
if (size % block_size > 0 and frag_idx != 0xffffffff) {
|
if (size % block_size > 0 and frag_idx != 0xffffffff) {
|
||||||
blocks += 1;
|
blocks += 1;
|
||||||
}
|
}
|
||||||
const block_sizes = alloc.alloc(BlockSize, blocks);
|
const block_sizes = try alloc.alloc(BlockSize, blocks);
|
||||||
errdefer alloc.free(block_sizes);
|
errdefer alloc.free(block_sizes);
|
||||||
_ = try rdr.read(std.mem.sliceAsBytes(block_sizes));
|
_ = try rdr.read(std.mem.sliceAsBytes(block_sizes));
|
||||||
return .{
|
return .{
|
||||||
@@ -63,9 +66,12 @@ pub const ExtFile = struct {
|
|||||||
.sparse = std.mem.readInt(u64, fixed[16..24], .little),
|
.sparse = std.mem.readInt(u64, fixed[16..24], .little),
|
||||||
.hard_link = std.mem.readInt(u32, fixed[24..28], .little),
|
.hard_link = std.mem.readInt(u32, fixed[24..28], .little),
|
||||||
.frag_idx = frag_idx,
|
.frag_idx = frag_idx,
|
||||||
.offset = std.mem.readInt(u32, fixed[32..36], .little),
|
.frag_offset = std.mem.readInt(u32, fixed[32..36], .little),
|
||||||
.xattr_idx = std.mem.readInt(u32, fixed[36..40], .little),
|
.xattr_idx = std.mem.readInt(u32, fixed[36..40], .little),
|
||||||
.block_sizes = blocks,
|
.block_sizes = block_sizes,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
pub fn hasFragment(self: ExtFile) bool {
|
||||||
|
return self.frag_idx != 0xffffffff;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+6
-6
@@ -9,7 +9,7 @@ pub const Symlink = struct {
|
|||||||
var fixed: [8]u8 = undefined;
|
var fixed: [8]u8 = undefined;
|
||||||
_ = try rdr.read(&fixed);
|
_ = try rdr.read(&fixed);
|
||||||
const size = std.mem.readInt(u32, fixed[4..8], .little);
|
const size = std.mem.readInt(u32, fixed[4..8], .little);
|
||||||
const target = alloc.alloc(u8, size);
|
const target = try alloc.alloc(u8, size);
|
||||||
errdefer alloc.free(target);
|
errdefer alloc.free(target);
|
||||||
_ = try rdr.read(target);
|
_ = try rdr.read(target);
|
||||||
return .{
|
return .{
|
||||||
@@ -29,7 +29,7 @@ pub const ExtSymlink = struct {
|
|||||||
var fixed: [8]u8 = undefined;
|
var fixed: [8]u8 = undefined;
|
||||||
_ = try rdr.read(&fixed);
|
_ = try rdr.read(&fixed);
|
||||||
const size = std.mem.readInt(u32, fixed[4..8], .little);
|
const size = std.mem.readInt(u32, fixed[4..8], .little);
|
||||||
const target = alloc.alloc(u8, size);
|
const target = try alloc.alloc(u8, size);
|
||||||
errdefer alloc.free(target);
|
errdefer alloc.free(target);
|
||||||
_ = try rdr.read(target);
|
_ = try rdr.read(target);
|
||||||
var xattr_idx: u32 = 0;
|
var xattr_idx: u32 = 0;
|
||||||
@@ -47,7 +47,7 @@ pub const Dev = packed struct {
|
|||||||
device: u32,
|
device: u32,
|
||||||
|
|
||||||
pub fn init(rdr: anytype) !Dev {
|
pub fn init(rdr: anytype) !Dev {
|
||||||
const out: Dev = undefined;
|
var out: Dev = undefined;
|
||||||
_ = try rdr.read(std.mem.asBytes(&out));
|
_ = try rdr.read(std.mem.asBytes(&out));
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -59,7 +59,7 @@ pub const ExtDev = packed struct {
|
|||||||
xattr_idx: u32,
|
xattr_idx: u32,
|
||||||
|
|
||||||
pub fn init(rdr: anytype) !ExtDev {
|
pub fn init(rdr: anytype) !ExtDev {
|
||||||
const out: ExtDev = undefined;
|
var out: ExtDev = undefined;
|
||||||
_ = try rdr.read(std.mem.asBytes(&out));
|
_ = try rdr.read(std.mem.asBytes(&out));
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -69,7 +69,7 @@ pub const IPC = packed struct {
|
|||||||
hard_link: u32,
|
hard_link: u32,
|
||||||
|
|
||||||
pub fn init(rdr: anytype) !IPC {
|
pub fn init(rdr: anytype) !IPC {
|
||||||
const out: IPC = undefined;
|
var out: IPC = undefined;
|
||||||
_ = try rdr.read(std.mem.asBytes(&out));
|
_ = try rdr.read(std.mem.asBytes(&out));
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -80,7 +80,7 @@ pub const ExtIPC = packed struct {
|
|||||||
xattr_idx: u32,
|
xattr_idx: u32,
|
||||||
|
|
||||||
pub fn init(rdr: anytype) !ExtIPC {
|
pub fn init(rdr: anytype) !ExtIPC {
|
||||||
const out: ExtIPC = undefined;
|
var out: ExtIPC = undefined;
|
||||||
_ = try rdr.read(std.mem.asBytes(&out));
|
_ = try rdr.read(std.mem.asBytes(&out));
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-15
@@ -29,7 +29,6 @@ pub fn SfsReader(comptime T: type) type {
|
|||||||
/// Export table. Each element is an inode referce.
|
/// Export table. Each element is an inode referce.
|
||||||
/// If accessing directly, keep in mind, the table starts at inode 1, as such it's recommended to use the InodeAt function instead.
|
/// If accessing directly, keep in mind, the table starts at inode 1, as such it's recommended to use the InodeAt function instead.
|
||||||
export_table: Table(Inode.Ref, T) = undefined,
|
export_table: Table(Inode.Ref, T) = undefined,
|
||||||
root: ?File(T) = null,
|
|
||||||
|
|
||||||
pub fn init(alloc: std.mem.Allocator, rdr: T, offset: u64) !Self {
|
pub fn init(alloc: std.mem.Allocator, rdr: T, offset: u64) !Self {
|
||||||
var out: Self = .{
|
var out: Self = .{
|
||||||
@@ -46,28 +45,21 @@ pub fn SfsReader(comptime T: type) type {
|
|||||||
self.id_table.deinit();
|
self.id_table.deinit();
|
||||||
self.frag_table.deinit();
|
self.frag_table.deinit();
|
||||||
self.export_table.deinit();
|
self.export_table.deinit();
|
||||||
if (self.root != null) self.root.?.deinit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn populateRoot(self: *Self) !void {
|
pub fn archiveRoot(self: *Self) !File(T) {
|
||||||
if (self.root != null) return;
|
var meta = MetadataReader(T).init(
|
||||||
const meta = MetadataReader(T).init(
|
|
||||||
self.alloc,
|
self.alloc,
|
||||||
self.super.comp,
|
self.super.comp,
|
||||||
self.rdr,
|
self.rdr,
|
||||||
self.super.inode_start + self.super.root_ref.block,
|
self.super.inode_start + self.super.root_ref.block,
|
||||||
);
|
);
|
||||||
try meta.skip(self.super.root_ref.offset);
|
try meta.skip(self.super.root_ref.offset);
|
||||||
const root_inode: Inode = try .init(meta, self.alloc, self.super.block_size);
|
const root_inode: Inode = try .init(&meta, self.alloc, self.super.block_size);
|
||||||
self.root = try .init(self, root_inode, "");
|
return try .init(self, root_inode, "");
|
||||||
}
|
}
|
||||||
|
pub fn open(self: *Self, path: []const u8) !File(T) {
|
||||||
pub fn archiveRoot(self: *Self) !File {
|
_ = self;
|
||||||
if (self.root == null) try self.populateRoot();
|
|
||||||
return self.root.?;
|
|
||||||
}
|
|
||||||
pub fn open(self: *Self, path: []const u8) !File {
|
|
||||||
if (self.root == null) try self.populateRoot();
|
|
||||||
_ = path;
|
_ = path;
|
||||||
// return self.root.?.open(path);
|
// return self.root.?.open(path);
|
||||||
return error{TODO}.TODO;
|
return error{TODO}.TODO;
|
||||||
@@ -78,7 +70,7 @@ pub fn SfsReader(comptime T: type) type {
|
|||||||
pub fn inodeAt(self: Self, num: u32) !Inode {
|
pub fn inodeAt(self: Self, num: u32) !Inode {
|
||||||
if (!self.super.flags.has_export) return SfsError.NotExportable;
|
if (!self.super.flags.has_export) return SfsError.NotExportable;
|
||||||
const ref = try self.export_table.get(num - 1);
|
const ref = try self.export_table.get(num - 1);
|
||||||
const meta = MetadataReader(T).init(
|
var meta = MetadataReader(T).init(
|
||||||
self.alloc,
|
self.alloc,
|
||||||
self.super.comp,
|
self.super.comp,
|
||||||
self.rdr,
|
self.rdr,
|
||||||
|
|||||||
+5
-11
@@ -27,8 +27,8 @@ pub fn DataReader(comptime T: type) type {
|
|||||||
|
|
||||||
frag: []u8 = &[0]u8{},
|
frag: []u8 = &[0]u8{},
|
||||||
|
|
||||||
read_block: []u8,
|
read_block: []u8 = &[0]u8{},
|
||||||
read_offset: u64,
|
read_offset: u64 = 0,
|
||||||
read_idx: u32 = 0,
|
read_idx: u32 = 0,
|
||||||
|
|
||||||
pub fn init(
|
pub fn init(
|
||||||
@@ -41,7 +41,7 @@ pub fn DataReader(comptime T: type) type {
|
|||||||
block_size: u32,
|
block_size: u32,
|
||||||
) !Self {
|
) !Self {
|
||||||
var cur_offset = init_offset;
|
var cur_offset = init_offset;
|
||||||
const offsets = alloc.alloc(u64, sizes.len);
|
const offsets = try alloc.alloc(u64, sizes.len);
|
||||||
for (0..sizes.len) |i| {
|
for (0..sizes.len) |i| {
|
||||||
offsets[i] = cur_offset;
|
offsets[i] = cur_offset;
|
||||||
cur_offset += sizes[i].size;
|
cur_offset += sizes[i].size;
|
||||||
@@ -74,10 +74,7 @@ pub fn DataReader(comptime T: type) type {
|
|||||||
defer self.alloc.free(block);
|
defer self.alloc.free(block);
|
||||||
_ = try self.comp.decompress(
|
_ = try self.comp.decompress(
|
||||||
self.alloc,
|
self.alloc,
|
||||||
std.io.limitedReader(
|
self.rdr.readerAt(entry.block).reader(),
|
||||||
self.rdr.readerAt(entry.block),
|
|
||||||
entry.size.size,
|
|
||||||
),
|
|
||||||
block,
|
block,
|
||||||
);
|
);
|
||||||
@memcpy(self.frag, block[offset..]);
|
@memcpy(self.frag, block[offset..]);
|
||||||
@@ -106,10 +103,7 @@ pub fn DataReader(comptime T: type) type {
|
|||||||
}
|
}
|
||||||
_ = try self.comp.decompress(
|
_ = try self.comp.decompress(
|
||||||
self.alloc,
|
self.alloc,
|
||||||
std.io.limitedReader(
|
self.rdr.readerAt(self.offsets[idx]).reader(),
|
||||||
self.rdr.readerAt(self.offsets[idx]),
|
|
||||||
self.sizes[idx].size,
|
|
||||||
),
|
|
||||||
block,
|
block,
|
||||||
);
|
);
|
||||||
return block;
|
return block;
|
||||||
|
|||||||
@@ -32,12 +32,12 @@ pub fn MetadataReader(comptime T: type) type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn readNextBlock(self: *Self) !void {
|
fn readNextBlock(self: *Self) !void {
|
||||||
const hdr: MetaHeader = undefined;
|
var hdr: MetaHeader = undefined;
|
||||||
_ = try self.rdr.pread(std.mem.asBytes(hdr), self.offset);
|
_ = try self.rdr.pread(std.mem.asBytes(&hdr), self.offset);
|
||||||
self.offset += 2;
|
self.offset += 2;
|
||||||
self.block_size = try self.comp.decompress(
|
self.block_size = try self.comp.decompress(
|
||||||
self.alloc,
|
self.alloc,
|
||||||
std.io.limitedReader(self.rdr.readerAt(self.offset), hdr.size),
|
self.rdr.readerAt(self.offset).reader(),
|
||||||
&self.block,
|
&self.block,
|
||||||
);
|
);
|
||||||
self.offset += hdr.size;
|
self.offset += hdr.size;
|
||||||
@@ -45,14 +45,14 @@ pub fn MetadataReader(comptime T: type) type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn skip(self: *Self, offset: u32) !void {
|
pub fn skip(self: *Self, offset: u32) !void {
|
||||||
var skipped = 0;
|
var skipped: u32 = 0;
|
||||||
const hdr: MetaHeader = undefined;
|
var hdr: MetaHeader = undefined;
|
||||||
while (offset - skipped >= 8192) {
|
while (offset - skipped >= 8192) {
|
||||||
_ = try self.rdr.pread(std.mem.asBytes(hdr), self.offset);
|
_ = try self.rdr.pread(std.mem.asBytes(&hdr), self.offset);
|
||||||
self.offset += 2 + hdr.size;
|
self.offset += 2 + hdr.size;
|
||||||
skipped += 8192;
|
skipped += 8192;
|
||||||
}
|
}
|
||||||
var to_skip = 0;
|
var to_skip: u32 = 0;
|
||||||
while (skipped < offset) {
|
while (skipped < offset) {
|
||||||
if (self.block_offset >= self.block_size) try self.readNextBlock();
|
if (self.block_offset >= self.block_size) try self.readNextBlock();
|
||||||
to_skip = @min(self.block_size - self.block_offset, offset - skipped);
|
to_skip = @min(self.block_size - self.block_offset, offset - skipped);
|
||||||
@@ -69,7 +69,7 @@ pub fn MetadataReader(comptime T: type) type {
|
|||||||
to_read = @min(buf.len - cur_red, self.block_size - self.block_offset);
|
to_read = @min(buf.len - cur_red, self.block_size - self.block_offset);
|
||||||
@memcpy(buf[cur_red .. cur_red + to_read], self.block[self.block_offset .. self.block_offset + to_read]);
|
@memcpy(buf[cur_red .. cur_red + to_read], self.block[self.block_offset .. self.block_offset + to_read]);
|
||||||
cur_red += to_read;
|
cur_red += to_read;
|
||||||
self.block_offset += to_read;
|
self.block_offset += @truncate(to_read);
|
||||||
}
|
}
|
||||||
return cur_red;
|
return cur_red;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ pub fn ToRead(comptime T: type) type {
|
|||||||
return struct {
|
return struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
|
pub const Error = anyerror;
|
||||||
|
|
||||||
rdr: T,
|
rdr: T,
|
||||||
offset: u64,
|
offset: u64,
|
||||||
|
|
||||||
@@ -20,5 +22,21 @@ pub fn ToRead(comptime T: type) type {
|
|||||||
self.offset += red;
|
self.offset += red;
|
||||||
return red;
|
return red;
|
||||||
}
|
}
|
||||||
|
pub fn readAll(self: *Self, buf: []u8) !usize {
|
||||||
|
var cur_red = try self.read(buf);
|
||||||
|
if (cur_red == 0) return cur_red;
|
||||||
|
var res: usize = 0;
|
||||||
|
while (cur_red < buf.len) {
|
||||||
|
res = try self.read(buf[cur_red..]);
|
||||||
|
if (res == 0) break;
|
||||||
|
cur_red += res;
|
||||||
|
}
|
||||||
|
return cur_red;
|
||||||
|
}
|
||||||
|
pub fn reader(self: anytype) std.io.Reader(*Self, anyerror, read) {
|
||||||
|
return .{
|
||||||
|
.context = @constCast(self),
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-1
@@ -3,4 +3,16 @@ const std = @import("std");
|
|||||||
pub const SfsReader = @import("reader.zig").SfsReader;
|
pub const SfsReader = @import("reader.zig").SfsReader;
|
||||||
pub const ExtractionOptions = @import("extract_options.zig");
|
pub const ExtractionOptions = @import("extract_options.zig");
|
||||||
|
|
||||||
pub const FileReader = SfsReader(std.fs.File);
|
pub const SfsFile = SfsReader(std.fs.File);
|
||||||
|
|
||||||
|
const test_file = "testing/LinuxPATest.sfs";
|
||||||
|
|
||||||
|
test "OpenTest" {
|
||||||
|
const fil = try std.fs.cwd().openFile(test_file, .{});
|
||||||
|
defer fil.close();
|
||||||
|
var rdr: SfsFile = try .init(std.testing.allocator, fil, 0);
|
||||||
|
defer rdr.deinit();
|
||||||
|
std.debug.print("{}\n", .{rdr.super});
|
||||||
|
const root = try rdr.archiveRoot();
|
||||||
|
defer root.deinit();
|
||||||
|
}
|
||||||
|
|||||||
+5
-5
@@ -54,24 +54,24 @@ pub const Compression = enum(u16) {
|
|||||||
pub fn decompress(self: Compression, alloc: std.mem.Allocator, source: anytype, dest: []u8) !usize {
|
pub fn decompress(self: Compression, alloc: std.mem.Allocator, source: anytype, dest: []u8) !usize {
|
||||||
switch (self) {
|
switch (self) {
|
||||||
.gzip => {
|
.gzip => {
|
||||||
const decomp = std.compress.zlib.decompressor(source);
|
var decomp = std.compress.zlib.decompressor(source);
|
||||||
return decomp.read(dest);
|
return decomp.read(dest);
|
||||||
},
|
},
|
||||||
.lzma => {
|
.lzma => {
|
||||||
const decomp = try std.compress.lzma.decompress(alloc, source);
|
var decomp = try std.compress.lzma.decompress(alloc, source);
|
||||||
defer decomp.deinit();
|
defer decomp.deinit();
|
||||||
return decomp.read(dest);
|
return decomp.read(dest);
|
||||||
},
|
},
|
||||||
.lzo => return DecompressError.LzoUnavailable,
|
.lzo => return DecompressError.LzoUnavailable,
|
||||||
.xz => {
|
.xz => {
|
||||||
const decomp = try std.compress.xz.decompress(alloc, source);
|
var decomp = try std.compress.xz.decompress(alloc, source);
|
||||||
defer decomp.deinit();
|
defer decomp.deinit();
|
||||||
return decomp.read(dest);
|
return decomp.read(dest);
|
||||||
},
|
},
|
||||||
.lz4 => return DecompressError.Lz4Unavailable,
|
.lz4 => return DecompressError.Lz4Unavailable,
|
||||||
.zstd => {
|
.zstd => {
|
||||||
const window: [@min(std.compress.zstd.DecompressorOptions.default_window_buffer_len, dest.len)]u8 = undefined;
|
var window: [std.compress.zstd.DecompressorOptions.default_window_buffer_len]u8 = undefined;
|
||||||
const decomp = std.compress.zstd.decompressor(source, .{ .window_buffer = window });
|
var decomp = std.compress.zstd.decompressor(source, .{ .window_buffer = &window });
|
||||||
return decomp.read(dest);
|
return decomp.read(dest);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user