@openclaw/fs-safe 0.5.5 → 0.6.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 +49 -0
- package/README.md +16 -10
- package/dist/advanced.d.ts +2 -1
- package/dist/advanced.d.ts.map +1 -1
- package/dist/advanced.js +1 -0
- package/dist/archive-crc32.d.ts +2 -0
- package/dist/archive-crc32.d.ts.map +1 -0
- package/dist/archive-crc32.js +14 -0
- package/dist/archive-kind.js +2 -2
- package/dist/archive-native.d.ts.map +1 -1
- package/dist/archive-native.js +7 -0
- package/dist/archive-read.d.ts.map +1 -1
- package/dist/archive-read.js +24 -5
- package/dist/archive-tar-meta.d.ts.map +1 -1
- package/dist/archive-tar-meta.js +53 -6
- package/dist/archive-tar-pax.d.ts +8 -0
- package/dist/archive-tar-pax.d.ts.map +1 -0
- package/dist/archive-tar-pax.js +100 -0
- package/dist/archive-tar-runtime.d.ts +1 -0
- package/dist/archive-tar-runtime.d.ts.map +1 -1
- package/dist/archive-zip-admission.d.ts +7 -0
- package/dist/archive-zip-admission.d.ts.map +1 -0
- package/dist/archive-zip-admission.js +60 -0
- package/dist/archive-zip-count.d.ts +2 -0
- package/dist/archive-zip-count.d.ts.map +1 -0
- package/dist/archive-zip-count.js +140 -0
- package/dist/archive-zip-directory.d.ts +8 -0
- package/dist/archive-zip-directory.d.ts.map +1 -0
- package/dist/archive-zip-directory.js +224 -0
- package/dist/archive-zip-integrity.d.ts.map +1 -1
- package/dist/archive-zip-integrity.js +1 -14
- package/dist/archive-zip-names.d.ts +12 -0
- package/dist/archive-zip-names.d.ts.map +1 -0
- package/dist/archive-zip-names.js +99 -0
- package/dist/archive-zip-preflight.d.ts +1 -1
- package/dist/archive-zip-preflight.d.ts.map +1 -1
- package/dist/archive-zip-preflight.js +8 -145
- package/dist/archive.d.ts.map +1 -1
- package/dist/archive.js +32 -23
- package/dist/file-hash.d.ts.map +1 -1
- package/dist/file-hash.js +25 -19
- package/dist/file-identity.d.ts +1 -0
- package/dist/file-identity.d.ts.map +1 -1
- package/dist/file-identity.js +10 -0
- package/dist/file-lock-sync.d.ts.map +1 -1
- package/dist/file-lock-sync.js +19 -7
- package/dist/move-path.js +2 -2
- package/dist/native-binding.d.ts +3 -0
- package/dist/native-binding.d.ts.map +1 -1
- package/dist/native-operations.d.ts +4 -1
- package/dist/native-operations.d.ts.map +1 -1
- package/dist/native-operations.js +24 -8
- package/dist/native-pinned-write-windows.d.ts +8 -0
- package/dist/native-pinned-write-windows.d.ts.map +1 -0
- package/dist/native-pinned-write-windows.js +92 -0
- package/dist/native-pinned-write.d.ts.map +1 -1
- package/dist/native-pinned-write.js +136 -127
- package/dist/native-staged-file.d.ts +24 -0
- package/dist/native-staged-file.d.ts.map +1 -0
- package/dist/native-staged-file.js +337 -0
- package/dist/native.d.ts.map +1 -1
- package/dist/native.js +4 -4
- package/dist/opened-realpath.d.ts +2 -0
- package/dist/opened-realpath.d.ts.map +1 -1
- package/dist/opened-realpath.js +12 -7
- package/dist/output-sibling.js +3 -3
- package/dist/owner-dacl.d.ts.map +1 -1
- package/dist/owner-dacl.js +2 -1
- package/dist/permission-exec.d.ts +19 -0
- package/dist/permission-exec.d.ts.map +1 -1
- package/dist/permission-exec.js +57 -11
- package/dist/permissions-public.d.ts +1 -1
- package/dist/permissions-public.d.ts.map +1 -1
- package/dist/permissions-windows.d.ts +3 -0
- package/dist/permissions-windows.d.ts.map +1 -1
- package/dist/permissions-windows.js +16 -5
- package/dist/permissions.d.ts +5 -0
- package/dist/permissions.d.ts.map +1 -1
- package/dist/pinned-write.d.ts +6 -0
- package/dist/pinned-write.d.ts.map +1 -1
- package/dist/pinned-write.js +19 -29
- package/dist/private-directory.d.ts.map +1 -1
- package/dist/private-directory.js +3 -2
- package/dist/private-temp-workspace.d.ts.map +1 -1
- package/dist/private-temp-workspace.js +23 -15
- package/dist/publish-file.d.ts.map +1 -1
- package/dist/publish-file.js +2 -2
- package/dist/replace-file-descriptor.d.ts +3 -3
- package/dist/replace-file-descriptor.d.ts.map +1 -1
- package/dist/replace-file-descriptor.js +2 -2
- package/dist/root-impl.d.ts.map +1 -1
- package/dist/root-impl.js +84 -75
- package/dist/root-paths.d.ts +11 -14
- package/dist/root-paths.d.ts.map +1 -1
- package/dist/root-paths.js +36 -27
- package/dist/root-write-verification.d.ts +11 -0
- package/dist/root-write-verification.d.ts.map +1 -0
- package/dist/root-write-verification.js +91 -0
- package/dist/secret-file.d.ts +1 -6
- package/dist/secret-file.d.ts.map +1 -1
- package/dist/secret-file.js +43 -117
- package/dist/secret-read-async.d.ts +1 -1
- package/dist/secret-read-async.d.ts.map +1 -1
- package/dist/secret-read-async.js +45 -67
- package/dist/secret-read-policy.d.ts +13 -0
- package/dist/secret-read-policy.d.ts.map +1 -0
- package/dist/secret-read-policy.js +28 -0
- package/dist/secret.d.ts +2 -1
- package/dist/secret.d.ts.map +1 -1
- package/dist/secret.js +2 -1
- package/dist/secure-file.d.ts.map +1 -1
- package/dist/secure-file.js +25 -16
- package/dist/sibling-temp.js +1 -1
- package/dist/sidecar-lock-acquire.d.ts.map +1 -1
- package/dist/sidecar-lock-acquire.js +4 -1
- package/dist/staged-directory.d.ts +16 -0
- package/dist/staged-directory.d.ts.map +1 -0
- package/dist/staged-directory.js +60 -0
- package/dist/staged-file-types.d.ts +56 -0
- package/dist/staged-file-types.d.ts.map +1 -0
- package/dist/staged-file-types.js +1 -0
- package/dist/staged-file.d.ts +10 -0
- package/dist/staged-file.d.ts.map +1 -0
- package/dist/staged-file.js +15 -0
- package/dist/strict-file-identity.d.ts +6 -0
- package/dist/strict-file-identity.d.ts.map +1 -0
- package/dist/strict-file-identity.js +48 -0
- package/dist/temp-cleanup.d.ts.map +1 -1
- package/dist/temp-cleanup.js +3 -3
- package/dist/temp-target.d.ts.map +1 -1
- package/dist/temp-target.js +9 -7
- package/dist/windows-owner.d.ts +3 -0
- package/dist/windows-owner.d.ts.map +1 -1
- package/dist/windows-owner.js +10 -2
- package/docs/advanced.md +11 -1
- package/docs/archive.md +62 -15
- package/docs/config.md +7 -0
- package/docs/contributing.md +45 -7
- package/docs/durability.md +17 -4
- package/docs/errors.md +16 -1
- package/docs/index.md +3 -1
- package/docs/install.md +15 -7
- package/docs/migrating-to-0.5.md +7 -7
- package/docs/migrating-to-0.6.md +43 -0
- package/docs/native-helper.md +15 -5
- package/docs/native.md +40 -11
- package/docs/path-scope.md +28 -2
- package/docs/permissions.md +13 -2
- package/docs/root.md +1 -1
- package/docs/secret-file.md +8 -0
- package/docs/secure-file.md +17 -1
- package/docs/security-model.md +15 -1
- package/docs/sidecar-lock.md +13 -3
- package/docs/staged-file.md +178 -0
- package/docs/testing.md +1 -1
- package/docs/writing.md +19 -0
- package/package.json +16 -9
- package/dist/native/darwin-arm64/fs-safe-native.node +0 -0
- package/dist/native/darwin-x64/fs-safe-native.node +0 -0
- package/dist/native/linux-arm64-gnu/fs-safe-native.node +0 -0
- package/dist/native/linux-arm64-musl/fs-safe-native.node +0 -0
- package/dist/native/linux-x64-gnu/fs-safe-native.node +0 -0
- package/dist/native/linux-x64-musl/fs-safe-native.node +0 -0
- package/dist/native/win32-x64-msvc/fs-safe-native.node +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import os from "node:os";
|
|
2
2
|
import { getNativeBinding } from "./native.js";
|
|
3
|
-
import { executePermissionCommand } from "./permission-exec.js";
|
|
3
|
+
import { executePermissionCommand, formatPermissionErrorDetail, getPermissionCommandFailure, } from "./permission-exec.js";
|
|
4
4
|
import { normalizeLowercaseStringOrEmpty } from "./string-coerce.js";
|
|
5
5
|
import { resolveWindowsSystemCommand } from "./windows-command.js";
|
|
6
6
|
import { inspectWindowsOwner, resolveWindowsCurrentUserSid, resolveWindowsPrincipalSids, } from "./windows-owner.js";
|
|
@@ -90,7 +90,7 @@ export async function inspectWindowsPermissions(params) {
|
|
|
90
90
|
});
|
|
91
91
|
if (owner.error) {
|
|
92
92
|
const error = `Windows owner inspection failed: ${owner.error}`;
|
|
93
|
-
return { ...unverified, ownerError: owner.error, error };
|
|
93
|
+
return { ...unverified, ownerError: owner.error, error, errorDetail: owner.errorDetail, errorCause: owner.errorCause };
|
|
94
94
|
}
|
|
95
95
|
const acl = await inspectWindowsAcl(params.targetPath, {
|
|
96
96
|
env: params.opts?.env,
|
|
@@ -105,7 +105,7 @@ export async function inspectWindowsPermissions(params) {
|
|
|
105
105
|
...(owner.error ? { ownerError: owner.error } : {}),
|
|
106
106
|
};
|
|
107
107
|
if (!acl.ok)
|
|
108
|
-
return { ...unverified, ...ownerFields, error: acl.error };
|
|
108
|
+
return { ...unverified, ...ownerFields, error: acl.error, errorDetail: acl.errorDetail, errorCause: acl.errorCause };
|
|
109
109
|
return {
|
|
110
110
|
ok: true,
|
|
111
111
|
isSymlink: params.stat.isSymlink,
|
|
@@ -231,7 +231,13 @@ export function summarizeWindowsAcl(entries, env) {
|
|
|
231
231
|
return { trusted, untrustedWorld, untrustedGroup };
|
|
232
232
|
}
|
|
233
233
|
export async function inspectWindowsAcl(targetPath, opts) {
|
|
234
|
-
|
|
234
|
+
let command = "";
|
|
235
|
+
let startedAt = performance.now();
|
|
236
|
+
const exec = async (file, args) => {
|
|
237
|
+
command = file;
|
|
238
|
+
startedAt = performance.now();
|
|
239
|
+
return await (opts?.exec ?? defaultPermissionExec)(file, args);
|
|
240
|
+
};
|
|
235
241
|
try {
|
|
236
242
|
if (opts?.principalTranslationFailed)
|
|
237
243
|
throw new Error("Windows ACL principal SID translation failed");
|
|
@@ -260,7 +266,12 @@ export async function inspectWindowsAcl(targetPath, opts) {
|
|
|
260
266
|
return { ok: true, entries, trusted, untrustedWorld, untrustedGroup };
|
|
261
267
|
}
|
|
262
268
|
catch (err) {
|
|
263
|
-
return {
|
|
269
|
+
return {
|
|
270
|
+
ok: false, entries: [], trusted: [], untrustedWorld: [], untrustedGroup: [],
|
|
271
|
+
error: formatPermissionErrorDetail(String(err)),
|
|
272
|
+
errorDetail: getPermissionCommandFailure(err, command, performance.now() - startedAt),
|
|
273
|
+
errorCause: err,
|
|
274
|
+
};
|
|
264
275
|
}
|
|
265
276
|
}
|
|
266
277
|
export function formatWindowsAclSummary(summary) {
|
package/dist/permissions.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import type { PermissionCommandFailure } from "./permission-exec.js";
|
|
1
2
|
import { type PermissionExec } from "./permissions-windows.js";
|
|
3
|
+
export type { PermissionCommandFailure } from "./permission-exec.js";
|
|
2
4
|
export { createIcaclsResetCommand, formatIcaclsResetCommand, formatWindowsAclSummary, inspectWindowsAcl, parseIcaclsOutput, resolveWindowsUserPrincipal, summarizeWindowsAcl, } from "./permissions-windows.js";
|
|
3
5
|
export type { IcaclsResetCommandOptions, PermissionExec, WindowsAclEntry, WindowsAclSummary, WindowsUserInfoProvider, } from "./permissions-windows.js";
|
|
4
6
|
export type PermissionCheck = {
|
|
@@ -20,6 +22,9 @@ export type PermissionCheck = {
|
|
|
20
22
|
ownerError?: string;
|
|
21
23
|
aclSummary?: string;
|
|
22
24
|
error?: string;
|
|
25
|
+
errorDetail?: PermissionCommandFailure;
|
|
26
|
+
/** Original inspection failure, retained separately from serializable diagnostics. */
|
|
27
|
+
errorCause?: unknown;
|
|
23
28
|
};
|
|
24
29
|
export type PermissionCheckOptions = {
|
|
25
30
|
platform?: NodeJS.Platform;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,EACvB,iBAAiB,EACjB,iBAAiB,EACjB,2BAA2B,EAC3B,mBAAmB,GACpB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,yBAAyB,EACzB,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,0BAA0B,CAAC;AAElC,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,OAAO,GAAG,aAAa,GAAG,SAAS,CAAC;IAC5C,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"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"}
|
package/dist/pinned-write.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Readable } from "node:stream";
|
|
2
|
+
import { type AsyncDirectoryGuard } from "./directory-guard.js";
|
|
2
3
|
import type { FileIdentityStat } from "./file-identity.js";
|
|
3
4
|
export type PinnedWriteInput = {
|
|
4
5
|
kind: "buffer";
|
|
@@ -10,6 +11,10 @@ export type PinnedWriteInput = {
|
|
|
10
11
|
};
|
|
11
12
|
export type RenameIdentityMismatchPolicy = "throw" | "verify-content";
|
|
12
13
|
export type RenameIdentityPolicy = "strict" | "verify-content-with-lock";
|
|
14
|
+
export type PublishedWriteIdentity = Readonly<{
|
|
15
|
+
dev: bigint;
|
|
16
|
+
ino: bigint;
|
|
17
|
+
}>;
|
|
13
18
|
export type PinnedWriteParams = {
|
|
14
19
|
rootPath: string;
|
|
15
20
|
relativeParentPath: string;
|
|
@@ -21,6 +26,7 @@ export type PinnedWriteParams = {
|
|
|
21
26
|
input: PinnedWriteInput;
|
|
22
27
|
rootIdentity?: FileIdentityStat;
|
|
23
28
|
onRenameIdentityMismatch?: RenameIdentityMismatchPolicy;
|
|
29
|
+
verifyPublished?: (fd: number, identity: PublishedWriteIdentity, parentGuard: AsyncDirectoryGuard) => Promise<void>;
|
|
24
30
|
};
|
|
25
31
|
export declare function runPinnedWriteHelper(params: PinnedWriteParams): Promise<FileIdentityStat>;
|
|
26
32
|
export declare function runPinnedWriteWithRenamePolicy(params: PinnedWriteParams & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pinned-write.d.ts","sourceRoot":"","sources":["../src/pinned-write.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"pinned-write.d.ts","sourceRoot":"","sources":["../src/pinned-write.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAkE,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAGhI,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAU3D,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;AAgEzC,MAAM,MAAM,4BAA4B,GAAG,OAAO,GAAG,gBAAgB,CAAC;AAEtE,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,4BAA4B,CAAC;IAExD,eAAe,CAAC,EAAE,CAChB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,sBAAsB,EAChC,WAAW,EAAE,mBAAmB,KAC7B,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,CAAC;AAEF,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAe/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
|
@@ -115,7 +115,7 @@ async function runPinnedWriteFallback(params) {
|
|
|
115
115
|
: await createNearestExistingDirectoryGuard(params.rootPath, parentPath);
|
|
116
116
|
const targetPath = path.join(parentPath, params.basename);
|
|
117
117
|
if (params.overwrite === false) {
|
|
118
|
-
|
|
118
|
+
const handle = await withAsyncDirectoryGuards([parentGuard], async () => await fs.open(targetPath, fsSync.constants.O_WRONLY | fsSync.constants.O_CREAT | fsSync.constants.O_EXCL, params.mode), {
|
|
119
119
|
onPostGuardFailure: async (openedHandle) => {
|
|
120
120
|
// The parent failed verification, so targetPath may now resolve
|
|
121
121
|
// somewhere else. Close the fd, but do not clean up by path.
|
|
@@ -124,6 +124,7 @@ async function runPinnedWriteFallback(params) {
|
|
|
124
124
|
});
|
|
125
125
|
let created = true;
|
|
126
126
|
try {
|
|
127
|
+
const verificationIdentity = await handle.stat({ bigint: true });
|
|
127
128
|
await handle.chmod(params.mode);
|
|
128
129
|
if (params.input.kind === "buffer") {
|
|
129
130
|
assertWithinMaxBytes(byteLength(params.input.data, params.input.encoding), params.maxBytes);
|
|
@@ -139,9 +140,10 @@ async function runPinnedWriteFallback(params) {
|
|
|
139
140
|
}
|
|
140
141
|
await syncFileBestEffort(handle);
|
|
141
142
|
const stat = await handle.stat();
|
|
142
|
-
await handle.close().catch(() => undefined);
|
|
143
143
|
await syncDirectoryBestEffort(parentPath);
|
|
144
|
+
// Publication is complete. A failed outer check must not remove its target.
|
|
144
145
|
created = false;
|
|
146
|
+
await params.verifyPublished?.(handle.fd, verificationIdentity, parentGuard);
|
|
145
147
|
return { dev: stat.dev, ino: stat.ino };
|
|
146
148
|
}
|
|
147
149
|
finally {
|
|
@@ -160,10 +162,11 @@ async function runPinnedWriteFallback(params) {
|
|
|
160
162
|
: 0);
|
|
161
163
|
let handle;
|
|
162
164
|
let tempStat;
|
|
163
|
-
let
|
|
165
|
+
let readHandle;
|
|
164
166
|
let renamed = false;
|
|
165
167
|
try {
|
|
166
168
|
handle = await fs.open(tempPath, tempFlags, params.mode);
|
|
169
|
+
let verificationIdentity = await handle.stat({ bigint: true });
|
|
167
170
|
await handle.chmod(params.mode);
|
|
168
171
|
if (params.input.kind === "buffer") {
|
|
169
172
|
assertWithinMaxBytes(byteLength(params.input.data, params.input.encoding), params.maxBytes);
|
|
@@ -184,14 +187,13 @@ async function runPinnedWriteFallback(params) {
|
|
|
184
187
|
}
|
|
185
188
|
const expectedTempStat = tempStat;
|
|
186
189
|
await syncFileBestEffort(handle);
|
|
187
|
-
|
|
188
|
-
handle = undefined;
|
|
190
|
+
let verifiedIdentity = expectedTempStat;
|
|
189
191
|
await withAsyncDirectoryGuards([parentGuard], async () => {
|
|
190
192
|
await fs.rename(tempPath, targetPath);
|
|
191
193
|
renamed = true;
|
|
192
194
|
await getFsSafeTestHooks()?.afterPinnedWriteFallbackRename?.(targetPath);
|
|
193
195
|
await syncDirectoryBestEffort(parentPath);
|
|
194
|
-
targetStat = await fs.lstat(targetPath);
|
|
196
|
+
const targetStat = await fs.lstat(targetPath);
|
|
195
197
|
if (targetStat.isSymbolicLink()) {
|
|
196
198
|
throw new FsSafeError("path-mismatch", "fallback target changed during write");
|
|
197
199
|
}
|
|
@@ -211,38 +213,26 @@ async function runPinnedWriteFallback(params) {
|
|
|
211
213
|
(process.platform !== "win32" && "O_NOFOLLOW" in fsSync.constants
|
|
212
214
|
? fsSync.constants.O_NOFOLLOW
|
|
213
215
|
: 0);
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
try {
|
|
218
|
-
// Capture fd-based identity before reading — this is stable across all
|
|
219
|
-
// subsequent lookups (on FUSE and locally), unlike the lstat-based
|
|
220
|
-
// targetStat that triggered this fallback.
|
|
221
|
-
readHandleStat = await readHandle.stat();
|
|
222
|
-
actualHash = sha256Hex(await readHandle.readFile());
|
|
223
|
-
}
|
|
224
|
-
finally {
|
|
225
|
-
await readHandle.close().catch(() => undefined);
|
|
226
|
-
}
|
|
216
|
+
readHandle = await fs.open(targetPath, readFlags);
|
|
217
|
+
const readHandleStat = await readHandle.stat({ bigint: true });
|
|
218
|
+
const actualHash = sha256Hex(await readHandle.readFile());
|
|
227
219
|
if (actualHash !== expectedHash) {
|
|
228
220
|
throw new FsSafeError("path-mismatch", "fallback target changed during write");
|
|
229
221
|
}
|
|
230
|
-
//
|
|
231
|
-
|
|
232
|
-
//
|
|
233
|
-
|
|
222
|
+
// The content-verified destination, not the old temp inode, is now pinned.
|
|
223
|
+
verificationIdentity = readHandleStat;
|
|
224
|
+
// Preserve the helper's legacy numeric return facts, not the private proof.
|
|
225
|
+
verifiedIdentity = { dev: Number(readHandleStat.dev), ino: Number(readHandleStat.ino) };
|
|
234
226
|
}
|
|
235
227
|
});
|
|
228
|
+
await params.verifyPublished?.((readHandle ?? handle).fd, verificationIdentity, parentGuard);
|
|
229
|
+
return { dev: verifiedIdentity.dev, ino: verifiedIdentity.ino };
|
|
236
230
|
}
|
|
237
|
-
|
|
231
|
+
finally {
|
|
232
|
+
await readHandle?.close().catch(() => undefined);
|
|
238
233
|
await handle?.close().catch(() => undefined);
|
|
239
234
|
if (!renamed) {
|
|
240
235
|
await fs.rm(tempPath, { force: true }).catch(() => undefined);
|
|
241
236
|
}
|
|
242
|
-
throw error;
|
|
243
|
-
}
|
|
244
|
-
if (!targetStat) {
|
|
245
|
-
throw new FsSafeError("path-mismatch", "fallback target was not verified");
|
|
246
237
|
}
|
|
247
|
-
return { dev: targetStat.dev, ino: targetStat.ino };
|
|
248
238
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"private-directory.d.ts","sourceRoot":"","sources":["../src/private-directory.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,6BAA6B,GAAG;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;CAC5B,CAAC;AAEF,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,6BAA6B,GACtC,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"private-directory.d.ts","sourceRoot":"","sources":["../src/private-directory.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,6BAA6B,GAAG;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;CAC5B,CAAC;AAEF,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,6BAA6B,GACtC,OAAO,CAAC,IAAI,CAAC,CAkBf"}
|
|
@@ -3,11 +3,12 @@ import { getNativeBinding } from "./native.js";
|
|
|
3
3
|
export async function createPrivateDirectory(targetPath, options) {
|
|
4
4
|
const platform = options?.platform ?? process.platform;
|
|
5
5
|
if (platform !== "win32") {
|
|
6
|
-
throw new FsSafeError("helper-unavailable", "private-directory creation is
|
|
6
|
+
throw new FsSafeError("helper-unavailable", "private-directory creation is supported only on Windows");
|
|
7
7
|
}
|
|
8
8
|
const native = getNativeBinding();
|
|
9
9
|
if (!native) {
|
|
10
|
-
throw new FsSafeError("helper-unavailable", "private Windows directory creation requires the
|
|
10
|
+
throw new FsSafeError("helper-unavailable", "private Windows directory creation requires the matching optional native platform package; " +
|
|
11
|
+
"install @openclaw/fs-safe with optional dependencies enabled on a supported platform and use FS_SAFE_NATIVE_MODE=auto or require");
|
|
11
12
|
}
|
|
12
13
|
native.createPrivateDirectory(targetPath);
|
|
13
14
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"private-temp-workspace.d.ts","sourceRoot":"","sources":["../src/private-temp-workspace.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,aAAa,EACnB,MAAM,iBAAiB,CAAC;AAUzB,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,0BAA0B,GAAG,SAAS,GAAG,SAAS,GAAG,mBAAmB,CAAC;AAErF,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,uBAAuB,CAAC;IAClC,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACpE,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3D,SAAS,CACP,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAE,GACtC,OAAO,CAAC,MAAM,CAAC,CAAC;IACnB,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9D,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACxC,OAAO,IAAI,OAAO,CAAC,0BAA0B,CAAC,CAAC;IAC/C,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,uBAAuB,CAAC;IAClC,KAAK,EAAE,aAAa,CAAC;IACrB,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;IAC3D,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAClD,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,MAAM,CAAC;IAC5F,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,OAAO,IAAI,0BAA0B,CAAC;IACtC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;CAC1B,CAAC;
|
|
1
|
+
{"version":3,"file":"private-temp-workspace.d.ts","sourceRoot":"","sources":["../src/private-temp-workspace.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,aAAa,EACnB,MAAM,iBAAiB,CAAC;AAUzB,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,0BAA0B,GAAG,SAAS,GAAG,SAAS,GAAG,mBAAmB,CAAC;AAErF,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,uBAAuB,CAAC;IAClC,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACpE,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3D,SAAS,CACP,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAE,GACtC,OAAO,CAAC,MAAM,CAAC,CAAC;IACnB,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9D,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACxC,OAAO,IAAI,OAAO,CAAC,0BAA0B,CAAC,CAAC;IAC/C,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,uBAAuB,CAAC;IAClC,KAAK,EAAE,aAAa,CAAC;IACrB,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;IAC3D,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAClD,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,MAAM,CAAC;IAC5F,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,OAAO,IAAI,0BAA0B,CAAC;IACtC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;CAC1B,CAAC;AA+KF,wBAAsB,aAAa,CACjC,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,aAAa,CAAC,CAExB;AAED,wBAAsB,iBAAiB,CAAC,CAAC,EACvC,OAAO,EAAE,oBAAoB,EAC7B,GAAG,EAAE,CAAC,SAAS,EAAE,aAAa,KAAK,OAAO,CAAC,CAAC,CAAC,GAC5C,OAAO,CAAC,CAAC,CAAC,CAUZ;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,oBAAoB,GAC5B,iBAAiB,CA8EnB;AAED,wBAAgB,qBAAqB,CAAC,CAAC,EACrC,OAAO,EAAE,oBAAoB,EAC7B,GAAG,EAAE,CAAC,SAAS,EAAE,iBAAiB,KAAK,CAAC,GACvC,CAAC,CAUH"}
|
|
@@ -4,7 +4,7 @@ import fs from "node:fs/promises";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { fileStore, fileStoreSync, } from "./file-store.js";
|
|
6
6
|
import { FsSafeError } from "./errors.js";
|
|
7
|
-
import {
|
|
7
|
+
import { sameFileIdentityForCleanup } from "./file-identity.js";
|
|
8
8
|
import { isNotFoundPathError } from "./path.js";
|
|
9
9
|
import { throwFsSafeReadError } from "./read-error.js";
|
|
10
10
|
import { matchRootFileOpenFailure, openRootFileSync, } from "./root-file.js";
|
|
@@ -82,12 +82,12 @@ function ensurePrivateDirectorySync(dir, mode) {
|
|
|
82
82
|
async function cleanupWorkspace(dir, identity) {
|
|
83
83
|
let current;
|
|
84
84
|
try {
|
|
85
|
-
current = await fs.lstat(dir);
|
|
85
|
+
current = await fs.lstat(dir, { bigint: true });
|
|
86
86
|
}
|
|
87
87
|
catch (error) {
|
|
88
88
|
return error.code === "ENOENT" ? "missing" : "identity-mismatch";
|
|
89
89
|
}
|
|
90
|
-
if (!
|
|
90
|
+
if (!sameFileIdentityForCleanup(current, identity)) {
|
|
91
91
|
return "identity-mismatch";
|
|
92
92
|
}
|
|
93
93
|
await fs.rm(dir, { recursive: true, force: true });
|
|
@@ -96,12 +96,12 @@ async function cleanupWorkspace(dir, identity) {
|
|
|
96
96
|
function cleanupWorkspaceSync(dir, identity) {
|
|
97
97
|
let current;
|
|
98
98
|
try {
|
|
99
|
-
current = fsSync.lstatSync(dir);
|
|
99
|
+
current = fsSync.lstatSync(dir, { bigint: true });
|
|
100
100
|
}
|
|
101
101
|
catch (error) {
|
|
102
102
|
return error.code === "ENOENT" ? "missing" : "identity-mismatch";
|
|
103
103
|
}
|
|
104
|
-
if (!
|
|
104
|
+
if (!sameFileIdentityForCleanup(current, identity)) {
|
|
105
105
|
return "identity-mismatch";
|
|
106
106
|
}
|
|
107
107
|
fsSync.rmSync(dir, { recursive: true, force: true });
|
|
@@ -115,12 +115,16 @@ async function createTempWorkspace(options) {
|
|
|
115
115
|
await ensurePrivateDirectory(root, dirMode);
|
|
116
116
|
const dir = await fs.mkdtemp(path.join(root, sanitizeTempPrefix(options.prefix)));
|
|
117
117
|
await fs.chmod(dir, dirMode).catch(() => undefined);
|
|
118
|
-
const stat = await fs.lstat(dir);
|
|
118
|
+
const stat = await fs.lstat(dir, { bigint: true });
|
|
119
119
|
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
120
120
|
throw new Error(`Temp workspace must be a directory: ${dir}`);
|
|
121
121
|
}
|
|
122
|
-
const identity = { dev: stat.dev, ino: stat.ino };
|
|
123
|
-
const
|
|
122
|
+
const identity = { dev: Number(stat.dev), ino: Number(stat.ino) };
|
|
123
|
+
const cleanupIdentity = { dev: stat.dev, ino: stat.ino };
|
|
124
|
+
const unregisterTempDir = registerTempPathForExit(dir, {
|
|
125
|
+
recursive: true,
|
|
126
|
+
identity: cleanupIdentity,
|
|
127
|
+
});
|
|
124
128
|
const store = fileStore({ rootDir: dir, private: true, dirMode, mode });
|
|
125
129
|
return {
|
|
126
130
|
dir,
|
|
@@ -144,7 +148,7 @@ async function createTempWorkspace(options) {
|
|
|
144
148
|
},
|
|
145
149
|
cleanup: async () => {
|
|
146
150
|
try {
|
|
147
|
-
return await cleanupWorkspace(dir,
|
|
151
|
+
return await cleanupWorkspace(dir, cleanupIdentity);
|
|
148
152
|
}
|
|
149
153
|
finally {
|
|
150
154
|
unregisterTempDir();
|
|
@@ -152,7 +156,7 @@ async function createTempWorkspace(options) {
|
|
|
152
156
|
},
|
|
153
157
|
[Symbol.asyncDispose]: async () => {
|
|
154
158
|
try {
|
|
155
|
-
await cleanupWorkspace(dir,
|
|
159
|
+
await cleanupWorkspace(dir, cleanupIdentity);
|
|
156
160
|
}
|
|
157
161
|
finally {
|
|
158
162
|
unregisterTempDir();
|
|
@@ -194,12 +198,16 @@ export function tempWorkspaceSync(options) {
|
|
|
194
198
|
catch {
|
|
195
199
|
// Best-effort on platforms that do not enforce POSIX modes.
|
|
196
200
|
}
|
|
197
|
-
const stat = fsSync.lstatSync(dir);
|
|
201
|
+
const stat = fsSync.lstatSync(dir, { bigint: true });
|
|
198
202
|
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
199
203
|
throw new Error(`Temp workspace must be a directory: ${dir}`);
|
|
200
204
|
}
|
|
201
|
-
const identity = { dev: stat.dev, ino: stat.ino };
|
|
202
|
-
const
|
|
205
|
+
const identity = { dev: Number(stat.dev), ino: Number(stat.ino) };
|
|
206
|
+
const cleanupIdentity = { dev: stat.dev, ino: stat.ino };
|
|
207
|
+
const unregisterTempDir = registerTempPathForExit(dir, {
|
|
208
|
+
recursive: true,
|
|
209
|
+
identity: cleanupIdentity,
|
|
210
|
+
});
|
|
203
211
|
const store = fileStoreSync({ rootDir: dir, private: true, dirMode, mode });
|
|
204
212
|
return {
|
|
205
213
|
dir,
|
|
@@ -236,7 +244,7 @@ export function tempWorkspaceSync(options) {
|
|
|
236
244
|
},
|
|
237
245
|
cleanup: () => {
|
|
238
246
|
try {
|
|
239
|
-
return cleanupWorkspaceSync(dir,
|
|
247
|
+
return cleanupWorkspaceSync(dir, cleanupIdentity);
|
|
240
248
|
}
|
|
241
249
|
finally {
|
|
242
250
|
unregisterTempDir();
|
|
@@ -244,7 +252,7 @@ export function tempWorkspaceSync(options) {
|
|
|
244
252
|
},
|
|
245
253
|
[Symbol.dispose]: () => {
|
|
246
254
|
try {
|
|
247
|
-
cleanupWorkspaceSync(dir,
|
|
255
|
+
cleanupWorkspaceSync(dir, cleanupIdentity);
|
|
248
256
|
}
|
|
249
257
|
finally {
|
|
250
258
|
unregisterTempDir();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish-file.d.ts","sourceRoot":"","sources":["../src/publish-file.ts"],"names":[],"mappings":"AACA,OAAe,EAAoB,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAI/D,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EAC1B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,
|
|
1
|
+
{"version":3,"file":"publish-file.d.ts","sourceRoot":"","sources":["../src/publish-file.ts"],"names":[],"mappings":"AACA,OAAe,EAAoB,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAI/D,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EAC1B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAML,KAAK,qCAAqC,EAC3C,MAAM,2BAA2B,CAAC;AAGnC,YAAY,EACV,2BAA2B,EAC3B,wCAAwC,EACxC,kCAAkC,EAClC,gCAAgC,EAChC,qCAAqC,GACtC,MAAM,2BAA2B,CAAC;AAEnC,MAAM,MAAM,4BAA4B,GACpC,cAAc,GACd,eAAe,GACf,kBAAkB,CAAC;AAEvB,MAAM,MAAM,0BAA0B,GAAG;IACvC,MAAM,EAAE,UAAU,GAAG,gBAAgB,GAAG,kBAAkB,CAAC;IAC3D,QAAQ,EAAE,KAAK,CAAC;IAChB,aAAa,EAAE,oBAAoB,CAAC;CACrC,CAAC;AAkBF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE/D;AA2ND,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,sBAAsB,CAAC,EAAE,gBAAgB,CAAC;IAC1C,QAAQ,EAAE,4BAA4B,CAAC;IACvC,aAAa,CAAC,EAAE,qCAAqC,CAAC;IACtD,aAAa,CAAC,EAAE,gBAAgB,CAAC;CAClC,GAAG,OAAO,CAAC,0BAA0B,CAAC,CA4MtC"}
|
package/dist/publish-file.js
CHANGED
|
@@ -5,7 +5,7 @@ import path from "node:path";
|
|
|
5
5
|
import { pinDirectory, } from "./directory-durability.js";
|
|
6
6
|
import { FsSafeError } from "./errors.js";
|
|
7
7
|
import { hashFileHandle } from "./file-hash.js";
|
|
8
|
-
import { sameFileIdentity } from "./file-identity.js";
|
|
8
|
+
import { sameFileIdentity, sameFileIdentityForCleanup, } from "./file-identity.js";
|
|
9
9
|
import { syncNativeFileBestEffort } from "./native-operations.js";
|
|
10
10
|
import { getNativeBinding, requireNativeBinding } from "./native.js";
|
|
11
11
|
import { directorySyncFailure, publicationFailure, rememberCreatedTarget, } from "./publish-file-failure.js";
|
|
@@ -163,7 +163,7 @@ async function removeCreatedTargetIfUnchanged(targetPath, identity) {
|
|
|
163
163
|
}
|
|
164
164
|
try {
|
|
165
165
|
const current = await fs.lstat(targetPath, { bigint: true });
|
|
166
|
-
if (!current.isSymbolicLink() &&
|
|
166
|
+
if (!current.isSymbolicLink() && sameFileIdentityForCleanup(current, identity)) {
|
|
167
167
|
await fs.rm(targetPath);
|
|
168
168
|
return "removed";
|
|
169
169
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import syncFs, { type
|
|
1
|
+
import syncFs, { type BigIntStats } from "node:fs";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
type AsyncTempFileSystem = Pick<typeof fs, "lstat" | "open" | "writeFile">;
|
|
4
4
|
type SyncTempFileSystem = Pick<typeof syncFs, "closeSync" | "fstatSync" | "fsyncSync" | "lstatSync" | "openSync" | "writeFileSync">;
|
|
@@ -20,7 +20,7 @@ export declare function writeTempFile(params: {
|
|
|
20
20
|
content: string | Uint8Array;
|
|
21
21
|
mode: number;
|
|
22
22
|
sync: boolean;
|
|
23
|
-
}): Promise<
|
|
23
|
+
}): Promise<BigIntStats>;
|
|
24
24
|
export declare function writeTempFileSync(params: {
|
|
25
25
|
fsModule: SyncTempFileSystem;
|
|
26
26
|
tempPath: string;
|
|
@@ -28,6 +28,6 @@ export declare function writeTempFileSync(params: {
|
|
|
28
28
|
mode: number;
|
|
29
29
|
fchmodSync?: SyncFchmod;
|
|
30
30
|
sync: boolean;
|
|
31
|
-
}):
|
|
31
|
+
}): BigIntStats;
|
|
32
32
|
export {};
|
|
33
33
|
//# sourceMappingURL=replace-file-descriptor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replace-file-descriptor.d.ts","sourceRoot":"","sources":["../src/replace-file-descriptor.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,EAAE,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"replace-file-descriptor.d.ts","sourceRoot":"","sources":["../src/replace-file-descriptor.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,EAAE,EAAE,KAAK,WAAW,EAAc,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAuB,MAAM,kBAAkB,CAAC;AAIvD,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;AA2B5D,wBAAsB,kBAAkB,CAAC,MAAM,EAAE;IAC/C,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBhB;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,CAcP;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;CACf,GAAG,OAAO,CAAC,WAAW,CAAC,CAkBvB;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;CACf,GAAG,WAAW,CAkBd"}
|
|
@@ -67,7 +67,7 @@ export async function writeTempFile(params) {
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
|
-
return await handle.stat();
|
|
70
|
+
return await handle.stat({ bigint: true });
|
|
71
71
|
}
|
|
72
72
|
finally {
|
|
73
73
|
await handle.close();
|
|
@@ -88,7 +88,7 @@ export function writeTempFileSync(params) {
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
-
return params.fsModule.fstatSync(fd);
|
|
91
|
+
return params.fsModule.fstatSync(fd, { bigint: true });
|
|
92
92
|
}
|
|
93
93
|
finally {
|
|
94
94
|
params.fsModule.closeSync(fd);
|
package/dist/root-impl.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-impl.d.ts","sourceRoot":"","sources":["../src/root-impl.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"root-impl.d.ts","sourceRoot":"","sources":["../src/root-impl.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,KAAK,EAAE,MAAM,SAAS,CAAC;AAElD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAW7D,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,KAAK,oBAAoB,EAG1B,MAAM,mBAAmB,CAAC;AAY3B,OAAO,EAAwB,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAyB9E,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAY,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAMpF,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,kCAAkC,EAAE,MAAM,sBAAsB,CAAC;AAC1E,YAAY,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,EAAE,oBAAoB,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,KAAK,CAAC;IACZ,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,oBAAoB,CAAC;AAC5D,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,OAAO,CAAC;AAChD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE/D,MAAM,MAAM,YAAY,GAAG;IACzB,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,IAAI,CAChC,YAAY,EACZ,WAAW,GAAG,UAAU,GAAG,iBAAiB,GAAG,UAAU,CAC1D,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;AAEhE,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,YAAY,EAAE,eAAe,GAAG,OAAO,GAAG,MAAM,GAAG,gBAAgB,CAAC,GAAG;IACzG,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,YAAY,EAAE,eAAe,GAAG,OAAO,GAAG,MAAM,CAAC,GAAG;IAC7F,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,eAAe,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC,GAAG;IAClG,eAAe,CAAC,EAAE,cAAc,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,gBAAgB,GAAG;IACpD,QAAQ,CAAC,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,KAAK,CAAC,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7C,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;AACpE,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,oBAAoB,EAAE,WAAW,CAAC,CAAC;AAE5E,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,GAAG;IACjD,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG;IAClE,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC;AACpE,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC;AA6BnE,eAAO,MAAM,sBAAsB,QAAmB,CAAC;AA6IvD,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAEhC,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/C,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3E,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3E,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5E,QAAQ,CACN,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,eAAe,GAAG;QAAE,QAAQ,CAAC,EAAE,cAAc,CAAA;KAAE,GACxD,OAAO,CAAC,MAAM,CAAC,CAAC;IACnB,QAAQ,CAAC,CAAC,GAAG,OAAO,EAClB,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,eAAe,GAAG;QAAE,QAAQ,CAAC,EAAE,cAAc,CAAA;KAAE,GACxD,OAAO,CAAC,CAAC,CAAC,CAAC;IACd,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/E,MAAM,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACzE,YAAY,CACV,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,uBAAuB,GAChC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC/B,MAAM,CACJ,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzE,KAAK,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,UAAU,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,KAAK,CACH,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,MAAM,CACJ,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,SAAS,CACP,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,UAAU,CACR,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3F,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,KAAK,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACnF,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,aAAa,EAAE,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAClF,IAAI,CACF,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,qBAAqB,CAAC,aAAa,CAAC,CAAC;CAC5F;AAyRD,wBAAsB,IAAI,CACxB,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,YAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAEf;AAqFD,wBAAsB,mBAAmB,CAAC,MAAM,EAAE;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,UAAU,CAAC,CAOtB;AAED,wBAAsB,mBAAmB,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAG3F;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,EAAE,oBAAoB,CAAC;IAClC,eAAe,EAAE,OAAO,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,KAAK,CAAC;IACZ,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC,CAAC"}
|