authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-07-21 20:40:34+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-07-22 08:51:23+02:00
logaa6fcaf76f00453f160545e760c37d64588f4517
tree8b49e097f27763c092e36b5fe3ef2638615cbe0b
parent65581b37cb4027d025ae7b0fc643ff0bd9c7f769

Add missing cross-platform Dir.readLink fns


3 files changed, 49 insertions(+), 13 deletions(-)

lib/std/fs.zig+21-1
......@@ -1215,7 +1215,6 @@ pub const Dir = struct {
12151215 /// A symbolic link (also known as a soft link) may point to an existing file or to a nonexistent
12161216 /// one; the latter case is known as a dangling link.
12171217 /// If `sym_link_path` exists, it will not be overwritten.
1218 /// TODO add Windows support
12191218 pub fn symLink(
12201219 self: Dir,
12211220 target_path: []const u8,
......@@ -1275,17 +1274,38 @@ pub const Dir = struct {
12751274 /// The return value is a slice of `buffer`, from index `0`.
12761275 /// Asserts that the path parameter has no null bytes.
12771276 pub fn readLink(self: Dir, sub_path: []const u8, buffer: []u8) ![]u8 {
1277 if (builtin.os.tag == .wasi) {
1278 return self.readLinkWasi(sub_path, buffer);
1279 }
1280 if (builtin.os.tag == .windows) {
1281 return os.windows.ReadLink(self.fd, sub_path, buffer);
1282 }
12781283 const sub_path_c = try os.toPosixPath(sub_path);
12791284 return self.readLinkZ(&sub_path_c, buffer);
12801285 }
12811286
12821287 pub const readLinkC = @compileError("deprecated: renamed to readLinkZ");
12831288
1289 /// WASI-only. Same as `readLink` except targeting WASI.
1290 pub fn readLinkWasi(self: Dir, sub_path: []const u8, buffer: []u8) ![]u8 {
1291 return os.readlinkatWasi(self.fd, sub_path, buffer);
1292 }
1293
12841294 /// Same as `readLink`, except the `pathname` parameter is null-terminated.
12851295 pub fn readLinkZ(self: Dir, sub_path_c: [*:0]const u8, buffer: []u8) ![]u8 {
1296 if (builtin.os.tag == .windows) {
1297 const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);
1298 return self.readLinkW(sub_path_w, buffer);
1299 }
12861300 return os.readlinkatZ(self.fd, sub_path_c, buffer);
12871301 }
12881302
1303 /// Windows-only. Same as `readLink` except the pathname parameter
1304 /// is null-terminated, WTF16 encoded.
1305 pub fn readLinkW(self: Dir, sub_path_w: [*:0]const u16, buffer: []u8) ![]u8 {
1306 return os.windows.ReadLinkW(self.fd, sub_path_w, buffer);
1307 }
1308
12891309 /// On success, caller owns returned buffer.
12901310 /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.
12911311 pub fn readFileAlloc(self: Dir, allocator: *mem.Allocator, file_path: []const u8, max_bytes: usize) ![]u8 {
lib/std/fs/test.zig+26
......@@ -10,6 +10,32 @@ const Dir = std.fs.Dir;
1010const File = std.fs.File;
1111const tmpDir = testing.tmpDir;
1212
13test "Dir.readLink" {
14 var tmp = tmpDir(.{});
15 defer tmp.cleanup();
16
17 // Create some targets
18 try tmp.dir.writeFile("file.txt", "nonsense");
19 try tmp.dir.makeDir("subdir");
20
21 {
22 // Create symbolic link by path
23 try tmp.dir.symLink("file.txt", "symlink1", .{});
24 try testReadLink(tmp.dir, "file.txt", "symlink1");
25 }
26 {
27 // Create symbolic link by path
28 try tmp.dir.symLink("subdir", "symlink2", .{ .is_directory = true });
29 try testReadLink(tmp.dir, "subdir", "symlink2");
30 }
31}
32
33fn testReadLink(dir: Dir, target_path: []const u8, symlink_path: []const u8) !void {
34 var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;
35 const given = try dir.readLink(symlink_path, buffer[0..]);
36 testing.expect(mem.eql(u8, target_path, given));
37}
38
1339test "readLinkAbsolute" {
1440 if (builtin.os.tag == .wasi) return error.SkipZigTest;
1541
lib/std/os.zig+2-12
......@@ -1594,9 +1594,7 @@ pub fn symlinkat(target_path: []const u8, newdirfd: fd_t, sym_link_path: []const
15941594 return symlinkatWasi(target_path, newdirfd, sym_link_path);
15951595 }
15961596 if (builtin.os.tag == .windows) {
1597 const target_path_w = try windows.sliceToPrefixedFileW(target_path);
1598 const sym_link_path_w = try windows.sliceToPrefixedFileW(sym_link_path);
1599 return symlinkatW(target_path_w.span().ptr, newdirfd, sym_link_path_w.span().ptr);
1597 @compileError("symlinkat is not supported on Windows; use std.os.windows.CreateSymbolicLink instead");
16001598 }
16011599 const target_path_c = try toPosixPath(target_path);
16021600 const sym_link_path_c = try toPosixPath(sym_link_path);
......@@ -1629,19 +1627,11 @@ pub fn symlinkatWasi(target_path: []const u8, newdirfd: fd_t, sym_link_path: []c
16291627 }
16301628}
16311629
1632/// Windows-only. The same as `symlinkat` except the paths are null-terminated, WTF-16 encoded.
1633/// See also `symlinkat`.
1634pub fn symlinkatW(target_path: [*:0]const u16, newdirfd: fd_t, sym_link_path: [*:0]const u16) SymLinkError!void {
1635 @compileError("TODO implement on Windows");
1636}
1637
16381630/// The same as `symlinkat` except the parameters are null-terminated pointers.
16391631/// See also `symlinkat`.
16401632pub fn symlinkatZ(target_path: [*:0]const u8, newdirfd: fd_t, sym_link_path: [*:0]const u8) SymLinkError!void {
16411633 if (builtin.os.tag == .windows) {
1642 const target_path_w = try windows.cStrToPrefixedFileW(target_path);
1643 const sym_link_path_w = try windows.cStrToPrefixedFileW(sym_link_path);
1644 return symlinkatW(target_path_w.span().ptr, newdirfd, sym_link_path.span().ptr);
1634 @compileError("symlinkat is not supported on Windows; use std.os.windows.CreateSymbolicLink instead");
16451635 }
16461636 switch (errno(system.symlinkat(target_path, newdirfd, sym_link_path))) {
16471637 0 => return,