| ... | ... | @@ -7505,6 +7505,7 @@ fn dirRenamePreserve( |
| 7505 | 7505 | ) Dir.RenamePreserveError!void { |
| 7506 | 7506 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 7507 | 7507 | if (is_windows) return dirRenameWindowsInner(old_dir, old_sub_path, new_dir, new_sub_path, false); |
| 7508 | if (is_darwin) return dirRenamePreserveDarwin(old_dir, old_sub_path, new_dir, new_sub_path); |
| 7508 | 7509 | if (native_os == .linux) return dirRenamePreserveLinux(old_dir, old_sub_path, new_dir, new_sub_path); |
| 7509 | 7510 | // Make a hard link then delete the original. |
| 7510 | 7511 | try dirHardLink(t, old_dir, old_sub_path, new_dir, new_sub_path, .{ .follow_symlinks = false }); |
| ... | ... | @@ -7696,6 +7697,58 @@ fn dirRenamePosix( |
| 7696 | 7697 | return renameat(old_dir.handle, old_sub_path_posix, new_dir.handle, new_sub_path_posix); |
| 7697 | 7698 | } |
| 7698 | 7699 | |
| 7700 | fn dirRenamePreserveDarwin( |
| 7701 | old_dir: Dir, |
| 7702 | old_sub_path: []const u8, |
| 7703 | new_dir: Dir, |
| 7704 | new_sub_path: []const u8, |
| 7705 | ) Dir.RenamePreserveError!void { |
| 7706 | var old_path_buffer: [posix.PATH_MAX]u8 = undefined; |
| 7707 | var new_path_buffer: [posix.PATH_MAX]u8 = undefined; |
| 7708 | const old_sub_path_posix = try pathToPosix(old_sub_path, &old_path_buffer); |
| 7709 | const new_sub_path_posix = try pathToPosix(new_sub_path, &new_path_buffer); |
| 7710 | |
| 7711 | const syscall: Syscall = try .start(); |
| 7712 | while (true) { |
| 7713 | switch (posix.errno(std.c.renameatx_np( |
| 7714 | old_dir.handle, |
| 7715 | old_sub_path_posix, |
| 7716 | new_dir.handle, |
| 7717 | new_sub_path_posix, |
| 7718 | .{ .EXCL = true }, |
| 7719 | ))) { |
| 7720 | .SUCCESS => { |
| 7721 | syscall.finish(); |
| 7722 | break; |
| 7723 | }, |
| 7724 | .INTR => { |
| 7725 | try syscall.checkCancel(); |
| 7726 | continue; |
| 7727 | }, |
| 7728 | .INVAL => |err| return syscall.errnoBug(err), |
| 7729 | .FAULT => |err| return syscall.errnoBug(err), |
| 7730 | .BADF => |err| return syscall.errnoBug(err), |
| 7731 | .ISDIR => |err| return syscall.errnoBug(err), |
| 7732 | .NOTEMPTY => |err| return syscall.errnoBug(err), |
| 7733 | .OPNOTSUPP => return syscall.fail(error.OperationUnsupported), |
| 7734 | .IO => return syscall.fail(error.HardwareFailure), |
| 7735 | .DEADLK => return syscall.fail(error.AccessDenied), |
| 7736 | .ACCES => return syscall.fail(error.AccessDenied), |
| 7737 | .DQUOT => return syscall.fail(error.DiskQuota), |
| 7738 | .EXIST => return syscall.fail(error.PathAlreadyExists), |
| 7739 | .LOOP => return syscall.fail(error.LinkQuotaExceeded), |
| 7740 | .NAMETOOLONG => return syscall.fail(error.NameTooLong), |
| 7741 | .NOENT => return syscall.fail(error.FileNotFound), |
| 7742 | .NOSPC => return syscall.fail(error.NoSpaceLeft), |
| 7743 | .NOTDIR => return syscall.fail(error.NotDir), |
| 7744 | .PERM => return syscall.fail(error.PermissionDenied), |
| 7745 | .ROFS => return syscall.fail(error.ReadOnlyFileSystem), |
| 7746 | .XDEV => return syscall.fail(error.CrossDevice), |
| 7747 | else => |err| return syscall.unexpectedErrno(err), |
| 7748 | } |
| 7749 | } |
| 7750 | } |
| 7751 | |
| 7699 | 7752 | fn dirRenamePreserveLinux( |
| 7700 | 7753 | old_dir: Dir, |
| 7701 | 7754 | old_sub_path: []const u8, |
| ... | ... | @@ -7783,49 +7836,6 @@ fn renameat( |
| 7783 | 7836 | }; |
| 7784 | 7837 | } |
| 7785 | 7838 | |
| 7786 | | fn renameatPreserve( |
| 7787 | | old_dir: posix.fd_t, |
| 7788 | | old_sub_path: [*:0]const u8, |
| 7789 | | new_dir: posix.fd_t, |
| 7790 | | new_sub_path: [*:0]const u8, |
| 7791 | | ) Dir.RenameError!void { |
| 7792 | | const syscall: Syscall = try .start(); |
| 7793 | | while (true) { |
| 7794 | | switch (posix.errno(posix.system.renameat(old_dir, old_sub_path, new_dir, new_sub_path))) { |
| 7795 | | .SUCCESS => return syscall.finish(), |
| 7796 | | .INTR => { |
| 7797 | | try syscall.checkCancel(); |
| 7798 | | continue; |
| 7799 | | }, |
| 7800 | | else => |e| { |
| 7801 | | syscall.finish(); |
| 7802 | | switch (e) { |
| 7803 | | .ACCES => return error.AccessDenied, |
| 7804 | | .PERM => return error.PermissionDenied, |
| 7805 | | .BUSY => return error.FileBusy, |
| 7806 | | .DQUOT => return error.DiskQuota, |
| 7807 | | .FAULT => |err| return errnoBug(err), |
| 7808 | | .INVAL => |err| return errnoBug(err), |
| 7809 | | .ISDIR => return error.IsDir, |
| 7810 | | .LOOP => return error.SymLinkLoop, |
| 7811 | | .MLINK => return error.LinkQuotaExceeded, |
| 7812 | | .NAMETOOLONG => return error.NameTooLong, |
| 7813 | | .NOENT => return error.FileNotFound, |
| 7814 | | .NOTDIR => return error.NotDir, |
| 7815 | | .NOMEM => return error.SystemResources, |
| 7816 | | .NOSPC => return error.NoSpaceLeft, |
| 7817 | | .EXIST => return error.PathAlreadyExists, |
| 7818 | | .NOTEMPTY => return error.PathAlreadyExists, |
| 7819 | | .ROFS => return error.ReadOnlyFileSystem, |
| 7820 | | .XDEV => return error.CrossDevice, |
| 7821 | | .ILSEQ => return error.BadPathName, |
| 7822 | | else => |err| return posix.unexpectedErrno(err), |
| 7823 | | } |
| 7824 | | }, |
| 7825 | | } |
| 7826 | | } |
| 7827 | | } |
| 7828 | | |
| 7829 | 7839 | const dirSymLink = switch (native_os) { |
| 7830 | 7840 | .windows => dirSymLinkWindows, |
| 7831 | 7841 | .wasi => dirSymLinkWasi, |