@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.
Files changed (159) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +1 -1
  3. package/dist/advanced.d.ts +2 -2
  4. package/dist/advanced.d.ts.map +1 -1
  5. package/dist/advanced.js +2 -2
  6. package/dist/archive-kind.d.ts +1 -0
  7. package/dist/archive-kind.d.ts.map +1 -1
  8. package/dist/archive-kind.js +6 -0
  9. package/dist/archive-limits.d.ts +0 -1
  10. package/dist/archive-limits.d.ts.map +1 -1
  11. package/dist/archive-limits.js +0 -3
  12. package/dist/archive-native.d.ts.map +1 -1
  13. package/dist/archive-native.js +5 -8
  14. package/dist/archive-parser-errors.d.ts +2 -0
  15. package/dist/archive-parser-errors.d.ts.map +1 -0
  16. package/dist/archive-parser-errors.js +12 -0
  17. package/dist/archive-read.d.ts.map +1 -1
  18. package/dist/archive-read.js +7 -13
  19. package/dist/archive-tar-wasm.d.ts +1 -1
  20. package/dist/archive-tar-wasm.d.ts.map +1 -1
  21. package/dist/archive-tar-wasm.js +5 -8
  22. package/dist/archive.d.ts.map +1 -1
  23. package/dist/archive.js +43 -6
  24. package/dist/atomic.d.ts +1 -1
  25. package/dist/atomic.d.ts.map +1 -1
  26. package/dist/atomic.js +1 -1
  27. package/dist/bounded-read-stream.d.ts +1 -5
  28. package/dist/bounded-read-stream.d.ts.map +1 -1
  29. package/dist/bounded-read-stream.js +5 -13
  30. package/dist/byte-budget.d.ts +0 -1
  31. package/dist/byte-budget.d.ts.map +1 -1
  32. package/dist/byte-budget.js +1 -1
  33. package/dist/directory-mode-owner.d.ts.map +1 -1
  34. package/dist/directory-mode-owner.js +2 -0
  35. package/dist/error-detail.d.ts +1 -0
  36. package/dist/error-detail.d.ts.map +1 -1
  37. package/dist/error-detail.js +6 -0
  38. package/dist/file-store-boundary.d.ts +1 -1
  39. package/dist/file-store-boundary.d.ts.map +1 -1
  40. package/dist/file-store-boundary.js +2 -13
  41. package/dist/file-store.js +1 -1
  42. package/dist/file-sync.d.ts +5 -0
  43. package/dist/file-sync.d.ts.map +1 -0
  44. package/dist/file-sync.js +19 -0
  45. package/dist/guarded-mutation.d.ts +3 -0
  46. package/dist/guarded-mutation.d.ts.map +1 -1
  47. package/dist/guarded-mutation.js +5 -1
  48. package/dist/home-dir.d.ts +0 -10
  49. package/dist/home-dir.d.ts.map +1 -1
  50. package/dist/home-dir.js +0 -28
  51. package/dist/json-durable-queue-ownership.d.ts +1 -0
  52. package/dist/json-durable-queue-ownership.d.ts.map +1 -1
  53. package/dist/json-durable-queue-ownership.js +139 -18
  54. package/dist/json-durable-queue.d.ts.map +1 -1
  55. package/dist/json-durable-queue.js +5 -10
  56. package/dist/json-store.d.ts.map +1 -1
  57. package/dist/json-store.js +1 -1
  58. package/dist/local-roots.d.ts.map +1 -1
  59. package/dist/local-roots.js +2 -3
  60. package/dist/move-path-cleanup.d.ts +1 -1
  61. package/dist/move-path-cleanup.d.ts.map +1 -1
  62. package/dist/move-path-cleanup.js +4 -2
  63. package/dist/move-path.d.ts +9 -0
  64. package/dist/move-path.d.ts.map +1 -1
  65. package/dist/move-path.js +53 -16
  66. package/dist/native-operations.d.ts +0 -1
  67. package/dist/native-operations.d.ts.map +1 -1
  68. package/dist/native-operations.js +0 -10
  69. package/dist/native-pinned-write-windows.d.ts.map +1 -1
  70. package/dist/native-pinned-write-windows.js +5 -4
  71. package/dist/native-staged-file.d.ts +8 -1
  72. package/dist/native-staged-file.d.ts.map +1 -1
  73. package/dist/native-staged-file.js +30 -9
  74. package/dist/opened-realpath.d.ts +12 -1
  75. package/dist/opened-realpath.d.ts.map +1 -1
  76. package/dist/opened-realpath.js +8 -7
  77. package/dist/output.d.ts.map +1 -1
  78. package/dist/output.js +26 -2
  79. package/dist/path-policy.js +1 -1
  80. package/dist/permissions.d.ts +1 -0
  81. package/dist/permissions.d.ts.map +1 -1
  82. package/dist/permissions.js +3 -0
  83. package/dist/pinned-write.d.ts +1 -2
  84. package/dist/pinned-write.d.ts.map +1 -1
  85. package/dist/pinned-write.js +2 -11
  86. package/dist/private-temp-workspace.js +1 -1
  87. package/dist/publish-file.js +2 -2
  88. package/dist/replace-file-copy-source.d.ts.map +1 -1
  89. package/dist/replace-file-copy-source.js +2 -7
  90. package/dist/replace-file-descriptor.d.ts.map +1 -1
  91. package/dist/replace-file-descriptor.js +3 -16
  92. package/dist/replace-file-temp-owner.d.ts.map +1 -1
  93. package/dist/replace-file-temp-owner.js +2 -7
  94. package/dist/replace-file.d.ts.map +1 -1
  95. package/dist/replace-file.js +21 -8
  96. package/dist/root-errors.d.ts +1 -0
  97. package/dist/root-errors.d.ts.map +1 -1
  98. package/dist/root-errors.js +9 -0
  99. package/dist/root-file.d.ts.map +1 -1
  100. package/dist/root-file.js +17 -28
  101. package/dist/root-impl.d.ts.map +1 -1
  102. package/dist/root-impl.js +12 -33
  103. package/dist/root-path.d.ts.map +1 -1
  104. package/dist/root-path.js +49 -94
  105. package/dist/root-write-mode.d.ts +6 -0
  106. package/dist/root-write-mode.d.ts.map +1 -0
  107. package/dist/root-write-mode.js +60 -0
  108. package/dist/root-write-verification.js +2 -2
  109. package/dist/safe-path-segment.d.ts +1 -0
  110. package/dist/safe-path-segment.d.ts.map +1 -1
  111. package/dist/safe-path-segment.js +1 -1
  112. package/dist/secret-file.d.ts.map +1 -1
  113. package/dist/secret-file.js +2 -9
  114. package/dist/secret-read-async.d.ts.map +1 -1
  115. package/dist/secret-read-async.js +2 -10
  116. package/dist/secret-read-policy.d.ts +4 -0
  117. package/dist/secret-read-policy.d.ts.map +1 -1
  118. package/dist/secret-read-policy.js +12 -0
  119. package/dist/sibling-staged-file.d.ts.map +1 -1
  120. package/dist/sibling-staged-file.js +2 -7
  121. package/dist/sidecar-lock-policy.d.ts +0 -1
  122. package/dist/sidecar-lock-policy.d.ts.map +1 -1
  123. package/dist/sidecar-lock-policy.js +0 -4
  124. package/dist/string-coerce.d.ts +0 -9
  125. package/dist/string-coerce.d.ts.map +1 -1
  126. package/dist/string-coerce.js +0 -56
  127. package/dist/temp-target.d.ts.map +1 -1
  128. package/dist/temp-target.js +1 -12
  129. package/docs/atomic.md +53 -19
  130. package/docs/staged-file.md +6 -2
  131. package/docs/writing.md +5 -0
  132. package/package.json +8 -8
  133. package/dist/archive-tar-extract.d.ts +0 -11
  134. package/dist/archive-tar-extract.d.ts.map +0 -1
  135. package/dist/archive-tar-extract.js +0 -49
  136. package/dist/fsync.d.ts +0 -2
  137. package/dist/fsync.d.ts.map +0 -1
  138. package/dist/fsync.js +0 -1
  139. package/dist/json-durable-queue-retirement.d.ts +0 -9
  140. package/dist/json-durable-queue-retirement.d.ts.map +0 -1
  141. package/dist/json-durable-queue-retirement.js +0 -126
  142. package/dist/json-durable-queue-transfer-lock.d.ts +0 -2
  143. package/dist/json-durable-queue-transfer-lock.d.ts.map +0 -1
  144. package/dist/json-durable-queue-transfer-lock.js +0 -19
  145. package/dist/mode.d.ts +0 -2
  146. package/dist/mode.d.ts.map +0 -1
  147. package/dist/mode.js +0 -3
  148. package/dist/output-sibling.d.ts +0 -8
  149. package/dist/output-sibling.d.ts.map +0 -1
  150. package/dist/output-sibling.js +0 -30
  151. package/dist/read-error.d.ts +0 -2
  152. package/dist/read-error.d.ts.map +0 -1
  153. package/dist/read-error.js +0 -11
  154. package/dist/short-path.d.ts +0 -2
  155. package/dist/short-path.d.ts.map +0 -1
  156. package/dist/short-path.js +0 -7
  157. package/dist/staged-file.d.ts +0 -10
  158. package/dist/staged-file.d.ts.map +0 -1
  159. 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":"AAEA,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;AAO3D,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
