@backblaze-labs/b2-sdk 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +110 -5
- package/README.md +144 -33
- package/dist/_virtual/_b2-sdk-version-json.cjs +4 -0
- package/dist/_virtual/_b2-sdk-version-json.js +4 -0
- package/dist/auth/account-info.d.cts +32 -0
- package/dist/auth/account-info.d.cts.map +1 -1
- package/dist/auth/account-info.d.ts +32 -0
- package/dist/auth/account-info.d.ts.map +1 -1
- package/dist/auth/file.cjs +408 -207
- package/dist/auth/file.cjs.map +1 -1
- package/dist/auth/file.d.cts +77 -3
- package/dist/auth/file.d.cts.map +1 -1
- package/dist/auth/file.d.ts +77 -3
- package/dist/auth/file.d.ts.map +1 -1
- package/dist/auth/file.js +407 -207
- package/dist/auth/file.js.map +1 -1
- package/dist/auth/in-memory.cjs +212 -183
- package/dist/auth/in-memory.cjs.map +1 -1
- package/dist/auth/in-memory.d.cts +8 -0
- package/dist/auth/in-memory.d.cts.map +1 -1
- package/dist/auth/in-memory.d.ts +8 -0
- package/dist/auth/in-memory.d.ts.map +1 -1
- package/dist/auth/in-memory.js +211 -182
- package/dist/auth/in-memory.js.map +1 -1
- package/dist/auth/index.cjs +7 -9
- package/dist/auth/index.d.cts +3 -2
- package/dist/auth/index.d.cts.map +1 -1
- package/dist/auth/index.d.ts +3 -2
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +2 -8
- package/dist/auth/realms.cjs +80 -7
- package/dist/auth/realms.cjs.map +1 -1
- package/dist/auth/realms.d.cts +27 -4
- package/dist/auth/realms.d.cts.map +1 -1
- package/dist/auth/realms.d.ts +27 -4
- package/dist/auth/realms.d.ts.map +1 -1
- package/dist/auth/realms.js +80 -9
- package/dist/auth/realms.js.map +1 -1
- package/dist/auth/upload-url-pool.cjs +55 -51
- package/dist/auth/upload-url-pool.cjs.map +1 -1
- package/dist/auth/upload-url-pool.js +55 -51
- package/dist/auth/upload-url-pool.js.map +1 -1
- package/dist/bucket.cjs +785 -787
- package/dist/bucket.cjs.map +1 -1
- package/dist/bucket.d.cts +35 -47
- package/dist/bucket.d.cts.map +1 -1
- package/dist/bucket.d.ts +35 -47
- package/dist/bucket.d.ts.map +1 -1
- package/dist/bucket.js +780 -782
- package/dist/bucket.js.map +1 -1
- package/dist/client.cjs +246 -228
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +25 -17
- package/dist/client.d.cts.map +1 -1
- package/dist/client.d.ts +25 -17
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +243 -225
- package/dist/client.js.map +1 -1
- package/dist/copy/large.cjs +114 -71
- package/dist/copy/large.cjs.map +1 -1
- package/dist/copy/large.d.cts +6 -0
- package/dist/copy/large.d.cts.map +1 -1
- package/dist/copy/large.d.ts +6 -0
- package/dist/copy/large.d.ts.map +1 -1
- package/dist/copy/large.js +112 -69
- package/dist/copy/large.js.map +1 -1
- package/dist/download/checksum.cjs +89 -0
- package/dist/download/checksum.cjs.map +1 -0
- package/dist/download/checksum.d.cts +40 -0
- package/dist/download/checksum.d.cts.map +1 -0
- package/dist/download/checksum.d.ts +40 -0
- package/dist/download/checksum.d.ts.map +1 -0
- package/dist/download/checksum.js +87 -0
- package/dist/download/checksum.js.map +1 -0
- package/dist/download/parallel.cjs +214 -118
- package/dist/download/parallel.cjs.map +1 -1
- package/dist/download/parallel.d.cts +5 -1
- package/dist/download/parallel.d.cts.map +1 -1
- package/dist/download/parallel.d.ts +5 -1
- package/dist/download/parallel.d.ts.map +1 -1
- package/dist/download/parallel.js +212 -116
- package/dist/download/parallel.js.map +1 -1
- package/dist/download/single.cjs +188 -97
- package/dist/download/single.cjs.map +1 -1
- package/dist/download/single.d.cts +6 -1
- package/dist/download/single.d.cts.map +1 -1
- package/dist/download/single.d.ts +6 -1
- package/dist/download/single.d.ts.map +1 -1
- package/dist/download/single.js +186 -98
- package/dist/download/single.js.map +1 -1
- package/dist/errors/index.cjs +699 -243
- package/dist/errors/index.cjs.map +1 -1
- package/dist/errors/index.d.cts +285 -82
- package/dist/errors/index.d.cts.map +1 -1
- package/dist/errors/index.d.ts +285 -82
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +678 -261
- package/dist/errors/index.js.map +1 -1
- package/dist/http/retry.cjs +45 -28
- package/dist/http/retry.cjs.map +1 -1
- package/dist/http/retry.d.cts +15 -2
- package/dist/http/retry.d.cts.map +1 -1
- package/dist/http/retry.d.ts +15 -2
- package/dist/http/retry.d.ts.map +1 -1
- package/dist/http/retry.js +46 -31
- package/dist/http/retry.js.map +1 -1
- package/dist/http/transport.cjs +438 -140
- package/dist/http/transport.cjs.map +1 -1
- package/dist/http/transport.d.cts +21 -2
- package/dist/http/transport.d.cts.map +1 -1
- package/dist/http/transport.d.ts +21 -2
- package/dist/http/transport.d.ts.map +1 -1
- package/dist/http/transport.js +437 -140
- package/dist/http/transport.js.map +1 -1
- package/dist/http/url-guard.cjs +154 -89
- package/dist/http/url-guard.cjs.map +1 -1
- package/dist/http/url-guard.d.cts +25 -3
- package/dist/http/url-guard.d.cts.map +1 -1
- package/dist/http/url-guard.d.ts +25 -3
- package/dist/http/url-guard.d.ts.map +1 -1
- package/dist/http/url-guard.js +152 -90
- package/dist/http/url-guard.js.map +1 -1
- package/dist/http/user-agent.cjs +84 -44
- package/dist/http/user-agent.cjs.map +1 -1
- package/dist/http/user-agent.js +84 -46
- package/dist/http/user-agent.js.map +1 -1
- package/dist/index.cjs +101 -77
- package/dist/index.d.cts +27 -21
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +27 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -71
- package/dist/internal/b2-naming.cjs +66 -0
- package/dist/internal/b2-naming.cjs.map +1 -0
- package/dist/internal/b2-naming.d.cts +43 -0
- package/dist/internal/b2-naming.d.cts.map +1 -0
- package/dist/internal/b2-naming.d.ts +43 -0
- package/dist/internal/b2-naming.d.ts.map +1 -0
- package/dist/internal/b2-naming.js +60 -0
- package/dist/internal/b2-naming.js.map +1 -0
- package/dist/internal/upload-retry-options.cjs +21 -0
- package/dist/internal/upload-retry-options.cjs.map +1 -0
- package/dist/internal/upload-retry-options.d.cts +12 -0
- package/dist/internal/upload-retry-options.d.cts.map +1 -0
- package/dist/internal/upload-retry-options.d.ts +12 -0
- package/dist/internal/upload-retry-options.d.ts.map +1 -0
- package/dist/internal/upload-retry-options.js +21 -0
- package/dist/internal/upload-retry-options.js.map +1 -0
- package/dist/internal/url-redaction.cjs +31 -0
- package/dist/internal/url-redaction.cjs.map +1 -0
- package/dist/internal/url-redaction.d.cts +17 -0
- package/dist/internal/url-redaction.d.cts.map +1 -0
- package/dist/internal/url-redaction.d.ts +17 -0
- package/dist/internal/url-redaction.d.ts.map +1 -0
- package/dist/internal/url-redaction.js +31 -0
- package/dist/internal/url-redaction.js.map +1 -0
- package/dist/notifications/index.cjs +4 -6
- package/dist/notifications/index.d.cts +1 -1
- package/dist/notifications/index.d.cts.map +1 -1
- package/dist/notifications/index.d.ts +1 -1
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +1 -6
- package/dist/notifications/webhook.cjs +195 -85
- package/dist/notifications/webhook.cjs.map +1 -1
- package/dist/notifications/webhook.d.cts.map +1 -1
- package/dist/notifications/webhook.d.ts.map +1 -1
- package/dist/notifications/webhook.js +195 -87
- package/dist/notifications/webhook.js.map +1 -1
- package/dist/object.cjs +253 -210
- package/dist/object.cjs.map +1 -1
- package/dist/object.d.cts +9 -55
- package/dist/object.d.cts.map +1 -1
- package/dist/object.d.ts +9 -55
- package/dist/object.d.ts.map +1 -1
- package/dist/object.js +249 -206
- package/dist/object.js.map +1 -1
- package/dist/raw/encoding.cjs +74 -35
- package/dist/raw/encoding.cjs.map +1 -1
- package/dist/raw/encoding.js +74 -38
- package/dist/raw/encoding.js.map +1 -1
- package/dist/raw/index.cjs +678 -587
- package/dist/raw/index.cjs.map +1 -1
- package/dist/raw/index.d.cts +121 -18
- package/dist/raw/index.d.cts.map +1 -1
- package/dist/raw/index.d.ts +121 -18
- package/dist/raw/index.d.ts.map +1 -1
- package/dist/raw/index.js +674 -589
- package/dist/raw/index.js.map +1 -1
- package/dist/s3/index.cjs +355 -18
- package/dist/s3/index.cjs.map +1 -1
- package/dist/s3/index.d.cts +233 -5
- package/dist/s3/index.d.cts.map +1 -1
- package/dist/s3/index.d.ts +233 -5
- package/dist/s3/index.d.ts.map +1 -1
- package/dist/s3/index.js +351 -22
- package/dist/s3/index.js.map +1 -1
- package/dist/s3/sigv4.cjs +149 -0
- package/dist/s3/sigv4.cjs.map +1 -0
- package/dist/s3/sigv4.d.cts +43 -0
- package/dist/s3/sigv4.d.cts.map +1 -0
- package/dist/s3/sigv4.d.ts +43 -0
- package/dist/s3/sigv4.d.ts.map +1 -0
- package/dist/s3/sigv4.js +148 -0
- package/dist/s3/sigv4.js.map +1 -0
- package/dist/s3/validation.cjs +69 -0
- package/dist/s3/validation.cjs.map +1 -0
- package/dist/s3/validation.d.cts +43 -0
- package/dist/s3/validation.d.cts.map +1 -0
- package/dist/s3/validation.d.ts +43 -0
- package/dist/s3/validation.d.ts.map +1 -0
- package/dist/s3/validation.js +66 -0
- package/dist/s3/validation.js.map +1 -0
- package/dist/simulator/capabilities.cjs +63 -48
- package/dist/simulator/capabilities.cjs.map +1 -1
- package/dist/simulator/capabilities.js +63 -49
- package/dist/simulator/capabilities.js.map +1 -1
- package/dist/simulator/index.cjs +2124 -1548
- package/dist/simulator/index.cjs.map +1 -1
- package/dist/simulator/index.d.cts +79 -11
- package/dist/simulator/index.d.cts.map +1 -1
- package/dist/simulator/index.d.ts +79 -11
- package/dist/simulator/index.d.ts.map +1 -1
- package/dist/simulator/index.js +2112 -1546
- package/dist/simulator/index.js.map +1 -1
- package/dist/simulator/validation.cjs +191 -153
- package/dist/simulator/validation.cjs.map +1 -1
- package/dist/simulator/validation.d.cts +3 -21
- package/dist/simulator/validation.d.cts.map +1 -1
- package/dist/simulator/validation.d.ts +3 -21
- package/dist/simulator/validation.d.ts.map +1 -1
- package/dist/simulator/validation.js +188 -162
- package/dist/simulator/validation.js.map +1 -1
- package/dist/streams/collect.cjs +74 -24
- package/dist/streams/collect.cjs.map +1 -1
- package/dist/streams/collect.d.cts +14 -1
- package/dist/streams/collect.d.cts.map +1 -1
- package/dist/streams/collect.d.ts +14 -1
- package/dist/streams/collect.d.ts.map +1 -1
- package/dist/streams/collect.js +74 -25
- package/dist/streams/collect.js.map +1 -1
- package/dist/streams/file-source.cjs +287 -0
- package/dist/streams/file-source.cjs.map +1 -0
- package/dist/streams/file-source.d.cts +96 -0
- package/dist/streams/file-source.d.cts.map +1 -0
- package/dist/streams/file-source.d.ts +96 -0
- package/dist/streams/file-source.d.ts.map +1 -0
- package/dist/streams/file-source.js +286 -0
- package/dist/streams/file-source.js.map +1 -0
- package/dist/streams/hash.cjs +207 -115
- package/dist/streams/hash.cjs.map +1 -1
- package/dist/streams/hash.d.cts +5 -4
- package/dist/streams/hash.d.cts.map +1 -1
- package/dist/streams/hash.d.ts +5 -4
- package/dist/streams/hash.d.ts.map +1 -1
- package/dist/streams/hash.js +208 -95
- package/dist/streams/hash.js.map +1 -1
- package/dist/streams/index.cjs +12 -12
- package/dist/streams/index.d.cts +3 -3
- package/dist/streams/index.d.cts.map +1 -1
- package/dist/streams/index.d.ts +3 -3
- package/dist/streams/index.d.ts.map +1 -1
- package/dist/streams/index.js +2 -10
- package/dist/streams/progress.cjs +60 -46
- package/dist/streams/progress.cjs.map +1 -1
- package/dist/streams/progress.js +60 -46
- package/dist/streams/progress.js.map +1 -1
- package/dist/streams/source.cjs +316 -146
- package/dist/streams/source.cjs.map +1 -1
- package/dist/streams/source.d.cts +56 -18
- package/dist/streams/source.d.cts.map +1 -1
- package/dist/streams/source.d.ts +56 -18
- package/dist/streams/source.d.ts.map +1 -1
- package/dist/streams/source.js +312 -149
- package/dist/streams/source.js.map +1 -1
- package/dist/sync/actions/index.cjs +236 -184
- package/dist/sync/actions/index.cjs.map +1 -1
- package/dist/sync/actions/index.d.cts +29 -21
- package/dist/sync/actions/index.d.cts.map +1 -1
- package/dist/sync/actions/index.d.ts +29 -21
- package/dist/sync/actions/index.d.ts.map +1 -1
- package/dist/sync/actions/index.js +236 -190
- package/dist/sync/actions/index.js.map +1 -1
- package/dist/sync/b2-sha1-reader.cjs +148 -0
- package/dist/sync/b2-sha1-reader.cjs.map +1 -0
- package/dist/sync/b2-sha1-reader.d.cts +58 -0
- package/dist/sync/b2-sha1-reader.d.cts.map +1 -0
- package/dist/sync/b2-sha1-reader.d.ts +58 -0
- package/dist/sync/b2-sha1-reader.d.ts.map +1 -0
- package/dist/sync/b2-sha1-reader.js +145 -0
- package/dist/sync/b2-sha1-reader.js.map +1 -0
- package/dist/sync/download-staging.cjs +265 -0
- package/dist/sync/download-staging.cjs.map +1 -0
- package/dist/sync/download-staging.d.cts +54 -0
- package/dist/sync/download-staging.d.cts.map +1 -0
- package/dist/sync/download-staging.d.ts +54 -0
- package/dist/sync/download-staging.d.ts.map +1 -0
- package/dist/sync/download-staging.js +259 -0
- package/dist/sync/download-staging.js.map +1 -0
- package/dist/sync/filesystem-errors.cjs +32 -0
- package/dist/sync/filesystem-errors.cjs.map +1 -0
- package/dist/sync/filesystem-errors.d.cts +8 -0
- package/dist/sync/filesystem-errors.d.cts.map +1 -0
- package/dist/sync/filesystem-errors.d.ts +8 -0
- package/dist/sync/filesystem-errors.d.ts.map +1 -0
- package/dist/sync/filesystem-errors.js +32 -0
- package/dist/sync/filesystem-errors.js.map +1 -0
- package/dist/sync/filters.cjs +217 -0
- package/dist/sync/filters.cjs.map +1 -0
- package/dist/sync/filters.d.cts +51 -0
- package/dist/sync/filters.d.cts.map +1 -0
- package/dist/sync/filters.d.ts +51 -0
- package/dist/sync/filters.d.ts.map +1 -0
- package/dist/sync/filters.js +213 -0
- package/dist/sync/filters.js.map +1 -0
- package/dist/sync/index.cjs +39 -22
- package/dist/sync/index.d.cts +14 -9
- package/dist/sync/index.d.cts.map +1 -1
- package/dist/sync/index.d.ts +14 -9
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +9 -20
- package/dist/sync/local-file-identity.cjs +61 -0
- package/dist/sync/local-file-identity.cjs.map +1 -0
- package/dist/sync/local-file-identity.d.cts +37 -0
- package/dist/sync/local-file-identity.d.cts.map +1 -0
- package/dist/sync/local-file-identity.d.ts +37 -0
- package/dist/sync/local-file-identity.d.ts.map +1 -0
- package/dist/sync/local-file-identity.js +60 -0
- package/dist/sync/local-file-identity.js.map +1 -0
- package/dist/sync/local-file-io.cjs +364 -0
- package/dist/sync/local-file-io.cjs.map +1 -0
- package/dist/sync/local-file-io.d.cts +75 -0
- package/dist/sync/local-file-io.d.cts.map +1 -0
- package/dist/sync/local-file-io.d.ts +75 -0
- package/dist/sync/local-file-io.d.ts.map +1 -0
- package/dist/sync/local-file-io.js +360 -0
- package/dist/sync/local-file-io.js.map +1 -0
- package/dist/sync/local-filesystem-root.cjs +27 -0
- package/dist/sync/local-filesystem-root.cjs.map +1 -0
- package/dist/sync/local-filesystem-root.d.cts +18 -0
- package/dist/sync/local-filesystem-root.d.cts.map +1 -0
- package/dist/sync/local-filesystem-root.d.ts +18 -0
- package/dist/sync/local-filesystem-root.d.ts.map +1 -0
- package/dist/sync/local-filesystem-root.js +26 -0
- package/dist/sync/local-filesystem-root.js.map +1 -0
- package/dist/sync/local-sha1.cjs +119 -0
- package/dist/sync/local-sha1.cjs.map +1 -0
- package/dist/sync/local-sha1.d.cts +39 -0
- package/dist/sync/local-sha1.d.cts.map +1 -0
- package/dist/sync/local-sha1.d.ts +39 -0
- package/dist/sync/local-sha1.d.ts.map +1 -0
- package/dist/sync/local-sha1.js +117 -0
- package/dist/sync/local-sha1.js.map +1 -0
- package/dist/sync/pairing.cjs +118 -29
- package/dist/sync/pairing.cjs.map +1 -1
- package/dist/sync/pairing.d.cts +7 -2
- package/dist/sync/pairing.d.cts.map +1 -1
- package/dist/sync/pairing.d.ts +7 -2
- package/dist/sync/pairing.d.ts.map +1 -1
- package/dist/sync/pairing.js +120 -31
- package/dist/sync/pairing.js.map +1 -1
- package/dist/sync/path-order.cjs +30 -0
- package/dist/sync/path-order.cjs.map +1 -0
- package/dist/sync/path-order.d.cts +28 -0
- package/dist/sync/path-order.d.cts.map +1 -0
- package/dist/sync/path-order.d.ts +28 -0
- package/dist/sync/path-order.d.ts.map +1 -0
- package/dist/sync/path-order.js +29 -0
- package/dist/sync/path-order.js.map +1 -0
- package/dist/sync/path-safety.cjs +111 -0
- package/dist/sync/path-safety.cjs.map +1 -0
- package/dist/sync/path-safety.d.cts +78 -0
- package/dist/sync/path-safety.d.cts.map +1 -0
- package/dist/sync/path-safety.d.ts +78 -0
- package/dist/sync/path-safety.d.ts.map +1 -0
- package/dist/sync/path-safety.js +105 -0
- package/dist/sync/path-safety.js.map +1 -0
- package/dist/sync/paths.d.cts +19 -0
- package/dist/sync/paths.d.cts.map +1 -0
- package/dist/sync/paths.d.ts +19 -0
- package/dist/sync/paths.d.ts.map +1 -0
- package/dist/sync/policies/compare.cjs +389 -11
- package/dist/sync/policies/compare.cjs.map +1 -1
- package/dist/sync/policies/compare.d.cts +100 -2
- package/dist/sync/policies/compare.d.cts.map +1 -1
- package/dist/sync/policies/compare.d.ts +100 -2
- package/dist/sync/policies/compare.d.ts.map +1 -1
- package/dist/sync/policies/compare.js +387 -13
- package/dist/sync/policies/compare.js.map +1 -1
- package/dist/sync/policies/index.cjs +76 -65
- package/dist/sync/policies/index.cjs.map +1 -1
- package/dist/sync/policies/index.d.cts +35 -6
- package/dist/sync/policies/index.d.cts.map +1 -1
- package/dist/sync/policies/index.d.ts +35 -6
- package/dist/sync/policies/index.d.ts.map +1 -1
- package/dist/sync/policies/index.js +76 -65
- package/dist/sync/policies/index.js.map +1 -1
- package/dist/sync/prefix.cjs +96 -0
- package/dist/sync/prefix.cjs.map +1 -0
- package/dist/sync/prefix.d.cts +55 -0
- package/dist/sync/prefix.d.cts.map +1 -0
- package/dist/sync/prefix.d.ts +55 -0
- package/dist/sync/prefix.d.ts.map +1 -0
- package/dist/sync/prefix.js +92 -0
- package/dist/sync/prefix.js.map +1 -0
- package/dist/sync/regexp-safety.cjs +192 -0
- package/dist/sync/regexp-safety.cjs.map +1 -0
- package/dist/sync/regexp-safety.d.cts +29 -0
- package/dist/sync/regexp-safety.d.cts.map +1 -0
- package/dist/sync/regexp-safety.d.ts +29 -0
- package/dist/sync/regexp-safety.d.ts.map +1 -0
- package/dist/sync/regexp-safety.js +190 -0
- package/dist/sync/regexp-safety.js.map +1 -0
- package/dist/sync/scan-events.cjs +33 -0
- package/dist/sync/scan-events.cjs.map +1 -0
- package/dist/sync/scan-events.d.cts +17 -0
- package/dist/sync/scan-events.d.cts.map +1 -0
- package/dist/sync/scan-events.d.ts +17 -0
- package/dist/sync/scan-events.d.ts.map +1 -0
- package/dist/sync/scan-events.js +32 -0
- package/dist/sync/scan-events.js.map +1 -0
- package/dist/sync/scan-limit.cjs +33 -0
- package/dist/sync/scan-limit.cjs.map +1 -0
- package/dist/sync/scan-limit.d.cts +21 -0
- package/dist/sync/scan-limit.d.cts.map +1 -0
- package/dist/sync/scan-limit.d.ts +21 -0
- package/dist/sync/scan-limit.d.ts.map +1 -0
- package/dist/sync/scan-limit.js +31 -0
- package/dist/sync/scan-limit.js.map +1 -0
- package/dist/sync/scanners/b2.cjs +239 -55
- package/dist/sync/scanners/b2.cjs.map +1 -1
- package/dist/sync/scanners/b2.d.cts +26 -7
- package/dist/sync/scanners/b2.d.cts.map +1 -1
- package/dist/sync/scanners/b2.d.ts +26 -7
- package/dist/sync/scanners/b2.d.ts.map +1 -1
- package/dist/sync/scanners/b2.js +239 -55
- package/dist/sync/scanners/b2.js.map +1 -1
- package/dist/sync/scanners/local.cjs +215 -56
- package/dist/sync/scanners/local.cjs.map +1 -1
- package/dist/sync/scanners/local.d.cts +22 -7
- package/dist/sync/scanners/local.d.cts.map +1 -1
- package/dist/sync/scanners/local.d.ts +22 -7
- package/dist/sync/scanners/local.d.ts.map +1 -1
- package/dist/sync/scanners/local.js +216 -57
- package/dist/sync/scanners/local.js.map +1 -1
- package/dist/sync/sha1-metadata.cjs +94 -0
- package/dist/sync/sha1-metadata.cjs.map +1 -0
- package/dist/sync/sha1-metadata.d.cts +82 -0
- package/dist/sync/sha1-metadata.d.cts.map +1 -0
- package/dist/sync/sha1-metadata.d.ts +82 -0
- package/dist/sync/sha1-metadata.d.ts.map +1 -0
- package/dist/sync/sha1-metadata.js +89 -0
- package/dist/sync/sha1-metadata.js.map +1 -0
- package/dist/sync/sha1-options.cjs +23 -0
- package/dist/sync/sha1-options.cjs.map +1 -0
- package/dist/sync/sha1-options.d.cts +14 -0
- package/dist/sync/sha1-options.d.cts.map +1 -0
- package/dist/sync/sha1-options.d.ts +14 -0
- package/dist/sync/sha1-options.d.ts.map +1 -0
- package/dist/sync/sha1-options.js +21 -0
- package/dist/sync/sha1-options.js.map +1 -0
- package/dist/sync/synchronizer.cjs +782 -197
- package/dist/sync/synchronizer.cjs.map +1 -1
- package/dist/sync/synchronizer.d.cts +47 -1
- package/dist/sync/synchronizer.d.cts.map +1 -1
- package/dist/sync/synchronizer.d.ts +47 -1
- package/dist/sync/synchronizer.d.ts.map +1 -1
- package/dist/sync/synchronizer.js +779 -173
- package/dist/sync/synchronizer.js.map +1 -1
- package/dist/sync/types.d.cts +208 -16
- package/dist/sync/types.d.cts.map +1 -1
- package/dist/sync/types.d.ts +208 -16
- package/dist/sync/types.d.ts.map +1 -1
- package/dist/types/auth.cjs +76 -56
- package/dist/types/auth.cjs.map +1 -1
- package/dist/types/auth.d.cts +67 -9
- package/dist/types/auth.d.cts.map +1 -1
- package/dist/types/auth.d.ts +67 -9
- package/dist/types/auth.d.ts.map +1 -1
- package/dist/types/auth.js +77 -57
- package/dist/types/auth.js.map +1 -1
- package/dist/types/bucket.cjs +74 -38
- package/dist/types/bucket.cjs.map +1 -1
- package/dist/types/bucket.js +75 -41
- package/dist/types/bucket.js.map +1 -1
- package/dist/types/encryption.cjs +364 -327
- package/dist/types/encryption.cjs.map +1 -1
- package/dist/types/encryption.d.cts +16 -0
- package/dist/types/encryption.d.cts.map +1 -1
- package/dist/types/encryption.d.ts +16 -0
- package/dist/types/encryption.d.ts.map +1 -1
- package/dist/types/encryption.js +364 -310
- package/dist/types/encryption.js.map +1 -1
- package/dist/types/errors.cjs +47 -0
- package/dist/types/errors.cjs.map +1 -0
- package/dist/types/errors.d.cts +13 -4
- package/dist/types/errors.d.cts.map +1 -1
- package/dist/types/errors.d.ts +13 -4
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/errors.js +47 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/file.cjs +36 -19
- package/dist/types/file.cjs.map +1 -1
- package/dist/types/file.d.cts +2 -2
- package/dist/types/file.d.cts.map +1 -1
- package/dist/types/file.d.ts +2 -2
- package/dist/types/file.d.ts.map +1 -1
- package/dist/types/file.js +37 -21
- package/dist/types/file.js.map +1 -1
- package/dist/types/ids.cjs +53 -9
- package/dist/types/ids.cjs.map +1 -1
- package/dist/types/ids.js +54 -15
- package/dist/types/ids.js.map +1 -1
- package/dist/types/index.d.cts +12 -11
- package/dist/types/index.d.cts.map +1 -1
- package/dist/types/index.d.ts +12 -11
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/key.d.cts +44 -8
- package/dist/types/key.d.cts.map +1 -1
- package/dist/types/key.d.ts +44 -8
- package/dist/types/key.d.ts.map +1 -1
- package/dist/types/lock.cjs +33 -13
- package/dist/types/lock.cjs.map +1 -1
- package/dist/types/lock.js +34 -15
- package/dist/types/lock.js.map +1 -1
- package/dist/types/notifications.cjs +44 -22
- package/dist/types/notifications.cjs.map +1 -1
- package/dist/types/notifications.js +45 -23
- package/dist/types/notifications.js.map +1 -1
- package/dist/types/upload.d.cts +39 -5
- package/dist/types/upload.d.cts.map +1 -1
- package/dist/types/upload.d.ts +39 -5
- package/dist/types/upload.d.ts.map +1 -1
- package/dist/upload/abort-scope.cjs +91 -0
- package/dist/upload/abort-scope.cjs.map +1 -0
- package/dist/upload/abort-scope.d.cts +48 -0
- package/dist/upload/abort-scope.d.cts.map +1 -0
- package/dist/upload/abort-scope.d.ts +48 -0
- package/dist/upload/abort-scope.d.ts.map +1 -0
- package/dist/upload/abort-scope.js +88 -0
- package/dist/upload/abort-scope.js.map +1 -0
- package/dist/upload/cancel.cjs +183 -8
- package/dist/upload/cancel.cjs.map +1 -1
- package/dist/upload/cancel.d.cts +110 -2
- package/dist/upload/cancel.d.cts.map +1 -1
- package/dist/upload/cancel.d.ts +110 -2
- package/dist/upload/cancel.d.ts.map +1 -1
- package/dist/upload/cancel.js +178 -9
- package/dist/upload/cancel.js.map +1 -1
- package/dist/upload/concurrency.cjs +79 -52
- package/dist/upload/concurrency.cjs.map +1 -1
- package/dist/upload/concurrency.js +79 -53
- package/dist/upload/concurrency.js.map +1 -1
- package/dist/upload/finish.cjs +59 -0
- package/dist/upload/finish.cjs.map +1 -0
- package/dist/upload/finish.d.cts +26 -0
- package/dist/upload/finish.d.cts.map +1 -0
- package/dist/upload/finish.d.ts +26 -0
- package/dist/upload/finish.d.ts.map +1 -0
- package/dist/upload/finish.js +59 -0
- package/dist/upload/finish.js.map +1 -0
- package/dist/upload/large.cjs +301 -218
- package/dist/upload/large.cjs.map +1 -1
- package/dist/upload/large.d.cts +76 -9
- package/dist/upload/large.d.cts.map +1 -1
- package/dist/upload/large.d.ts +76 -9
- package/dist/upload/large.d.ts.map +1 -1
- package/dist/upload/large.js +301 -218
- package/dist/upload/large.js.map +1 -1
- package/dist/upload/options.cjs +28 -0
- package/dist/upload/options.cjs.map +1 -0
- package/dist/upload/options.d.cts +104 -0
- package/dist/upload/options.d.cts.map +1 -0
- package/dist/upload/options.d.ts +104 -0
- package/dist/upload/options.d.ts.map +1 -0
- package/dist/upload/options.js +27 -0
- package/dist/upload/options.js.map +1 -0
- package/dist/upload/resume.cjs +333 -33
- package/dist/upload/resume.cjs.map +1 -1
- package/dist/upload/resume.d.cts +82 -12
- package/dist/upload/resume.d.cts.map +1 -1
- package/dist/upload/resume.d.ts +82 -12
- package/dist/upload/resume.d.ts.map +1 -1
- package/dist/upload/resume.js +330 -33
- package/dist/upload/resume.js.map +1 -1
- package/dist/upload/retry.cjs +186 -0
- package/dist/upload/retry.cjs.map +1 -0
- package/dist/upload/retry.d.cts +127 -0
- package/dist/upload/retry.d.cts.map +1 -0
- package/dist/upload/retry.d.ts +127 -0
- package/dist/upload/retry.d.ts.map +1 -0
- package/dist/upload/retry.js +182 -0
- package/dist/upload/retry.js.map +1 -0
- package/dist/upload/single.cjs +68 -44
- package/dist/upload/single.cjs.map +1 -1
- package/dist/upload/single.d.cts +2 -1
- package/dist/upload/single.d.cts.map +1 -1
- package/dist/upload/single.d.ts +2 -1
- package/dist/upload/single.d.ts.map +1 -1
- package/dist/upload/single.js +68 -44
- package/dist/upload/single.js.map +1 -1
- package/dist/upload/stream.cjs +317 -193
- package/dist/upload/stream.cjs.map +1 -1
- package/dist/upload/stream.d.cts +3 -1
- package/dist/upload/stream.d.cts.map +1 -1
- package/dist/upload/stream.d.ts +3 -1
- package/dist/upload/stream.d.ts.map +1 -1
- package/dist/upload/stream.js +316 -192
- package/dist/upload/stream.js.map +1 -1
- package/dist/util/best-effort.cjs +42 -8
- package/dist/util/best-effort.cjs.map +1 -1
- package/dist/util/best-effort.d.cts +2 -1
- package/dist/util/best-effort.d.cts.map +1 -1
- package/dist/util/best-effort.d.ts +2 -1
- package/dist/util/best-effort.d.ts.map +1 -1
- package/dist/util/best-effort.js +43 -9
- package/dist/util/best-effort.js.map +1 -1
- package/dist/util/bytes.cjs +23 -0
- package/dist/util/bytes.cjs.map +1 -0
- package/dist/util/bytes.d.cts +15 -0
- package/dist/util/bytes.d.cts.map +1 -0
- package/dist/util/bytes.d.ts +15 -0
- package/dist/util/bytes.d.ts.map +1 -0
- package/dist/util/bytes.js +23 -0
- package/dist/util/bytes.js.map +1 -0
- package/dist/util/crypto.cjs +68 -0
- package/dist/util/crypto.cjs.map +1 -0
- package/dist/util/crypto.d.cts +26 -0
- package/dist/util/crypto.d.cts.map +1 -0
- package/dist/util/crypto.d.ts +26 -0
- package/dist/util/crypto.d.ts.map +1 -0
- package/dist/util/crypto.js +66 -0
- package/dist/util/crypto.js.map +1 -0
- package/dist/util/defaults.cjs +25 -9
- package/dist/util/defaults.cjs.map +1 -1
- package/dist/util/defaults.js +26 -11
- package/dist/util/defaults.js.map +1 -1
- package/dist/util/error-reason.cjs +41 -0
- package/dist/util/error-reason.cjs.map +1 -0
- package/dist/util/error-reason.d.cts +9 -0
- package/dist/util/error-reason.d.cts.map +1 -0
- package/dist/util/error-reason.d.ts +9 -0
- package/dist/util/error-reason.d.ts.map +1 -0
- package/dist/util/error-reason.js +41 -0
- package/dist/util/error-reason.js.map +1 -0
- package/dist/util/http.cjs +23 -0
- package/dist/util/http.cjs.map +1 -0
- package/dist/util/http.d.cts +13 -0
- package/dist/util/http.d.cts.map +1 -0
- package/dist/util/http.d.ts +13 -0
- package/dist/util/http.d.ts.map +1 -0
- package/dist/util/http.js +23 -0
- package/dist/util/http.js.map +1 -0
- package/dist/util/normalize.cjs +66 -7
- package/dist/util/normalize.cjs.map +1 -1
- package/dist/util/normalize.js +67 -10
- package/dist/util/normalize.js.map +1 -1
- package/dist/util/paginator.cjs +63 -14
- package/dist/util/paginator.cjs.map +1 -1
- package/dist/util/paginator.js +64 -16
- package/dist/util/paginator.js.map +1 -1
- package/dist/util/plan-ranges.cjs +47 -22
- package/dist/util/plan-ranges.cjs.map +1 -1
- package/dist/util/plan-ranges.js +48 -24
- package/dist/util/plan-ranges.js.map +1 -1
- package/dist/util/sha1.cjs +27 -0
- package/dist/util/sha1.cjs.map +1 -0
- package/dist/util/sha1.d.cts +17 -0
- package/dist/util/sha1.d.cts.map +1 -0
- package/dist/util/sha1.d.ts +17 -0
- package/dist/util/sha1.d.ts.map +1 -0
- package/dist/util/sha1.js +26 -0
- package/dist/util/sha1.js.map +1 -0
- package/dist/util/text-codec.cjs +29 -5
- package/dist/util/text-codec.cjs.map +1 -1
- package/dist/util/text-codec.js +30 -7
- package/dist/util/text-codec.js.map +1 -1
- package/dist/util/to-error.cjs +18 -4
- package/dist/util/to-error.cjs.map +1 -1
- package/dist/util/to-error.js +19 -5
- package/dist/util/to-error.js.map +1 -1
- package/dist/version.cjs +17 -5
- package/dist/version.cjs.map +1 -1
- package/dist/version.d.cts +3 -3
- package/dist/version.d.ts +3 -3
- package/dist/version.js +19 -6
- package/dist/version.js.map +1 -1
- package/package.json +19 -16
- package/dist/auth/index.cjs.map +0 -1
- package/dist/auth/index.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/notifications/index.cjs.map +0 -1
- package/dist/notifications/index.js.map +0 -1
- package/dist/package.json.cjs +0 -9
- package/dist/package.json.cjs.map +0 -1
- package/dist/package.json.js +0 -9
- package/dist/package.json.js.map +0 -1
- package/dist/streams/index.cjs.map +0 -1
- package/dist/streams/index.js.map +0 -1
- package/dist/sync/index.cjs.map +0 -1
- package/dist/sync/index.js.map +0 -1
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
const require_error_reason = require("../util/error-reason.cjs");
|
|
2
|
+
const require_local_file_identity = require("./local-file-identity.cjs");
|
|
3
|
+
const require_path_safety = require("./path-safety.cjs");
|
|
4
|
+
const require_download_staging = require("./download-staging.cjs");
|
|
5
|
+
const require_b2_sha1_reader = require("./b2-sha1-reader.cjs");
|
|
6
|
+
//#region src/sync/local-file-io.ts
|
|
7
|
+
/** @internal */
|
|
8
|
+
var localFileIoTestHooks = {};
|
|
9
|
+
/**
|
|
10
|
+
* Verifies that a previously scanned local file still points at the same regular file.
|
|
11
|
+
*
|
|
12
|
+
* @param path - Scanned local path and file identity.
|
|
13
|
+
*
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
async function validateScannedLocalFile(path) {
|
|
17
|
+
await (await openValidatedScannedLocalFile(path)).close();
|
|
18
|
+
}
|
|
19
|
+
async function openValidatedScannedLocalFile(path) {
|
|
20
|
+
const { constants } = await import("node:fs");
|
|
21
|
+
const { open } = await import("node:fs/promises");
|
|
22
|
+
const flags = constants.O_RDONLY | require_path_safety.noFollowFlag(constants) | (constants.O_NONBLOCK ?? 0);
|
|
23
|
+
const handle = await open(path.absolutePath, flags).catch((err) => {
|
|
24
|
+
if (require_path_safety.hasErrorCode(err, "ELOOP")) throw new Error("local file changed before upload: not a regular file");
|
|
25
|
+
throw new Error(`local file changed before upload: could not open scanned file: ${require_error_reason.sanitizeErrorReason(err)}`);
|
|
26
|
+
});
|
|
27
|
+
try {
|
|
28
|
+
require_local_file_identity.assertSameScannedRegularFile(await handle.stat(), path, "upload", { platform: localFileIoTestHooks.platform });
|
|
29
|
+
return handle;
|
|
30
|
+
} catch (err) {
|
|
31
|
+
await handle.close().catch(() => {});
|
|
32
|
+
throw err;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Streams a B2 download under a local sync root with path, timeout, and size checks.
|
|
37
|
+
*
|
|
38
|
+
* @param root - Local sync root.
|
|
39
|
+
* @param relPath - Destination path relative to the root.
|
|
40
|
+
* @param body - Download body stream.
|
|
41
|
+
* @param options - Expected byte count, idle timeout, and optional abort signal.
|
|
42
|
+
*
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
45
|
+
async function writeLocalStreamInsideRoot(root, relPath, body, options) {
|
|
46
|
+
const { constants } = await import("node:fs");
|
|
47
|
+
const { link, lstat, mkdir, open, realpath, rename, rm, stat } = await import("node:fs/promises");
|
|
48
|
+
const path = await import("node:path");
|
|
49
|
+
const { randomUUID } = await import("node:crypto");
|
|
50
|
+
assertValidExpectedBytes(options.expectedBytes);
|
|
51
|
+
const segments = require_path_safety.safeRelativePathSegments(relPath);
|
|
52
|
+
if (require_download_staging.isDownloadStagingDirectorySegment(segments[0])) throw new Error(`unsafe local destination path: ${require_download_staging.DOWNLOAD_STAGING_DIRECTORY_NAME} is reserved for SDK download staging`);
|
|
53
|
+
const rootRealPath = await realpath(root);
|
|
54
|
+
let current = rootRealPath;
|
|
55
|
+
for (const segment of segments.slice(0, -1)) {
|
|
56
|
+
current = path.join(current, segment);
|
|
57
|
+
try {
|
|
58
|
+
await mkdir(current);
|
|
59
|
+
} catch (err) {
|
|
60
|
+
if (!require_path_safety.hasErrorCode(err, "EEXIST")) throw err;
|
|
61
|
+
}
|
|
62
|
+
if (!(await lstat(current)).isDirectory()) throw new Error("unsafe local destination path: parent is not a directory");
|
|
63
|
+
await localFileIoTestHooks.afterParentDirectoryValidated?.(current);
|
|
64
|
+
}
|
|
65
|
+
const destPath = path.join(rootRealPath, ...segments);
|
|
66
|
+
require_path_safety.assertPathInsideRoot(rootRealPath, destPath, path);
|
|
67
|
+
const parentRealPath = await realpath(path.dirname(destPath));
|
|
68
|
+
const finalPath = path.join(parentRealPath, path.basename(destPath));
|
|
69
|
+
require_path_safety.assertPathInsideRoot(rootRealPath, finalPath, path);
|
|
70
|
+
try {
|
|
71
|
+
const targetStats = await lstat(finalPath);
|
|
72
|
+
if (targetStats.isSymbolicLink()) throw new Error("unsafe local destination path: target is a symbolic link");
|
|
73
|
+
if (targetStats.isFile() && targetStats.nlink > 1) throw new Error("unsafe local destination path: target has multiple hard links");
|
|
74
|
+
} catch (err) {
|
|
75
|
+
if (!require_path_safety.hasErrorCode(err, "ENOENT")) throw err;
|
|
76
|
+
}
|
|
77
|
+
const statForDeviceCheck = localFileIoTestHooks.statForDeviceCheck ?? stat;
|
|
78
|
+
await require_download_staging.assertDownloadPathSameDevice(rootRealPath, parentRealPath, statForDeviceCheck, "unsafe local destination path: cannot publish download across filesystems");
|
|
79
|
+
let parentHandle;
|
|
80
|
+
let anchoredParentPath;
|
|
81
|
+
/* v8 ignore start -- Linux-only fd-relative path support is covered by Linux CI */
|
|
82
|
+
if (globalThis.process?.platform === "linux" && constants.O_DIRECTORY !== void 0 && localFileIoTestHooks.disableProcFdAnchoring !== true) try {
|
|
83
|
+
parentHandle = await open(parentRealPath, constants.O_RDONLY | constants.O_DIRECTORY | require_path_safety.noFollowFlag(constants));
|
|
84
|
+
anchoredParentPath = `/proc/self/fd/${parentHandle.fd}`;
|
|
85
|
+
} catch (err) {
|
|
86
|
+
if (require_path_safety.hasErrorCode(err, "ELOOP") || require_path_safety.hasErrorCode(err, "ENOTDIR")) throw new Error("unsafe local destination path: parent is not a directory");
|
|
87
|
+
throw err;
|
|
88
|
+
}
|
|
89
|
+
/* v8 ignore stop */
|
|
90
|
+
const finalName = path.basename(destPath);
|
|
91
|
+
const finalWritePath = path.join(anchoredParentPath ?? parentRealPath, finalName);
|
|
92
|
+
let publishMode;
|
|
93
|
+
try {
|
|
94
|
+
publishMode = await replacementFileMode(finalPath);
|
|
95
|
+
} catch (err) {
|
|
96
|
+
/* v8 ignore next -- best-effort close during setup failure */
|
|
97
|
+
await parentHandle?.close().catch(() => {});
|
|
98
|
+
throw err;
|
|
99
|
+
}
|
|
100
|
+
let stagingDirectory;
|
|
101
|
+
try {
|
|
102
|
+
stagingDirectory = await require_download_staging.createDownloadStagingDirectory(rootRealPath, path, randomUUID, statForDeviceCheck, localFileIoTestHooks.beforeStagingMarkerWrite);
|
|
103
|
+
} catch (err) {
|
|
104
|
+
/* v8 ignore next -- best-effort close during setup failure */
|
|
105
|
+
await parentHandle?.close().catch(() => {});
|
|
106
|
+
throw err;
|
|
107
|
+
}
|
|
108
|
+
const tmpPath = path.join(stagingDirectory, `.b2sdk-${randomUUID()}.partial`);
|
|
109
|
+
let handle;
|
|
110
|
+
try {
|
|
111
|
+
handle = await open(tmpPath, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | require_path_safety.noFollowFlag(constants), PRIVATE_DOWNLOAD_FILE_MODE);
|
|
112
|
+
/* v8 ignore next -- best-effort chmod */
|
|
113
|
+
await handle.chmod(PRIVATE_DOWNLOAD_FILE_MODE).catch(() => {});
|
|
114
|
+
await localFileIoTestHooks.afterTempFileCreated?.(tmpPath, stagingDirectory);
|
|
115
|
+
} catch (err) {
|
|
116
|
+
await parentHandle?.close().catch(() => {});
|
|
117
|
+
await rm(stagingDirectory, {
|
|
118
|
+
recursive: true,
|
|
119
|
+
force: true
|
|
120
|
+
}).catch(() => {});
|
|
121
|
+
throw err;
|
|
122
|
+
}
|
|
123
|
+
/* v8 ignore stop */
|
|
124
|
+
try {
|
|
125
|
+
const tmpRealPath = await realpath(tmpPath);
|
|
126
|
+
require_path_safety.assertPathInsideRoot(stagingDirectory, tmpRealPath, path);
|
|
127
|
+
} catch (err) {
|
|
128
|
+
/* v8 ignore next -- best-effort cleanup */
|
|
129
|
+
await handle?.close().catch(() => {});
|
|
130
|
+
/* v8 ignore next -- best-effort cleanup */
|
|
131
|
+
await rm(tmpPath, { force: true }).catch(() => {});
|
|
132
|
+
/* v8 ignore next -- best-effort cleanup */
|
|
133
|
+
await rm(stagingDirectory, {
|
|
134
|
+
recursive: true,
|
|
135
|
+
force: true
|
|
136
|
+
}).catch(() => {});
|
|
137
|
+
/* v8 ignore next -- best-effort cleanup */
|
|
138
|
+
await parentHandle?.close().catch(() => {});
|
|
139
|
+
throw err;
|
|
140
|
+
}
|
|
141
|
+
const writeHandle = handle;
|
|
142
|
+
const reader = body.getReader();
|
|
143
|
+
let completed = false;
|
|
144
|
+
try {
|
|
145
|
+
let bytesWritten = 0;
|
|
146
|
+
while (true) {
|
|
147
|
+
const { done, value } = await require_b2_sha1_reader.readStreamChunkWithTimeout(reader, options.idleTimeoutMillis, `download read stalled for ${options.idleTimeoutMillis} ms`, options.signal);
|
|
148
|
+
if (done) break;
|
|
149
|
+
if (bytesWritten + value.byteLength > options.expectedBytes) throw new Error(`download read exceeded ${options.expectedBytes} byte limit`);
|
|
150
|
+
await writeAll(writeHandle, value, bytesWritten);
|
|
151
|
+
bytesWritten += value.byteLength;
|
|
152
|
+
}
|
|
153
|
+
if (bytesWritten !== options.expectedBytes) throw new Error(`download read ended after ${bytesWritten} bytes, expected ${options.expectedBytes}`);
|
|
154
|
+
if (publishMode !== PRIVATE_DOWNLOAD_FILE_MODE)
|
|
155
|
+
/* v8 ignore next -- best-effort mode preservation */
|
|
156
|
+
await writeHandle.chmod(publishMode).catch(() => {});
|
|
157
|
+
await writeHandle.close();
|
|
158
|
+
handle = void 0;
|
|
159
|
+
const [parentRealPathBeforeRename, parentStatsBeforeRename] = await Promise.all([realpath(path.dirname(destPath)), stat(path.dirname(destPath))]);
|
|
160
|
+
require_path_safety.assertPathInsideRoot(rootRealPath, path.join(parentRealPathBeforeRename, path.basename(destPath)), path);
|
|
161
|
+
await localFileIoTestHooks.beforeFinalRename?.(parentRealPathBeforeRename);
|
|
162
|
+
let publishPath = finalWritePath;
|
|
163
|
+
if (anchoredParentPath === void 0) {
|
|
164
|
+
const [parentRealPathAfterHook, parentStatsAfterHook] = await Promise.all([realpath(path.dirname(destPath)), stat(path.dirname(destPath))]);
|
|
165
|
+
if (parentRealPathAfterHook !== parentRealPathBeforeRename || !sameParentIdentity(parentStatsAfterHook, parentStatsBeforeRename)) throw new Error("unsafe local destination path: parent changed before final publish");
|
|
166
|
+
publishPath = path.join(parentRealPathAfterHook, path.basename(destPath));
|
|
167
|
+
require_path_safety.assertPathInsideRoot(rootRealPath, publishPath, path);
|
|
168
|
+
}
|
|
169
|
+
await publishDownload(lstat, link, path, randomUUID, rename, rm, tmpPath, publishPath, options.expectedDestination);
|
|
170
|
+
completed = true;
|
|
171
|
+
} catch (err) {
|
|
172
|
+
/* v8 ignore next -- best-effort cleanup */
|
|
173
|
+
reader.cancel(err).catch(() => {});
|
|
174
|
+
throw err;
|
|
175
|
+
} finally {
|
|
176
|
+
reader.releaseLock();
|
|
177
|
+
if (!completed) {
|
|
178
|
+
/* v8 ignore next -- best-effort cleanup */
|
|
179
|
+
await handle?.close().catch(() => {});
|
|
180
|
+
/* v8 ignore next -- best-effort cleanup */
|
|
181
|
+
await rm(tmpPath, { force: true }).catch(() => {});
|
|
182
|
+
}
|
|
183
|
+
/* v8 ignore next -- best-effort cleanup */
|
|
184
|
+
await rm(stagingDirectory, {
|
|
185
|
+
recursive: true,
|
|
186
|
+
force: true
|
|
187
|
+
}).catch(() => {});
|
|
188
|
+
/* v8 ignore next -- best-effort cleanup */
|
|
189
|
+
await parentHandle?.close().catch(() => {});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function assertValidExpectedBytes(expectedBytes) {
|
|
193
|
+
if (!Number.isSafeInteger(expectedBytes) || expectedBytes < 0) throw new Error("download expectedBytes must be a non-negative safe integer");
|
|
194
|
+
}
|
|
195
|
+
async function assertExpectedDownloadDestination(lstat, finalPath, expectedDestination) {
|
|
196
|
+
if (expectedDestination === void 0) return;
|
|
197
|
+
try {
|
|
198
|
+
const stats = await lstat(finalPath);
|
|
199
|
+
if (expectedDestination === null) throw new Error("local destination changed before download: file was created");
|
|
200
|
+
require_local_file_identity.assertSameScannedRegularFile(stats, {
|
|
201
|
+
...expectedDestination,
|
|
202
|
+
absolutePath: finalPath
|
|
203
|
+
}, "download", { platform: localFileIoTestHooks.platform });
|
|
204
|
+
} catch (err) {
|
|
205
|
+
if (require_path_safety.hasErrorCode(err, "ENOENT")) {
|
|
206
|
+
if (expectedDestination === null) return;
|
|
207
|
+
throw new Error("local file changed before download: file missing");
|
|
208
|
+
}
|
|
209
|
+
throw err;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
async function publishDownload(lstat, link, path, randomUUID, rename, rm, tmpPath, publishPath, expectedDestination) {
|
|
213
|
+
await assertExpectedDownloadDestination(lstat, publishPath, expectedDestination);
|
|
214
|
+
await localFileIoTestHooks.beforeDownloadPublish?.(publishPath);
|
|
215
|
+
if (expectedDestination === void 0) {
|
|
216
|
+
await rename(tmpPath, publishPath);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (expectedDestination === null) {
|
|
220
|
+
await linkDownloadNoOverwrite(link, tmpPath, publishPath, "local destination changed before download: file was created");
|
|
221
|
+
/* v8 ignore next -- staging cleanup is best-effort after a guarded publish succeeds. */
|
|
222
|
+
await rm(tmpPath, { force: true }).catch(() => {});
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
const backupPath = path.join(path.dirname(publishPath), require_path_safety.makeReservedSyncTempFileName(path.basename(publishPath), randomUUID()));
|
|
226
|
+
let backupExists = false;
|
|
227
|
+
let removeBackup = false;
|
|
228
|
+
try {
|
|
229
|
+
try {
|
|
230
|
+
await rename(publishPath, backupPath);
|
|
231
|
+
backupExists = true;
|
|
232
|
+
await localFileIoTestHooks.afterDownloadBackupRename?.(backupPath);
|
|
233
|
+
} catch (err) {
|
|
234
|
+
if (require_path_safety.hasErrorCode(err, "ENOENT")) throw new Error("local file changed before download: file missing");
|
|
235
|
+
throw err;
|
|
236
|
+
}
|
|
237
|
+
require_local_file_identity.assertSameScannedRegularFile(await lstat(backupPath), {
|
|
238
|
+
...expectedDestination,
|
|
239
|
+
absolutePath: backupPath
|
|
240
|
+
}, "download", {
|
|
241
|
+
compareChangeTime: false,
|
|
242
|
+
platform: localFileIoTestHooks.platform
|
|
243
|
+
});
|
|
244
|
+
await linkDownloadNoOverwrite(link, tmpPath, publishPath, "local destination changed before download: file was created");
|
|
245
|
+
removeBackup = true;
|
|
246
|
+
/* v8 ignore next -- staging cleanup is best-effort after a guarded publish succeeds. */
|
|
247
|
+
await rm(tmpPath, { force: true }).catch(() => {});
|
|
248
|
+
} catch (err) {
|
|
249
|
+
if (backupExists && !removeBackup) await restoreBackupWithoutOverwrite(link, rm, backupPath, publishPath).catch(() => {});
|
|
250
|
+
throw err;
|
|
251
|
+
} finally {
|
|
252
|
+
if (removeBackup)
|
|
253
|
+
/* v8 ignore next -- old destination cleanup is best-effort after publish succeeds. */
|
|
254
|
+
await rm(backupPath, { force: true }).catch(() => {});
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
async function linkDownloadNoOverwrite(link, sourcePath, destPath, message) {
|
|
258
|
+
try {
|
|
259
|
+
await link(sourcePath, destPath);
|
|
260
|
+
} catch (err) {
|
|
261
|
+
if (require_path_safety.hasErrorCode(err, "EEXIST")) throw new Error(message);
|
|
262
|
+
throw err;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
async function restoreBackupWithoutOverwrite(link, rm, backupPath, publishPath) {
|
|
266
|
+
try {
|
|
267
|
+
await link(backupPath, publishPath);
|
|
268
|
+
await rm(backupPath, { force: true });
|
|
269
|
+
} catch (err) {
|
|
270
|
+
if (require_path_safety.hasErrorCode(err, "EEXIST")) return;
|
|
271
|
+
throw err;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
var PRIVATE_DOWNLOAD_FILE_MODE = 384;
|
|
275
|
+
async function replacementFileMode(filePath) {
|
|
276
|
+
const { lstat } = await import("node:fs/promises");
|
|
277
|
+
try {
|
|
278
|
+
const stats = await lstat(filePath);
|
|
279
|
+
return stats.isFile() ? stats.mode & 511 : PRIVATE_DOWNLOAD_FILE_MODE;
|
|
280
|
+
} catch (err) {
|
|
281
|
+
if (require_path_safety.hasErrorCode(err, "ENOENT")) return PRIVATE_DOWNLOAD_FILE_MODE;
|
|
282
|
+
throw err;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Deletes a scanned local file under a sync root without re-resolving attacker-controlled parents.
|
|
287
|
+
*
|
|
288
|
+
* @param root - Local sync root.
|
|
289
|
+
* @param scannedPath - Previously scanned local file metadata.
|
|
290
|
+
*
|
|
291
|
+
* @internal
|
|
292
|
+
*/
|
|
293
|
+
async function deleteLocalFileInsideRoot(root, scannedPath) {
|
|
294
|
+
if (root === "") throw new Error("Local sync root required for filesystem mutation");
|
|
295
|
+
const { constants } = await import("node:fs");
|
|
296
|
+
const { lstat, open, realpath, stat, unlink } = await import("node:fs/promises");
|
|
297
|
+
const path = await import("node:path");
|
|
298
|
+
const segments = require_path_safety.safeRelativePathSegments(scannedPath.relativePath);
|
|
299
|
+
const safeRoot = path.resolve(root);
|
|
300
|
+
const rootStats = await lstat(safeRoot);
|
|
301
|
+
if (rootStats.isSymbolicLink()) throw new Error(`Refusing to access sync root through symlink: ${scannedPath.relativePath}`);
|
|
302
|
+
if (!rootStats.isDirectory()) throw new Error(`Local sync root is not a directory: ${scannedPath.relativePath}`);
|
|
303
|
+
const rootRealPath = await realpath(safeRoot);
|
|
304
|
+
const expectedPath = path.join(rootRealPath, ...segments);
|
|
305
|
+
require_path_safety.assertPathInsideRoot(rootRealPath, expectedPath, path);
|
|
306
|
+
if (path.resolve(scannedPath.absolutePath) !== expectedPath) throw new Error(`Refusing to delete outside sync root: ${scannedPath.relativePath}`);
|
|
307
|
+
const [parentRealPath, parentStats] = await Promise.all([realpath(path.dirname(expectedPath)), stat(path.dirname(expectedPath))]);
|
|
308
|
+
const finalPath = path.join(parentRealPath, path.basename(expectedPath));
|
|
309
|
+
require_path_safety.assertPathInsideRoot(rootRealPath, finalPath, path);
|
|
310
|
+
const platform = globalThis.process?.platform;
|
|
311
|
+
let parentHandle;
|
|
312
|
+
let anchoredParentPath;
|
|
313
|
+
/* v8 ignore start -- Linux-only fd-relative path support is covered by Linux CI */
|
|
314
|
+
if (platform === "linux" && constants.O_DIRECTORY !== void 0 && localFileIoTestHooks.disableProcFdAnchoring !== true) try {
|
|
315
|
+
await localFileIoTestHooks.beforeLocalDeleteOpenParent?.(parentRealPath);
|
|
316
|
+
parentHandle = await open(parentRealPath, constants.O_RDONLY | constants.O_DIRECTORY | require_path_safety.noFollowFlag(constants));
|
|
317
|
+
anchoredParentPath = `/proc/self/fd/${parentHandle.fd}`;
|
|
318
|
+
} catch (err) {
|
|
319
|
+
if (require_path_safety.hasErrorCode(err, "ELOOP") || require_path_safety.hasErrorCode(err, "ENOTDIR")) throw new Error("unsafe local delete path: parent is not a directory");
|
|
320
|
+
throw err;
|
|
321
|
+
}
|
|
322
|
+
/* v8 ignore stop */
|
|
323
|
+
try {
|
|
324
|
+
const unlinkPath = anchoredParentPath === void 0 ? finalPath : path.join(anchoredParentPath, path.basename(expectedPath));
|
|
325
|
+
require_local_file_identity.assertSameScannedRegularFile(await lstat(unlinkPath), {
|
|
326
|
+
...scannedPath,
|
|
327
|
+
absolutePath: unlinkPath
|
|
328
|
+
}, "delete", { platform: localFileIoTestHooks.platform });
|
|
329
|
+
await localFileIoTestHooks.beforeLocalDeleteUnlink?.(parentRealPath);
|
|
330
|
+
if (anchoredParentPath === void 0 && localFileIoTestHooks.disableProcFdAnchoring === true && parentRealPath !== rootRealPath) throw new Error("unsafe local delete path: stable parent handle unavailable for unlink");
|
|
331
|
+
if (anchoredParentPath === void 0) {
|
|
332
|
+
const [parentRealPathBeforeUnlink, parentStatsBeforeUnlink] = await Promise.all([realpath(path.dirname(expectedPath)), stat(path.dirname(expectedPath))]);
|
|
333
|
+
if (parentRealPathBeforeUnlink !== parentRealPath || !sameParentIdentity(parentStatsBeforeUnlink, parentStats)) throw new Error("unsafe local delete path: parent changed before unlink");
|
|
334
|
+
}
|
|
335
|
+
require_local_file_identity.assertSameScannedRegularFile(await lstat(unlinkPath), {
|
|
336
|
+
...scannedPath,
|
|
337
|
+
absolutePath: unlinkPath
|
|
338
|
+
}, "delete", { platform: localFileIoTestHooks.platform });
|
|
339
|
+
await unlink(unlinkPath);
|
|
340
|
+
} finally {
|
|
341
|
+
/* v8 ignore next -- best-effort cleanup */
|
|
342
|
+
await parentHandle?.close().catch(() => {});
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
function sameParentIdentity(current, expected) {
|
|
346
|
+
return current.dev === expected.dev && current.ino === expected.ino;
|
|
347
|
+
}
|
|
348
|
+
async function writeAll(handle, data, position) {
|
|
349
|
+
let offset = 0;
|
|
350
|
+
while (offset < data.byteLength) {
|
|
351
|
+
const { bytesWritten } = await handle.write(data, offset, data.byteLength - offset, position + offset);
|
|
352
|
+
/* v8 ignore next -- defensive: FileHandle.write should progress for non-empty chunks. */
|
|
353
|
+
if (bytesWritten <= 0) throw new Error("download write made no progress");
|
|
354
|
+
offset += bytesWritten;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
//#endregion
|
|
358
|
+
exports.DOWNLOAD_STAGING_DIRECTORY_NAME = require_download_staging.DOWNLOAD_STAGING_DIRECTORY_NAME;
|
|
359
|
+
exports.deleteLocalFileInsideRoot = deleteLocalFileInsideRoot;
|
|
360
|
+
exports.localFileIoTestHooks = localFileIoTestHooks;
|
|
361
|
+
exports.validateScannedLocalFile = validateScannedLocalFile;
|
|
362
|
+
exports.writeLocalStreamInsideRoot = writeLocalStreamInsideRoot;
|
|
363
|
+
|
|
364
|
+
//# sourceMappingURL=local-file-io.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-file-io.cjs","names":[],"sources":["../../src/sync/local-file-io.ts"],"sourcesContent":["import { sanitizeErrorReason } from '../util/error-reason.ts'\nimport { readStreamChunkWithTimeout } from './b2-sha1-reader.ts'\nimport {\n assertDownloadPathSameDevice,\n createDownloadStagingDirectory,\n DOWNLOAD_STAGING_DIRECTORY_NAME,\n isDownloadStagingDirectorySegment,\n} from './download-staging.ts'\nimport { assertSameScannedRegularFile } from './local-file-identity.ts'\nimport {\n assertPathInsideRoot,\n hasErrorCode,\n makeReservedSyncTempFileName,\n noFollowFlag,\n safeRelativePathSegments,\n} from './path-safety.ts'\nimport { DEFAULT_SHA1_IDLE_TIMEOUT_MILLIS } from './sha1-options.ts'\nimport type { LocalSyncPath } from './types.ts'\n\ntype DeviceStat = { readonly dev: number | bigint }\ntype DeviceStatFn = (path: string) => Promise<DeviceStat>\n\nexport { DOWNLOAD_STAGING_DIRECTORY_NAME }\n\n/** @internal */\nexport const localFileIoTestHooks: {\n afterParentDirectoryValidated?: (path: string) => Promise<void> | void\n afterDownloadBackupRename?: (path: string) => Promise<void> | void\n afterTempFileCreated?: (path: string, stagingDirectory: string) => Promise<void> | void\n beforeDownloadPublish?: (path: string) => Promise<void> | void\n beforeFinalRename?: (path: string) => Promise<void> | void\n beforeLocalDeleteOpenParent?: (path: string) => Promise<void> | void\n beforeLocalDeleteUnlink?: (path: string) => Promise<void> | void\n beforeStagingMarkerWrite?: (path: string) => Promise<void> | void\n disableProcFdAnchoring?: boolean\n platform?: string\n statForDeviceCheck?: DeviceStatFn\n} = {}\n\ninterface ScannedLocalFileHandle {\n stat(): Promise<{\n isFile(): boolean\n readonly dev: number\n readonly ino: number\n readonly mtimeMs: number\n readonly ctimeMs: number\n readonly size: number\n }>\n readFile(): Promise<Uint8Array>\n close(): Promise<void>\n}\n\n/**\n * Verifies that a previously scanned local file still points at the same regular file.\n *\n * @param path - Scanned local path and file identity.\n *\n * @internal\n */\nexport async function validateScannedLocalFile(path: LocalSyncPath): Promise<void> {\n const handle = await openValidatedScannedLocalFile(path)\n await handle.close()\n}\n\n/**\n * Reads a previously scanned local file while rejecting symlink swaps and metadata drift.\n *\n * @param path - Scanned local path and file identity.\n *\n * @returns The file bytes.\n *\n * @internal\n */\nexport async function readScannedLocalFile(path: LocalSyncPath): Promise<Uint8Array> {\n const handle = await openValidatedScannedLocalFile(path)\n try {\n const data = await handle.readFile()\n if (data.byteLength !== path.size) {\n throw new Error('local file changed before upload: size changed while reading')\n }\n return data\n } finally {\n await handle.close()\n }\n}\n\nasync function openValidatedScannedLocalFile(path: LocalSyncPath): Promise<ScannedLocalFileHandle> {\n const { constants } = await import('node:fs')\n const { open } = await import('node:fs/promises')\n const flags =\n constants.O_RDONLY |\n noFollowFlag(constants) |\n ((constants as { O_NONBLOCK?: number }).O_NONBLOCK ?? 0)\n const handle = await open(path.absolutePath, flags).catch((err: unknown) => {\n if (hasErrorCode(err, 'ELOOP')) {\n throw new Error('local file changed before upload: not a regular file')\n }\n throw new Error(\n `local file changed before upload: could not open scanned file: ${sanitizeErrorReason(err)}`,\n )\n })\n try {\n const stats = await handle.stat()\n assertSameScannedRegularFile(stats, path, 'upload', {\n platform: localFileIoTestHooks.platform,\n })\n return handle\n } catch (err) {\n await handle.close().catch(() => {})\n throw err\n }\n}\n\n/**\n * Writes bytes under a local sync root after path containment checks.\n *\n * @param root - Local sync root.\n * @param relPath - Destination path relative to the root.\n * @param data - Bytes to write.\n *\n * @internal\n */\nexport async function writeLocalFileInsideRoot(\n root: string,\n relPath: string,\n data: Uint8Array,\n): Promise<void> {\n await writeLocalStreamInsideRoot(\n root,\n relPath,\n new ReadableStream<Uint8Array>({\n start(controller) {\n controller.enqueue(data)\n controller.close()\n },\n }),\n {\n expectedBytes: data.byteLength,\n idleTimeoutMillis: DEFAULT_SHA1_IDLE_TIMEOUT_MILLIS,\n },\n )\n}\n\n/**\n * Streams a B2 download under a local sync root with path, timeout, and size checks.\n *\n * @param root - Local sync root.\n * @param relPath - Destination path relative to the root.\n * @param body - Download body stream.\n * @param options - Expected byte count, idle timeout, and optional abort signal.\n *\n * @internal\n */\nexport async function writeLocalStreamInsideRoot(\n root: string,\n relPath: string,\n body: ReadableStream<Uint8Array>,\n options: {\n readonly expectedBytes: number\n readonly expectedDestination?: LocalSyncPath | null\n readonly idleTimeoutMillis: number\n readonly signal?: AbortSignal\n },\n): Promise<void> {\n const { constants } = await import('node:fs')\n const { link, lstat, mkdir, open, realpath, rename, rm, stat } = await import('node:fs/promises')\n const path = await import('node:path')\n const { randomUUID } = await import('node:crypto')\n assertValidExpectedBytes(options.expectedBytes)\n const segments = safeRelativePathSegments(relPath)\n if (isDownloadStagingDirectorySegment(segments[0])) {\n throw new Error(\n `unsafe local destination path: ${DOWNLOAD_STAGING_DIRECTORY_NAME} is reserved for SDK download staging`,\n )\n }\n const rootRealPath = await realpath(root)\n\n let current = rootRealPath\n for (const segment of segments.slice(0, -1)) {\n current = path.join(current, segment)\n try {\n await mkdir(current)\n } catch (err) {\n if (!hasErrorCode(err, 'EEXIST')) throw err\n }\n const stats = await lstat(current)\n if (!stats.isDirectory()) {\n throw new Error('unsafe local destination path: parent is not a directory')\n }\n await localFileIoTestHooks.afterParentDirectoryValidated?.(current)\n }\n\n const destPath = path.join(rootRealPath, ...segments)\n assertPathInsideRoot(rootRealPath, destPath, path)\n\n const parentRealPath = await realpath(path.dirname(destPath))\n const finalPath = path.join(parentRealPath, path.basename(destPath))\n assertPathInsideRoot(rootRealPath, finalPath, path)\n try {\n const targetStats = await lstat(finalPath)\n if (targetStats.isSymbolicLink()) {\n throw new Error('unsafe local destination path: target is a symbolic link')\n }\n if (targetStats.isFile() && targetStats.nlink > 1) {\n throw new Error('unsafe local destination path: target has multiple hard links')\n }\n } catch (err) {\n if (!hasErrorCode(err, 'ENOENT')) throw err\n }\n const statForDeviceCheck = localFileIoTestHooks.statForDeviceCheck ?? stat\n await assertDownloadPathSameDevice(\n rootRealPath,\n parentRealPath,\n statForDeviceCheck,\n 'unsafe local destination path: cannot publish download across filesystems',\n )\n\n let parentHandle: Awaited<ReturnType<typeof open>> | undefined\n let anchoredParentPath: string | undefined\n const platform = (globalThis as { process?: { platform?: string } }).process?.platform\n /* v8 ignore start -- Linux-only fd-relative path support is covered by Linux CI */\n if (\n platform === 'linux' &&\n constants.O_DIRECTORY !== undefined &&\n localFileIoTestHooks.disableProcFdAnchoring !== true\n ) {\n try {\n parentHandle = await open(\n parentRealPath,\n constants.O_RDONLY | constants.O_DIRECTORY | noFollowFlag(constants),\n )\n anchoredParentPath = `/proc/self/fd/${parentHandle.fd}`\n } catch (err) {\n if (hasErrorCode(err, 'ELOOP') || hasErrorCode(err, 'ENOTDIR')) {\n throw new Error('unsafe local destination path: parent is not a directory')\n }\n throw err\n }\n }\n /* v8 ignore stop */\n const finalName = path.basename(destPath)\n const finalWritePath = path.join(anchoredParentPath ?? parentRealPath, finalName)\n let publishMode: number\n try {\n publishMode = await replacementFileMode(finalPath)\n } catch (err) {\n /* v8 ignore next -- best-effort close during setup failure */\n await parentHandle?.close().catch(() => {})\n throw err\n }\n let stagingDirectory: string\n try {\n stagingDirectory = await createDownloadStagingDirectory(\n rootRealPath,\n path,\n randomUUID,\n statForDeviceCheck,\n localFileIoTestHooks.beforeStagingMarkerWrite,\n )\n } catch (err) {\n /* v8 ignore next -- best-effort close during setup failure */\n await parentHandle?.close().catch(() => {})\n throw err\n }\n const tmpPath = path.join(stagingDirectory, `.b2sdk-${randomUUID()}.partial`)\n let handle: Awaited<ReturnType<typeof open>> | undefined\n try {\n handle = await open(\n tmpPath,\n constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | noFollowFlag(constants),\n PRIVATE_DOWNLOAD_FILE_MODE,\n )\n /* v8 ignore next -- best-effort chmod */\n await handle.chmod(PRIVATE_DOWNLOAD_FILE_MODE).catch(() => {})\n await localFileIoTestHooks.afterTempFileCreated?.(tmpPath, stagingDirectory)\n /* v8 ignore start -- defensive cleanup before the main write try/finally exists */\n } catch (err) {\n await parentHandle?.close().catch(() => {})\n await rm(stagingDirectory, { recursive: true, force: true }).catch(() => {})\n throw err\n }\n /* v8 ignore stop */\n try {\n const tmpRealPath = await realpath(tmpPath)\n assertPathInsideRoot(stagingDirectory, tmpRealPath, path)\n } catch (err) {\n /* v8 ignore next -- best-effort cleanup */\n await handle?.close().catch(() => {})\n /* v8 ignore next -- best-effort cleanup */\n await rm(tmpPath, { force: true }).catch(() => {})\n /* v8 ignore next -- best-effort cleanup */\n await rm(stagingDirectory, { recursive: true, force: true }).catch(() => {})\n /* v8 ignore next -- best-effort cleanup */\n await parentHandle?.close().catch(() => {})\n throw err\n }\n const writeHandle = handle\n const reader = body.getReader()\n let completed = false\n try {\n let bytesWritten = 0\n while (true) {\n const { done, value } = await readStreamChunkWithTimeout(\n reader,\n options.idleTimeoutMillis,\n `download read stalled for ${options.idleTimeoutMillis} ms`,\n options.signal,\n )\n if (done) break\n if (bytesWritten + value.byteLength > options.expectedBytes) {\n throw new Error(`download read exceeded ${options.expectedBytes} byte limit`)\n }\n await writeAll(writeHandle, value, bytesWritten)\n bytesWritten += value.byteLength\n }\n if (bytesWritten !== options.expectedBytes) {\n throw new Error(\n `download read ended after ${bytesWritten} bytes, expected ${options.expectedBytes}`,\n )\n }\n if (publishMode !== PRIVATE_DOWNLOAD_FILE_MODE) {\n /* v8 ignore next -- best-effort mode preservation */\n await writeHandle.chmod(publishMode).catch(() => {})\n }\n await writeHandle.close()\n handle = undefined\n\n const [parentRealPathBeforeRename, parentStatsBeforeRename] = await Promise.all([\n realpath(path.dirname(destPath)),\n stat(path.dirname(destPath)),\n ])\n const finalPathBeforeRename = path.join(parentRealPathBeforeRename, path.basename(destPath))\n assertPathInsideRoot(rootRealPath, finalPathBeforeRename, path)\n await localFileIoTestHooks.beforeFinalRename?.(parentRealPathBeforeRename)\n let publishPath = finalWritePath\n if (anchoredParentPath === undefined) {\n const [parentRealPathAfterHook, parentStatsAfterHook] = await Promise.all([\n realpath(path.dirname(destPath)),\n stat(path.dirname(destPath)),\n ])\n if (\n parentRealPathAfterHook !== parentRealPathBeforeRename ||\n !sameParentIdentity(parentStatsAfterHook, parentStatsBeforeRename)\n ) {\n throw new Error('unsafe local destination path: parent changed before final publish')\n }\n publishPath = path.join(parentRealPathAfterHook, path.basename(destPath))\n assertPathInsideRoot(rootRealPath, publishPath, path)\n }\n await publishDownload(\n lstat,\n link,\n path,\n randomUUID,\n rename,\n rm,\n tmpPath,\n publishPath,\n options.expectedDestination,\n )\n completed = true\n } catch (err) {\n /* v8 ignore next -- best-effort cleanup */\n void reader.cancel(err).catch(() => {})\n throw err\n } finally {\n reader.releaseLock()\n if (!completed) {\n /* v8 ignore next -- best-effort cleanup */\n await handle?.close().catch(() => {})\n /* v8 ignore next -- best-effort cleanup */\n await rm(tmpPath, { force: true }).catch(() => {})\n }\n /* v8 ignore next -- best-effort cleanup */\n await rm(stagingDirectory, { recursive: true, force: true }).catch(() => {})\n /* v8 ignore next -- best-effort cleanup */\n await parentHandle?.close().catch(() => {})\n }\n}\n\nfunction assertValidExpectedBytes(expectedBytes: number): void {\n if (!Number.isSafeInteger(expectedBytes) || expectedBytes < 0) {\n throw new Error('download expectedBytes must be a non-negative safe integer')\n }\n}\n\nasync function assertExpectedDownloadDestination(\n lstat: typeof import('node:fs/promises')['lstat'],\n finalPath: string,\n expectedDestination: LocalSyncPath | null | undefined,\n): Promise<void> {\n if (expectedDestination === undefined) return\n\n try {\n const stats = await lstat(finalPath)\n if (expectedDestination === null) {\n throw new Error('local destination changed before download: file was created')\n }\n assertSameScannedRegularFile(\n stats,\n { ...expectedDestination, absolutePath: finalPath },\n 'download',\n { platform: localFileIoTestHooks.platform },\n )\n } catch (err) {\n if (hasErrorCode(err, 'ENOENT')) {\n if (expectedDestination === null) return\n throw new Error('local file changed before download: file missing')\n }\n throw err\n }\n}\n\nasync function publishDownload(\n lstat: typeof import('node:fs/promises')['lstat'],\n link: typeof import('node:fs/promises')['link'],\n path: typeof import('node:path'),\n randomUUID: () => string,\n rename: typeof import('node:fs/promises')['rename'],\n rm: typeof import('node:fs/promises')['rm'],\n tmpPath: string,\n publishPath: string,\n expectedDestination: LocalSyncPath | null | undefined,\n): Promise<void> {\n await assertExpectedDownloadDestination(lstat, publishPath, expectedDestination)\n await localFileIoTestHooks.beforeDownloadPublish?.(publishPath)\n\n if (expectedDestination === undefined) {\n await rename(tmpPath, publishPath)\n return\n }\n\n if (expectedDestination === null) {\n await linkDownloadNoOverwrite(\n link,\n tmpPath,\n publishPath,\n 'local destination changed before download: file was created',\n )\n /* v8 ignore next -- staging cleanup is best-effort after a guarded publish succeeds. */\n await rm(tmpPath, { force: true }).catch(() => {})\n return\n }\n\n const backupPath = path.join(\n path.dirname(publishPath),\n makeReservedSyncTempFileName(path.basename(publishPath), randomUUID()),\n )\n let backupExists = false\n let removeBackup = false\n\n try {\n try {\n await rename(publishPath, backupPath)\n backupExists = true\n await localFileIoTestHooks.afterDownloadBackupRename?.(backupPath)\n } catch (err) {\n if (hasErrorCode(err, 'ENOENT')) {\n throw new Error('local file changed before download: file missing')\n }\n throw err\n }\n\n const backupStats = await lstat(backupPath)\n assertSameScannedRegularFile(\n backupStats,\n { ...expectedDestination, absolutePath: backupPath },\n 'download',\n { compareChangeTime: false, platform: localFileIoTestHooks.platform },\n )\n await linkDownloadNoOverwrite(\n link,\n tmpPath,\n publishPath,\n 'local destination changed before download: file was created',\n )\n removeBackup = true\n /* v8 ignore next -- staging cleanup is best-effort after a guarded publish succeeds. */\n await rm(tmpPath, { force: true }).catch(() => {})\n } catch (err) {\n if (backupExists && !removeBackup) {\n await restoreBackupWithoutOverwrite(link, rm, backupPath, publishPath).catch(() => {})\n }\n throw err\n } finally {\n if (removeBackup) {\n /* v8 ignore next -- old destination cleanup is best-effort after publish succeeds. */\n await rm(backupPath, { force: true }).catch(() => {})\n }\n }\n}\n\nasync function linkDownloadNoOverwrite(\n link: typeof import('node:fs/promises')['link'],\n sourcePath: string,\n destPath: string,\n message: string,\n): Promise<void> {\n try {\n await link(sourcePath, destPath)\n } catch (err) {\n if (hasErrorCode(err, 'EEXIST')) throw new Error(message)\n throw err\n }\n}\n\nasync function restoreBackupWithoutOverwrite(\n link: typeof import('node:fs/promises')['link'],\n rm: typeof import('node:fs/promises')['rm'],\n backupPath: string,\n publishPath: string,\n): Promise<void> {\n try {\n await link(backupPath, publishPath)\n await rm(backupPath, { force: true })\n } catch (err) {\n if (hasErrorCode(err, 'EEXIST')) return\n throw err\n }\n}\n\nconst PRIVATE_DOWNLOAD_FILE_MODE = 0o600\nasync function replacementFileMode(filePath: string): Promise<number> {\n const { lstat } = await import('node:fs/promises')\n try {\n const stats = await lstat(filePath)\n return stats.isFile() ? stats.mode & 0o777 : PRIVATE_DOWNLOAD_FILE_MODE\n } catch (err) {\n if (hasErrorCode(err, 'ENOENT')) return PRIVATE_DOWNLOAD_FILE_MODE\n throw err\n }\n}\n\n/**\n * Deletes a scanned local file under a sync root without re-resolving attacker-controlled parents.\n *\n * @param root - Local sync root.\n * @param scannedPath - Previously scanned local file metadata.\n *\n * @internal\n */\nexport async function deleteLocalFileInsideRoot(\n root: string,\n scannedPath: LocalSyncPath,\n): Promise<void> {\n if (root === '') {\n throw new Error('Local sync root required for filesystem mutation')\n }\n\n const { constants } = await import('node:fs')\n const { lstat, open, realpath, stat, unlink } = await import('node:fs/promises')\n const path = await import('node:path')\n const segments = safeRelativePathSegments(scannedPath.relativePath)\n const safeRoot = path.resolve(root)\n const rootStats = await lstat(safeRoot)\n if (rootStats.isSymbolicLink()) {\n throw new Error(`Refusing to access sync root through symlink: ${scannedPath.relativePath}`)\n }\n if (!rootStats.isDirectory()) {\n throw new Error(`Local sync root is not a directory: ${scannedPath.relativePath}`)\n }\n const rootRealPath = await realpath(safeRoot)\n const expectedPath = path.join(rootRealPath, ...segments)\n assertPathInsideRoot(rootRealPath, expectedPath, path)\n\n const scannerPath = path.resolve(scannedPath.absolutePath)\n if (scannerPath !== expectedPath) {\n throw new Error(`Refusing to delete outside sync root: ${scannedPath.relativePath}`)\n }\n\n const [parentRealPath, parentStats] = await Promise.all([\n realpath(path.dirname(expectedPath)),\n stat(path.dirname(expectedPath)),\n ])\n const finalPath = path.join(parentRealPath, path.basename(expectedPath))\n assertPathInsideRoot(rootRealPath, finalPath, path)\n\n const platform = (globalThis as { process?: { platform?: string } }).process?.platform\n let parentHandle: Awaited<ReturnType<typeof open>> | undefined\n let anchoredParentPath: string | undefined\n /* v8 ignore start -- Linux-only fd-relative path support is covered by Linux CI */\n if (\n platform === 'linux' &&\n constants.O_DIRECTORY !== undefined &&\n localFileIoTestHooks.disableProcFdAnchoring !== true\n ) {\n try {\n await localFileIoTestHooks.beforeLocalDeleteOpenParent?.(parentRealPath)\n parentHandle = await open(\n parentRealPath,\n constants.O_RDONLY | constants.O_DIRECTORY | noFollowFlag(constants),\n )\n anchoredParentPath = `/proc/self/fd/${parentHandle.fd}`\n } catch (err) {\n if (hasErrorCode(err, 'ELOOP') || hasErrorCode(err, 'ENOTDIR')) {\n throw new Error('unsafe local delete path: parent is not a directory')\n }\n throw err\n }\n }\n /* v8 ignore stop */\n\n try {\n const unlinkPath =\n anchoredParentPath === undefined\n ? finalPath\n : path.join(anchoredParentPath, path.basename(expectedPath))\n const stats = await lstat(unlinkPath)\n assertSameScannedRegularFile(stats, { ...scannedPath, absolutePath: unlinkPath }, 'delete', {\n platform: localFileIoTestHooks.platform,\n })\n await localFileIoTestHooks.beforeLocalDeleteUnlink?.(parentRealPath)\n if (\n anchoredParentPath === undefined &&\n localFileIoTestHooks.disableProcFdAnchoring === true &&\n parentRealPath !== rootRealPath\n ) {\n throw new Error('unsafe local delete path: stable parent handle unavailable for unlink')\n }\n\n if (anchoredParentPath === undefined) {\n const [parentRealPathBeforeUnlink, parentStatsBeforeUnlink] = await Promise.all([\n realpath(path.dirname(expectedPath)),\n stat(path.dirname(expectedPath)),\n ])\n if (\n parentRealPathBeforeUnlink !== parentRealPath ||\n !sameParentIdentity(parentStatsBeforeUnlink, parentStats)\n ) {\n throw new Error('unsafe local delete path: parent changed before unlink')\n }\n }\n const finalStats = await lstat(unlinkPath)\n assertSameScannedRegularFile(\n finalStats,\n { ...scannedPath, absolutePath: unlinkPath },\n 'delete',\n { platform: localFileIoTestHooks.platform },\n )\n await unlink(unlinkPath)\n } finally {\n /* v8 ignore next -- best-effort cleanup */\n await parentHandle?.close().catch(() => {})\n }\n}\n\nfunction sameParentIdentity(\n current: { readonly dev: number | bigint; readonly ino: number | bigint },\n expected: { readonly dev: number | bigint; readonly ino: number | bigint },\n): boolean {\n return current.dev === expected.dev && current.ino === expected.ino\n}\n\nasync function writeAll(\n handle: {\n write(\n buffer: Uint8Array,\n offset: number,\n length: number,\n position: number,\n ): Promise<{ readonly bytesWritten: number }>\n },\n data: Uint8Array,\n position: number,\n): Promise<void> {\n let offset = 0\n while (offset < data.byteLength) {\n const { bytesWritten } = await handle.write(\n data,\n offset,\n data.byteLength - offset,\n position + offset,\n )\n /* v8 ignore next -- defensive: FileHandle.write should progress for non-empty chunks. */\n if (bytesWritten <= 0) throw new Error('download write made no progress')\n offset += bytesWritten\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { DOWNLOAD_STAGING_DIRECTORY_NAME } from './download-staging.js';
|
|
2
|
+
import { LocalSyncPath } from './types.js';
|
|
3
|
+
type DeviceStat = {
|
|
4
|
+
readonly dev: number | bigint;
|
|
5
|
+
};
|
|
6
|
+
type DeviceStatFn = (path: string) => Promise<DeviceStat>;
|
|
7
|
+
export { DOWNLOAD_STAGING_DIRECTORY_NAME };
|
|
8
|
+
/** @internal */
|
|
9
|
+
export declare const localFileIoTestHooks: {
|
|
10
|
+
afterParentDirectoryValidated?: (path: string) => Promise<void> | void;
|
|
11
|
+
afterDownloadBackupRename?: (path: string) => Promise<void> | void;
|
|
12
|
+
afterTempFileCreated?: (path: string, stagingDirectory: string) => Promise<void> | void;
|
|
13
|
+
beforeDownloadPublish?: (path: string) => Promise<void> | void;
|
|
14
|
+
beforeFinalRename?: (path: string) => Promise<void> | void;
|
|
15
|
+
beforeLocalDeleteOpenParent?: (path: string) => Promise<void> | void;
|
|
16
|
+
beforeLocalDeleteUnlink?: (path: string) => Promise<void> | void;
|
|
17
|
+
beforeStagingMarkerWrite?: (path: string) => Promise<void> | void;
|
|
18
|
+
disableProcFdAnchoring?: boolean;
|
|
19
|
+
platform?: string;
|
|
20
|
+
statForDeviceCheck?: DeviceStatFn;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Verifies that a previously scanned local file still points at the same regular file.
|
|
24
|
+
*
|
|
25
|
+
* @param path - Scanned local path and file identity.
|
|
26
|
+
*
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
29
|
+
export declare function validateScannedLocalFile(path: LocalSyncPath): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Reads a previously scanned local file while rejecting symlink swaps and metadata drift.
|
|
32
|
+
*
|
|
33
|
+
* @param path - Scanned local path and file identity.
|
|
34
|
+
*
|
|
35
|
+
* @returns The file bytes.
|
|
36
|
+
*
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
export declare function readScannedLocalFile(path: LocalSyncPath): Promise<Uint8Array>;
|
|
40
|
+
/**
|
|
41
|
+
* Writes bytes under a local sync root after path containment checks.
|
|
42
|
+
*
|
|
43
|
+
* @param root - Local sync root.
|
|
44
|
+
* @param relPath - Destination path relative to the root.
|
|
45
|
+
* @param data - Bytes to write.
|
|
46
|
+
*
|
|
47
|
+
* @internal
|
|
48
|
+
*/
|
|
49
|
+
export declare function writeLocalFileInsideRoot(root: string, relPath: string, data: Uint8Array): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Streams a B2 download under a local sync root with path, timeout, and size checks.
|
|
52
|
+
*
|
|
53
|
+
* @param root - Local sync root.
|
|
54
|
+
* @param relPath - Destination path relative to the root.
|
|
55
|
+
* @param body - Download body stream.
|
|
56
|
+
* @param options - Expected byte count, idle timeout, and optional abort signal.
|
|
57
|
+
*
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
60
|
+
export declare function writeLocalStreamInsideRoot(root: string, relPath: string, body: ReadableStream<Uint8Array>, options: {
|
|
61
|
+
readonly expectedBytes: number;
|
|
62
|
+
readonly expectedDestination?: LocalSyncPath | null;
|
|
63
|
+
readonly idleTimeoutMillis: number;
|
|
64
|
+
readonly signal?: AbortSignal;
|
|
65
|
+
}): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Deletes a scanned local file under a sync root without re-resolving attacker-controlled parents.
|
|
68
|
+
*
|
|
69
|
+
* @param root - Local sync root.
|
|
70
|
+
* @param scannedPath - Previously scanned local file metadata.
|
|
71
|
+
*
|
|
72
|
+
* @internal
|
|
73
|
+
*/
|
|
74
|
+
export declare function deleteLocalFileInsideRoot(root: string, scannedPath: LocalSyncPath): Promise<void>;
|
|
75
|
+
//# sourceMappingURL=local-file-io.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-file-io.d.ts","sourceRoot":"","sources":["../../src/sync/local-file-io.js"],"names":[],"mappings":"AAEA,OAAO,EAGL,+BAA+B,EAEhC,MAAM,uBAAuB,CAAA;AAU9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,KAAK,UAAU,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAAA;AACnD,KAAK,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAA;AAEzD,OAAO,EAAE,+BAA+B,EAAE,CAAA;AAE1C,gBAAgB;AAChB,eAAO,MAAM,oBAAoB,EAAE;IACjC,6BAA6B,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACtE,yBAAyB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAClE,oBAAoB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACvF,qBAAqB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAC9D,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAC1D,2BAA2B,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACpE,uBAAuB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAChE,wBAAwB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACjE,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,kBAAkB,CAAC,EAAE,YAAY,CAAA;CAC7B,CAAA;AAeN;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAGjF;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CAWnF;AA6BD;;;;;;;;GAQG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;;;;;;;;GASG;AACH,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,EAChC,OAAO,EAAE;IACP,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,mBAAmB,CAAC,EAAE,aAAa,GAAG,IAAI,CAAA;IACnD,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAA;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAC9B,GACA,OAAO,CAAC,IAAI,CAAC,CAuNf;AA2JD;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,aAAa,GACzB,OAAO,CAAC,IAAI,CAAC,CAoGf"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { DOWNLOAD_STAGING_DIRECTORY_NAME } from './download-staging.js';
|
|
2
|
+
import { LocalSyncPath } from './types.js';
|
|
3
|
+
type DeviceStat = {
|
|
4
|
+
readonly dev: number | bigint;
|
|
5
|
+
};
|
|
6
|
+
type DeviceStatFn = (path: string) => Promise<DeviceStat>;
|
|
7
|
+
export { DOWNLOAD_STAGING_DIRECTORY_NAME };
|
|
8
|
+
/** @internal */
|
|
9
|
+
export declare const localFileIoTestHooks: {
|
|
10
|
+
afterParentDirectoryValidated?: (path: string) => Promise<void> | void;
|
|
11
|
+
afterDownloadBackupRename?: (path: string) => Promise<void> | void;
|
|
12
|
+
afterTempFileCreated?: (path: string, stagingDirectory: string) => Promise<void> | void;
|
|
13
|
+
beforeDownloadPublish?: (path: string) => Promise<void> | void;
|
|
14
|
+
beforeFinalRename?: (path: string) => Promise<void> | void;
|
|
15
|
+
beforeLocalDeleteOpenParent?: (path: string) => Promise<void> | void;
|
|
16
|
+
beforeLocalDeleteUnlink?: (path: string) => Promise<void> | void;
|
|
17
|
+
beforeStagingMarkerWrite?: (path: string) => Promise<void> | void;
|
|
18
|
+
disableProcFdAnchoring?: boolean;
|
|
19
|
+
platform?: string;
|
|
20
|
+
statForDeviceCheck?: DeviceStatFn;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Verifies that a previously scanned local file still points at the same regular file.
|
|
24
|
+
*
|
|
25
|
+
* @param path - Scanned local path and file identity.
|
|
26
|
+
*
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
29
|
+
export declare function validateScannedLocalFile(path: LocalSyncPath): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Reads a previously scanned local file while rejecting symlink swaps and metadata drift.
|
|
32
|
+
*
|
|
33
|
+
* @param path - Scanned local path and file identity.
|
|
34
|
+
*
|
|
35
|
+
* @returns The file bytes.
|
|
36
|
+
*
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
export declare function readScannedLocalFile(path: LocalSyncPath): Promise<Uint8Array>;
|
|
40
|
+
/**
|
|
41
|
+
* Writes bytes under a local sync root after path containment checks.
|
|
42
|
+
*
|
|
43
|
+
* @param root - Local sync root.
|
|
44
|
+
* @param relPath - Destination path relative to the root.
|
|
45
|
+
* @param data - Bytes to write.
|
|
46
|
+
*
|
|
47
|
+
* @internal
|
|
48
|
+
*/
|
|
49
|
+
export declare function writeLocalFileInsideRoot(root: string, relPath: string, data: Uint8Array): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Streams a B2 download under a local sync root with path, timeout, and size checks.
|
|
52
|
+
*
|
|
53
|
+
* @param root - Local sync root.
|
|
54
|
+
* @param relPath - Destination path relative to the root.
|
|
55
|
+
* @param body - Download body stream.
|
|
56
|
+
* @param options - Expected byte count, idle timeout, and optional abort signal.
|
|
57
|
+
*
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
60
|
+
export declare function writeLocalStreamInsideRoot(root: string, relPath: string, body: ReadableStream<Uint8Array>, options: {
|
|
61
|
+
readonly expectedBytes: number;
|
|
62
|
+
readonly expectedDestination?: LocalSyncPath | null;
|
|
63
|
+
readonly idleTimeoutMillis: number;
|
|
64
|
+
readonly signal?: AbortSignal;
|
|
65
|
+
}): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Deletes a scanned local file under a sync root without re-resolving attacker-controlled parents.
|
|
68
|
+
*
|
|
69
|
+
* @param root - Local sync root.
|
|
70
|
+
* @param scannedPath - Previously scanned local file metadata.
|
|
71
|
+
*
|
|
72
|
+
* @internal
|
|
73
|
+
*/
|
|
74
|
+
export declare function deleteLocalFileInsideRoot(root: string, scannedPath: LocalSyncPath): Promise<void>;
|
|
75
|
+
//# sourceMappingURL=local-file-io.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-file-io.d.ts","sourceRoot":"","sources":["../../src/sync/local-file-io.js"],"names":[],"mappings":"AAEA,OAAO,EAGL,+BAA+B,EAEhC,MAAM,uBAAuB,CAAA;AAU9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,KAAK,UAAU,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAAA;AACnD,KAAK,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAA;AAEzD,OAAO,EAAE,+BAA+B,EAAE,CAAA;AAE1C,gBAAgB;AAChB,eAAO,MAAM,oBAAoB,EAAE;IACjC,6BAA6B,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACtE,yBAAyB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAClE,oBAAoB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACvF,qBAAqB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAC9D,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAC1D,2BAA2B,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACpE,uBAAuB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAChE,wBAAwB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACjE,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,kBAAkB,CAAC,EAAE,YAAY,CAAA;CAC7B,CAAA;AAeN;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAGjF;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CAWnF;AA6BD;;;;;;;;GAQG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;;;;;;;;GASG;AACH,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,EAChC,OAAO,EAAE;IACP,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,mBAAmB,CAAC,EAAE,aAAa,GAAG,IAAI,CAAA;IACnD,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAA;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAC9B,GACA,OAAO,CAAC,IAAI,CAAC,CAuNf;AA2JD;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,aAAa,GACzB,OAAO,CAAC,IAAI,CAAC,CAoGf"}
|