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" {...@@ -218,6 +218,32 @@ test "Dir.readLink" {
218 }.impl);218 }.impl);
219}219}
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
221fn testReadLink(dir: Dir, target_path: []const u8, symlink_path: []const u8) !void {247fn testReadLink(dir: Dir, target_path: []const u8, symlink_path: []const u8) !void {
222 var buffer: [fs.max_path_bytes]u8 = undefined;248 var buffer: [fs.max_path_bytes]u8 = undefined;
223 const actual = try dir.readLink(symlink_path, buffer[0..]);249 const actual = try dir.readLink(symlink_path, buffer[0..]);
lib/std/os/windows.zig+2
...@@ -3125,6 +3125,7 @@ pub const ReadLinkError = error{...@@ -3125,6 +3125,7 @@ pub const ReadLinkError = error{
3125 BadPathName,3125 BadPathName,
3126 AntivirusInterference,3126 AntivirusInterference,
3127 UnsupportedReparsePointType,3127 UnsupportedReparsePointType,
3128 NotLink,
3128};3129};
31293130
3130/// `sub_path_w` will never be accessed after `out_buffer` has been written to, so it3131/// `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...@@ -3155,6 +3156,7 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u16) ReadLi
3155 const rc = DeviceIoControl(result_handle, FSCTL.GET_REPARSE_POINT, .{ .out = reparse_buf[0..] });3156 const rc = DeviceIoControl(result_handle, FSCTL.GET_REPARSE_POINT, .{ .out = reparse_buf[0..] });
3156 switch (rc) {3157 switch (rc) {
3157 .SUCCESS => {},3158 .SUCCESS => {},
3159 .NOT_A_REPARSE_POINT => return error.NotLink,
3158 else => return unexpectedStatus(rc),3160 else => return unexpectedStatus(rc),
3159 }3161 }
31603162