Atomically replace a scan-local regular file with ``payload``.
(scan_dir: Path, relative_path: str, payload: bytes)
| 533 | |
| 534 | |
| 535 | def atomic_write(scan_dir: Path, relative_path: str, payload: bytes) -> None: |
| 536 | """Atomically replace a scan-local regular file with ``payload``.""" |
| 537 | |
| 538 | with _locked_parent(scan_dir, relative_path, create=True) as (parent_path, leaf_name): |
| 539 | destination_path = parent_path / leaf_name |
| 540 | _validate_existing_output(destination_path) |
| 541 | |
| 542 | temp_handle: _OwnedHandle | None = None |
| 543 | temp_path: Path | None = None |
| 544 | for _ in range(16): |
| 545 | temp_path = parent_path / f".{leaf_name}.{secrets.token_hex(8)}.tmp" |
| 546 | try: |
| 547 | temp_handle = _create_file( |
| 548 | temp_path, |
| 549 | access=_GENERIC_WRITE | _DELETE | _FILE_READ_ATTRIBUTES, |
| 550 | share=0, |
| 551 | disposition=_CREATE_NEW, |
| 552 | flags=_FILE_ATTRIBUTE_NORMAL, |
| 553 | ) |
| 554 | except WindowsScanLocalFileError as exc: |
| 555 | if exc.errno in _COLLISION_ERRORS: |
| 556 | continue |
| 557 | raise |
| 558 | break |
| 559 | if temp_handle is None or temp_path is None: |
| 560 | raise WindowsScanLocalFileError(errno.EEXIST, "could not allocate a unique temp file") |
| 561 | |
| 562 | with temp_handle: |
| 563 | assert temp_handle.value is not None |
| 564 | try: |
| 565 | _verify_regular_file(temp_handle.value, temp_path) |
| 566 | _write_all(temp_handle.value, payload) |
| 567 | _rename_handle(temp_handle.value, destination_path) |
| 568 | _verify_regular_file(temp_handle.value, destination_path) |
| 569 | except BaseException: |
| 570 | # Deleting by handle removes the exact temp/output file and cannot |
| 571 | # be redirected through a swapped path or reparse point. |
| 572 | try: |
| 573 | _mark_handle_for_deletion(temp_handle.value) |
| 574 | except OSError: |
| 575 | pass |
| 576 | raise |
| 577 | |
| 578 | |
| 579 | def unlink_if_exists(scan_dir: Path, relative_path: str) -> None: |
nothing calls this directly
no test coverage detected