gh-135034: Normalize link targets in tarfile, add `os.path.realpath(s… · Yhg1s/cpython@3612d8f (original) (raw)

`@@ -29,7 +29,7 @@

`

29

29

`"abspath","curdir","pardir","sep","pathsep","defpath","altsep",

`

30

30

`"extsep","devnull","realpath","supports_unicode_filenames","relpath",

`

31

31

`"samefile", "sameopenfile", "samestat", "commonpath", "isjunction",

`

32

``

`-

"isdevdrive"]

`

``

32

`+

"isdevdrive", "ALLOW_MISSING"]

`

33

33

``

34

34

`def _get_bothseps(path):

`

35

35

`if isinstance(path, bytes):

`

`@@ -601,9 +601,10 @@ def abspath(path):

`

601

601

`from nt import _findfirstfile, _getfinalpathname, readlink as _nt_readlink

`

602

602

`except ImportError:

`

603

603

`# realpath is a no-op on systems without _getfinalpathname support.

`

604

``

`-

realpath = abspath

`

``

604

`+

def realpath(path, *, strict=False):

`

``

605

`+

return abspath(path)

`

605

606

`else:

`

606

``

`-

def _readlink_deep(path):

`

``

607

`+

def _readlink_deep(path, ignored_error=OSError):

`

607

608

`# These error codes indicate that we should stop reading links and

`

608

609

`# return the path we currently have.

`

609

610

`# 1: ERROR_INVALID_FUNCTION

`

`@@ -636,7 +637,7 @@ def _readlink_deep(path):

`

636

637

`path = old_path

`

637

638

`break

`

638

639

`path = normpath(join(dirname(old_path), path))

`

639

``

`-

except OSError as ex:

`

``

640

`+

except ignored_error as ex:

`

640

641

`if ex.winerror in allowed_winerror:

`

641

642

`break

`

642

643

`raise

`

`@@ -645,7 +646,7 @@ def _readlink_deep(path):

`

645

646

`break

`

646

647

`return path

`

647

648

``

648

``

`-

def _getfinalpathname_nonstrict(path):

`

``

649

`+

def _getfinalpathname_nonstrict(path, ignored_error=OSError):

`

649

650

`# These error codes indicate that we should stop resolving the path

`

650

651

`# and return the value we currently have.

`

651

652

`# 1: ERROR_INVALID_FUNCTION

`

`@@ -673,25 +674,26 @@ def _getfinalpathname_nonstrict(path):

`

673

674

`try:

`

674

675

`path = _getfinalpathname(path)

`

675

676

`return join(path, tail) if tail else path

`

676

``

`-

except OSError as ex:

`

``

677

`+

except ignored_error as ex:

`

677

678

`if ex.winerror not in allowed_winerror:

`

678

679

`raise

`

679

680

`try:

`

680

681

`# The OS could not resolve this path fully, so we attempt

`

681

682

`# to follow the link ourselves. If we succeed, join the tail

`

682

683

`# and return.

`

683

``

`-

new_path = _readlink_deep(path)

`

``

684

`+

new_path = _readlink_deep(path,

`

``

685

`+

ignored_error=ignored_error)

`

684

686

`if new_path != path:

`

685

687

`return join(new_path, tail) if tail else new_path

`

686

``

`-

except OSError:

`

``

688

`+

except ignored_error:

`

687

689

`# If we fail to readlink(), let's keep traversing

`

688

690

`pass

`

689

691

`# If we get these errors, try to get the real name of the file without accessing it.

`

690

692

`if ex.winerror in (1, 5, 32, 50, 87, 1920, 1921):

`

691

693

`try:

`

692

694

`name = _findfirstfile(path)

`

693

695

`path, _ = split(path)

`

694

``

`-

except OSError:

`

``

696

`+

except ignored_error:

`

695

697

`path, name = split(path)

`

696

698

`else:

`

697

699

`path, name = split(path)

`

`@@ -721,24 +723,32 @@ def realpath(path, *, strict=False):

`

721

723

`if normcase(path) == devnull:

`

722

724

`return '\\.\NUL'

`

723

725

`had_prefix = path.startswith(prefix)

`

``

726

+

``

727

`+

if strict is ALLOW_MISSING:

`

``

728

`+

ignored_error = FileNotFoundError

`

``

729

`+

strict = True

`

``

730

`+

elif strict:

`

``

731

`+

ignored_error = ()

`

``

732

`+

else:

`

``

733

`+

ignored_error = OSError

`

``

734

+

724

735

`if not had_prefix and not isabs(path):

`

725

736

`path = join(cwd, path)

`

726

737

`try:

`

727

738

`path = _getfinalpathname(path)

`

728

739

`initial_winerror = 0

`

729

740

`except ValueError as ex:

`

730

741

`# gh-106242: Raised for embedded null characters

`

731

``

`-

In strict mode, we convert into an OSError.

`

``

742

`+

In strict modes, we convert into an OSError.

`

732

743

`# Non-strict mode returns the path as-is, since we've already

`

733

744

`# made it absolute.

`

734

745

`if strict:

`

735

746

`raise OSError(str(ex)) from None

`

736

747

`path = normpath(path)

`

737

``

`-

except OSError as ex:

`

738

``

`-

if strict:

`

739

``

`-

raise

`

``

748

`+

except ignored_error as ex:

`

740

749

`initial_winerror = ex.winerror

`

741

``

`-

path = _getfinalpathname_nonstrict(path)

`

``

750

`+

path = _getfinalpathname_nonstrict(path,

`

``

751

`+

ignored_error=ignored_error)

`

742

752

`# The path returned by _getfinalpathname will always start with \?\ -

`

743

753

`# strip off that prefix unless it was already provided on the original

`

744

754

`# path.

`