+ {"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, syncNativeFileBestEffort, writeNativeInput, } from "./native-operations.js";
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
- syncNativeFileBestEffort(tempFd);
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
- syncNativeFileBestEffort(targetFd);
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
- syncNativeFileBestEffort(parentFd);
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":"AAEA,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,CAgD9F;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"}
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 { syncNativeFileBestEffort, writeNativeInput } from "./native-operations.js";
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
- if (!this.#binding.stagedFileMatches(this.#parentFd, name, fd) ||
166
- fs.fstatSync(fd, { bigint: true }).nlink !== 1n) {
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
- syncNativeFileBestEffort(fd);
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
- fs.fchmodSync(fd, this.#publishedMode);
264
- syncNativeFileBestEffort(fd);
265
- syncNativeFileBestEffort(this.#parentFd);
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: FileIdentityStat, ioPath: string): Promise<string>;
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,wBAAsB,8BAA8B,CAClD,EAAE,EAAE,MAAM,EACV,UAAU,EAAE,gBAAgB,EAC5B,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CA2CjB"}
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"}
@@ -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
- : process.platform === "win32"
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
- return await fs.realpath(candidatePath);
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) {
@@ -1 +1 @@
1
- {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AASA,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"}
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
+ }
@@ -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 "./short-path.js";
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({
@@ -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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"}
@@ -120,3 +120,6 @@ export function isWorldReadable(bits) {
120
120
  export function isGroupReadable(bits) {
121
121
  return bits != null && (bits & 0o040) !== 0;
122
122
  }
123
+ export function formatPosixMode(mode) {
124
+ return (mode & 0o777).toString(8).padStart(3, "0");
125
+ }
@@ -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?: RenameIdentityMismatchPolicy;
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":"AAKA,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;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,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"}
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"}
@@ -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 "./fsync.js";
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 "./read-error.js";
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";
@@ -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 { syncNativeFileBestEffort } from "./native-operations.js";
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
- syncNativeFileBestEffort(sourceNativeParent.handle.fd);
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;AAMnD,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;AAgEF,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
+ {"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 NOFOLLOW = process.platform !== "win32" && "O_NOFOLLOW" in syncFs.constants
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":"AAAA,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,CA0BzD;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,CA0BxC"}
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
- try {
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
- try {
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;AAM9F,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;AAqEF,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
+ {"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 = syncFs.constants.O_RDONLY |
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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"}
@@ -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
- await params.assertSourceCurrent();
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
- params.assertSourceCurrent();
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;
@@ -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"}