authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-06-22 09:40:06+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-06-22 09:40:06+02:00
logc950f0c6c3d5472a635ba8b971f46200d41221fd
tree6661eabedac6f5cf2c65da2b83164267c49dbe7d
parent64078ca92439d4f01d4a6e60a6ad33025da5a36a

Enhance std.os.readlinkat coverage

Adds Windows stub (still needs to be implemented on Windows), adds WASI implementation, adds unit test testing basic chain of ops: create file -> symlink -> readlink.

2 files changed, 51 insertions(+), 3 deletions(-)

lib/std/os.zig+44-2
......@@ -1588,7 +1588,7 @@ pub const symlinkatC = @compileError("deprecated: renamed to symlinkatZ");
15881588/// WASI-only. The same as `symlinkat` but targeting WASI.
15891589/// See also `symlinkat`.
15901590pub fn symlinkatWasi(target_path: []const u8, newdirfd: fd_t, sym_link_path: []const u8) SymLinkError!void {
1591 switch (wasi.path_symlink(sym_link_path.ptr, sym_link_path.len, newdirfd, target_path.ptr, target_path.len)) {
1591 switch (wasi.path_symlink(target_path.ptr, target_path.len, newdirfd, sym_link_path.ptr, sym_link_path.len)) {
15921592 wasi.ESUCCESS => {},
15931593 wasi.EFAULT => unreachable,
15941594 wasi.EINVAL => unreachable,
......@@ -2343,12 +2343,54 @@ pub fn readlinkZ(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8
23432343 }
23442344}
23452345
2346/// Similar to `readlink` except reads value of a symbolink link **relative** to `dirfd` directory handle.
2347/// The return value is a slice of `out_buffer` from index 0.
2348/// See also `readlinkatWasi`, `realinkatZ` and `realinkatW`.
2349pub fn readlinkat(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 {
2350 if (builtin.os.tag == .wasi) {
2351 return readlinkatWasi(dirfd, file_path, out_buffer);
2352 }
2353 if (builtin.os.tag == .windows) {
2354 const file_path_w = try windows.cStrToPrefixedFileW(file_path);
2355 return readlinkatW(dirfd, file_path.span().ptr, out_buffer);
2356 }
2357 const file_path_c = try toPosixPath(file_path);
2358 return readlinkatZ(dirfd, &file_path_c, out_buffer);
2359}
2360
23462361pub const readlinkatC = @compileError("deprecated: renamed to readlinkatZ");
23472362
2363/// WASI-only. Same as `readlinkat` but targets WASI.
2364/// See also `readlinkat`.
2365pub fn readlinkatWasi(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 {
2366 var bufused: usize = undefined;
2367 switch (wasi.path_readlink(dirfd, file_path.ptr, file_path.len, out_buffer.ptr, out_buffer.len, &bufused)) {
2368 wasi.ESUCCESS => return out_buffer[0..bufused],
2369 wasi.EACCES => return error.AccessDenied,
2370 wasi.EFAULT => unreachable,
2371 wasi.EINVAL => unreachable,
2372 wasi.EIO => return error.FileSystem,
2373 wasi.ELOOP => return error.SymLinkLoop,
2374 wasi.ENAMETOOLONG => return error.NameTooLong,
2375 wasi.ENOENT => return error.FileNotFound,
2376 wasi.ENOMEM => return error.SystemResources,
2377 wasi.ENOTDIR => return error.NotDir,
2378 else => |err| return unexpectedErrno(err),
2379 }
2380}
2381
2382/// Windows-only. Same as `readlinkat` except `file_path` is null-terminated, WTF16 encoded.
2383/// See also `readlinkat`.
2384pub fn readlinkatW(dirfd: fd_t, file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 {
2385 @compileError("TODO implement on Windows");
2386}
2387
2388/// Same as `readlinkat` except `file_path` is null-terminated.
2389/// See also `readlinkat`.
23482390pub fn readlinkatZ(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 {
23492391 if (builtin.os.tag == .windows) {
23502392 const file_path_w = try windows.cStrToPrefixedFileW(file_path);
2351 @compileError("TODO implement readlink for Windows");
2393 return readlinkatW(dirfd, file_path_w.span().ptr, out_buffer);
23522394 }
23532395 const rc = system.readlinkat(dirfd, file_path, out_buffer.ptr, out_buffer.len);
23542396 switch (errno(rc)) {
lib/std/os/test.zig+7-1
......@@ -19,6 +19,9 @@ const tmpDir = std.testing.tmpDir;
1919const Dir = std.fs.Dir;
2020
2121test "readlinkat" {
22 // enable when `readlinkat` and `symlinkat` are implemented on Windows
23 if (builtin.os.tag == .windows) return error.SkipZigTest;
24
2225 var tmp = tmpDir(.{});
2326 defer tmp.cleanup();
2427
......@@ -28,7 +31,10 @@ test "readlinkat" {
2831 // create a symbolic link
2932 try os.symlinkat("file.txt", tmp.dir.fd, "link");
3033
31 // TODO read the link
34 // read the link
35 var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;
36 const read_link = try os.readlinkat(tmp.dir.fd, "link", buffer[0..]);
37 expect(mem.eql(u8, "file.txt", read_link));
3238}
3339
3440test "makePath, put some files in it, deleteTree" {