56ad79ba94
Fixed a couple bugs Added scaffold for extraction
103 lines
3.0 KiB
Zig
103 lines
3.0 KiB
Zig
const std = @import("std");
|
|
const Io = std.Io;
|
|
|
|
const Archive = @import("archive.zig");
|
|
const Directory = @import("directory.zig");
|
|
const ExtractionOptions = @import("options.zig");
|
|
const Inode = @import("inode.zig");
|
|
|
|
const SfsFile = @This();
|
|
|
|
alloc: std.mem.Allocator,
|
|
archive: *Archive,
|
|
|
|
inode: Inode,
|
|
name: []const u8,
|
|
|
|
/// The given allocator must have been used to create the Inode and name.
|
|
pub fn init(alloc: std.mem.Allocator, archive: *Archive, inode: Inode, name: []const u8) SfsFile {
|
|
return .{
|
|
.alloc = alloc,
|
|
.archive = archive,
|
|
|
|
.inode = inode,
|
|
.name = name,
|
|
};
|
|
}
|
|
pub fn initDirEntry(alloc: std.mem.Allocator, io: Io, archive: *Archive, entry: Directory.Entry) !SfsFile {
|
|
const new_name = try alloc.alloc(u8, entry.name.len);
|
|
defer alloc.free(new_name);
|
|
@memcpy(new_name, entry.name);
|
|
|
|
return .{
|
|
.alloc = alloc,
|
|
.archive = archive,
|
|
|
|
.inode = try .initDirEntry(
|
|
alloc,
|
|
io,
|
|
&archive.cache,
|
|
archive.super.inode_start,
|
|
archive.super.block_size,
|
|
entry,
|
|
),
|
|
.name = new_name,
|
|
};
|
|
}
|
|
/// Creates a new copy of the given SfsFile using the given allocator
|
|
pub fn copy(self: SfsFile, alloc: std.mem.Allocator) !SfsFile {
|
|
const new_name = try alloc(u8, self.name.len);
|
|
errdefer alloc.free(new_name);
|
|
|
|
return .{
|
|
.alloc = alloc,
|
|
.archive = self.archive,
|
|
|
|
.inode = try self.inode.copy(alloc),
|
|
.name = new_name,
|
|
};
|
|
}
|
|
pub fn deinit(self: SfsFile) void {
|
|
self.inode.deinit(self.alloc);
|
|
self.alloc.free(self.name);
|
|
}
|
|
|
|
/// Attempts to open the filepath if the SfsFile is a directory.
|
|
/// If the given path refers to itself (such as "" or "."), a copied SfsFile is returned.
|
|
pub fn open(self: SfsFile, alloc: std.mem.Allocator, io: Io, filepath: []const u8) !SfsFile {
|
|
const path = std.mem.trim(u8, filepath, "/");
|
|
|
|
const first_element: []const u8 = std.mem.sliceTo(path, '/');
|
|
|
|
const dir: Directory = try self.inode.directory(alloc, io, &self.archive.cache, self.archive.super.dir_start);
|
|
defer dir.deinit(alloc);
|
|
|
|
var cur_slice = dir.entries;
|
|
var idx: usize = undefined;
|
|
while (cur_slice.len > 0) {
|
|
idx = cur_slice.len / 2;
|
|
switch (std.mem.order(u8, first_element, cur_slice[idx].name)) {
|
|
.eq => break,
|
|
.lt => cur_slice = cur_slice[0..idx],
|
|
.gt => cur_slice = cur_slice[idx..],
|
|
}
|
|
} else {
|
|
return error.NotFound;
|
|
}
|
|
if (first_element.len == path.len) return .initDirEntry(alloc, io, self.archive, cur_slice[idx]);
|
|
if (cur_slice[idx].type != .dir) return error.NotFound;
|
|
const tmp_file: SfsFile = try .initDirEntry(alloc, io, self.archive, cur_slice[idx]);
|
|
defer tmp_file.deinit();
|
|
|
|
return tmp_file.open(alloc, io, path[first_element.len..]);
|
|
}
|
|
|
|
pub fn extract(self: SfsFile, alloc: std.mem.Allocator, io: Io, ext_dir: []const u8, options: ExtractionOptions) !void {
|
|
_ = self;
|
|
_ = alloc;
|
|
_ = io;
|
|
_ = ext_dir;
|
|
_ = options;
|
|
return error.TODO;
|
|
}
|