Commit 19e4deb4 authored by Lars Gustäbel's avatar Lars Gustäbel

Backport the nts() function from the trunk. This fixes problems with

the xstar format that puts extra fields inside the space that POSIX
has reserved for the prefix field.
parent cea7224a
...@@ -139,13 +139,22 @@ def stn(s, length): ...@@ -139,13 +139,22 @@ def stn(s, length):
""" """
return s[:length] + (length - len(s)) * NUL 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): def nti(s):
"""Convert a number field to a python number. """Convert a number field to a python number.
""" """
# There are two possible encodings for a number field, see # There are two possible encodings for a number field, see
# itn() below. # itn() below.
if s[0] != chr(0200): if s[0] != chr(0200):
n = int(s.rstrip(NUL + " ") or "0", 8) n = int(nts(s) or "0", 8)
else: else:
n = 0L n = 0L
for i in xrange(len(s) - 1): for i in xrange(len(s) - 1):
...@@ -872,7 +881,7 @@ class TarInfo(object): ...@@ -872,7 +881,7 @@ class TarInfo(object):
tarinfo = cls() tarinfo = cls()
tarinfo.buf = buf tarinfo.buf = buf
tarinfo.name = buf[0:100].rstrip(NUL) tarinfo.name = nts(buf[0:100])
tarinfo.mode = nti(buf[100:108]) tarinfo.mode = nti(buf[100:108])
tarinfo.uid = nti(buf[108:116]) tarinfo.uid = nti(buf[108:116])
tarinfo.gid = nti(buf[116:124]) tarinfo.gid = nti(buf[116:124])
...@@ -880,12 +889,12 @@ class TarInfo(object): ...@@ -880,12 +889,12 @@ class TarInfo(object):
tarinfo.mtime = nti(buf[136:148]) tarinfo.mtime = nti(buf[136:148])
tarinfo.chksum = nti(buf[148:156]) tarinfo.chksum = nti(buf[148:156])
tarinfo.type = buf[156:157] tarinfo.type = buf[156:157]
tarinfo.linkname = buf[157:257].rstrip(NUL) tarinfo.linkname = nts(buf[157:257])
tarinfo.uname = buf[265:297].rstrip(NUL) tarinfo.uname = nts(buf[265:297])
tarinfo.gname = buf[297:329].rstrip(NUL) tarinfo.gname = nts(buf[297:329])
tarinfo.devmajor = nti(buf[329:337]) tarinfo.devmajor = nti(buf[329:337])
tarinfo.devminor = nti(buf[337:345]) tarinfo.devminor = nti(buf[337:345])
prefix = buf[345:500].rstrip(NUL) prefix = nts(buf[345:500])
if prefix and not tarinfo.issparse(): if prefix and not tarinfo.issparse():
tarinfo.name = prefix + "/" + tarinfo.name tarinfo.name = prefix + "/" + tarinfo.name
...@@ -1892,9 +1901,9 @@ class TarFile(object): ...@@ -1892,9 +1901,9 @@ class TarFile(object):
# the longname information. # the longname information.
next.offset = tarinfo.offset next.offset = tarinfo.offset
if tarinfo.type == GNUTYPE_LONGNAME: if tarinfo.type == GNUTYPE_LONGNAME:
next.name = buf.rstrip(NUL) next.name = nts(buf)
elif tarinfo.type == GNUTYPE_LONGLINK: elif tarinfo.type == GNUTYPE_LONGLINK:
next.linkname = buf.rstrip(NUL) next.linkname = nts(buf)
return next return next
......
...@@ -26,7 +26,7 @@ def path(path): ...@@ -26,7 +26,7 @@ def path(path):
testtar = path("testtar.tar") testtar = path("testtar.tar")
tempdir = os.path.join(tempfile.gettempdir(), "testtar" + os.extsep + "dir") tempdir = os.path.join(tempfile.gettempdir(), "testtar" + os.extsep + "dir")
tempname = test_support.TESTFN tempname = test_support.TESTFN
membercount = 12 membercount = 13
def tarname(comp=""): def tarname(comp=""):
if not comp: if not comp:
...@@ -225,6 +225,12 @@ class ReadTest(BaseTest): ...@@ -225,6 +225,12 @@ class ReadTest(BaseTest):
self.assertEqual(tarinfo.mtime, os.path.getmtime(path)) self.assertEqual(tarinfo.mtime, os.path.getmtime(path))
tar.close() 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): class ReadStreamTest(ReadTest):
sep = "|" sep = "|"
......
This diff was suppressed by a .gitattributes entry.
...@@ -83,6 +83,8 @@ Core and builtins ...@@ -83,6 +83,8 @@ Core and builtins
Library Library
------- -------
- tarfile.py: Fix reading of xstar archives.
- #2021: Allow tempfile.NamedTemporaryFile to be used in with statements - #2021: Allow tempfile.NamedTemporaryFile to be used in with statements
by correctly supporting the context management protocol. by correctly supporting the context management protocol.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment