@openclaw/fs-safe 0.13.0 → 0.14.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 +26 -1
- package/dist/copy-file-input.d.ts +1 -1
- package/dist/copy-file-input.d.ts.map +1 -1
- package/dist/copy-file-input.js +2 -0
- package/dist/file-store-sync-directory.d.ts.map +1 -1
- package/dist/file-store-sync-directory.js +14 -7
- package/dist/guest-dispatch-python.js +1 -1
- package/dist/native-binding.d.ts +9 -0
- package/dist/native-binding.d.ts.map +1 -1
- package/dist/native-binding.js +8 -1
- package/dist/native-operations.d.ts.map +1 -1
- package/dist/native-operations.js +6 -4
- package/dist/native-parent-admission.d.ts +1 -0
- package/dist/native-parent-admission.d.ts.map +1 -1
- package/dist/native-parent-admission.js +6 -3
- package/dist/native-pinned-write-windows.d.ts.map +1 -1
- package/dist/native-pinned-write-windows.js +8 -6
- package/dist/native-pinned-write.d.ts.map +1 -1
- package/dist/native-pinned-write.js +200 -163
- package/dist/native-policy-directory-observation.d.ts +12 -0
- package/dist/native-policy-directory-observation.d.ts.map +1 -0
- package/dist/native-policy-directory-observation.js +61 -0
- package/dist/native-staged-file.d.ts +4 -4
- package/dist/native-staged-file.d.ts.map +1 -1
- package/dist/native-staged-file.js +20 -10
- package/dist/native.d.ts +1 -1
- package/dist/native.d.ts.map +1 -1
- package/dist/native.js +7 -2
- package/dist/pinned-mutation-admission.d.ts.map +1 -1
- package/dist/pinned-mutation-admission.js +13 -24
- package/dist/pinned-mutation-observation.d.ts +7 -1
- package/dist/pinned-mutation-observation.d.ts.map +1 -1
- package/dist/pinned-mutation-observation.js +87 -5
- package/dist/publish-file.d.ts.map +1 -1
- package/dist/publish-file.js +5 -3
- package/dist/root-directory-creation.d.ts.map +1 -1
- package/dist/root-directory-creation.js +5 -4
- package/dist/root-impl.d.ts.map +1 -1
- package/dist/root-impl.js +2 -1
- package/dist/root-path-existing.d.ts.map +1 -1
- package/dist/root-path-existing.js +1 -2
- package/dist/root-write-compatibility.d.ts +1 -2
- package/dist/root-write-compatibility.d.ts.map +1 -1
- package/dist/root-write-compatibility.js +17 -68
- package/dist/root-write-complete-parent.d.ts.map +1 -1
- package/dist/root-write-complete-parent.js +3 -1
- package/dist/root-write-lock-binding.d.ts +15 -0
- package/dist/root-write-lock-binding.d.ts.map +1 -0
- package/dist/root-write-lock-binding.js +162 -0
- package/dist/staged-directory.d.ts +5 -2
- package/dist/staged-directory.d.ts.map +1 -1
- package/dist/staged-directory.js +37 -1
- package/dist/temp-workspace-admission.d.ts.map +1 -1
- package/dist/temp-workspace-admission.js +28 -4
- package/docs/guest.md +1 -1
- package/docs/native-helper.md +14 -1
- package/docs/native.md +8 -0
- package/docs/writing.md +6 -0
- package/package.json +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 0.14.0 - 2026-09-17
|
|
4
|
+
|
|
5
|
+
### Highlights
|
|
6
|
+
|
|
7
|
+
- **Safer guest directory selection:** descriptor-relative listings now report regular files as well as directories without following symlinks, so consumers can select files without reopening path-type checks.
|
|
8
|
+
|
|
9
|
+
### Filesystem boundaries and performance
|
|
10
|
+
|
|
11
|
+
- Report both directory and regular-file kinds from descriptor-relative guest listings. Symlinks and special entries report neither kind.
|
|
12
|
+
- Reduce repeated filesystem observations during policy-bound native parent creation, Windows compatibility writes and metadata reads, synchronous store-directory permission repair, and missing temporary-root creation. Fresh identity, canonical-path, lock-destination, callback, and publication checks remain at mutation boundaries.
|
|
13
|
+
|
|
14
|
+
### Validation
|
|
15
|
+
|
|
16
|
+
- Register the path-prefix and synchronous `lockRoot` performance workflows on the default branch. Their dispatch stubs fail closed without checking out or executing repository code.
|
|
17
|
+
|
|
18
|
+
## 0.13.1 - 2026-09-16
|
|
19
|
+
|
|
20
|
+
### Highlights
|
|
21
|
+
|
|
22
|
+
- **Correct native cleanup in Node workers:** guarded writes, moves, and staged-file cleanup close native-created descriptors through their originating binding, eliminating unmanaged-descriptor warnings while preserving Node's own descriptor tracking. ([#438](https://github.com/openclaw/fs-safe/pull/438))
|
|
23
|
+
|
|
24
|
+
### Fixes and compatibility
|
|
25
|
+
|
|
26
|
+
- Retain the correct closer through errors and native-mode changes, including staged files whose parent directory was opened by Node. Borrowed handles keep their caller-owned lifetime.
|
|
27
|
+
- On Windows, close exported descriptors through the same host runtime's libuv table that opened them. Descriptor-producing operations require complete native close support before allocation; stale helpers are treated as unavailable under the existing native-mode policy.
|
|
28
|
+
- Add real Worker coverage on Node 22/24 and verify that Windows native close releases both file and directory descriptors. Forced `Worker.terminate()` reclamation remains a [documented limitation](https://github.com/openclaw/fs-safe/blob/v0.13.1/docs/native-helper.md); callers should close retained resources and finish in-flight work before termination.
|
|
4
29
|
|
|
5
30
|
## 0.13.0 - 2026-09-16
|
|
6
31
|
|
|
@@ -2,7 +2,7 @@ import { type BigIntStats } from "node:fs";
|
|
|
2
2
|
import type { FileHandle } from "node:fs/promises";
|
|
3
3
|
import { type CopyCloneMode } from "./copy-policy.js";
|
|
4
4
|
import { type NativeBinding } from "./native.js";
|
|
5
|
-
import type
|
|
5
|
+
import { type NativeFileCopyResult } from "./native-binding.js";
|
|
6
6
|
export type CopyFileInput = {
|
|
7
7
|
kind: "file";
|
|
8
8
|
handle: FileHandle;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"copy-file-input.d.ts","sourceRoot":"","sources":["../src/copy-file-input.ts"],"names":[],"mappings":"AAAA,OAAW,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAE5E,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"copy-file-input.d.ts","sourceRoot":"","sources":["../src/copy-file-input.ts"],"names":[],"mappings":"AAAA,OAAW,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAE5E,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAwB,KAAK,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAItF,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B,CAAC;AAEF,wBAAgB,wBAAwB,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,aAAa,CAM5E;AAED,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EAChD,QAAQ,EAAE,WAAW,GACpB,OAAO,CAAC,IAAI,CAAC,CASf;AAED,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,aAAa,EACpB,QAAQ,CAAC,EAAE,MAAM,EACjB,oBAAoB,CAAC,EAAE,MAAM,IAAI,GAChC,OAAO,CAAC,IAAI,CAAC,CAIf;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,aAAa,EACpB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC,CA+B3C;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAWnG"}
|
package/dist/copy-file-input.js
CHANGED
|
@@ -2,6 +2,7 @@ import fs, {} from "node:fs";
|
|
|
2
2
|
import { resolveCopyCloneMode } from "./copy-policy.js";
|
|
3
3
|
import { FsSafeError } from "./errors.js";
|
|
4
4
|
import { getNativeBinding } from "./native.js";
|
|
5
|
+
import { captureNativeFdClose } from "./native-binding.js";
|
|
5
6
|
import { inspectFileIdentity } from "./strict-file-identity.js";
|
|
6
7
|
import { transferFileHandle } from "./file-handle-transfer.js";
|
|
7
8
|
export function resolveFileCopyCloneMode(mode) {
|
|
@@ -34,6 +35,7 @@ export async function createNativeCopyFile(native, input, parentFd, basename, ma
|
|
|
34
35
|
}
|
|
35
36
|
return undefined;
|
|
36
37
|
}
|
|
38
|
+
captureNativeFdClose(native);
|
|
37
39
|
const nativeSignal = input.signal ? AbortSignal.any([input.signal]) : undefined;
|
|
38
40
|
try {
|
|
39
41
|
// The caller adopts this descriptor before observing a later cancellation.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-store-sync-directory.d.ts","sourceRoot":"","sources":["../src/file-store-sync-directory.ts"],"names":[],"mappings":"AAAA,OAAW,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAc/C,KAAK,kBAAkB,GAAG,eAAe,GAAG,OAAO,CAAC;AAOpD,MAAM,MAAM,yBAAyB,GAAG,QAAQ,CAAC;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,WAAW,CAAC;CACxB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"file-store-sync-directory.d.ts","sourceRoot":"","sources":["../src/file-store-sync-directory.ts"],"names":[],"mappings":"AAAA,OAAW,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAc/C,KAAK,kBAAkB,GAAG,eAAe,GAAG,OAAO,CAAC;AAOpD,MAAM,MAAM,yBAAyB,GAAG,QAAQ,CAAC;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,WAAW,CAAC;CACxB,CAAC,CAAC;AA0VH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,kBAAkB,CAAC;CACnC,GAAG,yBAAyB,CA4D5B;AAED,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,yBAAyB,GACjC,IAAI,CAsBN"}
|
|
@@ -11,7 +11,9 @@ function changedStoreDirectory(messagePrefix, cause) {
|
|
|
11
11
|
return new FsSafeError("outside-workspace", `${messagePrefix} directory escapes root`, { cause });
|
|
12
12
|
}
|
|
13
13
|
function storeDirectoryRealPath(dir) {
|
|
14
|
-
const
|
|
14
|
+
const operationPath = pathForWindowsFilesystem(dir);
|
|
15
|
+
const realPath = process.platform === "win32"
|
|
16
|
+
? realpathSync(operationPath) : realpathSync.native(operationPath);
|
|
15
17
|
assertNoWindowsPathAlias(realPath, "filesystem");
|
|
16
18
|
return realPath;
|
|
17
19
|
}
|
|
@@ -72,7 +74,9 @@ function assertAdmittedEdgeCurrent(receipts, rootReal, messagePrefix) {
|
|
|
72
74
|
if (!rootReceipt || !targetReceipt) {
|
|
73
75
|
throw new FsSafeError("helper-failed", "store directory receipt is missing");
|
|
74
76
|
}
|
|
75
|
-
const rootStat =
|
|
77
|
+
const rootStat = rootReal === undefined
|
|
78
|
+
? inspectReceiptCurrent(rootReceipt, messagePrefix, true)
|
|
79
|
+
: assertRootCurrent(rootReceipt, rootReal, messagePrefix);
|
|
76
80
|
if (targetIndex === 0)
|
|
77
81
|
return rootStat;
|
|
78
82
|
const parent = receipts[targetIndex - 1];
|
|
@@ -87,10 +91,13 @@ function assertAdmittedEdgeCurrent(receipts, rootReal, messagePrefix) {
|
|
|
87
91
|
return targetStat;
|
|
88
92
|
}
|
|
89
93
|
function assertModeTargetCurrent(receipts, rootReal, messagePrefix) {
|
|
94
|
+
const root = receipts[0];
|
|
90
95
|
const target = receipts.at(-1);
|
|
91
|
-
if (!target)
|
|
96
|
+
if (!root || !target)
|
|
92
97
|
throw new FsSafeError("helper-failed", "store directory receipt is missing");
|
|
93
|
-
|
|
98
|
+
// The target's canonical observation shares the exact identity fence. Keep
|
|
99
|
+
// the trailing root canonical check: an ancestor relocation can retain IDs.
|
|
100
|
+
assertAdmittedEdgeCurrent(receipts, undefined, messagePrefix);
|
|
94
101
|
let targetReal;
|
|
95
102
|
try {
|
|
96
103
|
targetReal = storeDirectoryRealPath(target.dir);
|
|
@@ -98,10 +105,10 @@ function assertModeTargetCurrent(receipts, rootReal, messagePrefix) {
|
|
|
98
105
|
catch (error) {
|
|
99
106
|
throw changedStoreDirectory(messagePrefix, error);
|
|
100
107
|
}
|
|
101
|
-
if (!isPathInside(rootReal, targetReal))
|
|
108
|
+
if (target === root ? targetReal !== rootReal : !isPathInside(rootReal, targetReal)) {
|
|
102
109
|
throw changedStoreDirectory(messagePrefix);
|
|
103
|
-
|
|
104
|
-
return
|
|
110
|
+
}
|
|
111
|
+
return assertAdmittedEdgeCurrent(receipts, rootReal, messagePrefix);
|
|
105
112
|
}
|
|
106
113
|
function assertReceiptChain(receipts, rootReal, messagePrefix) {
|
|
107
114
|
const rootReceipt = receipts[0];
|
|
@@ -59,7 +59,7 @@ export const GUEST_FILESYSTEM_DISPATCH_PYTHON = [
|
|
|
59
59
|
" try:",
|
|
60
60
|
" target_fd = walk_dir(root_fd, sys.argv[3], False)",
|
|
61
61
|
" with os.scandir(target_fd) as entries:",
|
|
62
|
-
" print(json.dumps([{'name': entry.name, 'isDirectory': entry.is_dir(follow_symlinks=False)} for entry in entries]))",
|
|
62
|
+
" print(json.dumps([{'name': entry.name, 'isDirectory': entry.is_dir(follow_symlinks=False), 'isFile': entry.is_file(follow_symlinks=False)} for entry in entries]))",
|
|
63
63
|
" finally:",
|
|
64
64
|
" if target_fd is not None:",
|
|
65
65
|
" os.close(target_fd)",
|
package/dist/native-binding.d.ts
CHANGED
|
@@ -20,6 +20,10 @@ export interface NativeDirectoryObservation {
|
|
|
20
20
|
ino: bigint;
|
|
21
21
|
realPath: string;
|
|
22
22
|
}
|
|
23
|
+
export interface NativeDirectoryFdObservation extends NativeDirectoryObservation {
|
|
24
|
+
mode: bigint;
|
|
25
|
+
nlink: bigint;
|
|
26
|
+
}
|
|
23
27
|
export interface NativeArchiveEntry {
|
|
24
28
|
index: number;
|
|
25
29
|
path: string;
|
|
@@ -89,6 +93,8 @@ export interface NativeDarwinAclFacts {
|
|
|
89
93
|
state: "absent" | "empty" | "present";
|
|
90
94
|
}
|
|
91
95
|
export interface NativeBinding {
|
|
96
|
+
/** Internal: consumes only a descriptor returned by this binding. */
|
|
97
|
+
closeOwnedFd(fd: number): void;
|
|
92
98
|
/** Internal Darwin-only synchronous inspection; the caller retains its fd. */
|
|
93
99
|
inspectDarwinAcl?(fd: number): NativeDarwinAclFacts;
|
|
94
100
|
/** POSIX system canonicalization; confinement and identity policy stay with callers. */
|
|
@@ -98,6 +104,8 @@ export interface NativeBinding {
|
|
|
98
104
|
};
|
|
99
105
|
/** Internal: exact directory identity and canonical path from one no-follow handle. */
|
|
100
106
|
observeDirectory?(path: string): NativeDirectoryObservation;
|
|
107
|
+
/** Internal POSIX-only exact name/descriptor observation; the caller retains its fd. */
|
|
108
|
+
observeDirectoryFd?(fd: number, expectedPath: string): NativeDirectoryFdObservation;
|
|
101
109
|
/** Linux/Windows byte transfer; callers retain both admitted descriptors until settlement. */
|
|
102
110
|
copyFileContents?(sourceFd: number, targetFd: number, signal?: AbortSignal): Promise<void>;
|
|
103
111
|
/** Internal: same private, immutable input ownership as the ZIP buffer reader. */
|
|
@@ -139,4 +147,5 @@ export interface NativeBinding {
|
|
|
139
147
|
renameReplace(sourceRootFd: number, sourceRelPath: string, targetRootFd: number, targetRelPath: string): void;
|
|
140
148
|
sha256File(fd: number, maxBytes?: number, signal?: AbortSignal): Promise<NativeFileHash>;
|
|
141
149
|
}
|
|
150
|
+
export declare function captureNativeFdClose(binding: NativeBinding): (fd: number) => void;
|
|
142
151
|
//# sourceMappingURL=native-binding.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-binding.d.ts","sourceRoot":"","sources":["../src/native-binding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"native-binding.d.ts","sourceRoot":"","sources":["../src/native-binding.ts"],"names":[],"mappings":"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"}
|
package/dist/native-binding.js
CHANGED
|
@@ -1 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import { FsSafeError } from "./errors.js";
|
|
2
|
+
export function captureNativeFdClose(binding) {
|
|
3
|
+
if (typeof binding.closeOwnedFd !== "function") {
|
|
4
|
+
throw new FsSafeError("helper-unavailable", "native descriptor ownership is unavailable");
|
|
5
|
+
}
|
|
6
|
+
// Retained descriptors must remain disposable after native configuration changes.
|
|
7
|
+
return binding.closeOwnedFd.bind(binding);
|
|
8
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-operations.d.ts","sourceRoot":"","sources":["../src/native-operations.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,WAAW,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAG/D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"native-operations.d.ts","sourceRoot":"","sources":["../src/native-operations.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,WAAW,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAG/D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAK7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAI1D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,WAAW,EAAE,oBAAoB,CAAC;IAC3C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC;IACvB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5E,CAAC;AAEF,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOrD;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAS5D;AAED,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,gBAAgB,EACvB,QAAQ,CAAC,EAAE,MAAM,EACjB,oBAAoB,CAAC,EAAE,MAAM,IAAI,GAChC,OAAO,CAAC,IAAI,CAAC,CAoBf;AA0BD,wBAAgB,oCAAoC,CAAC,MAAM,EAAE;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB,GAAG,IAAI,CAqBP;AAED,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAyDvC"}
|
|
@@ -4,6 +4,7 @@ import path from "node:path";
|
|
|
4
4
|
import { FsSafeError } from "./errors.js";
|
|
5
5
|
import { sameFileIdentityForCleanup } from "./file-identity.js";
|
|
6
6
|
import { getNativeBinding } from "./native.js";
|
|
7
|
+
import { captureNativeFdClose } from "./native-binding.js";
|
|
7
8
|
import { writeAllToFile } from "./write-file-handle.js";
|
|
8
9
|
import { writeCopyFileToFd } from "./copy-file-input.js";
|
|
9
10
|
export function nativeOpenFlags(flags) {
|
|
@@ -44,7 +45,7 @@ export async function writeNativeInput(fd, input, maxBytes, assertBeforeMutation
|
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
|
-
function wrapNativeFd(fd, containment) {
|
|
48
|
+
function wrapNativeFd(fd, containment, closeFd) {
|
|
48
49
|
let open = true;
|
|
49
50
|
return {
|
|
50
51
|
fd,
|
|
@@ -52,7 +53,7 @@ function wrapNativeFd(fd, containment) {
|
|
|
52
53
|
async close() {
|
|
53
54
|
if (open) {
|
|
54
55
|
open = false;
|
|
55
|
-
|
|
56
|
+
closeFd(fd);
|
|
56
57
|
}
|
|
57
58
|
},
|
|
58
59
|
async stat() {
|
|
@@ -89,6 +90,7 @@ export async function createNativeExclusiveFile(targetPath, mode) {
|
|
|
89
90
|
if (!binding) {
|
|
90
91
|
return undefined;
|
|
91
92
|
}
|
|
93
|
+
const closeFd = captureNativeFdClose(binding);
|
|
92
94
|
const parentPath = path.dirname(targetPath);
|
|
93
95
|
const basename = path.basename(targetPath);
|
|
94
96
|
const parent = await fs.open(parentPath, fsSync.constants.O_RDONLY |
|
|
@@ -113,12 +115,12 @@ export async function createNativeExclusiveFile(targetPath, mode) {
|
|
|
113
115
|
fd = opened.fd;
|
|
114
116
|
fsSync.fchmodSync(fd, mode);
|
|
115
117
|
created = fsSync.fstatSync(fd, { bigint: true });
|
|
116
|
-
return wrapNativeFd(fd, opened.containment);
|
|
118
|
+
return wrapNativeFd(fd, opened.containment, closeFd);
|
|
117
119
|
}
|
|
118
120
|
catch (error) {
|
|
119
121
|
if (fd !== undefined) {
|
|
120
122
|
try {
|
|
121
|
-
|
|
123
|
+
closeFd(fd);
|
|
122
124
|
}
|
|
123
125
|
catch {
|
|
124
126
|
// Preserve the original error.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-parent-admission.d.ts","sourceRoot":"","sources":["../src/native-parent-admission.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,WAAW,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAKnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"native-parent-admission.d.ts","sourceRoot":"","sources":["../src/native-parent-admission.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,WAAW,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAKnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,OAAO,EAAE,uBAAuB,EAAwB,MAAM,uBAAuB,CAAC;AAKtF,KAAK,YAAY,GAAG,IAAI,CAAC,gBAAgB,EAAE,KAAK,GAAG,KAAK,CAAC,CAAC;AAE1D,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,IAAI,IAAI,CAAC;IACd,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,KAAK,GAAG,WAAW,CAAA;KAAE,CAAC;IACpE,eAAe,CAAC,EAAE,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC;CAC9D,CAAC;AAEF,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,YAAY,GAClB,OAAO,CAET;AAaD,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5E,OAAO,CAAC,mBAAmB,CAAC,CAgD9B;AAED,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,aAAa,EACtB,aAAa,EAAE,mBAAmB,EAClC,kBAAkB,EAAE,MAAM,GACzB,OAAO,CAAC,qBAAqB,CAAC,CA+DhC;AAED,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,qBAAqB,GAAG,SAAS,GAAG,IAAI,CAE7F"}
|
|
@@ -3,6 +3,7 @@ import fs from "node:fs/promises";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { inspectDirectoryIdentity } from "./directory-guard.js";
|
|
5
5
|
import { FsSafeError } from "./errors.js";
|
|
6
|
+
import { captureNativeFdClose } from "./native-binding.js";
|
|
6
7
|
import { realpathSync } from "./realpath.js";
|
|
7
8
|
import { describeStagedDirectory, exactIdentityMatches } from "./staged-directory.js";
|
|
8
9
|
import { inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
@@ -18,6 +19,7 @@ function assertParentAdmissionAvailable(binding) {
|
|
|
18
19
|
if (typeof binding.openBeneath !== "function") {
|
|
19
20
|
throw unavailable("native parent directory admission is unavailable");
|
|
20
21
|
}
|
|
22
|
+
captureNativeFdClose(binding);
|
|
21
23
|
}
|
|
22
24
|
export async function openNativeRootAdmission(binding, params) {
|
|
23
25
|
assertParentAdmissionAvailable(binding);
|
|
@@ -68,6 +70,7 @@ export async function openNativeRootAdmission(binding, params) {
|
|
|
68
70
|
}
|
|
69
71
|
export async function openNativeParentAdmission(binding, rootAdmission, relativeParentPath) {
|
|
70
72
|
assertParentAdmissionAvailable(binding);
|
|
73
|
+
const closeFd = captureNativeFdClose(binding);
|
|
71
74
|
const directoryFlags = fsSync.constants.O_RDONLY | (fsSync.constants.O_DIRECTORY ?? 0);
|
|
72
75
|
assertNoWindowsPathAlias(relativeParentPath, "relative", "native parent uses a Windows filesystem namespace alias");
|
|
73
76
|
const opened = binding.openBeneath(rootAdmission.root.fd, relativeParentPath, directoryFlags);
|
|
@@ -102,13 +105,14 @@ export async function openNativeParentAdmission(binding, rootAdmission, relative
|
|
|
102
105
|
}
|
|
103
106
|
return {
|
|
104
107
|
fd: parentFd,
|
|
108
|
+
close: () => closeFd(parentFd),
|
|
105
109
|
guard: { dir: parentPath, realPath: parentPath, stat: parentPathStat },
|
|
106
110
|
stagedDirectory,
|
|
107
111
|
};
|
|
108
112
|
}
|
|
109
113
|
catch (error) {
|
|
110
114
|
try {
|
|
111
|
-
|
|
115
|
+
closeFd(parentFd);
|
|
112
116
|
}
|
|
113
117
|
catch (closeError) {
|
|
114
118
|
if (process.platform !== "win32") {
|
|
@@ -119,6 +123,5 @@ export async function openNativeParentAdmission(binding, rootAdmission, relative
|
|
|
119
123
|
}
|
|
120
124
|
}
|
|
121
125
|
export function closeNativeParentAdmission(admission) {
|
|
122
|
-
|
|
123
|
-
fsSync.closeSync(admission.fd);
|
|
126
|
+
admission?.close();
|
|
124
127
|
}
|
|
@@ -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;AACnD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAEnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAM3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,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;AACnD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAEnE,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;AAa3D,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,CA2F3B"}
|
|
@@ -4,19 +4,21 @@ import fsSync, {} from "node:fs";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { FsSafeError } from "./errors.js";
|
|
6
6
|
import { nativeOpenFlags, removeNativeCreatedFileIfStillPinned, writeNativeInput, } from "./native-operations.js";
|
|
7
|
+
import { captureNativeFdClose } from "./native-binding.js";
|
|
7
8
|
import { inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
8
9
|
import { assertFinalSymlinkRejected } from "./root-symlink-policy.js";
|
|
9
|
-
function closeWriteFd(fd) {
|
|
10
|
+
function closeWriteFd(closeFd, fd) {
|
|
10
11
|
if (fd === undefined)
|
|
11
12
|
return;
|
|
12
13
|
try {
|
|
13
|
-
|
|
14
|
+
closeFd(fd);
|
|
14
15
|
}
|
|
15
16
|
catch (error) {
|
|
16
17
|
return error;
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
20
|
export async function runPinnedWriteWindows(binding, params, root, parentFd, parentGuard) {
|
|
21
|
+
const closeFd = captureNativeFdClose(binding);
|
|
20
22
|
const parentPath = parentGuard.realPath;
|
|
21
23
|
let tempFd;
|
|
22
24
|
let targetFd;
|
|
@@ -64,7 +66,7 @@ export async function runPinnedWriteWindows(binding, params, root, parentFd, par
|
|
|
64
66
|
syncFileBestEffortSync(targetFd);
|
|
65
67
|
}
|
|
66
68
|
catch (error) {
|
|
67
|
-
closeWriteFd(targetFd);
|
|
69
|
+
closeWriteFd(closeFd, targetFd);
|
|
68
70
|
targetFd = undefined;
|
|
69
71
|
// Staged copies and streamed creates preserve publication for caller recovery.
|
|
70
72
|
if (params.input.kind === "buffer" ||
|
|
@@ -86,8 +88,8 @@ export async function runPinnedWriteWindows(binding, params, root, parentFd, par
|
|
|
86
88
|
return { dev: targetIdentity.dev, ino: targetIdentity.ino };
|
|
87
89
|
}
|
|
88
90
|
finally {
|
|
89
|
-
const targetCloseError = closeWriteFd(targetFd);
|
|
90
|
-
const tempCloseError = closeWriteFd(tempFd);
|
|
91
|
+
const targetCloseError = closeWriteFd(closeFd, targetFd);
|
|
92
|
+
const tempCloseError = closeWriteFd(closeFd, tempFd);
|
|
91
93
|
if (!renamed) {
|
|
92
94
|
removeNativeCreatedFileIfStillPinned({
|
|
93
95
|
parentPath,
|
|
@@ -96,7 +98,7 @@ export async function runPinnedWriteWindows(binding, params, root, parentFd, par
|
|
|
96
98
|
created: tempIdentity,
|
|
97
99
|
});
|
|
98
100
|
}
|
|
99
|
-
const parentCloseError = closeWriteFd(parentFd);
|
|
101
|
+
const parentCloseError = closeWriteFd(closeFd, parentFd);
|
|
100
102
|
await root.close().catch(() => undefined);
|
|
101
103
|
const closeError = targetCloseError ?? tempCloseError ?? parentCloseError;
|
|
102
104
|
if (completed && closeError !== undefined)
|
|
@@ -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;AAI3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,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;AAI3D,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,CAsGvH"}
|