authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-03-21 00:04:10+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-03-21 00:04:10+01:00
loge938344100da959308aa27dee1295e5ce02efc30
treee549e778aef7a4a0fa4d20dc83ca94a59070706a
parent4c3877069dbf3476b15cea9258d164bda26e8385
parenta9e5c72aa885c67348277ca982fb964fd686254e

Merge pull request 'linux: fix handling of O_TMPFILE flag on filesystems that do not support it' (#31543) from eshom/zig:tmpfile-not-supported into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31543 Reviewed-by: Andrew Kelley <andrew@ziglang.org>

2 files changed, 23 insertions(+), 17 deletions(-)

lib/std/Io/Threaded.zig+1-1
......@@ -4704,7 +4704,7 @@ fn dirCreateFileAtomic(
47044704 try syscall.checkCancel();
47054705 continue;
47064706 },
4707 .ISDIR, .NOENT => {
4707 .ISDIR, .NOENT, .OPNOTSUPP => {
47084708 // Ambiguous error code. It might mean the file system
47094709 // does not support O_TMPFILE. Therefore, we must fall
47104710 // back to not using O_TMPFILE.
lib/std/Io/Uring.zig+22-16
......@@ -593,7 +593,10 @@ const CachedFd = struct {
593593 @atomicStore(Once, &cached_fd.once, .uninitialized, .monotonic);
594594 futexWake(ev, @ptrCast(&cached_fd.once), 1);
595595 }
596 const fd = try ev.openat(cancel_region, linux.AT.FDCWD, path, flags, 0);
596 const fd = ev.openat(cancel_region, linux.AT.FDCWD, path, flags, 0) catch |err| switch (err) {
597 error.OperationUnsupported => return error.Unexpected, // TMPFILE unset.
598 else => |e| return e,
599 };
597600 @atomicStore(Once, &cached_fd.once, .fromFd(fd), .monotonic);
598601 futexWake(ev, @ptrCast(&cached_fd.once), std.math.maxInt(u32));
599602 return fd;
......@@ -2722,12 +2725,10 @@ fn dirOpenDir(
27222725 error.WouldBlock => return errnoBug(.AGAIN),
27232726 error.FileTooBig => return errnoBug(.FBIG),
27242727 error.NoSpaceLeft => return errnoBug(.NOSPC),
2725 error.DeviceBusy => return errnoBug(.BUSY), // O_EXCL not passed
2728 error.DeviceBusy => return errnoBug(.BUSY), // EXCL unset.
27262729 error.FileBusy => return errnoBug(.TXTBSY),
27272730 error.PathAlreadyExists => return errnoBug(.EXIST), // Not creating.
2728 error.PipeBusy => return error.Unexpected, // Not opening a pipe.
2729 error.AntivirusInterference => unreachable, // Windows-only
2730 error.FileLocksUnsupported => return errnoBug(.OPNOTSUPP), // Not asking for locks.
2731 error.OperationUnsupported => return errnoBug(.OPNOTSUPP), // No TMPFILE, no locks.
27312732 else => |e| return e,
27322733 },
27332734 };
......@@ -2810,13 +2811,16 @@ fn dirCreateFile(
28102811
28112812 var maybe_sync: CancelRegion.Sync.Maybe = .{ .cancel_region = .init() };
28122813 defer maybe_sync.deinit(ev);
2813 const fd = try ev.openat(&maybe_sync.cancel_region, dir.handle, sub_path_posix, .{
2814 const fd = ev.openat(&maybe_sync.cancel_region, dir.handle, sub_path_posix, .{
28142815 .ACCMODE = if (flags.read) .RDWR else .WRONLY,
28152816 .CREAT = true,
28162817 .TRUNC = flags.truncate,
28172818 .EXCL = flags.exclusive,
28182819 .CLOEXEC = true,
2819 }, flags.permissions.toMode());
2820 }, flags.permissions.toMode()) catch |err| switch (err) {
2821 error.OperationUnsupported => return error.Unexpected, // TMPFILE unset.
2822 else => |e| return e,
2823 };
28202824 errdefer ev.closeAsync(fd);
28212825
28222826 switch (flags.lock) {
......@@ -2892,7 +2896,7 @@ fn dirCreateFileAtomic(
28922896 flags,
28932897 options.permissions.toMode(),
28942898 ) catch |err| switch (err) {
2895 error.IsDir, error.FileNotFound => {
2899 error.IsDir, error.FileNotFound, error.OperationUnsupported => {
28962900 // Ambiguous error code. It might mean the file system
28972901 // does not support O_TMPFILE. Therefore, we must fall
28982902 // back to not using O_TMPFILE.
......@@ -2901,9 +2905,6 @@ fn dirCreateFileAtomic(
29012905 error.FileTooBig => return errnoBug(.FBIG),
29022906 error.DeviceBusy => return errnoBug(.BUSY), // O_EXCL not passed
29032907 error.PathAlreadyExists => return errnoBug(.EXIST), // Not creating.
2904 error.PipeBusy => return error.Unexpected, // Not opening a pipe.
2905 error.AntivirusInterference => unreachable, // Windows-only
2906 error.FileLocksUnsupported => return errnoBug(.OPNOTSUPP), // Not asking for locks.
29072908 else => |e| return e,
29082909 },
29092910 .flags = .{ .nonblocking = false },
......@@ -2994,7 +2995,7 @@ fn dirOpenFile(
29942995
29952996 var maybe_sync: CancelRegion.Sync.Maybe = .{ .cancel_region = .init() };
29962997 defer maybe_sync.deinit(ev);
2997 const fd = try ev.openat(&maybe_sync.cancel_region, dir.handle, sub_path_posix, .{
2998 const fd = ev.openat(&maybe_sync.cancel_region, dir.handle, sub_path_posix, .{
29982999 .ACCMODE = switch (flags.mode) {
29993000 .read_only => .RDONLY,
30003001 .write_only => .WRONLY,
......@@ -3004,7 +3005,10 @@ fn dirOpenFile(
30043005 .NOFOLLOW = !flags.follow_symlinks,
30053006 .CLOEXEC = true,
30063007 .PATH = flags.path_only,
3007 }, 0);
3008 }, 0) catch |err| switch (err) {
3009 error.OperationUnsupported => return error.Unexpected, // TMPFILE unset.
3010 else => |e| return e,
3011 };
30083012 errdefer ev.closeAsync(fd);
30093013
30103014 if (!flags.allow_directory) {
......@@ -3149,7 +3153,7 @@ fn dirRealPathFile(
31493153 .PATH = true,
31503154 }, 0) catch |err| switch (err) {
31513155 error.WouldBlock => return errnoBug(.AGAIN),
3152 error.FileLocksUnsupported => return errnoBug(.OPNOTSUPP), // Not asking for locks.
3156 error.OperationUnsupported => return errnoBug(.OPNOTSUPP), // Not asking for locks.
31533157 else => |e| return e,
31543158 };
31553159 defer ev.closeAsync(fd);
......@@ -5616,7 +5620,7 @@ fn openat(
56165620 path: [*:0]const u8,
56175621 flags: linux.O,
56185622 mode: linux.mode_t,
5619) File.OpenError!fd_t {
5623) !fd_t {
56205624 var mut_flags = flags;
56215625 if (@hasField(linux.O, "LARGEFILE")) mut_flags.LARGEFILE = true;
56225626 while (true) {
......@@ -5662,7 +5666,9 @@ fn openat(
56625666 .PERM => return error.PermissionDenied,
56635667 .EXIST => return error.PathAlreadyExists,
56645668 .BUSY => return error.DeviceBusy,
5665 .OPNOTSUPP => return error.FileLocksUnsupported,
5669 // This can be triggered by file locking and TMPFILE, but those
5670 // flags are mutually exclusive.
5671 .OPNOTSUPP => return error.OperationUnsupported,
56665672 .AGAIN => return error.WouldBlock,
56675673 .TXTBSY => return error.FileBusy,
56685674 .NXIO => return error.NoDevice,