Serhiy Storchaka added the comment:
Patches updated to resolve merge conflict with issue11981.
Please review and apply any of this patches. This is needed for some
other my zipfile patches.
----------
Added file: http://bugs.python.org/file28145/zipfile_zip64_always_2.patch
Added file: http://bugs.python.org/file28146/zipfile_zip64_try_2.patch
_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue9720>
_______________________________________
diff -r 6f3d3003acf3 Lib/zipfile.py
--- a/Lib/zipfile.py Wed Nov 28 12:34:27 2012 +0200
+++ b/Lib/zipfile.py Wed Nov 28 14:15:29 2012 +0200
@@ -346,7 +346,7 @@
# compress_size Size of the compressed file
# file_size Size of the uncompressed file
- def FileHeader(self):
+ def FileHeader(self, zip64=None):
"""Return the per-file header as a string."""
dt = self.date_time
dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2]
@@ -362,12 +362,17 @@
extra = self.extra
min_version = 0
- if file_size > ZIP64_LIMIT or compress_size > ZIP64_LIMIT:
- # File is larger than what fits into a 4 byte integer,
- # fall back to the ZIP64 extension
+ if zip64 is None:
+ zip64 = file_size > ZIP64_LIMIT or compress_size > ZIP64_LIMIT
+ if zip64:
fmt = '<HHQQ'
extra = extra + struct.pack(fmt,
1, struct.calcsize(fmt)-4, file_size, compress_size)
+ if file_size > ZIP64_LIMIT or compress_size > ZIP64_LIMIT:
+ if not zip64:
+ raise LargeZipFile("Filesize would require ZIP64 extensions")
+ # File is larger than what fits into a 4 byte integer,
+ # fall back to the ZIP64 extension
file_size = 0xffffffff
compress_size = 0xffffffff
min_version = ZIP64_VERSION
@@ -1301,7 +1306,7 @@
zinfo.CRC = 0
self.filelist.append(zinfo)
self.NameToInfo[zinfo.filename] = zinfo
- self.fp.write(zinfo.FileHeader())
+ self.fp.write(zinfo.FileHeader(False))
return
cmpr = _get_compressor(zinfo.compress_type)
@@ -1309,8 +1314,9 @@
# Must overwrite CRC and sizes with correct data later
zinfo.CRC = CRC = 0
zinfo.compress_size = compress_size = 0
- zinfo.file_size = file_size = 0
- self.fp.write(zinfo.FileHeader())
+ # Compressed size can be larger than uncompressed size
+ self.fp.write(zinfo.FileHeader(self._allowZip64))
+ file_size = 0
while 1:
buf = fp.read(1024 * 8)
if not buf:
@@ -1330,11 +1336,11 @@
zinfo.compress_size = file_size
zinfo.CRC = CRC
zinfo.file_size = file_size
- # Seek backwards and write CRC and file sizes
+ # Seek backwards and write file header (which will now include
+ # correct CRC and file sizes)
position = self.fp.tell() # Preserve current position in file
- self.fp.seek(zinfo.header_offset + 14, 0)
- self.fp.write(struct.pack("<LLL", zinfo.CRC, zinfo.compress_size,
- zinfo.file_size))
+ self.fp.seek(zinfo.header_offset, 0)
+ self.fp.write(zinfo.FileHeader(self._allowZip64))
self.fp.seek(position, 0)
self.filelist.append(zinfo)
self.NameToInfo[zinfo.filename] = zinfo
@@ -1376,13 +1382,18 @@
zinfo.compress_size = len(data) # Compressed size
else:
zinfo.compress_size = zinfo.file_size
- self.fp.write(zinfo.FileHeader())
+ zip64 = zinfo.file_size > ZIP64_LIMIT or \
+ zinfo.compress_size > ZIP64_LIMIT
+ if zip64 and not self._allowZip64:
+ raise LargeZipFile("Filesize would require ZIP64 extensions")
+ self.fp.write(zinfo.FileHeader(zip64))
self.fp.write(data)
- self.fp.flush()
if zinfo.flag_bits & 0x08:
# Write CRC and file sizes after the file data
- self.fp.write(struct.pack("<LLL", zinfo.CRC, zinfo.compress_size,
+ fmt = '<LQQ' if zip64 else '<LLL'
+ self.fp.write(struct.pack(fmt, zinfo.CRC, zinfo.compress_size,
zinfo.file_size))
+ self.fp.flush()
self.filelist.append(zinfo)
self.NameToInfo[zinfo.filename] = zinfo
diff -r 6f3d3003acf3 Lib/zipfile.py
--- a/Lib/zipfile.py Wed Nov 28 12:34:27 2012 +0200
+++ b/Lib/zipfile.py Wed Nov 28 14:15:50 2012 +0200
@@ -346,7 +346,7 @@
# compress_size Size of the compressed file
# file_size Size of the uncompressed file
- def FileHeader(self):
+ def FileHeader(self, zip64=None):
"""Return the per-file header as a string."""
dt = self.date_time
dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2]
@@ -362,12 +362,17 @@
extra = self.extra
min_version = 0
- if file_size > ZIP64_LIMIT or compress_size > ZIP64_LIMIT:
- # File is larger than what fits into a 4 byte integer,
- # fall back to the ZIP64 extension
+ if zip64 is None:
+ zip64 = file_size > ZIP64_LIMIT or compress_size > ZIP64_LIMIT
+ if zip64:
fmt = '<HHQQ'
extra = extra + struct.pack(fmt,
1, struct.calcsize(fmt)-4, file_size, compress_size)
+ if file_size > ZIP64_LIMIT or compress_size > ZIP64_LIMIT:
+ if not zip64:
+ raise LargeZipFile("Filesize would require ZIP64 extensions")
+ # File is larger than what fits into a 4 byte integer,
+ # fall back to the ZIP64 extension
file_size = 0xffffffff
compress_size = 0xffffffff
min_version = ZIP64_VERSION
@@ -1301,7 +1306,7 @@
zinfo.CRC = 0
self.filelist.append(zinfo)
self.NameToInfo[zinfo.filename] = zinfo
- self.fp.write(zinfo.FileHeader())
+ self.fp.write(zinfo.FileHeader(False))
return
cmpr = _get_compressor(zinfo.compress_type)
@@ -1309,8 +1314,11 @@
# Must overwrite CRC and sizes with correct data later
zinfo.CRC = CRC = 0
zinfo.compress_size = compress_size = 0
- zinfo.file_size = file_size = 0
- self.fp.write(zinfo.FileHeader())
+ # Compressed size can be larger than uncompressed size
+ zip64 = self._allowZip64 and \
+ zinfo.file_size * 1.05 > ZIP64_LIMIT
+ self.fp.write(zinfo.FileHeader(zip64))
+ file_size = 0
while 1:
buf = fp.read(1024 * 8)
if not buf:
@@ -1330,11 +1338,16 @@
zinfo.compress_size = file_size
zinfo.CRC = CRC
zinfo.file_size = file_size
- # Seek backwards and write CRC and file sizes
+ if not zip64 and self._allowZip64:
+ if file_size > ZIP64_LIMIT:
+ raise RuntimeError('File size has increased during
compressing')
+ if compress_size > ZIP64_LIMIT:
+ raise RuntimeError('Compressed size larger than uncompressed
size')
+ # Seek backwards and write file header (which will now include
+ # correct CRC and file sizes)
position = self.fp.tell() # Preserve current position in file
- self.fp.seek(zinfo.header_offset + 14, 0)
- self.fp.write(struct.pack("<LLL", zinfo.CRC, zinfo.compress_size,
- zinfo.file_size))
+ self.fp.seek(zinfo.header_offset, 0)
+ self.fp.write(zinfo.FileHeader(zip64))
self.fp.seek(position, 0)
self.filelist.append(zinfo)
self.NameToInfo[zinfo.filename] = zinfo
@@ -1376,13 +1389,18 @@
zinfo.compress_size = len(data) # Compressed size
else:
zinfo.compress_size = zinfo.file_size
- self.fp.write(zinfo.FileHeader())
+ zip64 = zinfo.file_size > ZIP64_LIMIT or \
+ zinfo.compress_size > ZIP64_LIMIT
+ if zip64 and not self._allowZip64:
+ raise LargeZipFile("Filesize would require ZIP64 extensions")
+ self.fp.write(zinfo.FileHeader(zip64))
self.fp.write(data)
- self.fp.flush()
if zinfo.flag_bits & 0x08:
# Write CRC and file sizes after the file data
- self.fp.write(struct.pack("<LLL", zinfo.CRC, zinfo.compress_size,
+ fmt = '<LQQ' if zip64 else '<LLL'
+ self.fp.write(struct.pack(fmt, zinfo.CRC, zinfo.compress_size,
zinfo.file_size))
+ self.fp.flush()
self.filelist.append(zinfo)
self.NameToInfo[zinfo.filename] = zinfo
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com