diff -r 358a35471f9f Lib/tarfile.py --- a/Lib/tarfile.py Fri Dec 13 20:53:26 2013 -0500 +++ b/Lib/tarfile.py Sat Dec 14 17:18:46 2013 +0800 @@ -1996,8 +1996,12 @@ tarinfo._link_target = os.path.join(path, tarinfo.linkname) try: - self._extract_member(tarinfo, os.path.join(path, tarinfo.name), - set_attrs=set_attrs) + joined_path = '/' + tarinfo.name + # We don't want to join '/home/user' and 'home/user/file' to avoid + # '/home/user/home/user/file'. + if path != joined_path[:len(path)]: + joined_path = os.path.join(path, tarinfo.name) + self._extract_member(tarinfo, joined_path, set_attrs=set_attrs) except OSError as e: if self.errorlevel > 0: raise @@ -2155,6 +2159,8 @@ try: # For systems that support symbolic and hard links. if tarinfo.issym(): + if os.path.exists(targetpath): + os.unlink(targetpath) os.symlink(tarinfo.linkname, targetpath) else: # See extract(). diff -r 358a35471f9f Lib/test/test_tarfile.py --- a/Lib/test/test_tarfile.py Fri Dec 13 20:53:26 2013 -0500 +++ b/Lib/test/test_tarfile.py Sat Dec 14 17:18:46 2013 +0800 @@ -1068,20 +1068,28 @@ temparchive = os.path.join(TEMPDIR, "testsymlinks.tar") os.mkdir(tempdir) try: - source_file = os.path.join(tempdir,'source') + source_file = os.path.join(tempdir, 'source') + other_source_file = os.path.join(tempdir, 'other_source') target_file = os.path.join(tempdir,'symlink') - with open(source_file,'w') as f: - f.write('something\n') + open(source_file, 'w').close() + open(other_source_file, 'w').close() os.symlink(source_file, target_file) tar = tarfile.open(temparchive,'w') tar.add(source_file) tar.add(target_file) tar.close() + # Point target_file to other_source_file to exersice overwriting + # behavior. + os.unlink(target_file) + os.symlink(other_source_file, target_file) # Let's extract it to the location which contains the symlink tar = tarfile.open(temparchive,'r') - # this should not raise OSError: [Errno 17] File exists + # This should not raise OSError: [Errno 17] File exists try: tar.extractall(path=tempdir) + # target_file that symlinked to other_source_file now symlinks + # back to source_file. + self.assertEqual(os.readlink(target_file), source_file) except OSError: self.fail("extractall failed with symlinked files") finally: