File stuff
This commit is contained in:
+32
-10
@@ -9,6 +9,7 @@ const BlockSize = @import("inode/file.zig").BlockSize;
|
|||||||
const LookupTable = @import("lookup_table.zig");
|
const LookupTable = @import("lookup_table.zig");
|
||||||
const MetadataReader = @import("util/metadata.zig");
|
const MetadataReader = @import("util/metadata.zig");
|
||||||
const OffsetFile = @import("util/offset_file.zig");
|
const OffsetFile = @import("util/offset_file.zig");
|
||||||
|
const Utils = @import("util/utils.zig");
|
||||||
|
|
||||||
pub const Error = error{
|
pub const Error = error{
|
||||||
BadMagic,
|
BadMagic,
|
||||||
@@ -53,11 +54,23 @@ pub fn root(self: Archive, alloc: std.mem.Allocator) !File {
|
|||||||
return .{
|
return .{
|
||||||
.alloc = alloc,
|
.alloc = alloc,
|
||||||
|
|
||||||
.inode = try self.refToInode(alloc, self.super.root_ref),
|
.inode = try Utils.refToInode(
|
||||||
|
alloc,
|
||||||
|
&self.stateless_decomp,
|
||||||
|
self.file,
|
||||||
|
self.super.inode_start,
|
||||||
|
self.super.block_size,
|
||||||
|
self.super.root_ref,
|
||||||
|
),
|
||||||
.name = "",
|
.name = "",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub fn open(self: Archive, alloc: std.mem.Allocator, path: []const u8) !File {}
|
pub fn open(self: Archive, alloc: std.mem.Allocator, path: []const u8) !File {
|
||||||
|
if (Utils.pathIsSelf(path)) return self.root(alloc);
|
||||||
|
var root_file = self.root(alloc);
|
||||||
|
defer root_file.deinit();
|
||||||
|
return root_file.open(alloc, path);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn fragEntry(self: Archive, idx: u32) !FragEntry {
|
pub fn fragEntry(self: Archive, idx: u32) !FragEntry {
|
||||||
return LookupTable.stateless(FragEntry, self.fil, &self.stateless_decomp, self.super.frag_start, idx);
|
return LookupTable.stateless(FragEntry, self.fil, &self.stateless_decomp, self.super.frag_start, idx);
|
||||||
@@ -67,14 +80,7 @@ pub fn id(self: Archive, idx: u32) !u16 {
|
|||||||
}
|
}
|
||||||
pub fn inode(self: Archive, alloc: std.mem.Allocator, inode_num: u32) !Inode {
|
pub fn inode(self: Archive, alloc: std.mem.Allocator, inode_num: u32) !Inode {
|
||||||
const ref = try LookupTable.stateless(Inode.Ref, self.file, &self.stateless_decomp, self.super.export_start, inode_num - 1);
|
const ref = try LookupTable.stateless(Inode.Ref, self.file, &self.stateless_decomp, self.super.export_start, inode_num - 1);
|
||||||
return self.refToInode(alloc, ref);
|
return Utils.refToInode(alloc, &self.stateless_decomp, self.file, self.super.inode_start, self.super.block_size, ref);
|
||||||
}
|
|
||||||
|
|
||||||
inline fn refToInode(self: Archive, alloc: std.mem.Allocator, ref: Inode.Ref) !Inode {
|
|
||||||
var rdr = self.file.readerAt(self.super.inode_start + ref.block_start, &[0]u8{});
|
|
||||||
var meta: MetadataReader = .init(&rdr.interface, &self.stateless_decomp);
|
|
||||||
try meta.interface.discardAll(ref.block_offset);
|
|
||||||
return .read(alloc, &meta.interface, self.super.block_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Superblock
|
// Superblock
|
||||||
@@ -127,9 +133,25 @@ pub const Superblock = packed struct {
|
|||||||
if (std.math.log2(self.block_size) != self.block_log)
|
if (std.math.log2(self.block_size) != self.block_log)
|
||||||
return Error.BadBlockLog;
|
return Error.BadBlockLog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn toMinimal(self: Superblock) MinimalSuperblock {
|
||||||
|
return .{
|
||||||
|
.inode_count = self.inode_count,
|
||||||
|
.block_size = self.block_size,
|
||||||
|
.frag_count = self.frag_count,
|
||||||
|
.id_count = self.id_count,
|
||||||
|
.id_start = self.id_start,
|
||||||
|
.xattr_start = self.xattr_start,
|
||||||
|
.inode_start = self.inode_start,
|
||||||
|
.dir_start = self.dir_start,
|
||||||
|
.frag_start = self.frag_start,
|
||||||
|
.export_start = self.export_start,
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const MinimalSuperblock = struct {
|
pub const MinimalSuperblock = struct {
|
||||||
|
inode_count: u32,
|
||||||
block_size: u32,
|
block_size: u32,
|
||||||
frag_count: u32,
|
frag_count: u32,
|
||||||
id_count: u16,
|
id_count: u16,
|
||||||
|
|||||||
+45
-2
@@ -1,15 +1,23 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const Archive = @import("archive.zig");
|
const Archive = @import("archive.zig");
|
||||||
|
const Decompressor = @import("decomp.zig");
|
||||||
const Directory = @import("directory.zig");
|
const Directory = @import("directory.zig");
|
||||||
const Inode = @import("inode.zig");
|
const Inode = @import("inode.zig");
|
||||||
const MetadataReader = @import("util/metadata.zig");
|
const MetadataReader = @import("util/metadata.zig");
|
||||||
|
const Utils = @import("util/utils.zig");
|
||||||
|
|
||||||
|
pub const Error = error{
|
||||||
|
NotDirectory,
|
||||||
|
NotRegularFile,
|
||||||
|
};
|
||||||
|
|
||||||
const File = @This();
|
const File = @This();
|
||||||
|
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
|
|
||||||
archive: Archive,
|
superblock: Archive.MinimalSuperblock,
|
||||||
|
decomp: Decompressor,
|
||||||
|
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
inode: Inode,
|
inode: Inode,
|
||||||
@@ -19,8 +27,43 @@ pub fn init(alloc: std.mem.Allocator, archive: Archive, entry: Directory.Entry)
|
|||||||
errdefer alloc.free(new_name);
|
errdefer alloc.free(new_name);
|
||||||
@memcpy(new_name, entry.name);
|
@memcpy(new_name, entry.name);
|
||||||
var rdr = archive.file.readerAt(archive.super.inode_start + entry.block_start, &[0]u8{});
|
var rdr = archive.file.readerAt(archive.super.inode_start + entry.block_start, &[0]u8{});
|
||||||
var meta
|
var meta: MetadataReader = .init(&rdr.interface, &archive.stateless_decomp);
|
||||||
|
try meta.interface.discardAll(entry.block_offset);
|
||||||
|
return .{
|
||||||
|
.alloc = alloc,
|
||||||
|
.superblock = archive.super,
|
||||||
|
.decomp = .{
|
||||||
|
.alloc = alloc,
|
||||||
|
.vtable = &.{ .stateless = archive.stateless_decomp.vtable.stateless },
|
||||||
|
},
|
||||||
|
.name = new_name,
|
||||||
|
.inode = try .read(alloc, &meta.interface, archive.super.block_size),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
pub fn deinit(self: File) void {
|
pub fn deinit(self: File) void {
|
||||||
self.alloc.free(self.name);
|
self.alloc.free(self.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Opens a sub-directory. If the given path is "", ".", "/", or "./", a copy of the File is returned.
|
||||||
|
pub fn open(self: File, alloc: std.mem.Allocator, path: []const u8) !File {
|
||||||
|
switch (self.inode.hdr.inode_type) {
|
||||||
|
.dir, .ext_dir => {},
|
||||||
|
else => Error.NotDirectory,
|
||||||
|
}
|
||||||
|
if (Utils.pathIsSelf(path)) {
|
||||||
|
const new_name = try alloc.alloc(u8, self.name.len);
|
||||||
|
@memcpy(new_name, self.name);
|
||||||
|
return .{
|
||||||
|
.alloc = alloc,
|
||||||
|
.superblock = self.superblock,
|
||||||
|
.decomp = .{
|
||||||
|
.alloc = alloc,
|
||||||
|
.vtable = &.{ .stateless = self.decomp.vtable.stateless },
|
||||||
|
},
|
||||||
|
.name = new_name,
|
||||||
|
.inode = self.inode,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return error.TODO;
|
||||||
|
}
|
||||||
|
|||||||
@@ -40,10 +40,11 @@ fn advanceBuffer(self: *MetadataReader) Reader.Error!void {
|
|||||||
self.interface.end = hdr.size;
|
self.interface.end = hdr.size;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.interface.end = self.decomp.decompress(self.read_buf[0..hdr.size], self.interface.buffer) catch |err| return switch (err) {
|
self.interface.end = self.decomp.decompress(self.read_buf[0..hdr.size], self.interface.buffer) catch |err|
|
||||||
error.OutOfMemory => error.ReadFailed,
|
return switch (err) {
|
||||||
else => err,
|
error.OutOfMemory => error.ReadFailed,
|
||||||
};
|
else => err,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stream(rdr: *Reader, wrt: *Writer, limit: Limit) Reader.StreamError!usize {
|
fn stream(rdr: *Reader, wrt: *Writer, limit: Limit) Reader.StreamError!usize {
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
const Decompressor = @import("../decomp.zig");
|
||||||
|
const Inode = @import("../inode.zig");
|
||||||
|
const MetadataReader = @import("metadata.zig");
|
||||||
|
const OffsetFile = @import("offset_file.zig");
|
||||||
|
|
||||||
|
pub fn pathIsSelf(path: []const u8) bool {
|
||||||
|
if (path.len == 0) return true;
|
||||||
|
if (path.len == 1) {
|
||||||
|
return switch (path[0]) {
|
||||||
|
'.', '/' => true,
|
||||||
|
else => false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return std.mem.eql(u8, path, "./");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn refToInode(alloc: std.mem.Allocator, decomp: *const Decompressor, fil: OffsetFile, inode_start: u64, block_size: u32, ref: Inode.Ref) !Inode {
|
||||||
|
var rdr = try fil.readerAt(inode_start + ref.block_start, &[0]u8{});
|
||||||
|
var meta: MetadataReader = .init(&rdr.interface, decomp);
|
||||||
|
try meta.interface.discardAll(ref.block_offset);
|
||||||
|
return .read(alloc, &meta.interface, block_size);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user