Skip to content

Commit

Permalink
rsync: use a more robust check for relative link than "startswith"
Browse files Browse the repository at this point in the history
`startswith` is incorrect for paths in general, e.g. doesn't handle
Windows extended-length paths and other such.

The particular code here also wasn't careful about `/a/bc` not being
relative to `/a/b`.
  • Loading branch information
bluetech committed Apr 22, 2023
1 parent 8f0e8ec commit db7f204
Showing 1 changed file with 19 additions and 3 deletions.
22 changes: 19 additions & 3 deletions execnet/rsync.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,26 @@ def _send_directory(self, path):
self._send_directory_structure(p)

def _send_link_structure(self, path):
linkpoint = os.readlink(path)
sourcedir = self._sourcedir
basename = path[len(self._sourcedir) + 1 :]
if linkpoint.startswith(self._sourcedir):
self._send_link("linkbase", basename, linkpoint[len(self._sourcedir) + 1 :])
linkpoint = os.readlink(path)
# On Windows, readlink returns an extended path (//?/) for
# absolute links, but relpath doesn't like mixing extended
# and non-extended paths. So fix it up ourselves.
if (
os.path.__name__ == "ntpath"
and linkpoint.startswith("\\\\?\\")
and not self._sourcedir.startswith("\\\\?\\")
):
sourcedir = "\\\\?\\" + self._sourcedir
try:
relpath = os.path.relpath(linkpoint, sourcedir)
except ValueError:
relpath = None
if relpath not in (None, os.curdir, os.pardir) and not relpath.startswith(
os.pardir + os.sep
):
self._send_link("linkbase", basename, relpath)
else:
# relative or absolute link, just send it
self._send_link("link", basename, linkpoint)
Expand Down

0 comments on commit db7f204

Please sign in to comment.