@openclaw/fs-safe 0.14.0 → 0.16.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 +88 -0
- package/README.md +38 -10
- package/dist/advanced.d.ts +2 -1
- package/dist/advanced.d.ts.map +1 -1
- package/dist/advanced.js +2 -1
- package/dist/archive-kind.d.ts +0 -1
- package/dist/archive-kind.d.ts.map +1 -1
- package/dist/archive-kind.js +5 -17
- package/dist/archive-merge.d.ts.map +1 -1
- package/dist/archive-merge.js +113 -46
- package/dist/archive-parser.wasm +0 -0
- package/dist/archive-read.d.ts.map +1 -1
- package/dist/archive-read.js +10 -11
- package/dist/archive-tar-stream.d.ts +3 -0
- package/dist/archive-tar-stream.d.ts.map +1 -1
- package/dist/archive-tar-stream.js +56 -37
- package/dist/archive-tar-wasm.d.ts +16 -4
- package/dist/archive-tar-wasm.d.ts.map +1 -1
- package/dist/archive-tar-wasm.js +134 -34
- package/dist/archive-zip-directory.d.ts +4 -0
- package/dist/archive-zip-directory.d.ts.map +1 -1
- package/dist/archive-zip-directory.js +2 -0
- package/dist/archive-zip-entry.d.ts +6 -2
- package/dist/archive-zip-entry.d.ts.map +1 -1
- package/dist/archive-zip-entry.js +23 -8
- package/dist/archive-zip-integrity.d.ts.map +1 -1
- package/dist/archive-zip-integrity.js +3 -4
- package/dist/archive-zip-loader.d.ts.map +1 -1
- package/dist/archive-zip-loader.js +107 -31
- package/dist/archive-zip-names.d.ts +1 -0
- package/dist/archive-zip-names.d.ts.map +1 -1
- package/dist/archive-zip-names.js +6 -0
- package/dist/archive.d.ts.map +1 -1
- package/dist/archive.js +11 -11
- package/dist/bounded-read-stream.d.ts +0 -1
- package/dist/bounded-read-stream.d.ts.map +1 -1
- package/dist/bounded-read-stream.js +0 -6
- package/dist/clone-metadata.d.ts +1 -0
- package/dist/clone-metadata.d.ts.map +1 -1
- package/dist/clone-metadata.js +6 -2
- package/dist/copy-publication.d.ts +6 -0
- package/dist/copy-publication.d.ts.map +1 -1
- package/dist/copy-publication.js +3 -0
- package/dist/copy-tree-portable.d.ts.map +1 -1
- package/dist/copy-tree-portable.js +44 -24
- package/dist/copy.d.ts.map +1 -1
- package/dist/copy.js +29 -11
- package/dist/create-directory.d.ts +20 -0
- package/dist/create-directory.d.ts.map +1 -0
- package/dist/create-directory.js +130 -0
- package/dist/create-file-async.d.ts +7 -0
- package/dist/create-file-async.d.ts.map +1 -0
- package/dist/create-file-async.js +121 -0
- package/dist/create-file.d.ts +8 -0
- package/dist/create-file.d.ts.map +1 -0
- package/dist/create-file.js +190 -0
- package/dist/create-owned-file.d.ts +8 -0
- package/dist/create-owned-file.d.ts.map +1 -0
- package/dist/create-owned-file.js +16 -0
- package/dist/create.d.ts +4 -0
- package/dist/create.d.ts.map +1 -0
- package/dist/create.js +2 -0
- package/dist/creation-darwin.d.ts +7 -0
- package/dist/creation-darwin.d.ts.map +1 -0
- package/dist/creation-darwin.js +79 -0
- package/dist/creation-file-state.d.ts +19 -0
- package/dist/creation-file-state.d.ts.map +1 -0
- package/dist/creation-file-state.js +118 -0
- package/dist/creation-path.d.ts +21 -0
- package/dist/creation-path.d.ts.map +1 -0
- package/dist/creation-path.js +71 -0
- package/dist/creation-permissions.d.ts +19 -0
- package/dist/creation-permissions.d.ts.map +1 -0
- package/dist/creation-permissions.js +125 -0
- package/dist/directory-durability.d.ts +1 -1
- package/dist/directory-durability.d.ts.map +1 -1
- package/dist/directory-durability.js +22 -80
- package/dist/directory-guard.d.ts +3 -0
- package/dist/directory-guard.d.ts.map +1 -1
- package/dist/directory-mode-node.d.ts +2 -0
- package/dist/directory-mode-node.d.ts.map +1 -1
- package/dist/directory-mode-node.js +8 -0
- package/dist/directory-mode-owner.js +5 -5
- package/dist/directory-receipt.d.ts +24 -0
- package/dist/directory-receipt.d.ts.map +1 -0
- package/dist/directory-receipt.js +127 -0
- package/dist/file-cleanup.d.ts +19 -0
- package/dist/file-cleanup.d.ts.map +1 -0
- package/dist/file-cleanup.js +78 -0
- package/dist/file-handle-transfer.d.ts +2 -0
- package/dist/file-handle-transfer.d.ts.map +1 -1
- package/dist/file-handle-transfer.js +57 -2
- package/dist/file-identity.d.ts.map +1 -1
- package/dist/file-identity.js +18 -4
- package/dist/file-lock-sync-admission.d.ts +19 -0
- package/dist/file-lock-sync-admission.d.ts.map +1 -0
- package/dist/file-lock-sync-admission.js +93 -0
- package/dist/file-lock-sync-root-acquire.d.ts +4 -0
- package/dist/file-lock-sync-root-acquire.d.ts.map +1 -0
- package/dist/file-lock-sync-root-acquire.js +370 -0
- package/dist/file-lock-sync-root-arbitration.d.ts +18 -0
- package/dist/file-lock-sync-root-arbitration.d.ts.map +1 -0
- package/dist/file-lock-sync-root-arbitration.js +66 -0
- package/dist/file-lock-sync-root-held.d.ts +34 -0
- package/dist/file-lock-sync-root-held.d.ts.map +1 -0
- package/dist/file-lock-sync-root-held.js +393 -0
- package/dist/file-lock-sync-root-io.d.ts +44 -0
- package/dist/file-lock-sync-root-io.d.ts.map +1 -0
- package/dist/file-lock-sync-root-io.js +209 -0
- package/dist/file-lock-sync-root-mutation.d.ts +17 -0
- package/dist/file-lock-sync-root-mutation.d.ts.map +1 -0
- package/dist/file-lock-sync-root-mutation.js +277 -0
- package/dist/file-lock-sync-root-options.d.ts +20 -0
- package/dist/file-lock-sync-root-options.d.ts.map +1 -0
- package/dist/file-lock-sync-root-options.js +58 -0
- package/dist/file-lock-sync-root-registration.d.ts +2 -0
- package/dist/file-lock-sync-root-registration.d.ts.map +1 -0
- package/dist/file-lock-sync-root-registration.js +90 -0
- package/dist/file-lock-sync-root.d.ts +36 -0
- package/dist/file-lock-sync-root.d.ts.map +1 -0
- package/dist/file-lock-sync-root.js +361 -0
- package/dist/file-lock-sync-stale-admission.d.ts +24 -0
- package/dist/file-lock-sync-stale-admission.d.ts.map +1 -0
- package/dist/file-lock-sync-stale-admission.js +205 -0
- package/dist/file-lock-sync.d.ts.map +1 -1
- package/dist/file-lock-sync.js +245 -205
- package/dist/file-observation.d.ts +1 -1
- package/dist/file-observation.d.ts.map +1 -1
- package/dist/file-store-boundary.d.ts +2 -6
- package/dist/file-store-boundary.d.ts.map +1 -1
- package/dist/file-store-boundary.js +3 -9
- package/dist/file-store-prune.d.ts.map +1 -1
- package/dist/file-store-prune.js +5 -1
- package/dist/file-store-sync-write.d.ts.map +1 -1
- package/dist/file-store-sync-write.js +5 -8
- package/dist/file-store.d.ts.map +1 -1
- package/dist/file-store.js +47 -12
- package/dist/guarded-mkdir.d.ts +1 -0
- package/dist/guarded-mkdir.d.ts.map +1 -1
- package/dist/guarded-mkdir.js +36 -7
- package/dist/json-document-store.d.ts.map +1 -1
- package/dist/json-document-store.js +22 -15
- package/dist/json-durable-queue-ownership.d.ts +0 -1
- package/dist/json-durable-queue-ownership.d.ts.map +1 -1
- package/dist/json-durable-queue-ownership.js +0 -6
- package/dist/move-path.js +1 -1
- package/dist/native-binding.d.ts +13 -1
- package/dist/native-binding.d.ts.map +1 -1
- package/dist/native-fallback-warning.d.ts +4 -0
- package/dist/native-fallback-warning.d.ts.map +1 -0
- package/dist/native-fallback-warning.js +11 -0
- package/dist/native-operations.d.ts +0 -2
- package/dist/native-operations.d.ts.map +1 -1
- package/dist/native-operations.js +0 -24
- package/dist/native-parent-admission.d.ts +5 -2
- package/dist/native-parent-admission.d.ts.map +1 -1
- package/dist/native-parent-admission.js +27 -7
- package/dist/native-pinned-write-windows.d.ts +1 -1
- package/dist/native-pinned-write-windows.d.ts.map +1 -1
- package/dist/native-pinned-write-windows.js +174 -29
- package/dist/native-pinned-write.d.ts.map +1 -1
- package/dist/native-pinned-write.js +26 -14
- package/dist/native-policy-parent-windows.d.ts +14 -0
- package/dist/native-policy-parent-windows.d.ts.map +1 -0
- package/dist/native-policy-parent-windows.js +209 -0
- package/dist/native-rename-outcome.d.ts +4 -0
- package/dist/native-rename-outcome.d.ts.map +1 -0
- package/dist/native-rename-outcome.js +8 -0
- package/dist/native-staged-file.d.ts +3 -2
- package/dist/native-staged-file.d.ts.map +1 -1
- package/dist/native-staged-file.js +121 -72
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +12 -8
- package/dist/owner-dacl.d.ts.map +1 -1
- package/dist/owner-dacl.js +10 -4
- package/dist/path-prefix.d.ts.map +1 -1
- package/dist/path-prefix.js +30 -8
- package/dist/path-suffix-aliases.d.ts +2 -0
- package/dist/path-suffix-aliases.d.ts.map +1 -1
- package/dist/path-suffix-aliases.js +25 -17
- package/dist/permission-exec.d.ts +2 -0
- package/dist/permission-exec.d.ts.map +1 -1
- package/dist/permission-exec.js +150 -21
- package/dist/permissions-windows.js +1 -1
- package/dist/pinned-mutation-admission.d.ts.map +1 -1
- package/dist/pinned-mutation-admission.js +10 -5
- package/dist/pinned-mutation-observation.d.ts +0 -1
- package/dist/pinned-mutation-observation.d.ts.map +1 -1
- package/dist/pinned-mutation-observation.js +0 -19
- package/dist/pinned-mutation-shared-route.d.ts +1 -0
- package/dist/pinned-mutation-shared-route.d.ts.map +1 -1
- package/dist/pinned-mutation-shared-route.js +1 -1
- package/dist/pinned-write-input.d.ts +4 -0
- package/dist/pinned-write-input.d.ts.map +1 -0
- package/dist/pinned-write-input.js +25 -0
- package/dist/pinned-write-mode.d.ts +5 -0
- package/dist/pinned-write-mode.d.ts.map +1 -0
- package/dist/pinned-write-mode.js +24 -0
- package/dist/pinned-write-staged.d.ts +6 -0
- package/dist/pinned-write-staged.d.ts.map +1 -0
- package/dist/pinned-write-staged.js +187 -0
- package/dist/pinned-write-types.d.ts +5 -0
- package/dist/pinned-write-types.d.ts.map +1 -1
- package/dist/pinned-write.d.ts.map +1 -1
- package/dist/pinned-write.js +35 -145
- package/dist/private-directory.d.ts.map +1 -1
- package/dist/private-directory.js +18 -4
- package/dist/private-producer-handoff-sync.d.ts +14 -0
- package/dist/private-producer-handoff-sync.d.ts.map +1 -0
- package/dist/private-producer-handoff-sync.js +114 -0
- package/dist/private-producer-handoff.d.ts +22 -4
- package/dist/private-producer-handoff.d.ts.map +1 -1
- package/dist/private-producer-handoff.js +140 -77
- package/dist/private-temp-workspace.d.ts.map +1 -1
- package/dist/private-temp-workspace.js +75 -121
- package/dist/publish-copy-stage.d.ts +2 -1
- package/dist/publish-copy-stage.d.ts.map +1 -1
- package/dist/publish-copy-stage.js +16 -7
- package/dist/publish-file.d.ts.map +1 -1
- package/dist/publish-file.js +2 -2
- package/dist/regular-file.d.ts.map +1 -1
- package/dist/regular-file.js +1 -15
- package/dist/replace-directory.d.ts.map +1 -1
- package/dist/replace-directory.js +256 -18
- package/dist/replace-file-copy-fallback.d.ts.map +1 -1
- package/dist/replace-file-copy-fallback.js +62 -70
- package/dist/replace-file-copy-source.d.ts.map +1 -1
- package/dist/replace-file-copy-source.js +10 -12
- package/dist/replace-file-temp-owner.d.ts +5 -9
- package/dist/replace-file-temp-owner.d.ts.map +1 -1
- package/dist/replace-file-temp-owner.js +56 -72
- package/dist/replace-file.js +6 -6
- package/dist/retained-directory-replacement.d.ts +26 -0
- package/dist/retained-directory-replacement.d.ts.map +1 -0
- package/dist/retained-directory-replacement.js +193 -0
- package/dist/root-boundary.d.ts +1 -0
- package/dist/root-boundary.d.ts.map +1 -1
- package/dist/root-boundary.js +4 -0
- package/dist/root-context.d.ts +0 -8
- package/dist/root-context.d.ts.map +1 -1
- package/dist/root-context.js +0 -3
- package/dist/root-create-input.d.ts +8 -1
- package/dist/root-create-input.d.ts.map +1 -1
- package/dist/root-create-input.js +17 -4
- package/dist/root-directory-creation.d.ts +3 -3
- package/dist/root-directory-creation.d.ts.map +1 -1
- package/dist/root-directory-creation.js +15 -3
- package/dist/root-directory-list.d.ts +1 -0
- package/dist/root-directory-list.d.ts.map +1 -1
- package/dist/root-directory-list.js +1 -0
- package/dist/root-impl.d.ts.map +1 -1
- package/dist/root-impl.js +46 -17
- package/dist/root-move-noreplace.d.ts.map +1 -1
- package/dist/root-move-noreplace.js +24 -15
- package/dist/root-options.d.ts +12 -4
- package/dist/root-options.d.ts.map +1 -1
- package/dist/root-path-errors.d.ts +1 -0
- package/dist/root-path-errors.d.ts.map +1 -1
- package/dist/root-path-errors.js +11 -2
- package/dist/root-path-existing.d.ts.map +1 -1
- package/dist/root-path-existing.js +11 -35
- package/dist/root-path-stat.d.ts.map +1 -1
- package/dist/root-path-stat.js +59 -7
- package/dist/root-path.js +1 -13
- package/dist/root-remove.d.ts +1 -0
- package/dist/root-remove.d.ts.map +1 -1
- package/dist/root-remove.js +4 -0
- package/dist/root-walk.d.ts +1 -1
- package/dist/root-walk.d.ts.map +1 -1
- package/dist/root-walk.js +17 -2
- package/dist/root-write-admission.d.ts +0 -2
- package/dist/root-write-admission.d.ts.map +1 -1
- package/dist/root-write-admission.js +1 -15
- package/dist/root-write-complete-parent.d.ts.map +1 -1
- package/dist/root-write-complete-parent.js +7 -23
- package/dist/root-write-publication.js +1 -1
- package/dist/root-write-verification.d.ts.map +1 -1
- package/dist/root-write-verification.js +29 -42
- package/dist/secret-file.d.ts.map +1 -1
- package/dist/secret-file.js +3 -24
- package/dist/secret-read-async.d.ts.map +1 -1
- package/dist/secret-read-async.js +3 -24
- package/dist/secret-read-policy.d.ts +6 -2
- package/dist/secret-read-policy.d.ts.map +1 -1
- package/dist/secret-read-policy.js +26 -2
- package/dist/secure-file-windows.d.ts +6 -0
- package/dist/secure-file-windows.d.ts.map +1 -1
- package/dist/secure-file-windows.js +34 -117
- package/dist/secure-file.js +2 -2
- package/dist/sibling-temp.d.ts.map +1 -1
- package/dist/sibling-temp.js +23 -12
- package/dist/sidecar-lock-acquire.d.ts +2 -28
- package/dist/sidecar-lock-acquire.d.ts.map +1 -1
- package/dist/sidecar-lock-acquire.js +288 -199
- package/dist/sidecar-lock-admission-context.d.ts +19 -0
- package/dist/sidecar-lock-admission-context.d.ts.map +1 -0
- package/dist/sidecar-lock-admission-context.js +60 -0
- package/dist/sidecar-lock-admission-parser.d.ts +43 -0
- package/dist/sidecar-lock-admission-parser.d.ts.map +1 -0
- package/dist/sidecar-lock-admission-parser.js +113 -0
- package/dist/sidecar-lock-admission.d.ts +35 -0
- package/dist/sidecar-lock-admission.d.ts.map +1 -0
- package/dist/sidecar-lock-admission.js +7 -0
- package/dist/sidecar-lock-reclaim.d.ts +9 -4
- package/dist/sidecar-lock-reclaim.d.ts.map +1 -1
- package/dist/sidecar-lock-reclaim.js +80 -25
- package/dist/sidecar-lock-root.d.ts.map +1 -1
- package/dist/sidecar-lock-root.js +2 -1
- package/dist/sidecar-lock-stale-admission.d.ts +39 -0
- package/dist/sidecar-lock-stale-admission.d.ts.map +1 -0
- package/dist/sidecar-lock-stale-admission.js +232 -0
- package/dist/sidecar-lock-target.d.ts +8 -0
- package/dist/sidecar-lock-target.d.ts.map +1 -0
- package/dist/sidecar-lock-target.js +55 -0
- package/dist/sidecar-lock.d.ts.map +1 -1
- package/dist/sidecar-lock.js +100 -16
- package/dist/staged-directory.d.ts.map +1 -1
- package/dist/staged-directory.js +6 -6
- package/dist/staged-file-settlement.d.ts +17 -0
- package/dist/staged-file-settlement.d.ts.map +1 -0
- package/dist/staged-file-settlement.js +57 -0
- package/dist/temp-workspace-descriptor.d.ts.map +1 -1
- package/dist/temp-workspace-descriptor.js +9 -27
- package/dist/temp-workspace-owner.d.ts.map +1 -1
- package/dist/temp-workspace-owner.js +8 -8
- package/dist/walk.d.ts +5 -1
- package/dist/walk.d.ts.map +1 -1
- package/dist/walk.js +19 -6
- package/dist/windows-owner.d.ts.map +1 -1
- package/dist/windows-owner.js +4 -3
- package/dist/windows-security-bridge.cs +336 -0
- package/dist/windows-security-bridge.ps1 +15 -0
- package/dist/windows-security-command.d.ts +26 -0
- package/dist/windows-security-command.d.ts.map +1 -0
- package/dist/windows-security-command.js +363 -0
- package/dist/windows-security-facts.d.ts +6 -0
- package/dist/windows-security-facts.d.ts.map +1 -0
- package/dist/windows-security-facts.js +108 -0
- package/docs/advanced.md +4 -2
- package/docs/archive.md +97 -46
- package/docs/atomic.md +85 -8
- package/docs/config.md +6 -2
- package/docs/contributing.md +44 -4
- package/docs/copy.md +37 -0
- package/docs/creation.md +128 -0
- package/docs/durability.md +24 -0
- package/docs/file-store.md +19 -0
- package/docs/install.md +31 -7
- package/docs/json-store.md +5 -0
- package/docs/migrating-to-0.5.md +15 -6
- package/docs/migrating-to-0.6.md +9 -4
- package/docs/native-helper.md +32 -12
- package/docs/native.md +38 -7
- package/docs/output.md +6 -0
- package/docs/path-prefix.md +10 -0
- package/docs/path-suffix-aliases.md +51 -6
- package/docs/permissions.md +50 -14
- package/docs/public-api.md +3 -2
- package/docs/root.md +56 -3
- package/docs/secret-file.md +11 -2
- package/docs/secure-file.md +9 -4
- package/docs/sidecar-lock.md +114 -8
- package/docs/staged-file.md +12 -3
- package/docs/temp.md +20 -3
- package/docs/walk.md +67 -1
- package/docs/writing.md +76 -6
- package/package.json +19 -16
- package/dist/darwin-acl.d.ts +0 -4
- package/dist/darwin-acl.d.ts.map +0 -1
- package/dist/darwin-acl.js +0 -24
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import fsSync, {} from "node:fs";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { inspectDirectoryIdentity } from "./directory-guard.js";
|
|
4
|
+
import { inspectDirectoryIdentity, inspectDirectoryIdentitySync } from "./directory-guard.js";
|
|
5
|
+
import { inspectNativeDirectoryObservation } from "./native-directory-observation.js";
|
|
5
6
|
import { FsSafeError } from "./errors.js";
|
|
6
7
|
import { captureNativeFdClose } from "./native-binding.js";
|
|
7
8
|
import { realpathSync } from "./realpath.js";
|
|
@@ -50,6 +51,7 @@ export async function openNativeRootAdmission(binding, params) {
|
|
|
50
51
|
}
|
|
51
52
|
return {
|
|
52
53
|
exactRoot,
|
|
54
|
+
reportCloseErrors: params.reportCloseErrors,
|
|
53
55
|
operation: params.operation ?? "native admission",
|
|
54
56
|
root,
|
|
55
57
|
rootPath: params.rootPath,
|
|
@@ -61,14 +63,14 @@ export async function openNativeRootAdmission(binding, params) {
|
|
|
61
63
|
}
|
|
62
64
|
catch (closeError) {
|
|
63
65
|
// Windows admission keeps the typed boundary failure primary.
|
|
64
|
-
if (process.platform !== "win32") {
|
|
66
|
+
if (process.platform !== "win32" || params.reportCloseErrors) {
|
|
65
67
|
throw createSuppressedError(closeError, error, "native root admission and close failed");
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
70
|
throw error;
|
|
69
71
|
}
|
|
70
72
|
}
|
|
71
|
-
export async function openNativeParentAdmission(binding, rootAdmission, relativeParentPath) {
|
|
73
|
+
export async function openNativeParentAdmission(binding, rootAdmission, relativeParentPath, observation) {
|
|
72
74
|
assertParentAdmissionAvailable(binding);
|
|
73
75
|
const closeFd = captureNativeFdClose(binding);
|
|
74
76
|
const directoryFlags = fsSync.constants.O_RDONLY | (fsSync.constants.O_DIRECTORY ?? 0);
|
|
@@ -82,6 +84,27 @@ export async function openNativeParentAdmission(binding, rootAdmission, relative
|
|
|
82
84
|
const parentInput = relativeParentPath
|
|
83
85
|
? path.join(rootAdmission.rootPath, ...relativeParentPath.split("/"))
|
|
84
86
|
: rootAdmission.rootPath;
|
|
87
|
+
if (observation === "native-directory" && process.platform === "win32" && rootAdmission.exactRoot &&
|
|
88
|
+
typeof binding.observeDirectory === "function") {
|
|
89
|
+
const stat = inspectFileIdentitySync(() => fsSync.fstatSync(parentFd, { bigint: true }));
|
|
90
|
+
let observed;
|
|
91
|
+
try {
|
|
92
|
+
observed = inspectNativeDirectoryObservation(binding, parentInput, stat);
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
if (error?.code !== "OBSERVATION_UNAVAILABLE")
|
|
96
|
+
throw error;
|
|
97
|
+
}
|
|
98
|
+
if (observed) {
|
|
99
|
+
assertNoWindowsPathAlias(observed.realPath, "filesystem", "native parent uses a Windows filesystem namespace alias");
|
|
100
|
+
inspectDirectoryIdentitySync(observed.realPath, stat, stat);
|
|
101
|
+
return {
|
|
102
|
+
fd: parentFd,
|
|
103
|
+
close: () => closeFd(parentFd),
|
|
104
|
+
guard: { dir: observed.realPath, realPath: observed.realPath, stat },
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
85
108
|
const parentPath = realpathSync.native(pathForWindowsFilesystem(parentInput));
|
|
86
109
|
assertNoWindowsPathAlias(parentPath, "filesystem", "native parent uses a Windows filesystem namespace alias");
|
|
87
110
|
const stagedDirectory = process.platform === "win32"
|
|
@@ -115,13 +138,10 @@ export async function openNativeParentAdmission(binding, rootAdmission, relative
|
|
|
115
138
|
closeFd(parentFd);
|
|
116
139
|
}
|
|
117
140
|
catch (closeError) {
|
|
118
|
-
if (process.platform !== "win32") {
|
|
141
|
+
if (process.platform !== "win32" || rootAdmission.reportCloseErrors) {
|
|
119
142
|
throw createSuppressedError(closeError, error, "native parent admission and close failed");
|
|
120
143
|
}
|
|
121
144
|
}
|
|
122
145
|
throw error;
|
|
123
146
|
}
|
|
124
147
|
}
|
|
125
|
-
export function closeNativeParentAdmission(admission) {
|
|
126
|
-
admission?.close();
|
|
127
|
-
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { FileHandle } from "node:fs/promises";
|
|
2
|
-
import type
|
|
2
|
+
import { type AnyAsyncDirectoryGuard } from "./directory-guard.js";
|
|
3
3
|
import type { FileIdentityStat } from "./file-identity.js";
|
|
4
4
|
import type { NativeBinding } from "./native.js";
|
|
5
5
|
import type { PinnedWriteParams } from "./pinned-write.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-pinned-write-windows.d.ts","sourceRoot":"","sources":["../src/native-pinned-write-windows.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"native-pinned-write-windows.d.ts","sourceRoot":"","sources":["../src/native-pinned-write-windows.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,OAAO,EAA4B,KAAK,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE7F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAM3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAuD3D,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,sBAAsB,GAClC,OAAO,CAAC,gBAAgB,CAAC,CA6L3B"}
|
|
@@ -2,11 +2,20 @@ import { syncFileBestEffortSync } from "./file-sync.js";
|
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import fsSync, {} from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
|
+
import { createFileHandle } from "./create.js";
|
|
6
|
+
import { hasPreservedCreationArtifacts } from "./creation-file-state.js";
|
|
7
|
+
import { assertSyncDirectoryGuard } from "./directory-guard.js";
|
|
5
8
|
import { FsSafeError } from "./errors.js";
|
|
6
|
-
import { nativeOpenFlags, removeNativeCreatedFileIfStillPinned,
|
|
9
|
+
import { nativeOpenFlags, removeNativeCreatedFileIfStillPinned, } from "./native-operations.js";
|
|
10
|
+
import { writePinnedInput } from "./pinned-write-input.js";
|
|
7
11
|
import { captureNativeFdClose } from "./native-binding.js";
|
|
8
12
|
import { inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
9
13
|
import { assertFinalSymlinkRejected } from "./root-symlink-policy.js";
|
|
14
|
+
import { classifyNativeRenameFailure } from "./native-rename-outcome.js";
|
|
15
|
+
import { cleanupPinnedFilePath } from "./file-cleanup.js";
|
|
16
|
+
import { createStagedFileReceipt, settleStagedFile } from "./staged-file-settlement.js";
|
|
17
|
+
import { exactIdentityMatches } from "./staged-directory.js";
|
|
18
|
+
import { inspectNativeDirectoryObservation } from "./native-directory-observation.js";
|
|
10
19
|
function closeWriteFd(closeFd, fd) {
|
|
11
20
|
if (fd === undefined)
|
|
12
21
|
return;
|
|
@@ -14,42 +23,132 @@ function closeWriteFd(closeFd, fd) {
|
|
|
14
23
|
closeFd(fd);
|
|
15
24
|
}
|
|
16
25
|
catch (error) {
|
|
17
|
-
return error;
|
|
26
|
+
return { error };
|
|
18
27
|
}
|
|
19
28
|
}
|
|
29
|
+
function readParentIdentity(parentFd, guard) {
|
|
30
|
+
const stat = inspectFileIdentitySync(() => fsSync.fstatSync(parentFd, { bigint: true }));
|
|
31
|
+
if (!stat.isDirectory() || !exactIdentityMatches(guard.stat, stat)) {
|
|
32
|
+
throw new FsSafeError("path-mismatch", "native write parent identity changed");
|
|
33
|
+
}
|
|
34
|
+
return stat;
|
|
35
|
+
}
|
|
36
|
+
function assertNamedParentCurrent(binding, guard, identity) {
|
|
37
|
+
if (typeof binding.observeDirectory === "function") {
|
|
38
|
+
try {
|
|
39
|
+
const observed = inspectNativeDirectoryObservation(binding, guard.dir, identity);
|
|
40
|
+
if (observed.realPath !== guard.realPath) {
|
|
41
|
+
throw new FsSafeError("path-mismatch", "native write parent pathname changed");
|
|
42
|
+
}
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
if (error?.code !== "OBSERVATION_UNAVAILABLE")
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
assertSyncDirectoryGuard({ ...guard, stat: identity });
|
|
51
|
+
}
|
|
20
52
|
export async function runPinnedWriteWindows(binding, params, root, parentFd, parentGuard) {
|
|
21
53
|
const closeFd = captureNativeFdClose(binding);
|
|
22
54
|
const parentPath = parentGuard.realPath;
|
|
23
55
|
let tempFd;
|
|
56
|
+
let privateHandle;
|
|
24
57
|
let targetFd;
|
|
58
|
+
let publicationProbeFd;
|
|
25
59
|
let tempIdentity;
|
|
26
60
|
let tempName = "";
|
|
27
61
|
let renamed = false;
|
|
28
62
|
let completed = false;
|
|
63
|
+
const completeCreate = params.overwrite === false && params.input.kind !== "file" && params.input.stageBeforePublish === true;
|
|
64
|
+
let receipt;
|
|
65
|
+
let publication = Object.freeze({ status: "not-published" });
|
|
66
|
+
let phase = "prepare";
|
|
67
|
+
let failure;
|
|
68
|
+
const closeTemp = async () => {
|
|
69
|
+
const handle = privateHandle;
|
|
70
|
+
const fd = tempFd;
|
|
71
|
+
privateHandle = undefined;
|
|
72
|
+
tempFd = undefined;
|
|
73
|
+
if (handle)
|
|
74
|
+
await handle.close();
|
|
75
|
+
else if (fd !== undefined)
|
|
76
|
+
closeFd(fd);
|
|
77
|
+
};
|
|
29
78
|
try {
|
|
30
79
|
tempName = `.fs-safe-${randomUUID()}.tmp`;
|
|
31
80
|
params.assertBeforeMutation?.();
|
|
32
|
-
|
|
81
|
+
if (params.private) {
|
|
82
|
+
const parentIdentity = fsSync.fstatSync(parentFd, { bigint: true });
|
|
83
|
+
privateHandle = await createFileHandle(path.join(parentPath, tempName), {
|
|
84
|
+
private: true,
|
|
85
|
+
mode: 0o600,
|
|
86
|
+
assertBeforeMutation: params.assertBeforeMutation,
|
|
87
|
+
}, {
|
|
88
|
+
expectedParentIdentity: {
|
|
89
|
+
dev: parentIdentity.dev, ino: parentIdentity.ino, realPath: parentPath,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
tempFd = privateHandle.fd;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
tempFd = binding.openBeneath(parentFd, tempName, nativeOpenFlags(fsSync.constants.O_WRONLY | fsSync.constants.O_CREAT | fsSync.constants.O_EXCL)).fd;
|
|
96
|
+
}
|
|
33
97
|
const verificationIdentity = inspectFileIdentitySync(() => fsSync.fstatSync(tempFd, { bigint: true }));
|
|
34
98
|
tempIdentity = verificationIdentity;
|
|
35
99
|
// Creation is requested at 0600 in the binding, but a restrictive umask
|
|
36
100
|
// can remove owner access. Keep the unpublished inode private and
|
|
37
101
|
// reopenable until the published name has been identity-fenced.
|
|
38
102
|
fsSync.fchmodSync(tempFd, 0o600);
|
|
39
|
-
await
|
|
40
|
-
if (params.sync !== false)
|
|
41
|
-
|
|
103
|
+
await writePinnedInput(tempFd, params.input, params.maxBytes, params.assertBeforeMutation);
|
|
104
|
+
if (params.sync !== false) {
|
|
105
|
+
if (params.strictFileSync)
|
|
106
|
+
fsSync.fsyncSync(tempFd);
|
|
107
|
+
else
|
|
108
|
+
syncFileBestEffortSync(tempFd);
|
|
109
|
+
}
|
|
42
110
|
if (params.input.kind === "file")
|
|
43
111
|
await params.input.verifySource();
|
|
112
|
+
if (completeCreate) {
|
|
113
|
+
const parentIdentity = readParentIdentity(parentFd, parentGuard);
|
|
114
|
+
receipt = createStagedFileReceipt(Object.freeze({
|
|
115
|
+
path: parentGuard.dir,
|
|
116
|
+
realPath: parentGuard.realPath,
|
|
117
|
+
identity: Object.freeze({ dev: parentIdentity.dev, ino: parentIdentity.ino }),
|
|
118
|
+
}), tempName, fsSync.fstatSync(tempFd, { bigint: true }));
|
|
119
|
+
}
|
|
120
|
+
phase = "publish";
|
|
44
121
|
assertFinalSymlinkRejected(path.join(parentPath, params.basename), params.rejectFinalSymlink);
|
|
45
122
|
params.assertBeforeMutation?.();
|
|
46
|
-
if (params.
|
|
47
|
-
|
|
123
|
+
if (params.assertBeforeMutation) {
|
|
124
|
+
// Callbacks can replace names synchronously. Fence the named parent and
|
|
125
|
+
// stage against retained descriptors before the rename can expose bytes.
|
|
126
|
+
assertNamedParentCurrent(binding, parentGuard, readParentIdentity(parentFd, parentGuard));
|
|
127
|
+
publicationProbeFd = binding.openBeneath(parentFd, tempName, nativeOpenFlags(fsSync.constants.O_RDONLY)).fd;
|
|
128
|
+
const named = inspectFileIdentitySync(() => fsSync.fstatSync(publicationProbeFd, { bigint: true }), verificationIdentity);
|
|
129
|
+
const retained = inspectFileIdentitySync(() => fsSync.fstatSync(tempFd, { bigint: true }), verificationIdentity);
|
|
130
|
+
if (!named.isFile() || !retained.isFile() || named.nlink !== 1n || retained.nlink !== 1n) {
|
|
131
|
+
throw new FsSafeError("path-mismatch", "native write stage changed before publication");
|
|
132
|
+
}
|
|
133
|
+
assertFinalSymlinkRejected(path.join(parentPath, params.basename), params.rejectFinalSymlink);
|
|
48
134
|
}
|
|
49
|
-
|
|
50
|
-
|
|
135
|
+
try {
|
|
136
|
+
if (params.overwrite === false) {
|
|
137
|
+
binding.renameNoReplace(parentFd, tempName, parentFd, params.basename);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
binding.renameReplace(parentFd, tempName, parentFd, params.basename);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
if (completeCreate && classifyNativeRenameFailure(error) === "indeterminate") {
|
|
145
|
+
publication = Object.freeze({ status: "indeterminate", basename: params.basename, overwrite: false });
|
|
146
|
+
}
|
|
147
|
+
throw error;
|
|
51
148
|
}
|
|
52
149
|
renamed = true;
|
|
150
|
+
if (receipt)
|
|
151
|
+
publication = Object.freeze({ status: "published", staged: receipt, basename: params.basename, overwrite: false });
|
|
53
152
|
params.onPublished?.(verificationIdentity);
|
|
54
153
|
targetFd = binding.openBeneath(parentFd, params.basename, nativeOpenFlags(fsSync.constants.O_RDONLY)).fd;
|
|
55
154
|
const targetStat = inspectFileIdentitySync(() => fsSync.fstatSync(targetFd, { bigint: true }), verificationIdentity);
|
|
@@ -62,15 +161,21 @@ export async function runPinnedWriteWindows(binding, params, root, parentFd, par
|
|
|
62
161
|
// verifiable and so broader modes are never exposed before that fence.
|
|
63
162
|
try {
|
|
64
163
|
fsSync.fchmodSync(targetFd, params.mode);
|
|
65
|
-
|
|
66
|
-
|
|
164
|
+
// Windows FlushFileBuffers needs write access; the verification reopen is read-only.
|
|
165
|
+
if (params.sync !== false) {
|
|
166
|
+
if (params.strictFileSync)
|
|
167
|
+
fsSync.fsyncSync(tempFd);
|
|
168
|
+
else
|
|
169
|
+
syncFileBestEffortSync(tempFd);
|
|
170
|
+
}
|
|
67
171
|
}
|
|
68
172
|
catch (error) {
|
|
69
|
-
|
|
70
|
-
|
|
173
|
+
if (!completeCreate) {
|
|
174
|
+
closeWriteFd(closeFd, targetFd);
|
|
175
|
+
targetFd = undefined;
|
|
176
|
+
}
|
|
71
177
|
// Staged copies and streamed creates preserve publication for caller recovery.
|
|
72
|
-
if (params.input.kind
|
|
73
|
-
(params.input.kind === "stream" && !params.input.stageBeforePublish)) {
|
|
178
|
+
if (params.input.kind !== "file" && !params.input.stageBeforePublish) {
|
|
74
179
|
removeNativeCreatedFileIfStillPinned({
|
|
75
180
|
parentPath,
|
|
76
181
|
parentFd,
|
|
@@ -87,21 +192,61 @@ export async function runPinnedWriteWindows(binding, params, root, parentFd, par
|
|
|
87
192
|
completed = true;
|
|
88
193
|
return { dev: targetIdentity.dev, ino: targetIdentity.ino };
|
|
89
194
|
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
failure = { error };
|
|
197
|
+
throw error;
|
|
198
|
+
}
|
|
90
199
|
finally {
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
200
|
+
const preservedPreparation = params.private && tempFd === undefined && hasPreservedCreationArtifacts(failure?.error);
|
|
201
|
+
if (completeCreate || preservedPreparation) {
|
|
202
|
+
await settleStagedFile({
|
|
203
|
+
temporaryBasename: tempName, publication, phase, failure,
|
|
204
|
+
cleanup: async () => {
|
|
205
|
+
if (preservedPreparation)
|
|
206
|
+
return "preserved";
|
|
207
|
+
if (publication.status === "indeterminate")
|
|
208
|
+
return "preserved";
|
|
209
|
+
if (renamed || tempFd === undefined)
|
|
210
|
+
return "not-needed";
|
|
211
|
+
return await cleanupPinnedFilePath({
|
|
212
|
+
pathname: path.join(parentPath, tempName), handle: { fd: tempFd },
|
|
213
|
+
identity: tempIdentity, parentGuard, throwOnCleanupError: true,
|
|
214
|
+
});
|
|
215
|
+
},
|
|
216
|
+
close: [
|
|
217
|
+
() => { if (targetFd !== undefined)
|
|
218
|
+
closeFd(targetFd); },
|
|
219
|
+
() => { if (publicationProbeFd !== undefined)
|
|
220
|
+
closeFd(publicationProbeFd); },
|
|
221
|
+
closeTemp,
|
|
222
|
+
() => closeFd(parentFd),
|
|
223
|
+
() => root.close(),
|
|
224
|
+
],
|
|
99
225
|
});
|
|
100
226
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
227
|
+
else {
|
|
228
|
+
const targetCloseFailure = closeWriteFd(closeFd, targetFd);
|
|
229
|
+
const probeCloseFailure = closeWriteFd(closeFd, publicationProbeFd);
|
|
230
|
+
let tempCloseFailure;
|
|
231
|
+
try {
|
|
232
|
+
await closeTemp();
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
tempCloseFailure = { error };
|
|
236
|
+
}
|
|
237
|
+
if (!renamed) {
|
|
238
|
+
removeNativeCreatedFileIfStillPinned({
|
|
239
|
+
parentPath,
|
|
240
|
+
parentFd,
|
|
241
|
+
basename: tempName,
|
|
242
|
+
created: tempIdentity,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
const parentCloseFailure = closeWriteFd(closeFd, parentFd);
|
|
246
|
+
await root.close().catch(() => undefined);
|
|
247
|
+
const closeFailure = targetCloseFailure ?? probeCloseFailure ?? tempCloseFailure ?? parentCloseFailure;
|
|
248
|
+
if (completed && closeFailure)
|
|
249
|
+
throw closeFailure.error;
|
|
250
|
+
}
|
|
106
251
|
}
|
|
107
252
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-pinned-write.d.ts","sourceRoot":"","sources":["../src/native-pinned-write.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"native-pinned-write.d.ts","sourceRoot":"","sources":["../src/native-pinned-write.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAK3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,OAAO,KAAK,EAIV,iBAAiB,EAClB,MAAM,mBAAmB,CAAC;AA8W3B,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA8GvH"}
|
|
@@ -55,6 +55,7 @@ import path from "node:path";
|
|
|
55
55
|
import { inspectDirectoryIdentity } from "./directory-guard.js";
|
|
56
56
|
import { FsSafeError } from "./errors.js";
|
|
57
57
|
import { runPinnedWriteWindows } from "./native-pinned-write-windows.js";
|
|
58
|
+
import { capturePolicyAwareWindowsParent } from "./native-policy-parent-windows.js";
|
|
58
59
|
import { openNativeParentAdmission, openNativeRootAdmission } from "./native-parent-admission.js";
|
|
59
60
|
import { assertNativeStaging, writeNativeStage } from "./native-staged-file.js";
|
|
60
61
|
import { captureNativeFdClose } from "./native-binding.js";
|
|
@@ -367,15 +368,18 @@ export async function runPinnedWriteNative(binding, params) {
|
|
|
367
368
|
assertNativeStaging(binding);
|
|
368
369
|
}
|
|
369
370
|
const directoryFlags = fsSync.constants.O_RDONLY | (fsSync.constants.O_DIRECTORY ?? 0);
|
|
371
|
+
const completeCreate = params.overwrite === false && params.input.kind !== "file" && params.input.stageBeforePublish === true;
|
|
370
372
|
const rootAdmission = await openNativeRootAdmission(binding, {
|
|
371
373
|
rootPath: params.rootPath,
|
|
372
374
|
rootIdentity: params.rootIdentity,
|
|
373
375
|
operation: "native write",
|
|
376
|
+
reportCloseErrors: completeCreate,
|
|
374
377
|
});
|
|
375
378
|
const root = rootAdmission.root;
|
|
376
379
|
const posixRoot = __addDisposableResource(env_2, windows ? undefined : root, true);
|
|
377
380
|
let parentFd;
|
|
378
381
|
let windowsOwnsDirectories = false;
|
|
382
|
+
let admissionFailure;
|
|
379
383
|
// Until stage construction takes ownership, even admission failures must close
|
|
380
384
|
// the raw POSIX parent. Disposal preserves both admission and close failures.
|
|
381
385
|
const parentGuard = __addDisposableResource(env_2, {
|
|
@@ -389,14 +393,18 @@ export async function runPinnedWriteNative(binding, params) {
|
|
|
389
393
|
let parentPath;
|
|
390
394
|
let directory;
|
|
391
395
|
let parentPathStat;
|
|
392
|
-
let policyParentAdmitted = false;
|
|
393
396
|
if (!windows && params.mutationAdmission) {
|
|
394
397
|
const admitted = await capturePolicyAwarePosixParent(binding, params, root.fd, directoryFlags);
|
|
395
398
|
parentFd = admitted.parentFd;
|
|
396
399
|
parentPath = admitted.parentPath;
|
|
397
400
|
directory = admitted.directory;
|
|
398
401
|
parentPathStat = admitted.parentPathStat;
|
|
399
|
-
|
|
402
|
+
}
|
|
403
|
+
else if (windows && params.mutationAdmission) {
|
|
404
|
+
const admitted = await capturePolicyAwareWindowsParent(binding, params, rootAdmission);
|
|
405
|
+
parentFd = admitted.fd;
|
|
406
|
+
parentPath = admitted.guard.realPath;
|
|
407
|
+
parentPathStat = admitted.guard.stat;
|
|
400
408
|
}
|
|
401
409
|
else {
|
|
402
410
|
if (params.mkdir) {
|
|
@@ -409,15 +417,6 @@ export async function runPinnedWriteNative(binding, params) {
|
|
|
409
417
|
directory = admitted.stagedDirectory;
|
|
410
418
|
parentPathStat = admitted.guard.stat;
|
|
411
419
|
}
|
|
412
|
-
if (!policyParentAdmitted && params.mutationAdmission) {
|
|
413
|
-
const targetPath = path.join(parentPath, params.basename);
|
|
414
|
-
await authorizePinnedMutation(params, {
|
|
415
|
-
targetPath,
|
|
416
|
-
mutationPath: targetPath,
|
|
417
|
-
phase: "parent",
|
|
418
|
-
});
|
|
419
|
-
await inspectDirectoryIdentity(parentPath, inspectFileIdentitySync(() => fsSync.fstatSync(parentFd, { bigint: true })));
|
|
420
|
-
}
|
|
421
420
|
const verificationGuard = { dir: parentPath, realPath: parentPath, stat: parentPathStat };
|
|
422
421
|
if (params.overwrite === false) {
|
|
423
422
|
try {
|
|
@@ -439,8 +438,13 @@ export async function runPinnedWriteNative(binding, params) {
|
|
|
439
438
|
parentFd = undefined;
|
|
440
439
|
return await writeNativeStage(binding, ownedParent, closeFd, directory, params, verificationGuard);
|
|
441
440
|
}
|
|
441
|
+
catch (error) {
|
|
442
|
+
admissionFailure = { error };
|
|
443
|
+
throw error;
|
|
444
|
+
}
|
|
442
445
|
finally {
|
|
443
446
|
if (windows && !windowsOwnsDirectories) {
|
|
447
|
+
const closeErrors = [];
|
|
444
448
|
if (parentFd !== undefined) {
|
|
445
449
|
// Match the Windows leaf cleanup contract: an admission or identity
|
|
446
450
|
// failure remains primary, while every owned directory is still given
|
|
@@ -449,11 +453,19 @@ export async function runPinnedWriteNative(binding, params) {
|
|
|
449
453
|
try {
|
|
450
454
|
closeFd(parentFd);
|
|
451
455
|
}
|
|
452
|
-
catch {
|
|
453
|
-
|
|
456
|
+
catch (error) {
|
|
457
|
+
closeErrors.push(error);
|
|
454
458
|
}
|
|
455
459
|
}
|
|
456
|
-
|
|
460
|
+
try {
|
|
461
|
+
await root.close();
|
|
462
|
+
}
|
|
463
|
+
catch (error) {
|
|
464
|
+
closeErrors.push(error);
|
|
465
|
+
}
|
|
466
|
+
if (completeCreate && closeErrors.length > 0) {
|
|
467
|
+
throw new AggregateError([...(admissionFailure ? [admissionFailure.error] : []), ...closeErrors], "native create admission and close failed");
|
|
468
|
+
}
|
|
457
469
|
}
|
|
458
470
|
}
|
|
459
471
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type BigIntStats } from "node:fs";
|
|
2
|
+
import { type AsyncDirectoryGuard } from "./directory-guard.js";
|
|
3
|
+
import { type NativeRootAdmission } from "./native-parent-admission.js";
|
|
4
|
+
import type { NativeBinding } from "./native.js";
|
|
5
|
+
import type { PinnedWriteParams } from "./pinned-write.js";
|
|
6
|
+
import { type MutationDirectoryObservation } from "./pinned-mutation-observation.js";
|
|
7
|
+
type PolicyParent = {
|
|
8
|
+
fd: number;
|
|
9
|
+
guard: AsyncDirectoryGuard<BigIntStats>;
|
|
10
|
+
observation: MutationDirectoryObservation;
|
|
11
|
+
};
|
|
12
|
+
export declare function capturePolicyAwareWindowsParent(binding: NativeBinding, params: PinnedWriteParams, rootAdmission: NativeRootAdmission): Promise<PolicyParent>;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=native-policy-parent-windows.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-policy-parent-windows.d.ts","sourceRoot":"","sources":["../src/native-policy-parent-windows.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAEnD,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAA6B,KAAK,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAKjD,OAAO,KAAK,EAAE,iBAAiB,EAAkG,MAAM,mBAAmB,CAAC;AAC3J,OAAO,EAA4B,KAAK,4BAA4B,EAAE,MAAM,kCAAkC,CAAC;AAK/G,KAAK,YAAY,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC;IACxC,WAAW,EAAE,4BAA4B,CAAC;CAC3C,CAAC;AA4BF,wBAAsB,+BAA+B,CACnD,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,iBAAiB,EACzB,aAAa,EAAE,mBAAmB,GACjC,OAAO,CAAC,YAAY,CAAC,CA+KvB"}
|