aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2023-10-07 23:09:39 -0700
committerAndrew Kelley <andrew@ziglang.org>2023-10-08 16:54:31 -0700
commit7b25d050e64fd91ec7df17f29f3a1b84e1431241 (patch)
tree86458208ef0dc07a626285dfc0424d5b860af7ee /lib/std
parente5c2a7dbca103b0c61bebaff95c5d5a5b777bd59 (diff)
downloadzig-7b25d050e64fd91ec7df17f29f3a1b84e1431241.tar.gz
zig-7b25d050e64fd91ec7df17f29f3a1b84e1431241.zip
std.tar: fix creation of symlinks with omit_empty_directories
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/tar.zig52
1 files changed, 44 insertions, 8 deletions
diff --git a/lib/std/tar.zig b/lib/std/tar.zig
index 9ed69730aa..bdbec87e39 100644
--- a/lib/std/tar.zig
+++ b/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),
} });