Commit cc9c5c5b0e

Jakub Konka <kubkon@jakubkonka.com>
2020-07-15 17:55:02
Handle relative/absolute symlinks; add more tests
1 parent a8a02df
Changed files (2)
lib
lib/std/os/test.zig
@@ -70,29 +70,46 @@ test "readlink" {
     var arena = ArenaAllocator.init(testing.allocator);
     defer arena.deinit();
 
+
     const base_path = blk: {
         const relative_path = try fs.path.join(&arena.allocator, &[_][]const u8{ "zig-cache", "tmp", tmp.sub_path[0..] });
         break :blk try fs.realpathAlloc(&arena.allocator, relative_path);
     };
+    const allocator = &arena.allocator;
 
-    try testReadlink(&arena.allocator, base_path, "file.txt", "symlink1", false);
-    try testReadlink(&arena.allocator, base_path, "subdir", "symlink2", true);
-}
+    {
+        const target_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "file.txt" });
+        const symlink_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "symlink1" });
+        std.debug.warn("\ntarget_path={}\n", .{target_path});
+        std.debug.warn("symlink_path={}\n", .{symlink_path});
 
-fn testReadlink(allocator: *mem.Allocator, base_path: []const u8, target_name: []const u8, symlink_name: []const u8, is_dir: bool) !void {
-        const target_path = try fs.path.join(allocator, &[_][]const u8{ base_path, target_name });
-        const symlink_path = try fs.path.join(allocator, &[_][]const u8{ base_path, symlink_name });
+        // Create symbolic link by path
+        try os.symlink(target_path, symlink_path, .{ .is_directory = false });
+        try testReadlink(target_path, symlink_path);
+    }
+    {
+        const target_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "subdir" });
+        const symlink_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "symlink2" });
         std.debug.warn("\ntarget_path={}\n", .{target_path});
         std.debug.warn("symlink_path={}\n", .{symlink_path});
 
         // Create symbolic link by path
-        try os.symlink(target_path, symlink_path, .{ .is_directory = is_dir });
+        try os.symlink(target_path, symlink_path, .{ .is_directory = true });
+        try testReadlink(target_path, symlink_path);
+    }
 
-        // Read the link and verify
-        var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;
-        const given = try os.readlink(symlink_path, buffer[0..]);
-        std.debug.warn("given={}\n", .{given});
-        expect(mem.eql(u8, target_path, given));
+    if (builtin.os.tag == .windows) {
+        try testReadlink("C:\\ProgramData", "C:\\Users\\All Users");
+        try testReadlink("C:\\Users\\Default", "C:\\Users\\Default User");
+        try testReadlink("C:\\Users", "C:\\Documents and Settings");
+    }
+}
+
+fn testReadlink(target_path: []const u8, symlink_path: []const u8) !void {
+    var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;
+    const given = try os.readlink(symlink_path, buffer[0..]);
+    std.debug.warn("given={}\n", .{given});
+    expect(mem.eql(u8, target_path, given));
 }
 
 test "readlinkat" {
lib/std/os.zig
@@ -2437,7 +2437,10 @@ pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8
 
 fn parseReadlinkPath(path: []const u16, is_relative: bool, out_buffer: []u8) []u8 {
     const prefix = [_]u16{ '\\', '?', '?', '\\' };
-    const start_index = if (mem.startsWith(u16, path, &prefix)) prefix.len else 0;
+    var start_index: usize = 0;
+    if (!is_relative and mem.startsWith(u16, path, &prefix)) {
+        start_index = prefix.len;
+    }
     const out_len = std.unicode.utf16leToUtf8(out_buffer, path[start_index..]) catch unreachable;
     return out_buffer[0..out_len];
 }