bpo-36434: Properly handle writing errors in ZIP files. (GH-12559) (G… · python/cpython@4724ba9
@@ -1101,47 +1101,50 @@ def write(self, data):
11011101def close(self):
11021102if self.closed:
11031103return
1104-super().close()
1105-# Flush any data from the compressor, and update header info
1106-if self._compressor:
1107-buf = self._compressor.flush()
1108-self._compress_size += len(buf)
1109-self._fileobj.write(buf)
1110-self._zinfo.compress_size = self._compress_size
1111-else:
1112-self._zinfo.compress_size = self._file_size
1113-self._zinfo.CRC = self._crc
1114-self._zinfo.file_size = self._file_size
1115-1116-# Write updated header info
1117-if self._zinfo.flag_bits & 0x08:
1118-# Write CRC and file sizes after the file data
1119-fmt = '<LLQQ' if self._zip64 else '<LLLL'
1120-self._fileobj.write(struct.pack(fmt, _DD_SIGNATURE, self._zinfo.CRC,
1121-self._zinfo.compress_size, self._zinfo.file_size))
1122-self._zipfile.start_dir = self._fileobj.tell()
1123-else:
1124-if not self._zip64:
1125-if self._file_size > ZIP64_LIMIT:
1126-raise RuntimeError('File size unexpectedly exceeded ZIP64 '
1127-'limit')
1128-if self._compress_size > ZIP64_LIMIT:
1129-raise RuntimeError('Compressed size unexpectedly exceeded '
1130-'ZIP64 limit')
1131-# Seek backwards and write file header (which will now include
1132-# correct CRC and file sizes)
1133-1134-# Preserve current position in file
1135-self._zipfile.start_dir = self._fileobj.tell()
1136-self._fileobj.seek(self._zinfo.header_offset)
1137-self._fileobj.write(self._zinfo.FileHeader(self._zip64))
1138-self._fileobj.seek(self._zipfile.start_dir)
1139-1140-self._zipfile._writing = False
1141-1142-# Successfully written: Add file to our caches
1143-self._zipfile.filelist.append(self._zinfo)
1144-self._zipfile.NameToInfo[self._zinfo.filename] = self._zinfo
1104+try:
1105+super().close()
1106+# Flush any data from the compressor, and update header info
1107+if self._compressor:
1108+buf = self._compressor.flush()
1109+self._compress_size += len(buf)
1110+self._fileobj.write(buf)
1111+self._zinfo.compress_size = self._compress_size
1112+else:
1113+self._zinfo.compress_size = self._file_size
1114+self._zinfo.CRC = self._crc
1115+self._zinfo.file_size = self._file_size
1116+1117+# Write updated header info
1118+if self._zinfo.flag_bits & 0x08:
1119+# Write CRC and file sizes after the file data
1120+fmt = '<LLQQ' if self._zip64 else '<LLLL'
1121+self._fileobj.write(struct.pack(fmt, _DD_SIGNATURE, self._zinfo.CRC,
1122+self._zinfo.compress_size, self._zinfo.file_size))
1123+self._zipfile.start_dir = self._fileobj.tell()
1124+else:
1125+if not self._zip64:
1126+if self._file_size > ZIP64_LIMIT:
1127+raise RuntimeError(
1128+'File size unexpectedly exceeded ZIP64 limit')
1129+if self._compress_size > ZIP64_LIMIT:
1130+raise RuntimeError(
1131+'Compressed size unexpectedly exceeded ZIP64 limit')
1132+# Seek backwards and write file header (which will now include
1133+# correct CRC and file sizes)
1134+1135+# Preserve current position in file
1136+self._zipfile.start_dir = self._fileobj.tell()
1137+self._fileobj.seek(self._zinfo.header_offset)
1138+self._fileobj.write(self._zinfo.FileHeader(self._zip64))
1139+self._fileobj.seek(self._zipfile.start_dir)
1140+1141+# Successfully written: Add file to our caches
1142+self._zipfile.filelist.append(self._zinfo)
1143+self._zipfile.NameToInfo[self._zinfo.filename] = self._zinfo
1144+finally:
1145+self._zipfile._writing = False
1146+1147+1145114811461149class ZipFile:
11471150""" Class with methods to open, read, write, close, list zip files.