Same as symLink, except tries to create the symbolic link until it
succeeds or encounters an error other than error.PathAlreadyExists.
pub fn symLinkAtomic(
dir: Dir,
io: Io,
target_path: []const u8,
sym_link_path: []const u8,
flags: SymLinkFlags,
) !void
pub fn symLinkAtomic(
dir: Dir,
io: Io,
target_path: []const u8,
sym_link_path: []const u8,
flags: SymLinkFlags,
) !void {
if (dir.symLink(io, target_path, sym_link_path, flags)) {
return;
} else |err| switch (err) {
error.PathAlreadyExists => {},
else => |e| return e,
}
const dirname = path.dirname(sym_link_path) orelse ".";
const rand_len = @sizeOf(u64) * 2;
const temp_path_len = dirname.len + 1 + rand_len;
var temp_path_buf: [max_path_bytes]u8 = undefined;
if (temp_path_len > temp_path_buf.len) return error.NameTooLong;
@memcpy(temp_path_buf[0..dirname.len], dirname);
temp_path_buf[dirname.len] = path.sep;
const temp_path = temp_path_buf[0..temp_path_len];
var random_integer: u64 = undefined;
while (true) {
io.random(@ptrCast(&random_integer));
temp_path[dirname.len + 1 ..][0..rand_len].* = std.fmt.hex(random_integer);
if (dir.symLink(io, target_path, temp_path, flags)) {
return dir.rename(temp_path, dir, sym_link_path, io);
} else |err| switch (err) {
error.PathAlreadyExists => continue,
else => |e| return e,
}
}
}