Further progress
Mainly focusing on getting things more consistent
This commit is contained in:
+22
-4
@@ -1,6 +1,24 @@
|
||||
dereference_symlinks: bool,
|
||||
unbreak_symlinks: bool,
|
||||
ignore_permissions: bool,
|
||||
const std = @import("std");
|
||||
|
||||
const Self = @This();
|
||||
|
||||
/// Replace symlinks with their targets
|
||||
dereference_symlinks: bool = false,
|
||||
/// Always extract a symlink's target if it's part of the archive.
|
||||
/// May result in the symlink's target being changed.
|
||||
unbreak_symlinks: bool = false,
|
||||
/// Do not set file's permissions & owner when extracted.
|
||||
ignore_permissions: bool = false,
|
||||
|
||||
processor_count: u16,
|
||||
// max_memory: u64,
|
||||
|
||||
pol: std.Thread.Pool = undefined,
|
||||
|
||||
pub fn init(alloc: std.mem.Allocator, thread_count: u16) !Self {
|
||||
var out: Self = .{};
|
||||
out.pol.init(.{
|
||||
.allocator = alloc,
|
||||
.n_jobs = thread_count,
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
+82
-1
@@ -1,3 +1,84 @@
|
||||
const std = @import("std");
|
||||
|
||||
const dir = @import("directory.zig");
|
||||
|
||||
const DirEntry = dir.Entry;
|
||||
const Inode = @import("inode.zig");
|
||||
const SfsReader = @import("reader.zig").SfsReader;
|
||||
const ToReader = @import("reader/to_read.zig").ToRead;
|
||||
const ExtractionOptions = @import("extract_options.zig");
|
||||
const Compression = @import("superblock.zig").Compression;
|
||||
const MetadataReader = @import("reader/metadata.zig").MetadataReader;
|
||||
|
||||
pub const FileError = error{
|
||||
NotRegular,
|
||||
NotDirectory,
|
||||
};
|
||||
|
||||
pub fn File(comptime T: type) type {
|
||||
return struct {};
|
||||
return struct {
|
||||
const Self = @This();
|
||||
|
||||
rdr: *SfsReader(T),
|
||||
|
||||
inode: Inode,
|
||||
name: []const u8,
|
||||
|
||||
/// Directory entries. Only populated on directories.
|
||||
entries: ?[]DirEntry = null,
|
||||
/// File reader. Only populated on regular files.
|
||||
// data_reader: ?DataReader
|
||||
|
||||
pub fn init(rdr: *SfsReader(T), inode: Inode, name: []const u8) !Self {
|
||||
var out = Self{
|
||||
.rdr = rdr,
|
||||
.inode = inode,
|
||||
.name = name,
|
||||
};
|
||||
switch (inode.data) {
|
||||
.dir => |d| {
|
||||
const meta = MetadataReader(T).init(
|
||||
rdr.alloc,
|
||||
rdr.super.comp,
|
||||
rdr.rdr,
|
||||
d.block + rdr.super.dir_start,
|
||||
);
|
||||
try meta.skip(d.offset);
|
||||
out.entries = try dir.readDirectory(rdr.alloc, meta, d.size);
|
||||
},
|
||||
.ext_dir => |d| {
|
||||
const meta = MetadataReader(T).init(
|
||||
rdr.alloc,
|
||||
rdr.super.comp,
|
||||
rdr.rdr,
|
||||
d.block + rdr.super.dir_start,
|
||||
);
|
||||
try meta.skip(d.offset);
|
||||
out.entries = try dir.readDirectory(rdr.alloc, meta, d.size);
|
||||
},
|
||||
.file => |f| {
|
||||
_ = f;
|
||||
//TODO
|
||||
},
|
||||
.ext_file => |f| {
|
||||
_ = f;
|
||||
//TODO
|
||||
},
|
||||
}
|
||||
return out;
|
||||
}
|
||||
pub fn deinit(self: Self) void {
|
||||
self.rdr.alloc.free(self.name);
|
||||
self.inode.deinit(self.rdr.alloc);
|
||||
if (self.entries != null) {
|
||||
for (self.entries.?) |e| {
|
||||
e.deinit(self.rdr.alloc);
|
||||
}
|
||||
self.rdr.alloc.free(self.entries.?);
|
||||
}
|
||||
// if(self.data_reader != null){
|
||||
// self.data_reader.?.deinit();
|
||||
// }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
+9
-6
@@ -4,6 +4,8 @@ const dir = @import("inode/dir.zig");
|
||||
const file = @import("inode/file.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;
|
||||
@@ -86,10 +88,11 @@ pub fn init(rdr: anytype, alloc: std.mem.Allocator, block_size: u32) !Self {
|
||||
.data = data,
|
||||
};
|
||||
}
|
||||
pub fn initFromRef(p_rdr: anytype, comp: Compression, ref: Ref, table_start: u64, alloc: std.mem.Allocator, block_size: u32) !Self {
|
||||
const rdr: ToRead(@TypeOf(p_rdr)) = .init(p_rdr, ref.block + table_start);
|
||||
const meta_rdr: MetadataReader(ToRead(@TypeOf(p_rdr))) = try .init(alloc, comp, rdr);
|
||||
defer meta_rdr.deinit();
|
||||
try meta_rdr.skip(ref.offset);
|
||||
return init(meta_rdr, alloc, block_size);
|
||||
pub fn deinit(self: Self, alloc: std.mem.Allocator) void {
|
||||
switch (self.data) {
|
||||
.file => |f| alloc.free(f.block_sizes),
|
||||
.ext_file => |f| alloc.free(f.block_sizes),
|
||||
.symlink => |s| alloc.free(s.target),
|
||||
.ext_symlink => |s| alloc.free(s.target),
|
||||
}
|
||||
}
|
||||
|
||||
+18
-5
@@ -5,8 +5,13 @@ const Table = @import("table.zig").Table;
|
||||
const PRead = @import("reader/p_read.zig").PRead;
|
||||
const FragEntry = @import("fragment.zig").FragEntry;
|
||||
const Superblock = @import("superblock.zig").Superblock;
|
||||
const MetadataReader = @import("reader/metadata.zig").MetadataReader;
|
||||
|
||||
pub fn Reader(comptime T: type) type {
|
||||
pub const SfsError = error{
|
||||
NotExportable,
|
||||
};
|
||||
|
||||
pub fn SfsReader(comptime T: type) type {
|
||||
comptime std.debug.assert(std.meta.hasFn(T, "pread"));
|
||||
|
||||
return struct {
|
||||
@@ -40,14 +45,22 @@ pub fn Reader(comptime T: type) type {
|
||||
self.id_table.deinit();
|
||||
self.frag_table.deinit();
|
||||
self.export_table.deinit();
|
||||
// if (self.root != null) self.root.?.deinit();
|
||||
}
|
||||
|
||||
/// Returns the inode with the given Inode Number.
|
||||
/// Requires for the archive to have an export table.
|
||||
pub fn InodeAt(self: Self, num: u32) !Inode {
|
||||
/// Requires the archive to have an export table.
|
||||
pub fn inodeAt(self: Self, num: u32) !Inode {
|
||||
if (!self.super.flags.has_export) return SfsError.NotExportable;
|
||||
const ref = try self.export_table.get(num - 1);
|
||||
_ = ref;
|
||||
return error{TODO}.TODO;
|
||||
const meta = MetadataReader(T).init(
|
||||
self.alloc,
|
||||
self.super.comp,
|
||||
self.rdr,
|
||||
self.super.inode_start + ref.block,
|
||||
);
|
||||
try meta.skip(ref.offset);
|
||||
return .init(meta, self.alloc, self.super.block_size);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
const std = @import("std");
|
||||
|
||||
const PRead = @import("p_read.zig").Pread;
|
||||
const FragEntry = @import("../fragment.zig").FragEntry;
|
||||
const BlockSize = @import("../inode/file.zig").BlockSize;
|
||||
const Compression = @import("../superblock.zig").Compression;
|
||||
|
||||
pub fn DataReader(comptime T: type) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
|
||||
alloc: std.mem.Allocator,
|
||||
|
||||
rdr: PRead(T),
|
||||
comp: Compression,
|
||||
offsets: []BlockSize,
|
||||
|
||||
file_size: u64,
|
||||
block_size: u32,
|
||||
sizes: []BlockSize,
|
||||
|
||||
frag: []u8 = undefined,
|
||||
|
||||
pub fn init(
|
||||
alloc: std.mem.Allocator,
|
||||
rdr: PRead(T),
|
||||
comp: Compression,
|
||||
init_offset: u64,
|
||||
file_size: u64,
|
||||
sizes: []BlockSize,
|
||||
block_size: u32,
|
||||
) !Self {
|
||||
var cur_offset = init_offset;
|
||||
const offsets = alloc.alloc(u64, sizes.len);
|
||||
for (0..sizes.len) |i| {
|
||||
offsets[i] = cur_offset;
|
||||
cur_offset += sizes[i].size;
|
||||
}
|
||||
return .{
|
||||
.alloc = alloc,
|
||||
.rdr = rdr,
|
||||
.comp = comp,
|
||||
.offsets = offsets,
|
||||
.file_size = file_size,
|
||||
.block_size = block_size,
|
||||
.sizes = sizes,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn addFragment(self: *Self, entry: FragEntry, offset: u32) void {
|
||||
self.frag = self.alloc.alloc(u8, self.file_size % self.block_size);
|
||||
//TODO:
|
||||
}
|
||||
};
|
||||
}
|
||||
+16
-7
@@ -1,5 +1,6 @@
|
||||
const std = @import("std");
|
||||
|
||||
const PRead = @import("p_read.zig").PRead;
|
||||
const Compression = @import("../superblock.zig").Compression;
|
||||
|
||||
const MetaHeader = packed struct {
|
||||
@@ -14,36 +15,44 @@ pub fn MetadataReader(comptime T: type) type {
|
||||
|
||||
alloc: std.mem.Allocator,
|
||||
comp: Compression,
|
||||
rdr: T,
|
||||
rdr: PRead(T),
|
||||
offset: u64,
|
||||
|
||||
block: [8192]u8 = undefined,
|
||||
block_size: usize = 0,
|
||||
block_offset: u32 = 0,
|
||||
|
||||
pub fn init(alloc: std.mem.Allocator, comp: Compression, rdr: T) !Self {
|
||||
var out: Self = .{
|
||||
pub fn init(alloc: std.mem.Allocator, comp: Compression, rdr: PRead(T), offset: u64) Self {
|
||||
return .{
|
||||
.alloc = alloc,
|
||||
.comp = comp,
|
||||
.rdr = rdr,
|
||||
.offset = offset,
|
||||
};
|
||||
try out.readNextBlock();
|
||||
return out;
|
||||
}
|
||||
|
||||
fn readNextBlock(self: *Self) !void {
|
||||
const hdr: MetaHeader = undefined;
|
||||
_ = try self.rdr.read(std.mem.asBytes(hdr));
|
||||
_ = try self.rdr.pread(std.mem.asBytes(hdr), self.offset);
|
||||
self.offset += 2;
|
||||
self.block_size = try self.comp.decompress(
|
||||
8192,
|
||||
self.alloc,
|
||||
std.io.limitedReader(self.rdr, hdr.size),
|
||||
std.io.limitedReader(self.rdr.readerAt(self.offset), hdr.size),
|
||||
self.block,
|
||||
);
|
||||
self.offset += hdr.size;
|
||||
self.block_offset = 0;
|
||||
}
|
||||
|
||||
pub fn skip(self: *Self, offset: u32) !void {
|
||||
var skipped = 0;
|
||||
const hdr: MetaHeader = undefined;
|
||||
while (offset - skipped >= 8192) {
|
||||
_ = try self.rdr.pread(std.mem.asBytes(hdr), self.offset);
|
||||
self.offset += 2 + hdr.size;
|
||||
skipped += 8192;
|
||||
}
|
||||
var to_skip = 0;
|
||||
while (skipped < offset) {
|
||||
if (self.block_offset >= self.block_size) try self.readNextBlock();
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub const Reader = @import("reader.zig").Reader;
|
||||
pub const SfsReader = @import("reader.zig").SfsReader;
|
||||
pub const ExtractionOptions = @import("extract_options.zig");
|
||||
|
||||
pub const FileReader = Reader(std.fs.File);
|
||||
pub const FileReader = SfsReader(std.fs.File);
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ pub const Superblock = packed struct {
|
||||
export_start: u64,
|
||||
};
|
||||
|
||||
const DecompressError = error{
|
||||
pub const DecompressError = error{
|
||||
LzoUnavailable,
|
||||
Lz4Unavailable,
|
||||
};
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
const std = @import("std");
|
||||
|
||||
const TableError = error{
|
||||
pub const TableError = error{
|
||||
InvalidIndex,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user