@openclaw/fs-safe 0.8.2 → 0.8.3
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 +9 -0
- package/README.md +1 -1
- package/dist/advanced.d.ts +2 -2
- package/dist/advanced.d.ts.map +1 -1
- package/dist/advanced.js +2 -2
- package/dist/archive-kind.d.ts +1 -0
- package/dist/archive-kind.d.ts.map +1 -1
- package/dist/archive-kind.js +6 -0
- package/dist/archive-limits.d.ts +0 -1
- package/dist/archive-limits.d.ts.map +1 -1
- package/dist/archive-limits.js +0 -3
- package/dist/archive-native.d.ts.map +1 -1
- package/dist/archive-native.js +5 -8
- package/dist/archive-parser-errors.d.ts +2 -0
- package/dist/archive-parser-errors.d.ts.map +1 -0
- package/dist/archive-parser-errors.js +12 -0
- package/dist/archive-read.d.ts.map +1 -1
- package/dist/archive-read.js +7 -13
- package/dist/archive-tar-wasm.d.ts +1 -1
- package/dist/archive-tar-wasm.d.ts.map +1 -1
- package/dist/archive-tar-wasm.js +5 -8
- package/dist/archive.d.ts.map +1 -1
- package/dist/archive.js +43 -6
- package/dist/atomic.d.ts +1 -1
- package/dist/atomic.d.ts.map +1 -1
- package/dist/atomic.js +1 -1
- package/dist/bounded-read-stream.d.ts +1 -5
- package/dist/bounded-read-stream.d.ts.map +1 -1
- package/dist/bounded-read-stream.js +5 -13
- package/dist/byte-budget.d.ts +0 -1
- package/dist/byte-budget.d.ts.map +1 -1
- package/dist/byte-budget.js +1 -1
- package/dist/directory-mode-owner.d.ts.map +1 -1
- package/dist/directory-mode-owner.js +2 -0
- package/dist/error-detail.d.ts +1 -0
- package/dist/error-detail.d.ts.map +1 -1
- package/dist/error-detail.js +6 -0
- package/dist/file-store-boundary.d.ts +1 -1
- package/dist/file-store-boundary.d.ts.map +1 -1
- package/dist/file-store-boundary.js +2 -13
- package/dist/file-store.js +1 -1
- package/dist/file-sync.d.ts +5 -0
- package/dist/file-sync.d.ts.map +1 -0
- package/dist/file-sync.js +19 -0
- package/dist/guarded-mutation.d.ts +3 -0
- package/dist/guarded-mutation.d.ts.map +1 -1
- package/dist/guarded-mutation.js +5 -1
- package/dist/home-dir.d.ts +0 -10
- package/dist/home-dir.d.ts.map +1 -1
- package/dist/home-dir.js +0 -28
- package/dist/json-durable-queue-ownership.d.ts +1 -0
- package/dist/json-durable-queue-ownership.d.ts.map +1 -1
- package/dist/json-durable-queue-ownership.js +139 -18
- package/dist/json-durable-queue.d.ts.map +1 -1
- package/dist/json-durable-queue.js +5 -10
- package/dist/json-store.d.ts.map +1 -1
- package/dist/json-store.js +1 -1
- package/dist/local-roots.d.ts.map +1 -1
- package/dist/local-roots.js +2 -3
- package/dist/move-path-cleanup.d.ts +1 -1
- package/dist/move-path-cleanup.d.ts.map +1 -1
- package/dist/move-path-cleanup.js +4 -2
- package/dist/move-path.d.ts +9 -0
- package/dist/move-path.d.ts.map +1 -1
- package/dist/move-path.js +53 -16
- package/dist/native-operations.d.ts +0 -1
- package/dist/native-operations.d.ts.map +1 -1
- package/dist/native-operations.js +0 -10
- package/dist/native-pinned-write-windows.d.ts.map +1 -1
- package/dist/native-pinned-write-windows.js +5 -4
- package/dist/native-staged-file.d.ts +8 -1
- package/dist/native-staged-file.d.ts.map +1 -1
- package/dist/native-staged-file.js +30 -9
- package/dist/opened-realpath.d.ts +12 -1
- package/dist/opened-realpath.d.ts.map +1 -1
- package/dist/opened-realpath.js +8 -7
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +26 -2
- package/dist/path-policy.js +1 -1
- package/dist/permissions.d.ts +1 -0
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +3 -0
- package/dist/pinned-write.d.ts +1 -2
- package/dist/pinned-write.d.ts.map +1 -1
- package/dist/pinned-write.js +2 -11
- package/dist/private-temp-workspace.js +1 -1
- package/dist/publish-file.js +2 -2
- package/dist/replace-file-copy-source.d.ts.map +1 -1
- package/dist/replace-file-copy-source.js +2 -7
- package/dist/replace-file-descriptor.d.ts.map +1 -1
- package/dist/replace-file-descriptor.js +3 -16
- package/dist/replace-file-temp-owner.d.ts.map +1 -1
- package/dist/replace-file-temp-owner.js +2 -7
- package/dist/replace-file.d.ts.map +1 -1
- package/dist/replace-file.js +21 -8
- package/dist/root-errors.d.ts +1 -0
- package/dist/root-errors.d.ts.map +1 -1
- package/dist/root-errors.js +9 -0
- package/dist/root-file.d.ts.map +1 -1
- package/dist/root-file.js +17 -28
- package/dist/root-impl.d.ts.map +1 -1
- package/dist/root-impl.js +12 -33
- package/dist/root-path.d.ts.map +1 -1
- package/dist/root-path.js +49 -94
- package/dist/root-write-mode.d.ts +6 -0
- package/dist/root-write-mode.d.ts.map +1 -0
- package/dist/root-write-mode.js +60 -0
- package/dist/root-write-verification.js +2 -2
- package/dist/safe-path-segment.d.ts +1 -0
- package/dist/safe-path-segment.d.ts.map +1 -1
- package/dist/safe-path-segment.js +1 -1
- package/dist/secret-file.d.ts.map +1 -1
- package/dist/secret-file.js +2 -9
- package/dist/secret-read-async.d.ts.map +1 -1
- package/dist/secret-read-async.js +2 -10
- package/dist/secret-read-policy.d.ts +4 -0
- package/dist/secret-read-policy.d.ts.map +1 -1
- package/dist/secret-read-policy.js +12 -0
- package/dist/sibling-staged-file.d.ts.map +1 -1
- package/dist/sibling-staged-file.js +2 -7
- package/dist/sidecar-lock-policy.d.ts +0 -1
- package/dist/sidecar-lock-policy.d.ts.map +1 -1
- package/dist/sidecar-lock-policy.js +0 -4
- package/dist/string-coerce.d.ts +0 -9
- package/dist/string-coerce.d.ts.map +1 -1
- package/dist/string-coerce.js +0 -56
- package/dist/temp-target.d.ts.map +1 -1
- package/dist/temp-target.js +1 -12
- package/docs/atomic.md +53 -19
- package/docs/staged-file.md +6 -2
- package/docs/writing.md +5 -0
- package/package.json +8 -8
- package/dist/archive-tar-extract.d.ts +0 -11
- package/dist/archive-tar-extract.d.ts.map +0 -1
- package/dist/archive-tar-extract.js +0 -49
- package/dist/fsync.d.ts +0 -2
- package/dist/fsync.d.ts.map +0 -1
- package/dist/fsync.js +0 -1
- package/dist/json-durable-queue-retirement.d.ts +0 -9
- package/dist/json-durable-queue-retirement.d.ts.map +0 -1
- package/dist/json-durable-queue-retirement.js +0 -126
- package/dist/json-durable-queue-transfer-lock.d.ts +0 -2
- package/dist/json-durable-queue-transfer-lock.d.ts.map +0 -1
- package/dist/json-durable-queue-transfer-lock.js +0 -19
- package/dist/mode.d.ts +0 -2
- package/dist/mode.d.ts.map +0 -1
- package/dist/mode.js +0 -3
- package/dist/output-sibling.d.ts +0 -8
- package/dist/output-sibling.d.ts.map +0 -1
- package/dist/output-sibling.js +0 -30
- package/dist/read-error.d.ts +0 -2
- package/dist/read-error.d.ts.map +0 -1
- package/dist/read-error.js +0 -11
- package/dist/short-path.d.ts +0 -2
- package/dist/short-path.d.ts.map +0 -1
- package/dist/short-path.js +0 -7
- package/dist/staged-file.d.ts +0 -10
- package/dist/staged-file.d.ts.map +0 -1
- package/dist/staged-file.js +0 -15
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-pinned-write-windows.d.ts","sourceRoot":"","sources":["../src/native-pinned-write-windows.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"native-pinned-write-windows.d.ts","sourceRoot":"","sources":["../src/native-pinned-write-windows.ts"],"names":[],"mappings":"AAGA,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;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAG3D,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,IAAI,CAAC,gBAAgB,EAAE,KAAK,GAAG,KAAK,CAAC,EAC3C,KAAK,EAAE,IAAI,CAAC,gBAAgB,EAAE,KAAK,GAAG,KAAK,CAAC,GAC3C,OAAO,CAET;AAWD,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,CAiF3B"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { syncFileBestEffortSync } from "./file-sync.js";
|
|
1
2
|
import { randomUUID } from "node:crypto";
|
|
2
3
|
import fsSync, {} from "node:fs";
|
|
3
4
|
import { FsSafeError } from "./errors.js";
|
|
4
|
-
import { nativeOpenFlags, removeNativeCreatedFileIfStillPinned,
|
|
5
|
+
import { nativeOpenFlags, removeNativeCreatedFileIfStillPinned, writeNativeInput, } from "./native-operations.js";
|
|
5
6
|
import { inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
6
7
|
export function sameNativeIdentity(left, right) {
|
|
7
8
|
return left.dev === right.dev && left.ino === right.ino;
|
|
@@ -34,7 +35,7 @@ export async function runPinnedWriteWindows(binding, params, root, parentFd, par
|
|
|
34
35
|
// reopenable until the published name has been identity-fenced.
|
|
35
36
|
fsSync.fchmodSync(tempFd, 0o600);
|
|
36
37
|
await writeNativeInput(tempFd, params.input, params.maxBytes);
|
|
37
|
-
|
|
38
|
+
syncFileBestEffortSync(tempFd);
|
|
38
39
|
if (params.overwrite === false) {
|
|
39
40
|
binding.renameNoReplace(parentFd, tempName, parentFd, params.basename);
|
|
40
41
|
}
|
|
@@ -53,7 +54,7 @@ export async function runPinnedWriteWindows(binding, params, root, parentFd, par
|
|
|
53
54
|
// verifiable and so broader modes are never exposed before that fence.
|
|
54
55
|
try {
|
|
55
56
|
fsSync.fchmodSync(targetFd, params.mode);
|
|
56
|
-
|
|
57
|
+
syncFileBestEffortSync(targetFd);
|
|
57
58
|
}
|
|
58
59
|
catch (error) {
|
|
59
60
|
closeWriteFd(targetFd);
|
|
@@ -66,7 +67,7 @@ export async function runPinnedWriteWindows(binding, params, root, parentFd, par
|
|
|
66
67
|
});
|
|
67
68
|
throw error;
|
|
68
69
|
}
|
|
69
|
-
|
|
70
|
+
syncFileBestEffortSync(parentFd);
|
|
70
71
|
// Verification follows publication and final chmod, outside rollback handling.
|
|
71
72
|
await params.verifyPublished?.(targetFd, verificationIdentity, parentGuard);
|
|
72
73
|
completed = true;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DirectoryReceipt } from "./directory-durability.js";
|
|
1
2
|
import type { AnyAsyncDirectoryGuard } from "./directory-guard.js";
|
|
2
3
|
import type { FileIdentityStat } from "./file-identity.js";
|
|
3
4
|
import type { NativeBinding } from "./native-binding.js";
|
|
@@ -20,5 +21,11 @@ declare class NativeStagedFile implements StagedFile {
|
|
|
20
21
|
}
|
|
21
22
|
export declare const createNativeStage: (...args: Parameters<typeof NativeStagedFile.create>) => Promise<StagedFile>;
|
|
22
23
|
export declare const writeNativeStage: typeof NativeStagedFile.write;
|
|
23
|
-
export {};
|
|
24
|
+
export type { PublishedFileReceipt, StagedFile, StagedFileCleanupReceipt, StagedFileFailureDetails, StagedFilePublication, StagedFileReceipt, } from "./staged-file-types.js";
|
|
25
|
+
export declare function stageFileInDirectory(options: {
|
|
26
|
+
directory: string | DirectoryReceipt;
|
|
27
|
+
content: string | Uint8Array;
|
|
28
|
+
/** Published mode; the unpublished stage stays at 0600. Defaults to 0600. */
|
|
29
|
+
mode?: number;
|
|
30
|
+
}): Promise<StagedFile>;
|
|
24
31
|
//# sourceMappingURL=native-staged-file.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-staged-file.d.ts","sourceRoot":"","sources":["../src/native-staged-file.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"native-staged-file.d.ts","sourceRoot":"","sources":["../src/native-staged-file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAKlE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAEnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE7E,OAAO,KAAK,EACV,oBAAoB,EACpB,UAAU,EACV,wBAAwB,EAGxB,iBAAiB,EAClB,MAAM,wBAAwB,CAAC;AAEhC,MAAM,MAAM,oBAAoB,GAAG,aAAa,GAAG,QAAQ,CAAC,IAAI,CAC9D,aAAa,EACb,kBAAkB,GAAG,mBAAmB,GAAG,kBAAkB,CAC9D,CAAC,CAAC;AAEH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,IAAI,oBAAoB,CAUnG;AA6BD,cAAM,gBAAiB,YAAW,UAAU;;IAU1C,YACE,OAAO,EAAE,oBAAoB,EAC7B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,iBAAiB,CAAC,WAAW,CAAC,EACzC,aAAa,EAAE,OAAO,EACtB,aAAa,EAAE,MAAM,EAOtB;IAGD,OAAa,MAAM,CACjB,OAAO,EAAE,oBAAoB,EAC7B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,iBAAiB,CAAC,WAAW,CAAC,EACzC,KAAK,EAAE,gBAAgB,EACvB,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,MAAM,EAEjB,aAAa,UAAO,GACnB,OAAO,CAAC,gBAAgB,CAAC,CAc3B;IAED,OAAa,KAAK,CAChB,OAAO,EAAE,oBAAoB,EAC7B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,iBAAiB,CAAC,WAAW,CAAC,EACzC,MAAM,EAAE,iBAAiB,EACzB,WAAW,EAAE,sBAAsB,GAClC,OAAO,CAAC,gBAAgB,CAAC,CAU3B;IAED,IAAI,OAAO,IAAI,iBAAiB,CAK/B;IAoFK,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAEnC;IAEK,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAqD9F;IA6CK,OAAO,IAAI,OAAO,CAAC,wBAAwB,CAAC,CAMjD;IAEK,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAO3C;CACF;AAED,eAAO,MAAM,iBAAiB,EAAE,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC,UAAU,CAClF,CAAC;AAC1B,eAAO,MAAM,gBAAgB,+BAAyB,CAAC;AAEvD,YAAY,EACV,oBAAoB,EAAE,UAAU,EAAE,wBAAwB,EAAE,wBAAwB,EACpF,qBAAqB,EAAE,iBAAiB,GACzC,MAAM,wBAAwB,CAAC;AAEhC,wBAAsB,oBAAoB,CAAC,OAAO,EAAE;IAClD,SAAS,EAAE,MAAM,GAAG,gBAAgB,CAAC;IACrC,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC;IAC7B,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,OAAO,CAAC,UAAU,CAAC,CAUtB"}
|
|
@@ -50,11 +50,13 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
50
50
|
var e = new Error(message);
|
|
51
51
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
52
|
});
|
|
53
|
+
import { requireNativeBinding } from "./native.js";
|
|
54
|
+
import { syncFileBestEffortSync } from "./file-sync.js";
|
|
53
55
|
import { randomUUID } from "node:crypto";
|
|
54
56
|
import fs from "node:fs";
|
|
55
57
|
import { FsSafeError } from "./errors.js";
|
|
56
|
-
import {
|
|
57
|
-
import { assertStagedDirectoryCurrent } from "./staged-directory.js";
|
|
58
|
+
import { writeNativeInput } from "./native-operations.js";
|
|
59
|
+
import { assertStagedDirectoryCurrent, openStagedDirectory } from "./staged-directory.js";
|
|
58
60
|
export function assertNativeStaging(binding) {
|
|
59
61
|
if ([
|
|
60
62
|
binding.createStagedFile,
|
|
@@ -162,10 +164,12 @@ class NativeStagedFile {
|
|
|
162
164
|
}
|
|
163
165
|
#assertNamed(name) {
|
|
164
166
|
const fd = this.#file();
|
|
165
|
-
|
|
166
|
-
fs.fstatSync(fd, { bigint: true })
|
|
167
|
+
const stat = this.#binding.stagedFileMatches(this.#parentFd, name, fd)
|
|
168
|
+
? fs.fstatSync(fd, { bigint: true }) : undefined;
|
|
169
|
+
if (!stat || stat.nlink !== 1n) {
|
|
167
170
|
throw new FsSafeError("path-mismatch", "staged entry no longer names the exclusive created file");
|
|
168
171
|
}
|
|
172
|
+
return Number(stat.mode & 4095n);
|
|
169
173
|
}
|
|
170
174
|
#assertCurrent() {
|
|
171
175
|
if (this.#open().publication.status !== "not-published") {
|
|
@@ -188,7 +192,7 @@ class NativeStagedFile {
|
|
|
188
192
|
const fd = state.fileFd;
|
|
189
193
|
fs.fchmodSync(fd, 0o600);
|
|
190
194
|
await writeNativeInput(fd, input, maxBytes);
|
|
191
|
-
|
|
195
|
+
syncFileBestEffortSync(fd);
|
|
192
196
|
const stat = fs.fstatSync(fd, { bigint: true });
|
|
193
197
|
this.#receipt = Object.freeze({
|
|
194
198
|
directory: this.#directory,
|
|
@@ -255,14 +259,20 @@ class NativeStagedFile {
|
|
|
255
259
|
overwrite,
|
|
256
260
|
});
|
|
257
261
|
state.publication = receipt;
|
|
258
|
-
this.#assertNamed(basename);
|
|
262
|
+
const stagedMode = this.#assertNamed(basename);
|
|
259
263
|
assertStagedDirectoryCurrent(this.#directory);
|
|
260
264
|
// Keep contents private until the published name passes its identity
|
|
261
265
|
// fence. Mode changes use the owned fd, including for final mode 000.
|
|
262
266
|
const fd = this.#file();
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
267
|
+
if (this.#publishedMode !== 0o600 || stagedMode !== 0o600)
|
|
268
|
+
fs.fchmodSync(fd, this.#publishedMode);
|
|
269
|
+
// Content was synced before rename. A lost chmod leaves staged 0600,
|
|
270
|
+
// no wider than modes retaining owner rw. Restrictive modes and observed
|
|
271
|
+
// widening of the stage still need the permission correction made durable.
|
|
272
|
+
if ((this.#publishedMode & 0o600) !== 0o600 || (stagedMode & ~this.#publishedMode) !== 0) {
|
|
273
|
+
syncFileBestEffortSync(fd);
|
|
274
|
+
}
|
|
275
|
+
syncFileBestEffortSync(this.#parentFd);
|
|
266
276
|
this.#assertNamed(basename);
|
|
267
277
|
assertStagedDirectoryCurrent(this.#directory);
|
|
268
278
|
return receipt;
|
|
@@ -335,3 +345,14 @@ class NativeStagedFile {
|
|
|
335
345
|
}
|
|
336
346
|
export const createNativeStage = NativeStagedFile.create;
|
|
337
347
|
export const writeNativeStage = NativeStagedFile.write;
|
|
348
|
+
export async function stageFileInDirectory(options) {
|
|
349
|
+
if (process.platform !== "linux" && process.platform !== "darwin") {
|
|
350
|
+
throw new FsSafeError("unsupported-platform", "retained-directory staging requires Linux or macOS");
|
|
351
|
+
}
|
|
352
|
+
const binding = requireNativeBinding();
|
|
353
|
+
assertNativeStaging(binding);
|
|
354
|
+
const input = { kind: "buffer", data: Buffer.from(options.content) };
|
|
355
|
+
const mode = options.mode ?? 0o600;
|
|
356
|
+
const parent = openStagedDirectory(options.directory);
|
|
357
|
+
return await createNativeStage(binding, parent.fd, parent.receipt, input, mode);
|
|
358
|
+
}
|
|
@@ -1,5 +1,16 @@
|
|
|
1
|
+
import type { BigIntStats, Stats } from "node:fs";
|
|
1
2
|
import type { FileHandle } from "node:fs/promises";
|
|
2
3
|
import { type FileIdentityStat } from "./file-identity.js";
|
|
3
4
|
export declare function resolveOpenedFileRealPathForHandle(handle: FileHandle, ioPath: string): Promise<string>;
|
|
4
|
-
export declare function resolveOpenedFileRealPathForFd(fd: number, handleStat:
|
|
5
|
+
export declare function resolveOpenedFileRealPathForFd(fd: number, handleStat: {
|
|
6
|
+
dev: bigint;
|
|
7
|
+
ino: bigint;
|
|
8
|
+
}, ioPath: string): Promise<{
|
|
9
|
+
realPath: string;
|
|
10
|
+
stat: BigIntStats;
|
|
11
|
+
}>;
|
|
12
|
+
export declare function resolveOpenedFileRealPathForFd(fd: number, handleStat: FileIdentityStat, ioPath: string): Promise<{
|
|
13
|
+
realPath: string;
|
|
14
|
+
stat: Stats | BigIntStats;
|
|
15
|
+
}>;
|
|
5
16
|
//# sourceMappingURL=opened-realpath.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opened-realpath.d.ts","sourceRoot":"","sources":["../src/opened-realpath.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,OAAO,EAAoB,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG7E,wBAAsB,kCAAkC,CACtD,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED,
|
|
1
|
+
{"version":3,"file":"opened-realpath.d.ts","sourceRoot":"","sources":["../src/opened-realpath.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,OAAO,EAAoB,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG7E,wBAAsB,kCAAkC,CACtD,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED,wBAAgB,8BAA8B,CAC5C,EAAE,EAAE,MAAM,EACV,UAAU,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EACxC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC,CAAC;AACpD,wBAAgB,8BAA8B,CAC5C,EAAE,EAAE,MAAM,EACV,UAAU,EAAE,gBAAgB,EAC5B,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,KAAK,GAAG,WAAW,CAAA;CAAE,CAAC,CAAC"}
|
package/dist/opened-realpath.js
CHANGED
|
@@ -5,22 +5,20 @@ import { sameFileIdentity } from "./file-identity.js";
|
|
|
5
5
|
import { isNotFoundPathError } from "./path.js";
|
|
6
6
|
export async function resolveOpenedFileRealPathForHandle(handle, ioPath) {
|
|
7
7
|
const handleStat = await handle.stat();
|
|
8
|
-
return await resolveOpenedFileRealPathForFd(handle.fd, handleStat, ioPath);
|
|
8
|
+
return (await resolveOpenedFileRealPathForFd(handle.fd, handleStat, ioPath)).realPath;
|
|
9
9
|
}
|
|
10
10
|
export async function resolveOpenedFileRealPathForFd(fd, handleStat, ioPath) {
|
|
11
11
|
const statOptions = typeof handleStat.dev === "bigint" || typeof handleStat.ino === "bigint"
|
|
12
12
|
? { bigint: true } : undefined;
|
|
13
13
|
const fdCandidates = process.platform === "linux"
|
|
14
14
|
? [`/proc/self/fd/${fd}`, `/dev/fd/${fd}`]
|
|
15
|
-
:
|
|
16
|
-
? []
|
|
17
|
-
: [`/dev/fd/${fd}`];
|
|
15
|
+
: [];
|
|
18
16
|
for (const fdPath of fdCandidates) {
|
|
19
17
|
try {
|
|
20
18
|
const fdRealPath = await fs.realpath(fdPath);
|
|
21
19
|
const fdRealStat = statOptions ? await fs.stat(fdRealPath, statOptions) : await fs.stat(fdRealPath);
|
|
22
20
|
if (sameFileIdentity(handleStat, fdRealStat)) {
|
|
23
|
-
return fdRealPath;
|
|
21
|
+
return { realPath: fdRealPath, stat: fdRealStat };
|
|
24
22
|
}
|
|
25
23
|
}
|
|
26
24
|
catch {
|
|
@@ -31,7 +29,7 @@ export async function resolveOpenedFileRealPathForFd(fd, handleStat, ioPath) {
|
|
|
31
29
|
const ioRealPath = await fs.realpath(ioPath);
|
|
32
30
|
const ioRealStat = statOptions ? await fs.stat(ioRealPath, statOptions) : await fs.stat(ioRealPath);
|
|
33
31
|
if (sameFileIdentity(handleStat, ioRealStat)) {
|
|
34
|
-
return ioRealPath;
|
|
32
|
+
return { realPath: ioRealPath, stat: ioRealStat };
|
|
35
33
|
}
|
|
36
34
|
}
|
|
37
35
|
catch (err) {
|
|
@@ -77,7 +75,10 @@ async function resolveOpenedFileRealPathFromParent(handleStat, ioPath, statOptio
|
|
|
77
75
|
try {
|
|
78
76
|
const candidateStat = statOptions ? await fs.lstat(candidatePath, statOptions) : await fs.lstat(candidatePath);
|
|
79
77
|
if (candidateStat.isFile() && sameFileIdentity(handleStat, candidateStat)) {
|
|
80
|
-
|
|
78
|
+
const realPath = await fs.realpath(candidatePath);
|
|
79
|
+
const stat = statOptions ? await fs.stat(realPath, statOptions) : await fs.stat(realPath);
|
|
80
|
+
if (sameFileIdentity(handleStat, stat))
|
|
81
|
+
return { realPath, stat };
|
|
81
82
|
}
|
|
82
83
|
}
|
|
83
84
|
catch (err) {
|
package/dist/output.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,wBAAwB,CAAC,CAAC,GAAG,IAAI,IAAI;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IAClC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,uBAAuB,CAAC,CAAC,GAAG,IAAI,IAAI;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,CAAC,CAAC;CACX,CAAC;AAyDF,wBAAsB,2BAA2B,CAAC,CAAC,GAAG,IAAI,EACxD,OAAO,EAAE,wBAAwB,CAAC,CAAC,CAAC,GACnC,OAAO,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAgDrC"}
|
package/dist/output.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { writeCallbackSibling } from "./sibling-staged-file.js";
|
|
1
3
|
import path from "node:path";
|
|
2
4
|
import { normalizeMaxBytes } from "./byte-budget.js";
|
|
3
5
|
import { FsSafeError } from "./errors.js";
|
|
4
|
-
import { sanitizeUntrustedFileName } from "./filename.js";
|
|
6
|
+
import { fitFileNameToPortableComponent, sanitizeUntrustedFileName } from "./filename.js";
|
|
5
7
|
import { isPathInside } from "./path.js";
|
|
6
|
-
import { writeExternalFileViaSibling } from "./output-sibling.js";
|
|
7
8
|
import { root } from "./root.js";
|
|
8
9
|
import { tempFile } from "./temp-target.js";
|
|
9
10
|
const NON_PORTABLE_FILE_NAME_CHARACTERS = /[\u0000-\u001f\u007f-\u009f<>:"/\\|?*]/u;
|
|
@@ -97,3 +98,26 @@ export async function writeExternalFileWithinRoot(options) {
|
|
|
97
98
|
await staged.cleanup();
|
|
98
99
|
}
|
|
99
100
|
}
|
|
101
|
+
function buildSiblingTempPath(targetPath, fallbackFileName) {
|
|
102
|
+
const prefix = `.fs-safe-output-${process.pid}-${randomUUID()}-`;
|
|
103
|
+
const suffix = ".part";
|
|
104
|
+
const safeTail = fitFileNameToPortableComponent({
|
|
105
|
+
prefix,
|
|
106
|
+
fileName: tempFileNameForTarget(targetPath, fallbackFileName),
|
|
107
|
+
suffix,
|
|
108
|
+
});
|
|
109
|
+
return path.join(path.dirname(targetPath), `${prefix}${safeTail}${suffix}`);
|
|
110
|
+
}
|
|
111
|
+
async function writeExternalFileViaSibling(params) {
|
|
112
|
+
const finalPath = path.resolve(params.finalPath);
|
|
113
|
+
const { result } = await writeCallbackSibling({
|
|
114
|
+
tempPath: buildSiblingTempPath(finalPath, params.fallbackFileName),
|
|
115
|
+
write: params.write,
|
|
116
|
+
resolveFinalPath: () => finalPath,
|
|
117
|
+
mode: params.mode,
|
|
118
|
+
maxBytes: params.maxBytes,
|
|
119
|
+
syncTempFile: true,
|
|
120
|
+
syncParentDir: true,
|
|
121
|
+
});
|
|
122
|
+
return result;
|
|
123
|
+
}
|
package/dist/path-policy.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import { ROOT_PATH_ALIAS_POLICIES, resolveRootPath, } from "./root-path.js";
|
|
3
3
|
import { isNotFoundPathError } from "./path.js";
|
|
4
|
-
import { shortPath } from "./
|
|
4
|
+
import { shortPath } from "./error-detail.js";
|
|
5
5
|
export const PATH_ALIAS_POLICIES = ROOT_PATH_ALIAS_POLICIES;
|
|
6
6
|
export async function assertNoPathAliasEscape(params) {
|
|
7
7
|
const resolved = await resolveRootPath({
|
package/dist/permissions.d.ts
CHANGED
|
@@ -56,4 +56,5 @@ export declare function isWorldWritable(bits: number | null): boolean;
|
|
|
56
56
|
export declare function isGroupWritable(bits: number | null): boolean;
|
|
57
57
|
export declare function isWorldReadable(bits: number | null): boolean;
|
|
58
58
|
export declare function isGroupReadable(bits: number | null): boolean;
|
|
59
|
+
export declare function formatPosixMode(mode: number): string;
|
|
59
60
|
//# sourceMappingURL=permissions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"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"}
|
package/dist/permissions.js
CHANGED
package/dist/pinned-write.d.ts
CHANGED
|
@@ -9,7 +9,6 @@ export type PinnedWriteInput = {
|
|
|
9
9
|
kind: "stream";
|
|
10
10
|
stream: Readable;
|
|
11
11
|
};
|
|
12
|
-
export type RenameIdentityMismatchPolicy = "throw" | "verify-content";
|
|
13
12
|
export type RenameIdentityPolicy = "strict" | "verify-content-with-lock";
|
|
14
13
|
export type PublishedWriteIdentity = Readonly<{
|
|
15
14
|
dev: bigint;
|
|
@@ -25,7 +24,7 @@ export type PinnedWriteParams = {
|
|
|
25
24
|
maxBytes?: number;
|
|
26
25
|
input: PinnedWriteInput;
|
|
27
26
|
rootIdentity?: FileIdentityStat;
|
|
28
|
-
onRenameIdentityMismatch?:
|
|
27
|
+
onRenameIdentityMismatch?: "verify-content";
|
|
29
28
|
verifyPublished?: (fd: number, identity: PublishedWriteIdentity, parentGuard: AnyAsyncDirectoryGuard) => Promise<void>;
|
|
30
29
|
};
|
|
31
30
|
export declare function runPinnedWriteHelper(params: PinnedWriteParams): Promise<FileIdentityStat>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pinned-write.d.ts","sourceRoot":"","sources":["../src/pinned-write.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pinned-write.d.ts","sourceRoot":"","sources":["../src/pinned-write.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAA4F,KAAK,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAG7J,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAY3D,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,cAAc,CAAA;CAAE,GACpE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,QAAQ,CAAA;CAAE,CAAC;AAsDzC,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,0BAA0B,CAAC;AAEzE,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE5E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,gBAAgB,CAAC;IACxB,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC,wBAAwB,CAAC,EAAE,gBAAgB,CAAC;IAE5C,eAAe,CAAC,EAAE,CAChB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,sBAAsB,EAChC,WAAW,EAAE,sBAAsB,KAChC,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,CAAC;AAEF,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAgB/F;AAED,wBAAsB,8BAA8B,CAClD,MAAM,EAAE,iBAAiB,GAAG;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,oBAAoB,CAAC;CACvC,GACA,OAAO,CAAC,gBAAgB,CAAC,CA2B3B"}
|
package/dist/pinned-write.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { syncFileBestEffort } from "./file-sync.js";
|
|
1
2
|
import { randomUUID } from "node:crypto";
|
|
2
3
|
import fsSync, {} from "node:fs";
|
|
3
4
|
import fs from "node:fs/promises";
|
|
@@ -5,7 +6,7 @@ import path from "node:path";
|
|
|
5
6
|
import { normalizeMaxBytes } from "./byte-budget.js";
|
|
6
7
|
import { createAsyncDirectoryGuard, createNearestExistingDirectoryGuard, inspectDirectoryIdentity } from "./directory-guard.js";
|
|
7
8
|
import { FsSafeError } from "./errors.js";
|
|
8
|
-
import { syncDirectoryBestEffort } from "./
|
|
9
|
+
import { syncDirectoryBestEffort } from "./directory-durability.js";
|
|
9
10
|
import { sameFileIdentity, sha256Hex } from "./file-identity.js";
|
|
10
11
|
import { withAsyncDirectoryGuards } from "./guarded-mutation.js";
|
|
11
12
|
import { mkdirPathComponentsWithGuards } from "./guarded-mkdir.js";
|
|
@@ -35,16 +36,6 @@ function assertWithinMaxBytes(bytes, maxBytes) {
|
|
|
35
36
|
throw new FsSafeError("too-large", `file exceeds limit of ${maxBytes} bytes (got at least ${bytes})`);
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
|
-
async function syncFileBestEffort(handle) {
|
|
39
|
-
try {
|
|
40
|
-
await handle.sync();
|
|
41
|
-
}
|
|
42
|
-
catch (error) {
|
|
43
|
-
if (error?.code !== "EPERM") {
|
|
44
|
-
throw error;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
39
|
async function writeStreamToHandle(stream, handle, maxBytes) {
|
|
49
40
|
let bytes = 0;
|
|
50
41
|
for await (const chunk of stream) {
|
|
@@ -5,7 +5,7 @@ import path from "node:path";
|
|
|
5
5
|
import { fileStore, fileStoreSync, } from "./file-store.js";
|
|
6
6
|
import { FsSafeError } from "./errors.js";
|
|
7
7
|
import { isNotFoundPathError } from "./path.js";
|
|
8
|
-
import { throwFsSafeReadError } from "./
|
|
8
|
+
import { throwFsSafeReadError } from "./root-errors.js";
|
|
9
9
|
import { matchRootFileOpenFailure, openRootFileSync, } from "./root-file.js";
|
|
10
10
|
import { registerTempPathForExit, } from "./temp-cleanup.js";
|
|
11
11
|
import { TempWorkspaceCleanupCapability, TempWorkspaceCleanupOwner, } from "./temp-workspace-owner.js";
|
package/dist/publish-file.js
CHANGED
|
@@ -6,7 +6,7 @@ import { pinDirectory, } from "./directory-durability.js";
|
|
|
6
6
|
import { FsSafeError } from "./errors.js";
|
|
7
7
|
import { hashFileHandle } from "./file-hash.js";
|
|
8
8
|
import { sameFileIdentity, sameFileIdentityForCleanup, } from "./file-identity.js";
|
|
9
|
-
import {
|
|
9
|
+
import { syncFileBestEffortSync } from "./file-sync.js";
|
|
10
10
|
import { getNativeBinding, requireNativeBinding } from "./native.js";
|
|
11
11
|
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
12
12
|
import { directorySyncFailure, publicationFailure, rememberCreatedTarget, } from "./publish-file-failure.js";
|
|
@@ -256,7 +256,7 @@ export async function publishFileExclusive(params) {
|
|
|
256
256
|
throw error;
|
|
257
257
|
}
|
|
258
258
|
}
|
|
259
|
-
|
|
259
|
+
syncFileBestEffortSync(sourceNativeParent.handle.fd);
|
|
260
260
|
const targetIdentity = await fs.lstat(targetPath);
|
|
261
261
|
return {
|
|
262
262
|
method: "rename-noreplace",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replace-file-copy-source.d.ts","sourceRoot":"","sources":["../src/replace-file-copy-source.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,EAAE,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"replace-file-copy-source.d.ts","sourceRoot":"","sources":["../src/replace-file-copy-source.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,EAAE,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAOnD,KAAK,qBAAqB,GAAG,IAAI,CAAC,cAAc,kBAAkB,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC;AACvF,KAAK,oBAAoB,GAAG,IAAI,CAC9B,OAAO,MAAM,EACb,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,CAClE,CAAC;AA0DF,wBAAsB,mBAAmB,CAAC,MAAM,EAAE;IAChD,QAAQ,EAAE,qBAAqB,CAAC;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,CAAC,EAAE,WAAW,CAAC;CAChC,GAAG,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CA0BjD;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAC9C,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,CAAC,EAAE,WAAW,CAAC;CAChC,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CA8BxC"}
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import syncFs, {} from "node:fs";
|
|
2
|
+
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
2
3
|
import { FsSafeError } from "./errors.js";
|
|
3
4
|
import { sameFileIdentity } from "./file-identity.js";
|
|
4
5
|
import { inspectFileIdentity, inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
5
|
-
const
|
|
6
|
-
? syncFs.constants.O_NOFOLLOW
|
|
7
|
-
: 0;
|
|
8
|
-
const NONBLOCK = process.platform !== "win32" && "O_NONBLOCK" in syncFs.constants
|
|
9
|
-
? syncFs.constants.O_NONBLOCK
|
|
10
|
-
: 0;
|
|
11
|
-
const OPEN_READ_FLAGS = syncFs.constants.O_RDONLY | NOFOLLOW | NONBLOCK;
|
|
6
|
+
const OPEN_READ_FLAGS = resolveReadOpenFlags();
|
|
12
7
|
const READ_CHUNK_BYTES = 64 * 1024;
|
|
13
8
|
function assertSourcePreview(source, src) {
|
|
14
9
|
if (source.isSymbolicLink()) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replace-file-descriptor.d.ts","sourceRoot":"","sources":["../src/replace-file-descriptor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"replace-file-descriptor.d.ts","sourceRoot":"","sources":["../src/replace-file-descriptor.ts"],"names":[],"mappings":"AACA,OAAO,MAAM,EAAE,EAAE,KAAK,WAAW,EAAc,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,EAAE,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAIvD,OAAO,EAA0C,KAAK,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE5G,KAAK,mBAAmB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,GAAG,MAAM,GAAG,WAAW,CAAC,CAAC;AAC3E,KAAK,kBAAkB,GAAG,IAAI,CAC5B,OAAO,MAAM,EACb,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,UAAU,GAAG,eAAe,CACrF,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;AAE5D,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,EACjC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAUf;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,IAAI,CAAC,OAAO,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,WAAW,CAAC,EACrE,OAAO,EAAE,MAAM,GACd,IAAI,CAgBN;AA2BD,wBAAsB,mBAAmB,CAAC,MAAM,EAAE;IAChD,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,4FAA4F;IAC5F,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,GAAG,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CA4B1C;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE;IAC/C,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,GAAG,OAAO,CAAC,IAAI,CAAC,CAOhB;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB,GAAG,IAAI,CAeP;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE;IAC1C,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,KAAK,IAAI,CAAC;CAC9C,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,WAAW,CAAA;CAAE,CAAC,CAoBzD;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,KAAK,IAAI,CAAC;CAC9C,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,WAAW,CAAA;CAAE,CAoBxC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { syncFileBestEffort, syncFileBestEffortSync } from "./file-sync.js";
|
|
1
2
|
import syncFs, {} from "node:fs";
|
|
2
3
|
import fs, {} from "node:fs/promises";
|
|
3
4
|
import { FsSafeError } from "./errors.js";
|
|
@@ -116,14 +117,7 @@ export async function writeTempFile(params) {
|
|
|
116
117
|
await params.fsModule.writeFile(handle, params.content);
|
|
117
118
|
await handle.chmod(params.mode);
|
|
118
119
|
if (params.sync) {
|
|
119
|
-
|
|
120
|
-
await handle.sync();
|
|
121
|
-
}
|
|
122
|
-
catch (error) {
|
|
123
|
-
if (error.code !== "EPERM") {
|
|
124
|
-
throw error;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
120
|
+
await syncFileBestEffort(handle);
|
|
127
121
|
}
|
|
128
122
|
await inspectFileIdentity(() => handle.stat({ bigint: true }), identity);
|
|
129
123
|
return { handle, identity };
|
|
@@ -146,14 +140,7 @@ export function writeTempFileSync(params) {
|
|
|
146
140
|
params.fsModule.writeFileSync(fd, params.content);
|
|
147
141
|
params.fchmodSync?.(fd, params.mode);
|
|
148
142
|
if (params.sync) {
|
|
149
|
-
|
|
150
|
-
params.fsModule.fsyncSync(fd);
|
|
151
|
-
}
|
|
152
|
-
catch (error) {
|
|
153
|
-
if (error.code !== "EPERM") {
|
|
154
|
-
throw error;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
143
|
+
syncFileBestEffortSync(fd, params.fsModule);
|
|
157
144
|
}
|
|
158
145
|
inspectFileIdentitySync(() => params.fsModule.fstatSync(fd, { bigint: true }), identity);
|
|
159
146
|
return { fd, identity };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replace-file-temp-owner.d.ts","sourceRoot":"","sources":["../src/replace-file-temp-owner.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,EAAE,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,EAAE,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAA6B,KAAK,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"replace-file-temp-owner.d.ts","sourceRoot":"","sources":["../src/replace-file-temp-owner.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,EAAE,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,EAAE,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAA6B,KAAK,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAO9F,KAAK,oBAAoB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC,CAAC;AACzE,KAAK,mBAAmB,GAAG,IAAI,CAC7B,OAAO,MAAM,EACb,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,UAAU,GAAG,cAAc,GAAG,YAAY,CACrF,CAAC;AA8DF,wBAAsB,qBAAqB,CAAC,MAAM,EAAE;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,WAAW,EAAE,sBAAsB,CAAC;CACrC,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBhB;AA+BD,qBAAa,oBAAoB;;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAM1B,YAAY,QAAQ,EAAE,MAAM,EAG3B;IAED,KAAK,IAAI,IAAI,CAEZ;IAED,QAAQ,CAAC,UAAU,aAAc,WAAW,KAAG,IAAI,CAGjD;IAEF,KAAK,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,UAAU,CAAC;QAAC,QAAQ,EAAE,WAAW,CAAA;KAAE,GAAG,IAAI,CAG/D;IAED,IAAI,QAAQ,IAAI,WAAW,CAG1B;IAEK,aAAa,CAAC,QAAQ,EAAE,oBAAoB,EAAE,QAAQ,SAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkB3F;IAEK,eAAe,CACnB,QAAQ,EAAE,oBAAoB,EAC9B,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CA0Cf;IAED,WAAW,IAAI,IAAI,CAGlB;IAEK,MAAM,CAAC,MAAM,EAAE;QACnB,QAAQ,EAAE,oBAAoB,CAAC;QAC/B,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,mBAAmB,EAAE,OAAO,CAAC;KAC9B,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BhB;CACF;AAED,qBAAa,mBAAmB;;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAM1B,YAAY,QAAQ,EAAE,MAAM,EAG3B;IAED,KAAK,IAAI,IAAI,CAEZ;IAED,QAAQ,CAAC,UAAU,aAAc,WAAW,KAAG,IAAI,CAGjD;IAEF,KAAK,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,WAAW,CAAA;KAAE,GAAG,IAAI,CAGvD;IAED,IAAI,QAAQ,IAAI,WAAW,CAG1B;IAED,aAAa,CAAC,QAAQ,EAAE,mBAAmB,EAAE,QAAQ,SAAgB,GAAG,IAAI,CAkB3E;IAED,eAAe,CACb,QAAQ,EAAE,mBAAmB,EAC7B,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,IAAI,CAgDN;IAED,WAAW,IAAI,IAAI,CAGlB;IAED,MAAM,CAAC,MAAM,EAAE;QACb,QAAQ,EAAE,mBAAmB,CAAC;QAC9B,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,mBAAmB,EAAE,OAAO,CAAC;KAC9B,GAAG,IAAI,CAgCP;CACF"}
|
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import syncFs, {} from "node:fs";
|
|
2
2
|
import fs, {} from "node:fs/promises";
|
|
3
3
|
import { assertAsyncDirectoryGuard } from "./directory-guard.js";
|
|
4
|
+
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
4
5
|
import { FsSafeError } from "./errors.js";
|
|
5
6
|
import { sameFileIdentityForCleanup, sha256Hex } from "./file-identity.js";
|
|
6
7
|
import { inspectFileIdentity, inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
7
8
|
import { registerTempPathForExit } from "./temp-cleanup.js";
|
|
8
|
-
const PUBLISHED_READ_FLAGS =
|
|
9
|
-
(process.platform !== "win32" && typeof syncFs.constants.O_NOFOLLOW === "number"
|
|
10
|
-
? syncFs.constants.O_NOFOLLOW
|
|
11
|
-
: 0) |
|
|
12
|
-
(process.platform !== "win32" && typeof syncFs.constants.O_NONBLOCK === "number"
|
|
13
|
-
? syncFs.constants.O_NONBLOCK
|
|
14
|
-
: 0);
|
|
9
|
+
const PUBLISHED_READ_FLAGS = resolveReadOpenFlags();
|
|
15
10
|
function assertOwnedFile(stat, pathname, pathnameEntry) {
|
|
16
11
|
if (stat.isSymbolicLink()) {
|
|
17
12
|
throw new FsSafeError("symlink", `Atomic replace owned file became a symlink: ${pathname}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replace-file.d.ts","sourceRoot":"","sources":["../src/replace-file.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"replace-file.d.ts","sourceRoot":"","sources":["../src/replace-file.ts"],"names":[],"mappings":"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"}
|
package/dist/replace-file.js
CHANGED
|
@@ -18,7 +18,8 @@ function isPermissionRenameError(error) {
|
|
|
18
18
|
}
|
|
19
19
|
async function renameWithRetry(params) {
|
|
20
20
|
for (let attempt = 0; attempt <= params.maxRetries; attempt++) {
|
|
21
|
-
|
|
21
|
+
if (attempt > 0)
|
|
22
|
+
await params.assertSourceCurrent();
|
|
22
23
|
try {
|
|
23
24
|
await params.fsModule.rename(params.src, params.dest);
|
|
24
25
|
return { method: "rename" };
|
|
@@ -48,7 +49,8 @@ async function renameWithRetry(params) {
|
|
|
48
49
|
}
|
|
49
50
|
function renameWithRetrySync(params) {
|
|
50
51
|
for (let attempt = 0; attempt <= params.maxRetries; attempt++) {
|
|
51
|
-
|
|
52
|
+
if (attempt > 0)
|
|
53
|
+
params.assertSourceCurrent();
|
|
52
54
|
try {
|
|
53
55
|
params.fsModule.renameSync(params.src, params.dest);
|
|
54
56
|
return { method: "rename" };
|
|
@@ -175,9 +177,12 @@ async function replaceFileAtomicUnserialized(options, syncParent) {
|
|
|
175
177
|
await tempOwner.assertCurrent(fsModule);
|
|
176
178
|
if (options.beforeRename) {
|
|
177
179
|
await options.beforeRename({ filePath, tempPath });
|
|
180
|
+
await tempOwner.assertCurrent(fsModule);
|
|
181
|
+
}
|
|
182
|
+
if (options.destinationHardlinks === "reject") {
|
|
183
|
+
await assertDestinationHardlinkPolicy(fsModule, filePath, options.destinationHardlinks);
|
|
184
|
+
await tempOwner.assertCurrent(fsModule);
|
|
178
185
|
}
|
|
179
|
-
await tempOwner.assertCurrent(fsModule);
|
|
180
|
-
await assertDestinationHardlinkPolicy(fsModule, filePath, options.destinationHardlinks);
|
|
181
186
|
const result = await renameWithRetry({
|
|
182
187
|
fsModule,
|
|
183
188
|
src: tempPath,
|
|
@@ -199,13 +204,16 @@ async function replaceFileAtomicUnserialized(options, syncParent) {
|
|
|
199
204
|
else {
|
|
200
205
|
await tempOwner.assertCurrent(fsModule);
|
|
201
206
|
}
|
|
207
|
+
let didSyncParent = false;
|
|
202
208
|
if (syncParent) {
|
|
203
209
|
await syncParent(dir);
|
|
210
|
+
didSyncParent = true;
|
|
204
211
|
}
|
|
205
212
|
else if (options.syncParentDir) {
|
|
206
213
|
await syncDirectoryBestEffort(fsModule, dir);
|
|
214
|
+
didSyncParent = true;
|
|
207
215
|
}
|
|
208
|
-
if (result.method === "rename") {
|
|
216
|
+
if (result.method === "rename" && didSyncParent) {
|
|
209
217
|
await tempOwner.assertPublished(fsModule, filePath, expectedHash);
|
|
210
218
|
}
|
|
211
219
|
return result;
|
|
@@ -269,9 +277,12 @@ function replaceFileAtomicSyncUnserialized(options) {
|
|
|
269
277
|
tempOwner.assertCurrent(fsModule);
|
|
270
278
|
if (options.beforeRename) {
|
|
271
279
|
options.beforeRename({ filePath, tempPath });
|
|
280
|
+
tempOwner.assertCurrent(fsModule);
|
|
281
|
+
}
|
|
282
|
+
if (options.destinationHardlinks === "reject") {
|
|
283
|
+
assertDestinationHardlinkPolicySync(fsModule, filePath, options.destinationHardlinks);
|
|
284
|
+
tempOwner.assertCurrent(fsModule);
|
|
272
285
|
}
|
|
273
|
-
tempOwner.assertCurrent(fsModule);
|
|
274
|
-
assertDestinationHardlinkPolicySync(fsModule, filePath, options.destinationHardlinks);
|
|
275
286
|
const result = renameWithRetrySync({
|
|
276
287
|
fsModule,
|
|
277
288
|
src: tempPath,
|
|
@@ -294,10 +305,12 @@ function replaceFileAtomicSyncUnserialized(options) {
|
|
|
294
305
|
else {
|
|
295
306
|
tempOwner.assertCurrent(fsModule);
|
|
296
307
|
}
|
|
308
|
+
let didSyncParent = false;
|
|
297
309
|
if (options.syncParentDir) {
|
|
298
310
|
syncDirectoryBestEffortSync(fsModule, dir);
|
|
311
|
+
didSyncParent = true;
|
|
299
312
|
}
|
|
300
|
-
if (result.method === "rename") {
|
|
313
|
+
if (result.method === "rename" && didSyncParent) {
|
|
301
314
|
tempOwner.assertPublished(fsModule, filePath, expectedHash);
|
|
302
315
|
}
|
|
303
316
|
return result;
|
package/dist/root-errors.d.ts
CHANGED
|
@@ -8,4 +8,5 @@ export declare function normalizePinnedWriteError(error: unknown): Error;
|
|
|
8
8
|
export declare function normalizePinnedPathError(error: unknown): Error;
|
|
9
9
|
export declare function normalizeRemoveGuardError(error: unknown): Error;
|
|
10
10
|
export declare function normalizeRemovePathError(error: unknown): Error;
|
|
11
|
+
export declare function throwFsSafeReadError(error: unknown, label: string): never;
|
|
11
12
|
//# sourceMappingURL=root-errors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-errors.d.ts","sourceRoot":"","sources":["../src/root-errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK1C,wBAAgB,iBAAiB,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,WAAW,CAI9D;AAED,wBAAgB,qBAAqB,IAAI,WAAW,CAEnD;AAED,wBAAgB,mCAAmC,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,WAAW,CAIhF;AAED,wBAAgB,6BAA6B,IAAI,WAAW,CAE3D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE5D;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAU/D;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAO9D;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAQ/D;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAe9D"}
|
|
1
|
+
{"version":3,"file":"root-errors.d.ts","sourceRoot":"","sources":["../src/root-errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK1C,wBAAgB,iBAAiB,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,WAAW,CAI9D;AAED,wBAAgB,qBAAqB,IAAI,WAAW,CAEnD;AAED,wBAAgB,mCAAmC,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,WAAW,CAIhF;AAED,wBAAgB,6BAA6B,IAAI,WAAW,CAE3D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE5D;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAU/D;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAO9D;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAQ/D;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAe9D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAQzE"}
|