SF #846659, fix bufsize violation and GNU longname/longlink extensions
This commit is contained in:
parent
13e50fe453
commit
0662f8a5ea
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue