Further progress
Mainly focusing on getting things more consistent
This commit is contained in:
+22
-4
@@ -1,6 +1,24 @@
|
|||||||
dereference_symlinks: bool,
|
const std = @import("std");
|
||||||
unbreak_symlinks: bool,
|
|
||||||
ignore_permissions: bool,
|
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,
|
// 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 {
|
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 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 ToRead = @import("reader/to_read.zig").ToRead;
|
||||||
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;
|
||||||
@@ -86,10 +88,11 @@ pub fn init(rdr: anytype, alloc: std.mem.Allocator, block_size: u32) !Self {
|
|||||||
.data = data,
|
.data = data,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub fn initFromRef(p_rdr: anytype, comp: Compression, ref: Ref, table_start: u64, alloc: std.mem.Allocator, block_size: u32) !Self {
|
pub fn deinit(self: Self, alloc: std.mem.Allocator) void {
|
||||||
const rdr: ToRead(@TypeOf(p_rdr)) = .init(p_rdr, ref.block + table_start);
|
switch (self.data) {
|
||||||
const meta_rdr: MetadataReader(ToRead(@TypeOf(p_rdr))) = try .init(alloc, comp, rdr);
|
.file => |f| alloc.free(f.block_sizes),
|
||||||
defer meta_rdr.deinit();
|
.ext_file => |f| alloc.free(f.block_sizes),
|
||||||
try meta_rdr.skip(ref.offset);
|
.symlink => |s| alloc.free(s.target),
|
||||||
return init(meta_rdr, alloc, block_size);
|
.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 PRead = @import("reader/p_read.zig").PRead;
|
||||||
const FragEntry = @import("fragment.zig").FragEntry;
|
const FragEntry = @import("fragment.zig").FragEntry;
|
||||||
const Superblock = @import("superblock.zig").Superblock;
|
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"));
|
comptime std.debug.assert(std.meta.hasFn(T, "pread"));
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
@@ -40,14 +45,22 @@ pub fn Reader(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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the inode with the given Inode Number.
|
/// Returns the inode with the given Inode Number.
|
||||||
/// Requires for the archive to have an export table.
|
/// Requires the archive to have an export table.
|
||||||
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;
|
||||||
const ref = try self.export_table.get(num - 1);
|
const ref = try self.export_table.get(num - 1);
|
||||||
_ = ref;
|
const meta = MetadataReader(T).init(
|
||||||
return error{TODO}.TODO;
|
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 std = @import("std");
|
||||||
|
|
||||||
|
const PRead = @import("p_read.zig").PRead;
|
||||||
const Compression = @import("../superblock.zig").Compression;
|
const Compression = @import("../superblock.zig").Compression;
|
||||||
|
|
||||||
const MetaHeader = packed struct {
|
const MetaHeader = packed struct {
|
||||||
@@ -14,36 +15,44 @@ pub fn MetadataReader(comptime T: type) type {
|
|||||||
|
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
comp: Compression,
|
comp: Compression,
|
||||||
rdr: T,
|
rdr: PRead(T),
|
||||||
|
offset: u64,
|
||||||
|
|
||||||
block: [8192]u8 = undefined,
|
block: [8192]u8 = undefined,
|
||||||
block_size: usize = 0,
|
block_size: usize = 0,
|
||||||
block_offset: u32 = 0,
|
block_offset: u32 = 0,
|
||||||
|
|
||||||
pub fn init(alloc: std.mem.Allocator, comp: Compression, rdr: T) !Self {
|
pub fn init(alloc: std.mem.Allocator, comp: Compression, rdr: PRead(T), offset: u64) Self {
|
||||||
var out: Self = .{
|
return .{
|
||||||
.alloc = alloc,
|
.alloc = alloc,
|
||||||
.comp = comp,
|
.comp = comp,
|
||||||
.rdr = rdr,
|
.rdr = rdr,
|
||||||
|
.offset = offset,
|
||||||
};
|
};
|
||||||
try out.readNextBlock();
|
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readNextBlock(self: *Self) !void {
|
fn readNextBlock(self: *Self) !void {
|
||||||
const hdr: MetaHeader = undefined;
|
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(
|
self.block_size = try self.comp.decompress(
|
||||||
8192,
|
8192,
|
||||||
self.alloc,
|
self.alloc,
|
||||||
std.io.limitedReader(self.rdr, hdr.size),
|
std.io.limitedReader(self.rdr.readerAt(self.offset), hdr.size),
|
||||||
self.block,
|
self.block,
|
||||||
);
|
);
|
||||||
|
self.offset += hdr.size;
|
||||||
self.block_offset = 0;
|
self.block_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn skip(self: *Self, offset: u32) !void {
|
pub fn skip(self: *Self, offset: u32) !void {
|
||||||
var skipped = 0;
|
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;
|
var to_skip = 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();
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
const std = @import("std");
|
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 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,
|
export_start: u64,
|
||||||
};
|
};
|
||||||
|
|
||||||
const DecompressError = error{
|
pub const DecompressError = error{
|
||||||
LzoUnavailable,
|
LzoUnavailable,
|
||||||
Lz4Unavailable,
|
Lz4Unavailable,
|
||||||
};
|
};
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const TableError = error{
|
pub const TableError = error{
|
||||||
InvalidIndex,
|
InvalidIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user