finally:
shutil.rmtree(tempdir)
+ # Guarantee that stored pathnames are not modified. Don't
+ # remove ./ or ../ or double slashes. Still make absolute
+ # pathnames relative.
+ # For details see bug #6054.
+ def _test_pathname(self, path, cmp_path=None, dir=False):
+ # Create a tarfile with an empty member named path
+ # and compare the stored name with the original.
+ foo = os.path.join(TEMPDIR, "foo")
+ if not dir:
+ open(foo, "w").close()
+ else:
+ os.mkdir(foo)
+
+ tar = tarfile.open(tmpname, self.mode)
+ try:
+ tar.add(foo, arcname=path)
+ finally:
+ tar.close()
+
+ tar = tarfile.open(tmpname, "r")
+ try:
+ t = tar.next()
+ finally:
+ tar.close()
+
+ if not dir:
+ os.remove(foo)
+ else:
+ os.rmdir(foo)
+
+ self.assertEqual(t.name, cmp_path or path.replace(os.sep, "/"))
+
+ def test_extractall_symlinks(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.symlink(source_file, target_file)
+ tar = tarfile.open(temparchive,'w')
+ tar.add(source_file)
+ tar.add(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 symlinked files")
+ finally:
+ tar.close()
+ finally:
+ os.unlink(temparchive)
+ shutil.rmtree(tempdir)
+
+ def test_pathnames(self):
+ self._test_pathname("foo")
+ self._test_pathname(os.path.join("foo", ".", "bar"))
+ self._test_pathname(os.path.join("foo", "..", "bar"))
+ self._test_pathname(os.path.join(".", "foo"))
+ self._test_pathname(os.path.join(".", "foo", "."))
+ self._test_pathname(os.path.join(".", "foo", ".", "bar"))
+ self._test_pathname(os.path.join(".", "foo", "..", "bar"))
+ self._test_pathname(os.path.join(".", "foo", "..", "bar"))
+ self._test_pathname(os.path.join("..", "foo"))
+ self._test_pathname(os.path.join("..", "foo", ".."))
+ self._test_pathname(os.path.join("..", "foo", ".", "bar"))
+ self._test_pathname(os.path.join("..", "foo", "..", "bar"))
+
+ self._test_pathname("foo" + os.sep + os.sep + "bar")
+ self._test_pathname("foo" + os.sep + os.sep, "foo", dir=True)
+
+ def test_abs_pathnames(self):
+ if sys.platform == "win32":
+ self._test_pathname("C:\\foo", "foo")
+ else:
+ self._test_pathname("/foo", "foo")
+ self._test_pathname("///foo", "foo")
+
+ def test_cwd(self):
+ # Test adding the current working directory.
+ cwd = os.getcwd()
+ os.chdir(TEMPDIR)
+ try:
+ tar = tarfile.open(tmpname, self.mode)
+ try:
+ tar.add(".")
+ finally:
+ tar.close()
+
+ tar = tarfile.open(tmpname, "r")
+ try:
+ for t in tar:
+ self.assertTrue(t.name == "." or t.name.startswith("./"))
+ finally:
+ tar.close()
+ finally:
+ os.chdir(cwd)
+
+
class StreamWriteTest(WriteTestBase):
mode = "w|"