authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-10-14 09:21:35+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-10-14 09:21:35+02:00
logc22d99a3b27ecbb82c8ea59ad7645a0c10483d61
tree2c394f4781e4312931bcd1872360edb25629484a
parent32534ecae6e87ba3ea22698d06843e6d4f353208
parentcdd6e545cc7e4c6cb32d1a87695f215ce9d5f753

Merge pull request 'std.Io.Threaded: handle unsupported renamePreserveLinux' (#37210)

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/37210

2 files changed, 18 insertions(+), 4 deletions(-)

lib/std/Io/Dir.zig+7-2
...@@ -1122,8 +1122,7 @@ pub const RenamePreserveError = error{...@@ -1122,8 +1122,7 @@ pub const RenamePreserveError = error{
1122 /// policy of the current thread or process disallows dataless directory materialization.1122 /// policy of the current thread or process disallows dataless directory materialization.
1123 AccessDenied,1123 AccessDenied,
1124 PathAlreadyExists,1124 PathAlreadyExists,
1125 /// Operating system or file system does not support atomic nonreplacing1125 /// Operating system or file system does not support atomic nonreplacing rename.
1126 /// rename.
1127 OperationUnsupported,1126 OperationUnsupported,
1128} || RenameError;1127} || RenameError;
11291128
...@@ -1131,6 +1130,12 @@ pub const RenamePreserveError = error{...@@ -1131,6 +1130,12 @@ pub const RenamePreserveError = error{
1131///1130///
1132/// If `new_sub_path` already exists, `error.PathAlreadyExists` will be returned.1131/// If `new_sub_path` already exists, `error.PathAlreadyExists` will be returned.
1133///1132///
1133/// If the operating system supports it, the entire operation will be done atomically. If unsupported, will
1134/// fall back to hard link followed by unlink, which is atomic with respect to `new_sub_path` but leaves a
1135/// window where the cleanup of `old_sub_path may fail. Although the operation is fairly portable, technically
1136/// this fallback, too, may be unsupported in some environments, in which case `error.OperationUnsupported` is
1137/// returned.
1138///
1134/// * On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/).1139/// * On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
1135/// * On WASI, both paths should be encoded as valid UTF-8.1140/// * On WASI, both paths should be encoded as valid UTF-8.
1136/// * On other platforms, both paths are an opaque sequence of bytes with no particular encoding.1141/// * On other platforms, both paths are an opaque sequence of bytes with no particular encoding.
lib/std/Io/Threaded.zig+11-2
...@@ -7756,7 +7756,14 @@ fn dirRenamePreserve(...@@ -7756,7 +7756,14 @@ fn dirRenamePreserve(
7756 const t: *Threaded = @ptrCast(@alignCast(userdata));7756 const t: *Threaded = @ptrCast(@alignCast(userdata));
7757 if (is_windows) return dirRenameWindowsInner(old_dir, old_sub_path, new_dir, new_sub_path, false);7757 if (is_windows) return dirRenameWindowsInner(old_dir, old_sub_path, new_dir, new_sub_path, false);
7758 if (is_darwin) return dirRenamePreserveDarwin(old_dir, old_sub_path, new_dir, new_sub_path);7758 if (is_darwin) return dirRenamePreserveDarwin(old_dir, old_sub_path, new_dir, new_sub_path);
7759 if (native_os == .linux) return dirRenamePreserveLinux(old_dir, old_sub_path, new_dir, new_sub_path);7759 if (native_os == .linux) {
7760 if (dirRenamePreserveLinux(old_dir, old_sub_path, new_dir, new_sub_path)) |_| {
7761 return;
7762 } else |err| switch (err) {
7763 else => |e| return e,
7764 error.OperationUnsupported => {}, // Fall back to link/unlink below.
7765 }
7766 }
7760 // Make a hard link then delete the original.7767 // Make a hard link then delete the original.
7761 try dirHardLink(t, old_dir, old_sub_path, new_dir, new_sub_path, .{ .follow_symlinks = false });7768 try dirHardLink(t, old_dir, old_sub_path, new_dir, new_sub_path, .{ .follow_symlinks = false });
7762 const prev = swapCancelProtection(t, .blocked);7769 const prev = swapCancelProtection(t, .blocked);
...@@ -8084,8 +8091,10 @@ fn dirRenamePreserveLinux(...@@ -8084,8 +8091,10 @@ fn dirRenamePreserveLinux(
8084 .ROFS => return syscall.fail(error.ReadOnlyFileSystem),8091 .ROFS => return syscall.fail(error.ReadOnlyFileSystem),
8085 .XDEV => return syscall.fail(error.CrossDevice),8092 .XDEV => return syscall.fail(error.CrossDevice),
8086 .ILSEQ => return syscall.fail(error.BadPathName),8093 .ILSEQ => return syscall.fail(error.BadPathName),
8094 // EINVAL when passing NOREPLACE=true observed on ext4, 7.0.0-38-generic #38~24.04.4-Ubuntu.
8095 // OPNOTSUPP handled defensively.
8096 .INVAL, .OPNOTSUPP => return syscall.fail(error.OperationUnsupported),
8087 .FAULT => |err| return syscall.errnoBug(err),8097 .FAULT => |err| return syscall.errnoBug(err),
8088 .INVAL => |err| return syscall.errnoBug(err),
8089 else => |err| return syscall.unexpectedErrno(err),8098 else => |err| return syscall.unexpectedErrno(err),
8090 };8099 };
8091}8100}