@openclaw/fs-safe 0.16.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +91 -0
- package/README.md +8 -1
- package/dist/absolute-path.d.ts +0 -1
- package/dist/absolute-path.js +2 -8
- package/dist/advanced.d.ts +2 -1
- package/dist/advanced.js +2 -0
- package/dist/archive-crc32.d.ts +0 -1
- package/dist/archive-deadline.d.ts +0 -1
- package/dist/archive-deadline.js +22 -23
- package/dist/archive-durability.d.ts +0 -1
- package/dist/archive-entry.d.ts +0 -1
- package/dist/archive-errors.d.ts +0 -1
- package/dist/archive-gzip-tail.d.ts +0 -1
- package/dist/archive-input.d.ts +0 -1
- package/dist/archive-kind.d.ts +0 -1
- package/dist/archive-limits.d.ts +0 -1
- package/dist/archive-merge.d.ts +3 -4
- package/dist/archive-merge.js +17 -7
- package/dist/archive-native.d.ts +3 -14
- package/dist/archive-native.js +46 -70
- package/dist/archive-options.d.ts +9 -2
- package/dist/archive-parser-errors.d.ts +0 -1
- package/dist/archive-parser.wasm +0 -0
- package/dist/archive-plan.d.ts +10 -1
- package/dist/archive-plan.js +31 -21
- package/dist/archive-policy.d.ts +0 -1
- package/dist/archive-read.d.ts +0 -1
- package/dist/archive-staging.d.ts +0 -1
- package/dist/archive-tar-inspect.d.ts +0 -1
- package/dist/archive-tar-stream.d.ts +0 -1
- package/dist/archive-tar-wasm.d.ts +0 -1
- package/dist/archive-tar.d.ts +0 -1
- package/dist/archive-zip-admission.d.ts +0 -1
- package/dist/archive-zip-count.d.ts +0 -1
- package/dist/archive-zip-count.js +21 -1
- package/dist/archive-zip-directory.d.ts +0 -1
- package/dist/archive-zip-directory.js +23 -1
- package/dist/archive-zip-entry.d.ts +0 -1
- package/dist/archive-zip-integrity.d.ts +0 -1
- package/dist/archive-zip-loader.d.ts +2 -1
- package/dist/archive-zip-loader.js +7 -0
- package/dist/archive-zip-manifest.d.ts +0 -1
- package/dist/archive-zip-names.d.ts +0 -1
- package/dist/archive-zip-names.js +7 -2
- package/dist/archive-zip-preflight.d.ts +0 -1
- package/dist/archive.d.ts +0 -1
- package/dist/archive.js +93 -164
- package/dist/async-lock.d.ts +0 -1
- package/dist/atomic.d.ts +0 -1
- package/dist/bounded-read-stream.d.ts +0 -1
- package/dist/bounded-read.d.ts +0 -1
- package/dist/byte-budget.d.ts +0 -1
- package/dist/byte-view.d.ts +2 -0
- package/dist/byte-view.js +13 -0
- package/dist/clone-metadata.d.ts +0 -1
- package/dist/config.d.ts +0 -1
- package/dist/containment.d.ts +0 -1
- package/dist/copy-file-input.d.ts +0 -1
- package/dist/copy-policy.d.ts +0 -1
- package/dist/copy-publication.d.ts +0 -1
- package/dist/copy-tree-portable.d.ts +0 -1
- package/dist/copy-tree-portable.js +9 -6
- package/dist/copy.d.ts +0 -1
- package/dist/copy.js +5 -5
- package/dist/create-directory.d.ts +0 -2
- package/dist/create-directory.js +3 -22
- package/dist/create-file-async.d.ts +0 -1
- package/dist/create-file.d.ts +0 -1
- package/dist/create-file.js +3 -14
- package/dist/create-owned-file.d.ts +0 -1
- package/dist/create.d.ts +1 -2
- package/dist/create.js +1 -1
- package/dist/creation-darwin.d.ts +0 -2
- package/dist/creation-darwin.js +0 -9
- package/dist/creation-file-state.d.ts +0 -1
- package/dist/creation-path.d.ts +2 -1
- package/dist/creation-path.js +12 -0
- package/dist/creation-permissions.d.ts +0 -1
- package/dist/creation-permissions.js +28 -38
- package/dist/deny-mutations.d.ts +2 -3
- package/dist/deny-mutations.js +55 -35
- package/dist/device-path.d.ts +0 -1
- package/dist/directory-durability.d.ts +6 -7
- package/dist/directory-entry-path.d.ts +0 -1
- package/dist/directory-guard.d.ts +2 -7
- package/dist/directory-guard.js +25 -56
- package/dist/directory-mode-node.d.ts +0 -1
- package/dist/directory-mode-owner.d.ts +0 -1
- package/dist/directory-receipt.d.ts +2 -3
- package/dist/directory-receipt.js +15 -19
- package/dist/durability.d.ts +0 -1
- package/dist/effective-uid.d.ts +0 -1
- package/dist/error-detail.d.ts +0 -1
- package/dist/errors.d.ts +0 -1
- package/dist/file-cleanup.d.ts +1 -1
- package/dist/file-cleanup.js +7 -4
- package/dist/file-contents.d.ts +5 -0
- package/dist/file-contents.js +40 -0
- package/dist/file-handle-transfer.d.ts +0 -1
- package/dist/file-hash.d.ts +0 -1
- package/dist/file-hash.js +186 -70
- package/dist/file-identity.d.ts +0 -1
- package/dist/file-lock-sync-acquisition.d.ts +22 -0
- package/dist/file-lock-sync-acquisition.js +98 -0
- package/dist/file-lock-sync-admission.d.ts +0 -2
- package/dist/file-lock-sync-admission.js +9 -48
- package/dist/file-lock-sync-root-acquire.d.ts +0 -1
- package/dist/file-lock-sync-root-acquire.js +35 -98
- package/dist/file-lock-sync-root-arbitration.d.ts +0 -1
- package/dist/file-lock-sync-root-held.d.ts +1 -3
- package/dist/file-lock-sync-root-held.js +7 -5
- package/dist/file-lock-sync-root-io.d.ts +0 -1
- package/dist/file-lock-sync-root-mutation.d.ts +4 -5
- package/dist/file-lock-sync-root-mutation.js +7 -9
- package/dist/file-lock-sync-root-options.d.ts +0 -1
- package/dist/file-lock-sync-root-registration.d.ts +0 -1
- package/dist/file-lock-sync-root.d.ts +1 -2
- package/dist/file-lock-sync-root.js +14 -87
- package/dist/file-lock-sync-stale-admission.d.ts +2 -7
- package/dist/file-lock-sync-stale-admission.js +24 -23
- package/dist/file-lock-sync.d.ts +0 -1
- package/dist/file-lock-sync.js +46 -128
- package/dist/file-lock.d.ts +0 -1
- package/dist/file-observation.d.ts +0 -1
- package/dist/file-store-boundary.d.ts +0 -2
- package/dist/file-store-boundary.js +6 -26
- package/dist/file-store-copy-source.d.ts +1 -2
- package/dist/file-store-copy-source.js +1 -1
- package/dist/file-store-limit.d.ts +1 -2
- package/dist/file-store-limit.js +2 -3
- package/dist/file-store-path.d.ts +0 -1
- package/dist/file-store-prune.d.ts +0 -1
- package/dist/file-store-sync-directory.d.ts +0 -1
- package/dist/file-store-sync-directory.js +194 -231
- package/dist/file-store-sync-write.d.ts +0 -1
- package/dist/file-store-sync-write.js +16 -26
- package/dist/file-store.d.ts +0 -1
- package/dist/file-store.js +6 -7
- package/dist/file-sync.d.ts +0 -1
- package/dist/filename.d.ts +0 -1
- package/dist/filename.js +1 -7
- package/dist/fs.d.ts +0 -1
- package/dist/guarded-mkdir.d.ts +0 -1
- package/dist/guarded-mkdir.js +6 -27
- package/dist/guarded-mutation.d.ts +0 -7
- package/dist/guarded-mutation.js +6 -11
- package/dist/guest-dispatch-python.d.ts +0 -1
- package/dist/guest-dispatch-python.js +41 -90
- package/dist/guest-native-python.d.ts +0 -1
- package/dist/guest.d.ts +0 -1
- package/dist/home-dir.d.ts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/install-path.d.ts +0 -1
- package/dist/install-path.js +2 -5
- package/dist/json-document-store.d.ts +0 -1
- package/dist/json-durable-queue-directory.d.ts +13 -1
- package/dist/json-durable-queue-directory.js +134 -0
- package/dist/json-durable-queue-ownership.d.ts +0 -1
- package/dist/json-durable-queue-ownership.js +43 -66
- package/dist/json-durable-queue-read.d.ts +0 -1
- package/dist/json-durable-queue-read.js +6 -6
- package/dist/json-durable-queue.d.ts +0 -1
- package/dist/json-durable-queue.js +17 -139
- package/dist/json-store.d.ts +0 -1
- package/dist/json-stringify.d.ts +0 -1
- package/dist/json.d.ts +0 -1
- package/dist/json.js +38 -90
- package/dist/local-file-access.d.ts +0 -1
- package/dist/local-file-access.js +3 -10
- package/dist/local-file-descriptor.d.ts +0 -1
- package/dist/local-roots.d.ts +0 -1
- package/dist/local-roots.js +19 -21
- package/dist/lock-config.d.ts +0 -1
- package/dist/move-path-cleanup.d.ts +5 -20
- package/dist/move-path-cleanup.js +57 -21
- package/dist/move-path-stage.d.ts +0 -1
- package/dist/move-path.d.ts +0 -1
- package/dist/move-path.js +62 -39
- package/dist/mutation-authority.d.ts +0 -1
- package/dist/native-binding.d.ts +0 -1
- package/dist/native-config.d.ts +0 -1
- package/dist/native-directory-observation.d.ts +0 -1
- package/dist/native-fallback-warning.d.ts +0 -1
- package/dist/native-operations.d.ts +1 -5
- package/dist/native-operations.js +2 -6
- package/dist/native-parent-admission.d.ts +0 -1
- package/dist/native-pinned-write-windows.d.ts +0 -1
- package/dist/native-pinned-write.d.ts +0 -1
- package/dist/native-pinned-write.js +4 -10
- package/dist/native-policy-directory-observation.d.ts +0 -1
- package/dist/native-policy-parent-windows.d.ts +0 -1
- package/dist/native-rename-outcome.d.ts +0 -1
- package/dist/native-staged-file.d.ts +17 -4
- package/dist/native-staged-file.js +63 -68
- package/dist/native.d.ts +0 -1
- package/dist/native.js +2 -2
- package/dist/opened-file-failure.d.ts +0 -1
- package/dist/opened-realpath.d.ts +0 -1
- package/dist/opened-realpath.js +11 -2
- package/dist/output.d.ts +0 -1
- package/dist/overwrite-file-handle.d.ts +0 -1
- package/dist/owner-dacl.d.ts +0 -1
- package/dist/path-case.d.ts +0 -1
- package/dist/path-policy.d.ts +0 -1
- package/dist/path-prefix.d.ts +0 -1
- package/dist/path-scope-lexical.d.ts +0 -1
- package/dist/path-segment-route.d.ts +0 -1
- package/dist/path-suffix-aliases.d.ts +0 -1
- package/dist/path.d.ts +0 -1
- package/dist/path.js +2 -1
- package/dist/permission-exec.d.ts +0 -1
- package/dist/permission-exec.js +19 -25
- package/dist/permissions-public.d.ts +0 -1
- package/dist/permissions-windows.d.ts +2 -10
- package/dist/permissions-windows.js +10 -30
- package/dist/permissions.d.ts +0 -1
- package/dist/permissions.js +11 -33
- package/dist/pinned-mutation-admission.d.ts +0 -1
- package/dist/pinned-mutation-observation.d.ts +0 -1
- package/dist/pinned-mutation-shared-route.d.ts +0 -1
- package/dist/pinned-open.d.ts +1 -1
- package/dist/pinned-open.js +1 -1
- package/dist/pinned-operation.d.ts +0 -1
- package/dist/pinned-write-input.d.ts +0 -1
- package/dist/pinned-write-input.js +11 -1
- package/dist/pinned-write-mode.d.ts +3 -4
- package/dist/pinned-write-mode.js +15 -8
- package/dist/pinned-write-staged.d.ts +0 -1
- package/dist/pinned-write-staged.js +10 -11
- package/dist/pinned-write-types.d.ts +9 -21
- package/dist/pinned-write.d.ts +0 -1
- package/dist/pinned-write.js +17 -13
- package/dist/positional-read.d.ts +0 -1
- package/dist/private-directory.d.ts +0 -1
- package/dist/private-producer-handoff-sync.d.ts +0 -1
- package/dist/private-producer-handoff-sync.js +9 -51
- package/dist/private-producer-handoff.d.ts +20 -1
- package/dist/private-producer-handoff.js +69 -46
- package/dist/private-temp-workspace.d.ts +0 -1
- package/dist/private-temp-workspace.js +11 -36
- package/dist/publish-copy-stage.d.ts +0 -1
- package/dist/publish-file-failure.d.ts +0 -1
- package/dist/publish-file.d.ts +2 -3
- package/dist/publish-file.js +56 -96
- package/dist/read-open-flags.d.ts +0 -1
- package/dist/read-opened-file.d.ts +0 -1
- package/dist/realpath.d.ts +0 -1
- package/dist/recursive-mkdir-path.d.ts +0 -1
- package/dist/regular-file.d.ts +0 -1
- package/dist/regular-file.js +107 -178
- package/dist/replace-directory.d.ts +0 -1
- package/dist/replace-file-copy-fallback.d.ts +0 -1
- package/dist/replace-file-copy-fallback.js +42 -29
- package/dist/replace-file-copy-source.d.ts +0 -1
- package/dist/replace-file-copy-source.js +19 -23
- package/dist/replace-file-descriptor.d.ts +0 -1
- package/dist/replace-file-descriptor.js +16 -17
- package/dist/replace-file-mode.d.ts +0 -1
- package/dist/replace-file-rename-policy.d.ts +0 -1
- package/dist/replace-file-temp-owner.d.ts +12 -13
- package/dist/replace-file-temp-owner.js +72 -91
- package/dist/replace-file.d.ts +0 -1
- package/dist/replace-file.js +9 -13
- package/dist/retained-directory-replacement.d.ts +0 -1
- package/dist/root-boundary.d.ts +0 -1
- package/dist/root-context.d.ts +0 -1
- package/dist/root-create-input.d.ts +0 -1
- package/dist/root-directory-creation.d.ts +0 -1
- package/dist/root-directory-list.d.ts +0 -1
- package/dist/root-directory-list.js +20 -3
- package/dist/root-directory.d.ts +0 -1
- package/dist/root-entries.d.ts +0 -1
- package/dist/root-errors.d.ts +0 -1
- package/dist/root-file-final-admission.d.ts +1 -2
- package/dist/root-file-final-admission.js +5 -2
- package/dist/root-file.d.ts +0 -1
- package/dist/root-file.js +3 -2
- package/dist/root-impl.d.ts +2 -10
- package/dist/root-impl.js +164 -111
- package/dist/root-move-noreplace.d.ts +2 -1
- package/dist/root-move-noreplace.js +2 -2
- package/dist/root-move-preflight.d.ts +0 -1
- package/dist/root-observed-path.d.ts +0 -1
- package/dist/root-options.d.ts +0 -1
- package/dist/root-path-errors.d.ts +0 -1
- package/dist/root-path-existing.d.ts +3 -1
- package/dist/root-path-existing.js +39 -18
- package/dist/root-path-observation.d.ts +0 -1
- package/dist/root-path-stat.d.ts +0 -1
- package/dist/root-path.d.ts +0 -1
- package/dist/root-path.js +60 -188
- package/dist/root-paths-lexical.d.ts +0 -1
- package/dist/root-paths.d.ts +0 -1
- package/dist/root-read-admission.d.ts +0 -1
- package/dist/root-read-admission.js +31 -39
- package/dist/root-remove-identity.d.ts +0 -1
- package/dist/root-remove-receipt.d.ts +0 -1
- package/dist/root-remove.d.ts +0 -1
- package/dist/root-remove.js +15 -1
- package/dist/root-symlink-policy.d.ts +0 -1
- package/dist/root-walk.d.ts +0 -1
- package/dist/root-write-admission.d.ts +0 -1
- package/dist/root-write-compatibility.d.ts +0 -1
- package/dist/root-write-complete-parent.d.ts +0 -1
- package/dist/root-write-lock-binding.d.ts +0 -1
- package/dist/root-write-mode.d.ts +0 -1
- package/dist/root-write-publication.d.ts +0 -1
- package/dist/root-write-verification.d.ts +0 -1
- package/dist/root.d.ts +0 -1
- package/dist/safe-path-segment.d.ts +1 -2
- package/dist/safe-path-segment.js +2 -5
- package/dist/secret-file.d.ts +0 -1
- package/dist/secret-file.js +7 -17
- package/dist/secret-read-async.d.ts +0 -1
- package/dist/secret-read-async.js +5 -5
- package/dist/secret-read-policy.d.ts +0 -1
- package/dist/secret.d.ts +0 -1
- package/dist/secure-file-windows.d.ts +0 -6
- package/dist/secure-file-windows.js +13 -28
- package/dist/secure-file.d.ts +0 -1
- package/dist/secure-file.js +9 -9
- package/dist/secure-temp-dir.d.ts +0 -1
- package/dist/secure-temp-repair.d.ts +0 -1
- package/dist/sibling-staged-file.d.ts +0 -1
- package/dist/sibling-staged-file.js +32 -39
- package/dist/sibling-temp.d.ts +0 -1
- package/dist/sidecar-lock-acquire.d.ts +1 -2
- package/dist/sidecar-lock-acquire.js +35 -58
- package/dist/sidecar-lock-admission-context.d.ts +0 -1
- package/dist/sidecar-lock-admission-parser.d.ts +0 -1
- package/dist/sidecar-lock-admission.d.ts +1 -5
- package/dist/sidecar-lock-admission.js +1 -7
- package/dist/sidecar-lock-handle.d.ts +3 -1
- package/dist/sidecar-lock-handle.js +6 -0
- package/dist/sidecar-lock-policy.d.ts +3 -1
- package/dist/sidecar-lock-policy.js +16 -0
- package/dist/sidecar-lock-reclaim.d.ts +1 -2
- package/dist/sidecar-lock-reclaim.js +11 -8
- package/dist/sidecar-lock-registration.d.ts +13 -0
- package/dist/sidecar-lock-registration.js +47 -0
- package/dist/sidecar-lock-root.d.ts +0 -1
- package/dist/sidecar-lock-stale-admission.d.ts +0 -1
- package/dist/sidecar-lock-target.d.ts +0 -1
- package/dist/sidecar-lock-types.d.ts +0 -1
- package/dist/sidecar-lock.d.ts +0 -1
- package/dist/sidecar-lock.js +19 -88
- package/dist/staged-directory.d.ts +2 -3
- package/dist/staged-file-settlement.d.ts +0 -1
- package/dist/staged-file-types.d.ts +0 -1
- package/dist/standalone-publication-path.d.ts +0 -1
- package/dist/stat-observation.d.ts +0 -1
- package/dist/store.d.ts +0 -1
- package/dist/strict-file-identity.d.ts +1 -2
- package/dist/strict-file-identity.js +9 -9
- package/dist/string-coerce.d.ts +0 -1
- package/dist/suppressed-error.d.ts +0 -1
- package/dist/symlink-parents.d.ts +0 -1
- package/dist/symlink-parents.js +2 -27
- package/dist/temp-cleanup.d.ts +0 -1
- package/dist/temp-target.d.ts +0 -1
- package/dist/temp-target.js +7 -46
- package/dist/temp-workspace-admission.d.ts +0 -8
- package/dist/temp-workspace-admission.js +0 -4
- package/dist/temp-workspace-child-admission.d.ts +0 -4
- package/dist/temp-workspace-child-admission.js +0 -12
- package/dist/temp-workspace-descriptor.d.ts +0 -6
- package/dist/temp-workspace-descriptor.js +0 -2
- package/dist/temp-workspace-identity.d.ts +0 -1
- package/dist/temp-workspace-owner.d.ts +1 -1
- package/dist/temp-workspace-owner.js +49 -26
- package/dist/temp-workspace-permissions.d.ts +0 -1
- package/dist/temp-workspace-types.d.ts +0 -1
- package/dist/temp.d.ts +0 -1
- package/dist/test-hooks.d.ts +0 -1
- package/dist/text-atomic.d.ts +0 -1
- package/dist/timing.d.ts +0 -1
- package/dist/trash.d.ts +0 -1
- package/dist/types.d.ts +0 -1
- package/dist/unicode-path.d.ts +0 -1
- package/dist/unicode-path.js +3 -0
- package/dist/walk.d.ts +0 -1
- package/dist/walk.js +4 -2
- package/dist/windows-command.d.ts +0 -1
- package/dist/windows-owner.d.ts +0 -1
- package/dist/windows-owner.js +4 -1
- package/dist/windows-path-alias.d.ts +0 -1
- package/dist/windows-path-alias.js +7 -43
- package/dist/windows-path-syntax.d.ts +5 -0
- package/dist/windows-path-syntax.js +21 -0
- package/dist/windows-security-command.d.ts +0 -1
- package/dist/windows-security-facts.d.ts +0 -1
- package/dist/write-file-handle.d.ts +7 -1
- package/dist/write-file-handle.js +23 -0
- package/dist/write-open-flags.d.ts +0 -1
- package/dist/write-open-flags.js +1 -8
- package/dist/write-queue.d.ts +0 -1
- package/dist/write-queue.js +1 -4
- package/docs/advanced.md +68 -1
- package/docs/archive.md +41 -2
- package/docs/atomic.md +43 -5
- package/docs/contributing.md +4 -0
- package/docs/copy.md +2 -0
- package/docs/creation.md +8 -4
- package/docs/durability.md +35 -0
- package/docs/file-contents.md +68 -0
- package/docs/json.md +5 -4
- package/docs/local-roots.md +2 -0
- package/docs/mutation-policy-proof.md +11 -7
- package/docs/native.md +9 -8
- package/docs/path.md +4 -4
- package/docs/permissions.md +6 -0
- package/docs/public-api.md +5 -0
- package/docs/quickstart.md +1 -1
- package/docs/reading.md +2 -2
- package/docs/regular-file.md +3 -0
- package/docs/root.md +19 -0
- package/docs/secret-file.md +4 -0
- package/docs/sidecar-lock.md +9 -1
- package/docs/staged-file.md +4 -3
- package/docs/store.md +3 -1
- package/docs/temp.md +4 -1
- package/docs/types.md +18 -2
- package/docs/walk.md +7 -0
- package/docs/writing.md +18 -5
- package/package.json +8 -9
- package/dist/absolute-path.d.ts.map +0 -1
- package/dist/advanced.d.ts.map +0 -1
- package/dist/archive-crc32.d.ts.map +0 -1
- package/dist/archive-deadline.d.ts.map +0 -1
- package/dist/archive-durability.d.ts.map +0 -1
- package/dist/archive-entry.d.ts.map +0 -1
- package/dist/archive-errors.d.ts.map +0 -1
- package/dist/archive-gzip-tail.d.ts.map +0 -1
- package/dist/archive-input.d.ts.map +0 -1
- package/dist/archive-kind.d.ts.map +0 -1
- package/dist/archive-limits.d.ts.map +0 -1
- package/dist/archive-merge.d.ts.map +0 -1
- package/dist/archive-native.d.ts.map +0 -1
- package/dist/archive-options.d.ts.map +0 -1
- package/dist/archive-parser-errors.d.ts.map +0 -1
- package/dist/archive-plan.d.ts.map +0 -1
- package/dist/archive-policy.d.ts.map +0 -1
- package/dist/archive-read.d.ts.map +0 -1
- package/dist/archive-staging.d.ts.map +0 -1
- package/dist/archive-tar-inspect.d.ts.map +0 -1
- package/dist/archive-tar-stream.d.ts.map +0 -1
- package/dist/archive-tar-wasm.d.ts.map +0 -1
- package/dist/archive-tar.d.ts.map +0 -1
- package/dist/archive-zip-admission.d.ts.map +0 -1
- package/dist/archive-zip-count.d.ts.map +0 -1
- package/dist/archive-zip-directory.d.ts.map +0 -1
- package/dist/archive-zip-entry.d.ts.map +0 -1
- package/dist/archive-zip-integrity.d.ts.map +0 -1
- package/dist/archive-zip-loader.d.ts.map +0 -1
- package/dist/archive-zip-manifest.d.ts.map +0 -1
- package/dist/archive-zip-names.d.ts.map +0 -1
- package/dist/archive-zip-preflight.d.ts.map +0 -1
- package/dist/archive.d.ts.map +0 -1
- package/dist/async-lock.d.ts.map +0 -1
- package/dist/atomic.d.ts.map +0 -1
- package/dist/bounded-read-stream.d.ts.map +0 -1
- package/dist/bounded-read.d.ts.map +0 -1
- package/dist/byte-budget.d.ts.map +0 -1
- package/dist/clone-metadata.d.ts.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/containment.d.ts.map +0 -1
- package/dist/copy-file-input.d.ts.map +0 -1
- package/dist/copy-policy.d.ts.map +0 -1
- package/dist/copy-publication.d.ts.map +0 -1
- package/dist/copy-tree-portable.d.ts.map +0 -1
- package/dist/copy.d.ts.map +0 -1
- package/dist/create-directory.d.ts.map +0 -1
- package/dist/create-file-async.d.ts.map +0 -1
- package/dist/create-file.d.ts.map +0 -1
- package/dist/create-owned-file.d.ts.map +0 -1
- package/dist/create.d.ts.map +0 -1
- package/dist/creation-darwin.d.ts.map +0 -1
- package/dist/creation-file-state.d.ts.map +0 -1
- package/dist/creation-path.d.ts.map +0 -1
- package/dist/creation-permissions.d.ts.map +0 -1
- package/dist/deny-mutations.d.ts.map +0 -1
- package/dist/device-path.d.ts.map +0 -1
- package/dist/directory-durability.d.ts.map +0 -1
- package/dist/directory-entry-path.d.ts.map +0 -1
- package/dist/directory-guard.d.ts.map +0 -1
- package/dist/directory-mode-node.d.ts.map +0 -1
- package/dist/directory-mode-owner.d.ts.map +0 -1
- package/dist/directory-receipt.d.ts.map +0 -1
- package/dist/durability.d.ts.map +0 -1
- package/dist/effective-uid.d.ts.map +0 -1
- package/dist/error-detail.d.ts.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/file-cleanup.d.ts.map +0 -1
- package/dist/file-handle-transfer.d.ts.map +0 -1
- package/dist/file-hash.d.ts.map +0 -1
- package/dist/file-identity.d.ts.map +0 -1
- package/dist/file-lock-sync-admission.d.ts.map +0 -1
- package/dist/file-lock-sync-root-acquire.d.ts.map +0 -1
- package/dist/file-lock-sync-root-arbitration.d.ts.map +0 -1
- package/dist/file-lock-sync-root-held.d.ts.map +0 -1
- package/dist/file-lock-sync-root-io.d.ts.map +0 -1
- package/dist/file-lock-sync-root-mutation.d.ts.map +0 -1
- package/dist/file-lock-sync-root-options.d.ts.map +0 -1
- package/dist/file-lock-sync-root-registration.d.ts.map +0 -1
- package/dist/file-lock-sync-root.d.ts.map +0 -1
- package/dist/file-lock-sync-stale-admission.d.ts.map +0 -1
- package/dist/file-lock-sync.d.ts.map +0 -1
- package/dist/file-lock.d.ts.map +0 -1
- package/dist/file-observation.d.ts.map +0 -1
- package/dist/file-store-boundary.d.ts.map +0 -1
- package/dist/file-store-copy-source.d.ts.map +0 -1
- package/dist/file-store-limit.d.ts.map +0 -1
- package/dist/file-store-path.d.ts.map +0 -1
- package/dist/file-store-prune.d.ts.map +0 -1
- package/dist/file-store-sync-directory.d.ts.map +0 -1
- package/dist/file-store-sync-write.d.ts.map +0 -1
- package/dist/file-store.d.ts.map +0 -1
- package/dist/file-sync.d.ts.map +0 -1
- package/dist/filename.d.ts.map +0 -1
- package/dist/fs.d.ts.map +0 -1
- package/dist/guarded-mkdir.d.ts.map +0 -1
- package/dist/guarded-mutation.d.ts.map +0 -1
- package/dist/guest-dispatch-python.d.ts.map +0 -1
- package/dist/guest-native-python.d.ts.map +0 -1
- package/dist/guest.d.ts.map +0 -1
- package/dist/home-dir.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/install-path.d.ts.map +0 -1
- package/dist/json-document-store.d.ts.map +0 -1
- package/dist/json-durable-queue-directory.d.ts.map +0 -1
- package/dist/json-durable-queue-ownership.d.ts.map +0 -1
- package/dist/json-durable-queue-paths.d.ts +0 -11
- package/dist/json-durable-queue-paths.d.ts.map +0 -1
- package/dist/json-durable-queue-paths.js +0 -42
- package/dist/json-durable-queue-read.d.ts.map +0 -1
- package/dist/json-durable-queue.d.ts.map +0 -1
- package/dist/json-store.d.ts.map +0 -1
- package/dist/json-stringify.d.ts.map +0 -1
- package/dist/json.d.ts.map +0 -1
- package/dist/local-file-access.d.ts.map +0 -1
- package/dist/local-file-descriptor.d.ts.map +0 -1
- package/dist/local-roots.d.ts.map +0 -1
- package/dist/lock-config.d.ts.map +0 -1
- package/dist/move-path-cleanup.d.ts.map +0 -1
- package/dist/move-path-stage.d.ts.map +0 -1
- package/dist/move-path.d.ts.map +0 -1
- package/dist/mutation-authority.d.ts.map +0 -1
- package/dist/native-binding.d.ts.map +0 -1
- package/dist/native-config.d.ts.map +0 -1
- package/dist/native-directory-observation.d.ts.map +0 -1
- package/dist/native-fallback-warning.d.ts.map +0 -1
- package/dist/native-operations.d.ts.map +0 -1
- package/dist/native-parent-admission.d.ts.map +0 -1
- package/dist/native-pinned-write-windows.d.ts.map +0 -1
- package/dist/native-pinned-write.d.ts.map +0 -1
- package/dist/native-policy-directory-observation.d.ts.map +0 -1
- package/dist/native-policy-parent-windows.d.ts.map +0 -1
- package/dist/native-rename-outcome.d.ts.map +0 -1
- package/dist/native-staged-file.d.ts.map +0 -1
- package/dist/native.d.ts.map +0 -1
- package/dist/opened-file-failure.d.ts.map +0 -1
- package/dist/opened-realpath.d.ts.map +0 -1
- package/dist/output.d.ts.map +0 -1
- package/dist/overwrite-file-handle.d.ts.map +0 -1
- package/dist/owner-dacl.d.ts.map +0 -1
- package/dist/path-case.d.ts.map +0 -1
- package/dist/path-policy.d.ts.map +0 -1
- package/dist/path-prefix.d.ts.map +0 -1
- package/dist/path-scope-lexical.d.ts.map +0 -1
- package/dist/path-segment-route.d.ts.map +0 -1
- package/dist/path-suffix-aliases.d.ts.map +0 -1
- package/dist/path.d.ts.map +0 -1
- package/dist/permission-exec.d.ts.map +0 -1
- package/dist/permissions-public.d.ts.map +0 -1
- package/dist/permissions-windows.d.ts.map +0 -1
- package/dist/permissions.d.ts.map +0 -1
- package/dist/pinned-mutation-admission.d.ts.map +0 -1
- package/dist/pinned-mutation-observation.d.ts.map +0 -1
- package/dist/pinned-mutation-shared-route.d.ts.map +0 -1
- package/dist/pinned-open.d.ts.map +0 -1
- package/dist/pinned-operation.d.ts.map +0 -1
- package/dist/pinned-write-input.d.ts.map +0 -1
- package/dist/pinned-write-mode.d.ts.map +0 -1
- package/dist/pinned-write-staged.d.ts.map +0 -1
- package/dist/pinned-write-types.d.ts.map +0 -1
- package/dist/pinned-write.d.ts.map +0 -1
- package/dist/positional-read.d.ts.map +0 -1
- package/dist/private-directory.d.ts.map +0 -1
- package/dist/private-producer-handoff-sync.d.ts.map +0 -1
- package/dist/private-producer-handoff.d.ts.map +0 -1
- package/dist/private-temp-workspace.d.ts.map +0 -1
- package/dist/publish-copy-stage.d.ts.map +0 -1
- package/dist/publish-file-failure.d.ts.map +0 -1
- package/dist/publish-file.d.ts.map +0 -1
- package/dist/read-open-flags.d.ts.map +0 -1
- package/dist/read-opened-file.d.ts.map +0 -1
- package/dist/realpath.d.ts.map +0 -1
- package/dist/recursive-mkdir-path.d.ts.map +0 -1
- package/dist/regular-file.d.ts.map +0 -1
- package/dist/replace-directory.d.ts.map +0 -1
- package/dist/replace-file-copy-fallback.d.ts.map +0 -1
- package/dist/replace-file-copy-source.d.ts.map +0 -1
- package/dist/replace-file-descriptor.d.ts.map +0 -1
- package/dist/replace-file-mode.d.ts.map +0 -1
- package/dist/replace-file-rename-policy.d.ts.map +0 -1
- package/dist/replace-file-temp-owner.d.ts.map +0 -1
- package/dist/replace-file.d.ts.map +0 -1
- package/dist/retained-directory-replacement.d.ts.map +0 -1
- package/dist/root-boundary.d.ts.map +0 -1
- package/dist/root-context.d.ts.map +0 -1
- package/dist/root-create-input.d.ts.map +0 -1
- package/dist/root-directory-creation.d.ts.map +0 -1
- package/dist/root-directory-list.d.ts.map +0 -1
- package/dist/root-directory.d.ts.map +0 -1
- package/dist/root-entries.d.ts.map +0 -1
- package/dist/root-errors.d.ts.map +0 -1
- package/dist/root-file-final-admission.d.ts.map +0 -1
- package/dist/root-file.d.ts.map +0 -1
- package/dist/root-impl.d.ts.map +0 -1
- package/dist/root-move-noreplace.d.ts.map +0 -1
- package/dist/root-move-preflight.d.ts.map +0 -1
- package/dist/root-observed-path.d.ts.map +0 -1
- package/dist/root-options.d.ts.map +0 -1
- package/dist/root-path-errors.d.ts.map +0 -1
- package/dist/root-path-existing.d.ts.map +0 -1
- package/dist/root-path-observation.d.ts.map +0 -1
- package/dist/root-path-stat.d.ts.map +0 -1
- package/dist/root-path-symlink.d.ts +0 -7
- package/dist/root-path-symlink.d.ts.map +0 -1
- package/dist/root-path-symlink.js +0 -55
- package/dist/root-path.d.ts.map +0 -1
- package/dist/root-paths-lexical.d.ts.map +0 -1
- package/dist/root-paths.d.ts.map +0 -1
- package/dist/root-read-admission.d.ts.map +0 -1
- package/dist/root-remove-identity.d.ts.map +0 -1
- package/dist/root-remove-receipt.d.ts.map +0 -1
- package/dist/root-remove.d.ts.map +0 -1
- package/dist/root-symlink-policy.d.ts.map +0 -1
- package/dist/root-walk.d.ts.map +0 -1
- package/dist/root-write-admission.d.ts.map +0 -1
- package/dist/root-write-compatibility.d.ts.map +0 -1
- package/dist/root-write-complete-parent.d.ts.map +0 -1
- package/dist/root-write-lock-binding.d.ts.map +0 -1
- package/dist/root-write-mode.d.ts.map +0 -1
- package/dist/root-write-publication.d.ts.map +0 -1
- package/dist/root-write-verification.d.ts.map +0 -1
- package/dist/root.d.ts.map +0 -1
- package/dist/safe-path-segment.d.ts.map +0 -1
- package/dist/secret-file.d.ts.map +0 -1
- package/dist/secret-read-async.d.ts.map +0 -1
- package/dist/secret-read-policy.d.ts.map +0 -1
- package/dist/secret.d.ts.map +0 -1
- package/dist/secure-file-windows.d.ts.map +0 -1
- package/dist/secure-file.d.ts.map +0 -1
- package/dist/secure-temp-dir.d.ts.map +0 -1
- package/dist/secure-temp-repair.d.ts.map +0 -1
- package/dist/sibling-staged-file.d.ts.map +0 -1
- package/dist/sibling-temp.d.ts.map +0 -1
- package/dist/sidecar-lock-acquire.d.ts.map +0 -1
- package/dist/sidecar-lock-admission-context.d.ts.map +0 -1
- package/dist/sidecar-lock-admission-parser.d.ts.map +0 -1
- package/dist/sidecar-lock-admission.d.ts.map +0 -1
- package/dist/sidecar-lock-handle.d.ts.map +0 -1
- package/dist/sidecar-lock-policy.d.ts.map +0 -1
- package/dist/sidecar-lock-reclaim.d.ts.map +0 -1
- package/dist/sidecar-lock-root.d.ts.map +0 -1
- package/dist/sidecar-lock-stale-admission.d.ts.map +0 -1
- package/dist/sidecar-lock-target.d.ts.map +0 -1
- package/dist/sidecar-lock-types.d.ts.map +0 -1
- package/dist/sidecar-lock.d.ts.map +0 -1
- package/dist/staged-directory.d.ts.map +0 -1
- package/dist/staged-file-settlement.d.ts.map +0 -1
- package/dist/staged-file-types.d.ts.map +0 -1
- package/dist/standalone-publication-path.d.ts.map +0 -1
- package/dist/stat-observation.d.ts.map +0 -1
- package/dist/store.d.ts.map +0 -1
- package/dist/strict-file-identity.d.ts.map +0 -1
- package/dist/string-coerce.d.ts.map +0 -1
- package/dist/suppressed-error.d.ts.map +0 -1
- package/dist/symlink-parents.d.ts.map +0 -1
- package/dist/temp-cleanup.d.ts.map +0 -1
- package/dist/temp-target.d.ts.map +0 -1
- package/dist/temp-workspace-admission.d.ts.map +0 -1
- package/dist/temp-workspace-child-admission.d.ts.map +0 -1
- package/dist/temp-workspace-descriptor.d.ts.map +0 -1
- package/dist/temp-workspace-identity.d.ts.map +0 -1
- package/dist/temp-workspace-owner.d.ts.map +0 -1
- package/dist/temp-workspace-permissions.d.ts.map +0 -1
- package/dist/temp-workspace-types.d.ts.map +0 -1
- package/dist/temp.d.ts.map +0 -1
- package/dist/test-hooks.d.ts.map +0 -1
- package/dist/text-atomic.d.ts.map +0 -1
- package/dist/timing.d.ts.map +0 -1
- package/dist/trash.d.ts.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/unicode-path.d.ts.map +0 -1
- package/dist/walk.d.ts.map +0 -1
- package/dist/windows-command.d.ts.map +0 -1
- package/dist/windows-owner.d.ts.map +0 -1
- package/dist/windows-path-alias.d.ts.map +0 -1
- package/dist/windows-security-command.d.ts.map +0 -1
- package/dist/windows-security-facts.d.ts.map +0 -1
- package/dist/write-file-handle.d.ts.map +0 -1
- package/dist/write-open-flags.d.ts.map +0 -1
- package/dist/write-queue.d.ts.map +0 -1
package/dist/regular-file.js
CHANGED
|
@@ -5,10 +5,10 @@ import { readFileDescriptorBoundedSync, readFileHandleBounded } from "./bounded-
|
|
|
5
5
|
import { normalizeMaxBytes } from "./byte-budget.js";
|
|
6
6
|
import { assertNoUnsafeDeviceReadPath } from "./device-path.js";
|
|
7
7
|
import { FsSafeError } from "./errors.js";
|
|
8
|
-
import {
|
|
8
|
+
import { inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
9
9
|
import { isNotFoundPathError } from "./path.js";
|
|
10
10
|
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
11
|
-
import {
|
|
11
|
+
import { assertNoSymlinkParentsSync } from "./symlink-parents.js";
|
|
12
12
|
import { getFsSafeTestHooks } from "./test-hooks.js";
|
|
13
13
|
import { isNonRegularWriteOpenError, isNonRegularWriteOpenErrorSync, resolveNonblockingWriteFlag, } from "./write-open-flags.js";
|
|
14
14
|
import { assertNoWindowsPathAlias, resolvePathPreservingWindowsRoot, } from "./windows-path-alias.js";
|
|
@@ -50,18 +50,7 @@ export function statRegularFileSync(filePath) {
|
|
|
50
50
|
return { missing: false, stat };
|
|
51
51
|
}
|
|
52
52
|
export async function readRegularFile(params) {
|
|
53
|
-
const maxBytes =
|
|
54
|
-
const filePath = params.filePath;
|
|
55
|
-
assertNoWindowsPathAlias(filePath, "filesystem", "file path uses a Windows filesystem namespace alias");
|
|
56
|
-
assertNoUnsafeDeviceReadPath(filePath);
|
|
57
|
-
const before = await inspectFileIdentity(async () => {
|
|
58
|
-
const stat = fsSync.lstatSync(filePath, { bigint: true });
|
|
59
|
-
assertRegularReadStat(stat, filePath, true);
|
|
60
|
-
return stat;
|
|
61
|
-
}).catch((error) => throwReadPreviewError(error, filePath));
|
|
62
|
-
if (maxBytes !== undefined && before.size > maxBytes) {
|
|
63
|
-
throw regularFileTooLargeError(filePath, maxBytes);
|
|
64
|
-
}
|
|
53
|
+
const { filePath, maxBytes, before } = prepareRegularRead(params);
|
|
65
54
|
let handle;
|
|
66
55
|
try {
|
|
67
56
|
handle = await fs.open(filePath, resolveReadOpenFlags());
|
|
@@ -73,28 +62,7 @@ export async function readRegularFile(params) {
|
|
|
73
62
|
throw err;
|
|
74
63
|
}
|
|
75
64
|
try {
|
|
76
|
-
const stat =
|
|
77
|
-
const identity = await inspectFileIdentity(async () => {
|
|
78
|
-
const exact = fsSync.fstatSync(handle.fd, { bigint: true });
|
|
79
|
-
assertRegularReadStat(exact, filePath);
|
|
80
|
-
return exact;
|
|
81
|
-
}, before);
|
|
82
|
-
try {
|
|
83
|
-
await inspectFileIdentity(async () => {
|
|
84
|
-
const current = fsSync.lstatSync(filePath, { bigint: true });
|
|
85
|
-
assertRegularReadStat(current, filePath);
|
|
86
|
-
return current;
|
|
87
|
-
}, identity);
|
|
88
|
-
}
|
|
89
|
-
catch (err) {
|
|
90
|
-
if (isNotFoundPathError(err)) {
|
|
91
|
-
throw new FsSafeError("path-mismatch", `File changed during read: ${filePath}`);
|
|
92
|
-
}
|
|
93
|
-
throw err;
|
|
94
|
-
}
|
|
95
|
-
if (maxBytes !== undefined && stat.size > maxBytes) {
|
|
96
|
-
throw regularFileTooLargeError(filePath, maxBytes);
|
|
97
|
-
}
|
|
65
|
+
const stat = inspectOpenedRegularRead(handle.fd, filePath, before, maxBytes);
|
|
98
66
|
// With a byte cap, avoid readFile(): a raced file growth would allocate
|
|
99
67
|
// the oversized content before the post-read check could reject it.
|
|
100
68
|
let buffer;
|
|
@@ -127,47 +95,7 @@ function assertRegularReadStat(stat, filePath, preview = false) {
|
|
|
127
95
|
throw new Error(preview ? "path must be a regular file" : `File is not a regular file: ${filePath}`);
|
|
128
96
|
}
|
|
129
97
|
}
|
|
130
|
-
function
|
|
131
|
-
const stat = fsSync.fstatSync(params.fd);
|
|
132
|
-
const identity = inspectFileIdentitySync(() => {
|
|
133
|
-
const exact = fsSync.fstatSync(params.fd, { bigint: true });
|
|
134
|
-
assertRegularReadStat(exact, params.filePath);
|
|
135
|
-
return exact;
|
|
136
|
-
}, params.preOpenStat);
|
|
137
|
-
try {
|
|
138
|
-
inspectFileIdentitySync(() => {
|
|
139
|
-
const current = fsSync.lstatSync(params.filePath, { bigint: true });
|
|
140
|
-
assertRegularReadStat(current, params.filePath);
|
|
141
|
-
return current;
|
|
142
|
-
}, identity);
|
|
143
|
-
}
|
|
144
|
-
catch (error) {
|
|
145
|
-
if (isNotFoundPathError(error)) {
|
|
146
|
-
throw new FsSafeError("path-mismatch", `File changed during read: ${params.filePath}`);
|
|
147
|
-
}
|
|
148
|
-
throw error;
|
|
149
|
-
}
|
|
150
|
-
if (params.maxBytes !== undefined && stat.size > params.maxBytes) {
|
|
151
|
-
throw regularFileTooLargeError(params.filePath, params.maxBytes);
|
|
152
|
-
}
|
|
153
|
-
// Keep capped sync reads incremental for the same reason as async reads:
|
|
154
|
-
// readFileSync(fd) would buffer a raced oversized file before throwing.
|
|
155
|
-
let buffer;
|
|
156
|
-
try {
|
|
157
|
-
buffer =
|
|
158
|
-
params.maxBytes === undefined
|
|
159
|
-
? fsSync.readFileSync(params.fd)
|
|
160
|
-
: readFileDescriptorBoundedSync(params.fd, params.maxBytes);
|
|
161
|
-
}
|
|
162
|
-
catch (error) {
|
|
163
|
-
if (params.maxBytes !== undefined) {
|
|
164
|
-
translateBoundedReadOverflow(error, params.filePath, params.maxBytes);
|
|
165
|
-
}
|
|
166
|
-
throw error;
|
|
167
|
-
}
|
|
168
|
-
return { buffer, stat };
|
|
169
|
-
}
|
|
170
|
-
export function readRegularFileSync(params) {
|
|
98
|
+
function prepareRegularRead(params) {
|
|
171
99
|
const maxBytes = normalizeMaxBytes(params.maxBytes);
|
|
172
100
|
const filePath = params.filePath;
|
|
173
101
|
assertNoWindowsPathAlias(filePath, "filesystem", "file path uses a Windows filesystem namespace alias");
|
|
@@ -186,6 +114,35 @@ export function readRegularFileSync(params) {
|
|
|
186
114
|
if (maxBytes !== undefined && before.size > maxBytes) {
|
|
187
115
|
throw regularFileTooLargeError(filePath, maxBytes);
|
|
188
116
|
}
|
|
117
|
+
return { filePath, maxBytes, before };
|
|
118
|
+
}
|
|
119
|
+
function inspectOpenedRegularRead(fd, filePath, preOpenStat, maxBytes) {
|
|
120
|
+
const stat = fsSync.fstatSync(fd);
|
|
121
|
+
const identity = inspectFileIdentitySync(() => {
|
|
122
|
+
const exact = fsSync.fstatSync(fd, { bigint: true });
|
|
123
|
+
assertRegularReadStat(exact, filePath);
|
|
124
|
+
return exact;
|
|
125
|
+
}, preOpenStat);
|
|
126
|
+
try {
|
|
127
|
+
inspectFileIdentitySync(() => {
|
|
128
|
+
const current = fsSync.lstatSync(filePath, { bigint: true });
|
|
129
|
+
assertRegularReadStat(current, filePath);
|
|
130
|
+
return current;
|
|
131
|
+
}, identity);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
if (isNotFoundPathError(error)) {
|
|
135
|
+
throw new FsSafeError("path-mismatch", `File changed during read: ${filePath}`);
|
|
136
|
+
}
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
139
|
+
if (maxBytes !== undefined && stat.size > maxBytes) {
|
|
140
|
+
throw regularFileTooLargeError(filePath, maxBytes);
|
|
141
|
+
}
|
|
142
|
+
return stat;
|
|
143
|
+
}
|
|
144
|
+
export function readRegularFileSync(params) {
|
|
145
|
+
const { filePath, maxBytes, before } = prepareRegularRead(params);
|
|
189
146
|
let fd;
|
|
190
147
|
try {
|
|
191
148
|
fd = fsSync.openSync(filePath, resolveReadOpenFlags());
|
|
@@ -197,12 +154,21 @@ export function readRegularFileSync(params) {
|
|
|
197
154
|
throw error;
|
|
198
155
|
}
|
|
199
156
|
try {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
maxBytes
|
|
205
|
-
|
|
157
|
+
const stat = inspectOpenedRegularRead(fd, filePath, before, maxBytes);
|
|
158
|
+
// Keep capped reads incremental so raced growth cannot allocate unbounded content.
|
|
159
|
+
let buffer;
|
|
160
|
+
try {
|
|
161
|
+
buffer = maxBytes === undefined
|
|
162
|
+
? fsSync.readFileSync(fd)
|
|
163
|
+
: readFileDescriptorBoundedSync(fd, maxBytes);
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
if (maxBytes !== undefined) {
|
|
167
|
+
translateBoundedReadOverflow(error, filePath, maxBytes);
|
|
168
|
+
}
|
|
169
|
+
throw error;
|
|
170
|
+
}
|
|
171
|
+
return { buffer, stat };
|
|
206
172
|
}
|
|
207
173
|
finally {
|
|
208
174
|
fsSync.closeSync(fd);
|
|
@@ -223,12 +189,27 @@ function throwAppendIdentityError(error, filePath) {
|
|
|
223
189
|
}
|
|
224
190
|
throw error;
|
|
225
191
|
}
|
|
226
|
-
|
|
192
|
+
function captureAppendOptions(options) {
|
|
227
193
|
const filePath = options.filePath;
|
|
228
194
|
assertNoWindowsPathAlias(filePath, "filesystem", "file path uses a Windows filesystem namespace alias");
|
|
229
|
-
|
|
195
|
+
return {
|
|
196
|
+
filePath, content: options.content, encoding: options.encoding ?? "utf8",
|
|
197
|
+
mode: options.mode ?? 0o600, maxFileBytes: options.maxFileBytes,
|
|
198
|
+
rejectSymlinkParents: options.rejectSymlinkParents,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function inspectAppendPath(filePath) {
|
|
202
|
+
const stat = fsSync.lstatSync(filePath, { bigint: true });
|
|
203
|
+
if (stat.isSymbolicLink())
|
|
204
|
+
throw new Error(`Refusing to append through symlink: ${filePath}`);
|
|
205
|
+
if (!stat.isFile())
|
|
206
|
+
throw new Error(`Refusing to append to non-file: ${filePath}`);
|
|
207
|
+
return stat;
|
|
208
|
+
}
|
|
209
|
+
function prepareRegularAppend(filePath, rejectSymlinkParents) {
|
|
210
|
+
if (rejectSymlinkParents === true) {
|
|
230
211
|
const resolvedDir = resolvePathPreservingWindowsRoot(path.dirname(filePath));
|
|
231
|
-
|
|
212
|
+
assertNoSymlinkParentsSync({
|
|
232
213
|
rootDir: path.parse(resolvedDir).root,
|
|
233
214
|
targetPath: resolvedDir,
|
|
234
215
|
allowMissing: false,
|
|
@@ -237,35 +218,45 @@ export async function appendRegularFile(options) {
|
|
|
237
218
|
messagePrefix: "Refusing to append under",
|
|
238
219
|
});
|
|
239
220
|
}
|
|
240
|
-
let preOpenStat;
|
|
241
221
|
try {
|
|
242
|
-
|
|
243
|
-
const stat = fsSync.lstatSync(filePath, { bigint: true });
|
|
244
|
-
if (stat.isSymbolicLink()) {
|
|
245
|
-
throw new Error(`Refusing to append through symlink: ${filePath}`);
|
|
246
|
-
}
|
|
247
|
-
if (!stat.isFile()) {
|
|
248
|
-
throw new Error(`Refusing to append to non-file: ${filePath}`);
|
|
249
|
-
}
|
|
250
|
-
return stat;
|
|
251
|
-
});
|
|
222
|
+
return inspectFileIdentitySync(() => inspectAppendPath(filePath));
|
|
252
223
|
}
|
|
253
224
|
catch (error) {
|
|
254
225
|
if (!isNotFoundPathError(error))
|
|
255
226
|
throw error;
|
|
256
227
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
228
|
+
}
|
|
229
|
+
function inspectOpenedRegularAppend(fd, filePath, preOpenStat) {
|
|
230
|
+
try {
|
|
231
|
+
const identity = inspectFileIdentitySync(() => {
|
|
232
|
+
const stat = fsSync.fstatSync(fd, { bigint: true });
|
|
233
|
+
assertRegularAppendStat(stat, filePath);
|
|
234
|
+
return stat;
|
|
235
|
+
}, preOpenStat);
|
|
236
|
+
inspectFileIdentitySync(() => {
|
|
237
|
+
const current = fsSync.lstatSync(filePath, { bigint: true });
|
|
238
|
+
assertRegularAppendStat(current, filePath);
|
|
239
|
+
return current;
|
|
240
|
+
}, identity);
|
|
241
|
+
return identity;
|
|
242
|
+
}
|
|
243
|
+
catch (error) {
|
|
244
|
+
throwAppendIdentityError(error, filePath);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
export async function appendRegularFile(options) {
|
|
248
|
+
const { filePath, content, encoding, mode, maxFileBytes, rejectSymlinkParents } = captureAppendOptions(options);
|
|
249
|
+
const preOpenStat = prepareRegularAppend(filePath, rejectSymlinkParents);
|
|
250
|
+
const contentBytes = Buffer.isBuffer(content) ? content.byteLength : Buffer.byteLength(content, encoding);
|
|
251
|
+
if (maxFileBytes !== undefined &&
|
|
252
|
+
Number(preOpenStat?.size ?? 0n) + contentBytes > maxFileBytes) {
|
|
262
253
|
return;
|
|
263
254
|
}
|
|
264
255
|
await getFsSafeTestHooks()?.beforeRegularFileAppendOpen?.(filePath);
|
|
265
256
|
const flags = resolveRegularFileAppendFlags();
|
|
266
257
|
let handle;
|
|
267
258
|
try {
|
|
268
|
-
handle = await fs.open(filePath, flags,
|
|
259
|
+
handle = await fs.open(filePath, flags, mode);
|
|
269
260
|
}
|
|
270
261
|
catch (error) {
|
|
271
262
|
if (await isNonRegularWriteOpenError(error, filePath, flags)) {
|
|
@@ -274,30 +265,14 @@ export async function appendRegularFile(options) {
|
|
|
274
265
|
throw error;
|
|
275
266
|
}
|
|
276
267
|
try {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
identity
|
|
280
|
-
const stat = fsSync.fstatSync(handle.fd, { bigint: true });
|
|
281
|
-
assertRegularAppendStat(stat, filePath);
|
|
282
|
-
return stat;
|
|
283
|
-
}, preOpenStat);
|
|
284
|
-
await inspectFileIdentity(async () => {
|
|
285
|
-
const current = fsSync.lstatSync(filePath, { bigint: true });
|
|
286
|
-
assertRegularAppendStat(current, filePath);
|
|
287
|
-
return current;
|
|
288
|
-
}, identity);
|
|
289
|
-
}
|
|
290
|
-
catch (error) {
|
|
291
|
-
throwAppendIdentityError(error, filePath);
|
|
292
|
-
}
|
|
293
|
-
if (options.maxFileBytes !== undefined &&
|
|
294
|
-
Number(identity.size) + contentBytes > options.maxFileBytes) {
|
|
268
|
+
const identity = inspectOpenedRegularAppend(handle.fd, filePath, preOpenStat);
|
|
269
|
+
if (maxFileBytes !== undefined &&
|
|
270
|
+
Number(identity.size) + contentBytes > maxFileBytes) {
|
|
295
271
|
return;
|
|
296
272
|
}
|
|
297
|
-
const mode = options.mode ?? 0o600;
|
|
298
273
|
// Tighten before writing; restore explicit special bits only after content is complete.
|
|
299
274
|
await handle.chmod(mode);
|
|
300
|
-
await handle.appendFile(
|
|
275
|
+
await handle.appendFile(content, encoding);
|
|
301
276
|
if (mode & 0o7000)
|
|
302
277
|
await handle.chmod(mode);
|
|
303
278
|
}
|
|
@@ -306,48 +281,18 @@ export async function appendRegularFile(options) {
|
|
|
306
281
|
}
|
|
307
282
|
}
|
|
308
283
|
export function appendRegularFileSync(options) {
|
|
309
|
-
const filePath = options
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
rootDir: path.parse(resolvedDir).root,
|
|
315
|
-
targetPath: resolvedDir,
|
|
316
|
-
allowMissing: false,
|
|
317
|
-
allowRootChildSymlink: true,
|
|
318
|
-
requireDirectories: true,
|
|
319
|
-
messagePrefix: "Refusing to append under",
|
|
320
|
-
});
|
|
321
|
-
}
|
|
322
|
-
let preOpenStat;
|
|
323
|
-
try {
|
|
324
|
-
preOpenStat = inspectFileIdentitySync(() => {
|
|
325
|
-
const stat = fsSync.lstatSync(filePath, { bigint: true });
|
|
326
|
-
if (stat.isSymbolicLink()) {
|
|
327
|
-
throw new Error(`Refusing to append through symlink: ${filePath}`);
|
|
328
|
-
}
|
|
329
|
-
if (!stat.isFile()) {
|
|
330
|
-
throw new Error(`Refusing to append to non-file: ${filePath}`);
|
|
331
|
-
}
|
|
332
|
-
return stat;
|
|
333
|
-
});
|
|
334
|
-
}
|
|
335
|
-
catch (error) {
|
|
336
|
-
if (!isNotFoundPathError(error))
|
|
337
|
-
throw error;
|
|
338
|
-
}
|
|
339
|
-
const contentBuffer = typeof options.content === "string"
|
|
340
|
-
? Buffer.from(options.content, options.encoding ?? "utf8")
|
|
341
|
-
: Buffer.from(options.content);
|
|
342
|
-
if (options.maxFileBytes !== undefined &&
|
|
343
|
-
Number(preOpenStat?.size ?? 0n) + contentBuffer.byteLength > options.maxFileBytes) {
|
|
284
|
+
const { filePath, content, encoding, mode, maxFileBytes, rejectSymlinkParents } = captureAppendOptions(options);
|
|
285
|
+
const preOpenStat = prepareRegularAppend(filePath, rejectSymlinkParents);
|
|
286
|
+
const contentBuffer = typeof content === "string" ? Buffer.from(content, encoding) : Buffer.from(content);
|
|
287
|
+
if (maxFileBytes !== undefined &&
|
|
288
|
+
Number(preOpenStat?.size ?? 0n) + contentBuffer.byteLength > maxFileBytes) {
|
|
344
289
|
return;
|
|
345
290
|
}
|
|
346
291
|
getFsSafeTestHooks()?.beforeRegularFileAppendOpenSync?.(filePath);
|
|
347
292
|
const flags = resolveRegularFileAppendFlags();
|
|
348
293
|
let fd;
|
|
349
294
|
try {
|
|
350
|
-
fd = fsSync.openSync(filePath, flags,
|
|
295
|
+
fd = fsSync.openSync(filePath, flags, mode);
|
|
351
296
|
}
|
|
352
297
|
catch (error) {
|
|
353
298
|
if (isNonRegularWriteOpenErrorSync(error, filePath, flags)) {
|
|
@@ -356,27 +301,11 @@ export function appendRegularFileSync(options) {
|
|
|
356
301
|
throw error;
|
|
357
302
|
}
|
|
358
303
|
try {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
identity
|
|
362
|
-
const stat = fsSync.fstatSync(fd, { bigint: true });
|
|
363
|
-
assertRegularAppendStat(stat, filePath);
|
|
364
|
-
return stat;
|
|
365
|
-
}, preOpenStat);
|
|
366
|
-
inspectFileIdentitySync(() => {
|
|
367
|
-
const current = fsSync.lstatSync(filePath, { bigint: true });
|
|
368
|
-
assertRegularAppendStat(current, filePath);
|
|
369
|
-
return current;
|
|
370
|
-
}, identity);
|
|
371
|
-
}
|
|
372
|
-
catch (error) {
|
|
373
|
-
throwAppendIdentityError(error, filePath);
|
|
374
|
-
}
|
|
375
|
-
if (options.maxFileBytes !== undefined &&
|
|
376
|
-
Number(identity.size) + contentBuffer.byteLength > options.maxFileBytes) {
|
|
304
|
+
const identity = inspectOpenedRegularAppend(fd, filePath, preOpenStat);
|
|
305
|
+
if (maxFileBytes !== undefined &&
|
|
306
|
+
Number(identity.size) + contentBuffer.byteLength > maxFileBytes) {
|
|
377
307
|
return;
|
|
378
308
|
}
|
|
379
|
-
const mode = options.mode ?? 0o600;
|
|
380
309
|
fsSync.fchmodSync(fd, mode);
|
|
381
310
|
fsSync.appendFileSync(fd, contentBuffer);
|
|
382
311
|
if (mode & 0o7000)
|
|
@@ -2,9 +2,10 @@ import syncFs, {} from "node:fs";
|
|
|
2
2
|
import fs, {} from "node:fs/promises";
|
|
3
3
|
import { readBoundedAsync, readBoundedSync } from "./bounded-read.js";
|
|
4
4
|
import { FsSafeError } from "./errors.js";
|
|
5
|
-
import {
|
|
5
|
+
import { inspectFileIdentity, inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
6
6
|
import { readOwnedCopySource, readOwnedCopySourceSync } from "./replace-file-copy-source.js";
|
|
7
7
|
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
8
|
+
import { hasErrorCode } from "./file-cleanup.js";
|
|
8
9
|
const SUPPORTS_NOFOLLOW = process.platform !== "win32" && "O_NOFOLLOW" in syncFs.constants;
|
|
9
10
|
const NOFOLLOW = SUPPORTS_NOFOLLOW ? syncFs.constants.O_NOFOLLOW : 0;
|
|
10
11
|
const OPEN_READ_FLAGS = resolveReadOpenFlags();
|
|
@@ -19,39 +20,37 @@ function closeSyncAfterAdmissionFailure(fsModule, fd, error) {
|
|
|
19
20
|
}
|
|
20
21
|
throw error;
|
|
21
22
|
}
|
|
22
|
-
function
|
|
23
|
-
return error.code === "ENOENT";
|
|
24
|
-
}
|
|
25
|
-
function assertPinnedDestination(pathname, opened, dest, hardlinks, admission) {
|
|
23
|
+
function admitDestinationKind(pathname, opened, dest, admission) {
|
|
26
24
|
if (admission === "hardlinks") {
|
|
27
|
-
if (pathname.isSymbolicLink() || !pathname.isFile()
|
|
25
|
+
if (pathname.isSymbolicLink() || !pathname.isFile()) {
|
|
28
26
|
throw new FsSafeError("path-mismatch", `Atomic replace destination changed while opening: ${dest}`);
|
|
29
27
|
}
|
|
30
|
-
if (opened.nlink > 1) {
|
|
31
|
-
throw new FsSafeError("hardlink", `Hardlinked atomic replace destination not allowed: ${dest}`);
|
|
32
|
-
}
|
|
33
|
-
return;
|
|
34
28
|
}
|
|
35
|
-
if (pathname.isSymbolicLink()) {
|
|
29
|
+
else if (pathname.isSymbolicLink()) {
|
|
36
30
|
throw new FsSafeError("symlink", `Refusing copy fallback through symlink destination: ${dest}`);
|
|
37
31
|
}
|
|
38
|
-
if (!pathname.isFile() || !opened.isFile()) {
|
|
32
|
+
else if (!pathname.isFile() || !opened.isFile()) {
|
|
39
33
|
throw new FsSafeError("not-file", `Copy fallback destination must be a regular file: ${dest}`);
|
|
40
34
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (hardlinks === "reject" && opened.nlink >
|
|
45
|
-
throw new FsSafeError("hardlink", `Hardlinked copy fallback destination not allowed: ${dest}`);
|
|
35
|
+
return pathname;
|
|
36
|
+
}
|
|
37
|
+
function assertDestinationLinks(opened, dest, admission, hardlinks) {
|
|
38
|
+
if ((admission === "hardlinks" || hardlinks === "reject") && opened.nlink > 1n) {
|
|
39
|
+
throw new FsSafeError("hardlink", `Hardlinked ${admission === "hardlinks" ? "atomic replace" : "copy fallback"} destination not allowed: ${dest}`);
|
|
46
40
|
}
|
|
47
41
|
}
|
|
42
|
+
function inspectPinnedDestinationSync(fsModule, fd, dest, admission, hardlinks) {
|
|
43
|
+
const opened = inspectFileIdentitySync(() => fsModule.fstatSync(fd, { bigint: true }));
|
|
44
|
+
inspectFileIdentitySync(() => admitDestinationKind(fsModule.lstatSync(dest, { bigint: true }), opened, dest, admission), opened);
|
|
45
|
+
assertDestinationLinks(opened, dest, admission, hardlinks);
|
|
46
|
+
}
|
|
48
47
|
async function openPinnedDestination(fsModule, dest, admission, hardlinks) {
|
|
49
48
|
let preview;
|
|
50
49
|
try {
|
|
51
50
|
preview = fsModule === fs ? syncFs.lstatSync(dest) : await fsModule.lstat(dest);
|
|
52
51
|
}
|
|
53
52
|
catch (error) {
|
|
54
|
-
if (
|
|
53
|
+
if (hasErrorCode(error, "ENOENT"))
|
|
55
54
|
return null;
|
|
56
55
|
throw error;
|
|
57
56
|
}
|
|
@@ -64,13 +63,22 @@ async function openPinnedDestination(fsModule, dest, admission, hardlinks) {
|
|
|
64
63
|
}
|
|
65
64
|
const handle = await fsModule.open(dest, admission === "restore" ? OPEN_READ_WRITE_FLAGS : OPEN_READ_FLAGS);
|
|
66
65
|
try {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
if (fsModule === fs)
|
|
67
|
+
inspectPinnedDestinationSync(syncFs, handle.fd, dest, admission, hardlinks);
|
|
68
|
+
else {
|
|
69
|
+
const opened = await inspectFileIdentity(() => handle.stat({ bigint: true }));
|
|
70
|
+
await inspectFileIdentity(async () => admitDestinationKind(await fsModule.lstat(dest, { bigint: true }), opened, dest, admission), opened);
|
|
71
|
+
assertDestinationLinks(opened, dest, admission, hardlinks);
|
|
72
|
+
}
|
|
70
73
|
return handle;
|
|
71
74
|
}
|
|
72
75
|
catch (error) {
|
|
73
|
-
|
|
76
|
+
try {
|
|
77
|
+
await handle.close();
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// Preserve the already-selected admission failure.
|
|
81
|
+
}
|
|
74
82
|
throw error;
|
|
75
83
|
}
|
|
76
84
|
}
|
|
@@ -80,7 +88,7 @@ function openPinnedDestinationSync(fsModule, dest, admission, hardlinks) {
|
|
|
80
88
|
preview = fsModule.lstatSync(dest);
|
|
81
89
|
}
|
|
82
90
|
catch (error) {
|
|
83
|
-
if (
|
|
91
|
+
if (hasErrorCode(error, "ENOENT"))
|
|
84
92
|
return null;
|
|
85
93
|
throw error;
|
|
86
94
|
}
|
|
@@ -91,8 +99,7 @@ function openPinnedDestinationSync(fsModule, dest, admission, hardlinks) {
|
|
|
91
99
|
}
|
|
92
100
|
const fd = fsModule.openSync(dest, admission === "restore" ? OPEN_READ_WRITE_FLAGS : OPEN_READ_FLAGS);
|
|
93
101
|
try {
|
|
94
|
-
|
|
95
|
-
assertPinnedDestination(fsModule.lstatSync(dest), opened, dest, hardlinks, admission);
|
|
102
|
+
inspectPinnedDestinationSync(fsModule, fd, dest, admission, hardlinks);
|
|
96
103
|
return fd;
|
|
97
104
|
}
|
|
98
105
|
catch (error) {
|
|
@@ -103,8 +110,14 @@ export async function assertDestinationHardlinkPolicy(fsModule, dest, policy) {
|
|
|
103
110
|
if (policy !== "reject")
|
|
104
111
|
return;
|
|
105
112
|
const handle = await openPinnedDestination(fsModule, dest, "hardlinks");
|
|
106
|
-
if (handle)
|
|
107
|
-
|
|
113
|
+
if (!handle)
|
|
114
|
+
return;
|
|
115
|
+
try {
|
|
116
|
+
await handle.close();
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// The asynchronous admission pin has best-effort close semantics.
|
|
120
|
+
}
|
|
108
121
|
}
|
|
109
122
|
export function assertDestinationHardlinkPolicySync(fsModule, dest, policy) {
|
|
110
123
|
if (policy !== "reject")
|
|
@@ -239,7 +252,7 @@ export async function copyFallbackReplace(params) {
|
|
|
239
252
|
? syncFs.lstatSync(params.dest) : await params.fsModule.lstat(params.dest);
|
|
240
253
|
}
|
|
241
254
|
catch (error) {
|
|
242
|
-
if (!
|
|
255
|
+
if (!hasErrorCode(error, "ENOENT"))
|
|
243
256
|
throw error;
|
|
244
257
|
}
|
|
245
258
|
if (destStat?.isSymbolicLink()) {
|
|
@@ -294,7 +307,7 @@ export function copyFallbackReplaceSync(params) {
|
|
|
294
307
|
destStat = params.fsModule.lstatSync(params.dest);
|
|
295
308
|
}
|
|
296
309
|
catch (error) {
|
|
297
|
-
if (!
|
|
310
|
+
if (!hasErrorCode(error, "ENOENT"))
|
|
298
311
|
throw error;
|
|
299
312
|
}
|
|
300
313
|
if (destStat?.isSymbolicLink()) {
|
|
@@ -3,8 +3,8 @@ import fs, {} from "node:fs/promises";
|
|
|
3
3
|
import { readBoundedSync } from "./bounded-read.js";
|
|
4
4
|
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
5
5
|
import { FsSafeError } from "./errors.js";
|
|
6
|
-
import { sameFileIdentity } from "./file-identity.js";
|
|
7
6
|
import { inspectFileIdentity, inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
7
|
+
import { hasErrorCode } from "./file-cleanup.js";
|
|
8
8
|
const OPEN_READ_FLAGS = resolveReadOpenFlags();
|
|
9
9
|
function assertSourcePreview(source, src) {
|
|
10
10
|
if (source.isSymbolicLink()) {
|
|
@@ -18,10 +18,10 @@ function assertSourcePreview(source, src) {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
function assertOpenedSource(opened, current, src) {
|
|
21
|
-
if (!opened.isFile() || current.isSymbolicLink()
|
|
21
|
+
if (!opened.isFile() || current.isSymbolicLink()) {
|
|
22
22
|
throw new FsSafeError("path-mismatch", `Copy fallback source changed while opening: ${src}`);
|
|
23
23
|
}
|
|
24
|
-
if (opened.nlink !==
|
|
24
|
+
if (opened.nlink !== 1n) {
|
|
25
25
|
throw new FsSafeError("hardlink", `Hardlinked copy fallback source not allowed: ${src}`);
|
|
26
26
|
}
|
|
27
27
|
}
|
|
@@ -35,7 +35,7 @@ async function openSource(fsModule, src) {
|
|
|
35
35
|
return await fsModule.open(src, OPEN_READ_FLAGS);
|
|
36
36
|
}
|
|
37
37
|
catch (error) {
|
|
38
|
-
if (error
|
|
38
|
+
if (hasErrorCode(error, "ELOOP")) {
|
|
39
39
|
throw sourceSymlinkError(src, error);
|
|
40
40
|
}
|
|
41
41
|
throw error;
|
|
@@ -46,7 +46,7 @@ function openSourceSync(fsModule, src) {
|
|
|
46
46
|
return fsModule.openSync(src, OPEN_READ_FLAGS);
|
|
47
47
|
}
|
|
48
48
|
catch (error) {
|
|
49
|
-
if (error
|
|
49
|
+
if (hasErrorCode(error, "ELOOP")) {
|
|
50
50
|
throw sourceSymlinkError(src, error);
|
|
51
51
|
}
|
|
52
52
|
throw error;
|
|
@@ -65,34 +65,30 @@ export async function readOwnedCopySource(params) {
|
|
|
65
65
|
? syncFs.lstatSync(params.src) : await params.fsModule.lstat(params.src), params.src);
|
|
66
66
|
const handle = await openSource(params.fsModule, params.src);
|
|
67
67
|
try {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
? syncFs.lstatSync(params.src, { bigint: true }) : params.fsModule.lstat(params.src, { bigint: true }), exact);
|
|
73
|
-
}
|
|
74
|
-
const opened = params.fsModule === fs ? syncFs.fstatSync(handle.fd) : await handle.stat();
|
|
75
|
-
const current = params.fsModule === fs
|
|
76
|
-
? syncFs.lstatSync(params.src) : await params.fsModule.lstat(params.src);
|
|
68
|
+
const opened = await inspectFileIdentity(() => params.fsModule === fs
|
|
69
|
+
? syncFs.fstatSync(handle.fd, { bigint: true }) : handle.stat({ bigint: true }), params.expectedIdentity);
|
|
70
|
+
const current = await inspectFileIdentity(() => params.fsModule === fs
|
|
71
|
+
? syncFs.lstatSync(params.src, { bigint: true }) : params.fsModule.lstat(params.src, { bigint: true }), opened);
|
|
77
72
|
assertOpenedSource(opened, current, params.src);
|
|
78
|
-
return { replacement: await handle.readFile(), mode: opened.mode };
|
|
73
|
+
return { replacement: await handle.readFile(), mode: Number(opened.mode) };
|
|
79
74
|
}
|
|
80
75
|
finally {
|
|
81
|
-
|
|
76
|
+
try {
|
|
77
|
+
await handle.close();
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// Best-effort close includes synchronous adapter throws.
|
|
81
|
+
}
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
export function readOwnedCopySourceSync(params) {
|
|
85
85
|
assertSourcePreview(params.fsModule.lstatSync(params.src), params.src);
|
|
86
86
|
const fd = openSourceSync(params.fsModule, params.src);
|
|
87
87
|
try {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
inspectFileIdentitySync(() => params.fsModule.lstatSync(params.src, { bigint: true }), exact);
|
|
91
|
-
}
|
|
92
|
-
const opened = params.fsModule.fstatSync(fd);
|
|
93
|
-
const current = params.fsModule.lstatSync(params.src);
|
|
88
|
+
const opened = inspectFileIdentitySync(() => params.fsModule.fstatSync(fd, { bigint: true }), params.expectedIdentity);
|
|
89
|
+
const current = inspectFileIdentitySync(() => params.fsModule.lstatSync(params.src, { bigint: true }), opened);
|
|
94
90
|
assertOpenedSource(opened, current, params.src);
|
|
95
|
-
return { replacement: readAllSync(params.fsModule, fd, opened.size), mode: opened.mode };
|
|
91
|
+
return { replacement: readAllSync(params.fsModule, fd, Number(opened.size)), mode: Number(opened.mode) };
|
|
96
92
|
}
|
|
97
93
|
finally {
|
|
98
94
|
try {
|