swarm-deploy 0.1.0 → 0.3.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 +60 -0
- package/README.md +780 -50
- package/RELEASING.md +2 -2
- package/SECURITY.md +2 -3
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +182 -25
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +32 -27
- package/dist/client.js +103 -54
- package/dist/client.js.map +1 -1
- package/dist/errors.d.ts +6 -0
- package/dist/errors.js +6 -0
- package/dist/errors.js.map +1 -1
- package/dist/files.d.ts +13 -28
- package/dist/files.js +13 -78
- package/dist/files.js.map +1 -1
- package/dist/hooks-module.d.ts +9 -0
- package/dist/hooks-module.js +118 -0
- package/dist/hooks-module.js.map +1 -0
- package/dist/hooks.d.ts +69 -0
- package/dist/hooks.js +88 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +8 -4
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/release.d.ts +26 -0
- package/dist/release.js +419 -0
- package/dist/release.js.map +1 -0
- package/dist/server.d.ts +97 -0
- package/dist/server.js +527 -53
- package/dist/server.js.map +1 -1
- package/dist/storage/commit-journal.d.ts +39 -2
- package/dist/storage/commit-journal.js +140 -2
- package/dist/storage/commit-journal.js.map +1 -1
- package/dist/storage/commit-store.d.ts +69 -8
- package/dist/storage/commit-store.js +374 -22
- package/dist/storage/commit-store.js.map +1 -1
- package/dist/storage/layout.js +7 -1
- package/dist/storage/layout.js.map +1 -1
- package/dist/storage/link-store.d.ts +88 -0
- package/dist/storage/link-store.js +448 -0
- package/dist/storage/link-store.js.map +1 -0
- package/dist/storage/recovery.d.ts +2 -1
- package/dist/storage/recovery.js +8 -1
- package/dist/storage/recovery.js.map +1 -1
- package/dist/storage/retention.d.ts +41 -21
- package/dist/storage/retention.js +162 -8
- package/dist/storage/retention.js.map +1 -1
- package/dist/storage/tar-session-store.d.ts +36 -5
- package/dist/storage/tar-session-store.js +283 -55
- package/dist/storage/tar-session-store.js.map +1 -1
- package/dist/storage/tree-fs.d.ts +44 -0
- package/dist/storage/tree-fs.js +580 -0
- package/dist/storage/tree-fs.js.map +1 -0
- package/dist/storage/tree-staging.d.ts +9 -0
- package/dist/storage/tree-staging.js +64 -0
- package/dist/storage/tree-staging.js.map +1 -0
- package/dist/storage/types.d.ts +15 -0
- package/dist/symlinks.d.ts +44 -0
- package/dist/symlinks.js +153 -0
- package/dist/symlinks.js.map +1 -0
- package/dist/tar-protocol/controls.d.ts +52 -0
- package/dist/tar-protocol/controls.js +160 -2
- package/dist/tar-protocol/controls.js.map +1 -1
- package/dist/tar-protocol/direct-wire.d.ts +8 -3
- package/dist/tar-protocol/direct-wire.js +14 -3
- package/dist/tar-protocol/direct-wire.js.map +1 -1
- package/dist/tar-protocol/manifest.d.ts +13 -1
- package/dist/tar-protocol/manifest.js +26 -1
- package/dist/tar-protocol/manifest.js.map +1 -1
- package/dist/tar-protocol/tree-extract.d.ts +37 -0
- package/dist/tar-protocol/tree-extract.js +240 -0
- package/dist/tar-protocol/tree-extract.js.map +1 -0
- package/dist/tar-protocol/tree-manifest.d.ts +45 -0
- package/dist/tar-protocol/tree-manifest.js +277 -0
- package/dist/tar-protocol/tree-manifest.js.map +1 -0
- package/dist/tar-protocol/tree-path.d.ts +15 -0
- package/dist/tar-protocol/tree-path.js +68 -0
- package/dist/tar-protocol/tree-path.js.map +1 -0
- package/dist/tar-protocol/tree.d.ts +68 -0
- package/dist/tar-protocol/tree.js +269 -0
- package/dist/tar-protocol/tree.js.map +1 -0
- package/dist/tar-protocol/ustar.d.ts +14 -0
- package/dist/tar-protocol/ustar.js +81 -1
- package/dist/tar-protocol/ustar.js.map +1 -1
- package/dist/types.d.ts +3 -0
- package/package.json +3 -1
|
@@ -0,0 +1,580 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.assertSymlinkCapable = assertSymlinkCapable;
|
|
7
|
+
exports.createTreeRoot = createTreeRoot;
|
|
8
|
+
exports.createTreeSubdirectory = createTreeSubdirectory;
|
|
9
|
+
exports.openTreeFile = openTreeFile;
|
|
10
|
+
exports.syncTreeDirectories = syncTreeDirectories;
|
|
11
|
+
exports.walkTree = walkTree;
|
|
12
|
+
exports.digestTree = digestTree;
|
|
13
|
+
exports.inspectTreePath = inspectTreePath;
|
|
14
|
+
exports.removeTree = removeTree;
|
|
15
|
+
/**
|
|
16
|
+
* Safe recursive tree primitives over a {@link StorageAdapter}.
|
|
17
|
+
*
|
|
18
|
+
* Guarantees, stated precisely:
|
|
19
|
+
*
|
|
20
|
+
* - Containment is absolute. A tree root must be a normalized absolute path that
|
|
21
|
+
* is a valid, direct child of its managed parent and is never a protected
|
|
22
|
+
* layout directory. Tree-relative paths are validated component by component,
|
|
23
|
+
* so no traversal, absolute path, or separator ever reaches the adapter.
|
|
24
|
+
* - Symbolic links, hard links, special files, and directory cycles are rejected
|
|
25
|
+
* or never followed: members are classified with `lstat`, file opens use
|
|
26
|
+
* `O_NOFOLLOW`, and removal unlinks links instead of traversing them.
|
|
27
|
+
* - Concurrent replacement of a directory is **detected, not prevented**. The
|
|
28
|
+
* adapter is path-based (there is no `openat`), so a local actor swapping a
|
|
29
|
+
* directory between a check and the following call cannot be excluded. Every
|
|
30
|
+
* operation therefore captures the identity (`dev:ino`) of each ancestor it
|
|
31
|
+
* relies on, verifies the whole chain immediately before and after each
|
|
32
|
+
* mutating call, and fails closed when any identity changed. A mutation that
|
|
33
|
+
* lands inside that unavoidable window is reported, not silently accepted.
|
|
34
|
+
* Local actors remain outside the threat model; remote input can only reach
|
|
35
|
+
* these functions through validated relative paths.
|
|
36
|
+
*/
|
|
37
|
+
const b4a_1 = __importDefault(require("b4a"));
|
|
38
|
+
const error_code_js_1 = require("../error-code.js");
|
|
39
|
+
const _path_1 = __importDefault(require("#path"));
|
|
40
|
+
const errors_js_1 = require("../errors.js");
|
|
41
|
+
const files_js_1 = require("../files.js");
|
|
42
|
+
const hash_js_1 = require("../tar-protocol/hash.js");
|
|
43
|
+
const tree_js_1 = require("../tar-protocol/tree.js");
|
|
44
|
+
const layout_js_1 = require("./layout.js");
|
|
45
|
+
const READ_BYTES = 64 * 1024;
|
|
46
|
+
const INTERNAL_NAME = '.swarm-deploy';
|
|
47
|
+
function treeError(code, message, cause = null) {
|
|
48
|
+
return new errors_js_1.SwarmDeployError(code, message, cause);
|
|
49
|
+
}
|
|
50
|
+
/** Keeps a stable coded error as is and wraps anything else, keeping it as the cause. */
|
|
51
|
+
function coded(error, code, message) {
|
|
52
|
+
return error instanceof errors_js_1.SwarmDeployError ? error : treeError(code, message, error);
|
|
53
|
+
}
|
|
54
|
+
function assertSymlinkCapable(storage) {
|
|
55
|
+
if (typeof storage.symlink !== 'function' || typeof storage.readlink !== 'function') {
|
|
56
|
+
throw treeError(errors_js_1.ERRORS.UNSUPPORTED_STORAGE, 'Storage adapter does not support symbolic links');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
// Containment
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
function assertNormalizedAbsolute(value, label) {
|
|
63
|
+
if (typeof value !== 'string' ||
|
|
64
|
+
value.length === 0 ||
|
|
65
|
+
value.includes('\u0000') ||
|
|
66
|
+
!_path_1.default.isAbsolute(value) ||
|
|
67
|
+
_path_1.default.resolve(value) !== value) {
|
|
68
|
+
throw treeError(errors_js_1.ERRORS.PROTOCOL_INVALID, `Tree ${label} must be a normalized absolute path`);
|
|
69
|
+
}
|
|
70
|
+
return value;
|
|
71
|
+
}
|
|
72
|
+
function isProtectedPath(target, options) {
|
|
73
|
+
if (_path_1.default.basename(target) === INTERNAL_NAME)
|
|
74
|
+
return true;
|
|
75
|
+
if (_path_1.default.basename(_path_1.default.dirname(target)) === INTERNAL_NAME)
|
|
76
|
+
return true;
|
|
77
|
+
const { layout } = options;
|
|
78
|
+
if (!layout)
|
|
79
|
+
return false;
|
|
80
|
+
if ([...(0, layout_js_1.protectedDirectories)(layout), layout.lock].includes(target))
|
|
81
|
+
return true;
|
|
82
|
+
// Never address an ancestor of the storage root: that would contain everything.
|
|
83
|
+
const prefix = target.endsWith(_path_1.default.sep) ? target : `${target}${_path_1.default.sep}`;
|
|
84
|
+
return layout.root === target || layout.root.startsWith(prefix);
|
|
85
|
+
}
|
|
86
|
+
/** A mutable tree root: normalized, absolute, and not itself a protected directory. */
|
|
87
|
+
function assertTreeRoot(treePath, options) {
|
|
88
|
+
const root = assertNormalizedAbsolute(treePath, 'root');
|
|
89
|
+
if (isProtectedPath(root, options)) {
|
|
90
|
+
throw treeError(errors_js_1.ERRORS.PROTOCOL_INVALID, 'Tree root is a protected storage directory');
|
|
91
|
+
}
|
|
92
|
+
return root;
|
|
93
|
+
}
|
|
94
|
+
/** `treePath` must be a valid direct child of `parent`, and neither may be protected. */
|
|
95
|
+
function assertManagedChild(treePath, parent, options) {
|
|
96
|
+
const child = assertNormalizedAbsolute(treePath, 'root');
|
|
97
|
+
const managedParent = assertNormalizedAbsolute(parent, 'parent');
|
|
98
|
+
if (child === managedParent) {
|
|
99
|
+
throw treeError(errors_js_1.ERRORS.PROTOCOL_INVALID, 'Tree root cannot be its managed parent');
|
|
100
|
+
}
|
|
101
|
+
if (isProtectedPath(child, options)) {
|
|
102
|
+
throw treeError(errors_js_1.ERRORS.PROTOCOL_INVALID, 'Tree root is a protected storage directory');
|
|
103
|
+
}
|
|
104
|
+
if (_path_1.default.dirname(child) !== managedParent) {
|
|
105
|
+
throw treeError(errors_js_1.ERRORS.PROTOCOL_INVALID, 'Tree root must be a direct child of its parent');
|
|
106
|
+
}
|
|
107
|
+
(0, files_js_1.validateBasename)(_path_1.default.basename(child));
|
|
108
|
+
return { treePath: child, parent: managedParent };
|
|
109
|
+
}
|
|
110
|
+
// ---------------------------------------------------------------------------
|
|
111
|
+
// Identity anchors
|
|
112
|
+
// ---------------------------------------------------------------------------
|
|
113
|
+
function isIdentityValue(value) {
|
|
114
|
+
return ((typeof value === 'number' && Number.isSafeInteger(value) && value >= 0) ||
|
|
115
|
+
(typeof value === 'bigint' && value >= 0n));
|
|
116
|
+
}
|
|
117
|
+
function anchorFrom(directory, stat, code) {
|
|
118
|
+
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
119
|
+
throw treeError(code, 'Unsafe tree directory');
|
|
120
|
+
}
|
|
121
|
+
if (!isIdentityValue(stat.dev) || !isIdentityValue(stat.ino)) {
|
|
122
|
+
throw treeError(code, 'Tree directory identity is unavailable');
|
|
123
|
+
}
|
|
124
|
+
return { path: directory, dev: stat.dev, ino: stat.ino };
|
|
125
|
+
}
|
|
126
|
+
async function captureAnchor(directory, storage, code) {
|
|
127
|
+
let stat;
|
|
128
|
+
try {
|
|
129
|
+
stat = await storage.lstat(directory);
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
throw treeError(code, 'Unable to inspect tree directory', error);
|
|
133
|
+
}
|
|
134
|
+
return anchorFrom(directory, stat, code);
|
|
135
|
+
}
|
|
136
|
+
async function verifyAnchors(anchors, storage, code) {
|
|
137
|
+
for (const anchor of anchors) {
|
|
138
|
+
const actual = await captureAnchor(anchor.path, storage, code);
|
|
139
|
+
if (actual.dev !== anchor.dev || actual.ino !== anchor.ino) {
|
|
140
|
+
throw treeError(code, 'Tree directory was replaced during the operation');
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Runs one adapter call between two verifications of every ancestor identity.
|
|
146
|
+
* An error raised by the call itself always wins over a verification failure
|
|
147
|
+
* that follows it, and is kept as the cause of the stable error.
|
|
148
|
+
*/
|
|
149
|
+
async function guarded(anchors, storage, code, message, operation) {
|
|
150
|
+
await verifyAnchors(anchors, storage, code);
|
|
151
|
+
let result;
|
|
152
|
+
try {
|
|
153
|
+
result = await operation();
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
await verifyAnchors(anchors, storage, code).catch(() => { });
|
|
157
|
+
throw coded(error, code, message);
|
|
158
|
+
}
|
|
159
|
+
await verifyAnchors(anchors, storage, code);
|
|
160
|
+
return result;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Like {@link guarded}, for a leaf call whose own target may legitimately vanish.
|
|
164
|
+
* Only an ENOENT raised by the call itself is reported as `missing`, and only
|
|
165
|
+
* after the whole ancestor chain was verified again: if any ancestor, the root,
|
|
166
|
+
* or the managed parent is gone or replaced, verification throws instead.
|
|
167
|
+
*/
|
|
168
|
+
async function guardedLeaf(anchors, storage, code, message, operation) {
|
|
169
|
+
await verifyAnchors(anchors, storage, code);
|
|
170
|
+
let value;
|
|
171
|
+
try {
|
|
172
|
+
value = await operation();
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
if ((0, error_code_js_1.isMissing)(error)) {
|
|
176
|
+
await verifyAnchors(anchors, storage, code);
|
|
177
|
+
return { missing: true };
|
|
178
|
+
}
|
|
179
|
+
await verifyAnchors(anchors, storage, code).catch(() => { });
|
|
180
|
+
throw coded(error, code, message);
|
|
181
|
+
}
|
|
182
|
+
await verifyAnchors(anchors, storage, code);
|
|
183
|
+
return { missing: false, value };
|
|
184
|
+
}
|
|
185
|
+
async function syncDirectory(directory, anchors, storage, code) {
|
|
186
|
+
await guarded(anchors, storage, code, 'Unable to synchronize tree directory', async () => {
|
|
187
|
+
const handle = await storage.open(directory, 'r');
|
|
188
|
+
try {
|
|
189
|
+
await handle.sync();
|
|
190
|
+
}
|
|
191
|
+
finally {
|
|
192
|
+
await handle.close();
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
// ---------------------------------------------------------------------------
|
|
197
|
+
// Creation
|
|
198
|
+
// ---------------------------------------------------------------------------
|
|
199
|
+
/**
|
|
200
|
+
* Validates `relativePath`, then captures the identity of the tree root and of
|
|
201
|
+
* every intermediate directory, rejecting symbolic links and missing members.
|
|
202
|
+
*/
|
|
203
|
+
async function resolveParent(treePath, relativePath, kind, storage, options) {
|
|
204
|
+
const root = assertTreeRoot(treePath, options);
|
|
205
|
+
(0, tree_js_1.assertTreeEntryPath)(relativePath, kind);
|
|
206
|
+
const components = relativePath.split('/');
|
|
207
|
+
const anchors = [await captureAnchor(root, storage, errors_js_1.ERRORS.PROTOCOL_INVALID)];
|
|
208
|
+
let parent = root;
|
|
209
|
+
for (const component of components.slice(0, -1)) {
|
|
210
|
+
parent = _path_1.default.join(parent, component);
|
|
211
|
+
anchors.push(await captureAnchor(parent, storage, errors_js_1.ERRORS.PROTOCOL_INVALID));
|
|
212
|
+
}
|
|
213
|
+
return { anchors, parent, target: _path_1.default.join(parent, components[components.length - 1]) };
|
|
214
|
+
}
|
|
215
|
+
async function createTreeRoot(treePath, parent, storage, options = {}) {
|
|
216
|
+
const managed = assertManagedChild(treePath, parent, options);
|
|
217
|
+
const anchors = [await captureAnchor(managed.parent, storage, errors_js_1.ERRORS.PROTOCOL_INVALID)];
|
|
218
|
+
await guarded(anchors, storage, errors_js_1.ERRORS.PROTOCOL_INVALID, 'Unable to create tree root', () => storage.mkdir(managed.treePath, { mode: 0o700 }));
|
|
219
|
+
await syncDirectory(managed.parent, anchors, storage, errors_js_1.ERRORS.PROTOCOL_INVALID);
|
|
220
|
+
}
|
|
221
|
+
async function createTreeSubdirectory(treePath, relativePath, storage, options = {}) {
|
|
222
|
+
const { anchors, target } = await resolveParent(treePath, relativePath, 'directory', storage, options);
|
|
223
|
+
await guarded(anchors, storage, errors_js_1.ERRORS.PROTOCOL_INVALID, 'Unable to create tree directory', () => storage.mkdir(target, { mode: 0o700 }));
|
|
224
|
+
}
|
|
225
|
+
async function openTreeFile(treePath, relativePath, storage, options = {}) {
|
|
226
|
+
const { anchors, target } = await resolveParent(treePath, relativePath, 'file', storage, options);
|
|
227
|
+
await verifyAnchors(anchors, storage, errors_js_1.ERRORS.PROTOCOL_INVALID);
|
|
228
|
+
let handle;
|
|
229
|
+
try {
|
|
230
|
+
handle = await (0, layout_js_1.openSafeRegularFile)(target, 'create', storage);
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
await verifyAnchors(anchors, storage, errors_js_1.ERRORS.PROTOCOL_INVALID).catch(() => { });
|
|
234
|
+
throw coded(error, errors_js_1.ERRORS.PROTOCOL_INVALID, 'Unable to create tree file');
|
|
235
|
+
}
|
|
236
|
+
try {
|
|
237
|
+
await verifyAnchors(anchors, storage, errors_js_1.ERRORS.PROTOCOL_INVALID);
|
|
238
|
+
}
|
|
239
|
+
catch (error) {
|
|
240
|
+
await handle.close().catch(() => { });
|
|
241
|
+
throw error;
|
|
242
|
+
}
|
|
243
|
+
return handle;
|
|
244
|
+
}
|
|
245
|
+
/** Synchronizes every directory in the tree, deepest first. */
|
|
246
|
+
async function syncTreeDirectories(treePath, storage) {
|
|
247
|
+
const { root, entries } = await walkIdentities(treePath, storage);
|
|
248
|
+
const directories = [root];
|
|
249
|
+
for (const entry of entries) {
|
|
250
|
+
if (entry.kind === 'directory') {
|
|
251
|
+
directories.push({
|
|
252
|
+
path: _path_1.default.join(root.path, ...entry.path.split('/')),
|
|
253
|
+
dev: entry.identity.dev,
|
|
254
|
+
ino: entry.identity.ino
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
for (const directory of directories.reverse()) {
|
|
259
|
+
await syncDirectory(directory.path, [directory], storage, errors_js_1.ERRORS.PROTOCOL_INVALID);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
// ---------------------------------------------------------------------------
|
|
263
|
+
// Walking and digesting
|
|
264
|
+
// ---------------------------------------------------------------------------
|
|
265
|
+
async function walkIdentities(treePath, storage) {
|
|
266
|
+
const code = errors_js_1.ERRORS.PROTOCOL_INVALID;
|
|
267
|
+
const rootPath = assertNormalizedAbsolute(treePath, 'root');
|
|
268
|
+
const root = await captureAnchor(rootPath, storage, code);
|
|
269
|
+
const seen = new Set([`${root.dev}:${root.ino}`]);
|
|
270
|
+
const entries = [];
|
|
271
|
+
const walk = async (chain, prefix) => {
|
|
272
|
+
const directory = chain[chain.length - 1].path;
|
|
273
|
+
const names = await guarded(chain, storage, code, 'Unable to read tree directory', () => storage.readdir(directory));
|
|
274
|
+
names.sort((left, right) => (0, tree_js_1.compareTreePaths)(left, right));
|
|
275
|
+
for (const name of names) {
|
|
276
|
+
const entryPath = prefix === '' ? name : `${prefix}/${name}`;
|
|
277
|
+
const entryAbsolute = _path_1.default.join(directory, name);
|
|
278
|
+
let stat;
|
|
279
|
+
try {
|
|
280
|
+
stat = await storage.lstat(entryAbsolute);
|
|
281
|
+
}
|
|
282
|
+
catch (error) {
|
|
283
|
+
throw treeError(code, 'Unable to inspect tree entry', error);
|
|
284
|
+
}
|
|
285
|
+
const kind = (0, tree_js_1.classifyTreeEntry)(stat);
|
|
286
|
+
(0, tree_js_1.assertTreeEntryPath)(entryPath, kind);
|
|
287
|
+
if (entries.length >= tree_js_1.MAX_TREE_ENTRIES)
|
|
288
|
+
throw treeError(code, 'Tree has too many entries');
|
|
289
|
+
const identity = {
|
|
290
|
+
dev: stat.dev,
|
|
291
|
+
ino: stat.ino,
|
|
292
|
+
size: kind === 'directory' ? 0 : stat.size,
|
|
293
|
+
...(typeof stat.mtimeMs === 'number' ? { mtimeMs: stat.mtimeMs } : {})
|
|
294
|
+
};
|
|
295
|
+
if (kind === 'directory') {
|
|
296
|
+
const key = `${stat.dev}:${stat.ino}`;
|
|
297
|
+
if (seen.has(key)) {
|
|
298
|
+
throw treeError(errors_js_1.ERRORS.INVALID_FILENAME, 'Tree contains a filesystem cycle');
|
|
299
|
+
}
|
|
300
|
+
seen.add(key);
|
|
301
|
+
const child = anchorFrom(entryAbsolute, stat, code);
|
|
302
|
+
entries.push({ kind, path: entryPath, size: 0, identity });
|
|
303
|
+
await walk([...chain, child], entryPath);
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
entries.push({ kind, path: entryPath, size: stat.size, identity });
|
|
307
|
+
}
|
|
308
|
+
await verifyAnchors(chain, storage, code);
|
|
309
|
+
};
|
|
310
|
+
await walk([root], '');
|
|
311
|
+
// Depth-first order is not bytewise order (`a-x` sorts before `a/c`), so the
|
|
312
|
+
// canonical order is established over full paths, as the snapshot does.
|
|
313
|
+
entries.sort((left, right) => (0, tree_js_1.compareTreePaths)(left.path, right.path));
|
|
314
|
+
(0, tree_js_1.assertCanonicalTreeEntries)(entries);
|
|
315
|
+
return { root, entries };
|
|
316
|
+
}
|
|
317
|
+
async function walkTree(treePath, storage) {
|
|
318
|
+
const { entries } = await walkIdentities(treePath, storage);
|
|
319
|
+
return entries.map(({ kind, path: entryPath, size }) => ({ kind, path: entryPath, size }));
|
|
320
|
+
}
|
|
321
|
+
function busy(message, cause = null) {
|
|
322
|
+
return treeError(errors_js_1.ERRORS.FILE_BUSY, message, cause);
|
|
323
|
+
}
|
|
324
|
+
function sameStamp(left, right) {
|
|
325
|
+
return (left.dev === right.dev &&
|
|
326
|
+
left.ino === right.ino &&
|
|
327
|
+
left.size === right.size &&
|
|
328
|
+
(left.mtimeMs === undefined || right.mtimeMs === undefined || left.mtimeMs === right.mtimeMs));
|
|
329
|
+
}
|
|
330
|
+
async function digestTreeFile(filePath, entry, anchors, storage) {
|
|
331
|
+
await verifyAnchors(anchors, storage, errors_js_1.ERRORS.FILE_BUSY);
|
|
332
|
+
let handle;
|
|
333
|
+
try {
|
|
334
|
+
handle = await (0, layout_js_1.openSafeRegularFile)(filePath, 'read', storage);
|
|
335
|
+
}
|
|
336
|
+
catch (error) {
|
|
337
|
+
if ((0, error_code_js_1.isMissing)(error))
|
|
338
|
+
throw busy('Tree file changed during digest', error);
|
|
339
|
+
throw coded(error, errors_js_1.ERRORS.PROTOCOL_INVALID, 'Unable to open tree file');
|
|
340
|
+
}
|
|
341
|
+
let outcome;
|
|
342
|
+
try {
|
|
343
|
+
const before = await handle.stat();
|
|
344
|
+
if (!before.isFile())
|
|
345
|
+
throw busy('Tree file changed during digest');
|
|
346
|
+
if (typeof before.nlink === 'number' && before.nlink > 1) {
|
|
347
|
+
throw treeError(errors_js_1.ERRORS.INVALID_FILENAME, 'Tree entries cannot be hard links');
|
|
348
|
+
}
|
|
349
|
+
if (!sameStamp(entry.identity, before))
|
|
350
|
+
throw busy('Tree file changed during digest');
|
|
351
|
+
const hash = new hash_js_1.SodiumSha256();
|
|
352
|
+
let position = 0;
|
|
353
|
+
while (position < entry.size) {
|
|
354
|
+
const bytes = b4a_1.default.alloc(Math.min(READ_BYTES, entry.size - position));
|
|
355
|
+
let offset = 0;
|
|
356
|
+
while (offset < bytes.byteLength) {
|
|
357
|
+
let read;
|
|
358
|
+
try {
|
|
359
|
+
read = await handle.read(bytes, offset, bytes.byteLength - offset, position + offset);
|
|
360
|
+
}
|
|
361
|
+
catch (error) {
|
|
362
|
+
throw treeError(errors_js_1.ERRORS.PROTOCOL_INVALID, 'Unable to read tree file', error);
|
|
363
|
+
}
|
|
364
|
+
const count = typeof read === 'number' ? read : read.bytesRead;
|
|
365
|
+
if (!Number.isSafeInteger(count) || count <= 0)
|
|
366
|
+
throw busy('Tree file was truncated');
|
|
367
|
+
offset += count;
|
|
368
|
+
}
|
|
369
|
+
hash.update(bytes);
|
|
370
|
+
position += bytes.byteLength;
|
|
371
|
+
}
|
|
372
|
+
const after = await handle.stat();
|
|
373
|
+
if (!after.isFile() || !sameStamp(entry.identity, after)) {
|
|
374
|
+
throw busy('Tree file changed during digest');
|
|
375
|
+
}
|
|
376
|
+
outcome = hash.digest();
|
|
377
|
+
}
|
|
378
|
+
catch (error) {
|
|
379
|
+
await handle.close().catch(() => { });
|
|
380
|
+
throw coded(error, errors_js_1.ERRORS.PROTOCOL_INVALID, 'Unable to digest tree file');
|
|
381
|
+
}
|
|
382
|
+
try {
|
|
383
|
+
await handle.close();
|
|
384
|
+
}
|
|
385
|
+
catch (error) {
|
|
386
|
+
throw treeError(errors_js_1.ERRORS.PROTOCOL_INVALID, 'Unable to close tree file', error);
|
|
387
|
+
}
|
|
388
|
+
await verifyAnchors(anchors, storage, errors_js_1.ERRORS.FILE_BUSY);
|
|
389
|
+
return outcome;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Recomputes the canonical tree digest from the extracted contents alone, then
|
|
393
|
+
* walks the tree again and requires the same entries and identities, so an
|
|
394
|
+
* addition, removal, or replacement during hashing fails with FILE_BUSY.
|
|
395
|
+
*/
|
|
396
|
+
async function digestTree(treePath, storage) {
|
|
397
|
+
const first = await walkIdentities(treePath, storage);
|
|
398
|
+
const directories = new Map([['', first.root]]);
|
|
399
|
+
for (const entry of first.entries) {
|
|
400
|
+
if (entry.kind === 'directory') {
|
|
401
|
+
directories.set(entry.path, {
|
|
402
|
+
path: _path_1.default.join(first.root.path, ...entry.path.split('/')),
|
|
403
|
+
dev: entry.identity.dev,
|
|
404
|
+
ino: entry.identity.ino
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
const digests = [];
|
|
409
|
+
let payloadBytes = 0;
|
|
410
|
+
for (const entry of first.entries) {
|
|
411
|
+
if (entry.kind === 'directory') {
|
|
412
|
+
digests.push({ entry: { kind: 'directory', path: entry.path, size: 0 } });
|
|
413
|
+
continue;
|
|
414
|
+
}
|
|
415
|
+
const components = entry.path.split('/');
|
|
416
|
+
const anchors = [];
|
|
417
|
+
for (let depth = 0; depth < components.length; depth++) {
|
|
418
|
+
const anchor = directories.get(components.slice(0, depth).join('/'));
|
|
419
|
+
if (!anchor)
|
|
420
|
+
throw treeError(errors_js_1.ERRORS.PROTOCOL_INVALID, 'Tree entry has no parent directory');
|
|
421
|
+
anchors.push(anchor);
|
|
422
|
+
}
|
|
423
|
+
const absolute = _path_1.default.join(first.root.path, ...components);
|
|
424
|
+
const sha256 = await digestTreeFile(absolute, entry, anchors, storage);
|
|
425
|
+
if (payloadBytes > Number.MAX_SAFE_INTEGER - entry.size) {
|
|
426
|
+
throw treeError(errors_js_1.ERRORS.PROTOCOL_INVALID, 'Tree payload exceeds safe integer range');
|
|
427
|
+
}
|
|
428
|
+
payloadBytes += entry.size;
|
|
429
|
+
digests.push({ entry: { kind: 'file', path: entry.path, size: entry.size }, sha256 });
|
|
430
|
+
}
|
|
431
|
+
let second;
|
|
432
|
+
try {
|
|
433
|
+
second = await walkIdentities(treePath, storage);
|
|
434
|
+
}
|
|
435
|
+
catch (error) {
|
|
436
|
+
throw busy('Tree changed during digest', error);
|
|
437
|
+
}
|
|
438
|
+
const unchanged = second.root.dev === first.root.dev &&
|
|
439
|
+
second.root.ino === first.root.ino &&
|
|
440
|
+
second.entries.length === first.entries.length &&
|
|
441
|
+
second.entries.every((entry, index) => {
|
|
442
|
+
const original = first.entries[index];
|
|
443
|
+
return (entry.path === original.path &&
|
|
444
|
+
entry.kind === original.kind &&
|
|
445
|
+
sameStamp(entry.identity, original.identity));
|
|
446
|
+
});
|
|
447
|
+
if (!unchanged)
|
|
448
|
+
throw busy('Tree changed during digest');
|
|
449
|
+
const entries = first.entries.map(({ kind, path: entryPath, size }) => ({
|
|
450
|
+
kind,
|
|
451
|
+
path: entryPath,
|
|
452
|
+
size
|
|
453
|
+
}));
|
|
454
|
+
return {
|
|
455
|
+
entries,
|
|
456
|
+
entryCount: entries.length,
|
|
457
|
+
payloadBytes,
|
|
458
|
+
treeSha256: (0, tree_js_1.treeDigest)(digests)
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
// ---------------------------------------------------------------------------
|
|
462
|
+
// Inspection and removal
|
|
463
|
+
// ---------------------------------------------------------------------------
|
|
464
|
+
async function inspect(treePath, parent, storage, code, options) {
|
|
465
|
+
const managed = assertManagedChild(treePath, parent, options);
|
|
466
|
+
const anchors = [await captureAnchor(managed.parent, storage, code)];
|
|
467
|
+
let stat = null;
|
|
468
|
+
try {
|
|
469
|
+
stat = await guarded(anchors, storage, code, 'Unable to inspect tree path', async () => {
|
|
470
|
+
try {
|
|
471
|
+
return await storage.lstat(managed.treePath);
|
|
472
|
+
}
|
|
473
|
+
catch (error) {
|
|
474
|
+
if ((0, error_code_js_1.isMissing)(error))
|
|
475
|
+
return null;
|
|
476
|
+
throw error;
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
catch (error) {
|
|
481
|
+
throw coded(error, code, 'Unable to inspect tree path');
|
|
482
|
+
}
|
|
483
|
+
if (stat === null)
|
|
484
|
+
return { state: 'MISSING', anchors, tree: null };
|
|
485
|
+
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
486
|
+
return { state: 'UNMANAGED', anchors, tree: null };
|
|
487
|
+
}
|
|
488
|
+
return { state: 'DIRECTORY', anchors, tree: anchorFrom(managed.treePath, stat, code) };
|
|
489
|
+
}
|
|
490
|
+
async function inspectTreePath(treePath, parent, storage, options = {}) {
|
|
491
|
+
return (await inspect(treePath, parent, storage, errors_js_1.ERRORS.PROTOCOL_INVALID, options)).state;
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Removes `treePath` iteratively using only `lstat`, `unlink`, and `rmdir`; it
|
|
495
|
+
* never calls a recursive remove. A symbolic link inside the tree is unlinked,
|
|
496
|
+
* never traversed. Depth and entry count are bounded by the canonical tree
|
|
497
|
+
* limits; exceeding either, or any failure, throws CLEANUP_FAILED and leaves
|
|
498
|
+
* the remaining tree in place as residue. Only the leaf entry a call targets may
|
|
499
|
+
* vanish concurrently (ENOENT), and only after the whole identity chain was
|
|
500
|
+
* verified again; a missing or moved root, directory, or parent is never a
|
|
501
|
+
* vanished member and throws CLEANUP_FAILED. Returns `false` only when the path
|
|
502
|
+
* was already absent; `true` means the original path is gone and the parent
|
|
503
|
+
* still matches its captured identity.
|
|
504
|
+
*
|
|
505
|
+
* Before and after every mutating call the identity of the parent, the tree
|
|
506
|
+
* root, and every directory above the entry is verified; a replaced directory
|
|
507
|
+
* aborts the removal (detected, not prevented — see the module guarantee).
|
|
508
|
+
*/
|
|
509
|
+
async function removeTree(treePath, parent, storage, options = {}) {
|
|
510
|
+
const code = errors_js_1.ERRORS.CLEANUP_FAILED;
|
|
511
|
+
const found = await inspect(treePath, parent, storage, code, options);
|
|
512
|
+
if (found.state === 'MISSING')
|
|
513
|
+
return false;
|
|
514
|
+
if (found.state === 'UNMANAGED' || found.tree === null) {
|
|
515
|
+
throw treeError(errors_js_1.ERRORS.PROTOCOL_INVALID, 'Refusing to remove an unmanaged tree path');
|
|
516
|
+
}
|
|
517
|
+
const [parentAnchor] = found.anchors;
|
|
518
|
+
const rootAnchor = found.tree;
|
|
519
|
+
const stack = [{ anchor: rootAnchor, depth: 0, names: null, index: 0 }];
|
|
520
|
+
// A directory holding the private storage directory is a storage root, never a tree.
|
|
521
|
+
try {
|
|
522
|
+
await storage.lstat(_path_1.default.join(found.tree.path, INTERNAL_NAME));
|
|
523
|
+
throw treeError(errors_js_1.ERRORS.PROTOCOL_INVALID, 'Refusing to remove a storage root');
|
|
524
|
+
}
|
|
525
|
+
catch (error) {
|
|
526
|
+
if (!(0, error_code_js_1.isMissing)(error))
|
|
527
|
+
throw coded(error, code, 'Unable to inspect tree root');
|
|
528
|
+
}
|
|
529
|
+
const chain = () => [parentAnchor, ...stack.map((frame) => frame.anchor)];
|
|
530
|
+
let visited = 0;
|
|
531
|
+
while (stack.length > 0) {
|
|
532
|
+
const frame = stack[stack.length - 1];
|
|
533
|
+
if (frame.names === null) {
|
|
534
|
+
// The directory is part of the verified chain, so a listing that reports
|
|
535
|
+
// it missing is never a vanished member: it fails the removal.
|
|
536
|
+
frame.names = await guarded(chain(), storage, code, 'Unable to read tree directory for removal', () => storage.readdir(frame.anchor.path));
|
|
537
|
+
frame.names.sort();
|
|
538
|
+
}
|
|
539
|
+
if (frame.index < frame.names.length) {
|
|
540
|
+
const child = _path_1.default.join(frame.anchor.path, frame.names[frame.index++]);
|
|
541
|
+
visited++;
|
|
542
|
+
if (visited > tree_js_1.MAX_TREE_ENTRIES) {
|
|
543
|
+
throw treeError(code, 'Tree has too many entries to remove');
|
|
544
|
+
}
|
|
545
|
+
// Only the leaf's own target may vanish, and only while the chain still matches.
|
|
546
|
+
const inspected = await guardedLeaf(chain(), storage, code, 'Unable to inspect tree entry', () => storage.lstat(child));
|
|
547
|
+
if (inspected.missing)
|
|
548
|
+
continue;
|
|
549
|
+
const stat = inspected.value;
|
|
550
|
+
if (!stat.isSymbolicLink() && stat.isDirectory()) {
|
|
551
|
+
if (frame.depth + 1 > tree_js_1.MAX_TREE_DEPTH)
|
|
552
|
+
throw treeError(code, 'Tree is too deep to remove');
|
|
553
|
+
stack.push({
|
|
554
|
+
anchor: anchorFrom(child, stat, code),
|
|
555
|
+
depth: frame.depth + 1,
|
|
556
|
+
names: null,
|
|
557
|
+
index: 0
|
|
558
|
+
});
|
|
559
|
+
continue;
|
|
560
|
+
}
|
|
561
|
+
await guardedLeaf(chain(), storage, code, 'Unable to remove tree entry', () => storage.unlink(child));
|
|
562
|
+
continue;
|
|
563
|
+
}
|
|
564
|
+
// The directory itself disappears with the call, so only its ancestors can
|
|
565
|
+
// be verified afterwards; the directory is verified immediately before. A
|
|
566
|
+
// directory that is already missing here was moved, not removed.
|
|
567
|
+
const ancestors = chain().slice(0, -1);
|
|
568
|
+
await verifyAnchors([...ancestors, frame.anchor], storage, code);
|
|
569
|
+
await guarded(ancestors, storage, code, 'Unable to remove tree directory', () => storage.rmdir(frame.anchor.path));
|
|
570
|
+
stack.pop();
|
|
571
|
+
}
|
|
572
|
+
// `true` is only returned once the original path is observably gone while the
|
|
573
|
+
// managed parent still matches its captured identity.
|
|
574
|
+
const remaining = await guardedLeaf([parentAnchor], storage, code, 'Unable to confirm tree removal', () => storage.lstat(rootAnchor.path));
|
|
575
|
+
if (!remaining.missing)
|
|
576
|
+
throw treeError(code, 'Tree path still exists after removal');
|
|
577
|
+
await syncDirectory(parentAnchor.path, [parentAnchor], storage, code);
|
|
578
|
+
return true;
|
|
579
|
+
}
|
|
580
|
+
//# sourceMappingURL=tree-fs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree-fs.js","sourceRoot":"","sources":["../../src/storage/tree-fs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { TreeExtractionTarget } from '../tar-protocol/tree-extract.js';
|
|
2
|
+
import type { StorageAdapter, StorageLayout } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Writes an extracted tree into `treePath`, which must live directly under
|
|
5
|
+
* `parent`. Every path is created exclusively, with no-follow opens, from
|
|
6
|
+
* validated components only, and every call carries the storage layout so the
|
|
7
|
+
* protected directories are refused by identity.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createTreeStagingTarget(treePath: string, parent: string, storage: StorageAdapter, layout: StorageLayout): TreeExtractionTarget;
|