@@ -889,61 +889,26 @@ pub const ReadLinkError = error{
889889 AccessDenied ,
890890 Unexpected ,
891891 NameTooLong ,
892+ BadPathName ,
893+ AntivirusInterference ,
892894 UnsupportedReparsePointType ,
893895};
894896
895897pub 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.
897- // With the latter, we'd need to call `NtCreateFile` twice, once for file symlink, and if that
898- // failed, again for dir symlink. Omitting any mention of file/dir flags makes it possible
899- // to open the symlink there and then.
900- const path_len_bytes = math .cast (u16 , sub_path_w .len * 2 ) orelse return error .NameTooLong ;
901- var nt_name = UNICODE_STRING {
902- .Length = path_len_bytes ,
903- .MaximumLength = path_len_bytes ,
904- .Buffer = @constCast (sub_path_w .ptr ),
905- };
906- var attr = OBJECT_ATTRIBUTES {
907- .Length = @sizeOf (OBJECT_ATTRIBUTES ),
908- .RootDirectory = if (std .fs .path .isAbsoluteWindowsWtf16 (sub_path_w )) null else dir ,
909- .Attributes = 0 , // Note we do not use OBJ_CASE_INSENSITIVE here.
910- .ObjectName = & nt_name ,
911- .SecurityDescriptor = null ,
912- .SecurityQualityOfService = null ,
898+ const result_handle = OpenFile (sub_path_w , .{
899+ .access_mask = FILE_READ_ATTRIBUTES | SYNCHRONIZE ,
900+ .dir = dir ,
901+ .creation = FILE_OPEN ,
902+ .follow_symlinks = false ,
903+ .filter = .any ,
904+ }) catch | err | switch (err ) {
905+ error .IsDir , error .NotDir = > return error .Unexpected , // filter = .any
906+ error .PathAlreadyExists = > return error .Unexpected , // FILE_OPEN
907+ error .WouldBlock = > return error .Unexpected ,
908+ error .NoDevice = > return error .FileNotFound ,
909+ error .PipeBusy = > return error .AccessDenied ,
910+ else = > | e | return e ,
913911 };
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- }
947912 defer CloseHandle (result_handle );
948913
949914 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
970935 const path_buf = @as ([* ]const u16 , & buf .PathBuffer );
971936 return parseReadlinkPath (path_buf [offset .. ][0.. len ], false , out_buffer );
972937 },
973- else = > | value | {
974- std .debug .print ("unsupported symlink type: {}" , .{value });
938+ else = > {
975939 return error .UnsupportedReparsePointType ;
976940 },
977941 }
0 commit comments