File stuff

This commit is contained in:
Caleb J. Gardner
2026-04-04 18:48:57 -05:00
parent c7c44029c9
commit eec468ff17
4 changed files with 106 additions and 16 deletions
+32 -10
View File
@@ -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
View File
@@ -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;
}
+5 -4
View File
@@ -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 {
+24
View File
@@ -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);
}