authorgravatar for igor.anic@gmail.comIgor Anić <igor.anic@gmail.com> 2026-08-01 13:41:45+02:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-08-01 23:46:10+02:00
log47c5f556c08c1b15c74dbaca743d17a3297bcdef
tree1fe7819435a81b5b9fb5b367d943a0a471f912ce
parentc854c6577a0720fc538f55d9e2a65621172035eb

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); } } ```

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

lib/std/Io/Uring.zig+4-2
...@@ -3561,7 +3561,7 @@ fn dirHardLink(...@@ -3561,7 +3561,7 @@ fn dirHardLink(
3561 old_sub_path_posix,3561 old_sub_path_posix,
3562 new_dir.handle,3562 new_dir.handle,
3563 new_sub_path_posix,3563 new_sub_path_posix,
3564 if (options.follow_symlinks) 0 else linux.AT.SYMLINK_NOFOLLOW,3564 if (options.follow_symlinks) linux.AT.SYMLINK_FOLLOW else 0,
3565 );3565 );
3566}3566}
35673567
...@@ -3993,7 +3993,7 @@ fn fileHardLink(...@@ -3993,7 +3993,7 @@ fn fileHardLink(
3993 "",3993 "",
3994 new_dir.handle,3994 new_dir.handle,
3995 new_sub_path_posix,3995 new_sub_path_posix,
3996 linux.AT.EMPTY_PATH | @as(u32, if (options.follow_symlinks) 0 else linux.AT.SYMLINK_NOFOLLOW),3996 linux.AT.EMPTY_PATH | @as(u32, if (options.follow_symlinks) linux.AT.SYMLINK_FOLLOW else 0),
3997 );3997 );
3998}3998}
39993999
...@@ -5545,6 +5545,8 @@ fn linkat(...@@ -5545,6 +5545,8 @@ fn linkat(
5545 new_path: [*:0]const u8,5545 new_path: [*:0]const u8,
5546 flags: u32,5546 flags: u32,
5547) File.HardLinkError!void {5547) File.HardLinkError!void {
5548 // allowed flags: https://man7.org/linux/man-pages/man2/linkat.2.html
5549 assert(flags & ~(@as(u32, linux.AT.SYMLINK_FOLLOW | linux.AT.EMPTY_PATH)) == 0);
5548 while (true) {5550 while (true) {
5549 const thread = try cancel_region.awaitIoUring();5551 const thread = try cancel_region.awaitIoUring();
5550 thread.enqueue().* = .{5552 thread.enqueue().* = .{