@openclaw/fs-safe 0.11.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (416) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/README.md +15 -8
  3. package/dist/absolute-path.d.ts.map +1 -1
  4. package/dist/absolute-path.js +32 -11
  5. package/dist/advanced.d.ts +3 -1
  6. package/dist/advanced.d.ts.map +1 -1
  7. package/dist/advanced.js +3 -1
  8. package/dist/archive-entry.d.ts.map +1 -1
  9. package/dist/archive-entry.js +4 -3
  10. package/dist/archive-gzip-tail.d.ts.map +1 -1
  11. package/dist/archive-gzip-tail.js +13 -9
  12. package/dist/archive-input.d.ts.map +1 -1
  13. package/dist/archive-input.js +6 -2
  14. package/dist/archive-merge.d.ts.map +1 -1
  15. package/dist/archive-merge.js +15 -2
  16. package/dist/archive-native.d.ts.map +1 -1
  17. package/dist/archive-native.js +7 -19
  18. package/dist/archive-plan.js +1 -1
  19. package/dist/archive-read.d.ts.map +1 -1
  20. package/dist/archive-read.js +55 -46
  21. package/dist/archive-staging.d.ts.map +1 -1
  22. package/dist/archive-staging.js +43 -10
  23. package/dist/archive-tar-inspect.d.ts.map +1 -1
  24. package/dist/archive-tar-inspect.js +4 -1
  25. package/dist/archive-zip-admission.d.ts +1 -1
  26. package/dist/archive-zip-admission.d.ts.map +1 -1
  27. package/dist/archive-zip-admission.js +2 -2
  28. package/dist/archive-zip-directory.d.ts +3 -0
  29. package/dist/archive-zip-directory.d.ts.map +1 -1
  30. package/dist/archive-zip-directory.js +13 -2
  31. package/dist/archive-zip-loader.d.ts +3 -2
  32. package/dist/archive-zip-loader.d.ts.map +1 -1
  33. package/dist/archive-zip-loader.js +30 -4
  34. package/dist/archive-zip-manifest.d.ts +5 -0
  35. package/dist/archive-zip-manifest.d.ts.map +1 -0
  36. package/dist/archive-zip-manifest.js +22 -0
  37. package/dist/archive-zip-names.d.ts +6 -1
  38. package/dist/archive-zip-names.d.ts.map +1 -1
  39. package/dist/archive-zip-names.js +50 -17
  40. package/dist/archive-zip-preflight.d.ts.map +1 -1
  41. package/dist/archive-zip-preflight.js +3 -2
  42. package/dist/archive.d.ts.map +1 -1
  43. package/dist/archive.js +9 -4
  44. package/dist/bounded-read.js +2 -2
  45. package/dist/darwin-acl.d.ts +4 -0
  46. package/dist/darwin-acl.d.ts.map +1 -0
  47. package/dist/darwin-acl.js +24 -0
  48. package/dist/deny-mutations.d.ts.map +1 -1
  49. package/dist/deny-mutations.js +8 -2
  50. package/dist/device-path.d.ts.map +1 -1
  51. package/dist/device-path.js +5 -3
  52. package/dist/directory-durability.d.ts.map +1 -1
  53. package/dist/directory-durability.js +67 -23
  54. package/dist/directory-entry-path.d.ts +3 -0
  55. package/dist/directory-entry-path.d.ts.map +1 -0
  56. package/dist/directory-entry-path.js +21 -0
  57. package/dist/directory-guard.d.ts +17 -1
  58. package/dist/directory-guard.d.ts.map +1 -1
  59. package/dist/directory-guard.js +134 -48
  60. package/dist/directory-mode-node.d.ts +12 -0
  61. package/dist/directory-mode-node.d.ts.map +1 -1
  62. package/dist/directory-mode-node.js +102 -4
  63. package/dist/effective-uid.d.ts +2 -0
  64. package/dist/effective-uid.d.ts.map +1 -0
  65. package/dist/effective-uid.js +25 -0
  66. package/dist/file-handle-transfer.d.ts.map +1 -1
  67. package/dist/file-handle-transfer.js +98 -27
  68. package/dist/file-hash.d.ts.map +1 -1
  69. package/dist/file-hash.js +12 -2
  70. package/dist/file-lock-sync.d.ts.map +1 -1
  71. package/dist/file-lock-sync.js +36 -6
  72. package/dist/file-lock.d.ts.map +1 -1
  73. package/dist/file-lock.js +29 -9
  74. package/dist/file-observation.d.ts +1 -1
  75. package/dist/file-observation.d.ts.map +1 -1
  76. package/dist/file-store-boundary.d.ts +6 -2
  77. package/dist/file-store-boundary.d.ts.map +1 -1
  78. package/dist/file-store-boundary.js +20 -65
  79. package/dist/file-store-copy-source.d.ts +5 -0
  80. package/dist/file-store-copy-source.d.ts.map +1 -0
  81. package/dist/file-store-copy-source.js +31 -0
  82. package/dist/file-store-path.d.ts.map +1 -1
  83. package/dist/file-store-path.js +4 -1
  84. package/dist/file-store-prune.d.ts.map +1 -1
  85. package/dist/file-store-prune.js +9 -1
  86. package/dist/file-store-sync-directory.d.ts +16 -0
  87. package/dist/file-store-sync-directory.d.ts.map +1 -0
  88. package/dist/file-store-sync-directory.js +349 -0
  89. package/dist/file-store.d.ts.map +1 -1
  90. package/dist/file-store.js +11 -28
  91. package/dist/filename.d.ts +1 -0
  92. package/dist/filename.d.ts.map +1 -1
  93. package/dist/filename.js +85 -23
  94. package/dist/fs.d.ts.map +1 -1
  95. package/dist/fs.js +3 -2
  96. package/dist/guarded-mkdir.d.ts +10 -0
  97. package/dist/guarded-mkdir.d.ts.map +1 -1
  98. package/dist/guarded-mkdir.js +217 -33
  99. package/dist/guest.d.ts.map +1 -1
  100. package/dist/guest.js +16 -5
  101. package/dist/home-dir.d.ts.map +1 -1
  102. package/dist/home-dir.js +73 -10
  103. package/dist/install-path.d.ts +6 -0
  104. package/dist/install-path.d.ts.map +1 -1
  105. package/dist/install-path.js +67 -19
  106. package/dist/json-durable-queue-ownership.d.ts +8 -0
  107. package/dist/json-durable-queue-ownership.d.ts.map +1 -1
  108. package/dist/json-durable-queue-ownership.js +134 -43
  109. package/dist/json-durable-queue-paths.d.ts +11 -0
  110. package/dist/json-durable-queue-paths.d.ts.map +1 -0
  111. package/dist/json-durable-queue-paths.js +42 -0
  112. package/dist/json-durable-queue-read.d.ts +6 -0
  113. package/dist/json-durable-queue-read.d.ts.map +1 -0
  114. package/dist/json-durable-queue-read.js +61 -0
  115. package/dist/json-durable-queue.d.ts +1 -1
  116. package/dist/json-durable-queue.d.ts.map +1 -1
  117. package/dist/json-durable-queue.js +83 -134
  118. package/dist/json-store.d.ts.map +1 -1
  119. package/dist/json-store.js +5 -1
  120. package/dist/json.d.ts.map +1 -1
  121. package/dist/json.js +54 -22
  122. package/dist/local-file-access.d.ts.map +1 -1
  123. package/dist/local-file-access.js +4 -0
  124. package/dist/local-file-descriptor.d.ts +17 -0
  125. package/dist/local-file-descriptor.d.ts.map +1 -0
  126. package/dist/local-file-descriptor.js +84 -0
  127. package/dist/local-roots.d.ts.map +1 -1
  128. package/dist/local-roots.js +35 -7
  129. package/dist/move-path-cleanup.d.ts +2 -0
  130. package/dist/move-path-cleanup.d.ts.map +1 -1
  131. package/dist/move-path-cleanup.js +44 -18
  132. package/dist/move-path.d.ts.map +1 -1
  133. package/dist/move-path.js +31 -6
  134. package/dist/native-binding.d.ts +21 -0
  135. package/dist/native-binding.d.ts.map +1 -1
  136. package/dist/native-directory-observation.d.ts +17 -0
  137. package/dist/native-directory-observation.d.ts.map +1 -0
  138. package/dist/native-directory-observation.js +37 -0
  139. package/dist/native-parent-admission.d.ts +31 -0
  140. package/dist/native-parent-admission.d.ts.map +1 -0
  141. package/dist/native-parent-admission.js +124 -0
  142. package/dist/native-pinned-write-windows.d.ts +0 -1
  143. package/dist/native-pinned-write-windows.d.ts.map +1 -1
  144. package/dist/native-pinned-write-windows.js +0 -3
  145. package/dist/native-pinned-write.d.ts.map +1 -1
  146. package/dist/native-pinned-write.js +309 -40
  147. package/dist/output.d.ts.map +1 -1
  148. package/dist/output.js +15 -5
  149. package/dist/overwrite-file-handle.d.ts.map +1 -1
  150. package/dist/overwrite-file-handle.js +5 -1
  151. package/dist/owner-dacl.d.ts.map +1 -1
  152. package/dist/owner-dacl.js +2 -0
  153. package/dist/path-policy.d.ts.map +1 -1
  154. package/dist/path-policy.js +7 -2
  155. package/dist/path-prefix.d.ts +7 -0
  156. package/dist/path-prefix.d.ts.map +1 -0
  157. package/dist/path-prefix.js +82 -0
  158. package/dist/path-scope-lexical.d.ts +14 -0
  159. package/dist/path-scope-lexical.d.ts.map +1 -0
  160. package/dist/path-scope-lexical.js +37 -0
  161. package/dist/path-segment-route.d.ts +7 -0
  162. package/dist/path-segment-route.d.ts.map +1 -0
  163. package/dist/path-segment-route.js +24 -0
  164. package/dist/path-suffix-aliases.d.ts +10 -0
  165. package/dist/path-suffix-aliases.d.ts.map +1 -0
  166. package/dist/path-suffix-aliases.js +386 -0
  167. package/dist/path.d.ts.map +1 -1
  168. package/dist/path.js +35 -6
  169. package/dist/permissions-windows.d.ts.map +1 -1
  170. package/dist/permissions-windows.js +14 -3
  171. package/dist/permissions.d.ts.map +1 -1
  172. package/dist/permissions.js +37 -8
  173. package/dist/pinned-mutation-admission.d.ts +25 -0
  174. package/dist/pinned-mutation-admission.d.ts.map +1 -0
  175. package/dist/pinned-mutation-admission.js +425 -0
  176. package/dist/pinned-mutation-observation.d.ts +34 -0
  177. package/dist/pinned-mutation-observation.d.ts.map +1 -0
  178. package/dist/pinned-mutation-observation.js +142 -0
  179. package/dist/pinned-mutation-shared-route.d.ts +24 -0
  180. package/dist/pinned-mutation-shared-route.d.ts.map +1 -0
  181. package/dist/pinned-mutation-shared-route.js +70 -0
  182. package/dist/pinned-open.d.ts +6 -0
  183. package/dist/pinned-open.d.ts.map +1 -1
  184. package/dist/pinned-open.js +28 -10
  185. package/dist/pinned-write-types.d.ts +75 -0
  186. package/dist/pinned-write-types.d.ts.map +1 -0
  187. package/dist/pinned-write-types.js +1 -0
  188. package/dist/pinned-write.d.ts +7 -33
  189. package/dist/pinned-write.d.ts.map +1 -1
  190. package/dist/pinned-write.js +152 -17
  191. package/dist/private-directory.d.ts.map +1 -1
  192. package/dist/private-directory.js +2 -0
  193. package/dist/private-producer-handoff.d.ts +16 -0
  194. package/dist/private-producer-handoff.d.ts.map +1 -0
  195. package/dist/private-producer-handoff.js +272 -0
  196. package/dist/private-temp-workspace.d.ts +2 -39
  197. package/dist/private-temp-workspace.d.ts.map +1 -1
  198. package/dist/private-temp-workspace.js +183 -77
  199. package/dist/publish-file.d.ts.map +1 -1
  200. package/dist/publish-file.js +33 -29
  201. package/dist/regular-file.d.ts.map +1 -1
  202. package/dist/regular-file.js +56 -45
  203. package/dist/replace-directory.d.ts.map +1 -1
  204. package/dist/replace-directory.js +12 -5
  205. package/dist/replace-file-temp-owner.d.ts +1 -0
  206. package/dist/replace-file-temp-owner.d.ts.map +1 -1
  207. package/dist/replace-file-temp-owner.js +12 -1
  208. package/dist/replace-file.d.ts.map +1 -1
  209. package/dist/replace-file.js +24 -24
  210. package/dist/root-boundary.d.ts +29 -0
  211. package/dist/root-boundary.d.ts.map +1 -0
  212. package/dist/root-boundary.js +182 -0
  213. package/dist/root-context.d.ts +12 -1
  214. package/dist/root-context.d.ts.map +1 -1
  215. package/dist/root-context.js +89 -16
  216. package/dist/root-directory-creation.d.ts +13 -0
  217. package/dist/root-directory-creation.d.ts.map +1 -0
  218. package/dist/root-directory-creation.js +212 -0
  219. package/dist/root-directory-list.d.ts +16 -4
  220. package/dist/root-directory-list.d.ts.map +1 -1
  221. package/dist/root-directory-list.js +182 -33
  222. package/dist/root-directory.d.ts +23 -0
  223. package/dist/root-directory.d.ts.map +1 -0
  224. package/dist/root-directory.js +141 -0
  225. package/dist/root-errors.d.ts.map +1 -1
  226. package/dist/root-errors.js +12 -1
  227. package/dist/root-file-final-admission.d.ts +21 -0
  228. package/dist/root-file-final-admission.d.ts.map +1 -0
  229. package/dist/root-file-final-admission.js +83 -0
  230. package/dist/root-file.d.ts.map +1 -1
  231. package/dist/root-file.js +103 -24
  232. package/dist/root-impl.d.ts +1 -0
  233. package/dist/root-impl.d.ts.map +1 -1
  234. package/dist/root-impl.js +316 -325
  235. package/dist/root-move-noreplace.d.ts +14 -0
  236. package/dist/root-move-noreplace.d.ts.map +1 -0
  237. package/dist/root-move-noreplace.js +202 -0
  238. package/dist/root-move-preflight.d.ts +8 -0
  239. package/dist/root-move-preflight.d.ts.map +1 -0
  240. package/dist/root-move-preflight.js +16 -0
  241. package/dist/root-observed-path.d.ts +9 -0
  242. package/dist/root-observed-path.d.ts.map +1 -0
  243. package/dist/root-observed-path.js +95 -0
  244. package/dist/root-path-errors.d.ts +12 -0
  245. package/dist/root-path-errors.d.ts.map +1 -0
  246. package/dist/root-path-errors.js +13 -0
  247. package/dist/root-path-existing.d.ts +2 -0
  248. package/dist/root-path-existing.d.ts.map +1 -1
  249. package/dist/root-path-existing.js +63 -22
  250. package/dist/root-path-observation.d.ts +63 -0
  251. package/dist/root-path-observation.d.ts.map +1 -0
  252. package/dist/root-path-observation.js +180 -0
  253. package/dist/root-path-stat.d.ts +5 -0
  254. package/dist/root-path-stat.d.ts.map +1 -0
  255. package/dist/root-path-stat.js +101 -0
  256. package/dist/root-path-symlink.d.ts.map +1 -1
  257. package/dist/root-path-symlink.js +23 -4
  258. package/dist/root-path.d.ts +13 -0
  259. package/dist/root-path.d.ts.map +1 -1
  260. package/dist/root-path.js +263 -73
  261. package/dist/root-paths-lexical.d.ts +9 -0
  262. package/dist/root-paths-lexical.d.ts.map +1 -0
  263. package/dist/root-paths-lexical.js +22 -0
  264. package/dist/root-paths.d.ts +3 -29
  265. package/dist/root-paths.d.ts.map +1 -1
  266. package/dist/root-paths.js +89 -178
  267. package/dist/root-read-admission.d.ts +26 -0
  268. package/dist/root-read-admission.d.ts.map +1 -0
  269. package/dist/root-read-admission.js +94 -0
  270. package/dist/root-remove-identity.d.ts +15 -0
  271. package/dist/root-remove-identity.d.ts.map +1 -0
  272. package/dist/root-remove-identity.js +89 -0
  273. package/dist/root-remove-receipt.d.ts +17 -0
  274. package/dist/root-remove-receipt.d.ts.map +1 -0
  275. package/dist/root-remove-receipt.js +37 -0
  276. package/dist/root-remove.d.ts +2 -1
  277. package/dist/root-remove.d.ts.map +1 -1
  278. package/dist/root-remove.js +172 -10
  279. package/dist/root-walk.d.ts.map +1 -1
  280. package/dist/root-walk.js +2 -1
  281. package/dist/root-write-admission.d.ts +68 -0
  282. package/dist/root-write-admission.d.ts.map +1 -0
  283. package/dist/root-write-admission.js +322 -0
  284. package/dist/root-write-compatibility.d.ts +13 -0
  285. package/dist/root-write-compatibility.d.ts.map +1 -0
  286. package/dist/root-write-compatibility.js +74 -0
  287. package/dist/root-write-complete-parent.d.ts +42 -0
  288. package/dist/root-write-complete-parent.d.ts.map +1 -0
  289. package/dist/root-write-complete-parent.js +195 -0
  290. package/dist/root-write-mode.d.ts +2 -0
  291. package/dist/root-write-mode.d.ts.map +1 -1
  292. package/dist/root-write-mode.js +20 -7
  293. package/dist/root-write-publication.d.ts +24 -0
  294. package/dist/root-write-publication.d.ts.map +1 -0
  295. package/dist/root-write-publication.js +85 -0
  296. package/dist/root-write-verification.d.ts.map +1 -1
  297. package/dist/root-write-verification.js +18 -7
  298. package/dist/safe-path-segment.d.ts.map +1 -1
  299. package/dist/safe-path-segment.js +3 -1
  300. package/dist/secret-file.d.ts.map +1 -1
  301. package/dist/secret-file.js +62 -24
  302. package/dist/secret-read-async.d.ts.map +1 -1
  303. package/dist/secret-read-async.js +18 -13
  304. package/dist/secret-read-policy.d.ts.map +1 -1
  305. package/dist/secret-read-policy.js +5 -1
  306. package/dist/secure-file-windows.d.ts +10 -0
  307. package/dist/secure-file-windows.d.ts.map +1 -0
  308. package/dist/secure-file-windows.js +186 -0
  309. package/dist/secure-file.d.ts.map +1 -1
  310. package/dist/secure-file.js +98 -10
  311. package/dist/secure-temp-dir.d.ts +6 -3
  312. package/dist/secure-temp-dir.d.ts.map +1 -1
  313. package/dist/secure-temp-dir.js +121 -101
  314. package/dist/secure-temp-repair.d.ts +35 -0
  315. package/dist/secure-temp-repair.d.ts.map +1 -0
  316. package/dist/secure-temp-repair.js +106 -0
  317. package/dist/sibling-staged-file.d.ts +3 -1
  318. package/dist/sibling-staged-file.d.ts.map +1 -1
  319. package/dist/sibling-staged-file.js +181 -50
  320. package/dist/sibling-temp.d.ts.map +1 -1
  321. package/dist/sibling-temp.js +27 -12
  322. package/dist/sidecar-lock-acquire.d.ts.map +1 -1
  323. package/dist/sidecar-lock-acquire.js +45 -15
  324. package/dist/sidecar-lock-root.d.ts.map +1 -1
  325. package/dist/sidecar-lock-root.js +4 -2
  326. package/dist/sidecar-lock.d.ts.map +1 -1
  327. package/dist/sidecar-lock.js +2 -3
  328. package/dist/staged-directory.d.ts +14 -5
  329. package/dist/staged-directory.d.ts.map +1 -1
  330. package/dist/staged-directory.js +54 -3
  331. package/dist/standalone-publication-path.d.ts +2 -0
  332. package/dist/standalone-publication-path.d.ts.map +1 -0
  333. package/dist/standalone-publication-path.js +6 -0
  334. package/dist/stat-observation.d.ts +11 -0
  335. package/dist/stat-observation.d.ts.map +1 -0
  336. package/dist/stat-observation.js +64 -0
  337. package/dist/strict-file-identity.d.ts.map +1 -1
  338. package/dist/strict-file-identity.js +39 -2
  339. package/dist/symlink-parents.d.ts.map +1 -1
  340. package/dist/symlink-parents.js +7 -2
  341. package/dist/temp-target.d.ts +2 -0
  342. package/dist/temp-target.d.ts.map +1 -1
  343. package/dist/temp-target.js +133 -4
  344. package/dist/temp-workspace-admission.d.ts +22 -0
  345. package/dist/temp-workspace-admission.d.ts.map +1 -0
  346. package/dist/temp-workspace-admission.js +374 -0
  347. package/dist/temp-workspace-child-admission.d.ts +13 -0
  348. package/dist/temp-workspace-child-admission.d.ts.map +1 -0
  349. package/dist/temp-workspace-child-admission.js +95 -0
  350. package/dist/temp-workspace-descriptor.d.ts +48 -0
  351. package/dist/temp-workspace-descriptor.d.ts.map +1 -0
  352. package/dist/temp-workspace-descriptor.js +363 -0
  353. package/dist/temp-workspace-identity.d.ts +15 -0
  354. package/dist/temp-workspace-identity.d.ts.map +1 -0
  355. package/dist/temp-workspace-identity.js +41 -0
  356. package/dist/temp-workspace-owner.d.ts +7 -6
  357. package/dist/temp-workspace-owner.d.ts.map +1 -1
  358. package/dist/temp-workspace-owner.js +121 -61
  359. package/dist/temp-workspace-permissions.d.ts +4 -0
  360. package/dist/temp-workspace-permissions.d.ts.map +1 -0
  361. package/dist/temp-workspace-permissions.js +32 -0
  362. package/dist/temp-workspace-types.d.ts +40 -0
  363. package/dist/temp-workspace-types.d.ts.map +1 -0
  364. package/dist/temp-workspace-types.js +1 -0
  365. package/dist/temp.d.ts +1 -1
  366. package/dist/temp.d.ts.map +1 -1
  367. package/dist/temp.js +1 -1
  368. package/dist/test-hooks.d.ts +7 -0
  369. package/dist/test-hooks.d.ts.map +1 -1
  370. package/dist/text-atomic.d.ts.map +1 -1
  371. package/dist/text-atomic.js +3 -1
  372. package/dist/trash.d.ts.map +1 -1
  373. package/dist/trash.js +54 -8
  374. package/dist/walk.d.ts.map +1 -1
  375. package/dist/walk.js +20 -16
  376. package/dist/windows-owner.d.ts.map +1 -1
  377. package/dist/windows-owner.js +5 -0
  378. package/dist/windows-path-alias.d.ts +39 -0
  379. package/dist/windows-path-alias.d.ts.map +1 -0
  380. package/dist/windows-path-alias.js +153 -0
  381. package/docs/advanced.md +28 -1
  382. package/docs/archive.md +29 -2
  383. package/docs/atomic.md +27 -3
  384. package/docs/contributing.md +4 -1
  385. package/docs/copy.md +4 -1
  386. package/docs/durability.md +18 -2
  387. package/docs/errors.md +14 -6
  388. package/docs/file-store.md +30 -3
  389. package/docs/filename.md +21 -7
  390. package/docs/guest.md +5 -0
  391. package/docs/install-path.md +61 -15
  392. package/docs/install.md +12 -8
  393. package/docs/json-store.md +5 -1
  394. package/docs/json.md +11 -0
  395. package/docs/mutation-policy-proof.md +65 -0
  396. package/docs/native-helper.md +28 -9
  397. package/docs/native.md +46 -10
  398. package/docs/output.md +33 -11
  399. package/docs/path-prefix.md +64 -0
  400. package/docs/path-suffix-aliases.md +159 -0
  401. package/docs/path.md +12 -1
  402. package/docs/permissions.md +26 -1
  403. package/docs/private-file-store.md +14 -0
  404. package/docs/public-api.md +14 -0
  405. package/docs/quickstart.md +1 -1
  406. package/docs/reading.md +8 -1
  407. package/docs/root.md +21 -4
  408. package/docs/secret-file.md +3 -0
  409. package/docs/secure-file.md +21 -16
  410. package/docs/security-model.md +76 -9
  411. package/docs/sidecar-lock.md +28 -1
  412. package/docs/store.md +27 -2
  413. package/docs/temp.md +262 -34
  414. package/docs/test-hooks.md +14 -0
  415. package/docs/writing.md +38 -8
  416. package/package.json +10 -10
