9767
9768
9769
9770
9771
9772
9773
9774
9775
9776
9777
9778
9779
9780
9781
9782
9783
9784
9785
9786
9787
9788
9789
9790
9791
9792
9793
9794
9795
9796
9797
9798
9799
9800
9801
9802
9803
9804
9805
9806
9807
9808
9809
9810
9811
9812
9813
9814
9815
9816
9817
9818
9819
9820
9821
9822
9823
9824
9825
9826
9827
9828
9829
9830
9831
9832
9833
9834
fn dirHardLink(
userdata: ?*anyopaque,
old_dir: Dir,
old_sub_path: []const u8,
new_dir: Dir,
new_sub_path: []const u8,
options: Dir.HardLinkOptions,
) Dir.HardLinkError!void {
if (is_windows) return error.OperationUnsupported;
const t: *Threaded = @ptrCast(@alignCast(userdata));
_ = t;
if (native_os == .wasi and !builtin.link_libc) {
const flags: std.os.wasi.lookupflags_t = .{
.SYMLINK_FOLLOW = options.follow_symlinks,
};
const syscall: Syscall = try .start();
while (true) {
switch (std.os.wasi.path_link(
old_dir.handle,
flags,
old_sub_path.ptr,
old_sub_path.len,
new_dir.handle,
new_sub_path.ptr,
new_sub_path.len,
)) {
.SUCCESS => return syscall.finish(),
.INTR => {
try syscall.checkCancel();
continue;
},
else => |e| {
syscall.finish();
switch (e) {
.ACCES => return error.AccessDenied,
.DQUOT => return error.DiskQuota,
.EXIST => return error.PathAlreadyExists,
.FAULT => |err| return errnoBug(err),
.IO => return error.HardwareFailure,
.LOOP => return error.SymLinkLoop,
.MLINK => return error.LinkQuotaExceeded,
.NAMETOOLONG => return error.NameTooLong,
.NOENT => return error.FileNotFound,
.NOMEM => return error.SystemResources,
.NOSPC => return error.NoSpaceLeft,
.NOTDIR => return error.NotDir,
.PERM => return error.PermissionDenied,
.ROFS => return error.ReadOnlyFileSystem,
.XDEV => return error.CrossDevice,
.INVAL => |err| return errnoBug(err),
.ILSEQ => return error.BadPathName,
else => |err| return posix.unexpectedErrno(err),
}
},
}
}
}
var old_path_buffer: [posix.PATH_MAX]u8 = undefined;
var new_path_buffer: [posix.PATH_MAX]u8 = undefined;
const old_sub_path_posix = try pathToPosix(old_sub_path, &old_path_buffer);
const new_sub_path_posix = try pathToPosix(new_sub_path, &new_path_buffer);
const flags: u32 = if (options.follow_symlinks) posix.AT.SYMLINK_FOLLOW else 0;
return linkat(old_dir.handle, old_sub_path_posix, new_dir.handle, new_sub_path_posix, flags);
}