Commit 7b25d050e6
lib/std/tar.zig
@@ -31,6 +31,10 @@ pub const Options = struct {
file_name: []const u8,
link_name: []const u8,
},
+ unable_to_create_file: struct {
+ code: anyerror,
+ file_name: []const u8,
+ },
unsupported_file_type: struct {
file_name: []const u8,
file_type: Header.FileType,
@@ -44,6 +48,9 @@ pub const Options = struct {
d.allocator.free(info.file_name);
d.allocator.free(info.link_name);
},
+ .unable_to_create_file => |info| {
+ d.allocator.free(info.file_name);
+ },
.unsupported_file_type => |info| {
d.allocator.free(info.file_name);
},
@@ -211,18 +218,34 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: anytype, options: Options) !voi
if (file_size == 0 and unstripped_file_name.len == 0) return;
const file_name = try stripComponents(unstripped_file_name, options.strip_components);
- if (std.fs.path.dirname(file_name)) |dir_name| {
- try dir.makePath(dir_name);
- }
- var file = try dir.createFile(file_name, .{});
- defer file.close();
+ var file = dir.createFile(file_name, .{}) catch |err| switch (err) {
+ error.FileNotFound => again: {
+ const code = code: {
+ if (std.fs.path.dirname(file_name)) |dir_name| {
+ dir.makePath(dir_name) catch |code| break :code code;
+ break :again dir.createFile(file_name, .{}) catch |code| {
+ break :code code;
+ };
+ }
+ break :code err;
+ };
+ const d = options.diagnostics orelse return error.UnableToCreateFile;
+ try d.errors.append(d.allocator, .{ .unable_to_create_file = .{
+ .code = code,
+ .file_name = try d.allocator.dupe(u8, file_name),
+ } });
+ break :again null;
+ },
+ else => |e| return e,
+ };
+ defer if (file) |f| f.close();
var file_off: usize = 0;
while (true) {
const temp = try buffer.readChunk(reader, @intCast(rounded_file_size + 512 - file_off));
if (temp.len == 0) return error.UnexpectedEndOfStream;
const slice = temp[0..@intCast(@min(file_size - file_off, temp.len))];
- try file.writeAll(slice);
+ if (file) |f| try f.writeAll(slice);
file_off += slice.len;
buffer.advance(slice.len);
@@ -275,13 +298,26 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: anytype, options: Options) !voi
},
.hard_link => return error.TarUnsupportedFileType,
.symbolic_link => {
+ // The file system path of the symbolic link.
const file_name = try stripComponents(unstripped_file_name, options.strip_components);
+ // The data inside the symbolic link.
const link_name = header.linkName();
- dir.symLink(link_name, file_name, .{}) catch |err| {
+ dir.symLink(link_name, file_name, .{}) catch |err| again: {
+ const code = code: {
+ if (err == error.FileNotFound) {
+ if (std.fs.path.dirname(file_name)) |dir_name| {
+ dir.makePath(dir_name) catch |code| break :code code;
+ break :again dir.symLink(link_name, file_name, .{}) catch |code| {
+ break :code code;
+ };
+ }
+ }
+ break :code err;
+ };
const d = options.diagnostics orelse return error.UnableToCreateSymLink;
try d.errors.append(d.allocator, .{ .unable_to_create_sym_link = .{
- .code = err,
+ .code = code,
.file_name = try d.allocator.dupe(u8, file_name),
.link_name = try d.allocator.dupe(u8, link_name),
} });
src/Package/Fetch.zig
@@ -1041,6 +1041,13 @@ fn unpackTarball(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!void {
}),
}));
},
+ .unable_to_create_file => |info| {
+ eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{
+ .msg = try eb.printString("unable to create file '{s}': {s}", .{
+ info.file_name, @errorName(info.code),
+ }),
+ }));
+ },
.unsupported_file_type => |info| {
eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{
.msg = try eb.printString("file '{s}' has unsupported type '{c}'", .{