| author | |
| committer | |
| log | 4d6429fc4fd299cdfb2256d4aac87bc6551ba09e |
| tree | 8b7de21ad01c27119b19a0b18b0cf962f418c985 |
| parent | 979fd12be96d5f8eda3e02ba676aecea78e6c0db |
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 |
| 9060 | pub extern "c" fn mmap(addr: ?*align(page_size) anyopaque, len: usize, prot: c_uint, flags: MAP, fd: fd_t, offset: off_t) *anyopaque; | 9060 | pub extern "c" fn mmap(addr: ?*align(page_size) anyopaque, len: usize, prot: c_uint, flags: MAP, fd: fd_t, offset: off_t) *anyopaque; |
| 9061 | pub extern "c" fn munmap(addr: *align(page_size) const anyopaque, len: usize) c_int; | 9061 | pub extern "c" fn munmap(addr: *align(page_size) const anyopaque, len: usize) c_int; |
| 9062 | pub extern "c" fn mprotect(addr: *align(page_size) anyopaque, len: usize, prot: c_uint) c_int; | 9062 | pub extern "c" fn mprotect(addr: *align(page_size) anyopaque, len: usize, prot: c_uint) c_int; |
| 9063 | pub extern "c" fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8, flags: c_int) c_int; | 9063 | pub extern "c" fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8) c_int; |
| 9064 | pub extern "c" fn linkat(oldfd: fd_t, oldpath: [*:0]const u8, newfd: fd_t, newpath: [*:0]const u8, flags: c_int) c_int; | 9064 | pub extern "c" fn linkat(oldfd: fd_t, oldpath: [*:0]const u8, newfd: fd_t, newpath: [*:0]const u8, flags: c_int) c_int; |
| 9065 | pub extern "c" fn unlink(path: [*:0]const u8) c_int; | 9065 | pub extern "c" fn unlink(path: [*:0]const u8) c_int; |
| 9066 | pub extern "c" fn unlinkat(dirfd: fd_t, path: [*:0]const u8, flags: c_uint) c_int; | 9066 | pub 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 | } |
| 1341 | 1341 | ||
| 1342 | pub fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8, flags: i32) usize { | 1342 | pub 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{ |
| 2202 | 2202 | ||
| 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. |
| 2205 | pub fn linkZ(oldpath: [*:0]const u8, newpath: [*:0]const u8, flags: i32) LinkError!void { | 2205 | pub 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 |
| 2233 | 2233 | ||
| 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. |
| 2236 | pub fn link(oldpath: []const u8, newpath: []const u8, flags: i32) LinkError!void { | 2236 | pub 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 directories | 2239 | 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 | } |
| 2247 | 2247 | ||
| 2248 | pub const LinkatError = LinkError || error{NotDir}; | 2248 | pub 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 {}; |
| 279 | 279 | ||
| 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"); |
| 282 | 282 | ||
| 283 | const efd = try cwd.openFile("example.txt", .{}); | 283 | const efd = try cwd.openFile("example.txt", .{}); |
| 284 | defer efd.close(); | 284 | defer efd.close(); |