Fixed some bugs; found some bugs
This commit is contained in:
@@ -161,6 +161,8 @@ test "SingleFileExtraction" {
|
|||||||
const alloc = std.testing.allocator;
|
const alloc = std.testing.allocator;
|
||||||
const io = std.testing.io;
|
const io = std.testing.io;
|
||||||
|
|
||||||
|
std.Io.Dir.cwd().deleteFile(io, TestFileExtractLocation) catch {};
|
||||||
|
|
||||||
var archive_file = try Io.Dir.cwd().openFile(io, TestArchive, .{});
|
var archive_file = try Io.Dir.cwd().openFile(io, TestArchive, .{});
|
||||||
defer archive_file.close(io);
|
defer archive_file.close(io);
|
||||||
var arc: Archive = try .init(alloc, io, archive_file);
|
var arc: Archive = try .init(alloc, io, archive_file);
|
||||||
@@ -178,6 +180,8 @@ test "FullExtraction" {
|
|||||||
const alloc = std.testing.allocator;
|
const alloc = std.testing.allocator;
|
||||||
const io = std.testing.io;
|
const io = std.testing.io;
|
||||||
|
|
||||||
|
std.Io.Dir.cwd().deleteTree(io, TestFullExtractLocation) catch {};
|
||||||
|
|
||||||
var archive_file = try Io.Dir.cwd().openFile(io, TestArchive, .{});
|
var archive_file = try Io.Dir.cwd().openFile(io, TestArchive, .{});
|
||||||
defer archive_file.close(io);
|
defer archive_file.close(io);
|
||||||
var arc: Archive = try .init(alloc, io, archive_file);
|
var arc: Archive = try .init(alloc, io, archive_file);
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ const help_mgs =
|
|||||||
const errors = error{InvalidArguments};
|
const errors = error{InvalidArguments};
|
||||||
|
|
||||||
var archive: []const u8 = "";
|
var archive: []const u8 = "";
|
||||||
var extLoc: []const u8 = "squashfs-root";
|
var ext_loc: []const u8 = "squashfs-root";
|
||||||
var offset: u64 = 0;
|
var offset: u64 = 0;
|
||||||
var threads: u32 = 0;
|
var threads: u32 = 0;
|
||||||
var verbose: bool = false;
|
var verbose: bool = false;
|
||||||
@@ -64,8 +64,12 @@ pub fn main(init: std.process.Init) !void {
|
|||||||
.ignore_permissions = ignore_permissions,
|
.ignore_permissions = ignore_permissions,
|
||||||
};
|
};
|
||||||
if (force)
|
if (force)
|
||||||
try Io.Dir.cwd().deleteTree(io, extLoc);
|
try Io.Dir.cwd().deleteTree(io, ext_loc);
|
||||||
try arc.extract(alloc, io, extLoc, options); //TODO: Handle error gracefully.
|
if (threads != 1) {
|
||||||
|
try arc.extract(alloc, io, ext_loc, options); //TODO: Handle error gracefully.
|
||||||
|
} else {
|
||||||
|
try arc.extract(alloc, Io.Threaded.global_single_threaded.io(), ext_loc, options);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleArgs(args: std.process.Args, out: *Writer) !void {
|
fn handleArgs(args: std.process.Args, out: *Writer) !void {
|
||||||
@@ -90,7 +94,7 @@ fn handleArgs(args: std.process.Args, out: *Writer) !void {
|
|||||||
try out.print("-d must be followed by a location\n", .{});
|
try out.print("-d must be followed by a location\n", .{});
|
||||||
return errors.InvalidArguments;
|
return errors.InvalidArguments;
|
||||||
}
|
}
|
||||||
extLoc = nxt.?;
|
ext_loc = nxt.?;
|
||||||
continue;
|
continue;
|
||||||
} else if (std.mem.eql(u8, arg, "-p")) {
|
} else if (std.mem.eql(u8, arg, "-p")) {
|
||||||
const nxt = arg_iter.next();
|
const nxt = arg_iter.next();
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ pub fn addFragment(self: *Extractor, data: []u8, offset: u32) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn asyncExtract(self: Extractor, io: Io, fil: Io.File) Error!void {
|
pub fn asyncExtract(self: Extractor, io: Io, fil: Io.File) Error!void {
|
||||||
|
if (self.size == 0) return;
|
||||||
|
|
||||||
|
// Initializ the file with the correct size.
|
||||||
try fil.writePositionalAll(io, &.{0}, self.size - 1);
|
try fil.writePositionalAll(io, &.{0}, self.size - 1);
|
||||||
|
|
||||||
var map = try fil.createMemoryMap(io, .{ .len = self.size, .protection = .{ .write = true } });
|
var map = try fil.createMemoryMap(io, .{ .len = self.size, .protection = .{ .write = true } });
|
||||||
|
|||||||
@@ -90,6 +90,9 @@ pub fn finished(self: *DecompCache, io: Io, offset: u64) void {
|
|||||||
std.debug.print("Finished using cache, but cache does not exist: {}\n", .{offset});
|
std.debug.print("Finished using cache, but cache does not exist: {}\n", .{offset});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.mut.lockUncancelable(io);
|
||||||
|
defer self.mut.unlock(io);
|
||||||
const use = cache.?.usage.fetchSub(1, .acquire);
|
const use = cache.?.usage.fetchSub(1, .acquire);
|
||||||
if (use == 0)
|
if (use == 0)
|
||||||
self.cond.broadcast(io);
|
self.cond.broadcast(io);
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ pub fn init(alloc: std.mem.Allocator, rdr: *Reader, size: u32) Error!Directory {
|
|||||||
.type = raw.type,
|
.type = raw.type,
|
||||||
.name = name,
|
.name = name,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
read += @sizeOf(RawEntry) + raw.name_size + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+48
-20
@@ -1,38 +1,43 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Io = std.Io;
|
const Io = std.Io;
|
||||||
|
|
||||||
const Atomic = std.atomic.Value;
|
const Atomic = std.atomic.Value;
|
||||||
|
|
||||||
const DecompCache = @import("decomp_cache.zig");
|
|
||||||
const ExtractionOptions = @import("options.zig");
|
|
||||||
const Inode = @import("inode.zig");
|
|
||||||
const Superblock = @import("archive.zig").Superblock;
|
|
||||||
const Directory = @import("directory.zig");
|
|
||||||
const DataExtractor = @import("data/extractor.zig");
|
const DataExtractor = @import("data/extractor.zig");
|
||||||
const DataReader = @import("data/reader.zig");
|
const DataReader = @import("data/reader.zig");
|
||||||
|
const DecompCache = @import("decomp_cache.zig");
|
||||||
|
const Directory = @import("directory.zig");
|
||||||
|
const ExtractionOptions = @import("options.zig");
|
||||||
|
const Inode = @import("inode.zig");
|
||||||
const Lookup = @import("lookup.zig");
|
const Lookup = @import("lookup.zig");
|
||||||
|
const Superblock = @import("archive.zig").Superblock;
|
||||||
const XattrTable = @import("xattr.zig");
|
const XattrTable = @import("xattr.zig");
|
||||||
|
|
||||||
pub fn extract(alloc: std.mem.Allocator, io: Io, inode: Inode, cache: *DecompCache, super: Superblock, ext_loc: []const u8, options: ExtractionOptions) !void {
|
pub fn extract(alloc: std.mem.Allocator, io: Io, inode: Inode, cache: *DecompCache, super: Superblock, ext_loc: []const u8, options: ExtractionOptions) !void {
|
||||||
const path = std.mem.trim(u8, ext_loc, "/");
|
const path = std.mem.trim(u8, ext_loc, "/");
|
||||||
|
|
||||||
var buf: [50]ReturnUnion = undefined;
|
var buf: [1000]ReturnUnion = undefined;
|
||||||
var sel: Io.Select(ReturnUnion) = .init(io, &buf);
|
var sel: Io.Select(ReturnUnion) = .init(io, &buf);
|
||||||
|
|
||||||
defer {
|
defer {
|
||||||
|
std.debug.print("starting cancel loop...\n", .{});
|
||||||
while (sel.cancel()) |ret| {
|
while (sel.cancel()) |ret| {
|
||||||
|
std.debug.print("HELLO!\n", .{});
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
.dir_ret => |d| {
|
.dir_ret => |d| {
|
||||||
const res = d catch continue;
|
const res = d catch continue;
|
||||||
|
if (!res.origin)
|
||||||
alloc.free(res.path);
|
alloc.free(res.path);
|
||||||
|
alloc.destroy(res.sub_files);
|
||||||
},
|
},
|
||||||
.file_ret => |f| {
|
.file_ret => |f| {
|
||||||
const res = f catch continue;
|
const res = f catch continue;
|
||||||
|
if (!res.origin)
|
||||||
alloc.free(res.path);
|
alloc.free(res.path);
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std.debug.print("goodbye\n", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
var id_table: Lookup.Table(u16) = .init(alloc, cache, super.id_start, super.id_count);
|
var id_table: Lookup.Table(u16) = .init(alloc, cache, super.id_start, super.id_count);
|
||||||
@@ -46,7 +51,7 @@ pub fn extract(alloc: std.mem.Allocator, io: Io, inode: Inode, cache: *DecompCac
|
|||||||
var frag_table: Lookup.Table(Lookup.FragmentEntry) = .init(alloc, cache, super.frag_start, super.frag_count);
|
var frag_table: Lookup.Table(Lookup.FragmentEntry) = .init(alloc, cache, super.frag_start, super.frag_count);
|
||||||
defer frag_table.deinit();
|
defer frag_table.deinit();
|
||||||
|
|
||||||
try extractReal(alloc, io, cache, super, &sel, &frag_table, path, inode, null, false);
|
try extractReal(alloc, io, cache, super, &sel, &frag_table, path, inode, null, true);
|
||||||
|
|
||||||
try ret_loop.await(io);
|
try ret_loop.await(io);
|
||||||
}
|
}
|
||||||
@@ -65,10 +70,6 @@ fn extractReal(
|
|||||||
) Error!void {
|
) Error!void {
|
||||||
io.checkCancel() catch |err| {
|
io.checkCancel() catch |err| {
|
||||||
if (parent != null) _ = parent.?.fetchSub(1, .acquire);
|
if (parent != null) _ = parent.?.fetchSub(1, .acquire);
|
||||||
if (!origin) {
|
|
||||||
alloc.free(path);
|
|
||||||
inode.deinit(alloc);
|
|
||||||
}
|
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -108,6 +109,7 @@ fn extractDir(
|
|||||||
parent: ?*Atomic(usize),
|
parent: ?*Atomic(usize),
|
||||||
origin: bool,
|
origin: bool,
|
||||||
) Error!DirReturn {
|
) Error!DirReturn {
|
||||||
|
std.debug.print("started extract of {s}\n", .{path});
|
||||||
defer {
|
defer {
|
||||||
if (parent != null)
|
if (parent != null)
|
||||||
_ = parent.?.fetchSub(1, .acquire);
|
_ = parent.?.fetchSub(1, .acquire);
|
||||||
@@ -115,6 +117,8 @@ fn extractDir(
|
|||||||
}
|
}
|
||||||
errdefer if (!origin) alloc.free(path);
|
errdefer if (!origin) alloc.free(path);
|
||||||
|
|
||||||
|
try Io.Dir.cwd().createDirPath(io, path);
|
||||||
|
|
||||||
const dir = inode.directory(alloc, io, cache, super.dir_start) catch |err| switch (err) {
|
const dir = inode.directory(alloc, io, cache, super.dir_start) catch |err| switch (err) {
|
||||||
error.NotDirectory => unreachable,
|
error.NotDirectory => unreachable,
|
||||||
else => |e| return e,
|
else => |e| return e,
|
||||||
@@ -145,6 +149,7 @@ fn extractDir(
|
|||||||
errdefer new_inode.deinit(alloc);
|
errdefer new_inode.deinit(alloc);
|
||||||
|
|
||||||
const new_path = try std.mem.concat(alloc, u8, &.{ path, "/", entry.name });
|
const new_path = try std.mem.concat(alloc, u8, &.{ path, "/", entry.name });
|
||||||
|
errdefer alloc.free(new_path);
|
||||||
|
|
||||||
try extractReal(
|
try extractReal(
|
||||||
alloc,
|
alloc,
|
||||||
@@ -172,6 +177,7 @@ fn extractFile(
|
|||||||
parent: ?*Atomic(usize),
|
parent: ?*Atomic(usize),
|
||||||
origin: bool,
|
origin: bool,
|
||||||
) Error!FileReturn {
|
) Error!FileReturn {
|
||||||
|
std.debug.print("started extract of {s}\n", .{path});
|
||||||
defer {
|
defer {
|
||||||
if (parent != null)
|
if (parent != null)
|
||||||
_ = parent.?.fetchSub(1, .acquire);
|
_ = parent.?.fetchSub(1, .acquire);
|
||||||
@@ -230,6 +236,7 @@ fn extractFile(
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
fn extractSymlink(alloc: std.mem.Allocator, io: Io, path: []const u8, inode: Inode, parent: ?*Atomic(usize), origin: bool) Error!void {
|
fn extractSymlink(alloc: std.mem.Allocator, io: Io, path: []const u8, inode: Inode, parent: ?*Atomic(usize), origin: bool) Error!void {
|
||||||
|
std.debug.print("started extract of {s}\n", .{path});
|
||||||
defer {
|
defer {
|
||||||
if (parent != null)
|
if (parent != null)
|
||||||
_ = parent.?.fetchSub(1, .acquire);
|
_ = parent.?.fetchSub(1, .acquire);
|
||||||
@@ -248,6 +255,7 @@ fn extractSymlink(alloc: std.mem.Allocator, io: Io, path: []const u8, inode: Ino
|
|||||||
try Io.Dir.cwd().symLink(io, target, path, .{});
|
try Io.Dir.cwd().symLink(io, target, path, .{});
|
||||||
}
|
}
|
||||||
fn extractNod(alloc: std.mem.Allocator, path: []const u8, inode: Inode, parent: ?*Atomic(usize), origin: bool) Error!FileReturn {
|
fn extractNod(alloc: std.mem.Allocator, path: []const u8, inode: Inode, parent: ?*Atomic(usize), origin: bool) Error!FileReturn {
|
||||||
|
std.debug.print("started extract of {s}\n", .{path});
|
||||||
defer {
|
defer {
|
||||||
if (parent != null)
|
if (parent != null)
|
||||||
_ = parent.?.fetchSub(1, .acquire);
|
_ = parent.?.fetchSub(1, .acquire);
|
||||||
@@ -319,7 +327,8 @@ fn extractNod(alloc: std.mem.Allocator, path: []const u8, inode: Inode, parent:
|
|||||||
// Loop
|
// Loop
|
||||||
|
|
||||||
fn returnLoop(alloc: std.mem.Allocator, io: Io, id_table: *Lookup.Table(u16), xattr_table: *XattrTable, sel: *Io.Select(ReturnUnion), options: ExtractionOptions) !void {
|
fn returnLoop(alloc: std.mem.Allocator, io: Io, id_table: *Lookup.Table(u16), xattr_table: *XattrTable, sel: *Io.Select(ReturnUnion), options: ExtractionOptions) !void {
|
||||||
while (true) {
|
var origin_finished = false;
|
||||||
|
while (!origin_finished) {
|
||||||
const finished = try sel.await();
|
const finished = try sel.await();
|
||||||
|
|
||||||
switch (finished) {
|
switch (finished) {
|
||||||
@@ -328,11 +337,19 @@ fn returnLoop(alloc: std.mem.Allocator, io: Io, id_table: *Lookup.Table(u16), xa
|
|||||||
if (ret.sub_files.load(.unordered) != 0) {
|
if (ret.sub_files.load(.unordered) != 0) {
|
||||||
sel.queue.putOne(io, .{ .dir_ret = ret }) catch |err| {
|
sel.queue.putOne(io, .{ .dir_ret = ret }) catch |err| {
|
||||||
if (!ret.origin) alloc.free(ret.path);
|
if (!ret.origin) alloc.free(ret.path);
|
||||||
|
alloc.destroy(ret.sub_files);
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!ret.origin) alloc.free(ret.path);
|
defer {
|
||||||
|
if (!ret.origin) {
|
||||||
|
alloc.free(ret.path);
|
||||||
|
} else {
|
||||||
|
origin_finished = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defer std.debug.print("finished extract of {s}\n", .{ret.path});
|
||||||
alloc.destroy(ret.sub_files);
|
alloc.destroy(ret.sub_files);
|
||||||
|
|
||||||
if (!options.ignore_permissions and (!options.ignore_xattr and ret.xattr_idx != null)) {
|
if (!options.ignore_permissions and (!options.ignore_xattr and ret.xattr_idx != null)) {
|
||||||
@@ -347,7 +364,10 @@ fn returnLoop(alloc: std.mem.Allocator, io: Io, id_table: *Lookup.Table(u16), xa
|
|||||||
try file.setOwner(io, try id_table.get(io, ret.uid_idx), try id_table.get(io, ret.gid_idx));
|
try file.setOwner(io, try id_table.get(io, ret.uid_idx), try id_table.get(io, ret.gid_idx));
|
||||||
}
|
}
|
||||||
if (!options.ignore_xattr and ret.xattr_idx != null) {
|
if (!options.ignore_xattr and ret.xattr_idx != null) {
|
||||||
const xattrs = try xattr_table.get(alloc, io, ret.xattr_idx.?);
|
const xattrs = xattr_table.get(alloc, io, ret.xattr_idx.?) catch |err| {
|
||||||
|
std.debug.print("YO {}\n", .{err});
|
||||||
|
return err;
|
||||||
|
};
|
||||||
defer xattrs.deinit(alloc);
|
defer xattrs.deinit(alloc);
|
||||||
|
|
||||||
for (xattrs.xattrs) |x| {
|
for (xattrs.xattrs) |x| {
|
||||||
@@ -360,7 +380,14 @@ fn returnLoop(alloc: std.mem.Allocator, io: Io, id_table: *Lookup.Table(u16), xa
|
|||||||
},
|
},
|
||||||
.file_ret => |f| {
|
.file_ret => |f| {
|
||||||
const ret = try f;
|
const ret = try f;
|
||||||
if (!ret.origin) alloc.free(ret.path);
|
defer {
|
||||||
|
if (!ret.origin) {
|
||||||
|
alloc.free(ret.path);
|
||||||
|
} else {
|
||||||
|
origin_finished = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defer std.debug.print("finished extract of {s}\n", .{ret.path});
|
||||||
|
|
||||||
if (!options.ignore_permissions and (!options.ignore_xattr and ret.xattr_idx != null)) {
|
if (!options.ignore_permissions and (!options.ignore_xattr and ret.xattr_idx != null)) {
|
||||||
const file = try Io.Dir.cwd().openFile(io, ret.path, .{});
|
const file = try Io.Dir.cwd().openFile(io, ret.path, .{});
|
||||||
@@ -374,7 +401,10 @@ fn returnLoop(alloc: std.mem.Allocator, io: Io, id_table: *Lookup.Table(u16), xa
|
|||||||
try file.setOwner(io, try id_table.get(io, ret.uid_idx), try id_table.get(io, ret.gid_idx));
|
try file.setOwner(io, try id_table.get(io, ret.uid_idx), try id_table.get(io, ret.gid_idx));
|
||||||
}
|
}
|
||||||
if (!options.ignore_xattr and ret.xattr_idx != null) {
|
if (!options.ignore_xattr and ret.xattr_idx != null) {
|
||||||
const xattrs = try xattr_table.get(alloc, io, ret.xattr_idx.?);
|
const xattrs = xattr_table.get(alloc, io, ret.xattr_idx.?) catch |err| {
|
||||||
|
std.debug.print("YO!!! {s} {}\n", .{ ret.path, err });
|
||||||
|
return err;
|
||||||
|
};
|
||||||
defer xattrs.deinit(alloc);
|
defer xattrs.deinit(alloc);
|
||||||
|
|
||||||
for (xattrs.xattrs) |x| {
|
for (xattrs.xattrs) |x| {
|
||||||
@@ -387,8 +417,6 @@ fn returnLoop(alloc: std.mem.Allocator, io: Io, id_table: *Lookup.Table(u16), xa
|
|||||||
},
|
},
|
||||||
.void_ret => |v| try v,
|
.void_ret => |v| try v,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sel.group.token.load(.unordered) == null) break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -401,7 +429,7 @@ const ReturnUnion = union(enum) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Error = error{ Canceled, MknodError } || Directory.Error || Io.Dir.CreateFileAtomicError || Io.File.Atomic.LinkError ||
|
const Error = error{ Canceled, MknodError } || Directory.Error || Io.Dir.CreateFileAtomicError || Io.File.Atomic.LinkError ||
|
||||||
DataExtractor.Error || Io.Dir.SymLinkError;
|
DataExtractor.Error || Io.Dir.SymLinkError || Io.Dir.CreateDirPathError;
|
||||||
|
|
||||||
const FileReturn = struct {
|
const FileReturn = struct {
|
||||||
path: []const u8,
|
path: []const u8,
|
||||||
|
|||||||
+17
-8
@@ -3,6 +3,7 @@ const Io = std.Io;
|
|||||||
|
|
||||||
const Archive = @import("archive.zig");
|
const Archive = @import("archive.zig");
|
||||||
const Directory = @import("directory.zig");
|
const Directory = @import("directory.zig");
|
||||||
|
const Extract = @import("extract.zig");
|
||||||
const ExtractionOptions = @import("options.zig");
|
const ExtractionOptions = @import("options.zig");
|
||||||
const Inode = @import("inode.zig");
|
const Inode = @import("inode.zig");
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ pub fn init(alloc: std.mem.Allocator, archive: *Archive, inode: Inode, name: []c
|
|||||||
}
|
}
|
||||||
pub fn initDirEntry(alloc: std.mem.Allocator, io: Io, archive: *Archive, entry: Directory.Entry) !SfsFile {
|
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);
|
const new_name = try alloc.alloc(u8, entry.name.len);
|
||||||
defer alloc.free(new_name);
|
errdefer alloc.free(new_name);
|
||||||
@memcpy(new_name, entry.name);
|
@memcpy(new_name, entry.name);
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
@@ -62,13 +63,19 @@ pub fn deinit(self: SfsFile) void {
|
|||||||
self.alloc.free(self.name);
|
self.alloc.free(self.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn isDir(self: *SfsFile) bool {
|
||||||
|
return switch (self.inode.hdr.type) {
|
||||||
|
.dir, .ext_dir => true,
|
||||||
|
else => false,
|
||||||
|
};
|
||||||
|
}
|
||||||
/// Attempts to open the filepath if the SfsFile is a directory.
|
/// 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.
|
/// 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 {
|
pub fn open(self: *SfsFile, alloc: std.mem.Allocator, io: Io, filepath: []const u8) !SfsFile {
|
||||||
const path = std.mem.trim(u8, filepath, "/");
|
const path = std.mem.trim(u8, filepath, "/");
|
||||||
|
|
||||||
const first_element: []const u8 = std.mem.sliceTo(path, '/');
|
const first_element: []const u8 = std.mem.sliceTo(path, '/');
|
||||||
|
var found_file: SfsFile = blk: {
|
||||||
const dir: Directory = try self.inode.directory(alloc, io, &self.archive.cache, self.archive.super.dir_start);
|
const dir: Directory = try self.inode.directory(alloc, io, &self.archive.cache, self.archive.super.dir_start);
|
||||||
defer dir.deinit(alloc);
|
defer dir.deinit(alloc);
|
||||||
|
|
||||||
@@ -84,15 +91,17 @@ pub fn open(self: *SfsFile, alloc: std.mem.Allocator, io: Io, filepath: []const
|
|||||||
} else {
|
} else {
|
||||||
return error.NotFound;
|
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;
|
|
||||||
var 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..]);
|
break :blk try .initDirEntry(alloc, io, self.archive, cur_slice[idx]);
|
||||||
|
};
|
||||||
|
if (first_element.len == path.len) return found_file;
|
||||||
|
defer found_file.deinit();
|
||||||
|
|
||||||
|
if (!found_file.isDir()) return error.NotFound;
|
||||||
|
|
||||||
|
return found_file.open(alloc, io, path[first_element.len..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Extract = @import("extract.zig");
|
|
||||||
pub fn extract(self: *SfsFile, alloc: std.mem.Allocator, io: Io, ext_dir: []const u8, options: ExtractionOptions) !void {
|
pub fn extract(self: *SfsFile, alloc: std.mem.Allocator, io: Io, ext_dir: []const u8, options: ExtractionOptions) !void {
|
||||||
return Extract.extract(alloc, io, self.inode, &self.archive.cache, self.archive.super, ext_dir, options);
|
return Extract.extract(alloc, io, self.inode, &self.archive.cache, self.archive.super, ext_dir, options);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -49,7 +49,9 @@ pub fn Table(comptime T: anytype) type {
|
|||||||
.values = .init(alloc),
|
.values = .init(alloc),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub fn deinit(self: *LookupTable) void {
|
pub fn deinit(self: *LookupTable, io: Io) void {
|
||||||
|
self.mut.lockUncancelable(io);
|
||||||
|
|
||||||
var iter = self.values.valueIterator();
|
var iter = self.values.valueIterator();
|
||||||
while (iter.next()) |v|
|
while (iter.next()) |v|
|
||||||
self.alloc.free(v.*);
|
self.alloc.free(v.*);
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ fn stream(r: *Reader, w: *Writer, limit: Limit) Reader.StreamError!usize {
|
|||||||
if (r.seek >= r.end) {
|
if (r.seek >= r.end) {
|
||||||
const self: *MetadataReader = @fieldParentPtr("interface", r);
|
const self: *MetadataReader = @fieldParentPtr("interface", r);
|
||||||
self.advance() catch |err| {
|
self.advance() catch |err| {
|
||||||
|
if (err != error.Canceled)
|
||||||
std.debug.print("error advancing metadata reader: {}\n", .{err});
|
std.debug.print("error advancing metadata reader: {}\n", .{err});
|
||||||
return Reader.Error.ReadFailed;
|
return Reader.Error.ReadFailed;
|
||||||
};
|
};
|
||||||
@@ -79,6 +80,7 @@ fn discard(r: *Reader, limit: Limit) Reader.Error!usize {
|
|||||||
if (r.seek >= r.end) {
|
if (r.seek >= r.end) {
|
||||||
const self: *MetadataReader = @fieldParentPtr("interface", r);
|
const self: *MetadataReader = @fieldParentPtr("interface", r);
|
||||||
self.advance() catch |err| {
|
self.advance() catch |err| {
|
||||||
|
if (err != error.Canceled)
|
||||||
std.debug.print("error advancing metadata reader: {}\n", .{err});
|
std.debug.print("error advancing metadata reader: {}\n", .{err});
|
||||||
return Reader.Error.ReadFailed;
|
return Reader.Error.ReadFailed;
|
||||||
};
|
};
|
||||||
@@ -91,6 +93,7 @@ fn readVec(r: *Reader, vec: [][]u8) Reader.Error!usize {
|
|||||||
if (r.seek >= r.end) {
|
if (r.seek >= r.end) {
|
||||||
const self: *MetadataReader = @fieldParentPtr("interface", r);
|
const self: *MetadataReader = @fieldParentPtr("interface", r);
|
||||||
self.advance() catch |err| {
|
self.advance() catch |err| {
|
||||||
|
if (err != error.Canceled)
|
||||||
std.debug.print("error advancing metadata reader: {}\n", .{err});
|
std.debug.print("error advancing metadata reader: {}\n", .{err});
|
||||||
return Reader.Error.ReadFailed;
|
return Reader.Error.ReadFailed;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user