@openclaw/fs-safe 0.8.3 → 0.8.4
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 +10 -0
- package/dist/absolute-path.d.ts.map +1 -1
- package/dist/absolute-path.js +8 -7
- package/dist/archive-native.d.ts +1 -0
- package/dist/archive-native.d.ts.map +1 -1
- package/dist/archive-native.js +15 -68
- package/dist/archive-plan.d.ts +20 -0
- package/dist/archive-plan.d.ts.map +1 -0
- package/dist/archive-plan.js +55 -0
- package/dist/archive-tar-inspect.d.ts +7 -0
- package/dist/archive-tar-inspect.d.ts.map +1 -0
- package/dist/archive-tar-inspect.js +59 -0
- package/dist/archive-tar.d.ts +3 -1
- package/dist/archive-tar.d.ts.map +1 -1
- package/dist/archive-tar.js +12 -49
- package/dist/archive.d.ts +1 -0
- package/dist/archive.d.ts.map +1 -1
- package/dist/archive.js +20 -36
- package/dist/bounded-read.d.ts.map +1 -1
- package/dist/bounded-read.js +31 -4
- package/dist/directory-durability.js +5 -5
- package/dist/directory-guard.d.ts.map +1 -1
- package/dist/directory-guard.js +5 -6
- package/dist/file-store-boundary.js +1 -1
- package/dist/file-store-prune.js +17 -8
- package/dist/file-store.js +2 -2
- package/dist/guarded-mkdir.d.ts.map +1 -1
- package/dist/guarded-mkdir.js +5 -4
- package/dist/native-binding.d.ts +2 -1
- package/dist/native-binding.d.ts.map +1 -1
- package/dist/native-pinned-write-windows.js +6 -3
- package/dist/native-pinned-write.js +3 -3
- package/dist/native-staged-file.d.ts +2 -2
- package/dist/native-staged-file.d.ts.map +1 -1
- package/dist/native-staged-file.js +12 -8
- package/dist/opened-realpath.d.ts.map +1 -1
- package/dist/opened-realpath.js +10 -9
- package/dist/path-policy.js +2 -2
- package/dist/pinned-write.d.ts +1 -0
- package/dist/pinned-write.d.ts.map +1 -1
- package/dist/pinned-write.js +15 -11
- package/dist/regular-file.js +8 -8
- package/dist/replace-file-descriptor.d.ts.map +1 -1
- package/dist/replace-file-descriptor.js +8 -4
- package/dist/replace-file-temp-owner.d.ts.map +1 -1
- package/dist/replace-file-temp-owner.js +13 -7
- package/dist/root-context.js +5 -5
- package/dist/root-impl.d.ts +2 -1
- package/dist/root-impl.d.ts.map +1 -1
- package/dist/root-impl.js +35 -26
- package/dist/root-path-existing.d.ts.map +1 -1
- package/dist/root-path-existing.js +2 -3
- package/dist/root-path-symlink.d.ts.map +1 -1
- package/dist/root-path-symlink.js +2 -3
- package/dist/root-path.d.ts.map +1 -1
- package/dist/root-path.js +3 -4
- package/dist/root-paths.d.ts.map +1 -1
- package/dist/root-paths.js +16 -15
- package/dist/root-write-mode.d.ts.map +1 -1
- package/dist/root-write-mode.js +5 -4
- package/dist/root-write-verification.js +6 -6
- package/dist/secret-file.js +2 -2
- package/dist/strict-file-identity.d.ts +1 -1
- package/dist/strict-file-identity.d.ts.map +1 -1
- package/dist/symlink-parents.d.ts.map +1 -1
- package/dist/symlink-parents.js +1 -2
- package/docs/archive.md +57 -0
- package/docs/reading.md +2 -0
- package/docs/root.md +10 -1
- package/docs/types.md +2 -1
- package/docs/writing.md +26 -3
- package/package.json +8 -8
package/dist/pinned-write.js
CHANGED
|
@@ -125,7 +125,7 @@ async function runPinnedWriteFallback(params) {
|
|
|
125
125
|
let created = true;
|
|
126
126
|
let createdIdentity;
|
|
127
127
|
try {
|
|
128
|
-
const verificationIdentity =
|
|
128
|
+
const verificationIdentity = fsSync.fstatSync(handle.fd, { bigint: true });
|
|
129
129
|
createdIdentity = verificationIdentity;
|
|
130
130
|
if (params.input.kind === "buffer") {
|
|
131
131
|
assertWithinMaxBytes(byteLength(params.input.data, params.input.encoding), params.maxBytes);
|
|
@@ -141,9 +141,11 @@ async function runPinnedWriteFallback(params) {
|
|
|
141
141
|
}
|
|
142
142
|
// Content writes may clear set-ID bits; finalize them through the owned fd.
|
|
143
143
|
await handle.chmod(params.mode);
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
if (params.sync !== false)
|
|
145
|
+
await syncFileBestEffort(handle);
|
|
146
|
+
const stat = fsSync.fstatSync(handle.fd);
|
|
147
|
+
if (params.sync !== false)
|
|
148
|
+
await syncDirectoryBestEffort(parentPath);
|
|
147
149
|
// Publication is complete. A failed outer check must not remove its target.
|
|
148
150
|
created = false;
|
|
149
151
|
await params.verifyPublished?.(handle.fd, verificationIdentity, parentGuard);
|
|
@@ -175,7 +177,7 @@ async function runPinnedWriteFallback(params) {
|
|
|
175
177
|
let renamed = false;
|
|
176
178
|
try {
|
|
177
179
|
handle = await fs.open(tempPath, tempFlags, params.mode);
|
|
178
|
-
let verificationIdentity =
|
|
180
|
+
let verificationIdentity = fsSync.fstatSync(handle.fd, { bigint: true });
|
|
179
181
|
tempIdentity = verificationIdentity;
|
|
180
182
|
if (params.input.kind === "buffer") {
|
|
181
183
|
assertWithinMaxBytes(byteLength(params.input.data, params.input.encoding), params.maxBytes);
|
|
@@ -189,21 +191,23 @@ async function runPinnedWriteFallback(params) {
|
|
|
189
191
|
else {
|
|
190
192
|
await writeStreamToHandle(params.input.stream, handle, params.maxBytes);
|
|
191
193
|
}
|
|
192
|
-
tempStat =
|
|
193
|
-
const tempPathStat =
|
|
194
|
+
tempStat = fsSync.fstatSync(handle.fd);
|
|
195
|
+
const tempPathStat = fsSync.lstatSync(tempPath);
|
|
194
196
|
if (tempPathStat.isSymbolicLink() || !sameFileIdentity(tempPathStat, tempStat)) {
|
|
195
197
|
throw new FsSafeError("path-mismatch", "fallback temp path changed during write");
|
|
196
198
|
}
|
|
197
199
|
const expectedTempStat = tempStat;
|
|
198
200
|
await handle.chmod(params.mode);
|
|
199
|
-
|
|
201
|
+
if (params.sync !== false)
|
|
202
|
+
await syncFileBestEffort(handle);
|
|
200
203
|
let verifiedIdentity = expectedTempStat;
|
|
201
204
|
await withAsyncDirectoryGuards([parentGuard], async () => {
|
|
202
205
|
await fs.rename(tempPath, targetPath);
|
|
203
206
|
renamed = true;
|
|
204
207
|
await getFsSafeTestHooks()?.afterPinnedWriteFallbackRename?.(targetPath);
|
|
205
|
-
|
|
206
|
-
|
|
208
|
+
if (params.sync !== false)
|
|
209
|
+
await syncDirectoryBestEffort(parentPath);
|
|
210
|
+
const targetStat = fsSync.lstatSync(targetPath);
|
|
207
211
|
if (targetStat.isSymbolicLink()) {
|
|
208
212
|
throw new FsSafeError("path-mismatch", "fallback target changed during write");
|
|
209
213
|
}
|
|
@@ -220,7 +224,7 @@ async function runPinnedWriteFallback(params) {
|
|
|
220
224
|
}
|
|
221
225
|
const expectedHash = sha256Hex(params.input.data, params.input.encoding);
|
|
222
226
|
readHandle = await fs.open(targetPath, resolveReadOpenFlags());
|
|
223
|
-
const readHandleStat =
|
|
227
|
+
const readHandleStat = fsSync.fstatSync(readHandle.fd, { bigint: true });
|
|
224
228
|
const actualHash = sha256Hex(await readHandle.readFile());
|
|
225
229
|
if (actualHash !== expectedHash) {
|
|
226
230
|
throw new FsSafeError("path-mismatch", "fallback target changed during write");
|
package/dist/regular-file.js
CHANGED
|
@@ -31,7 +31,7 @@ function translateBoundedReadOverflow(error, filePath, maxBytes) {
|
|
|
31
31
|
export async function statRegularFile(filePath) {
|
|
32
32
|
let stat;
|
|
33
33
|
try {
|
|
34
|
-
stat =
|
|
34
|
+
stat = fsSync.lstatSync(filePath);
|
|
35
35
|
}
|
|
36
36
|
catch (err) {
|
|
37
37
|
if (isNotFoundPathError(err)) {
|
|
@@ -64,7 +64,7 @@ export async function readRegularFile(params) {
|
|
|
64
64
|
const maxBytes = normalizeMaxBytes(params.maxBytes);
|
|
65
65
|
assertNoUnsafeDeviceReadPath(params.filePath);
|
|
66
66
|
const before = await inspectFileIdentity(async () => {
|
|
67
|
-
const stat =
|
|
67
|
+
const stat = fsSync.lstatSync(params.filePath, { bigint: true });
|
|
68
68
|
assertRegularReadStat(stat, params.filePath, true);
|
|
69
69
|
return stat;
|
|
70
70
|
}).catch((error) => throwReadPreviewError(error, params.filePath));
|
|
@@ -82,15 +82,15 @@ export async function readRegularFile(params) {
|
|
|
82
82
|
throw err;
|
|
83
83
|
}
|
|
84
84
|
try {
|
|
85
|
-
const stat =
|
|
85
|
+
const stat = fsSync.fstatSync(handle.fd);
|
|
86
86
|
const identity = await inspectFileIdentity(async () => {
|
|
87
|
-
const exact =
|
|
87
|
+
const exact = fsSync.fstatSync(handle.fd, { bigint: true });
|
|
88
88
|
assertRegularReadStat(exact, params.filePath);
|
|
89
89
|
return exact;
|
|
90
90
|
}, before);
|
|
91
91
|
try {
|
|
92
92
|
await inspectFileIdentity(async () => {
|
|
93
|
-
const current =
|
|
93
|
+
const current = fsSync.lstatSync(params.filePath, { bigint: true });
|
|
94
94
|
assertRegularReadStat(current, params.filePath);
|
|
95
95
|
return current;
|
|
96
96
|
}, identity);
|
|
@@ -245,7 +245,7 @@ export async function appendRegularFile(options) {
|
|
|
245
245
|
let preOpenStat;
|
|
246
246
|
try {
|
|
247
247
|
preOpenStat = await inspectFileIdentity(async () => {
|
|
248
|
-
const stat =
|
|
248
|
+
const stat = fsSync.lstatSync(options.filePath, { bigint: true });
|
|
249
249
|
if (stat.isSymbolicLink()) {
|
|
250
250
|
throw new Error(`Refusing to append through symlink: ${options.filePath}`);
|
|
251
251
|
}
|
|
@@ -282,12 +282,12 @@ export async function appendRegularFile(options) {
|
|
|
282
282
|
let identity;
|
|
283
283
|
try {
|
|
284
284
|
identity = await inspectFileIdentity(async () => {
|
|
285
|
-
const stat =
|
|
285
|
+
const stat = fsSync.fstatSync(handle.fd, { bigint: true });
|
|
286
286
|
assertRegularAppendStat(stat, options.filePath);
|
|
287
287
|
return stat;
|
|
288
288
|
}, preOpenStat);
|
|
289
289
|
await inspectFileIdentity(async () => {
|
|
290
|
-
const current =
|
|
290
|
+
const current = fsSync.lstatSync(options.filePath, { bigint: true });
|
|
291
291
|
assertRegularAppendStat(current, options.filePath);
|
|
292
292
|
return current;
|
|
293
293
|
}, identity);
|
|
@@ -1 +1 @@
|
|
|
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,
|
|
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,CA6B1C;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,CAuBzD;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"}
|
|
@@ -62,13 +62,14 @@ export async function pinDirectoryForMode(params) {
|
|
|
62
62
|
if (process.platform === "win32") {
|
|
63
63
|
return;
|
|
64
64
|
}
|
|
65
|
-
const expected =
|
|
65
|
+
const expected = params.fsModule === fs
|
|
66
|
+
? syncFs.lstatSync(params.dirPath) : await params.fsModule.lstat(params.dirPath);
|
|
66
67
|
assertDirectory(expected, params.dirPath);
|
|
67
68
|
const handle = await params.fsModule.open(params.dirPath, directoryOpenFlags());
|
|
68
69
|
try {
|
|
69
70
|
const owner = ownDirectoryMode({
|
|
70
71
|
async inspect() {
|
|
71
|
-
const opened = await handle.stat();
|
|
72
|
+
const opened = params.fsModule === fs ? syncFs.fstatSync(handle.fd) : await handle.stat();
|
|
72
73
|
assertOwnedDirectory(expected, opened);
|
|
73
74
|
return opened.mode & 0o7777;
|
|
74
75
|
},
|
|
@@ -112,14 +113,17 @@ export function applyDirectoryModeSync(params) {
|
|
|
112
113
|
export async function writeTempFile(params) {
|
|
113
114
|
const handle = await params.fsModule.open(params.tempPath, "wx", params.mode);
|
|
114
115
|
try {
|
|
115
|
-
|
|
116
|
+
// Custom adapters retain their async-only metadata contract.
|
|
117
|
+
const inspect = () => params.fsModule === fs
|
|
118
|
+
? syncFs.fstatSync(handle.fd, { bigint: true }) : handle.stat({ bigint: true });
|
|
119
|
+
const identity = await inspectFileIdentity(inspect);
|
|
116
120
|
params.onIdentity?.(identity);
|
|
117
121
|
await params.fsModule.writeFile(handle, params.content);
|
|
118
122
|
await handle.chmod(params.mode);
|
|
119
123
|
if (params.sync) {
|
|
120
124
|
await syncFileBestEffort(handle);
|
|
121
125
|
}
|
|
122
|
-
await inspectFileIdentity(
|
|
126
|
+
await inspectFileIdentity(inspect, identity);
|
|
123
127
|
return { handle, identity };
|
|
124
128
|
}
|
|
125
129
|
catch (error) {
|
|
@@ -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;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;
|
|
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;AAgEF,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,CAoB3F;IAEK,eAAe,CACnB,QAAQ,EAAE,oBAAoB,EAC9B,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CA4Cf;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"}
|
|
@@ -33,7 +33,9 @@ async function cleanupOwnedPath(params) {
|
|
|
33
33
|
if (!params.identity)
|
|
34
34
|
return true;
|
|
35
35
|
try {
|
|
36
|
-
const current =
|
|
36
|
+
const current = params.fsModule === fs
|
|
37
|
+
? syncFs.lstatSync(params.pathname, { bigint: true })
|
|
38
|
+
: await params.fsModule.lstat(params.pathname, { bigint: true });
|
|
37
39
|
if (current.isSymbolicLink() ||
|
|
38
40
|
!current.isFile() ||
|
|
39
41
|
current.nlink !== 1n ||
|
|
@@ -61,11 +63,11 @@ export async function cleanupPinnedFilePath(params) {
|
|
|
61
63
|
if ([guard.stat.dev, guard.stat.ino].some((value) => typeof value === "number" && !Number.isSafeInteger(value)))
|
|
62
64
|
return;
|
|
63
65
|
await assertAsyncDirectoryGuard(guard);
|
|
64
|
-
const parent =
|
|
66
|
+
const parent = syncFs.lstatSync(guard.dir, { bigint: true });
|
|
65
67
|
if (parent.isSymbolicLink() || !parent.isDirectory() ||
|
|
66
68
|
!sameFileIdentityForCleanup(parent, guard.stat))
|
|
67
69
|
return;
|
|
68
|
-
const opened =
|
|
70
|
+
const opened = syncFs.fstatSync(params.handle.fd, { bigint: true });
|
|
69
71
|
if (!opened.isFile() || opened.nlink !== 1n ||
|
|
70
72
|
!sameFileIdentityForCleanup(opened, params.identity))
|
|
71
73
|
return;
|
|
@@ -131,13 +133,15 @@ export class AsyncAtomicTempOwner {
|
|
|
131
133
|
}
|
|
132
134
|
async assertCurrent(fsModule, pathname = this.pathname) {
|
|
133
135
|
const opened = await inspectFileIdentity(async () => {
|
|
134
|
-
const stat =
|
|
136
|
+
const stat = fsModule === fs ? syncFs.fstatSync(this.#handle.fd, { bigint: true })
|
|
137
|
+
: await this.#handle.stat({ bigint: true });
|
|
135
138
|
assertOwnedFile(stat, pathname, false);
|
|
136
139
|
return stat;
|
|
137
140
|
}, this.identity);
|
|
138
141
|
try {
|
|
139
142
|
await inspectFileIdentity(async () => {
|
|
140
|
-
const stat =
|
|
143
|
+
const stat = fsModule === fs ? syncFs.lstatSync(pathname, { bigint: true })
|
|
144
|
+
: await fsModule.lstat(pathname, { bigint: true });
|
|
141
145
|
assertOwnedFile(stat, pathname, true);
|
|
142
146
|
return stat;
|
|
143
147
|
}, opened);
|
|
@@ -173,12 +177,14 @@ export class AsyncAtomicTempOwner {
|
|
|
173
177
|
throw error;
|
|
174
178
|
}
|
|
175
179
|
const identity = await inspectFileIdentity(async () => {
|
|
176
|
-
const stat =
|
|
180
|
+
const stat = fsModule === fs ? syncFs.fstatSync(published.fd, { bigint: true })
|
|
181
|
+
: await published.stat({ bigint: true });
|
|
177
182
|
assertOwnedFile(stat, pathname, false);
|
|
178
183
|
return stat;
|
|
179
184
|
});
|
|
180
185
|
await inspectFileIdentity(async () => {
|
|
181
|
-
const stat =
|
|
186
|
+
const stat = fsModule === fs ? syncFs.lstatSync(pathname, { bigint: true })
|
|
187
|
+
: await fsModule.lstat(pathname, { bigint: true });
|
|
182
188
|
assertOwnedFile(stat, pathname, true);
|
|
183
189
|
return stat;
|
|
184
190
|
}, identity);
|
package/dist/root-context.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import fs from "node:fs
|
|
1
|
+
import fs from "node:fs";
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { inspectDirectoryIdentity } from "./directory-guard.js";
|
|
@@ -25,7 +25,7 @@ export async function expandRelativePathWithHome(relativePath) {
|
|
|
25
25
|
if (cachedHomePath?.raw !== rawHome) {
|
|
26
26
|
let realHome = rawHome;
|
|
27
27
|
try {
|
|
28
|
-
realHome =
|
|
28
|
+
realHome = fs.realpathSync.native(rawHome);
|
|
29
29
|
}
|
|
30
30
|
catch {
|
|
31
31
|
// If the home dir cannot be canonicalized, keep lexical expansion behavior.
|
|
@@ -39,8 +39,8 @@ export async function resolveRootContext(rootDir) {
|
|
|
39
39
|
let rootReal;
|
|
40
40
|
let rootIdentity;
|
|
41
41
|
try {
|
|
42
|
-
rootReal =
|
|
43
|
-
const rootStat =
|
|
42
|
+
rootReal = fs.realpathSync.native(rootDir);
|
|
43
|
+
const rootStat = fs.statSync(rootReal);
|
|
44
44
|
if (!rootStat.isDirectory()) {
|
|
45
45
|
throw new FsSafeError("invalid-path", "root dir is not a directory");
|
|
46
46
|
}
|
|
@@ -83,7 +83,7 @@ export async function assertRootIdentityCurrent(root) {
|
|
|
83
83
|
await inspectDirectoryIdentity(root.rootReal, { dev: root.rootIdentity.dev, ino: root.rootIdentity.ino });
|
|
84
84
|
return;
|
|
85
85
|
}
|
|
86
|
-
current =
|
|
86
|
+
current = fs.lstatSync(root.rootReal);
|
|
87
87
|
}
|
|
88
88
|
catch (error) {
|
|
89
89
|
throw new FsSafeError("path-mismatch", "root path changed during operation", {
|
package/dist/root-impl.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ export type SymlinkPolicy = "reject" | "follow-within-root";
|
|
|
26
26
|
export type HardlinkPolicy = "reject" | "allow";
|
|
27
27
|
export type WritableOpenMode = "replace" | "append" | "update";
|
|
28
28
|
export type RootDefaults = {
|
|
29
|
+
durable?: boolean;
|
|
29
30
|
hardlinks?: HardlinkPolicy;
|
|
30
31
|
maxBytes?: number;
|
|
31
32
|
mkdir?: boolean;
|
|
@@ -37,7 +38,7 @@ export type RootDefaults = {
|
|
|
37
38
|
};
|
|
38
39
|
export type RootReadOptions = Pick<RootDefaults, "hardlinks" | "maxBytes" | "nonBlockingRead" | "symlinks">;
|
|
39
40
|
export type RootOpenOptions = Omit<RootReadOptions, "maxBytes">;
|
|
40
|
-
export type RootWriteOptions = Pick<RootDefaults, "denyMutations" | "mkdir" | "mode" | "renameIdentity"> & {
|
|
41
|
+
export type RootWriteOptions = Pick<RootDefaults, "denyMutations" | "durable" | "mkdir" | "mode" | "renameIdentity"> & {
|
|
41
42
|
encoding?: BufferEncoding;
|
|
42
43
|
overwrite?: boolean;
|
|
43
44
|
};
|
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,EAAe,KAAK,EAAE,MAAM,SAAS,CAAC;AAElD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAW7D,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,KAAK,oBAAoB,EAG1B,MAAM,mBAAmB,CAAC;AAY3B,OAAO,EAAwB,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAI9E,OAAO,EASL,KAAK,WAAW,EACjB,MAAM,mBAAmB,CAAC;AAa3B,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAY,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAOpF,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;
|
|
1
|
+
{"version":3,"file":"root-impl.d.ts","sourceRoot":"","sources":["../src/root-impl.ts"],"names":[],"mappings":"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"}
|
package/dist/root-impl.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { constants as fsConstants } from "node:fs";
|
|
2
|
+
import fsSync, { constants as fsConstants } from "node:fs";
|
|
3
3
|
import fs from "node:fs/promises";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { normalizeMaxBytes } from "./byte-budget.js";
|
|
@@ -87,7 +87,7 @@ async function openVerifiedLocalFile(filePath, options) {
|
|
|
87
87
|
// results that get sent to messaging channels). See openclaw/openclaw#31186.
|
|
88
88
|
try {
|
|
89
89
|
preOpenStat = await inspectFileIdentity(async () => {
|
|
90
|
-
const stat =
|
|
90
|
+
const stat = fsSync.lstatSync(filePath, { bigint: true });
|
|
91
91
|
observedBeforeOpen = true;
|
|
92
92
|
if (stat.isSymbolicLink() && options?.symlinks !== "follow-within-root") {
|
|
93
93
|
throw new FsSafeError("symlink", "symlink not allowed");
|
|
@@ -127,13 +127,13 @@ async function openVerifiedLocalFile(filePath, options) {
|
|
|
127
127
|
}
|
|
128
128
|
try {
|
|
129
129
|
await fsSafeTestHooks?.afterOpen?.(filePath, handle);
|
|
130
|
-
const stat =
|
|
130
|
+
const stat = fsSync.fstatSync(handle.fd);
|
|
131
131
|
if (!stat.isFile()) {
|
|
132
132
|
throw new FsSafeError("not-file", "not a file");
|
|
133
133
|
}
|
|
134
134
|
// Keep numeric Stats for the public receipt, never for identity verification.
|
|
135
135
|
let openedIdentity;
|
|
136
|
-
const identity = await inspectFileIdentity(async () => (openedIdentity =
|
|
136
|
+
const identity = await inspectFileIdentity(async () => (openedIdentity = fsSync.fstatSync(handle.fd, { bigint: true })), preOpenStat && !preOpenStat.isSymbolicLink() ? preOpenStat : undefined).catch(async (error) => {
|
|
137
137
|
if ([0, 1].includes(stat.nlink)) {
|
|
138
138
|
await recordPreOpenFileChange(error, handle, filePath, preOpenStat, openedIdentity);
|
|
139
139
|
}
|
|
@@ -156,8 +156,8 @@ async function openVerifiedLocalFile(filePath, options) {
|
|
|
156
156
|
};
|
|
157
157
|
await inspectPathIdentity(async () => {
|
|
158
158
|
const pathStat = options?.symlinks === "follow-within-root"
|
|
159
|
-
?
|
|
160
|
-
:
|
|
159
|
+
? fsSync.statSync(filePath, { bigint: true })
|
|
160
|
+
: fsSync.lstatSync(filePath, { bigint: true });
|
|
161
161
|
if (pathStat.isSymbolicLink() && options?.symlinks !== "follow-within-root") {
|
|
162
162
|
throw new FsSafeError("symlink", "symlink not allowed");
|
|
163
163
|
}
|
|
@@ -176,7 +176,7 @@ async function openVerifiedLocalFile(filePath, options) {
|
|
|
176
176
|
await inspectPathIdentity(async () => {
|
|
177
177
|
// Reuse the post-realpath observation; unknown Windows identities still
|
|
178
178
|
// get a fresh observation on inspectFileIdentity's retry.
|
|
179
|
-
const realStat = resolvedStat ??
|
|
179
|
+
const realStat = resolvedStat ?? fsSync.statSync(realPath, { bigint: true });
|
|
180
180
|
resolvedStat = undefined;
|
|
181
181
|
if (options?.hardlinks === "reject" && realStat.nlink > 1n) {
|
|
182
182
|
throw hardlinkedPathNotAllowedError();
|
|
@@ -275,6 +275,7 @@ export class RootHandle {
|
|
|
275
275
|
mkdir: this.defaults.mkdir,
|
|
276
276
|
mode: this.defaults.mode,
|
|
277
277
|
...this.mutationOptions(options),
|
|
278
|
+
durable: options.durable ?? this.defaults.durable ?? true,
|
|
278
279
|
});
|
|
279
280
|
}
|
|
280
281
|
async remove(relativePath, options = {}) {
|
|
@@ -307,6 +308,7 @@ export class RootHandle {
|
|
|
307
308
|
mode: this.defaults.mode,
|
|
308
309
|
renameIdentity: this.defaults.renameIdentity,
|
|
309
310
|
...this.mutationOptions(options),
|
|
311
|
+
durable: options.durable ?? this.defaults.durable ?? true,
|
|
310
312
|
});
|
|
311
313
|
}
|
|
312
314
|
async create(relativePath, data, options = {}) {
|
|
@@ -317,6 +319,7 @@ export class RootHandle {
|
|
|
317
319
|
mkdir: this.defaults.mkdir,
|
|
318
320
|
mode: this.defaults.mode,
|
|
319
321
|
...this.mutationOptions(options),
|
|
322
|
+
durable: options.durable ?? this.defaults.durable ?? true,
|
|
320
323
|
overwrite: false,
|
|
321
324
|
});
|
|
322
325
|
}
|
|
@@ -486,7 +489,7 @@ async function writeTempFileForAtomicReplace(params) {
|
|
|
486
489
|
}
|
|
487
490
|
return {
|
|
488
491
|
handle: tempHandle,
|
|
489
|
-
identity:
|
|
492
|
+
identity: fsSync.fstatSync(tempHandle.fd, { bigint: true }),
|
|
490
493
|
};
|
|
491
494
|
}
|
|
492
495
|
catch (error) {
|
|
@@ -525,7 +528,7 @@ async function openWritableFileInRoot(root, params) {
|
|
|
525
528
|
? resolved
|
|
526
529
|
: await prepareRootWriteTarget(rootReal, resolved);
|
|
527
530
|
try {
|
|
528
|
-
const resolvedRealPath =
|
|
531
|
+
const resolvedRealPath = fsSync.realpathSync.native(ioPath);
|
|
529
532
|
if (!isPathInside(rootWithSep, resolvedRealPath)) {
|
|
530
533
|
throw outsideWorkspaceError();
|
|
531
534
|
}
|
|
@@ -574,7 +577,7 @@ async function openWritableFileInRoot(root, params) {
|
|
|
574
577
|
let realPathForCleanup = null;
|
|
575
578
|
let createdIdentity = null;
|
|
576
579
|
try {
|
|
577
|
-
const stat =
|
|
580
|
+
const stat = fsSync.fstatSync(handle.fd);
|
|
578
581
|
if (createdForWrite) {
|
|
579
582
|
createdIdentity = stat;
|
|
580
583
|
}
|
|
@@ -585,7 +588,7 @@ async function openWritableFileInRoot(root, params) {
|
|
|
585
588
|
throw hardlinkedPathNotAllowedError();
|
|
586
589
|
}
|
|
587
590
|
try {
|
|
588
|
-
const lstat =
|
|
591
|
+
const lstat = fsSync.lstatSync(ioPath);
|
|
589
592
|
if (lstat.isSymbolicLink() || !lstat.isFile()) {
|
|
590
593
|
throw new FsSafeError(lstat.isSymbolicLink() ? "symlink" : "not-file", "path is not a regular file under root");
|
|
591
594
|
}
|
|
@@ -600,7 +603,7 @@ async function openWritableFileInRoot(root, params) {
|
|
|
600
603
|
}
|
|
601
604
|
const realPath = await resolveOpenedFileRealPathForHandle(handle, ioPath);
|
|
602
605
|
realPathForCleanup = realPath;
|
|
603
|
-
const realStat =
|
|
606
|
+
const realStat = fsSync.statSync(realPath);
|
|
604
607
|
if (!sameFileIdentity(stat, realStat)) {
|
|
605
608
|
throw new FsSafeError("path-mismatch", "path mismatch");
|
|
606
609
|
}
|
|
@@ -663,8 +666,9 @@ async function appendFileInRoot(root, params) {
|
|
|
663
666
|
const payload = prefix.length > 0 ? Buffer.concat([Buffer.from(prefix, "utf8"), params.data]) : params.data;
|
|
664
667
|
await target.handle.appendFile(payload);
|
|
665
668
|
}
|
|
666
|
-
|
|
667
|
-
|
|
669
|
+
if (params.durable !== false)
|
|
670
|
+
await target.handle.sync();
|
|
671
|
+
if (params.durable !== false && target.createdForWrite) {
|
|
668
672
|
await syncDirectoryBestEffort(path.dirname(target.realPath));
|
|
669
673
|
}
|
|
670
674
|
}
|
|
@@ -720,6 +724,7 @@ async function commitPinnedWriteInRoot(root, pinned, params) {
|
|
|
720
724
|
renameIdentity: params.renameIdentity,
|
|
721
725
|
mkdir: params.mkdir !== false,
|
|
722
726
|
mode: params.mode ?? pinned.mode,
|
|
727
|
+
sync: params.durable !== false,
|
|
723
728
|
overwrite: params.overwrite,
|
|
724
729
|
input: { kind: "buffer", data: params.data, encoding: params.encoding },
|
|
725
730
|
rootIdentity: root.rootIdentity,
|
|
@@ -803,12 +808,12 @@ async function copyFileInRoot(root, params) {
|
|
|
803
808
|
}
|
|
804
809
|
}
|
|
805
810
|
async function assertCopySourceCurrent(source, identity) {
|
|
806
|
-
await inspectFileIdentity(() => source.handle.
|
|
811
|
+
await inspectFileIdentity(() => fsSync.fstatSync(source.handle.fd, { bigint: true }), identity);
|
|
807
812
|
await assertCopySourcePathCurrent(source, identity);
|
|
808
813
|
}
|
|
809
814
|
async function assertCopySourcePathCurrent(source, identity) {
|
|
810
815
|
await inspectFileIdentity(async () => {
|
|
811
|
-
const current =
|
|
816
|
+
const current = fsSync.lstatSync(source.realPath, { bigint: true });
|
|
812
817
|
if (current.isSymbolicLink() || !current.isFile()) {
|
|
813
818
|
throw new FsSafeError("path-mismatch", "copy source path changed");
|
|
814
819
|
}
|
|
@@ -817,7 +822,7 @@ async function assertCopySourcePathCurrent(source, identity) {
|
|
|
817
822
|
}
|
|
818
823
|
async function removePathIfIdentityUnchanged(targetPath, identity) {
|
|
819
824
|
const parentGuard = await createAsyncDirectoryGuard(path.dirname(targetPath));
|
|
820
|
-
const current =
|
|
825
|
+
const current = fsSync.lstatSync(targetPath);
|
|
821
826
|
if (current.isSymbolicLink() || !sameFileIdentityForCleanup(current, identity)) {
|
|
822
827
|
return;
|
|
823
828
|
}
|
|
@@ -847,7 +852,7 @@ async function resolvePinnedWriteTargetInRoot(root, relativePath, requestedMode,
|
|
|
847
852
|
// and alias checks, but never open a competing owner's record just to reject it.
|
|
848
853
|
if (!overwrite) {
|
|
849
854
|
try {
|
|
850
|
-
const existing =
|
|
855
|
+
const existing = fsSync.statSync(resolved);
|
|
851
856
|
if (!existing.isFile())
|
|
852
857
|
throw new FsSafeError("not-file", "not a file");
|
|
853
858
|
if (existing.nlink > 1)
|
|
@@ -945,7 +950,7 @@ async function prepareRemoveGuard(targetPath) {
|
|
|
945
950
|
async function removePathFallback(resolved) {
|
|
946
951
|
const guard = await prepareRemoveGuard(resolved.resolved);
|
|
947
952
|
try {
|
|
948
|
-
await (
|
|
953
|
+
await (fsSync.lstatSync(resolved.resolved).isDirectory() ? fs.rmdir(resolved.resolved) : fs.rm(resolved.resolved));
|
|
949
954
|
}
|
|
950
955
|
catch (error) {
|
|
951
956
|
throw normalizeRemovePathError(error);
|
|
@@ -961,7 +966,7 @@ async function mkdirPathFallback(resolved) {
|
|
|
961
966
|
async function statPathFallback(root, relativePath) {
|
|
962
967
|
const resolved = await resolvePinnedPathInRoot(root, { relativePath, allowRoot: true });
|
|
963
968
|
try {
|
|
964
|
-
const stat = pathStatFromStats(
|
|
969
|
+
const stat = pathStatFromStats(fsSync.lstatSync(resolved.resolved));
|
|
965
970
|
await assertRootIdentityCurrent(root);
|
|
966
971
|
return stat;
|
|
967
972
|
}
|
|
@@ -985,7 +990,7 @@ async function listPathFallback(root, relativePath, withFileTypes) {
|
|
|
985
990
|
for (const name of sortedNames) {
|
|
986
991
|
entries.push({
|
|
987
992
|
name,
|
|
988
|
-
...pathStatFromStats(
|
|
993
|
+
...pathStatFromStats(fsSync.lstatSync(path.join(resolved.resolved, name))),
|
|
989
994
|
});
|
|
990
995
|
}
|
|
991
996
|
await assertRootIdentityCurrent(root);
|
|
@@ -1034,7 +1039,11 @@ async function movePathFallback(root, params) {
|
|
|
1034
1039
|
relativePath: params.toRelative,
|
|
1035
1040
|
policy: PATH_ALIAS_POLICIES.unlinkTarget,
|
|
1036
1041
|
});
|
|
1037
|
-
|
|
1042
|
+
let targetStat;
|
|
1043
|
+
try {
|
|
1044
|
+
targetStat = fsSync.lstatSync(resolvedTarget.resolved);
|
|
1045
|
+
}
|
|
1046
|
+
catch { /* Advisory lookup. */ }
|
|
1038
1047
|
return !(process.platform !== "win32" &&
|
|
1039
1048
|
params.overwrite &&
|
|
1040
1049
|
targetStat?.isSymbolicLink() === true);
|
|
@@ -1042,7 +1051,7 @@ async function movePathFallback(root, params) {
|
|
|
1042
1051
|
});
|
|
1043
1052
|
let sourceStat;
|
|
1044
1053
|
try {
|
|
1045
|
-
sourceStat =
|
|
1054
|
+
sourceStat = fsSync.lstatSync(source.resolved);
|
|
1046
1055
|
}
|
|
1047
1056
|
catch (error) {
|
|
1048
1057
|
if (isNotFoundPathError(error)) {
|
|
@@ -1061,7 +1070,7 @@ async function movePathFallback(root, params) {
|
|
|
1061
1070
|
}
|
|
1062
1071
|
if (!params.overwrite) {
|
|
1063
1072
|
try {
|
|
1064
|
-
|
|
1073
|
+
fsSync.lstatSync(target.resolved);
|
|
1065
1074
|
throw new FsSafeError("already-exists", "destination exists");
|
|
1066
1075
|
}
|
|
1067
1076
|
catch (error) {
|
|
@@ -1171,8 +1180,8 @@ async function writeMissingFileFallback(root, params) {
|
|
|
1171
1180
|
const handle = await fs.open(targetPath, OPEN_WRITE_CREATE_FLAGS, params.mode ?? 0o600).catch((error) => recordExclusiveCreateFailure(error, targetPath));
|
|
1172
1181
|
created = true;
|
|
1173
1182
|
try {
|
|
1174
|
-
createdIdentity =
|
|
1175
|
-
const writtenStat =
|
|
1183
|
+
createdIdentity = fsSync.fstatSync(handle.fd);
|
|
1184
|
+
const writtenStat = fsSync.fstatSync(handle.fd, { bigint: true });
|
|
1176
1185
|
if (typeof params.data === "string") {
|
|
1177
1186
|
await handle.writeFile(params.data, params.encoding ?? "utf8");
|
|
1178
1187
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-path-existing.d.ts","sourceRoot":"","sources":["../src/root-path-existing.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"root-path-existing.d.ts","sourceRoot":"","sources":["../src/root-path-existing.ts"],"names":[],"mappings":"AAoBA,wBAAsB,8BAA8B,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BxF;AAED,wBAAgB,kCAAkC,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CA0B7E"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
-
import fsp from "node:fs/promises";
|
|
3
2
|
import path from "node:path";
|
|
4
3
|
import { isNotFoundPathError } from "./path.js";
|
|
5
4
|
function isFilesystemRoot(candidate) {
|
|
@@ -7,7 +6,7 @@ function isFilesystemRoot(candidate) {
|
|
|
7
6
|
}
|
|
8
7
|
async function pathExists(targetPath) {
|
|
9
8
|
try {
|
|
10
|
-
|
|
9
|
+
fs.lstatSync(targetPath);
|
|
11
10
|
return true;
|
|
12
11
|
}
|
|
13
12
|
catch (error) {
|
|
@@ -33,7 +32,7 @@ export async function resolvePathViaExistingAncestor(targetPath) {
|
|
|
33
32
|
return normalized;
|
|
34
33
|
}
|
|
35
34
|
try {
|
|
36
|
-
const resolvedAncestor = path.resolve(
|
|
35
|
+
const resolvedAncestor = path.resolve(fs.realpathSync.native(cursor));
|
|
37
36
|
return missingSuffix.length === 0
|
|
38
37
|
? resolvedAncestor
|
|
39
38
|
: path.resolve(resolvedAncestor, ...missingSuffix);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-path-symlink.d.ts","sourceRoot":"","sources":["../src/root-path-symlink.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"root-path-symlink.d.ts","sourceRoot":"","sources":["../src/root-path-symlink.ts"],"names":[],"mappings":"AASA,KAAK,wBAAwB,GAAG;IAC9B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAiBF,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,MAAM,CAAC,CAQjB;AAED,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,wBAA6B,GACrC,MAAM,CAQR"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
-
import fsp from "node:fs/promises";
|
|
3
2
|
import path from "node:path";
|
|
4
3
|
import { FsSafeError } from "./errors.js";
|
|
5
4
|
import { isNotFoundPathError, isSymlinkOpenError } from "./path.js";
|
|
@@ -16,11 +15,11 @@ function normalizeSymlinkResolutionError(error, options) {
|
|
|
16
15
|
}
|
|
17
16
|
export async function resolveSymlinkHopPath(symlinkPath, options = {}) {
|
|
18
17
|
try {
|
|
19
|
-
return path.resolve(
|
|
18
|
+
return path.resolve(fs.realpathSync.native(symlinkPath));
|
|
20
19
|
}
|
|
21
20
|
catch (error) {
|
|
22
21
|
normalizeSymlinkResolutionError(error, options);
|
|
23
|
-
const linkTarget =
|
|
22
|
+
const linkTarget = fs.readlinkSync(symlinkPath);
|
|
24
23
|
return resolvePathViaExistingAncestor(path.resolve(path.dirname(symlinkPath), linkTarget));
|
|
25
24
|
}
|
|
26
25
|
}
|