]> granicus.if.org Git - python/commitdiff
Backport the nts() function from the trunk. This fixes problems with
authorLars Gustäbel <lars@gustaebel.de>
Mon, 11 Feb 2008 18:36:07 +0000 (18:36 +0000)
committerLars Gustäbel <lars@gustaebel.de>
Mon, 11 Feb 2008 18:36:07 +0000 (18:36 +0000)
the xstar format that puts extra fields inside the space that POSIX
has reserved for the prefix field.

Lib/tarfile.py
Lib/test/test_tarfile.py
Lib/test/testtar.tar
Misc/NEWS

index 94fdcb02768493621db98ec7325ac24cc4753ec6..5ad096dbf36beb559b2383f2cf7d3547562579b2 100644 (file)
@@ -139,13 +139,22 @@ def stn(s, length):
     """
     return s[:length] + (length - len(s)) * NUL
 
+def nts(s):
+    """Convert a null-terminated string field to a python string.
+    """
+    # Use the string up to the first null char.
+    p = s.find("\0")
+    if p == -1:
+        return s
+    return s[:p]
+
 def nti(s):
     """Convert a number field to a python number.
     """
     # There are two possible encodings for a number field, see
     # itn() below.
     if s[0] != chr(0200):
-        n = int(s.rstrip(NUL + " ") or "0", 8)
+        n = int(nts(s) or "0", 8)
     else:
         n = 0L
         for i in xrange(len(s) - 1):
@@ -872,7 +881,7 @@ class TarInfo(object):
 
         tarinfo = cls()
         tarinfo.buf = buf
-        tarinfo.name = buf[0:100].rstrip(NUL)
+        tarinfo.name = nts(buf[0:100])
         tarinfo.mode = nti(buf[100:108])
         tarinfo.uid = nti(buf[108:116])
         tarinfo.gid = nti(buf[116:124])
@@ -880,12 +889,12 @@ class TarInfo(object):
         tarinfo.mtime = nti(buf[136:148])
         tarinfo.chksum = nti(buf[148:156])
         tarinfo.type = buf[156:157]
-        tarinfo.linkname = buf[157:257].rstrip(NUL)
-        tarinfo.uname = buf[265:297].rstrip(NUL)
-        tarinfo.gname = buf[297:329].rstrip(NUL)
+        tarinfo.linkname = nts(buf[157:257])
+        tarinfo.uname = nts(buf[265:297])
+        tarinfo.gname = nts(buf[297:329])
         tarinfo.devmajor = nti(buf[329:337])
         tarinfo.devminor = nti(buf[337:345])
-        prefix = buf[345:500].rstrip(NUL)
+        prefix = nts(buf[345:500])
 
         if prefix and not tarinfo.issparse():
             tarinfo.name = prefix + "/" + tarinfo.name
@@ -1892,9 +1901,9 @@ class TarFile(object):
         # the longname information.
         next.offset = tarinfo.offset
         if tarinfo.type == GNUTYPE_LONGNAME:
-            next.name = buf.rstrip(NUL)
+            next.name = nts(buf)
         elif tarinfo.type == GNUTYPE_LONGLINK:
-            next.linkname = buf.rstrip(NUL)
+            next.linkname = nts(buf)
 
         return next
 
index dc2803895d708d2c6b623e8652fc06b99ea18b6f..a9797aeb992c4ddb9c745208573334bc5fd8f279 100644 (file)
@@ -26,7 +26,7 @@ def path(path):
 testtar = path("testtar.tar")
 tempdir = os.path.join(tempfile.gettempdir(), "testtar" + os.extsep + "dir")
 tempname = test_support.TESTFN
-membercount = 12
+membercount = 13
 
 def tarname(comp=""):
     if not comp:
@@ -225,6 +225,12 @@ class ReadTest(BaseTest):
             self.assertEqual(tarinfo.mtime, os.path.getmtime(path))
         tar.close()
 
+    def test_star(self):
+        try:
+            self.tar.getmember("7-STAR")
+        except KeyError:
+            self.fail("finding 7-STAR member failed (mangled prefix?)")
+
 
 class ReadStreamTest(ReadTest):
     sep = "|"
index 1f4493f3516ca1003553c591f94027068d8a6761..6c3efa9b01a43722151d9341c06c22e0b9b2cd46 100644 (file)
Binary files a/Lib/test/testtar.tar and b/Lib/test/testtar.tar differ
index e9473dd749a426eb2f78b6d0a6b1c7cccb8fbf74..0cd7407465399b2c3c9fcd2b41899e10e8b9df2f 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -83,6 +83,8 @@ Core and builtins
 Library
 -------
 
+- tarfile.py: Fix reading of xstar archives.
+
 - #2021: Allow tempfile.NamedTemporaryFile to be used in with statements
   by correctly supporting the context management protocol.