@openclaw/fs-safe 0.11.0 → 0.13.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 +119 -0
- package/README.md +15 -8
- package/dist/absolute-path.d.ts.map +1 -1
- package/dist/absolute-path.js +32 -11
- package/dist/advanced.d.ts +3 -1
- package/dist/advanced.d.ts.map +1 -1
- package/dist/advanced.js +3 -1
- package/dist/archive-entry.d.ts.map +1 -1
- package/dist/archive-entry.js +4 -3
- package/dist/archive-gzip-tail.d.ts.map +1 -1
- package/dist/archive-gzip-tail.js +13 -9
- package/dist/archive-input.d.ts.map +1 -1
- package/dist/archive-input.js +6 -2
- package/dist/archive-merge.d.ts.map +1 -1
- package/dist/archive-merge.js +15 -2
- package/dist/archive-native.d.ts.map +1 -1
- package/dist/archive-native.js +7 -19
- package/dist/archive-plan.js +1 -1
- package/dist/archive-read.d.ts.map +1 -1
- package/dist/archive-read.js +55 -46
- package/dist/archive-staging.d.ts.map +1 -1
- package/dist/archive-staging.js +43 -10
- package/dist/archive-tar-inspect.d.ts.map +1 -1
- package/dist/archive-tar-inspect.js +4 -1
- package/dist/archive-zip-admission.d.ts +1 -1
- package/dist/archive-zip-admission.d.ts.map +1 -1
- package/dist/archive-zip-admission.js +2 -2
- package/dist/archive-zip-directory.d.ts +3 -0
- package/dist/archive-zip-directory.d.ts.map +1 -1
- package/dist/archive-zip-directory.js +13 -2
- package/dist/archive-zip-loader.d.ts +3 -2
- package/dist/archive-zip-loader.d.ts.map +1 -1
- package/dist/archive-zip-loader.js +30 -4
- package/dist/archive-zip-manifest.d.ts +5 -0
- package/dist/archive-zip-manifest.d.ts.map +1 -0
- package/dist/archive-zip-manifest.js +22 -0
- package/dist/archive-zip-names.d.ts +6 -1
- package/dist/archive-zip-names.d.ts.map +1 -1
- package/dist/archive-zip-names.js +50 -17
- package/dist/archive-zip-preflight.d.ts.map +1 -1
- package/dist/archive-zip-preflight.js +3 -2
- package/dist/archive.d.ts.map +1 -1
- package/dist/archive.js +9 -4
- package/dist/bounded-read.js +2 -2
- package/dist/darwin-acl.d.ts +4 -0
- package/dist/darwin-acl.d.ts.map +1 -0
- package/dist/darwin-acl.js +24 -0
- package/dist/deny-mutations.d.ts.map +1 -1
- package/dist/deny-mutations.js +8 -2
- package/dist/device-path.d.ts.map +1 -1
- package/dist/device-path.js +5 -3
- package/dist/directory-durability.d.ts.map +1 -1
- package/dist/directory-durability.js +67 -23
- package/dist/directory-entry-path.d.ts +3 -0
- package/dist/directory-entry-path.d.ts.map +1 -0
- package/dist/directory-entry-path.js +21 -0
- package/dist/directory-guard.d.ts +17 -1
- package/dist/directory-guard.d.ts.map +1 -1
- package/dist/directory-guard.js +134 -48
- package/dist/directory-mode-node.d.ts +12 -0
- package/dist/directory-mode-node.d.ts.map +1 -1
- package/dist/directory-mode-node.js +102 -4
- package/dist/effective-uid.d.ts +2 -0
- package/dist/effective-uid.d.ts.map +1 -0
- package/dist/effective-uid.js +25 -0
- package/dist/file-handle-transfer.d.ts.map +1 -1
- package/dist/file-handle-transfer.js +98 -27
- package/dist/file-hash.d.ts.map +1 -1
- package/dist/file-hash.js +12 -2
- package/dist/file-lock-sync.d.ts.map +1 -1
- package/dist/file-lock-sync.js +36 -6
- package/dist/file-lock.d.ts.map +1 -1
- package/dist/file-lock.js +29 -9
- package/dist/file-observation.d.ts +1 -1
- package/dist/file-observation.d.ts.map +1 -1
- package/dist/file-store-boundary.d.ts +6 -2
- package/dist/file-store-boundary.d.ts.map +1 -1
- package/dist/file-store-boundary.js +20 -65
- package/dist/file-store-copy-source.d.ts +5 -0
- package/dist/file-store-copy-source.d.ts.map +1 -0
- package/dist/file-store-copy-source.js +31 -0
- package/dist/file-store-path.d.ts.map +1 -1
- package/dist/file-store-path.js +4 -1
- package/dist/file-store-prune.d.ts.map +1 -1
- package/dist/file-store-prune.js +9 -1
- package/dist/file-store-sync-directory.d.ts +16 -0
- package/dist/file-store-sync-directory.d.ts.map +1 -0
- package/dist/file-store-sync-directory.js +349 -0
- package/dist/file-store.d.ts.map +1 -1
- package/dist/file-store.js +11 -28
- package/dist/filename.d.ts +1 -0
- package/dist/filename.d.ts.map +1 -1
- package/dist/filename.js +85 -23
- package/dist/fs.d.ts.map +1 -1
- package/dist/fs.js +3 -2
- package/dist/guarded-mkdir.d.ts +10 -0
- package/dist/guarded-mkdir.d.ts.map +1 -1
- package/dist/guarded-mkdir.js +217 -33
- package/dist/guest.d.ts.map +1 -1
- package/dist/guest.js +16 -5
- package/dist/home-dir.d.ts.map +1 -1
- package/dist/home-dir.js +73 -10
- package/dist/install-path.d.ts +6 -0
- package/dist/install-path.d.ts.map +1 -1
- package/dist/install-path.js +67 -19
- package/dist/json-durable-queue-ownership.d.ts +8 -0
- package/dist/json-durable-queue-ownership.d.ts.map +1 -1
- package/dist/json-durable-queue-ownership.js +134 -43
- package/dist/json-durable-queue-paths.d.ts +11 -0
- package/dist/json-durable-queue-paths.d.ts.map +1 -0
- package/dist/json-durable-queue-paths.js +42 -0
- package/dist/json-durable-queue-read.d.ts +6 -0
- package/dist/json-durable-queue-read.d.ts.map +1 -0
- package/dist/json-durable-queue-read.js +61 -0
- package/dist/json-durable-queue.d.ts +1 -1
- package/dist/json-durable-queue.d.ts.map +1 -1
- package/dist/json-durable-queue.js +83 -134
- package/dist/json-store.d.ts.map +1 -1
- package/dist/json-store.js +5 -1
- package/dist/json.d.ts.map +1 -1
- package/dist/json.js +54 -22
- package/dist/local-file-access.d.ts.map +1 -1
- package/dist/local-file-access.js +4 -0
- package/dist/local-file-descriptor.d.ts +17 -0
- package/dist/local-file-descriptor.d.ts.map +1 -0
- package/dist/local-file-descriptor.js +84 -0
- package/dist/local-roots.d.ts.map +1 -1
- package/dist/local-roots.js +35 -7
- package/dist/move-path-cleanup.d.ts +2 -0
- package/dist/move-path-cleanup.d.ts.map +1 -1
- package/dist/move-path-cleanup.js +44 -18
- package/dist/move-path.d.ts.map +1 -1
- package/dist/move-path.js +31 -6
- package/dist/native-binding.d.ts +21 -0
- package/dist/native-binding.d.ts.map +1 -1
- package/dist/native-directory-observation.d.ts +17 -0
- package/dist/native-directory-observation.d.ts.map +1 -0
- package/dist/native-directory-observation.js +37 -0
- package/dist/native-parent-admission.d.ts +31 -0
- package/dist/native-parent-admission.d.ts.map +1 -0
- package/dist/native-parent-admission.js +124 -0
- package/dist/native-pinned-write-windows.d.ts +0 -1
- package/dist/native-pinned-write-windows.d.ts.map +1 -1
- package/dist/native-pinned-write-windows.js +0 -3
- package/dist/native-pinned-write.d.ts.map +1 -1
- package/dist/native-pinned-write.js +309 -40
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +15 -5
- package/dist/overwrite-file-handle.d.ts.map +1 -1
- package/dist/overwrite-file-handle.js +5 -1
- package/dist/owner-dacl.d.ts.map +1 -1
- package/dist/owner-dacl.js +2 -0
- package/dist/path-policy.d.ts.map +1 -1
- package/dist/path-policy.js +7 -2
- package/dist/path-prefix.d.ts +7 -0
- package/dist/path-prefix.d.ts.map +1 -0
- package/dist/path-prefix.js +82 -0
- package/dist/path-scope-lexical.d.ts +14 -0
- package/dist/path-scope-lexical.d.ts.map +1 -0
- package/dist/path-scope-lexical.js +37 -0
- package/dist/path-segment-route.d.ts +7 -0
- package/dist/path-segment-route.d.ts.map +1 -0
- package/dist/path-segment-route.js +24 -0
- package/dist/path-suffix-aliases.d.ts +10 -0
- package/dist/path-suffix-aliases.d.ts.map +1 -0
- package/dist/path-suffix-aliases.js +386 -0
- package/dist/path.d.ts.map +1 -1
- package/dist/path.js +35 -6
- package/dist/permissions-windows.d.ts.map +1 -1
- package/dist/permissions-windows.js +14 -3
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +37 -8
- package/dist/pinned-mutation-admission.d.ts +25 -0
- package/dist/pinned-mutation-admission.d.ts.map +1 -0
- package/dist/pinned-mutation-admission.js +425 -0
- package/dist/pinned-mutation-observation.d.ts +34 -0
- package/dist/pinned-mutation-observation.d.ts.map +1 -0
- package/dist/pinned-mutation-observation.js +142 -0
- package/dist/pinned-mutation-shared-route.d.ts +24 -0
- package/dist/pinned-mutation-shared-route.d.ts.map +1 -0
- package/dist/pinned-mutation-shared-route.js +70 -0
- package/dist/pinned-open.d.ts +6 -0
- package/dist/pinned-open.d.ts.map +1 -1
- package/dist/pinned-open.js +28 -10
- package/dist/pinned-write-types.d.ts +75 -0
- package/dist/pinned-write-types.d.ts.map +1 -0
- package/dist/pinned-write-types.js +1 -0
- package/dist/pinned-write.d.ts +7 -33
- package/dist/pinned-write.d.ts.map +1 -1
- package/dist/pinned-write.js +152 -17
- package/dist/private-directory.d.ts.map +1 -1
- package/dist/private-directory.js +2 -0
- package/dist/private-producer-handoff.d.ts +16 -0
- package/dist/private-producer-handoff.d.ts.map +1 -0
- package/dist/private-producer-handoff.js +272 -0
- package/dist/private-temp-workspace.d.ts +2 -39
- package/dist/private-temp-workspace.d.ts.map +1 -1
- package/dist/private-temp-workspace.js +183 -77
- package/dist/publish-file.d.ts.map +1 -1
- package/dist/publish-file.js +33 -29
- package/dist/regular-file.d.ts.map +1 -1
- package/dist/regular-file.js +56 -45
- package/dist/replace-directory.d.ts.map +1 -1
- package/dist/replace-directory.js +12 -5
- package/dist/replace-file-temp-owner.d.ts +1 -0
- package/dist/replace-file-temp-owner.d.ts.map +1 -1
- package/dist/replace-file-temp-owner.js +12 -1
- package/dist/replace-file.d.ts.map +1 -1
- package/dist/replace-file.js +24 -24
- package/dist/root-boundary.d.ts +29 -0
- package/dist/root-boundary.d.ts.map +1 -0
- package/dist/root-boundary.js +182 -0
- package/dist/root-context.d.ts +12 -1
- package/dist/root-context.d.ts.map +1 -1
- package/dist/root-context.js +89 -16
- package/dist/root-directory-creation.d.ts +13 -0
- package/dist/root-directory-creation.d.ts.map +1 -0
- package/dist/root-directory-creation.js +212 -0
- package/dist/root-directory-list.d.ts +16 -4
- package/dist/root-directory-list.d.ts.map +1 -1
- package/dist/root-directory-list.js +182 -33
- package/dist/root-directory.d.ts +23 -0
- package/dist/root-directory.d.ts.map +1 -0
- package/dist/root-directory.js +141 -0
- package/dist/root-errors.d.ts.map +1 -1
- package/dist/root-errors.js +12 -1
- package/dist/root-file-final-admission.d.ts +21 -0
- package/dist/root-file-final-admission.d.ts.map +1 -0
- package/dist/root-file-final-admission.js +83 -0
- package/dist/root-file.d.ts.map +1 -1
- package/dist/root-file.js +103 -24
- package/dist/root-impl.d.ts +1 -0
- package/dist/root-impl.d.ts.map +1 -1
- package/dist/root-impl.js +316 -325
- package/dist/root-move-noreplace.d.ts +14 -0
- package/dist/root-move-noreplace.d.ts.map +1 -0
- package/dist/root-move-noreplace.js +202 -0
- package/dist/root-move-preflight.d.ts +8 -0
- package/dist/root-move-preflight.d.ts.map +1 -0
- package/dist/root-move-preflight.js +16 -0
- package/dist/root-observed-path.d.ts +9 -0
- package/dist/root-observed-path.d.ts.map +1 -0
- package/dist/root-observed-path.js +95 -0
- package/dist/root-path-errors.d.ts +12 -0
- package/dist/root-path-errors.d.ts.map +1 -0
- package/dist/root-path-errors.js +13 -0
- package/dist/root-path-existing.d.ts +2 -0
- package/dist/root-path-existing.d.ts.map +1 -1
- package/dist/root-path-existing.js +63 -22
- package/dist/root-path-observation.d.ts +63 -0
- package/dist/root-path-observation.d.ts.map +1 -0
- package/dist/root-path-observation.js +180 -0
- package/dist/root-path-stat.d.ts +5 -0
- package/dist/root-path-stat.d.ts.map +1 -0
- package/dist/root-path-stat.js +101 -0
- package/dist/root-path-symlink.d.ts.map +1 -1
- package/dist/root-path-symlink.js +23 -4
- package/dist/root-path.d.ts +13 -0
- package/dist/root-path.d.ts.map +1 -1
- package/dist/root-path.js +263 -73
- package/dist/root-paths-lexical.d.ts +9 -0
- package/dist/root-paths-lexical.d.ts.map +1 -0
- package/dist/root-paths-lexical.js +22 -0
- package/dist/root-paths.d.ts +3 -29
- package/dist/root-paths.d.ts.map +1 -1
- package/dist/root-paths.js +89 -178
- package/dist/root-read-admission.d.ts +26 -0
- package/dist/root-read-admission.d.ts.map +1 -0
- package/dist/root-read-admission.js +94 -0
- package/dist/root-remove-identity.d.ts +15 -0
- package/dist/root-remove-identity.d.ts.map +1 -0
- package/dist/root-remove-identity.js +89 -0
- package/dist/root-remove-receipt.d.ts +17 -0
- package/dist/root-remove-receipt.d.ts.map +1 -0
- package/dist/root-remove-receipt.js +37 -0
- package/dist/root-remove.d.ts +2 -1
- package/dist/root-remove.d.ts.map +1 -1
- package/dist/root-remove.js +172 -10
- package/dist/root-walk.d.ts.map +1 -1
- package/dist/root-walk.js +2 -1
- package/dist/root-write-admission.d.ts +68 -0
- package/dist/root-write-admission.d.ts.map +1 -0
- package/dist/root-write-admission.js +322 -0
- package/dist/root-write-compatibility.d.ts +13 -0
- package/dist/root-write-compatibility.d.ts.map +1 -0
- package/dist/root-write-compatibility.js +74 -0
- package/dist/root-write-complete-parent.d.ts +42 -0
- package/dist/root-write-complete-parent.d.ts.map +1 -0
- package/dist/root-write-complete-parent.js +195 -0
- package/dist/root-write-mode.d.ts +2 -0
- package/dist/root-write-mode.d.ts.map +1 -1
- package/dist/root-write-mode.js +20 -7
- package/dist/root-write-publication.d.ts +24 -0
- package/dist/root-write-publication.d.ts.map +1 -0
- package/dist/root-write-publication.js +85 -0
- package/dist/root-write-verification.d.ts.map +1 -1
- package/dist/root-write-verification.js +18 -7
- package/dist/safe-path-segment.d.ts.map +1 -1
- package/dist/safe-path-segment.js +3 -1
- package/dist/secret-file.d.ts.map +1 -1
- package/dist/secret-file.js +62 -24
- package/dist/secret-read-async.d.ts.map +1 -1
- package/dist/secret-read-async.js +18 -13
- package/dist/secret-read-policy.d.ts.map +1 -1
- package/dist/secret-read-policy.js +5 -1
- package/dist/secure-file-windows.d.ts +10 -0
- package/dist/secure-file-windows.d.ts.map +1 -0
- package/dist/secure-file-windows.js +186 -0
- package/dist/secure-file.d.ts.map +1 -1
- package/dist/secure-file.js +98 -10
- package/dist/secure-temp-dir.d.ts +6 -3
- package/dist/secure-temp-dir.d.ts.map +1 -1
- package/dist/secure-temp-dir.js +121 -101
- package/dist/secure-temp-repair.d.ts +35 -0
- package/dist/secure-temp-repair.d.ts.map +1 -0
- package/dist/secure-temp-repair.js +106 -0
- package/dist/sibling-staged-file.d.ts +3 -1
- package/dist/sibling-staged-file.d.ts.map +1 -1
- package/dist/sibling-staged-file.js +181 -50
- package/dist/sibling-temp.d.ts.map +1 -1
- package/dist/sibling-temp.js +27 -12
- package/dist/sidecar-lock-acquire.d.ts.map +1 -1
- package/dist/sidecar-lock-acquire.js +45 -15
- package/dist/sidecar-lock-root.d.ts.map +1 -1
- package/dist/sidecar-lock-root.js +4 -2
- package/dist/sidecar-lock.d.ts.map +1 -1
- package/dist/sidecar-lock.js +2 -3
- package/dist/staged-directory.d.ts +14 -5
- package/dist/staged-directory.d.ts.map +1 -1
- package/dist/staged-directory.js +54 -3
- package/dist/standalone-publication-path.d.ts +2 -0
- package/dist/standalone-publication-path.d.ts.map +1 -0
- package/dist/standalone-publication-path.js +6 -0
- package/dist/stat-observation.d.ts +11 -0
- package/dist/stat-observation.d.ts.map +1 -0
- package/dist/stat-observation.js +64 -0
- package/dist/strict-file-identity.d.ts.map +1 -1
- package/dist/strict-file-identity.js +39 -2
- package/dist/symlink-parents.d.ts.map +1 -1
- package/dist/symlink-parents.js +7 -2
- package/dist/temp-target.d.ts +2 -0
- package/dist/temp-target.d.ts.map +1 -1
- package/dist/temp-target.js +133 -4
- package/dist/temp-workspace-admission.d.ts +22 -0
- package/dist/temp-workspace-admission.d.ts.map +1 -0
- package/dist/temp-workspace-admission.js +374 -0
- package/dist/temp-workspace-child-admission.d.ts +13 -0
- package/dist/temp-workspace-child-admission.d.ts.map +1 -0
- package/dist/temp-workspace-child-admission.js +95 -0
- package/dist/temp-workspace-descriptor.d.ts +48 -0
- package/dist/temp-workspace-descriptor.d.ts.map +1 -0
- package/dist/temp-workspace-descriptor.js +363 -0
- package/dist/temp-workspace-identity.d.ts +15 -0
- package/dist/temp-workspace-identity.d.ts.map +1 -0
- package/dist/temp-workspace-identity.js +41 -0
- package/dist/temp-workspace-owner.d.ts +7 -6
- package/dist/temp-workspace-owner.d.ts.map +1 -1
- package/dist/temp-workspace-owner.js +121 -61
- package/dist/temp-workspace-permissions.d.ts +4 -0
- package/dist/temp-workspace-permissions.d.ts.map +1 -0
- package/dist/temp-workspace-permissions.js +32 -0
- package/dist/temp-workspace-types.d.ts +40 -0
- package/dist/temp-workspace-types.d.ts.map +1 -0
- package/dist/temp-workspace-types.js +1 -0
- package/dist/temp.d.ts +1 -1
- package/dist/temp.d.ts.map +1 -1
- package/dist/temp.js +1 -1
- package/dist/test-hooks.d.ts +7 -0
- package/dist/test-hooks.d.ts.map +1 -1
- package/dist/text-atomic.d.ts.map +1 -1
- package/dist/text-atomic.js +3 -1
- package/dist/trash.d.ts.map +1 -1
- package/dist/trash.js +54 -8
- package/dist/walk.d.ts.map +1 -1
- package/dist/walk.js +20 -16
- package/dist/windows-owner.d.ts.map +1 -1
- package/dist/windows-owner.js +5 -0
- package/dist/windows-path-alias.d.ts +39 -0
- package/dist/windows-path-alias.d.ts.map +1 -0
- package/dist/windows-path-alias.js +153 -0
- package/docs/advanced.md +28 -1
- package/docs/archive.md +29 -2
- package/docs/atomic.md +27 -3
- package/docs/contributing.md +4 -1
- package/docs/copy.md +4 -1
- package/docs/durability.md +18 -2
- package/docs/errors.md +14 -6
- package/docs/file-store.md +30 -3
- package/docs/filename.md +21 -7
- package/docs/guest.md +5 -0
- package/docs/install-path.md +61 -15
- package/docs/install.md +12 -8
- package/docs/json-store.md +5 -1
- package/docs/json.md +11 -0
- package/docs/mutation-policy-proof.md +65 -0
- package/docs/native-helper.md +28 -9
- package/docs/native.md +46 -10
- package/docs/output.md +33 -11
- package/docs/path-prefix.md +64 -0
- package/docs/path-suffix-aliases.md +159 -0
- package/docs/path.md +12 -1
- package/docs/permissions.md +26 -1
- package/docs/private-file-store.md +14 -0
- package/docs/public-api.md +14 -0
- package/docs/quickstart.md +1 -1
- package/docs/reading.md +8 -1
- package/docs/root.md +21 -4
- package/docs/secret-file.md +3 -0
- package/docs/secure-file.md +21 -16
- package/docs/security-model.md +76 -9
- package/docs/sidecar-lock.md +28 -1
- package/docs/store.md +27 -2
- package/docs/temp.md +262 -34
- package/docs/test-hooks.md +14 -0
- package/docs/writing.md +38 -8
- package/package.json +10 -10
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { types } from "node:util";
|
|
1
2
|
import { ArchiveFormatError, ArchiveSecurityError } from "./archive-errors.js";
|
|
2
3
|
import { stripArchivePath, validateArchiveEntryPath } from "./archive-entry.js";
|
|
3
4
|
import { updateCrc32 } from "./archive-crc32.js";
|
|
@@ -40,7 +41,10 @@ function utf8(bytes) {
|
|
|
40
41
|
return zipFormat("invalid UTF-8 name");
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
|
-
|
|
44
|
+
// Canonical identity only; this does not replace raw path validation.
|
|
45
|
+
export function zipPathKey(name) {
|
|
46
|
+
if (name && name !== "." && !name.includes("/") && !name.includes("\\"))
|
|
47
|
+
return name;
|
|
44
48
|
return stripArchivePath(name, 0) ?? "";
|
|
45
49
|
}
|
|
46
50
|
function originalName(name, rawName, flags) {
|
|
@@ -69,37 +73,66 @@ export function admitZipNames(params) {
|
|
|
69
73
|
const { central, local, flags, centralExtra, localExtra, seen } = params;
|
|
70
74
|
if (!central.length || !local.length)
|
|
71
75
|
zipFormat("empty entry name");
|
|
76
|
+
// Reuse only within this synchronous call; shared backing bytes can change
|
|
77
|
+
// concurrently even though admission does not yield while checking names.
|
|
78
|
+
const sameName = !types.isSharedArrayBuffer(central.buffer) &&
|
|
79
|
+
!types.isSharedArrayBuffer(local.buffer) && central.equals(local);
|
|
72
80
|
const centralRaw = central.toString("latin1");
|
|
73
|
-
const localRaw = local.toString("latin1");
|
|
81
|
+
const localRaw = sameName ? centralRaw : local.toString("latin1");
|
|
74
82
|
const centralUtf8 = originalName(central, centralRaw, flags);
|
|
75
|
-
const localUtf8 = originalName(local, localRaw, flags);
|
|
83
|
+
const localUtf8 = sameName ? centralUtf8 : originalName(local, localRaw, flags);
|
|
76
84
|
const centralUnicode = unicodeName(central, centralExtra);
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
|
|
85
|
+
const centralField = centralExtra.get(0x7075);
|
|
86
|
+
const localField = localExtra.get(0x7075);
|
|
87
|
+
// Only immutable identical fields share their CRC-bound name admission.
|
|
88
|
+
const sameUnicode = (!centralField || !types.isSharedArrayBuffer(centralField.buffer)) &&
|
|
89
|
+
(!localField || !types.isSharedArrayBuffer(localField.buffer)) &&
|
|
90
|
+
(centralField === localField ||
|
|
91
|
+
(centralField !== undefined && localField !== undefined && centralField.equals(localField)));
|
|
92
|
+
const localUnicode = sameName && sameUnicode ? centralUnicode : unicodeName(local, localExtra);
|
|
93
|
+
const centralKey = zipPathKey(centralRaw);
|
|
94
|
+
if (!sameName && centralKey !== zipPathKey(localRaw)) {
|
|
80
95
|
zipFormat("central and local names disagree");
|
|
81
96
|
}
|
|
82
97
|
const interpretations = [centralUtf8, localUtf8, centralUnicode, localUnicode].filter((value) => value !== undefined);
|
|
83
|
-
|
|
84
|
-
|
|
98
|
+
// Canonical paths erase terminal separators. Preserve their kind meaning in
|
|
99
|
+
// every interpretation, including Unicode overrides of legacy-encoded names.
|
|
100
|
+
const directory = /[/\\]$/.test(centralRaw);
|
|
101
|
+
if (/[/\\]$/.test(localRaw) !== directory ||
|
|
102
|
+
interpretations.some((value) => /[/\\]$/.test(value) !== directory)) {
|
|
103
|
+
zipFormat("conflicting terminal directory markers");
|
|
104
|
+
}
|
|
105
|
+
const interpretationKey = interpretations.length ? zipPathKey(interpretations[0]) : undefined;
|
|
106
|
+
if (interpretations.some((value) => value !== interpretations[0] && zipPathKey(value) !== interpretationKey)) {
|
|
85
107
|
zipFormat("conflicting Unicode name interpretations");
|
|
86
108
|
}
|
|
87
109
|
// JSZip checks the central Unicode field against the local name. A slash-only
|
|
88
110
|
// spelling difference must not make one decoder ignore a meaningful override.
|
|
89
111
|
if (centralUnicode && !central.equals(local) &&
|
|
90
|
-
|
|
112
|
+
zipPathKey(centralUnicode) !== zipPathKey(local.toString("utf8"))) {
|
|
91
113
|
zipFormat("Unicode override disagrees with local decoder name");
|
|
92
114
|
}
|
|
93
|
-
if (!centralUnicode && localUnicode &&
|
|
115
|
+
if (!centralUnicode && localUnicode && zipPathKey(localUnicode) !== zipPathKey(local.toString("utf8"))) {
|
|
94
116
|
zipFormat("local-only Unicode override changes the name");
|
|
95
117
|
}
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
118
|
+
const unicodeKey = centralUnicode === undefined
|
|
119
|
+
? undefined : zipPathKey(Buffer.from(centralUnicode).toString("latin1"));
|
|
120
|
+
if (seen.has(centralKey) ||
|
|
121
|
+
(unicodeKey !== undefined && unicodeKey !== centralKey && seen.has(unicodeKey))) {
|
|
100
122
|
throw new ArchiveSecurityError("entry-path", "zip archive contains duplicate or colliding entry names");
|
|
101
123
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
124
|
+
seen.add(centralKey);
|
|
125
|
+
if (unicodeKey !== undefined && unicodeKey !== centralKey)
|
|
126
|
+
seen.add(unicodeKey);
|
|
127
|
+
const path = centralUnicode ?? centralUtf8 ?? (central.every((byte) => byte < 128) ? central.toString("ascii") : undefined);
|
|
128
|
+
const portablePath = centralUnicode ?? localUtf8 ?? (sameName && path !== undefined ? path : local.toString("utf8"));
|
|
129
|
+
// Reuse the admitted interpretation, never the Latin-1 Unicode collision key.
|
|
130
|
+
// Unflagged legacy names can decode differently and need their own key.
|
|
131
|
+
const portableKey = portablePath === centralRaw ? centralKey
|
|
132
|
+
: interpretations.includes(portablePath) ? interpretationKey : zipPathKey(portablePath);
|
|
133
|
+
return {
|
|
134
|
+
path,
|
|
135
|
+
portableKey,
|
|
136
|
+
directory,
|
|
137
|
+
};
|
|
105
138
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive-zip-preflight.d.ts","sourceRoot":"","sources":["../src/archive-zip-preflight.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAA0B,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"archive-zip-preflight.d.ts","sourceRoot":"","sources":["../src/archive-zip-preflight.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAA0B,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE3F,OAAO,EAAE,iCAAiC,EAAE,MAAM,wBAAwB,CAAC;AAC3E,YAAY,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAEnE,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,MAAM,GAAG,UAAU,EAC3B,MAAM,CAAC,EAAE,oBAAoB,GAC5B,OAAO,CAAC,mBAAmB,CAAC,CAQ9B"}
|
|
@@ -7,6 +7,7 @@ export async function loadZipArchiveWithPreflight(buffer, limits) {
|
|
|
7
7
|
if (buffer.byteLength > resolvedLimits.maxArchiveBytes) {
|
|
8
8
|
throw new ArchiveLimitError(ARCHIVE_LIMIT_ERROR_CODE.ARCHIVE_SIZE_EXCEEDS_LIMIT);
|
|
9
9
|
}
|
|
10
|
-
const
|
|
11
|
-
|
|
10
|
+
const entries = [];
|
|
11
|
+
admitZipBuffer(buffer, resolvedLimits, entry => { entries.push(entry); });
|
|
12
|
+
return await loadAdmittedZipArchive(buffer, entries);
|
|
12
13
|
}
|
package/dist/archive.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../src/archive.ts"],"names":[],"mappings":"AA4DA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../src/archive.ts"],"names":[],"mappings":"AA4DA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAIlE,YAAY,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AACjF,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,wBAAwB,EACxB,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC/F,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,KAAK,wBAAwB,EAAE,KAAK,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACpH,OAAO,EACL,wBAAwB,EACxB,iBAAiB,EACjB,6BAA6B,EAC7B,mBAAmB,EACnB,2BAA2B,EAC3B,uBAAuB,EACvB,4BAA4B,EAC5B,iCAAiC,EACjC,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,KAAK,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AACtF,OAAO,EAAE,oBAAoB,EAAE,KAAK,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAC3F,OAAO,EACL,kCAAkC,EAClC,iCAAiC,EACjC,4BAA4B,EAC5B,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,8BAA8B,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrF,OAAO,EACL,2BAA2B,EAC3B,iCAAiC,EACjC,KAAK,mBAAmB,GACzB,MAAM,4BAA4B,CAAC;AAiNpC,wBAAsB,cAAc,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiDjF"}
|
package/dist/archive.js
CHANGED
|
@@ -22,6 +22,7 @@ import { stageArchiveFileForExtraction } from "./archive-input.js";
|
|
|
22
22
|
import { getNativeBinding } from "./native.js";
|
|
23
23
|
import { resolveArchiveFilteredEntryPolicy, shouldExtractArchiveEntry, } from "./archive-policy.js";
|
|
24
24
|
import { writeSiblingTempFile } from "./sibling-temp.js";
|
|
25
|
+
import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
|
|
25
26
|
import { realpathSync } from "./realpath.js";
|
|
26
27
|
export { isWindowsDrivePath, normalizeArchiveEntryPath, resolveArchiveOutputPath, stripArchivePath, validateArchiveEntryPath, } from "./archive-entry.js";
|
|
27
28
|
export { resolveArchiveKind, resolvePackedRootDir } from "./archive-kind.js";
|
|
@@ -51,7 +52,7 @@ function resolveZipOutputPath(params) {
|
|
|
51
52
|
const canonicalPath = stripArchivePath(params.entryPath, 0);
|
|
52
53
|
if (!canonicalPath)
|
|
53
54
|
return null;
|
|
54
|
-
const relPath = stripArchivePath(canonicalPath, params.strip);
|
|
55
|
+
const relPath = params.strip === 0 ? canonicalPath : stripArchivePath(canonicalPath, params.strip);
|
|
55
56
|
if (!relPath) {
|
|
56
57
|
return null;
|
|
57
58
|
}
|
|
@@ -203,19 +204,23 @@ async function extractZip(params) {
|
|
|
203
204
|
}
|
|
204
205
|
}
|
|
205
206
|
export async function extractArchive(params) {
|
|
207
|
+
const archivePath = params.archivePath;
|
|
208
|
+
const destDir = params.destDir;
|
|
206
209
|
const onFiltered = resolveArchiveFilteredEntryPolicy(params.onFiltered);
|
|
207
|
-
const kind = params.kind ?? resolveArchiveKind(
|
|
210
|
+
const kind = params.kind ?? resolveArchiveKind(archivePath);
|
|
208
211
|
if (!kind) {
|
|
209
|
-
throw new Error(`unsupported archive: ${
|
|
212
|
+
throw new Error(`unsupported archive: ${archivePath}`);
|
|
210
213
|
}
|
|
211
214
|
const label = kind === "zip" ? "extract zip" : "extract tar";
|
|
212
215
|
const limits = resolveExtractLimits(params.limits);
|
|
213
216
|
const tarLimits = resolveTarMeterLimits(limits);
|
|
214
217
|
const native = getNativeBinding();
|
|
218
|
+
assertNoWindowsPathAlias(archivePath, "filesystem", "archive source uses a Windows filesystem namespace alias");
|
|
219
|
+
assertNoWindowsPathAlias(destDir, "filesystem", "archive destination uses a Windows filesystem namespace alias");
|
|
215
220
|
// Read the declared public fields before private adapters copy options: class
|
|
216
221
|
// getters and inherited policy must survive identically on every backend.
|
|
217
222
|
const options = {
|
|
218
|
-
archivePath
|
|
223
|
+
archivePath, destDir,
|
|
219
224
|
durable: params.durable,
|
|
220
225
|
stripComponents: params.stripComponents, limits,
|
|
221
226
|
entryModes: params.entryModes, entryFilter: params.entryFilter, onFiltered,
|
package/dist/bounded-read.js
CHANGED
|
@@ -54,7 +54,7 @@ export async function readBoundedAsync(maxBytes, readChunk, options = {}) {
|
|
|
54
54
|
// initial read; virtual files can report zero or stale sizes thereafter.
|
|
55
55
|
const currentSize = bytesRead < buffer.length ? observeRegularFileSize?.() : undefined;
|
|
56
56
|
total = addReadBytes(total, bytesRead, maxBytes, createLimitError);
|
|
57
|
-
if (currentSize !== undefined && bytesRead >= currentSize)
|
|
57
|
+
if (currentSize !== undefined && currentSize > 0 && bytesRead >= currentSize)
|
|
58
58
|
return finishReadBuffer(buffer, total, allocate);
|
|
59
59
|
}
|
|
60
60
|
while (true) {
|
|
@@ -120,7 +120,7 @@ export function readBoundedSync(maxBytes, readChunk, options = {}) {
|
|
|
120
120
|
return finishReadBuffer(buffer, 0);
|
|
121
121
|
const currentSize = bytesRead < buffer.length ? observeRegularFileSize?.() : undefined;
|
|
122
122
|
total = addReadBytes(total, bytesRead, maxBytes, createLimitError);
|
|
123
|
-
if (currentSize !== undefined && bytesRead >= currentSize)
|
|
123
|
+
if (currentSize !== undefined && currentSize > 0 && bytesRead >= currentSize)
|
|
124
124
|
return finishReadBuffer(buffer, total);
|
|
125
125
|
}
|
|
126
126
|
while (true) {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { NativeDarwinAclFacts } from "./native-binding.js";
|
|
2
|
+
/** Internal descriptor facts only; callers own identity, lifetime, and ACL policy. */
|
|
3
|
+
export declare function inspectDarwinAcl(fd: number): NativeDarwinAclFacts;
|
|
4
|
+
//# sourceMappingURL=darwin-acl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"darwin-acl.d.ts","sourceRoot":"","sources":["../src/darwin-acl.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAGhE,sFAAsF;AACtF,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,oBAAoB,CAmBjE"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { FsSafeError } from "./errors.js";
|
|
2
|
+
import { getNativeBinding } from "./native.js";
|
|
3
|
+
/** Internal descriptor facts only; callers own identity, lifetime, and ACL policy. */
|
|
4
|
+
export function inspectDarwinAcl(fd) {
|
|
5
|
+
if (!Number.isInteger(fd) || fd < 0 || fd > 0x7fff_ffff) {
|
|
6
|
+
throw new FsSafeError("permission-unverified", "Darwin ACL inspection requires a valid descriptor");
|
|
7
|
+
}
|
|
8
|
+
const native = getNativeBinding();
|
|
9
|
+
if (typeof native?.inspectDarwinAcl !== "function") {
|
|
10
|
+
throw new FsSafeError("helper-unavailable", "Darwin ACL inspection requires the matching native capability");
|
|
11
|
+
}
|
|
12
|
+
let facts;
|
|
13
|
+
try {
|
|
14
|
+
facts = native.inspectDarwinAcl(fd);
|
|
15
|
+
}
|
|
16
|
+
catch (cause) {
|
|
17
|
+
throw new FsSafeError("permission-unverified", "Darwin descriptor ACL could not be inspected", { cause });
|
|
18
|
+
}
|
|
19
|
+
const state = facts && typeof facts === "object" && "state" in facts ? facts.state : undefined;
|
|
20
|
+
if (state !== "absent" && state !== "empty" && state !== "present") {
|
|
21
|
+
throw new FsSafeError("permission-unverified", "Darwin ACL inspection returned invalid facts");
|
|
22
|
+
}
|
|
23
|
+
return { state };
|
|
24
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deny-mutations.d.ts","sourceRoot":"","sources":["../src/deny-mutations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"deny-mutations.d.ts","sourceRoot":"","sources":["../src/deny-mutations.ts"],"names":[],"mappings":"AASA,wBAAsB,8BAA8B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAQ1F;AAMD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B,CAAC;AAEF,KAAK,wBAAwB,GAAG;IAC9B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAsBF,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,kBAAkB,GAAG,SAAS,EACtC,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,IAAI,CAAC,CAiCf;AAED,wBAAgB,yBAAyB,CACvC,aAAa,EAAE,kBAAkB,GAAG,SAAS,EAC7C,UAAU,EAAE,kBAAkB,GAAG,SAAS,GACzC,kBAAkB,GAAG,SAAS,CAWhC"}
|
package/dist/deny-mutations.js
CHANGED
|
@@ -2,10 +2,15 @@ import path from "node:path";
|
|
|
2
2
|
import { FsSafeError } from "./errors.js";
|
|
3
3
|
import { assertNoNulPathInput, isPathInside } from "./path.js";
|
|
4
4
|
import { resolvePathViaExistingAncestor } from "./root-path-existing.js";
|
|
5
|
+
import { assertNoWindowsPathAlias, resolvePathPreservingWindowsRoot, } from "./windows-path-alias.js";
|
|
5
6
|
export async function resolveMutationComparablePaths(rawPath) {
|
|
6
7
|
assertNoNulPathInput(rawPath, "path contains a NUL byte");
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
assertNoWindowsPathAlias(rawPath, "filesystem", "mutation path uses a Windows filesystem namespace alias");
|
|
9
|
+
const resolved = resolvePathPreservingWindowsRoot(rawPath);
|
|
10
|
+
assertNoWindowsPathAlias(resolved, "filesystem", "mutation path uses a Windows filesystem namespace alias");
|
|
11
|
+
const canonical = await resolvePathViaExistingAncestor(resolved);
|
|
12
|
+
assertNoWindowsPathAlias(canonical, "filesystem", "mutation path uses a Windows filesystem namespace alias");
|
|
13
|
+
return new Set([resolved, canonical]);
|
|
9
14
|
}
|
|
10
15
|
function isSamePath(left, right) {
|
|
11
16
|
return isPathInside(left, right) && isPathInside(right, left);
|
|
@@ -20,6 +25,7 @@ function policyPathEntries(entries) {
|
|
|
20
25
|
throw new FsSafeError("invalid-path", "deny mutation paths must be non-empty");
|
|
21
26
|
}
|
|
22
27
|
assertNoNulPathInput(entry, "deny mutation path contains a NUL byte");
|
|
28
|
+
assertNoWindowsPathAlias(entry, "filesystem", "deny mutation path uses a Windows filesystem namespace alias");
|
|
23
29
|
if (!path.isAbsolute(entry)) {
|
|
24
30
|
throw new FsSafeError("invalid-path", "deny mutation paths must be absolute");
|
|
25
31
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-path.d.ts","sourceRoot":"","sources":["../src/device-path.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,0BAA0B,GAClC,cAAc,GACd,UAAU,GACV,gBAAgB,CAAC;AAErB,MAAM,MAAM,yBAAyB,GAAG;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,0BAA0B,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;CAC5B,CAAC;AAcF,eAAO,MAAM,6BAA6B,EAAE,WAAW,CAAC,MAAM,CAgC5D,CAAC;
|
|
1
|
+
{"version":3,"file":"device-path.d.ts","sourceRoot":"","sources":["../src/device-path.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,0BAA0B,GAClC,cAAc,GACd,UAAU,GACV,gBAAgB,CAAC;AAErB,MAAM,MAAM,yBAAyB,GAAG;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,0BAA0B,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;CAC5B,CAAC;AAcF,eAAO,MAAM,6BAA6B,EAAE,WAAW,CAAC,MAAM,CAgC5D,CAAC;AA2EH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjE;AAcD,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,2BAAgC,GACxC,yBAAyB,GAAG,SAAS,CAWvC;AAED,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,2BAA2B,GACpC,OAAO,CAET;AAED,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,2BAA2B,GACpC,IAAI,CAON"}
|
package/dist/device-path.js
CHANGED
|
@@ -96,9 +96,11 @@ function matchPosixDeviceReadPath(filePath, cwd) {
|
|
|
96
96
|
}
|
|
97
97
|
function normalizeWindowsDeviceBaseName(filePath) {
|
|
98
98
|
const normalized = trimTrailingWindowsSeparators(filePath.replace(/\//g, "\\"));
|
|
99
|
-
const
|
|
100
|
-
const
|
|
101
|
-
const
|
|
99
|
+
const start = normalized.lastIndexOf("\\") + 1;
|
|
100
|
+
const stream = normalized.indexOf(":", start);
|
|
101
|
+
const extension = normalized.indexOf(".", start);
|
|
102
|
+
const end = Math.min(stream < 0 ? normalized.length : stream, extension < 0 ? normalized.length : extension);
|
|
103
|
+
const stem = normalized.slice(start, end);
|
|
102
104
|
return trimTrailingWindowsIgnoredChars(stem).toUpperCase();
|
|
103
105
|
}
|
|
104
106
|
export function isWindowsReservedDeviceName(name) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"directory-durability.d.ts","sourceRoot":"","sources":["../src/directory-durability.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAM7C,OAAO,EAAoB,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"directory-durability.d.ts","sourceRoot":"","sources":["../src/directory-durability.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAM7C,OAAO,EAAoB,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAI7E,MAAM,MAAM,oBAAoB,GAC5B;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,GACpB;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7C,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,KAAK,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,gBAAgB,GAAG;IACvD,UAAU,EAAE,oBAAoB,GAAG;QAAE,MAAM,EAAE,YAAY,CAAA;KAAE,CAAC;CAC7D,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;IACnC,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACtC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wBAAwB,CAAC,EAAE,gBAAgB,CAAC;IAC5C,MAAM,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD,CAAC;AAwOF,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,GAAG,gBAAgB,EACpC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,OAAO,CAAC,eAAe,CAAC,CAe1B;AAED,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,GAAG,gBAAgB,EACpC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,OAAO,CAAC,oBAAoB,CAAC,CAqB/B;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,GAAG,gBAAgB,EACpC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,oBAAoB,CAyCtB;AAED,wBAAsB,uBAAuB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAElF;AAED,wBAAgB,2BAA2B,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAMvE;AAiCD,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,uBAAuB,CAAC,CA2FlC"}
|
|
@@ -4,6 +4,7 @@ import path from "node:path";
|
|
|
4
4
|
import { ensureAbsoluteDirectory } from "./absolute-path.js";
|
|
5
5
|
import { FsSafeError } from "./errors.js";
|
|
6
6
|
import { sameFileIdentity } from "./file-identity.js";
|
|
7
|
+
import { assertNoWindowsPathAlias, pathForWindowsFilesystem, resolvePathPreservingWindowsRoot } from "./windows-path-alias.js";
|
|
7
8
|
import { realpathSync } from "./realpath.js";
|
|
8
9
|
function directoryOpenFlags() {
|
|
9
10
|
if (process.platform === "win32") {
|
|
@@ -42,39 +43,67 @@ function assertDirectory(identity, pathname, label) {
|
|
|
42
43
|
throw new FsSafeError("not-file", `${label} must be a real directory: ${pathname}`);
|
|
43
44
|
}
|
|
44
45
|
}
|
|
46
|
+
function ownDirectoryReceipt(receipt) {
|
|
47
|
+
const pathname = receipt.path;
|
|
48
|
+
const realPath = receipt.realPath;
|
|
49
|
+
const identity = receipt.identity;
|
|
50
|
+
return { path: pathname, realPath, identity };
|
|
51
|
+
}
|
|
52
|
+
function assertDirectoryReceiptPaths(receipt, label) {
|
|
53
|
+
assertNoWindowsPathAlias(receipt.path, "filesystem", `${label} path uses a Windows filesystem namespace alias`);
|
|
54
|
+
assertNoWindowsPathAlias(receipt.realPath, "filesystem", `${label} real path uses a Windows filesystem namespace alias`);
|
|
55
|
+
}
|
|
45
56
|
async function createDirectoryReceipt(directoryPath, label) {
|
|
46
|
-
|
|
47
|
-
const
|
|
57
|
+
assertNoWindowsPathAlias(directoryPath, "filesystem", `${label} path uses a Windows filesystem namespace alias`);
|
|
58
|
+
const resolvedPath = resolvePathPreservingWindowsRoot(directoryPath);
|
|
59
|
+
assertNoWindowsPathAlias(resolvedPath, "filesystem", `${label} path uses a Windows filesystem namespace alias`);
|
|
60
|
+
const operationPath = pathForWindowsFilesystem(resolvedPath);
|
|
61
|
+
const identity = fsSync.lstatSync(operationPath);
|
|
48
62
|
assertDirectory(identity, resolvedPath, label);
|
|
63
|
+
const realPath = realpathSync.native(operationPath);
|
|
64
|
+
assertNoWindowsPathAlias(realPath, "filesystem", `${label} real path uses a Windows filesystem namespace alias`);
|
|
49
65
|
return {
|
|
50
66
|
path: resolvedPath,
|
|
51
|
-
realPath
|
|
67
|
+
realPath,
|
|
52
68
|
identity,
|
|
53
69
|
};
|
|
54
70
|
}
|
|
55
71
|
function createDirectoryReceiptSync(directoryPath, label) {
|
|
56
|
-
|
|
57
|
-
const
|
|
72
|
+
assertNoWindowsPathAlias(directoryPath, "filesystem", `${label} path uses a Windows filesystem namespace alias`);
|
|
73
|
+
const resolvedPath = resolvePathPreservingWindowsRoot(directoryPath);
|
|
74
|
+
assertNoWindowsPathAlias(resolvedPath, "filesystem", `${label} path uses a Windows filesystem namespace alias`);
|
|
75
|
+
const operationPath = pathForWindowsFilesystem(resolvedPath);
|
|
76
|
+
const identity = fsSync.lstatSync(operationPath);
|
|
58
77
|
assertDirectory(identity, resolvedPath, label);
|
|
78
|
+
const realPath = realpathSync(operationPath);
|
|
79
|
+
assertNoWindowsPathAlias(realPath, "filesystem", `${label} real path uses a Windows filesystem namespace alias`);
|
|
59
80
|
return {
|
|
60
81
|
path: resolvedPath,
|
|
61
|
-
realPath
|
|
82
|
+
realPath,
|
|
62
83
|
identity,
|
|
63
84
|
};
|
|
64
85
|
}
|
|
65
86
|
async function assertDirectoryReceiptCurrent(receipt, label) {
|
|
66
|
-
|
|
87
|
+
assertDirectoryReceiptPaths(receipt, label);
|
|
88
|
+
const operationPath = pathForWindowsFilesystem(receipt.path);
|
|
89
|
+
const currentIdentity = fsSync.lstatSync(operationPath);
|
|
67
90
|
assertDirectory(currentIdentity, receipt.path, label);
|
|
91
|
+
const realPath = realpathSync.native(operationPath);
|
|
92
|
+
assertNoWindowsPathAlias(realPath, "filesystem", `${label} real path uses a Windows filesystem namespace alias`);
|
|
68
93
|
if (!sameFileIdentity(receipt.identity, currentIdentity) ||
|
|
69
|
-
|
|
94
|
+
realPath !== receipt.realPath) {
|
|
70
95
|
throw new FsSafeError("path-mismatch", `${label} changed during durable directory operation: ${receipt.path}`);
|
|
71
96
|
}
|
|
72
97
|
}
|
|
73
98
|
function assertDirectoryReceiptCurrentSync(receipt, label) {
|
|
74
|
-
|
|
99
|
+
assertDirectoryReceiptPaths(receipt, label);
|
|
100
|
+
const operationPath = pathForWindowsFilesystem(receipt.path);
|
|
101
|
+
const currentIdentity = fsSync.lstatSync(operationPath);
|
|
75
102
|
assertDirectory(currentIdentity, receipt.path, label);
|
|
103
|
+
const realPath = realpathSync(operationPath);
|
|
104
|
+
assertNoWindowsPathAlias(realPath, "filesystem", `${label} real path uses a Windows filesystem namespace alias`);
|
|
76
105
|
if (!sameFileIdentity(receipt.identity, currentIdentity) ||
|
|
77
|
-
|
|
106
|
+
realPath !== receipt.realPath) {
|
|
78
107
|
throw new FsSafeError("path-mismatch", `${label} changed during durable directory operation: ${receipt.path}`);
|
|
79
108
|
}
|
|
80
109
|
}
|
|
@@ -88,19 +117,21 @@ async function assertOpenDirectoryCurrent(handle, receipt, label) {
|
|
|
88
117
|
}
|
|
89
118
|
class PinnedDirectoryImpl {
|
|
90
119
|
receipt;
|
|
120
|
+
#authority;
|
|
91
121
|
#handle;
|
|
92
122
|
#label;
|
|
93
123
|
#closed = false;
|
|
94
124
|
constructor(handle, receipt, label) {
|
|
95
125
|
this.#handle = handle;
|
|
96
|
-
this
|
|
126
|
+
this.#authority = receipt;
|
|
127
|
+
this.receipt = ownDirectoryReceipt(receipt);
|
|
97
128
|
this.#label = label;
|
|
98
129
|
}
|
|
99
130
|
async assertCurrent() {
|
|
100
131
|
if (this.#closed) {
|
|
101
132
|
throw new FsSafeError("helper-failed", `${this.#label} pin is already closed`);
|
|
102
133
|
}
|
|
103
|
-
await assertOpenDirectoryCurrent(this.#handle, this
|
|
134
|
+
await assertOpenDirectoryCurrent(this.#handle, this.#authority, this.#label);
|
|
104
135
|
}
|
|
105
136
|
async sync() {
|
|
106
137
|
await this.assertCurrent();
|
|
@@ -127,9 +158,11 @@ class PinnedDirectoryImpl {
|
|
|
127
158
|
}
|
|
128
159
|
export async function pinDirectory(directory, options = {}) {
|
|
129
160
|
const label = options.label ?? "directory";
|
|
130
|
-
const receipt = typeof directory === "string"
|
|
161
|
+
const receipt = typeof directory === "string"
|
|
162
|
+
? await createDirectoryReceipt(directory, label)
|
|
163
|
+
: ownDirectoryReceipt(directory);
|
|
131
164
|
await assertDirectoryReceiptCurrent(receipt, label);
|
|
132
|
-
const handle = await fs.open(receipt.path, directoryOpenFlags());
|
|
165
|
+
const handle = await fs.open(pathForWindowsFilesystem(receipt.path), directoryOpenFlags());
|
|
133
166
|
try {
|
|
134
167
|
await assertOpenDirectoryCurrent(handle, receipt, label);
|
|
135
168
|
return new PinnedDirectoryImpl(handle, receipt, label);
|
|
@@ -141,7 +174,9 @@ export async function pinDirectory(directory, options = {}) {
|
|
|
141
174
|
}
|
|
142
175
|
export async function syncDirectory(directory, options = {}) {
|
|
143
176
|
const label = options.label ?? "directory";
|
|
144
|
-
const receipt = typeof directory === "string"
|
|
177
|
+
const receipt = typeof directory === "string"
|
|
178
|
+
? await createDirectoryReceipt(directory, label)
|
|
179
|
+
: ownDirectoryReceipt(directory);
|
|
145
180
|
let pinned;
|
|
146
181
|
try {
|
|
147
182
|
pinned = await pinDirectory(receipt, { label });
|
|
@@ -162,11 +197,13 @@ export async function syncDirectory(directory, options = {}) {
|
|
|
162
197
|
}
|
|
163
198
|
export function syncDirectorySync(directory, options = {}) {
|
|
164
199
|
const label = options.label ?? "directory";
|
|
165
|
-
const receipt = typeof directory === "string"
|
|
200
|
+
const receipt = typeof directory === "string"
|
|
201
|
+
? createDirectoryReceiptSync(directory, label)
|
|
202
|
+
: ownDirectoryReceipt(directory);
|
|
166
203
|
assertDirectoryReceiptCurrentSync(receipt, label);
|
|
167
204
|
let descriptor;
|
|
168
205
|
try {
|
|
169
|
-
descriptor = fsSync.openSync(receipt.path, directoryOpenFlags());
|
|
206
|
+
descriptor = fsSync.openSync(pathForWindowsFilesystem(receipt.path), directoryOpenFlags());
|
|
170
207
|
}
|
|
171
208
|
catch (error) {
|
|
172
209
|
if (!isWindowsDirectoryOpenUnsupported(error)) {
|
|
@@ -211,7 +248,9 @@ export function syncDirectoryBestEffortSync(directoryPath) {
|
|
|
211
248
|
}
|
|
212
249
|
}
|
|
213
250
|
async function findExistingAncestorReceipt(targetPath, label) {
|
|
214
|
-
|
|
251
|
+
assertNoWindowsPathAlias(targetPath, "filesystem", `${label} path uses a Windows filesystem namespace alias`);
|
|
252
|
+
let currentPath = resolvePathPreservingWindowsRoot(targetPath);
|
|
253
|
+
assertNoWindowsPathAlias(currentPath, "filesystem", `${label} path uses a Windows filesystem namespace alias`);
|
|
215
254
|
while (true) {
|
|
216
255
|
try {
|
|
217
256
|
return await createDirectoryReceipt(currentPath, label);
|
|
@@ -229,12 +268,16 @@ async function findExistingAncestorReceipt(targetPath, label) {
|
|
|
229
268
|
}
|
|
230
269
|
}
|
|
231
270
|
export async function ensureDurableDirectory(options) {
|
|
232
|
-
const directoryPath = path.resolve(options.directoryPath);
|
|
233
271
|
const label = options.label ?? "directory";
|
|
272
|
+
const requestedDirectoryPath = options.directoryPath;
|
|
273
|
+
assertNoWindowsPathAlias(requestedDirectoryPath, "filesystem", `${label} path uses a Windows filesystem namespace alias`);
|
|
274
|
+
const directoryPath = resolvePathPreservingWindowsRoot(requestedDirectoryPath);
|
|
275
|
+
assertNoWindowsPathAlias(directoryPath, "filesystem", `${label} path uses a Windows filesystem namespace alias`);
|
|
234
276
|
const ancestorReceipt = await findExistingAncestorReceipt(directoryPath, label);
|
|
235
277
|
const targetExists = ancestorReceipt.path === directoryPath;
|
|
236
|
-
|
|
237
|
-
|
|
278
|
+
const expectedExistingIdentity = options.expectedExistingIdentity;
|
|
279
|
+
if (expectedExistingIdentity &&
|
|
280
|
+
(!targetExists || !sameFileIdentity(expectedExistingIdentity, ancestorReceipt.identity))) {
|
|
238
281
|
throw new FsSafeError("path-mismatch", `${label} changed before durable directory pinning: ${directoryPath}`);
|
|
239
282
|
}
|
|
240
283
|
const ancestor = await pinDirectory(ancestorReceipt, { label });
|
|
@@ -242,8 +285,9 @@ export async function ensureDurableDirectory(options) {
|
|
|
242
285
|
try {
|
|
243
286
|
await ancestor.assertCurrent();
|
|
244
287
|
if (!targetExists) {
|
|
245
|
-
|
|
246
|
-
|
|
288
|
+
const create = options.create;
|
|
289
|
+
if (create) {
|
|
290
|
+
await Reflect.apply(create, options, [directoryPath]);
|
|
247
291
|
}
|
|
248
292
|
else {
|
|
249
293
|
const created = await ensureAbsoluteDirectory(directoryPath, {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directory-entry-path.d.ts","sourceRoot":"","sources":["../src/directory-entry-path.ts"],"names":[],"mappings":"AAEA,4FAA4F;AAC5F,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,kBAAmB,GAAG,MAAM,CAenF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
/** Strip only trailing separators: lstat must inspect the entry, not follow a leaf link. */
|
|
3
|
+
export function directoryEntryPath(dir, platform = process.platform) {
|
|
4
|
+
const windows = platform === "win32";
|
|
5
|
+
if (typeof dir === "string") {
|
|
6
|
+
const last = dir[dir.length - 1];
|
|
7
|
+
if (last !== "/" && (!windows || last !== "\\"))
|
|
8
|
+
return dir;
|
|
9
|
+
}
|
|
10
|
+
let rootLength = (windows ? path.win32 : path.posix).parse(dir).root.length;
|
|
11
|
+
if (windows && /^[\\/]{2}[?.][\\/]UNC[\\/]/i.test(dir)) {
|
|
12
|
+
// Node parses the namespace prefix as the root; retain the complete UNC share.
|
|
13
|
+
const uncRoot = path.win32.parse(`\\\\${dir.slice(8)}`).root;
|
|
14
|
+
if (uncRoot.length > 1)
|
|
15
|
+
rootLength = Math.max(rootLength, uncRoot.length + 6);
|
|
16
|
+
}
|
|
17
|
+
let end = dir.length;
|
|
18
|
+
while (end > rootLength && (dir[end - 1] === "/" || (windows && dir[end - 1] === "\\")))
|
|
19
|
+
end--;
|
|
20
|
+
return end === rootLength || end === dir.length ? dir : dir.slice(0, end);
|
|
21
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { BigIntStats, Stats } from "node:fs";
|
|
2
|
+
import { type ExactStatIdentity, type StatObservationReceipt } from "./stat-observation.js";
|
|
2
3
|
export type AsyncDirectoryGuard<T extends Stats | BigIntStats = Stats> = {
|
|
3
4
|
dir: string;
|
|
4
5
|
realPath: string;
|
|
@@ -21,6 +22,7 @@ export declare function assertDirectoryIdentitySync(observedPath: string, expect
|
|
|
21
22
|
}): void;
|
|
22
23
|
export declare function createAsyncDirectoryGuard(dir: string, options: {
|
|
23
24
|
bigint: true;
|
|
25
|
+
initial?: BigIntStats;
|
|
24
26
|
}): Promise<AsyncDirectoryGuard<BigIntStats>>;
|
|
25
27
|
export declare function createAsyncDirectoryGuard(dir: string, options?: {
|
|
26
28
|
bigint?: false;
|
|
@@ -37,5 +39,19 @@ export declare function createNearestExistingDirectoryGuard(rootReal: string, ta
|
|
|
37
39
|
}): Promise<AnyAsyncDirectoryGuard>;
|
|
38
40
|
export declare function createNearestExistingSyncDirectoryGuard(rootReal: string, targetPath: string): SyncDirectoryGuard;
|
|
39
41
|
export declare function inspectDirectoryIdentity(dir: string, expected?: Pick<BigIntStats, "dev" | "ino">): Promise<BigIntStats>;
|
|
40
|
-
export declare function
|
|
42
|
+
export declare function observeDirectoryIdentitySync(dir: string, options: {
|
|
43
|
+
bigint: true;
|
|
44
|
+
}): BigIntStats;
|
|
45
|
+
export declare function observeDirectoryIdentitySync(dir: string, options?: {
|
|
46
|
+
bigint?: false;
|
|
47
|
+
}): Stats;
|
|
48
|
+
export declare function inspectDirectoryIdentitySync(dir: string, expected?: Pick<BigIntStats, "dev" | "ino">, initial?: BigIntStats, platform?: NodeJS.Platform): BigIntStats;
|
|
49
|
+
export type DirectoryObservationGuard = StatObservationReceipt & {
|
|
50
|
+
dir: string;
|
|
51
|
+
realPath: string;
|
|
52
|
+
};
|
|
53
|
+
export declare function extendDirectoryObservationGuard(observation: StatObservationReceipt, dir: string, realPath: string): DirectoryObservationGuard;
|
|
54
|
+
export declare function inspectDirectoryObservationSync(dir: string, expected?: ExactStatIdentity): StatObservationReceipt;
|
|
55
|
+
export declare function assertDirectoryObservationSync(dir: string, expected: ExactStatIdentity): Stats | BigIntStats;
|
|
56
|
+
export declare function assertDirectoryObservationGuardSync(guard: DirectoryObservationGuard): void;
|
|
41
57
|
//# sourceMappingURL=directory-guard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"directory-guard.d.ts","sourceRoot":"","sources":["../src/directory-guard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"directory-guard.d.ts","sourceRoot":"","sources":["../src/directory-guard.ts"],"names":[],"mappings":"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"}
|