authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-07-15 17:55:02+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-07-22 08:51:22+02:00
logcc9c5c5b0e7c37f96d7ea4c6bd22118ea72a0265
tree82947e5569da4fcbd0a63e81cc7160000659c1f0
parenta8a02dfbfaf4b9bd303712c853e202bd07837371

Handle relative/absolute symlinks; add more tests


2 files changed, 33 insertions(+), 13 deletions(-)

lib/std/os.zig+4-1
...@@ -2437,7 +2437,10 @@ pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8...@@ -2437,7 +2437,10 @@ pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8
24372437
2438fn parseReadlinkPath(path: []const u16, is_relative: bool, out_buffer: []u8) []u8 {2438fn parseReadlinkPath(path: []const u16, is_relative: bool, out_buffer: []u8) []u8 {
2439 const prefix = [_]u16{ '\\', '?', '?', '\\' };2439 const prefix = [_]u16{ '\\', '?', '?', '\\' };
2440 const start_index = if (mem.startsWith(u16, path, &prefix)) prefix.len else 0;2440 var start_index: usize = 0;
2441 if (!is_relative and mem.startsWith(u16, path, &prefix)) {
2442 start_index = prefix.len;
2443 }
2441 const out_len = std.unicode.utf16leToUtf8(out_buffer, path[start_index..]) catch unreachable;2444 const out_len = std.unicode.utf16leToUtf8(out_buffer, path[start_index..]) catch unreachable;
2442 return out_buffer[0..out_len];2445 return out_buffer[0..out_len];
2443}2446}
lib/std/os/test.zig+29-12
...@@ -70,29 +70,46 @@ test "readlink" {...@@ -70,29 +70,46 @@ test "readlink" {
70 var arena = ArenaAllocator.init(testing.allocator);70 var arena = ArenaAllocator.init(testing.allocator);
71 defer arena.deinit();71 defer arena.deinit();
7272
73
73 const base_path = blk: {74 const base_path = blk: {
74 const relative_path = try fs.path.join(&arena.allocator, &[_][]const u8{ "zig-cache", "tmp", tmp.sub_path[0..] });75 const relative_path = try fs.path.join(&arena.allocator, &[_][]const u8{ "zig-cache", "tmp", tmp.sub_path[0..] });
75 break :blk try fs.realpathAlloc(&arena.allocator, relative_path);76 break :blk try fs.realpathAlloc(&arena.allocator, relative_path);
76 };77 };
78 const allocator = &arena.allocator;
7779
78 try testReadlink(&arena.allocator, base_path, "file.txt", "symlink1", false);80 {
79 try testReadlink(&arena.allocator, base_path, "subdir", "symlink2", true);81 const target_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "file.txt" });
80}82 const symlink_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "symlink1" });
83 std.debug.warn("\ntarget_path={}\n", .{target_path});
84 std.debug.warn("symlink_path={}\n", .{symlink_path});
8185
82fn testReadlink(allocator: *mem.Allocator, base_path: []const u8, target_name: []const u8, symlink_name: []const u8, is_dir: bool) !void {86 // Create symbolic link by path
83 const target_path = try fs.path.join(allocator, &[_][]const u8{ base_path, target_name });87 try os.symlink(target_path, symlink_path, .{ .is_directory = false });
84 const symlink_path = try fs.path.join(allocator, &[_][]const u8{ base_path, symlink_name });88 try testReadlink(target_path, symlink_path);
89 }
90 {
91 const target_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "subdir" });
92 const symlink_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "symlink2" });
85 std.debug.warn("\ntarget_path={}\n", .{target_path});93 std.debug.warn("\ntarget_path={}\n", .{target_path});
86 std.debug.warn("symlink_path={}\n", .{symlink_path});94 std.debug.warn("symlink_path={}\n", .{symlink_path});
8795
88 // Create symbolic link by path96 // Create symbolic link by path
89 try os.symlink(target_path, symlink_path, .{ .is_directory = is_dir });97 try os.symlink(target_path, symlink_path, .{ .is_directory = true });
98 try testReadlink(target_path, symlink_path);
99 }
90100
91 // Read the link and verify101 if (builtin.os.tag == .windows) {
92 var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;102 try testReadlink("C:\\ProgramData", "C:\\Users\\All Users");
93 const given = try os.readlink(symlink_path, buffer[0..]);103 try testReadlink("C:\\Users\\Default", "C:\\Users\\Default User");
94 std.debug.warn("given={}\n", .{given});104 try testReadlink("C:\\Users", "C:\\Documents and Settings");
95 expect(mem.eql(u8, target_path, given));105 }
106}
107
108fn testReadlink(target_path: []const u8, symlink_path: []const u8) !void {
109 var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;
110 const given = try os.readlink(symlink_path, buffer[0..]);
111 std.debug.warn("given={}\n", .{given});
112 expect(mem.eql(u8, target_path, given));
96}113}
97114
98test "readlinkat" {115test "readlinkat" {