authorgravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2025-10-10 22:53:12-07:00
committergravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2025-11-15 18:07:25-08:00
log06a7597ea8ac8d66f20f75580f8e0a6964e1861e
tree360e527c05902a0f8c5701b4ca9a042175b11ad9
parent813e8614bc2ecda414f308a1662be074e788e3f2

windows.ReadLink: Use OpenFile now that `.filter = .any` exists

The reasoning in the comment deleted by this commit no longer applies, since that same benefit can be obtained by using OpenFile with `.filter = .any`. Also removes a stray debug.print

3 files changed, 23 insertions(+), 52 deletions(-)

lib/std/os/windows.zig+16-52
...@@ -889,61 +889,26 @@ pub const ReadLinkError = error{...@@ -889,61 +889,26 @@ pub const ReadLinkError = error{
889 AccessDenied,889 AccessDenied,
890 Unexpected,890 Unexpected,
891 NameTooLong,891 NameTooLong,
892 BadPathName,
893 AntivirusInterference,
892 UnsupportedReparsePointType,894 UnsupportedReparsePointType,
893};895};
894896
895pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u8) ReadLinkError![]u8 {897pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u8) ReadLinkError![]u8 {
896 // Here, we use `NtCreateFile` to shave off one syscall if we were to use `OpenFile` wrapper.898 const result_handle = OpenFile(sub_path_w, .{
897 // With the latter, we'd need to call `NtCreateFile` twice, once for file symlink, and if that899 .access_mask = FILE_READ_ATTRIBUTES | SYNCHRONIZE,
898 // failed, again for dir symlink. Omitting any mention of file/dir flags makes it possible900 .dir = dir,
899 // to open the symlink there and then.901 .creation = FILE_OPEN,
900 const path_len_bytes = math.cast(u16, sub_path_w.len * 2) orelse return error.NameTooLong;902 .follow_symlinks = false,
901 var nt_name = UNICODE_STRING{903 .filter = .any,
902 .Length = path_len_bytes,904 }) catch |err| switch (err) {
903 .MaximumLength = path_len_bytes,905 error.IsDir, error.NotDir => return error.Unexpected, // filter = .any
904 .Buffer = @constCast(sub_path_w.ptr),906 error.PathAlreadyExists => return error.Unexpected, // FILE_OPEN
905 };907 error.WouldBlock => return error.Unexpected,
906 var attr = OBJECT_ATTRIBUTES{908 error.NoDevice => return error.FileNotFound,
907 .Length = @sizeOf(OBJECT_ATTRIBUTES),909 error.PipeBusy => return error.AccessDenied,
908 .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir,910 else => |e| return e,
909 .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
910 .ObjectName = &nt_name,
911 .SecurityDescriptor = null,
912 .SecurityQualityOfService = null,
913 };911 };
914 var result_handle: HANDLE = undefined;
915 var io: IO_STATUS_BLOCK = undefined;
916
917 const rc = ntdll.NtCreateFile(
918 &result_handle,
919 FILE_READ_ATTRIBUTES | SYNCHRONIZE,
920 &attr,
921 &io,
922 null,
923 FILE_ATTRIBUTE_NORMAL,
924 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
925 FILE_OPEN,
926 FILE_OPEN_REPARSE_POINT | FILE_SYNCHRONOUS_IO_NONALERT,
927 null,
928 0,
929 );
930 switch (rc) {
931 .SUCCESS => {},
932 .OBJECT_NAME_INVALID => unreachable,
933 .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
934 .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
935 .NO_MEDIA_IN_DEVICE => return error.FileNotFound,
936 .BAD_NETWORK_PATH => return error.NetworkNotFound, // \\server was not found
937 .BAD_NETWORK_NAME => return error.NetworkNotFound, // \\server was found but \\server\share wasn't
938 .INVALID_PARAMETER => unreachable,
939 .SHARING_VIOLATION => return error.AccessDenied,
940 .ACCESS_DENIED => return error.AccessDenied,
941 .PIPE_BUSY => return error.AccessDenied,
942 .OBJECT_PATH_SYNTAX_BAD => unreachable,
943 .OBJECT_NAME_COLLISION => unreachable,
944 .FILE_IS_A_DIRECTORY => unreachable,
945 else => return unexpectedStatus(rc),
946 }
947 defer CloseHandle(result_handle);912 defer CloseHandle(result_handle);
948913
949 var reparse_buf: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 align(@alignOf(REPARSE_DATA_BUFFER)) = undefined;914 var reparse_buf: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 align(@alignOf(REPARSE_DATA_BUFFER)) = undefined;
...@@ -970,8 +935,7 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u8) ReadLin...@@ -970,8 +935,7 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u8) ReadLin
970 const path_buf = @as([*]const u16, &buf.PathBuffer);935 const path_buf = @as([*]const u16, &buf.PathBuffer);
971 return parseReadlinkPath(path_buf[offset..][0..len], false, out_buffer);936 return parseReadlinkPath(path_buf[offset..][0..len], false, out_buffer);
972 },937 },
973 else => |value| {938 else => {
974 std.debug.print("unsupported symlink type: {}", .{value});
975 return error.UnsupportedReparsePointType;939 return error.UnsupportedReparsePointType;
976 },940 },
977 }941 }
lib/std/posix.zig+6
...@@ -3001,6 +3001,12 @@ pub const ReadLinkError = error{...@@ -3001,6 +3001,12 @@ pub const ReadLinkError = error{
3001 UnsupportedReparsePointType,3001 UnsupportedReparsePointType,
3002 /// On Windows, `\\server` or `\\server\share` was not found.3002 /// On Windows, `\\server` or `\\server\share` was not found.
3003 NetworkNotFound,3003 NetworkNotFound,
3004 /// On Windows, antivirus software is enabled by default. It can be
3005 /// disabled, but Windows Update sometimes ignores the user's preference
3006 /// and re-enables it. When enabled, antivirus software on Windows
3007 /// intercepts file system operations and makes them significantly slower
3008 /// in addition to possibly failing with this error code.
3009 AntivirusInterference,
3004} || UnexpectedError;3010} || UnexpectedError;
30053011
3006/// Read value of a symbolic link.3012/// Read value of a symbolic link.
lib/std/zig/system.zig+1
...@@ -705,6 +705,7 @@ fn abiAndDynamicLinkerFromFile(...@@ -705,6 +705,7 @@ fn abiAndDynamicLinkerFromFile(
705 error.BadPathName => unreachable, // Windows only705 error.BadPathName => unreachable, // Windows only
706 error.UnsupportedReparsePointType => unreachable, // Windows only706 error.UnsupportedReparsePointType => unreachable, // Windows only
707 error.NetworkNotFound => unreachable, // Windows only707 error.NetworkNotFound => unreachable, // Windows only
708 error.AntivirusInterference => unreachable, // Windows only
708709
709 error.AccessDenied,710 error.AccessDenied,
710 error.PermissionDenied,711 error.PermissionDenied,