@@ -11,6 +11,7 @@ import { resolveReadOpenFlags } from "./read-open-flags.js";
11
11
  import { assertNoSymlinkParents, assertNoSymlinkParentsSync } from "./symlink-parents.js";
12
12
  import { getFsSafeTestHooks } from "./test-hooks.js";
13
13
  import { isNonRegularWriteOpenError, isNonRegularWriteOpenErrorSync, resolveNonblockingWriteFlag, } from "./write-open-flags.js";
14
+ import { assertNoWindowsPathAlias, resolvePathPreservingWindowsRoot, } from "./windows-path-alias.js";
14
15
  export function resolveRegularFileAppendFlags(constants = fsSync.constants) {
15
16
  const noFollow = constants.O_NOFOLLOW;
16
17
  return (constants.O_CREAT |
@@ -29,6 +30,7 @@ function translateBoundedReadOverflow(error, filePath, maxBytes) {
29
30
  throw error;
30
31
  }
31
32
  export async function statRegularFile(filePath) {
33
+ assertNoWindowsPathAlias(filePath, "filesystem", "file path uses a Windows filesystem namespace alias");
32
34
  let stat;
33
35
  try {
34
36
  stat = fsSync.lstatSync(filePath);
@@ -45,6 +47,7 @@ export async function statRegularFile(filePath) {
45
47
  return { missing: false, stat };
46
48
  }
47
49
  export function statRegularFileSync(filePath) {
50
+ assertNoWindowsPathAlias(filePath, "filesystem", "file path uses a Windows filesystem namespace alias");
48
51
  let stat;
49
52
  try {
50
53
  stat = fsSync.lstatSync(filePath);
@@ -62,22 +65,24 @@ export function statRegularFileSync(filePath) {
62
65
  }
63
66
  export async function readRegularFile(params) {
64
67
  const maxBytes = normalizeMaxBytes(params.maxBytes);
65
- assertNoUnsafeDeviceReadPath(params.filePath);
68
+ const filePath = params.filePath;
69
+ assertNoWindowsPathAlias(filePath, "filesystem", "file path uses a Windows filesystem namespace alias");
70
+ assertNoUnsafeDeviceReadPath(filePath);
66
71
  const before = await inspectFileIdentity(async () => {
67
- const stat = fsSync.lstatSync(params.filePath, { bigint: true });
68
- assertRegularReadStat(stat, params.filePath, true);
72
+ const stat = fsSync.lstatSync(filePath, { bigint: true });
73
+ assertRegularReadStat(stat, filePath, true);
69
74
  return stat;
70
- }).catch((error) => throwReadPreviewError(error, params.filePath));
75
+ }).catch((error) => throwReadPreviewError(error, filePath));
71
76
  if (maxBytes !== undefined && before.size > maxBytes) {
72
- throw regularFileTooLargeError(params.filePath, maxBytes);
77
+ throw regularFileTooLargeError(filePath, maxBytes);
73
78
  }
74
79
  let handle;
75
80
  try {
76
- handle = await fs.open(params.filePath, resolveReadOpenFlags());
81
+ handle = await fs.open(filePath, resolveReadOpenFlags());
77
82
  }
78
83
  catch (err) {
79
84
  if (isNotFoundPathError(err)) {
80
- throw new FsSafeError("path-mismatch", `File changed during read: ${params.filePath}`);
85
+ throw new FsSafeError("path-mismatch", `File changed during read: ${filePath}`);
81
86
  }
82
87
  throw err;
83
88
  }
@@ -85,24 +90,24 @@ export async function readRegularFile(params) {
85
90
  const stat = fsSync.fstatSync(handle.fd);
86
91
  const identity = await inspectFileIdentity(async () => {
87
92
  const exact = fsSync.fstatSync(handle.fd, { bigint: true });
88
- assertRegularReadStat(exact, params.filePath);
93
+ assertRegularReadStat(exact, filePath);
89
94
  return exact;
90
95
  }, before);
91
96
  try {
92
97
  await inspectFileIdentity(async () => {
93
- const current = fsSync.lstatSync(params.filePath, { bigint: true });
94
- assertRegularReadStat(current, params.filePath);
98
+ const current = fsSync.lstatSync(filePath, { bigint: true });
99
+ assertRegularReadStat(current, filePath);
95
100
  return current;
96
101
  }, identity);
97
102
  }
98
103
  catch (err) {
99
104
  if (isNotFoundPathError(err)) {
100
- throw new FsSafeError("path-mismatch", `File changed during read: ${params.filePath}`);
105
+ throw new FsSafeError("path-mismatch", `File changed during read: ${filePath}`);
101
106
  }
102
107
  throw err;
103
108
  }
104
109
  if (maxBytes !== undefined && stat.size > maxBytes) {
105
- throw regularFileTooLargeError(params.filePath, maxBytes);
110
+ throw regularFileTooLargeError(filePath, maxBytes);
106
111
  }
107
112
  // With a byte cap, avoid readFile(): a raced file growth would allocate
108
113
  // the oversized content before the post-read check could reject it.
@@ -115,7 +120,7 @@ export async function readRegularFile(params) {
115
120
  }
116
121
  catch (error) {
117
122
  if (maxBytes !== undefined) {
118
- translateBoundedReadOverflow(error, params.filePath, maxBytes);
123
+ translateBoundedReadOverflow(error, filePath, maxBytes);
119
124
  }
120
125
  throw error;
121
126
  }
@@ -178,35 +183,37 @@ function readOpenedRegularFileSync(params) {
178
183
  }
179
184
  export function readRegularFileSync(params) {
180
185
  const maxBytes = normalizeMaxBytes(params.maxBytes);
181
- assertNoUnsafeDeviceReadPath(params.filePath);
186
+ const filePath = params.filePath;
187
+ assertNoWindowsPathAlias(filePath, "filesystem", "file path uses a Windows filesystem namespace alias");
188
+ assertNoUnsafeDeviceReadPath(filePath);
182
189
  let before;
183
190
  try {
184
191
  before = inspectFileIdentitySync(() => {
185
- const stat = fsSync.lstatSync(params.filePath, { bigint: true });
186
- assertRegularReadStat(stat, params.filePath, true);
192
+ const stat = fsSync.lstatSync(filePath, { bigint: true });
193
+ assertRegularReadStat(stat, filePath, true);
187
194
  return stat;
188
195
  });
189
196
  }
190
197
  catch (error) {
191
- throwReadPreviewError(error, params.filePath);
198
+ throwReadPreviewError(error, filePath);
192
199
  }
193
200
  if (maxBytes !== undefined && before.size > maxBytes) {
194
- throw regularFileTooLargeError(params.filePath, maxBytes);
201
+ throw regularFileTooLargeError(filePath, maxBytes);
195
202
  }
196
203
  let fd;
197
204
  try {
198
- fd = fsSync.openSync(params.filePath, resolveReadOpenFlags());
205
+ fd = fsSync.openSync(filePath, resolveReadOpenFlags());
199
206
  }
200
207
  catch (error) {
201
208
  if (isNotFoundPathError(error)) {
202
- throw new FsSafeError("path-mismatch", `File changed during read: ${params.filePath}`);
209
+ throw new FsSafeError("path-mismatch", `File changed during read: ${filePath}`);
203
210
  }
204
211
  throw error;
205
212
  }
206
213
  try {
207
214
  return readOpenedRegularFileSync({
208
215
  fd,
209
- filePath: params.filePath,
216
+ filePath,
210
217
  preOpenStat: before,
211
218
  maxBytes,
212
219
  });
@@ -231,8 +238,10 @@ function throwAppendIdentityError(error, filePath) {
231
238
  throw error;
232
239
  }
233
240
  export async function appendRegularFile(options) {
241
+ const filePath = options.filePath;
242
+ assertNoWindowsPathAlias(filePath, "filesystem", "file path uses a Windows filesystem namespace alias");
234
243
  if (options.rejectSymlinkParents === true) {
235
- const resolvedDir = path.resolve(path.dirname(options.filePath));
244
+ const resolvedDir = resolvePathPreservingWindowsRoot(path.dirname(filePath));
236
245
  await assertNoSymlinkParents({
237
246
  rootDir: path.parse(resolvedDir).root,
238
247
  targetPath: resolvedDir,
@@ -245,12 +254,12 @@ export async function appendRegularFile(options) {
245
254
  let preOpenStat;
246
255
  try {
247
256
  preOpenStat = await inspectFileIdentity(async () => {
248
- const stat = fsSync.lstatSync(options.filePath, { bigint: true });
257
+ const stat = fsSync.lstatSync(filePath, { bigint: true });
249
258
  if (stat.isSymbolicLink()) {
250
- throw new Error(`Refusing to append through symlink: ${options.filePath}`);
259
+ throw new Error(`Refusing to append through symlink: ${filePath}`);
251
260
  }
252
261
  if (!stat.isFile()) {
253
- throw new Error(`Refusing to append to non-file: ${options.filePath}`);
262
+ throw new Error(`Refusing to append to non-file: ${filePath}`);
254
263
  }
255
264
  return stat;
256
265
  });
@@ -266,15 +275,15 @@ export async function appendRegularFile(options) {
266
275
  Number(preOpenStat?.size ?? 0n) + contentBytes > options.maxFileBytes) {
267
276
  return;
268
277
  }
269
- await getFsSafeTestHooks()?.beforeRegularFileAppendOpen?.(options.filePath);
278
+ await getFsSafeTestHooks()?.beforeRegularFileAppendOpen?.(filePath);
270
279
  const flags = resolveRegularFileAppendFlags();
271
280
  let handle;
272
281
  try {
273
- handle = await fs.open(options.filePath, flags, options.mode ?? 0o600);
282
+ handle = await fs.open(filePath, flags, options.mode ?? 0o600);
274
283
  }
275
284
  catch (error) {
276
- if (await isNonRegularWriteOpenError(error, options.filePath, flags)) {
277
- throw new Error(`Refusing to append to non-file: ${options.filePath}`);
285
+ if (await isNonRegularWriteOpenError(error, filePath, flags)) {
286
+ throw new Error(`Refusing to append to non-file: ${filePath}`);
278
287
  }
279
288
  throw error;
280
289
  }
@@ -283,17 +292,17 @@ export async function appendRegularFile(options) {
283
292
  try {
284
293
  identity = await inspectFileIdentity(async () => {
285
294
  const stat = fsSync.fstatSync(handle.fd, { bigint: true });
286
- assertRegularAppendStat(stat, options.filePath);
295
+ assertRegularAppendStat(stat, filePath);
287
296
  return stat;
288
297
  }, preOpenStat);
289
298
  await inspectFileIdentity(async () => {
290
- const current = fsSync.lstatSync(options.filePath, { bigint: true });
291
- assertRegularAppendStat(current, options.filePath);
299
+ const current = fsSync.lstatSync(filePath, { bigint: true });
300
+ assertRegularAppendStat(current, filePath);
292
301
  return current;
293
302
  }, identity);
294
303
  }
295
304
  catch (error) {
296
- throwAppendIdentityError(error, options.filePath);
305
+ throwAppendIdentityError(error, filePath);
297
306
  }
298
307
  if (options.maxFileBytes !== undefined &&
299
308
  Number(identity.size) + contentBytes > options.maxFileBytes) {
@@ -311,8 +320,10 @@ export async function appendRegularFile(options) {
311
320
  }
312
321
  }
313
322
  export function appendRegularFileSync(options) {
323
+ const filePath = options.filePath;
324
+ assertNoWindowsPathAlias(filePath, "filesystem", "file path uses a Windows filesystem namespace alias");
314
325
  if (options.rejectSymlinkParents === true) {
315
- const resolvedDir = path.resolve(path.dirname(options.filePath));
326
+ const resolvedDir = resolvePathPreservingWindowsRoot(path.dirname(filePath));
316
327
  assertNoSymlinkParentsSync({
317
328
  rootDir: path.parse(resolvedDir).root,
318
329
  targetPath: resolvedDir,
@@ -325,12 +336,12 @@ export function appendRegularFileSync(options) {
325
336
  let preOpenStat;
326
337
  try {
327
338
  preOpenStat = inspectFileIdentitySync(() => {
328
- const stat = fsSync.lstatSync(options.filePath, { bigint: true });
339
+ const stat = fsSync.lstatSync(filePath, { bigint: true });
329
340
  if (stat.isSymbolicLink()) {
330
- throw new Error(`Refusing to append through symlink: ${options.filePath}`);
341
+ throw new Error(`Refusing to append through symlink: ${filePath}`);
331
342
  }
332
343
  if (!stat.isFile()) {
333
- throw new Error(`Refusing to append to non-file: ${options.filePath}`);
344
+ throw new Error(`Refusing to append to non-file: ${filePath}`);
334
345
  }
335
346
  return stat;
336
347
  });
@@ -346,15 +357,15 @@ export function appendRegularFileSync(options) {
346
357
  Number(preOpenStat?.size ?? 0n) + contentBuffer.byteLength > options.maxFileBytes) {
347
358
  return;
348
359
  }
349
- getFsSafeTestHooks()?.beforeRegularFileAppendOpenSync?.(options.filePath);
360
+ getFsSafeTestHooks()?.beforeRegularFileAppendOpenSync?.(filePath);
350
361
  const flags = resolveRegularFileAppendFlags();
351
362
  let fd;
352
363
  try {
353
- fd = fsSync.openSync(options.filePath, flags, options.mode ?? 0o600);
364
+ fd = fsSync.openSync(filePath, flags, options.mode ?? 0o600);
354
365
  }
355
366
  catch (error) {
356
- if (isNonRegularWriteOpenErrorSync(error, options.filePath, flags)) {
357
- throw new Error(`Refusing to append to non-file: ${options.filePath}`);
367
+ if (isNonRegularWriteOpenErrorSync(error, filePath, flags)) {
368
+ throw new Error(`Refusing to append to non-file: ${filePath}`);
358
369
  }
359
370
  throw error;
360
371
  }
@@ -363,17 +374,17 @@ export function appendRegularFileSync(options) {
363
374
  try {
364
375
  identity = inspectFileIdentitySync(() => {
365
376
  const stat = fsSync.fstatSync(fd, { bigint: true });
366
- assertRegularAppendStat(stat, options.filePath);
377
+ assertRegularAppendStat(stat, filePath);
367
378
  return stat;
368
379
  }, preOpenStat);
369
380
  inspectFileIdentitySync(() => {
370
- const current = fsSync.lstatSync(options.filePath, { bigint: true });
371
- assertRegularAppendStat(current, options.filePath);
381
+ const current = fsSync.lstatSync(filePath, { bigint: true });
382
+ assertRegularAppendStat(current, filePath);
372
383
  return current;
373
384
  }, identity);
374
385
  }
375
386
  catch (error) {
376
- throwAppendIdentityError(error, options.filePath);
387
+ throwAppendIdentityError(error, filePath);
377
388
  }
378
389
  if (options.maxFileBytes !== undefined &&
379
390
  Number(identity.size) + contentBuffer.byteLength > options.maxFileBytes) {
@@ -1 +1 @@
1
- {"version":3,"file":"replace-directory.d.ts","sourceRoot":"","sources":["../src/replace-directory.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,6BAA6B,GAAG;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,IAAI,CAAC,CAKf"}
1
+ {"version":3,"file":"replace-directory.d.ts","sourceRoot":"","sources":["../src/replace-directory.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,6BAA6B,GAAG;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,IAAI,CAAC,CAiBf"}
@@ -4,17 +4,24 @@ import path from "node:path";
4
4
  import { guardedRename, guardedRm } from "./guarded-mutation.js";
5
5
  import { recursiveMkdirPath } from "./recursive-mkdir-path.js";
6
6
  import { assertSafePathPrefix } from "./safe-path-segment.js";
7
+ import { admitStandalonePublicationPath } from "./standalone-publication-path.js";
7
8
  import { serializePathWrite } from "./write-queue.js";
9
+ import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
8
10
  export async function replaceDirectoryAtomic(options) {
9
- const targetDir = path.resolve(options.targetDir);
11
+ const stagedDirInput = admitStandalonePublicationPath(options.stagedDir, "staged directory uses a Windows filesystem namespace alias");
12
+ const targetDirInput = admitStandalonePublicationPath(options.targetDir, "target directory uses a Windows filesystem namespace alias");
13
+ const stagedDir = path.resolve(stagedDirInput);
14
+ const targetDir = path.resolve(targetDirInput);
15
+ assertNoWindowsPathAlias(stagedDir, "filesystem", "staged directory uses a Windows filesystem namespace alias");
16
+ assertNoWindowsPathAlias(targetDir, "filesystem", "target directory uses a Windows filesystem namespace alias");
17
+ const backupPrefixInput = options.backupPrefix;
10
18
  await serializePathWrite(targetDir, async () => {
11
- await replaceDirectoryAtomicUnserialized(options, targetDir);
19
+ await replaceDirectoryAtomicUnserialized(stagedDir, targetDir, backupPrefixInput);
12
20
  });
13
21
  }
14
- async function replaceDirectoryAtomicUnserialized(options, targetDir) {
15
- const stagedDir = path.resolve(options.stagedDir);
22
+ async function replaceDirectoryAtomicUnserialized(stagedDir, targetDir, backupPrefixInput) {
16
23
  const parentDir = path.dirname(targetDir);
17
- const backupPrefix = assertSafePathPrefix(options.backupPrefix ?? ".fs-safe-dir-backup-", { label: "atomic directory backup prefix" });
24
+ const backupPrefix = assertSafePathPrefix(backupPrefixInput ?? ".fs-safe-dir-backup-", { label: "atomic directory backup prefix" });
18
25
  const backupDir = path.join(parentDir, `${backupPrefix}${process.pid}-${randomUUID()}`);
19
26
  let backupCreated = false;
20
27
  await fs.mkdir(recursiveMkdirPath(parentDir), { recursive: true });
@@ -3,6 +3,7 @@ import fs, { type FileHandle } from "node:fs/promises";
3
3
  import { type AnyAsyncDirectoryGuard } from "./directory-guard.js";
4
4
  type AsyncOwnerFileSystem = Pick<typeof fs, "lstat" | "open" | "unlink">;
5
5
  type SyncOwnerFileSystem = Pick<typeof syncFs, "closeSync" | "fstatSync" | "lstatSync" | "openSync" | "readFileSync" | "unlinkSync">;
6
+ export declare function removePathIfIdentityUnchanged(targetPath: string, identity: Pick<BigIntStats, "dev" | "ino">): Promise<void>;
6
7
  export declare function cleanupPinnedFilePath(params: {
7
8
  pathname: string;
8
9
  handle: FileHandle;
@@ -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;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,CAkDN;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,CAkCP;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;AAEvD,OAAO,EAAwD,KAAK,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAQzH,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;AAIF,wBAAsB,6BAA6B,CACjD,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,KAAK,CAAC,GACzC,OAAO,CAAC,IAAI,CAAC,CAOf;AA8DD,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,CAkDN;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,CAkCP;CACF"}
@@ -1,12 +1,23 @@
1
1
  import syncFs, {} from "node:fs";
2
2
  import fs, {} from "node:fs/promises";
3
- import { assertAsyncDirectoryGuard } from "./directory-guard.js";
3
+ import path from "node:path";
4
+ import { assertAsyncDirectoryGuard, createAsyncDirectoryGuard } from "./directory-guard.js";
4
5
  import { resolveReadOpenFlags } from "./read-open-flags.js";
5
6
  import { FsSafeError } from "./errors.js";
6
7
  import { sameFileIdentityForCleanup, sha256Hex } from "./file-identity.js";
8
+ import { withAsyncDirectoryGuards } from "./guarded-mutation.js";
7
9
  import { inspectFileIdentity, inspectFileIdentitySync } from "./strict-file-identity.js";
8
10
  import { registerTempPathForExit } from "./temp-cleanup.js";
9
11
  const PUBLISHED_READ_FLAGS = resolveReadOpenFlags();
12
+ export async function removePathIfIdentityUnchanged(targetPath, identity) {
13
+ const parentGuard = await createAsyncDirectoryGuard(path.dirname(targetPath), { bigint: true });
14
+ await withAsyncDirectoryGuards([parentGuard], async () => {
15
+ const current = syncFs.lstatSync(targetPath, { bigint: true });
16
+ if (current.isSymbolicLink() || !current.isFile() || !sameFileIdentityForCleanup(current, identity))
17
+ return;
18
+ await fs.unlink(targetPath);
19
+ });
20
+ }
10
21
  function assertOwnedFile(stat, pathname, pathnameEntry) {
11
22
  if (stat.isSymbolicLink()) {
12
23
  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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"}
@@ -9,6 +9,7 @@ import { inheritedRegularFileMode } from "./replace-file-mode.js";
9
9
  import { atomicExpectedContentHash, validateRenameIdentity, withAtomicRenameIdentityLock, withAtomicRenameIdentityLockSync, } from "./replace-file-rename-policy.js";
10
10
  import { AsyncAtomicTempOwner, SyncAtomicTempOwner } from "./replace-file-temp-owner.js";
11
11
  import { assertSafePathPrefix } from "./safe-path-segment.js";
12
+ import { admitStandalonePublicationPath } from "./standalone-publication-path.js";
12
13
  import { sleep, sleepSync } from "./timing.js";
13
14
  import { serializePathWrite } from "./write-queue.js";
14
15
  function isRetryableRenameError(error) {
@@ -85,6 +86,7 @@ function validateReplaceFilePath(filePath) {
85
86
  if (!filePath || filePath.includes("\0")) {
86
87
  throw new Error("Atomic replace file path must be non-empty.");
87
88
  }
89
+ return admitStandalonePublicationPath(filePath, "atomic replace path uses a Windows filesystem namespace alias");
88
90
  }
89
91
  function validateRestoreOptions(options) {
90
92
  if (options.copyFallbackRestore !== "restore-original")
@@ -101,7 +103,7 @@ function buildReplaceTempPath(filePath, tempPrefix) {
101
103
  const safePrefix = assertSafePathPrefix(tempPrefix ?? ".fs-safe-replace", { label: "atomic replace temp prefix" });
102
104
  return path.join(dir, `${safePrefix}.${process.pid}.${randomUUID()}.tmp`);
103
105
  }
104
- async function resolveMode(options) {
106
+ async function resolveMode(options, filePath) {
105
107
  const defaultMode = options.mode ?? 0o600;
106
108
  if (!options.preserveExistingMode) {
107
109
  return defaultMode;
@@ -109,7 +111,7 @@ async function resolveMode(options) {
109
111
  const fsModule = options.fileSystem?.promises ?? fs;
110
112
  let stat;
111
113
  try {
112
- stat = fsModule === fs ? syncFs.lstatSync(options.filePath) : await fsModule.lstat(options.filePath);
114
+ stat = fsModule === fs ? syncFs.lstatSync(filePath) : await fsModule.lstat(filePath);
113
115
  }
114
116
  catch (error) {
115
117
  if (error.code === "ENOENT") {
@@ -119,7 +121,7 @@ async function resolveMode(options) {
119
121
  }
120
122
  return stat ? inheritedRegularFileMode(stat) : defaultMode;
121
123
  }
122
- function resolveModeSync(options) {
124
+ function resolveModeSync(options, filePath) {
123
125
  const defaultMode = options.mode ?? 0o600;
124
126
  if (!options.preserveExistingMode) {
125
127
  return defaultMode;
@@ -127,7 +129,7 @@ function resolveModeSync(options) {
127
129
  const fsModule = options.fileSystem ?? syncFs;
128
130
  let stat;
129
131
  try {
130
- stat = fsModule.lstatSync(options.filePath);
132
+ stat = fsModule.lstatSync(filePath);
131
133
  }
132
134
  catch (error) {
133
135
  if (error.code !== "ENOENT") {
@@ -144,13 +146,13 @@ export async function replaceFileAtomic(options) {
144
146
  }
145
147
  // Internal owner hook: keep directory durability inside publication verification and serialization.
146
148
  export async function replaceFileAtomicWithDirectorySync(options, syncParent) {
147
- const filePath = options.filePath;
148
- validateReplaceFilePath(filePath);
149
+ const filePath = validateReplaceFilePath(options.filePath);
149
150
  validateRestoreOptions(options);
150
- validateRenameIdentity(options.renameIdentity);
151
+ const renameIdentity = options.renameIdentity;
152
+ validateRenameIdentity(renameIdentity);
151
153
  return await serializePathWrite(path.resolve(filePath), async () => {
152
- if (options.renameIdentity !== "verify-content-with-lock") {
153
- return await replaceFileAtomicUnserialized(options, syncParent);
154
+ if (renameIdentity !== "verify-content-with-lock") {
155
+ return await replaceFileAtomicUnserialized(options, filePath, renameIdentity, syncParent);
154
156
  }
155
157
  const fsModule = options.fileSystem?.promises ?? fs;
156
158
  const dir = path.dirname(filePath);
@@ -158,16 +160,15 @@ export async function replaceFileAtomicWithDirectorySync(options, syncParent) {
158
160
  recursive: true,
159
161
  mode: options.dirMode ?? 0o700,
160
162
  });
161
- return await withAtomicRenameIdentityLock(filePath, async () => await replaceFileAtomicUnserialized(options, syncParent));
163
+ return await withAtomicRenameIdentityLock(filePath, async () => await replaceFileAtomicUnserialized(options, filePath, renameIdentity, syncParent));
162
164
  });
163
165
  }
164
- async function replaceFileAtomicUnserialized(options, syncParent) {
165
- const filePath = options.filePath;
166
+ async function replaceFileAtomicUnserialized(options, filePath, renameIdentity, syncParent) {
166
167
  const fsModule = options.fileSystem?.promises ?? fs;
167
168
  const dir = path.dirname(filePath);
168
169
  const dirMode = options.dirMode ?? 0o700;
169
- const mode = await resolveMode(options);
170
- const expectedHash = atomicExpectedContentHash(options.renameIdentity, options.content);
170
+ const mode = await resolveMode(options, filePath);
171
+ const expectedHash = atomicExpectedContentHash(renameIdentity, options.content);
171
172
  const tempPath = buildReplaceTempPath(filePath, options.tempPrefix);
172
173
  const tempOwner = new AsyncAtomicTempOwner(tempPath);
173
174
  let originalError;
@@ -240,12 +241,12 @@ async function replaceFileAtomicUnserialized(options, syncParent) {
240
241
  }
241
242
  }
242
243
  export function replaceFileAtomicSync(options) {
243
- const filePath = options.filePath;
244
- validateReplaceFilePath(filePath);
244
+ const filePath = validateReplaceFilePath(options.filePath);
245
245
  validateRestoreOptions(options);
246
- validateRenameIdentity(options.renameIdentity);
247
- if (options.renameIdentity !== "verify-content-with-lock") {
248
- return replaceFileAtomicSyncUnserialized(options);
246
+ const renameIdentity = options.renameIdentity;
247
+ validateRenameIdentity(renameIdentity);
248
+ if (renameIdentity !== "verify-content-with-lock") {
249
+ return replaceFileAtomicSyncUnserialized(options, filePath, renameIdentity);
249
250
  }
250
251
  const fsModule = options.fileSystem ?? syncFs;
251
252
  const dir = path.dirname(filePath);
@@ -253,15 +254,14 @@ export function replaceFileAtomicSync(options) {
253
254
  recursive: true,
254
255
  mode: options.dirMode ?? 0o700,
255
256
  });
256
- return withAtomicRenameIdentityLockSync(filePath, () => replaceFileAtomicSyncUnserialized(options));
257
+ return withAtomicRenameIdentityLockSync(filePath, () => replaceFileAtomicSyncUnserialized(options, filePath, renameIdentity));
257
258
  }
258
- function replaceFileAtomicSyncUnserialized(options) {
259
- const filePath = options.filePath;
259
+ function replaceFileAtomicSyncUnserialized(options, filePath, renameIdentity) {
260
260
  const fsModule = options.fileSystem ?? syncFs;
261
261
  const dir = path.dirname(filePath);
262
262
  const dirMode = options.dirMode ?? 0o700;
263
- const mode = resolveModeSync(options);
264
- const expectedHash = atomicExpectedContentHash(options.renameIdentity, options.content);
263
+ const mode = resolveModeSync(options, filePath);
264
+ const expectedHash = atomicExpectedContentHash(renameIdentity, options.content);
265
265
  const fchmodSync = options.fileSystem?.fchmodSync ?? (options.fileSystem === undefined ? syncFs.fchmodSync : undefined);
266
266
  if (!fchmodSync &&
267
267
  (options.mode !== undefined ||
@@ -0,0 +1,29 @@
1
+ export type RootBoundaryIdentity = Readonly<{
2
+ dev: number | bigint;
3
+ ino: number | bigint;
4
+ }>;
5
+ export type AdmittedRootPath = Readonly<{
6
+ path: string;
7
+ relativePath: string;
8
+ admission: "exact" | "identity";
9
+ }>;
10
+ /**
11
+ * Admit a path at a trusted directory boundary.
12
+ *
13
+ * On Windows, an exact structural prefix is allocation-only and performs no
14
+ * filesystem observation. A match which depends on case folding is accepted
15
+ * only when the candidate prefix names the exact trusted root object. Accepted
16
+ * paths are always returned under the trusted root spelling.
17
+ */
18
+ export declare function admitPathInsideRoot(params: {
19
+ rootPath: string;
20
+ candidatePath: string;
21
+ rootIdentity?: RootBoundaryIdentity;
22
+ resolveCandidateRoot?: boolean;
23
+ identityCache?: Map<string, boolean>;
24
+ inspectCandidateRoot?: (candidateRootPath: string, expected: Readonly<{
25
+ dev: bigint;
26
+ ino: bigint;
27
+ }>) => void;
28
+ }): AdmittedRootPath | undefined;
29
+ //# sourceMappingURL=root-boundary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root-boundary.d.ts","sourceRoot":"","sources":["../src/root-boundary.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACtB,CAAC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,OAAO,GAAG,UAAU,CAAC;CACjC,CAAC,CAAC;AAwHH;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,oBAAoB,CAAC;IACpC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,oBAAoB,CAAC,EAAE,CACrB,iBAAiB,EAAE,MAAM,EACzB,QAAQ,EAAE,QAAQ,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,KAC7C,IAAI,CAAC;CACX,GAAG,gBAAgB,GAAG,SAAS,CAiE/B"}