]> granicus.if.org Git - python/commitdiff
SF #846659, fix bufsize violation and GNU longname/longlink extensions
authorNeal Norwitz <nnorwitz@gmail.com>
Tue, 20 Jul 2004 21:54:18 +0000 (21:54 +0000)
committerNeal Norwitz <nnorwitz@gmail.com>
Tue, 20 Jul 2004 21:54:18 +0000 (21:54 +0000)
Lib/tarfile.py
Lib/test/test_tarfile.py
Misc/NEWS

index 41257f1eb9993a687e31c4bd1804b2a3972a7a99..d20107ecd28c249a35994eef3555877957a9dfdc 100644 (file)
@@ -353,7 +353,6 @@ class _Stream:
         if self.mode == "w" and self.buf:
             if self.type != "tar":
                 self.buf += self.cmp.flush()
-            self.__write("")            # Write remaining blocks to output
             self.fileobj.write(self.buf)
             self.buf = ""
             if self.type == "gz":
@@ -1775,6 +1774,8 @@ class TarFile(object):
            of the longname as size, followed by data blocks,
            which contain the longname as a null terminated string.
         """
+        name += NUL
+
         tarinfo = TarInfo()
         tarinfo.name = "././@LongLink"
         tarinfo.type = type
@@ -1783,6 +1784,7 @@ class TarFile(object):
 
         # write extended header
         self.fileobj.write(tarinfo.tobuf())
+        self.offset += BLOCKSIZE
         # write name blocks
         self.fileobj.write(name)
         blocks, remainder = divmod(tarinfo.size, BLOCKSIZE)
index 9d40ace8c3b301eeedd4135134fb4c79bdc8615f..bd3fd8e5359fcecf5ed9280b2e45bdc9329b64fc 100644 (file)
@@ -205,6 +205,94 @@ class WriteTest(BaseTest):
 class WriteStreamTest(WriteTest):
     sep = '|'
 
+class WriteGNULongTest(unittest.TestCase):
+    """This testcase checks for correct creation of GNU Longname
+       and Longlink extensions.
+
+       It creates a tarfile and adds empty members with either
+       long names, long linknames or both and compares the size
+       of the tarfile with the expected size.
+
+       It checks for SF bug #812325 in TarFile._create_gnulong().
+
+       While I was writing this testcase, I noticed a second bug
+       in the same method:
+       Long{names,links} weren't null-terminated which lead to
+       bad tarfiles when their length was a multiple of 512. This
+       is tested as well.
+    """
+
+    def setUp(self):
+        self.tar = tarfile.open(tmpname(), "w")
+        self.tar.posix = False
+
+    def tearDown(self):
+        self.tar.close()
+
+    def _length(self, s):
+        blocks, remainder = divmod(len(s) + 1, 512)
+        if remainder:
+            blocks += 1
+        return blocks * 512
+
+    def _calc_size(self, name, link=None):
+        # initial tar header
+        count = 512
+
+        if len(name) > tarfile.LENGTH_NAME:
+            # gnu longname extended header + longname
+            count += 512
+            count += self._length(name)
+
+        if link is not None and len(link) > tarfile.LENGTH_LINK:
+            # gnu longlink extended header + longlink
+            count += 512
+            count += self._length(link)
+
+        return count
+
+    def _test(self, name, link=None):
+        tarinfo = tarfile.TarInfo(name)
+        if link:
+            tarinfo.linkname = link
+            tarinfo.type = tarfile.LNKTYPE
+
+        self.tar.addfile(tarinfo)
+
+        v1 = self._calc_size(name, link)
+        v2 = self.tar.offset
+        self.assertEqual(v1, v2, "GNU longname/longlink creation failed")
+
+    def test_longname_1023(self):
+        self._test(("longnam/" * 127) + "longnam")
+
+    def test_longname_1024(self):
+        self._test(("longnam/" * 127) + "longname")
+
+    def test_longname_1025(self):
+        self._test(("longnam/" * 127) + "longname_")
+
+    def test_longlink_1023(self):
+        self._test("name", ("longlnk/" * 127) + "longlnk")
+
+    def test_longlink_1024(self):
+        self._test("name", ("longlnk/" * 127) + "longlink")
+
+    def test_longlink_1025(self):
+        self._test("name", ("longlnk/" * 127) + "longlink_")
+
+    def test_longnamelink_1023(self):
+        self._test(("longnam/" * 127) + "longnam",
+                   ("longlnk/" * 127) + "longlnk")
+
+    def test_longnamelink_1024(self):
+        self._test(("longnam/" * 127) + "longname",
+                   ("longlnk/" * 127) + "longlink")
+
+    def test_longnamelink_1025(self):
+        self._test(("longnam/" * 127) + "longname_",
+                   ("longlnk/" * 127) + "longlink_")
+
 # Gzip TestCases
 class ReadTestGzip(ReadTest):
     comp = "gz"
@@ -245,7 +333,8 @@ def test_main():
         ReadTest,
         ReadStreamTest,
         WriteTest,
-        WriteStreamTest
+        WriteStreamTest,
+        WriteGNULongTest,
     ]
 
     if gzip:
index c3955762af2266890ed282a948a2697227ae2e65..fd6d24456eab30877c2605b6c9900239a09a7a09 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -39,6 +39,9 @@ Extension modules
 Library
 -------
 
+- Patch #846659.  Fix an error in tarfile.py when using
+  GNU longname/longlink creation. 
+
 - The obsolete FCNTL.py has been deleted.  The builtin fcntl module
   has been available (on platforms that support fcntl) since Python
   1.5a3, and all FCNTL.py did is export fcntl's names, after generating