@@ -530,15 +530,28 @@ def _readlink_deep(path, seen=None):
530
530
if seen is None :
531
531
seen = set ()
532
532
533
+ # These error codes indicate that we should stop reading links and
534
+ # return the path we currently have.
535
+ # 1: ERROR_INVALID_FUNCTION
536
+ # 2: ERROR_FILE_NOT_FOUND
537
+ # 3: ERROR_DIRECTORY_NOT_FOUND
538
+ # 5: ERROR_ACCESS_DENIED
539
+ # 21: ERROR_NOT_READY (implies drive with no media)
540
+ # 32: ERROR_SHARING_VIOLATION (probably an NTFS paging file)
541
+ # 50: ERROR_NOT_SUPPORTED (implies no support for reparse points)
542
+ # 67: ERROR_BAD_NET_NAME (implies remote server unavailable)
543
+ # 87: ERROR_INVALID_PARAMETER
544
+ # 4390: ERROR_NOT_A_REPARSE_POINT
545
+ # 4392: ERROR_INVALID_REPARSE_DATA
546
+ # 4393: ERROR_REPARSE_TAG_INVALID
547
+ allowed_winerror = 1 , 2 , 3 , 5 , 21 , 32 , 50 , 67 , 87 , 4390 , 4392 , 4393
548
+
533
549
while normcase (path ) not in seen :
534
550
seen .add (normcase (path ))
535
551
try :
536
552
path = _nt_readlink (path )
537
553
except OSError as ex :
538
- # Stop on incorrect function (1), file (2) or
539
- # directory (3) not found, or paths that are
540
- # not reparse points (4390)
541
- if ex .winerror in (1 , 2 , 3 , 4390 ):
554
+ if ex .winerror in allowed_winerror :
542
555
break
543
556
raise
544
557
except ValueError :
@@ -554,9 +567,20 @@ def _getfinalpathname_nonstrict(path):
554
567
except OSError :
555
568
pass
556
569
557
- # Allow file (2) or directory (3) not found, incorrect parameter (87),
558
- # invalid syntax (123), and symlinks that cannot be followed (1921)
559
- allowed_winerror = 2 , 3 , 87 , 123 , 1921
570
+ # These error codes indicate that we should stop resolving the path
571
+ # and return the value we currently have.
572
+ # 1: ERROR_INVALID_FUNCTION
573
+ # 2: ERROR_FILE_NOT_FOUND
574
+ # 3: ERROR_DIRECTORY_NOT_FOUND
575
+ # 5: ERROR_ACCESS_DENIED
576
+ # 21: ERROR_NOT_READY (implies drive with no media)
577
+ # 32: ERROR_SHARING_VIOLATION (probably an NTFS paging file)
578
+ # 50: ERROR_NOT_SUPPORTED
579
+ # 67: ERROR_BAD_NET_NAME (implies remote server unavailable)
580
+ # 87: ERROR_INVALID_PARAMETER
581
+ # 123: ERROR_INVALID_NAME
582
+ # 1921: ERROR_CANT_RESOLVE_FILENAME (implies unfollowable symlink)
583
+ allowed_winerror = 1 , 2 , 3 , 5 , 21 , 32 , 50 , 67 , 87 , 123 , 1921
560
584
561
585
# Non-strict algorithm is to find as much of the target directory
562
586
# as we can and join the rest.
@@ -571,6 +595,9 @@ def _getfinalpathname_nonstrict(path):
571
595
if ex .winerror not in allowed_winerror :
572
596
raise
573
597
path , name = split (path )
598
+ # TODO (bpo-38186): Request the real file name from the directory
599
+ # entry using FindFirstFileW. For now, we will return the path
600
+ # as best we have it
574
601
if path and not name :
575
602
return abspath (path + tail )
576
603
tail = join (name , tail ) if tail else name
0 commit comments