94 lines
2.3 KiB
Zig
94 lines
2.3 KiB
Zig
const std = @import("std");
|
|
const WaitGroup = std.Thread.WaitGroup;
|
|
const Mutex = std.Thread.Mutex;
|
|
|
|
const Archive = @import("../archive.zig");
|
|
const Inode = @import("../inode.zig");
|
|
const ExtractionOptions = @import("../options.zig");
|
|
|
|
const InodeFinish = @This();
|
|
|
|
const FinishEnum = enum {
|
|
wg,
|
|
fin,
|
|
};
|
|
pub const FinishUnion = union(FinishEnum) {
|
|
wg: *WaitGroup,
|
|
fin: *InodeFinish,
|
|
|
|
pub fn finish(self: FinishUnion) void {
|
|
switch (self) {
|
|
.wg => |wg| wg.finish(),
|
|
.fin => |fin| fin.finish(),
|
|
}
|
|
}
|
|
};
|
|
|
|
alloc: std.mem.Allocator,
|
|
|
|
inode: Inode,
|
|
path: []const u8,
|
|
archive: *Archive,
|
|
options: ExtractionOptions,
|
|
parent_finish: FinishUnion,
|
|
fil: ?std.fs.File,
|
|
out_err: *?anyerror,
|
|
|
|
wg: WaitGroup = .{},
|
|
mut: Mutex = .{},
|
|
|
|
pub fn create(
|
|
alloc: std.mem.Allocator,
|
|
inode: Inode,
|
|
path: []const u8,
|
|
archive: *Archive,
|
|
options: ExtractionOptions,
|
|
parent_finish: FinishUnion,
|
|
out_err: *?anyerror,
|
|
fil: ?std.fs.File,
|
|
work_size: usize,
|
|
) !*InodeFinish {
|
|
const out = try alloc.create(InodeFinish);
|
|
errdefer alloc.destroy(out);
|
|
out.* = .{
|
|
.alloc = alloc,
|
|
|
|
.inode = inode,
|
|
.path = path,
|
|
.archive = archive,
|
|
.options = options,
|
|
.parent_finish = parent_finish,
|
|
.out_err = out_err,
|
|
.fil = fil,
|
|
};
|
|
out.wg.startMany(work_size);
|
|
return out;
|
|
}
|
|
|
|
pub fn finish(self: *InodeFinish) void {
|
|
self.mut.lock();
|
|
{
|
|
defer self.mut.unlock();
|
|
self.wg.finish();
|
|
if (!self.wg.isDone()) return;
|
|
}
|
|
defer {
|
|
self.parent_finish.finish();
|
|
self.alloc.destroy(self);
|
|
}
|
|
if (self.fil == null)
|
|
self.fil = std.fs.cwd().openFile(self.path, .{}) catch |err| {
|
|
if (self.options.verbose)
|
|
self.options.verbose_writer.?.print("Error opening {s} to set metadata: {}\n", .{ self.path, err }) catch {};
|
|
self.out_err.* = err;
|
|
return;
|
|
};
|
|
defer self.fil.?.close();
|
|
self.inode.setMetadata(self.alloc, self.archive, self.fil.?, self.options) catch |err| {
|
|
if (self.options.verbose)
|
|
self.options.verbose_writer.?.print("Error setting metadata to {s}: {}\n", .{ self.path, err }) catch {};
|
|
self.out_err.* = err;
|
|
return;
|
|
};
|
|
}
|