diff options
author | Senthil Kumaran <senthil@uthcode.com> | 2011-05-17 10:12:18 +0800 |
---|---|---|
committer | Senthil Kumaran <senthil@uthcode.com> | 2011-05-17 10:12:18 +0800 |
commit | aa749990f44691d71834e2929ab6e17568947642 (patch) | |
tree | 9416ee560cdc3d50f1bbba15fcae76fdba8d863c | |
parent | cebe95af0c56d8ee53702947c4a131e2e486c14f (diff) | |
download | cpython-aa749990f44691d71834e2929ab6e17568947642.tar.gz |
Fix closes issue #12088 - fixes the tarfile.extractall issue when the
symlinks/hardlink was broken. It handles now in a graceful manner (No exception
is raised, behavior similar GNU tar).
-rw-r--r-- | Lib/tarfile.py | 4 | ||||
-rw-r--r-- | Lib/test/test_tarfile.py | 60 |
2 files changed, 63 insertions, 1 deletions
diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 105a75880d..6b9303e898 100644 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -2239,12 +2239,14 @@ class TarFile(object): if hasattr(os, "symlink") and hasattr(os, "link"): # For systems that support symbolic and hard links. if tarinfo.issym(): - if os.path.exists(targetpath): + if os.path.lexists(targetpath): os.unlink(targetpath) os.symlink(tarinfo.linkname, targetpath) else: # See extract(). if os.path.exists(tarinfo._link_target): + if os.path.lexists(targetpath): + os.unlink(targetpath) os.link(tarinfo._link_target, targetpath) else: self._extract_member(self._find_link_target(tarinfo), targetpath) diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index f78f9ce03f..6962f8e2d7 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -872,6 +872,66 @@ class WriteTest(WriteTestBase): os.unlink(temparchive) shutil.rmtree(tempdir) + @unittest.skipUnless(hasattr(os, 'symlink'), "needs os.symlink") + def test_extractall_broken_symlinks(self): + # Test if extractall works properly when tarfile contains broken + # symlinks + tempdir = os.path.join(TEMPDIR, "testsymlinks") + temparchive = os.path.join(TEMPDIR, "testsymlinks.tar") + os.mkdir(tempdir) + try: + source_file = os.path.join(tempdir,'source') + target_file = os.path.join(tempdir,'symlink') + with open(source_file,'w') as f: + f.write('something\n') + os.symlink(source_file, target_file) + tar = tarfile.open(temparchive,'w') + tar.add(target_file, arcname=os.path.basename(target_file)) + tar.close() + # remove the real file + os.unlink(source_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 + try: + tar.extractall(path=tempdir) + except OSError: + self.fail("extractall failed with broken symlinked files") + finally: + tar.close() + finally: + os.unlink(temparchive) + shutil.rmtree(tempdir) + + @unittest.skipUnless(hasattr(os, 'link'), "needs os.link") + def test_extractall_hardlinks(self): + # Test if extractall works properly when tarfile contains symlinks + tempdir = os.path.join(TEMPDIR, "testsymlinks") + temparchive = os.path.join(TEMPDIR, "testsymlinks.tar") + os.mkdir(tempdir) + try: + source_file = os.path.join(tempdir,'source') + target_file = os.path.join(tempdir,'symlink') + with open(source_file,'w') as f: + f.write('something\n') + os.link(source_file, target_file) + tar = tarfile.open(temparchive,'w') + tar.add(source_file, arcname=os.path.basename(source_file)) + tar.add(target_file, arcname=os.path.basename(target_file)) + tar.close() + # 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 + try: + tar.extractall(path=tempdir) + except OSError: + self.fail("extractall failed with linked files") + finally: + tar.close() + finally: + os.unlink(temparchive) + shutil.rmtree(tempdir) + class StreamWriteTest(WriteTestBase): mode = "w|" |