(archive)
| 399 | # Directories can be recognized by the trailing path_sep in the name, |
| 400 | # data_size and file_offset are 0. |
| 401 | def _read_directory(archive): |
| 402 | try: |
| 403 | fp = _io.open_code(archive) |
| 404 | except OSError: |
| 405 | raise ZipImportError(f"can't open Zip file: {archive!r}", path=archive) |
| 406 | |
| 407 | with fp: |
| 408 | # GH-87235: On macOS all file descriptors for /dev/fd/N share the same |
| 409 | # file offset, reset the file offset after scanning the zipfile diretory |
| 410 | # to not cause problems when some runs 'python3 /dev/fd/9 9<some_script' |
| 411 | start_offset = fp.tell() |
| 412 | try: |
| 413 | try: |
| 414 | fp.seek(-END_CENTRAL_DIR_SIZE, 2) |
| 415 | header_position = fp.tell() |
| 416 | buffer = fp.read(END_CENTRAL_DIR_SIZE) |
| 417 | except OSError: |
| 418 | raise ZipImportError(f"can't read Zip file: {archive!r}", path=archive) |
| 419 | if len(buffer) != END_CENTRAL_DIR_SIZE: |
| 420 | raise ZipImportError(f"can't read Zip file: {archive!r}", path=archive) |
| 421 | if buffer[:4] != STRING_END_ARCHIVE: |
| 422 | # Bad: End of Central Dir signature |
| 423 | # Check if there's a comment. |
| 424 | try: |
| 425 | fp.seek(0, 2) |
| 426 | file_size = fp.tell() |
| 427 | except OSError: |
| 428 | raise ZipImportError(f"can't read Zip file: {archive!r}", |
| 429 | path=archive) |
| 430 | max_comment_start = max(file_size - MAX_COMMENT_LEN - |
| 431 | END_CENTRAL_DIR_SIZE, 0) |
| 432 | try: |
| 433 | fp.seek(max_comment_start) |
| 434 | data = fp.read() |
| 435 | except OSError: |
| 436 | raise ZipImportError(f"can't read Zip file: {archive!r}", |
| 437 | path=archive) |
| 438 | pos = data.rfind(STRING_END_ARCHIVE) |
| 439 | if pos < 0: |
| 440 | raise ZipImportError(f'not a Zip file: {archive!r}', |
| 441 | path=archive) |
| 442 | buffer = data[pos:pos+END_CENTRAL_DIR_SIZE] |
| 443 | if len(buffer) != END_CENTRAL_DIR_SIZE: |
| 444 | raise ZipImportError(f"corrupt Zip file: {archive!r}", |
| 445 | path=archive) |
| 446 | header_position = file_size - len(data) + pos |
| 447 | |
| 448 | header_size = _unpack_uint32(buffer[12:16]) |
| 449 | header_offset = _unpack_uint32(buffer[16:20]) |
| 450 | if header_position < header_size: |
| 451 | raise ZipImportError(f'bad central directory size: {archive!r}', path=archive) |
| 452 | if header_position < header_offset: |
| 453 | raise ZipImportError(f'bad central directory offset: {archive!r}', path=archive) |
| 454 | header_position -= header_size |
| 455 | arc_offset = header_position - header_offset |
| 456 | if arc_offset < 0: |
| 457 | raise ZipImportError(f'bad central directory size or offset: {archive!r}', path=archive) |
| 458 |
no test coverage detected