(archive)
| 293 | # Directories can be recognized by the trailing path_sep in the name, |
| 294 | # data_size and file_offset are 0. |
| 295 | def _read_directory(archive): |
| 296 | try: |
| 297 | fp = _io.open_code(archive) |
| 298 | except OSError: |
| 299 | raise ZipImportError(f"can't open Zip file: {archive!r}", path=archive) |
| 300 | |
| 301 | with fp: |
| 302 | # GH-87235: On macOS all file descriptors for /dev/fd/N share the same |
| 303 | # file offset, reset the file offset after scanning the zipfile directory |
| 304 | # to not cause problems when some runs 'python3 /dev/fd/9 9<some_script' |
| 305 | start_offset = fp.tell() |
| 306 | try: |
| 307 | # Check if there's a comment. |
| 308 | try: |
| 309 | fp.seek(0, 2) |
| 310 | file_size = fp.tell() |
| 311 | except OSError: |
| 312 | raise ZipImportError(f"can't read Zip file: {archive!r}", |
| 313 | path=archive) |
| 314 | max_comment_plus_dirs_size = ( |
| 315 | MAX_COMMENT_LEN + END_CENTRAL_DIR_SIZE + |
| 316 | END_CENTRAL_DIR_SIZE_64 + END_CENTRAL_DIR_LOCATOR_SIZE_64) |
| 317 | max_comment_start = max(file_size - max_comment_plus_dirs_size, 0) |
| 318 | try: |
| 319 | fp.seek(max_comment_start) |
| 320 | data = fp.read(max_comment_plus_dirs_size) |
| 321 | except OSError: |
| 322 | raise ZipImportError(f"can't read Zip file: {archive!r}", |
| 323 | path=archive) |
| 324 | pos = data.rfind(STRING_END_ARCHIVE) |
| 325 | pos64 = data.rfind(STRING_END_ZIP_64) |
| 326 | |
| 327 | if (pos64 >= 0 and pos64+END_CENTRAL_DIR_SIZE_64+END_CENTRAL_DIR_LOCATOR_SIZE_64==pos): |
| 328 | # Zip64 at "correct" offset from standard EOCD |
| 329 | buffer = data[pos64:pos64 + END_CENTRAL_DIR_SIZE_64] |
| 330 | if len(buffer) != END_CENTRAL_DIR_SIZE_64: |
| 331 | raise ZipImportError( |
| 332 | f"corrupt Zip64 file: Expected {END_CENTRAL_DIR_SIZE_64} byte " |
| 333 | f"zip64 central directory, but read {len(buffer)} bytes.", |
| 334 | path=archive) |
| 335 | header_position = file_size - len(data) + pos64 |
| 336 | |
| 337 | central_directory_size = _unpack_uint64(buffer[40:48]) |
| 338 | central_directory_position = _unpack_uint64(buffer[48:56]) |
| 339 | num_entries = _unpack_uint64(buffer[24:32]) |
| 340 | elif pos >= 0: |
| 341 | buffer = data[pos:pos+END_CENTRAL_DIR_SIZE] |
| 342 | if len(buffer) != END_CENTRAL_DIR_SIZE: |
| 343 | raise ZipImportError(f"corrupt Zip file: {archive!r}", |
| 344 | path=archive) |
| 345 | |
| 346 | header_position = file_size - len(data) + pos |
| 347 | |
| 348 | # Buffer now contains a valid EOCD, and header_position gives the |
| 349 | # starting position of it. |
| 350 | central_directory_size = _unpack_uint32(buffer[12:16]) |
| 351 | central_directory_position = _unpack_uint32(buffer[16:20]) |
| 352 | num_entries = _unpack_uint16(buffer[8:10]) |
no test coverage detected
searching dependent graphs…