Created DataReader (untested)
Other minor fixes & tweaks
This commit is contained in:
+3
-4
@@ -6,7 +6,6 @@ const util = @import("utils/util.zig");
|
|||||||
const File = @import("file.zig");
|
const File = @import("file.zig");
|
||||||
const Inode = @import("inode.zig");
|
const Inode = @import("inode.zig");
|
||||||
const Decomp = @import("decomp.zig");
|
const Decomp = @import("decomp.zig");
|
||||||
|
|
||||||
const Options = @import("options.zig");
|
const Options = @import("options.zig");
|
||||||
|
|
||||||
const Archive = @This();
|
const Archive = @This();
|
||||||
@@ -16,7 +15,7 @@ map: Io.File.MemoryMap,
|
|||||||
super: Super,
|
super: Super,
|
||||||
root_inode_ref: Inode.Reference,
|
root_inode_ref: Inode.Reference,
|
||||||
|
|
||||||
pub fn open(io: Io, file: Io.File, offset: u64) !Archive {
|
pub fn init(io: Io, file: Io.File, offset: u64) !Archive {
|
||||||
var map = try file.createMemoryMap(io, .{
|
var map = try file.createMemoryMap(io, .{
|
||||||
.len = try file.length(io) - offset,
|
.len = try file.length(io) - offset,
|
||||||
.offset = offset,
|
.offset = offset,
|
||||||
@@ -33,7 +32,7 @@ pub fn open(io: Io, file: Io.File, offset: u64) !Archive {
|
|||||||
.root_inode_ref = superblock.root_inode_ref,
|
.root_inode_ref = superblock.root_inode_ref,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub fn close(self: *Archive, io: Io) void {
|
pub fn deinit(self: *Archive, io: Io) void {
|
||||||
self.map.destroy(io);
|
self.map.destroy(io);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +52,7 @@ pub fn root(self: *Archive, alloc: std.mem.Allocator) !File {
|
|||||||
.name = "",
|
.name = "",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub fn openFile(self: *Archive, alloc: std.mem.Allocator, filepath: []const u8) !File {
|
pub fn open(self: *Archive, alloc: std.mem.Allocator, filepath: []const u8) !File {
|
||||||
var root_file = try self.root(alloc);
|
var root_file = try self.root(alloc);
|
||||||
defer root_file.deinit();
|
defer root_file.deinit();
|
||||||
|
|
||||||
|
|||||||
+92
-1
@@ -4,6 +4,8 @@ const Io = std.Io;
|
|||||||
const Inode = @import("inode.zig");
|
const Inode = @import("inode.zig");
|
||||||
const Directory = @import("dir.zig");
|
const Directory = @import("dir.zig");
|
||||||
const MetadataReader = @import("utils/meta.zig");
|
const MetadataReader = @import("utils/meta.zig");
|
||||||
|
const Options = @import("options.zig");
|
||||||
|
const DataReader = @import("utils/data_reader.zig");
|
||||||
const Super = @import("archive.zig").Super;
|
const Super = @import("archive.zig").Super;
|
||||||
|
|
||||||
const File = @This();
|
const File = @This();
|
||||||
@@ -35,6 +37,31 @@ pub fn deinit(self: File) void {
|
|||||||
self.alloc.free(self.name);
|
self.alloc.free(self.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reader interface to read a regular file's contents.
|
||||||
|
pub fn reader(self: File, alloc: std.mem.Allocator) !DataReader {
|
||||||
|
return switch (self.inode.header.type) {
|
||||||
|
.file => |f| .init(
|
||||||
|
alloc,
|
||||||
|
self.data,
|
||||||
|
self.super.decomp_fn,
|
||||||
|
self.super.block_size,
|
||||||
|
f.start,
|
||||||
|
f.size,
|
||||||
|
f.blocks,
|
||||||
|
),
|
||||||
|
.ext_file => |f| .init(
|
||||||
|
alloc,
|
||||||
|
self.data,
|
||||||
|
self.super.decomp_fn,
|
||||||
|
self.super.block_size,
|
||||||
|
f.start,
|
||||||
|
f.size,
|
||||||
|
f.blocks,
|
||||||
|
),
|
||||||
|
else => error.NotRegularFile,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn open(self: File, alloc: std.mem.Allocator, filepath: []const u8) !File {
|
pub fn open(self: File, alloc: std.mem.Allocator, filepath: []const u8) !File {
|
||||||
switch (self.inode.header.type) {
|
switch (self.inode.header.type) {
|
||||||
.dir, .ext_dir => {},
|
.dir, .ext_dir => {},
|
||||||
@@ -47,6 +74,7 @@ pub fn open(self: File, alloc: std.mem.Allocator, filepath: []const u8) !File {
|
|||||||
return self.copy(alloc);
|
return self.copy(alloc);
|
||||||
|
|
||||||
const first_element: []u8 = std.mem.sliceTo(path, '/');
|
const first_element: []u8 = std.mem.sliceTo(path, '/');
|
||||||
|
const final = first_element.len == path.len;
|
||||||
|
|
||||||
var dir_size: u32 = undefined;
|
var dir_size: u32 = undefined;
|
||||||
var dir_rdr: MetadataReader = undefined;
|
var dir_rdr: MetadataReader = undefined;
|
||||||
@@ -67,10 +95,73 @@ pub fn open(self: File, alloc: std.mem.Allocator, filepath: []const u8) !File {
|
|||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
|
|
||||||
const inode: Inode = {
|
const entry: Directory.Entry = blk: {
|
||||||
var dir: Directory = try .read(alloc, &dir_rdr.interface, dir_size);
|
var dir: Directory = try .read(alloc, &dir_rdr.interface, dir_size);
|
||||||
defer dir.deinit(alloc);
|
defer dir.deinit(alloc);
|
||||||
|
|
||||||
|
var entries = dir.entries;
|
||||||
|
|
||||||
|
while (entries.len > 0) {
|
||||||
|
const idx = entries.len / 2;
|
||||||
|
const val = entries[idx];
|
||||||
|
|
||||||
|
switch (std.mem.order(u8, first_element, val.name)) {
|
||||||
|
.eq => {
|
||||||
|
if (final) {
|
||||||
|
const inode: Inode = try .fromRef(
|
||||||
|
alloc,
|
||||||
|
self.data,
|
||||||
|
.{ .start = val.start, .offset = val.offset },
|
||||||
|
self.super,
|
||||||
|
);
|
||||||
|
errdefer inode.deinit(alloc);
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.alloc = alloc,
|
||||||
|
|
||||||
|
.data = self.data,
|
||||||
|
.super = self.super,
|
||||||
|
|
||||||
|
.inode = inode,
|
||||||
|
.name = try alloc.dupe(u8, val.name),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
break :blk val;
|
||||||
|
},
|
||||||
|
.lt => entries = entries[0..idx],
|
||||||
|
.gt => entries = entries[idx..],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error.NotFound;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (entry.type != .dir)
|
||||||
|
return error.NotFound;
|
||||||
|
|
||||||
|
const transient_file: File = .{
|
||||||
|
.alloc = alloc,
|
||||||
|
|
||||||
|
.data = self.data,
|
||||||
|
.super = self.super,
|
||||||
|
|
||||||
|
.inode = try .fromRef(
|
||||||
|
alloc,
|
||||||
|
self.data,
|
||||||
|
.{ .start = entry.start, .offset = entry.offset },
|
||||||
|
self.super,
|
||||||
|
),
|
||||||
|
.name = "",
|
||||||
|
};
|
||||||
|
|
||||||
|
return transient_file.open(alloc, filepath[first_element.len..]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extract the given File to the location.
|
||||||
|
pub fn extract(self: File, alloc: std.mem.Allocator, io: Io, ext_loc: []const u8, options: Options) !void {
|
||||||
|
_ = self;
|
||||||
|
_ = alloc;
|
||||||
|
_ = io;
|
||||||
|
_ = ext_loc;
|
||||||
|
_ = options;
|
||||||
return error.TODO;
|
return error.TODO;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -246,7 +246,7 @@ pub const ExtDev = extern struct {
|
|||||||
xattr_idx: u32,
|
xattr_idx: u32,
|
||||||
|
|
||||||
pub fn read(rdr: *Io.Reader) !ExtDev {
|
pub fn read(rdr: *Io.Reader) !ExtDev {
|
||||||
return util.readValue(ExtDev, rdr);
|
return util.readValueRdr(ExtDev, rdr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -12,11 +12,11 @@ test "Open" {
|
|||||||
var archive_file = try Io.Dir.cwd().openFile(io, TEST_ARCHIVE, .{});
|
var archive_file = try Io.Dir.cwd().openFile(io, TEST_ARCHIVE, .{});
|
||||||
defer archive_file.close(io);
|
defer archive_file.close(io);
|
||||||
|
|
||||||
var arc: Archive = try .open(io, archive_file, 0);
|
var arc: Archive = try .init(io, archive_file, 0);
|
||||||
defer arc.close(io);
|
defer arc.deinit(io);
|
||||||
|
|
||||||
std.debug.print("{}\n", .{arc.super});
|
std.debug.print("{}\n", .{arc.super});
|
||||||
|
|
||||||
var root = try arc.root(alloc);
|
var root = try arc.root(alloc);
|
||||||
defer root.close();
|
defer root.deinit();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const Io = std.Io;
|
||||||
|
|
||||||
|
const Decomp = @import("../decomp.zig");
|
||||||
|
const BlockSize = @import("../inode.zig").BlockSize;
|
||||||
|
|
||||||
|
const DataReader = @This();
|
||||||
|
|
||||||
|
alloc: std.mem.Allocator,
|
||||||
|
|
||||||
|
data: []u8,
|
||||||
|
decomp: Decomp.Fn,
|
||||||
|
block_size: u32,
|
||||||
|
|
||||||
|
size: u64,
|
||||||
|
blocks: []BlockSize,
|
||||||
|
|
||||||
|
frag: ?[]u8 = null,
|
||||||
|
|
||||||
|
idx: u32 = 0,
|
||||||
|
buf: []u8,
|
||||||
|
|
||||||
|
interface: Io.Reader = .{
|
||||||
|
.buffer = &[0]u8{},
|
||||||
|
.seek = 0,
|
||||||
|
.end = 0,
|
||||||
|
.vtable = &.{
|
||||||
|
.stream = stream,
|
||||||
|
.discard = discard,
|
||||||
|
.readVec = readVec,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
pub fn init(alloc: std.mem.Allocator, data: []u8, decomp: Decomp.Fn, block_size: u32, start: u64, size: u64, blocks: []BlockSize) DataReader {
|
||||||
|
return .{
|
||||||
|
.alloc = alloc,
|
||||||
|
|
||||||
|
.data = data[start..],
|
||||||
|
.decomp = decomp,
|
||||||
|
.block_size = block_size,
|
||||||
|
|
||||||
|
.size = size,
|
||||||
|
.blocks = blocks,
|
||||||
|
.buf = if (blocks.len > 0) try alloc.alloc(u8, 1024 * 1024) else &[0]u8{},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
pub fn deinit(self: DataReader) void {
|
||||||
|
self.alloc.free(self.buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn addFrag(self: *DataReader, frag: []u8) void {
|
||||||
|
self.frag = frag;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn advance(self: *DataReader) Io.Reader.Error!void {
|
||||||
|
if (self.idx > self.blocks.len) return error.EndOfStream;
|
||||||
|
defer self.idx += 1;
|
||||||
|
|
||||||
|
self.interface.seek = 0;
|
||||||
|
errdefer self.interface.end = 0;
|
||||||
|
|
||||||
|
if (self.idx == self.blocks.len) {
|
||||||
|
if (self.frag == null) return error.EndOfStream;
|
||||||
|
|
||||||
|
self.interface.buffer = self.frag.?;
|
||||||
|
self.interface.end = self.frag.?.len;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.interface.end = if (self.frag == null and self.idx == self.blocks.len - 1)
|
||||||
|
self.size % self.block_size
|
||||||
|
else
|
||||||
|
self.block_size;
|
||||||
|
|
||||||
|
const block = self.blocks[self.idx];
|
||||||
|
|
||||||
|
if (block.size == 0) {
|
||||||
|
@memset(self.buf[0..self.interface.end], 0);
|
||||||
|
self.interface.buffer = self.buf;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block.uncompressed) {
|
||||||
|
self.interface.buffer = self.data;
|
||||||
|
self.data = self.data[self.interface.end..];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = self.decomp(self.alloc, self.data[0..block.size], self.buf[0..self.interface.end]) catch return error.ReadFailed;
|
||||||
|
self.data = self.data[block.size..];
|
||||||
|
|
||||||
|
self.interface.buffer = self.buf;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stream(rdr: *Io.Reader, wrt: *Io.Writer, limit: Io.Limit) Io.Reader.StreamError!usize {
|
||||||
|
if (rdr.seek >= rdr.end) {
|
||||||
|
var meta: *DataReader = @fieldParentPtr("interface", rdr);
|
||||||
|
try meta.advance();
|
||||||
|
}
|
||||||
|
if (limit == .nothing) return 0;
|
||||||
|
|
||||||
|
const size = @min(@intFromEnum(limit), rdr.end - rdr.seek);
|
||||||
|
|
||||||
|
const wrote = try wrt.write(rdr.buffer[rdr.seek..][0..size]);
|
||||||
|
rdr.seek += wrote;
|
||||||
|
|
||||||
|
return wrote;
|
||||||
|
}
|
||||||
|
fn discard(rdr: *Io.Reader, limit: Io.Limit) Io.Reader.Error!usize {
|
||||||
|
if (rdr.seek >= rdr.end) {
|
||||||
|
var meta: *DataReader = @fieldParentPtr("interface", rdr);
|
||||||
|
try meta.advance();
|
||||||
|
}
|
||||||
|
if (limit == .nothing) return 0;
|
||||||
|
|
||||||
|
const size = @min(@intFromEnum(limit), rdr.end - rdr.seek);
|
||||||
|
rdr.seek += size;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
fn readVec(rdr: *Io.Reader, vec: [][]u8) Io.Reader.Error!usize {
|
||||||
|
if (rdr.seek >= rdr.end) {
|
||||||
|
var meta: *DataReader = @fieldParentPtr("interface", rdr);
|
||||||
|
try meta.advance();
|
||||||
|
}
|
||||||
|
|
||||||
|
var wrote: usize = 0;
|
||||||
|
for (vec) |s| {
|
||||||
|
const size = @min(rdr.end - rdr.seek, s.len);
|
||||||
|
|
||||||
|
@memcpy(s[0..size], rdr.buffer[rdr.seek..][0..size]);
|
||||||
|
|
||||||
|
wrote += size;
|
||||||
|
rdr.seek += size;
|
||||||
|
|
||||||
|
if (rdr.seek >= rdr.end) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wrote;
|
||||||
|
}
|
||||||
+1
-1
@@ -15,7 +15,7 @@ decomp: Decomp.Fn,
|
|||||||
decomp_block: [8192]u8 = undefined,
|
decomp_block: [8192]u8 = undefined,
|
||||||
|
|
||||||
interface: Io.Reader = .{
|
interface: Io.Reader = .{
|
||||||
.buffer = &[0]u8,
|
.buffer = &[0]u8{},
|
||||||
.end = 0,
|
.end = 0,
|
||||||
.seek = 0,
|
.seek = 0,
|
||||||
.vtable = &.{
|
.vtable = &.{
|
||||||
|
|||||||
Reference in New Issue
Block a user