authorgravatar for pat.github@tullmann.orgPat Tullmann <pat.github@tullmann.org> 2024-07-31 22:49:39-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-08-07 13:05:42-07:00
log4d6429fc4fd299cdfb2256d4aac87bc6551ba09e
tree8b7de21ad01c27119b19a0b18b0cf962f418c985
parent979fd12be96d5f8eda3e02ba676aecea78e6c0db

POSIX link() syscall only takes two arguments (no flags)

The signature is documented as: int link(const char *, const char *); (see https://man7.org/linux/man-pages/man2/link.2.html or https://man.netbsd.org/link.2) And its not some Linux extension, the [syscall implementation](https://github.com/torvalds/linux/blob/21b136cc63d2a9ddd60d4699552b69c214b32964/fs/namei.c#L4794-L4797) only expects two arguments too. It probably *should* have a flags parameter, but its too late now. I am a bit surprised that linking glibc or musl against code that invokes a 'link' with three parameters doesn't fail (at least, I couldn't get any local test cases to trigger a compile or link error). The test case in std/posix/test.zig is currently disabled, but if I manually enable it, it works with this change.

4 files changed, 11 insertions(+), 12 deletions(-)

lib/std/c.zig+1-1
...@@ -9060,7 +9060,7 @@ pub extern "c" fn pwrite(fd: fd_t, buf: [*]const u8, nbyte: usize, offset: off_t...@@ -9060,7 +9060,7 @@ pub extern "c" fn pwrite(fd: fd_t, buf: [*]const u8, nbyte: usize, offset: off_t
9060pub extern "c" fn mmap(addr: ?*align(page_size) anyopaque, len: usize, prot: c_uint, flags: MAP, fd: fd_t, offset: off_t) *anyopaque;9060pub extern "c" fn mmap(addr: ?*align(page_size) anyopaque, len: usize, prot: c_uint, flags: MAP, fd: fd_t, offset: off_t) *anyopaque;
9061pub extern "c" fn munmap(addr: *align(page_size) const anyopaque, len: usize) c_int;9061pub extern "c" fn munmap(addr: *align(page_size) const anyopaque, len: usize) c_int;
9062pub extern "c" fn mprotect(addr: *align(page_size) anyopaque, len: usize, prot: c_uint) c_int;9062pub extern "c" fn mprotect(addr: *align(page_size) anyopaque, len: usize, prot: c_uint) c_int;
9063pub extern "c" fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8, flags: c_int) c_int;9063pub extern "c" fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8) c_int;
9064pub extern "c" fn linkat(oldfd: fd_t, oldpath: [*:0]const u8, newfd: fd_t, newpath: [*:0]const u8, flags: c_int) c_int;9064pub extern "c" fn linkat(oldfd: fd_t, oldpath: [*:0]const u8, newfd: fd_t, newpath: [*:0]const u8, flags: c_int) c_int;
9065pub extern "c" fn unlink(path: [*:0]const u8) c_int;9065pub extern "c" fn unlink(path: [*:0]const u8) c_int;
9066pub extern "c" fn unlinkat(dirfd: fd_t, path: [*:0]const u8, flags: c_uint) c_int;9066pub extern "c" fn unlinkat(dirfd: fd_t, path: [*:0]const u8, flags: c_uint) c_int;
lib/std/os/linux.zig+3-4
...@@ -1339,13 +1339,12 @@ pub fn tgkill(tgid: pid_t, tid: pid_t, sig: i32) usize {...@@ -1339,13 +1339,12 @@ pub fn tgkill(tgid: pid_t, tid: pid_t, sig: i32) usize {
1339 return syscall3(.tgkill, @as(usize, @bitCast(@as(isize, tgid))), @as(usize, @bitCast(@as(isize, tid))), @as(usize, @bitCast(@as(isize, sig))));1339 return syscall3(.tgkill, @as(usize, @bitCast(@as(isize, tgid))), @as(usize, @bitCast(@as(isize, tid))), @as(usize, @bitCast(@as(isize, sig))));
1340}1340}
13411341
1342pub fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8, flags: i32) usize {1342pub fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8) usize {
1343 if (@hasField(SYS, "link")) {1343 if (@hasField(SYS, "link")) {
1344 return syscall3(1344 return syscall2(
1345 .link,1345 .link,
1346 @intFromPtr(oldpath),1346 @intFromPtr(oldpath),
1347 @intFromPtr(newpath),1347 @intFromPtr(newpath),
1348 @as(usize, @bitCast(@as(isize, flags))),
1349 );1348 );
1350 } else {1349 } else {
1351 return syscall5(1350 return syscall5(
...@@ -1354,7 +1353,7 @@ pub fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8, flags: i32) usize {...@@ -1354,7 +1353,7 @@ pub fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8, flags: i32) usize {
1354 @intFromPtr(oldpath),1353 @intFromPtr(oldpath),
1355 @as(usize, @bitCast(@as(isize, AT.FDCWD))),1354 @as(usize, @bitCast(@as(isize, AT.FDCWD))),
1356 @intFromPtr(newpath),1355 @intFromPtr(newpath),
1357 @as(usize, @bitCast(@as(isize, flags))),1356 0,
1358 );1357 );
1359 }1358 }
1360}1359}
lib/std/posix.zig+6-6
...@@ -2202,11 +2202,11 @@ pub const LinkError = UnexpectedError || error{...@@ -2202,11 +2202,11 @@ pub const LinkError = UnexpectedError || error{
22022202
2203/// On WASI, both paths should be encoded as valid UTF-8.2203/// On WASI, both paths should be encoded as valid UTF-8.
2204/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding.2204/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding.
2205pub fn linkZ(oldpath: [*:0]const u8, newpath: [*:0]const u8, flags: i32) LinkError!void {2205pub fn linkZ(oldpath: [*:0]const u8, newpath: [*:0]const u8) LinkError!void {
2206 if (native_os == .wasi and !builtin.link_libc) {2206 if (native_os == .wasi and !builtin.link_libc) {
2207 return link(mem.sliceTo(oldpath, 0), mem.sliceTo(newpath, 0), flags);2207 return link(mem.sliceTo(oldpath, 0), mem.sliceTo(newpath, 0));
2208 }2208 }
2209 switch (errno(system.link(oldpath, newpath, flags))) {2209 switch (errno(system.link(oldpath, newpath))) {
2210 .SUCCESS => return,2210 .SUCCESS => return,
2211 .ACCES => return error.AccessDenied,2211 .ACCES => return error.AccessDenied,
2212 .DQUOT => return error.DiskQuota,2212 .DQUOT => return error.DiskQuota,
...@@ -2233,16 +2233,16 @@ pub fn linkZ(oldpath: [*:0]const u8, newpath: [*:0]const u8, flags: i32) LinkErr...@@ -2233,16 +2233,16 @@ pub fn linkZ(oldpath: [*:0]const u8, newpath: [*:0]const u8, flags: i32) LinkErr
22332233
2234/// On WASI, both paths should be encoded as valid UTF-8.2234/// On WASI, both paths should be encoded as valid UTF-8.
2235/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding.2235/// On other platforms, both paths are an opaque sequence of bytes with no particular encoding.
2236pub fn link(oldpath: []const u8, newpath: []const u8, flags: i32) LinkError!void {2236pub fn link(oldpath: []const u8, newpath: []const u8) LinkError!void {
2237 if (native_os == .wasi and !builtin.link_libc) {2237 if (native_os == .wasi and !builtin.link_libc) {
2238 return linkat(wasi.AT.FDCWD, oldpath, wasi.AT.FDCWD, newpath, flags) catch |err| switch (err) {2238 return linkat(wasi.AT.FDCWD, oldpath, wasi.AT.FDCWD, newpath, 0) catch |err| switch (err) {
2239 error.NotDir => unreachable, // link() does not support directories2239 error.NotDir => unreachable, // link() does not support directories
2240 else => |e| return e,2240 else => |e| return e,
2241 };2241 };
2242 }2242 }
2243 const old = try toPosixPath(oldpath);2243 const old = try toPosixPath(oldpath);
2244 const new = try toPosixPath(newpath);2244 const new = try toPosixPath(newpath);
2245 return try linkZ(&old, &new, flags);2245 return try linkZ(&old, &new);
2246}2246}
22472247
2248pub const LinkatError = LinkError || error{NotDir};2248pub const LinkatError = LinkError || error{NotDir};
lib/std/posix/test.zig+1-1
...@@ -278,7 +278,7 @@ test "link with relative paths" {...@@ -278,7 +278,7 @@ test "link with relative paths" {
278 cwd.deleteFile("new.txt") catch {};278 cwd.deleteFile("new.txt") catch {};
279279
280 try cwd.writeFile(.{ .sub_path = "example.txt", .data = "example" });280 try cwd.writeFile(.{ .sub_path = "example.txt", .data = "example" });
281 try posix.link("example.txt", "new.txt", 0);281 try posix.link("example.txt", "new.txt");
282282
283 const efd = try cwd.openFile("example.txt", .{});283 const efd = try cwd.openFile("example.txt", .{});
284 defer efd.close();284 defer efd.close();