authorgravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2025-12-10 18:59:15-08:00
committergravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2025-12-14 07:12:38-08:00
log36cb5ea5f4c9f1a96953f30812ebaf79f8a546d6
tree4a122b881c82ed7a1a9394e6e0379634b6f94bd8
parentea7512084bc6f0f18b9dc3d1ecd23599640b3363

windows.ReadLink: handle NOT_A_REPARSE_POINT and add test


2 files changed, 28 insertions(+), 0 deletions(-)

lib/std/fs/test.zig+26
......@@ -218,6 +218,32 @@ test "Dir.readLink" {
218218 }.impl);
219219}
220220
221test "Dir.readLink on non-symlinks" {
222 try testWithAllSupportedPathTypes(struct {
223 fn impl(ctx: *TestContext) !void {
224 const file_path = try ctx.transformPath("file.txt");
225 try ctx.dir.writeFile(.{ .sub_path = file_path, .data = "nonsense" });
226 const dir_path = try ctx.transformPath("subdir");
227 try ctx.dir.makeDir(dir_path);
228
229 // file
230 var buffer: [fs.max_path_bytes]u8 = undefined;
231 try std.testing.expectError(error.NotLink, ctx.dir.readLink(file_path, &buffer));
232 if (builtin.os.tag == .windows) {
233 var file_path_w = try std.os.windows.sliceToPrefixedFileW(ctx.dir.fd, file_path);
234 try std.testing.expectError(error.NotLink, ctx.dir.readLinkW(file_path_w.span(), &file_path_w.data));
235 }
236
237 // dir
238 try std.testing.expectError(error.NotLink, ctx.dir.readLink(dir_path, &buffer));
239 if (builtin.os.tag == .windows) {
240 var dir_path_w = try std.os.windows.sliceToPrefixedFileW(ctx.dir.fd, dir_path);
241 try std.testing.expectError(error.NotLink, ctx.dir.readLinkW(dir_path_w.span(), &dir_path_w.data));
242 }
243 }
244 }.impl);
245}
246
221247fn testReadLink(dir: Dir, target_path: []const u8, symlink_path: []const u8) !void {
222248 var buffer: [fs.max_path_bytes]u8 = undefined;
223249 const actual = try dir.readLink(symlink_path, buffer[0..]);
lib/std/os/windows.zig+2
......@@ -3125,6 +3125,7 @@ pub const ReadLinkError = error{
31253125 BadPathName,
31263126 AntivirusInterference,
31273127 UnsupportedReparsePointType,
3128 NotLink,
31283129};
31293130
31303131/// `sub_path_w` will never be accessed after `out_buffer` has been written to, so it
......@@ -3155,6 +3156,7 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u16) ReadLi
31553156 const rc = DeviceIoControl(result_handle, FSCTL.GET_REPARSE_POINT, .{ .out = reparse_buf[0..] });
31563157 switch (rc) {
31573158 .SUCCESS => {},
3159 .NOT_A_REPARSE_POINT => return error.NotLink,
31583160 else => return unexpectedStatus(rc),
31593161 }
31603162