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 MetadataReader = @import("util/metadata.zig");
|
||||
const OffsetFile = @import("util/offset_file.zig");
|
||||
const Utils = @import("util/utils.zig");
|
||||
|
||||
pub const Error = error{
|
||||
BadMagic,
|
||||
@@ -53,11 +54,23 @@ pub fn root(self: Archive, alloc: std.mem.Allocator) !File {
|
||||
return .{
|
||||
.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 = "",
|
||||
};
|
||||
}
|
||||
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 {
|
||||
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 {
|
||||
const ref = try LookupTable.stateless(Inode.Ref, self.file, &self.stateless_decomp, self.super.export_start, inode_num - 1);
|
||||
return self.refToInode(alloc, 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);
|
||||
return Utils.refToInode(alloc, &self.stateless_decomp, self.file, self.super.inode_start, self.super.block_size, ref);
|
||||
}
|
||||
|
||||
// Superblock
|
||||
@@ -127,9 +133,25 @@ pub const Superblock = packed struct {
|
||||
if (std.math.log2(self.block_size) != self.block_log)
|
||||
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 {
|
||||
inode_count: u32,
|
||||
block_size: u32,
|
||||
frag_count: u32,
|
||||
id_count: u16,
|
||||
|
||||
+45
-2
@@ -1,15 +1,23 @@
|
||||
const std = @import("std");
|
||||
|
||||
const Archive = @import("archive.zig");
|
||||
const Decompressor = @import("decomp.zig");
|
||||
const Directory = @import("directory.zig");
|
||||
const Inode = @import("inode.zig");
|
||||
const MetadataReader = @import("util/metadata.zig");
|
||||
const Utils = @import("util/utils.zig");
|
||||
|
||||
pub const Error = error{
|
||||
NotDirectory,
|
||||
NotRegularFile,
|
||||
};
|
||||
|
||||
const File = @This();
|
||||
|
||||
alloc: std.mem.Allocator,
|
||||
|
||||
archive: Archive,
|
||||
superblock: Archive.MinimalSuperblock,
|
||||
decomp: Decompressor,
|
||||
|
||||
name: []const u8,
|
||||
inode: Inode,
|
||||
@@ -19,8 +27,43 @@ pub fn init(alloc: std.mem.Allocator, archive: Archive, entry: Directory.Entry)
|
||||
errdefer alloc.free(new_name);
|
||||
@memcpy(new_name, entry.name);
|
||||
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 {
|
||||
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;
|
||||
return;
|
||||
}
|
||||
self.interface.end = self.decomp.decompress(self.read_buf[0..hdr.size], self.interface.buffer) catch |err| return switch (err) {
|
||||
error.OutOfMemory => error.ReadFailed,
|
||||
else => err,
|
||||
};
|
||||
self.interface.end = self.decomp.decompress(self.read_buf[0..hdr.size], self.interface.buffer) catch |err|
|
||||
return switch (err) {
|
||||
error.OutOfMemory => error.ReadFailed,
|
||||
else => err,
|
||||
};
|
||||
}
|
||||
|
||||
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