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 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
View File
@@ -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;
}
+5 -4
View File
@@ -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 {
+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);
}