| author | |
| committer | |
| log | aa6fcaf76f00453f160545e760c37d64588f4517 |
| tree | 8b49e097f27763c092e36b5fe3ef2638615cbe0b |
| parent | 65581b37cb4027d025ae7b0fc643ff0bd9c7f769 |
3 files changed, 49 insertions(+), 13 deletions(-)
lib/std/fs.zig+21-1| ... | ... | @@ -1215,7 +1215,6 @@ pub const Dir = struct { |
| 1215 | 1215 | /// A symbolic link (also known as a soft link) may point to an existing file or to a nonexistent |
| 1216 | 1216 | /// one; the latter case is known as a dangling link. |
| 1217 | 1217 | /// If `sym_link_path` exists, it will not be overwritten. |
| 1218 | /// TODO add Windows support | |
| 1219 | 1218 | pub fn symLink( |
| 1220 | 1219 | self: Dir, |
| 1221 | 1220 | target_path: []const u8, |
| ... | ... | @@ -1275,17 +1274,38 @@ pub const Dir = struct { |
| 1275 | 1274 | /// The return value is a slice of `buffer`, from index `0`. |
| 1276 | 1275 | /// Asserts that the path parameter has no null bytes. |
| 1277 | 1276 | 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 | } | |
| 1278 | 1283 | const sub_path_c = try os.toPosixPath(sub_path); |
| 1279 | 1284 | return self.readLinkZ(&sub_path_c, buffer); |
| 1280 | 1285 | } |
| 1281 | 1286 | |
| 1282 | 1287 | pub const readLinkC = @compileError("deprecated: renamed to readLinkZ"); |
| 1283 | 1288 | |
| 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 | ||
| 1284 | 1294 | /// Same as `readLink`, except the `pathname` parameter is null-terminated. |
| 1285 | 1295 | 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 | } | |
| 1286 | 1300 | return os.readlinkatZ(self.fd, sub_path_c, buffer); |
| 1287 | 1301 | } |
| 1288 | 1302 | |
| 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 | ||
| 1289 | 1309 | /// On success, caller owns returned buffer. |
| 1290 | 1310 | /// If the file is larger than `max_bytes`, returns `error.FileTooBig`. |
| 1291 | 1311 | 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; |
| 10 | 10 | const File = std.fs.File; |
| 11 | 11 | const tmpDir = testing.tmpDir; |
| 12 | 12 | |
| 13 | test "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 | ||
| 33 | fn 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 | ||
| 13 | 39 | test "readLinkAbsolute" { |
| 14 | 40 | if (builtin.os.tag == .wasi) return error.SkipZigTest; |
| 15 | 41 |
lib/std/os.zig+2-12| ... | ... | @@ -1594,9 +1594,7 @@ pub fn symlinkat(target_path: []const u8, newdirfd: fd_t, sym_link_path: []const |
| 1594 | 1594 | return symlinkatWasi(target_path, newdirfd, sym_link_path); |
| 1595 | 1595 | } |
| 1596 | 1596 | 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"); | |
| 1600 | 1598 | } |
| 1601 | 1599 | const target_path_c = try toPosixPath(target_path); |
| 1602 | 1600 | 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 |
| 1629 | 1627 | } |
| 1630 | 1628 | } |
| 1631 | 1629 | |
| 1632 | /// Windows-only. The same as `symlinkat` except the paths are null-terminated, WTF-16 encoded. | |
| 1633 | /// See also `symlinkat`. | |
| 1634 | pub 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 | ||
| 1638 | 1630 | /// The same as `symlinkat` except the parameters are null-terminated pointers. |
| 1639 | 1631 | /// See also `symlinkat`. |
| 1640 | 1632 | pub fn symlinkatZ(target_path: [*:0]const u8, newdirfd: fd_t, sym_link_path: [*:0]const u8) SymLinkError!void { |
| 1641 | 1633 | 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"); | |
| 1645 | 1635 | } |
| 1646 | 1636 | switch (errno(system.symlinkat(target_path, newdirfd, sym_link_path))) { |
| 1647 | 1637 | 0 => return, |