From 47c5f556c08c1b15c74dbaca743d17a3297bcdef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Anic=CC=81?= Date: Sat, 1 Aug 2026 13:41:45 +0200 Subject: [PATCH] Io.Uring: fix dir.hardLink Unsupported flags is used resulting in invalid arguments: ```Zig thread 556130 panic: programmer bug caused syscall error: INVAL .../lib/std/Io/Threaded.zig:14258:34: 0x116f3fa in errnoBug (std.zig) if (is_debug) std.debug.panic("programmer bug caused syscall error: {t}", .{err}); ^ .../lib/std/Io/Uring.zig:5583:44: 0x1281981 in linkat (std.zig) .INVAL => |err| return errnoBug(err), ^ .../lib/std/Io/Uring.zig:3555:21: 0x1289ab9 in dirHardLink (std.zig) return ev.linkat(``` ``` ```Zig test "linkat" { const gpa = testing.allocator; var uring: Io.Uring = undefined; try uring.init(gpa, .{}); defer uring.deinit(); var threaded = Io.Threaded.init(gpa, .{}); defer threaded.deinit(); for ([_]Io{ threaded.io(), uring.io() }) |io| { var tmp = testing.tmpDir(.{}); defer tmp.cleanup(); const dir = tmp.dir; const dir2 = try dir.createDirPathOpen(io, "folder/sub_folder", .{}); defer dir2.close(io); const file = try dir.createFile(io, "file", .{}); defer file.close(io); try dir.hardLink("file", dir2, "link", io, .{}); try file.hardLink(io, dir2, "link2", .{}); var stat = try dir.statFile(io, "folder/sub_folder/link", .{}); try testing.expectEqual(.file, stat.kind); stat = try dir.statFile(io, "folder/sub_folder/link2", .{}); try testing.expectEqual(.file, stat.kind); } } ``` --- lib/std/Io/Uring.zig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/std/Io/Uring.zig b/lib/std/Io/Uring.zig index 58d97dc0e8e090c84bec204f74be93a8bd5e5c37..6edf381378148e64941e64559150f77ad94a0650 100644 --- a/lib/std/Io/Uring.zig +++ b/lib/std/Io/Uring.zig @@ -3561,7 +3561,7 @@ fn dirHardLink( old_sub_path_posix, new_dir.handle, new_sub_path_posix, - if (options.follow_symlinks) 0 else linux.AT.SYMLINK_NOFOLLOW, + if (options.follow_symlinks) linux.AT.SYMLINK_FOLLOW else 0, ); } @@ -3993,7 +3993,7 @@ fn fileHardLink( "", new_dir.handle, new_sub_path_posix, - linux.AT.EMPTY_PATH | @as(u32, if (options.follow_symlinks) 0 else linux.AT.SYMLINK_NOFOLLOW), + linux.AT.EMPTY_PATH | @as(u32, if (options.follow_symlinks) linux.AT.SYMLINK_FOLLOW else 0), ); } @@ -5545,6 +5545,8 @@ fn linkat( new_path: [*:0]const u8, flags: u32, ) File.HardLinkError!void { + // allowed flags: https://man7.org/linux/man-pages/man2/linkat.2.html + assert(flags & ~(@as(u32, linux.AT.SYMLINK_FOLLOW | linux.AT.EMPTY_PATH)) == 0); while (true) { const thread = try cancel_region.awaitIoUring(); thread.enqueue().* = .{ -- 2.54.0