@ai-ecoverse/slicc-kernel 1.172.2 → 1.173.1
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/README.md +12 -6
- package/dist/index.js.map +1 -1
- package/dist/kernel-worker.js +469 -163
- package/dist/kernel-worker.js.map +4 -4
- package/dist/meta.js +204 -27
- package/dist/meta.js.map +4 -4
- package/dist/node-process-worker.cjs +3 -1
- package/dist/node-process-worker.cjs.map +2 -2
- package/dist/node-process-worker.js +3 -1
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +139 -10
- package/dist/node.js.map +3 -3
- package/dist/process-worker.js +3 -1
- package/dist/process-worker.js.map +2 -2
- package/dist/types/fs/meta-reads.d.ts +41 -0
- package/dist/types/fs/meta.d.ts +12 -1
- package/dist/types/fs/opfs.d.ts +2 -1
- package/dist/types/fs/types.d.ts +4 -0
- package/dist/types/fs/watch.d.ts +3 -0
- package/dist/types/kernel/proc-info.d.ts +4 -0
- package/dist/types/sudo.d.ts +6 -1
- package/package.json +4 -4
package/dist/kernel-worker.js
CHANGED
|
@@ -1,5 +1,149 @@
|
|
|
1
|
+
// src/fs/meta-reads.ts
|
|
2
|
+
var parentOf = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
3
|
+
var within = (path, root) => root === "/" || path === root || path.startsWith(`${root}/`);
|
|
4
|
+
var Invalidations = class {
|
|
5
|
+
seq = 0;
|
|
6
|
+
log = [];
|
|
7
|
+
open = /* @__PURE__ */ new Map();
|
|
8
|
+
start() {
|
|
9
|
+
const at = this.seq;
|
|
10
|
+
this.open.set(at, (this.open.get(at) ?? 0) + 1);
|
|
11
|
+
return at;
|
|
12
|
+
}
|
|
13
|
+
end(at) {
|
|
14
|
+
const left = (this.open.get(at) ?? 1) - 1;
|
|
15
|
+
if (left > 0) this.open.set(at, left);
|
|
16
|
+
else this.open.delete(at);
|
|
17
|
+
const oldest = this.open.keys().next();
|
|
18
|
+
if (oldest.done) this.log.length = 0;
|
|
19
|
+
else while (this.log.length > 0 && this.log[0].at <= oldest.value) this.log.shift();
|
|
20
|
+
}
|
|
21
|
+
note({ paths = [], trees = [] }) {
|
|
22
|
+
this.seq++;
|
|
23
|
+
if (this.open.size > 0) this.log.push({ at: this.seq, paths, trees });
|
|
24
|
+
}
|
|
25
|
+
since(at, hit) {
|
|
26
|
+
for (let i = this.log.length - 1; i >= 0; i--) {
|
|
27
|
+
const noted2 = this.log[i];
|
|
28
|
+
if (noted2.at <= at) return false;
|
|
29
|
+
if (hit(noted2)) return true;
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
entryStale(at, path) {
|
|
34
|
+
return this.since(
|
|
35
|
+
at,
|
|
36
|
+
({ paths, trees }) => paths.includes(path) || trees.some((tree2) => within(path, tree2))
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
listingStale(at, dir) {
|
|
40
|
+
return this.since(
|
|
41
|
+
at,
|
|
42
|
+
({ paths, trees }) => paths.some((path) => path !== "/" && parentOf(path) === dir) || trees.some((tree2) => within(dir, tree2) || tree2 !== "/" && parentOf(tree2) === dir)
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
var META_READS_IN_FLIGHT = 4;
|
|
47
|
+
var BatchedReads = class {
|
|
48
|
+
run;
|
|
49
|
+
invalidations;
|
|
50
|
+
keep;
|
|
51
|
+
queued = {
|
|
52
|
+
entry: /* @__PURE__ */ new Map(),
|
|
53
|
+
links: /* @__PURE__ */ new Map()
|
|
54
|
+
};
|
|
55
|
+
reading = {
|
|
56
|
+
entry: /* @__PURE__ */ new Map(),
|
|
57
|
+
links: /* @__PURE__ */ new Map()
|
|
58
|
+
};
|
|
59
|
+
inFlight = 0;
|
|
60
|
+
constructor(invalidations, run2, keep2) {
|
|
61
|
+
this.invalidations = invalidations;
|
|
62
|
+
this.run = run2;
|
|
63
|
+
this.keep = keep2;
|
|
64
|
+
}
|
|
65
|
+
entries(paths) {
|
|
66
|
+
const wanted = paths.map((path) => [path, this.want("entry", path)]);
|
|
67
|
+
this.pump();
|
|
68
|
+
return Promise.all(wanted.map(([, w]) => w.promise)).then(
|
|
69
|
+
(found) => new Map(wanted.map(([path], i) => [path, found[i]]))
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
links(dir) {
|
|
73
|
+
const wanted = this.want("links", dir);
|
|
74
|
+
this.pump();
|
|
75
|
+
return wanted.promise;
|
|
76
|
+
}
|
|
77
|
+
stale(kind, key, at) {
|
|
78
|
+
return kind === "entry" ? this.invalidations.entryStale(at, key) : this.invalidations.listingStale(at, key);
|
|
79
|
+
}
|
|
80
|
+
want(kind, key) {
|
|
81
|
+
const reading = this.reading[kind].get(key);
|
|
82
|
+
if (reading && !this.stale(kind, key, reading.at)) return reading;
|
|
83
|
+
const queued = this.queued[kind].get(key);
|
|
84
|
+
if (queued) return queued;
|
|
85
|
+
const made2 = Promise.withResolvers();
|
|
86
|
+
made2.promise.catch(() => void 0);
|
|
87
|
+
this.queued[kind].set(key, made2);
|
|
88
|
+
return made2;
|
|
89
|
+
}
|
|
90
|
+
pump() {
|
|
91
|
+
while (this.inFlight < META_READS_IN_FLIGHT && (this.queued.entry.size > 0 || this.queued.links.size > 0)) {
|
|
92
|
+
this.flush();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
flush() {
|
|
96
|
+
const entries = this.queued.entry;
|
|
97
|
+
const links = this.queued.links;
|
|
98
|
+
this.queued.entry = /* @__PURE__ */ new Map();
|
|
99
|
+
this.queued.links = /* @__PURE__ */ new Map();
|
|
100
|
+
const at = this.invalidations.start();
|
|
101
|
+
for (const [kind, taken] of [
|
|
102
|
+
["entry", entries],
|
|
103
|
+
["links", links]
|
|
104
|
+
]) {
|
|
105
|
+
for (const [key, wanted] of taken) {
|
|
106
|
+
wanted.at = at;
|
|
107
|
+
this.reading[kind].set(key, wanted);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
this.inFlight++;
|
|
111
|
+
const settled = (result, error) => {
|
|
112
|
+
this.inFlight--;
|
|
113
|
+
for (const [kind, taken, found] of [
|
|
114
|
+
["entry", entries, result?.entries],
|
|
115
|
+
["links", links, result?.links]
|
|
116
|
+
]) {
|
|
117
|
+
for (const [key, wanted] of taken) {
|
|
118
|
+
if (this.reading[kind].get(key) === wanted) this.reading[kind].delete(key);
|
|
119
|
+
if (!found) {
|
|
120
|
+
wanted.reject(error);
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
const value2 = found.get(key) ?? (kind === "entry" ? null : []);
|
|
124
|
+
if (!this.stale(kind, key, at)) this.keep(kind, key, value2);
|
|
125
|
+
wanted.resolve(value2);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
this.invalidations.end(at);
|
|
129
|
+
this.pump();
|
|
130
|
+
};
|
|
131
|
+
let reading;
|
|
132
|
+
try {
|
|
133
|
+
reading = this.run({ entries: [...entries.keys()], links: [...links.keys()] });
|
|
134
|
+
} catch (error) {
|
|
135
|
+
settled(void 0, error);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
reading.then(
|
|
139
|
+
(result) => settled(result),
|
|
140
|
+
(error) => settled(void 0, error)
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
1
145
|
// src/fs/path-map.ts
|
|
2
|
-
function
|
|
146
|
+
function parentOf2(path) {
|
|
3
147
|
if (path === "/" || path === "") return void 0;
|
|
4
148
|
const at = path.lastIndexOf("/");
|
|
5
149
|
return at <= 0 ? "/" : path.slice(0, at);
|
|
@@ -57,24 +201,24 @@ var PathMap = class {
|
|
|
57
201
|
this.children.clear();
|
|
58
202
|
}
|
|
59
203
|
link(path) {
|
|
60
|
-
for (let child = path, parent =
|
|
204
|
+
for (let child = path, parent = parentOf2(path); parent !== void 0; ) {
|
|
61
205
|
const set3 = this.children.get(parent);
|
|
62
206
|
if (set3?.has(child)) return;
|
|
63
207
|
if (set3) set3.add(child);
|
|
64
208
|
else this.children.set(parent, /* @__PURE__ */ new Set([child]));
|
|
65
209
|
child = parent;
|
|
66
|
-
parent =
|
|
210
|
+
parent = parentOf2(parent);
|
|
67
211
|
}
|
|
68
212
|
}
|
|
69
213
|
prune(path) {
|
|
70
|
-
for (let child = path, parent =
|
|
214
|
+
for (let child = path, parent = parentOf2(path); parent !== void 0; ) {
|
|
71
215
|
if (this.values.has(child) || this.children.has(child)) return;
|
|
72
216
|
const set3 = this.children.get(parent);
|
|
73
217
|
set3?.delete(child);
|
|
74
218
|
if (set3 && set3.size > 0) return;
|
|
75
219
|
this.children.delete(parent);
|
|
76
220
|
child = parent;
|
|
77
|
-
parent =
|
|
221
|
+
parent = parentOf2(parent);
|
|
78
222
|
}
|
|
79
223
|
}
|
|
80
224
|
};
|
|
@@ -83,11 +227,11 @@ var PathMap = class {
|
|
|
83
227
|
var META_DB = "slicc-kernel";
|
|
84
228
|
var META_VERSION = 1;
|
|
85
229
|
var META_STORE = "entries";
|
|
86
|
-
function
|
|
230
|
+
function parentOf3(path) {
|
|
87
231
|
return path.slice(0, path.lastIndexOf("/")) || "/";
|
|
88
232
|
}
|
|
89
233
|
function moved(entry, path) {
|
|
90
|
-
return entry.link === void 0 ? { ...entry, path } : { ...entry, path, dir:
|
|
234
|
+
return entry.link === void 0 ? { ...entry, path } : { ...entry, path, dir: parentOf3(path) };
|
|
91
235
|
}
|
|
92
236
|
function under(path, root) {
|
|
93
237
|
return path === root || path.startsWith(`${root}/`);
|
|
@@ -146,11 +290,21 @@ function settle(transaction, value2) {
|
|
|
146
290
|
}
|
|
147
291
|
var REMOVE_BATCH = 256;
|
|
148
292
|
var REMOVE_WAIT_MS = 5;
|
|
293
|
+
var LISTINGS_KEPT = 4096;
|
|
149
294
|
var IndexedDbMeta = class {
|
|
150
295
|
db;
|
|
151
296
|
cache = new PathMap();
|
|
297
|
+
listings = new PathMap();
|
|
152
298
|
channel;
|
|
153
|
-
|
|
299
|
+
invalidations = new Invalidations();
|
|
300
|
+
reads = new BatchedReads(
|
|
301
|
+
this.invalidations,
|
|
302
|
+
(batch) => this.read(batch),
|
|
303
|
+
(kind, key, value2) => {
|
|
304
|
+
if (kind === "entry") this.cache.set(key, value2);
|
|
305
|
+
else this.keepListing(key, value2);
|
|
306
|
+
}
|
|
307
|
+
);
|
|
154
308
|
listeners = /* @__PURE__ */ new Set();
|
|
155
309
|
listen(listener) {
|
|
156
310
|
this.listeners.add(listener);
|
|
@@ -169,32 +323,56 @@ var IndexedDbMeta = class {
|
|
|
169
323
|
this.drop({ trees: [...trees] });
|
|
170
324
|
}
|
|
171
325
|
drop({ paths = [], trees = [] }) {
|
|
172
|
-
this.
|
|
173
|
-
for (const path of paths)
|
|
174
|
-
|
|
326
|
+
this.invalidations.note({ paths, trees });
|
|
327
|
+
for (const path of paths) {
|
|
328
|
+
this.cache.delete(path);
|
|
329
|
+
if (path !== "/") this.listings.delete(parentOf3(path));
|
|
330
|
+
}
|
|
331
|
+
for (const tree2 of trees) {
|
|
332
|
+
this.cache.deleteTree(tree2);
|
|
333
|
+
this.listings.deleteTree(tree2);
|
|
334
|
+
if (tree2 !== "/") this.listings.delete(parentOf3(tree2));
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
keepListing(dir, links) {
|
|
338
|
+
if (this.listings.size >= LISTINGS_KEPT) this.listings.clear();
|
|
339
|
+
this.listings.set(dir, links);
|
|
340
|
+
}
|
|
341
|
+
async read({ entries, links }) {
|
|
342
|
+
this.settleRemoves();
|
|
343
|
+
const [transaction, store] = this.transaction("readonly");
|
|
344
|
+
const result = { entries: /* @__PURE__ */ new Map(), links: /* @__PURE__ */ new Map() };
|
|
345
|
+
for (const path of entries) {
|
|
346
|
+
const request3 = store.get(path);
|
|
347
|
+
request3.onsuccess = () => void result.entries.set(path, request3.result ?? null);
|
|
348
|
+
}
|
|
349
|
+
if (links.length > 0) {
|
|
350
|
+
const index = store.index("dir");
|
|
351
|
+
for (const dir of links) {
|
|
352
|
+
const request3 = index.getAll(dir);
|
|
353
|
+
request3.onsuccess = () => void result.links.set(dir, request3.result);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
return settle(transaction, () => result);
|
|
175
357
|
}
|
|
176
358
|
changed(invalidation2) {
|
|
177
359
|
this.drop(invalidation2);
|
|
178
360
|
this.channel.postMessage(invalidation2);
|
|
179
361
|
}
|
|
362
|
+
counted = { reads: 0, writes: 0 };
|
|
363
|
+
transactions() {
|
|
364
|
+
return { ...this.counted };
|
|
365
|
+
}
|
|
180
366
|
transaction(mode) {
|
|
367
|
+
if (mode === "readonly") this.counted.reads++;
|
|
368
|
+
else this.counted.writes++;
|
|
181
369
|
const transaction = this.db.transaction(META_STORE, mode);
|
|
182
370
|
return [transaction, transaction.objectStore(META_STORE)];
|
|
183
371
|
}
|
|
184
372
|
async get(paths) {
|
|
185
373
|
const missing6 = paths.filter((path) => !this.cache.has(path));
|
|
186
374
|
if (missing6.length > 0) {
|
|
187
|
-
this.
|
|
188
|
-
const generation = this.generation;
|
|
189
|
-
const [transaction, store] = this.transaction("readonly");
|
|
190
|
-
const found = /* @__PURE__ */ new Map();
|
|
191
|
-
for (const path of missing6) {
|
|
192
|
-
const request3 = store.get(path);
|
|
193
|
-
request3.onsuccess = () => void found.set(path, request3.result ?? null);
|
|
194
|
-
}
|
|
195
|
-
await settle(transaction, () => void 0);
|
|
196
|
-
if (generation === this.generation)
|
|
197
|
-
for (const [path, entry] of found) this.cache.set(path, entry);
|
|
375
|
+
const found = await this.reads.entries(missing6);
|
|
198
376
|
return paths.map(
|
|
199
377
|
(path) => (found.has(path) ? found.get(path) : this.cache.get(path)) ?? void 0
|
|
200
378
|
);
|
|
@@ -276,7 +454,8 @@ var IndexedDbMeta = class {
|
|
|
276
454
|
async removeFile(path) {
|
|
277
455
|
const known = this.cache.get(path);
|
|
278
456
|
if (!known) return this.remove([path]);
|
|
279
|
-
this.
|
|
457
|
+
this.invalidations.note({ paths: [path] });
|
|
458
|
+
if (path !== "/") this.listings.delete(parentOf3(path));
|
|
280
459
|
this.cache.set(path, null);
|
|
281
460
|
this.removing.set(path, JSON.stringify(known));
|
|
282
461
|
if (this.removing.size >= REMOVE_BATCH) return this.flushRemoves();
|
|
@@ -316,10 +495,8 @@ var IndexedDbMeta = class {
|
|
|
316
495
|
return settle(transaction, () => void this.channel.postMessage({ paths }));
|
|
317
496
|
}
|
|
318
497
|
async links(dir) {
|
|
319
|
-
this.
|
|
320
|
-
|
|
321
|
-
const request3 = store.index("dir").getAll(dir);
|
|
322
|
-
return settle(transaction, () => request3.result);
|
|
498
|
+
const known = this.listings.get(dir);
|
|
499
|
+
return [...known ?? await this.reads.links(dir)];
|
|
323
500
|
}
|
|
324
501
|
async under(path) {
|
|
325
502
|
this.settleRemoves();
|
|
@@ -803,14 +980,14 @@ function protectedPrefixes(paths) {
|
|
|
803
980
|
}
|
|
804
981
|
return [...new Set(paths.map((p) => normalizePath(p)))];
|
|
805
982
|
}
|
|
806
|
-
function
|
|
983
|
+
function within2(path, prefix) {
|
|
807
984
|
return prefix === "/" || path === prefix || path.startsWith(`${prefix}/`);
|
|
808
985
|
}
|
|
809
986
|
function isProtected(prefixes2, path) {
|
|
810
|
-
return prefixes2.some((prefix) =>
|
|
987
|
+
return prefixes2.some((prefix) => within2(path, prefix));
|
|
811
988
|
}
|
|
812
989
|
function holdsProtected(prefixes2, path) {
|
|
813
|
-
return prefixes2.some((prefix) =>
|
|
990
|
+
return prefixes2.some((prefix) => within2(prefix, path));
|
|
814
991
|
}
|
|
815
992
|
var MAX_LINKS = 40;
|
|
816
993
|
function partsOf(path) {
|
|
@@ -1537,6 +1714,7 @@ function sidecar(meta) {
|
|
|
1537
1714
|
};
|
|
1538
1715
|
if (meta.absent) ops.absent = meta.absent.bind(meta);
|
|
1539
1716
|
if (meta.forgetTrees) ops.forgetTrees = meta.forgetTrees.bind(meta);
|
|
1717
|
+
if (meta.transactions) ops.transactions = meta.transactions.bind(meta);
|
|
1540
1718
|
const { removeFile } = meta;
|
|
1541
1719
|
if (removeFile)
|
|
1542
1720
|
ops.removeFile = (path) => removeFile.call(meta, path).catch((err) => {
|
|
@@ -1559,7 +1737,7 @@ function missing2(err) {
|
|
|
1559
1737
|
function split(path) {
|
|
1560
1738
|
return path.split("/").filter(Boolean);
|
|
1561
1739
|
}
|
|
1562
|
-
function
|
|
1740
|
+
function parentOf4(path) {
|
|
1563
1741
|
return path.slice(0, path.lastIndexOf("/")) || "/";
|
|
1564
1742
|
}
|
|
1565
1743
|
function baseOf(path) {
|
|
@@ -1569,7 +1747,7 @@ function prefixes(path) {
|
|
|
1569
1747
|
const parts2 = split(path);
|
|
1570
1748
|
return parts2.map((_, i) => `/${parts2.slice(0, i + 1).join("/")}`);
|
|
1571
1749
|
}
|
|
1572
|
-
function
|
|
1750
|
+
function within3(path, root) {
|
|
1573
1751
|
return path === root || path.startsWith(`${root}/`);
|
|
1574
1752
|
}
|
|
1575
1753
|
var unstored = () => Object.assign(new Error("the file system kept fewer bytes than were written"), {
|
|
@@ -1931,7 +2109,7 @@ var OpfsFs = class {
|
|
|
1931
2109
|
async ownerAt(path, entry) {
|
|
1932
2110
|
const own = ownOf(entry);
|
|
1933
2111
|
if (own) return own;
|
|
1934
|
-
return path === "/" ? { ...ROOT_OWNER } : this.handedTo(
|
|
2112
|
+
return path === "/" ? { ...ROOT_OWNER } : this.handedTo(parentOf4(path));
|
|
1935
2113
|
}
|
|
1936
2114
|
async owned(stat, path, entry) {
|
|
1937
2115
|
return this.owners ? { ...stat, ...await this.ownerAt(path, entry) } : stat;
|
|
@@ -2026,7 +2204,7 @@ var OpfsFs = class {
|
|
|
2026
2204
|
async chown(path, change) {
|
|
2027
2205
|
if (!this.owners) return;
|
|
2028
2206
|
if (change.kind === "new") {
|
|
2029
|
-
const at = resolvePath((await this.locate(
|
|
2207
|
+
const at = resolvePath((await this.locate(parentOf4(path), true)).path, baseOf(path));
|
|
2030
2208
|
this.refuse(at);
|
|
2031
2209
|
const { uid = 0, gid = 0, mode } = change;
|
|
2032
2210
|
return this.stampNew(at, { uid, gid, ...mode !== void 0 ? { mode } : {} }, false);
|
|
@@ -2107,6 +2285,9 @@ var OpfsFs = class {
|
|
|
2107
2285
|
opfsOps() {
|
|
2108
2286
|
return this.calls + this.others;
|
|
2109
2287
|
}
|
|
2288
|
+
metaTransactions() {
|
|
2289
|
+
return this.meta.transactions?.();
|
|
2290
|
+
}
|
|
2110
2291
|
io(request3) {
|
|
2111
2292
|
this.others++;
|
|
2112
2293
|
return request3;
|
|
@@ -2229,7 +2410,7 @@ var OpfsFs = class {
|
|
|
2229
2410
|
for (const entry of await this.meta.get(prefixes(path))) {
|
|
2230
2411
|
if (entry?.link === void 0) continue;
|
|
2231
2412
|
if (entry.path !== path && await this.real(entry.path)) continue;
|
|
2232
|
-
if (await this.real(
|
|
2413
|
+
if (await this.real(parentOf4(entry.path))) return entry;
|
|
2233
2414
|
}
|
|
2234
2415
|
return void 0;
|
|
2235
2416
|
}
|
|
@@ -2261,11 +2442,11 @@ var OpfsFs = class {
|
|
|
2261
2442
|
if (this.rejectLinks) throw fsError("ELOOP", path);
|
|
2262
2443
|
const target = `${link2.link}${current.slice(link2.path.length)}`;
|
|
2263
2444
|
if (target.split("/").includes("..")) {
|
|
2264
|
-
const resolved2 = await this.physical(
|
|
2445
|
+
const resolved2 = await this.physical(parentOf4(link2.path), target, hops + 1, path);
|
|
2265
2446
|
current = resolved2.path;
|
|
2266
2447
|
hops = resolved2.hops - 1;
|
|
2267
2448
|
} else {
|
|
2268
|
-
current = resolvePath(
|
|
2449
|
+
current = resolvePath(parentOf4(link2.path), target);
|
|
2269
2450
|
}
|
|
2270
2451
|
this.crossing(path, current);
|
|
2271
2452
|
}
|
|
@@ -2356,11 +2537,11 @@ var OpfsFs = class {
|
|
|
2356
2537
|
movePending(from, to) {
|
|
2357
2538
|
if (to !== void 0) {
|
|
2358
2539
|
for (const path of [...this.fileTimes.keys()]) {
|
|
2359
|
-
if (
|
|
2540
|
+
if (within3(path, to)) this.fileTimes.delete(path);
|
|
2360
2541
|
}
|
|
2361
2542
|
}
|
|
2362
2543
|
for (const [path, ms] of [...this.fileTimes]) {
|
|
2363
|
-
if (!
|
|
2544
|
+
if (!within3(path, from)) continue;
|
|
2364
2545
|
this.fileTimes.delete(path);
|
|
2365
2546
|
if (to !== void 0) this.fileTimes.set(to + path.slice(from.length), ms);
|
|
2366
2547
|
}
|
|
@@ -2637,8 +2818,8 @@ var OpfsFs = class {
|
|
|
2637
2818
|
const file = this.movingFiles.get(at);
|
|
2638
2819
|
if (file !== void 0) return { done: file, away: true };
|
|
2639
2820
|
for (const m of this.renamingDirs) {
|
|
2640
|
-
if (
|
|
2641
|
-
if (
|
|
2821
|
+
if (within3(at, m.from)) return { done: m.done, away: true };
|
|
2822
|
+
if (within3(at, m.to)) return { done: m.done, away: false };
|
|
2642
2823
|
}
|
|
2643
2824
|
return void 0;
|
|
2644
2825
|
}
|
|
@@ -2674,7 +2855,7 @@ var OpfsFs = class {
|
|
|
2674
2855
|
idle2.resolve();
|
|
2675
2856
|
}
|
|
2676
2857
|
async writesDrained(tree2) {
|
|
2677
|
-
while ([...this.fileWrites.keys()].some((at) =>
|
|
2858
|
+
while ([...this.fileWrites.keys()].some((at) => within3(at, tree2))) {
|
|
2678
2859
|
this.writesIdle ??= Promise.withResolvers();
|
|
2679
2860
|
await this.writesIdle.promise;
|
|
2680
2861
|
}
|
|
@@ -2790,8 +2971,8 @@ var OpfsFs = class {
|
|
|
2790
2971
|
if (!missing2(err)) throw err;
|
|
2791
2972
|
}
|
|
2792
2973
|
const [entry] = await this.meta.get([path]);
|
|
2793
|
-
const wanted = entry?.link === void 0 ? path : resolvePath(
|
|
2794
|
-
return [resolvePath((await this.locate(
|
|
2974
|
+
const wanted = entry?.link === void 0 ? path : resolvePath(parentOf4(path), entry.link);
|
|
2975
|
+
return [resolvePath((await this.locate(parentOf4(wanted), true)).path, baseOf(wanted)), false];
|
|
2795
2976
|
}
|
|
2796
2977
|
async fileFor(path, create = true) {
|
|
2797
2978
|
const [target, existed] = await this.writeTarget(path);
|
|
@@ -2806,7 +2987,7 @@ var OpfsFs = class {
|
|
|
2806
2987
|
dir,
|
|
2807
2988
|
(parent) => this.io(parent.getFileHandle(name2, { create }))
|
|
2808
2989
|
);
|
|
2809
|
-
if (!existed) this.touch(Date.now(),
|
|
2990
|
+
if (!existed) this.touch(Date.now(), parentOf4(target));
|
|
2810
2991
|
return [handle, existed, target];
|
|
2811
2992
|
} catch (err) {
|
|
2812
2993
|
const code = err?.name === "TypeMismatchError" ? "EISDIR" : null;
|
|
@@ -2895,8 +3076,8 @@ var OpfsFs = class {
|
|
|
2895
3076
|
gid: owner.gid,
|
|
2896
3077
|
...mode !== void 0 ? { mode, parents: mode } : {}
|
|
2897
3078
|
};
|
|
2898
|
-
await this.mkdir(
|
|
2899
|
-
const parent = await this.locate(
|
|
3079
|
+
await this.mkdir(parentOf4(path), { recursive: true, ...above ? { owner: above } : {} });
|
|
3080
|
+
const parent = await this.locate(parentOf4(path), true);
|
|
2900
3081
|
if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
|
|
2901
3082
|
this.refuse(resolvePath(parent.path, baseOf(path)));
|
|
2902
3083
|
await this.io(parent.handle.getDirectoryHandle(baseOf(path), { create: true }));
|
|
@@ -2907,7 +3088,7 @@ var OpfsFs = class {
|
|
|
2907
3088
|
}
|
|
2908
3089
|
async mkdirExcl(path, owner) {
|
|
2909
3090
|
if (normalizePath(path) === "/") throw fsError("EEXIST", path);
|
|
2910
|
-
const parent = await this.locate(
|
|
3091
|
+
const parent = await this.locate(parentOf4(path), true);
|
|
2911
3092
|
if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
|
|
2912
3093
|
const dir = parent.handle;
|
|
2913
3094
|
const name2 = baseOf(path);
|
|
@@ -2929,7 +3110,7 @@ var OpfsFs = class {
|
|
|
2929
3110
|
}
|
|
2930
3111
|
async createExclusive(path, owner) {
|
|
2931
3112
|
if (normalizePath(path) === "/") throw fsError("EEXIST", path);
|
|
2932
|
-
const parent = await this.locate(
|
|
3113
|
+
const parent = await this.locate(parentOf4(path), true);
|
|
2933
3114
|
if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
|
|
2934
3115
|
const dir = parent.handle;
|
|
2935
3116
|
const name2 = baseOf(path);
|
|
@@ -2991,12 +3172,12 @@ var OpfsFs = class {
|
|
|
2991
3172
|
else this.forget(found.path);
|
|
2992
3173
|
this.movePending(found.path);
|
|
2993
3174
|
if (file && this.meta.absent?.(found.path)) {
|
|
2994
|
-
this.touch(now,
|
|
3175
|
+
this.touch(now, parentOf4(found.path));
|
|
2995
3176
|
return;
|
|
2996
3177
|
}
|
|
2997
3178
|
if (file && this.meta.removeFile) {
|
|
2998
3179
|
await this.meta.removeFile(found.path);
|
|
2999
|
-
this.touch(now,
|
|
3180
|
+
this.touch(now, parentOf4(found.path));
|
|
3000
3181
|
return;
|
|
3001
3182
|
}
|
|
3002
3183
|
}
|
|
@@ -3004,14 +3185,14 @@ var OpfsFs = class {
|
|
|
3004
3185
|
[found.path],
|
|
3005
3186
|
found.handle?.kind === "directory" ? vacatedAt(found.path) : void 0
|
|
3006
3187
|
);
|
|
3007
|
-
this.touch(Date.now(),
|
|
3188
|
+
this.touch(Date.now(), parentOf4(found.path));
|
|
3008
3189
|
}
|
|
3009
3190
|
links() {
|
|
3010
3191
|
return false;
|
|
3011
3192
|
}
|
|
3012
3193
|
async link(from, to, follow2) {
|
|
3013
3194
|
await (follow2 ? this.stat(from) : this.lstat(from));
|
|
3014
|
-
if (!(await this.stat(
|
|
3195
|
+
if (!(await this.stat(parentOf4(to))).isDirectory) throw fsError("ENOTDIR", to);
|
|
3015
3196
|
const taken = await this.exactly(() => this.lstat(to)).then(
|
|
3016
3197
|
() => true,
|
|
3017
3198
|
(err) => {
|
|
@@ -3038,14 +3219,14 @@ var OpfsFs = class {
|
|
|
3038
3219
|
const source = await this.locate(from, false);
|
|
3039
3220
|
this.refuse(source.path, true);
|
|
3040
3221
|
this.forget(source.path);
|
|
3041
|
-
const parent = await this.locate(
|
|
3222
|
+
const parent = await this.locate(parentOf4(to), true);
|
|
3042
3223
|
const destination = resolvePath(parent.path, baseOf(to));
|
|
3043
3224
|
this.refuse(destination, true);
|
|
3044
3225
|
await this.entering(destination, () => this.moveTo(source, parent, destination, to, call));
|
|
3045
3226
|
}
|
|
3046
3227
|
async moveTo(source, parent, destination, to, call) {
|
|
3047
3228
|
const sourceStat = await this.describe(source);
|
|
3048
|
-
if (sourceStat.isDirectory &&
|
|
3229
|
+
if (sourceStat.isDirectory && within3(destination, source.path)) throw fsError("EINVAL", to);
|
|
3049
3230
|
const target = await this.exactly(() => this.locate(destination, false)).catch((err) => {
|
|
3050
3231
|
if (missing2(err)) return null;
|
|
3051
3232
|
throw err;
|
|
@@ -3072,7 +3253,7 @@ var OpfsFs = class {
|
|
|
3072
3253
|
if (source.link) {
|
|
3073
3254
|
if (target?.handle) await this.rm(destination);
|
|
3074
3255
|
await this.meta.move(source.path, destination, carry, left);
|
|
3075
|
-
this.touch(Date.now(),
|
|
3256
|
+
this.touch(Date.now(), parentOf4(source.path), parent.path);
|
|
3076
3257
|
return;
|
|
3077
3258
|
}
|
|
3078
3259
|
const dir = parent.handle;
|
|
@@ -3121,7 +3302,7 @@ var OpfsFs = class {
|
|
|
3121
3302
|
if (second) await this.meta.update(second, () => void 0);
|
|
3122
3303
|
await this.restamp(destination, copies);
|
|
3123
3304
|
this.changed(source.path, destination);
|
|
3124
|
-
this.touch(Date.now(),
|
|
3305
|
+
this.touch(Date.now(), parentOf4(source.path), parent.path);
|
|
3125
3306
|
};
|
|
3126
3307
|
if (!copying) return sourceStat.isDirectory ? place() : this.movingFile(source.path, place);
|
|
3127
3308
|
const { promise, resolve: resolve2 } = Promise.withResolvers();
|
|
@@ -3318,7 +3499,7 @@ var OpfsFs = class {
|
|
|
3318
3499
|
for (const move of this.peerMoves.values()) {
|
|
3319
3500
|
for (const tree2 of move.trees) {
|
|
3320
3501
|
for (const mine of [from, to]) {
|
|
3321
|
-
if (tree2.some((theirs) =>
|
|
3502
|
+
if (tree2.some((theirs) => within3(mine, theirs) || within3(theirs, mine))) return move;
|
|
3322
3503
|
}
|
|
3323
3504
|
}
|
|
3324
3505
|
}
|
|
@@ -3376,7 +3557,7 @@ var OpfsFs = class {
|
|
|
3376
3557
|
}
|
|
3377
3558
|
async resolvedForms(at) {
|
|
3378
3559
|
if (at === "/") return [];
|
|
3379
|
-
const parent = await PLAIN.realpath.call(this,
|
|
3560
|
+
const parent = await PLAIN.realpath.call(this, parentOf4(at), true).catch(() => parentOf4(at));
|
|
3380
3561
|
const named = resolvePath(parent, baseOf(at));
|
|
3381
3562
|
const target = await PLAIN.realpath.call(this, at, true).catch(() => named);
|
|
3382
3563
|
return [.../* @__PURE__ */ new Set([named, target])].filter((form) => form !== at);
|
|
@@ -3420,7 +3601,7 @@ var OpfsFs = class {
|
|
|
3420
3601
|
try {
|
|
3421
3602
|
if (await this.real(from)) {
|
|
3422
3603
|
const moved2 = await this.locate(from, false);
|
|
3423
|
-
const back = await this.locate(
|
|
3604
|
+
const back = await this.locate(parentOf4(to), true);
|
|
3424
3605
|
await this.copy(
|
|
3425
3606
|
moved2.handle,
|
|
3426
3607
|
back.handle,
|
|
@@ -3474,7 +3655,7 @@ var OpfsFs = class {
|
|
|
3474
3655
|
await PLAIN.rm.call(this, to, { recursive: true });
|
|
3475
3656
|
if (left) {
|
|
3476
3657
|
const source = await this.locate(from, false);
|
|
3477
|
-
const target = await this.locate(
|
|
3658
|
+
const target = await this.locate(parentOf4(to), true);
|
|
3478
3659
|
await this.copy(
|
|
3479
3660
|
source.handle,
|
|
3480
3661
|
target.handle,
|
|
@@ -3516,7 +3697,7 @@ var OpfsFs = class {
|
|
|
3516
3697
|
continue;
|
|
3517
3698
|
}
|
|
3518
3699
|
if (real !== void 0 || at === "/") return;
|
|
3519
|
-
const parent = await this.realpath(
|
|
3700
|
+
const parent = await this.realpath(parentOf4(at), true).catch(() => parentOf4(at));
|
|
3520
3701
|
real = resolvePath(parent, baseOf(at));
|
|
3521
3702
|
if (real === at) return;
|
|
3522
3703
|
}
|
|
@@ -3530,7 +3711,7 @@ var OpfsFs = class {
|
|
|
3530
3711
|
if (source.handle?.kind !== "file") throw fsError("EINVAL", `${from}: not a regular file`);
|
|
3531
3712
|
const [entry] = await this.meta.get([source.path]);
|
|
3532
3713
|
if (entry?.fifo || entry?.socket) throw fsError("EINVAL", `${from}: not a regular file`);
|
|
3533
|
-
const parent = await this.locate(
|
|
3714
|
+
const parent = await this.locate(parentOf4(to), true);
|
|
3534
3715
|
if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", to);
|
|
3535
3716
|
const destination = resolvePath(parent.path, baseOf(to));
|
|
3536
3717
|
if (destination === source.path) throw fsError("EINVAL", `${from}: copied onto itself`);
|
|
@@ -3585,7 +3766,7 @@ var OpfsFs = class {
|
|
|
3585
3766
|
}
|
|
3586
3767
|
renameAt(at) {
|
|
3587
3768
|
for (const m of this.renamingDirs) {
|
|
3588
|
-
if (
|
|
3769
|
+
if (within3(at, m.from) || within3(at, m.to) || at === parentOf4(m.from) || at === parentOf4(m.to))
|
|
3589
3770
|
return m;
|
|
3590
3771
|
}
|
|
3591
3772
|
return void 0;
|
|
@@ -3678,7 +3859,7 @@ var OpfsFs = class {
|
|
|
3678
3859
|
}
|
|
3679
3860
|
}
|
|
3680
3861
|
async symlink(target, path, owner) {
|
|
3681
|
-
const parent = await this.locate(
|
|
3862
|
+
const parent = await this.locate(parentOf4(path), true);
|
|
3682
3863
|
if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
|
|
3683
3864
|
const at = resolvePath(parent.path, baseOf(path));
|
|
3684
3865
|
this.refuse(at);
|
|
@@ -3769,7 +3950,7 @@ var OpfsFs = class {
|
|
|
3769
3950
|
const known = listed.get(dir);
|
|
3770
3951
|
if (known !== void 0) return known;
|
|
3771
3952
|
const listing = (async () => {
|
|
3772
|
-
const above = dir === "/" ? void 0 : await list(
|
|
3953
|
+
const above = dir === "/" ? void 0 : await list(parentOf4(dir));
|
|
3773
3954
|
if (above === null) return null;
|
|
3774
3955
|
const handle = dir === "/" ? this.root : above?.get(baseOf(dir));
|
|
3775
3956
|
if (handle?.kind !== "directory") return void 0;
|
|
@@ -3789,7 +3970,7 @@ var OpfsFs = class {
|
|
|
3789
3970
|
listed.set(dir, listing);
|
|
3790
3971
|
return listing;
|
|
3791
3972
|
};
|
|
3792
|
-
const dirs = [...new Set(paths.filter((p) => split(p).length > 0).map(
|
|
3973
|
+
const dirs = [...new Set(paths.filter((p) => split(p).length > 0).map(parentOf4))];
|
|
3793
3974
|
let next3 = 0;
|
|
3794
3975
|
const lister = async () => {
|
|
3795
3976
|
while (next3 < dirs.length) await list(dirs[next3++]);
|
|
@@ -3797,7 +3978,7 @@ var OpfsFs = class {
|
|
|
3797
3978
|
await Promise.all(Array.from({ length: Math.min(RECONCILE_LISTINGS, dirs.length) }, lister));
|
|
3798
3979
|
return async (path) => {
|
|
3799
3980
|
if (split(path).length === 0) return true;
|
|
3800
|
-
const listing = done5.get(
|
|
3981
|
+
const listing = done5.get(parentOf4(path));
|
|
3801
3982
|
if (listing === null) return this.real(path);
|
|
3802
3983
|
return listing?.has(baseOf(path)) === true;
|
|
3803
3984
|
};
|
|
@@ -3813,10 +3994,10 @@ var OpfsFs = class {
|
|
|
3813
3994
|
const carried = new Set(entries.filter((e) => !e.vacated).map((e) => e.ino));
|
|
3814
3995
|
const checked = entries.filter((e) => !(e.vacated && carried.has(inodeOf(e.path))));
|
|
3815
3996
|
const real = await this.present(
|
|
3816
|
-
checked.flatMap((e) => e.link === void 0 ? [e.path] : [e.path,
|
|
3997
|
+
checked.flatMap((e) => e.link === void 0 ? [e.path] : [e.path, parentOf4(e.path)])
|
|
3817
3998
|
);
|
|
3818
3999
|
for (const entry of checked) {
|
|
3819
|
-
const stale = entry.link === void 0 ? !await real(entry.path) : await real(entry.path) || !await real(
|
|
4000
|
+
const stale = entry.link === void 0 ? !await real(entry.path) : await real(entry.path) || !await real(parentOf4(entry.path));
|
|
3820
4001
|
if (!stale) continue;
|
|
3821
4002
|
const seen = JSON.stringify(entry);
|
|
3822
4003
|
await this.meta.update(
|
|
@@ -3837,7 +4018,7 @@ function nothing() {
|
|
|
3837
4018
|
}
|
|
3838
4019
|
function touches(at, trees, listing = true, removing = false) {
|
|
3839
4020
|
return trees.some(
|
|
3840
|
-
([from, to]) =>
|
|
4021
|
+
([from, to]) => within3(at, from) || within3(at, to) || listing && (at === parentOf4(from) || at === parentOf4(to)) || removing && (at === "/" || within3(from, at) || within3(to, at))
|
|
3841
4022
|
);
|
|
3842
4023
|
}
|
|
3843
4024
|
function byIntent(a, b) {
|
|
@@ -5023,7 +5204,7 @@ function portFacadeHook(ask, gone) {
|
|
|
5023
5204
|
|
|
5024
5205
|
// src/fs/walk.ts
|
|
5025
5206
|
var MAX_LINKS3 = 40;
|
|
5026
|
-
function
|
|
5207
|
+
function parentOf5(path) {
|
|
5027
5208
|
return path.slice(0, path.lastIndexOf("/")) || "/";
|
|
5028
5209
|
}
|
|
5029
5210
|
async function mustBeDir(fs, path) {
|
|
@@ -5041,7 +5222,7 @@ async function realDir(fs, dir, budget = { hops: 0 }) {
|
|
|
5041
5222
|
const part = queue.shift();
|
|
5042
5223
|
if (part === ".") continue;
|
|
5043
5224
|
if (part === "..") {
|
|
5044
|
-
at =
|
|
5225
|
+
at = parentOf5(at);
|
|
5045
5226
|
continue;
|
|
5046
5227
|
}
|
|
5047
5228
|
const next3 = at === "/" ? `/${part}` : `${at}/${part}`;
|
|
@@ -5063,7 +5244,7 @@ function joinName(dir, name2) {
|
|
|
5063
5244
|
}
|
|
5064
5245
|
async function realTarget(fs, path) {
|
|
5065
5246
|
const budget = { hops: 0 };
|
|
5066
|
-
let dir = await realDir(fs,
|
|
5247
|
+
let dir = await realDir(fs, parentOf5(path), budget);
|
|
5067
5248
|
let name2 = path.slice(path.lastIndexOf("/") + 1);
|
|
5068
5249
|
for (; ; ) {
|
|
5069
5250
|
const link2 = await linkOf(fs, joinName(dir, name2));
|
|
@@ -5071,7 +5252,7 @@ async function realTarget(fs, path) {
|
|
|
5071
5252
|
if (budget.hops >= MAX_LINKS3) throw fsError("ELOOP", path);
|
|
5072
5253
|
budget.hops++;
|
|
5073
5254
|
const target = link2.startsWith("/") ? link2 : joinName(dir, link2);
|
|
5074
|
-
dir = await realDir(fs,
|
|
5255
|
+
dir = await realDir(fs, parentOf5(target), budget);
|
|
5075
5256
|
name2 = target.slice(target.lastIndexOf("/") + 1);
|
|
5076
5257
|
}
|
|
5077
5258
|
return joinName(dir, name2);
|
|
@@ -5148,7 +5329,7 @@ async function walk(fs, cred, path, follow2, links) {
|
|
|
5148
5329
|
if (!dir) return { path: joinName(at, [part, ...queue].join("/")), perm: void 0 };
|
|
5149
5330
|
if (!permits(cred, dir, X_OK)) return { path, perm: void 0, denied: at };
|
|
5150
5331
|
if (part === "..") {
|
|
5151
|
-
at =
|
|
5332
|
+
at = parentOf5(at);
|
|
5152
5333
|
continue;
|
|
5153
5334
|
}
|
|
5154
5335
|
const next3 = joinName(at, part);
|
|
@@ -5269,7 +5450,7 @@ function deny(g, op, path, errno3 = "EACCES") {
|
|
|
5269
5450
|
}
|
|
5270
5451
|
var FENCE_HOPS = 40;
|
|
5271
5452
|
async function entryAt(g, path) {
|
|
5272
|
-
const parent =
|
|
5453
|
+
const parent = parentOf5(path);
|
|
5273
5454
|
const real = await g.fs.realpath?.(parent, true).catch(() => void 0);
|
|
5274
5455
|
return real ? joinName(real, path.slice(path.lastIndexOf("/") + 1)) : path;
|
|
5275
5456
|
}
|
|
@@ -5280,7 +5461,7 @@ async function fencedNames(g, path) {
|
|
|
5280
5461
|
names2.push(at);
|
|
5281
5462
|
const link2 = await g.fs.readlink(at).catch(() => void 0);
|
|
5282
5463
|
if (link2 === void 0) break;
|
|
5283
|
-
at = await entryAt(g, normalizePath(g.fs.resolvePath(
|
|
5464
|
+
at = await entryAt(g, normalizePath(g.fs.resolvePath(parentOf5(at), link2)));
|
|
5284
5465
|
}
|
|
5285
5466
|
return names2;
|
|
5286
5467
|
}
|
|
@@ -5331,7 +5512,7 @@ async function unwritable(g, op, path, dir) {
|
|
|
5331
5512
|
}
|
|
5332
5513
|
async function inParent(g, op, path, old = false) {
|
|
5333
5514
|
await fence(g, op, path);
|
|
5334
|
-
const dir = await access(g.fs, g.cred,
|
|
5515
|
+
const dir = await access(g.fs, g.cred, parentOf5(path), W_OK | X_OK, linked(g, DIR));
|
|
5335
5516
|
if (old !== true) {
|
|
5336
5517
|
if (await unwritable(g, op, path, dir)) deny(g, op, path);
|
|
5337
5518
|
else if (old === "replaced" && dir.denied === void 0) await stickyEntry(g, op, path, dir);
|
|
@@ -5343,7 +5524,7 @@ async function inParent(g, op, path, old = false) {
|
|
|
5343
5524
|
if (!lookup2 || await present(g.fs, entryIn(dir, path), false)) deny(g, op, path);
|
|
5344
5525
|
}
|
|
5345
5526
|
async function makeIn(g, op, path, parents = true) {
|
|
5346
|
-
for (let dir =
|
|
5527
|
+
for (let dir = parentOf5(path); ; dir = parentOf5(dir)) {
|
|
5347
5528
|
const walked = await access(g.fs, g.cred, dir, W_OK | X_OK, linked(g, DIR));
|
|
5348
5529
|
if (await unwritable(g, op, path, walked)) {
|
|
5349
5530
|
if (!await present(g.fs, path, true)) deny(g, op, path);
|
|
@@ -5371,7 +5552,7 @@ async function renamable(g, from, to) {
|
|
|
5371
5552
|
if (from === to) return void await need(g, "rename", from, 0, { follow: false });
|
|
5372
5553
|
await inParent(g, "rename", from, true);
|
|
5373
5554
|
await inParent(g, "rename", to, "replaced");
|
|
5374
|
-
if (g.cred.euid === 0 ||
|
|
5555
|
+
if (g.cred.euid === 0 || parentOf5(from) === parentOf5(to)) return;
|
|
5375
5556
|
const st = await g.fs.lstat(from).catch(() => void 0);
|
|
5376
5557
|
if (st?.isDirectory && !permits(g.cred, permOf(st), W_OK)) deny(g, "rename", from);
|
|
5377
5558
|
}
|
|
@@ -5438,7 +5619,7 @@ async function writable(g, op, path) {
|
|
|
5438
5619
|
}
|
|
5439
5620
|
async function creatable(g, op, path) {
|
|
5440
5621
|
const target = await need(g, op, path, 0);
|
|
5441
|
-
if (target.denied === void 0) await need(g, op,
|
|
5622
|
+
if (target.denied === void 0) await need(g, op, parentOf5(target.path), W_OK | X_OK, DIR, path);
|
|
5442
5623
|
}
|
|
5443
5624
|
async function openable(g, op, path, want, create) {
|
|
5444
5625
|
const st = create ? await g.fs.stat(path).catch(() => void 0) : void 0;
|
|
@@ -6194,7 +6375,7 @@ function parsePrefix(text) {
|
|
|
6194
6375
|
if (length2 < 0 || length2 > max) return void 0;
|
|
6195
6376
|
return { ...parsed2, length: length2 };
|
|
6196
6377
|
}
|
|
6197
|
-
function
|
|
6378
|
+
function within4(prefix, addr) {
|
|
6198
6379
|
if (prefix.v6 !== addr.v6) return false;
|
|
6199
6380
|
const shift = BigInt((prefix.v6 ? 128 : 32) - prefix.length);
|
|
6200
6381
|
return addr.bits >> shift === prefix.bits >> shift;
|
|
@@ -6234,9 +6415,9 @@ var Routes = class {
|
|
|
6234
6415
|
if (!addr) return "unreachable";
|
|
6235
6416
|
if (addr.v6 && addr.bits === 1n) return "loopback";
|
|
6236
6417
|
if (!addr.v6 && addr.bits >> 24n === 127n) return "loopback";
|
|
6237
|
-
if (RESERVED.some((p) =>
|
|
6418
|
+
if (RESERVED.some((p) => within4(p, addr))) return "reserved";
|
|
6238
6419
|
if (addr.v6 && !this.ipv6) return "unreachable";
|
|
6239
|
-
if (this.exit || this.table.some((p) =>
|
|
6420
|
+
if (this.exit || this.table.some((p) => within4(p, addr))) return "uplink";
|
|
6240
6421
|
return "unreachable";
|
|
6241
6422
|
}
|
|
6242
6423
|
};
|
|
@@ -8188,7 +8369,7 @@ function hostRegistries(send2, gone, port) {
|
|
|
8188
8369
|
function visibleTo(g, notify) {
|
|
8189
8370
|
if (!g?.dac.enforcing) return notify;
|
|
8190
8371
|
let queue = Promise.resolve();
|
|
8191
|
-
const seen = async (path) => (await access(g.fs, g.cred,
|
|
8372
|
+
const seen = async (path) => (await access(g.fs, g.cred, parentOf5(path), R_OK | X_OK, { directory: true })).denied === void 0;
|
|
8192
8373
|
return (change) => {
|
|
8193
8374
|
queue = queue.then(async () => {
|
|
8194
8375
|
if (!("paths" in change)) return notify(change);
|
|
@@ -8206,7 +8387,7 @@ async function watchOp(l, req, watches, send2, g) {
|
|
|
8206
8387
|
}
|
|
8207
8388
|
if (g) for (const path of req.paths) await readable(g, "watch", l.fs.resolvePath("/", path));
|
|
8208
8389
|
const notify = visibleTo(g, (change) => send2({ watch: req.id, change }));
|
|
8209
|
-
const unwatch = l.watchers.watch(req.paths, { recursive: req.recursive }, notify);
|
|
8390
|
+
const unwatch = l.watchers.watch(req.paths, { recursive: req.recursive, peers: true }, notify);
|
|
8210
8391
|
watches.set(req.id, unwatch);
|
|
8211
8392
|
return { result: req.id };
|
|
8212
8393
|
}
|
|
@@ -8559,7 +8740,7 @@ function satisfies(version, range2) {
|
|
|
8559
8740
|
}
|
|
8560
8741
|
|
|
8561
8742
|
// src/version.ts
|
|
8562
|
-
var KERNEL_VERSION = true ? "1.
|
|
8743
|
+
var KERNEL_VERSION = true ? "1.173.1" : "0.0.0-dev";
|
|
8563
8744
|
var OS_RELEASE = "6.0.0-slicc";
|
|
8564
8745
|
function procVersion() {
|
|
8565
8746
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -9470,7 +9651,7 @@ var PathMarks = class {
|
|
|
9470
9651
|
}
|
|
9471
9652
|
changedSince(path, gen) {
|
|
9472
9653
|
if (gen < this.floor) return true;
|
|
9473
|
-
for (let p = path; this.touched.size > 0; p =
|
|
9654
|
+
for (let p = path; this.touched.size > 0; p = parentOf6(p)) {
|
|
9474
9655
|
if ((this.touched.get(p) ?? 0) > gen) return true;
|
|
9475
9656
|
if (p === "/") return false;
|
|
9476
9657
|
}
|
|
@@ -9505,7 +9686,7 @@ var PathMarks = class {
|
|
|
9505
9686
|
});
|
|
9506
9687
|
}
|
|
9507
9688
|
inFlight(path) {
|
|
9508
|
-
for (let p = path; this.flying.size > 0; p =
|
|
9689
|
+
for (let p = path; this.flying.size > 0; p = parentOf6(p)) {
|
|
9509
9690
|
if (this.flying.has(p)) return true;
|
|
9510
9691
|
if (p === "/") return false;
|
|
9511
9692
|
}
|
|
@@ -9525,9 +9706,9 @@ var LOOKUP_OPS = [
|
|
|
9525
9706
|
"readlink",
|
|
9526
9707
|
"realpath"
|
|
9527
9708
|
];
|
|
9528
|
-
var
|
|
9709
|
+
var within5 = (path, target) => path === target || target === "/" || path.startsWith(`${target}/`);
|
|
9529
9710
|
var TOUCHED_MAX = 4096;
|
|
9530
|
-
var
|
|
9711
|
+
var parentOf6 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
9531
9712
|
var PEER_RM_MS = 1e3;
|
|
9532
9713
|
var SHARED_ACK_MS = 24 * 60 * 60 * 1e3;
|
|
9533
9714
|
var delay = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
@@ -9715,7 +9896,7 @@ var UnlinkedKeeper = class {
|
|
|
9715
9896
|
};
|
|
9716
9897
|
}
|
|
9717
9898
|
async settled(path) {
|
|
9718
|
-
for (let p = path; this.replacing.size > 0; p =
|
|
9899
|
+
for (let p = path; this.replacing.size > 0; p = parentOf6(p)) {
|
|
9719
9900
|
await this.replacing.get(p)?.done;
|
|
9720
9901
|
if (p === "/") return;
|
|
9721
9902
|
}
|
|
@@ -9733,7 +9914,7 @@ var UnlinkedKeeper = class {
|
|
|
9733
9914
|
return this.marks.inFlight(path);
|
|
9734
9915
|
}
|
|
9735
9916
|
missed(path) {
|
|
9736
|
-
for (let p = path; this.replacing.size > 0; p =
|
|
9917
|
+
for (let p = path; this.replacing.size > 0; p = parentOf6(p)) {
|
|
9737
9918
|
if (this.replacing.get(p)?.sealed) return true;
|
|
9738
9919
|
if (p === "/") return false;
|
|
9739
9920
|
}
|
|
@@ -9753,7 +9934,7 @@ var UnlinkedKeeper = class {
|
|
|
9753
9934
|
for (const holder of this.holders) {
|
|
9754
9935
|
if (holder.owns(target)) continue;
|
|
9755
9936
|
for (const path of holder.held()) {
|
|
9756
|
-
if (!
|
|
9937
|
+
if (!within5(path, target) || holder.isKept(path)) continue;
|
|
9757
9938
|
held.set(path, [...held.get(path) ?? [], holder]);
|
|
9758
9939
|
}
|
|
9759
9940
|
}
|
|
@@ -9833,7 +10014,7 @@ var UnlinkedKeeper = class {
|
|
|
9833
10014
|
await this.serial(async () => {
|
|
9834
10015
|
await Promise.allSettled([this.fs.rename(file.hidden, path)]);
|
|
9835
10016
|
this.unlinkedName(file.hidden);
|
|
9836
|
-
await this.tidy(
|
|
10017
|
+
await this.tidy(parentOf6(file.hidden));
|
|
9837
10018
|
});
|
|
9838
10019
|
}
|
|
9839
10020
|
done5();
|
|
@@ -10072,7 +10253,7 @@ var UnlinkedKeeper = class {
|
|
|
10072
10253
|
}
|
|
10073
10254
|
await this.fs.rm(hidden).catch(() => void 0);
|
|
10074
10255
|
this.unlinkedName(hidden);
|
|
10075
|
-
await this.tidy(
|
|
10256
|
+
await this.tidy(parentOf6(hidden));
|
|
10076
10257
|
}
|
|
10077
10258
|
async linkedName(hidden) {
|
|
10078
10259
|
if (!mayLink(this.fs, hidden)) return;
|
|
@@ -11621,7 +11802,7 @@ function devCreation(path, cred) {
|
|
|
11621
11802
|
var HOSTNAME_PATH = "/etc/hostname";
|
|
11622
11803
|
var S_IFREG3 = 32768;
|
|
11623
11804
|
var MAX_HOPS2 = 40;
|
|
11624
|
-
var
|
|
11805
|
+
var parentOf7 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
11625
11806
|
var baseOf2 = (path) => path.slice(path.lastIndexOf("/") + 1);
|
|
11626
11807
|
function missing5(err) {
|
|
11627
11808
|
return err?.code === "ENOENT";
|
|
@@ -11651,7 +11832,7 @@ function linkFollower(fs, files) {
|
|
|
11651
11832
|
);
|
|
11652
11833
|
const viaParent = async (path) => {
|
|
11653
11834
|
if (!bases.has(baseOf2(path)) || !fs.realpath) return path;
|
|
11654
|
-
const parent =
|
|
11835
|
+
const parent = parentOf7(path);
|
|
11655
11836
|
const dir = await fs.realpath(parent, true).catch(() => parent);
|
|
11656
11837
|
return fs.resolvePath(dir, baseOf2(path));
|
|
11657
11838
|
};
|
|
@@ -11660,7 +11841,7 @@ function linkFollower(fs, files) {
|
|
|
11660
11841
|
for (let hop = 0; hop < MAX_HOPS2 && !files.has(current); hop++) {
|
|
11661
11842
|
const link2 = await linkOf2(current);
|
|
11662
11843
|
if (link2 === void 0) return viaParent(current);
|
|
11663
|
-
current = fs.resolvePath(
|
|
11844
|
+
current = fs.resolvePath(parentOf7(current), link2);
|
|
11664
11845
|
}
|
|
11665
11846
|
return current;
|
|
11666
11847
|
};
|
|
@@ -11741,7 +11922,7 @@ var DEFAULT_UMASK = 18;
|
|
|
11741
11922
|
function isModule(bytes) {
|
|
11742
11923
|
return MAGIC.every((b, i) => bytes[i] === b);
|
|
11743
11924
|
}
|
|
11744
|
-
function
|
|
11925
|
+
function within6(path, dir) {
|
|
11745
11926
|
return path.startsWith(dir === "/" ? "/" : `${dir}/`);
|
|
11746
11927
|
}
|
|
11747
11928
|
var FreshModules = class {
|
|
@@ -11765,10 +11946,10 @@ var FreshModules = class {
|
|
|
11765
11946
|
const target = normalizePath(to);
|
|
11766
11947
|
if (source === target) return;
|
|
11767
11948
|
for (const key of [...this.fresh.keys()]) {
|
|
11768
|
-
if (key === target ||
|
|
11949
|
+
if (key === target || within6(key, target)) this.fresh.delete(key);
|
|
11769
11950
|
}
|
|
11770
11951
|
for (const [key, fresh3] of [...this.fresh]) {
|
|
11771
|
-
if (key !== source && !
|
|
11952
|
+
if (key !== source && !within6(key, source)) continue;
|
|
11772
11953
|
this.fresh.delete(key);
|
|
11773
11954
|
this.fresh.set(target + key.slice(source.length), fresh3);
|
|
11774
11955
|
}
|
|
@@ -11810,7 +11991,7 @@ var FreshModules = class {
|
|
|
11810
11991
|
await fs.rm(path, options);
|
|
11811
11992
|
const at = normalizePath(path);
|
|
11812
11993
|
for (const key of [...this.fresh.keys()]) {
|
|
11813
|
-
if (key === at ||
|
|
11994
|
+
if (key === at || within6(key, at)) this.fresh.delete(key);
|
|
11814
11995
|
}
|
|
11815
11996
|
},
|
|
11816
11997
|
rename: async (from, to) => {
|
|
@@ -11915,10 +12096,10 @@ var WATCH_NOTES_LIMIT = 1e3;
|
|
|
11915
12096
|
var baseOf3 = (path) => path.slice(path.lastIndexOf("/") + 1);
|
|
11916
12097
|
var WATCH_BATCH_LIMIT = 1e3;
|
|
11917
12098
|
var under3 = (path, dir) => dir === "/" || path.startsWith(`${dir}/`);
|
|
11918
|
-
var
|
|
12099
|
+
var parentOf8 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
11919
12100
|
function touches2(watcher, changed) {
|
|
11920
12101
|
return watcher.paths.some(
|
|
11921
|
-
(watched) => changed === watched || under3(watched, changed) || (watcher.recursive ? under3(changed, watched) :
|
|
12102
|
+
(watched) => changed === watched || under3(watched, changed) || (watcher.recursive ? under3(changed, watched) : parentOf8(changed) === watched)
|
|
11922
12103
|
);
|
|
11923
12104
|
}
|
|
11924
12105
|
var REALS_KEPT = 4096;
|
|
@@ -11946,7 +12127,7 @@ function routed(watch, root, type, path, seq2) {
|
|
|
11946
12127
|
if (type === "rename") noted(watch, { ended: true, seq: seq2 });
|
|
11947
12128
|
return true;
|
|
11948
12129
|
}
|
|
11949
|
-
if (
|
|
12130
|
+
if (parentOf8(path) === root) noted(watch, { type, filename: baseOf3(path), seq: seq2 });
|
|
11950
12131
|
else if (watch.recursive && under3(path, root)) {
|
|
11951
12132
|
noted(watch, { type, filename: path.slice(root === "/" ? 1 : root.length + 1), seq: seq2 });
|
|
11952
12133
|
} else return false;
|
|
@@ -11978,6 +12159,7 @@ var FsWatchers = class {
|
|
|
11978
12159
|
const watcher = {
|
|
11979
12160
|
paths: paths.map(normalizePath),
|
|
11980
12161
|
recursive: options.recursive === true,
|
|
12162
|
+
peers: options.peers === true,
|
|
11981
12163
|
notify,
|
|
11982
12164
|
pending: /* @__PURE__ */ new Set(),
|
|
11983
12165
|
scheduled: false
|
|
@@ -12031,7 +12213,7 @@ var FsWatchers = class {
|
|
|
12031
12213
|
covers(path) {
|
|
12032
12214
|
for (const watch of this.typed) {
|
|
12033
12215
|
for (const root of watch.roots) {
|
|
12034
|
-
if (path === root ||
|
|
12216
|
+
if (path === root || parentOf8(path) === root || watch.recursive && under3(path, root))
|
|
12035
12217
|
return true;
|
|
12036
12218
|
}
|
|
12037
12219
|
}
|
|
@@ -12099,10 +12281,16 @@ var FsWatchers = class {
|
|
|
12099
12281
|
this.report(paths);
|
|
12100
12282
|
this.emit("change", paths);
|
|
12101
12283
|
}
|
|
12284
|
+
peerChanged(paths) {
|
|
12285
|
+
if (paths.length > 0) this.notify(paths, true);
|
|
12286
|
+
}
|
|
12102
12287
|
report(paths, notify = true) {
|
|
12103
12288
|
for (const tap of this.taps) tap(paths);
|
|
12104
|
-
if (
|
|
12289
|
+
if (notify) this.notify(paths);
|
|
12290
|
+
}
|
|
12291
|
+
notify(paths, peer = false) {
|
|
12105
12292
|
for (const watcher of this.watchers) {
|
|
12293
|
+
if (peer && !watcher.peers) continue;
|
|
12106
12294
|
for (const path of paths) {
|
|
12107
12295
|
const changed = normalizePath(path);
|
|
12108
12296
|
if (touches2(watcher, changed)) watcher.pending.add(changed);
|
|
@@ -13571,7 +13759,7 @@ function linkedTo(mount, path) {
|
|
|
13571
13759
|
return own?.kind !== "directory" && (attr2.nlink ?? 1) > 1;
|
|
13572
13760
|
};
|
|
13573
13761
|
}
|
|
13574
|
-
var
|
|
13762
|
+
var within7 = (path, target) => path === target || target === "/" || path.startsWith(`${target}/`);
|
|
13575
13763
|
var HeldSet = class extends Set {
|
|
13576
13764
|
idle;
|
|
13577
13765
|
moved;
|
|
@@ -13607,7 +13795,7 @@ var HeldSet = class extends Set {
|
|
|
13607
13795
|
}
|
|
13608
13796
|
};
|
|
13609
13797
|
function heldUnder(held, target) {
|
|
13610
|
-
for (const paths of held) for (const path of paths.keys()) if (
|
|
13798
|
+
for (const paths of held) for (const path of paths.keys()) if (within7(path, target)) return true;
|
|
13611
13799
|
return false;
|
|
13612
13800
|
}
|
|
13613
13801
|
var HeldPaths = class extends Map {
|
|
@@ -13648,7 +13836,7 @@ var HeldPaths = class extends Map {
|
|
|
13648
13836
|
if (this.bound.size === 0) return;
|
|
13649
13837
|
for (const [handle, key] of this.handles) {
|
|
13650
13838
|
if (!this.bound.has(handle) || this.keptHandles.has(handle)) continue;
|
|
13651
|
-
if (exact ? key === over :
|
|
13839
|
+
if (exact ? key === over : within7(key, over)) this.doubted.set(handle, ++this.doubts);
|
|
13652
13840
|
}
|
|
13653
13841
|
}
|
|
13654
13842
|
boundIno(handle) {
|
|
@@ -13784,24 +13972,24 @@ var HeldPaths = class extends Map {
|
|
|
13784
13972
|
return this.owning === path;
|
|
13785
13973
|
}
|
|
13786
13974
|
revoke(prefix) {
|
|
13787
|
-
for (const path of this.keys()) if (
|
|
13975
|
+
for (const path of this.keys()) if (within7(path, prefix)) this.revoked.add(path);
|
|
13788
13976
|
}
|
|
13789
13977
|
renamed(from, to) {
|
|
13790
13978
|
for (const [path, count2] of [...this]) {
|
|
13791
|
-
if (!
|
|
13979
|
+
if (!within7(path, from)) continue;
|
|
13792
13980
|
const moved2 = to + path.slice(from.length);
|
|
13793
13981
|
this.delete(path);
|
|
13794
13982
|
this.set(moved2, (this.get(moved2) ?? 0) + count2);
|
|
13795
13983
|
if (this.revoked.delete(path)) this.revoked.add(moved2);
|
|
13796
13984
|
}
|
|
13797
13985
|
for (const [path, count2] of [...this.opens]) {
|
|
13798
|
-
if (!
|
|
13986
|
+
if (!within7(path, from)) continue;
|
|
13799
13987
|
const moved2 = to + path.slice(from.length);
|
|
13800
13988
|
this.opens.delete(path);
|
|
13801
13989
|
this.opens.set(moved2, (this.opens.get(moved2) ?? 0) + count2);
|
|
13802
13990
|
}
|
|
13803
13991
|
for (const [id2, key] of this.handles) {
|
|
13804
|
-
if (
|
|
13992
|
+
if (within7(key, from)) this.handles.set(id2, to + key.slice(from.length));
|
|
13805
13993
|
}
|
|
13806
13994
|
this.onMoved?.(from, to);
|
|
13807
13995
|
}
|
|
@@ -13809,7 +13997,7 @@ var HeldPaths = class extends Map {
|
|
|
13809
13997
|
return this.revoked.has(path);
|
|
13810
13998
|
}
|
|
13811
13999
|
};
|
|
13812
|
-
var
|
|
14000
|
+
var parentOf9 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
13813
14001
|
var readonly = (mount) => mount.caps.readonly === true || mount.options.ro !== void 0;
|
|
13814
14002
|
function inodeless(mount, attr2) {
|
|
13815
14003
|
if (attr2.ino !== void 0) return false;
|
|
@@ -13916,13 +14104,13 @@ var MountTable = class {
|
|
|
13916
14104
|
});
|
|
13917
14105
|
}
|
|
13918
14106
|
under(path) {
|
|
13919
|
-
for (const mount of this.mounts.values()) if (
|
|
14107
|
+
for (const mount of this.mounts.values()) if (within7(mount.target, path)) return true;
|
|
13920
14108
|
return false;
|
|
13921
14109
|
}
|
|
13922
14110
|
locate(path) {
|
|
13923
14111
|
let best;
|
|
13924
14112
|
for (const mount of this.mounts.values()) {
|
|
13925
|
-
if (
|
|
14113
|
+
if (within7(path, mount.target) && (!best || mount.target.length > best.target.length))
|
|
13926
14114
|
best = mount;
|
|
13927
14115
|
}
|
|
13928
14116
|
if (!best) return void 0;
|
|
@@ -14069,7 +14257,7 @@ var MountTable = class {
|
|
|
14069
14257
|
async commitUnder(prefix) {
|
|
14070
14258
|
const at = normalizePath(prefix);
|
|
14071
14259
|
await Promise.all(
|
|
14072
|
-
[...this.sessions.keys()].filter((p) =>
|
|
14260
|
+
[...this.sessions.keys()].filter((p) => within7(p, at)).map((p) => this.commit(p))
|
|
14073
14261
|
);
|
|
14074
14262
|
}
|
|
14075
14263
|
async commitOverlapping(real, offset, length2) {
|
|
@@ -14107,11 +14295,11 @@ var MountTable = class {
|
|
|
14107
14295
|
mount.epoch++;
|
|
14108
14296
|
const linked2 = mount.caps.links ? linkedTo(mount, path) : () => false;
|
|
14109
14297
|
for (const [key, cached] of [...mount.attrs])
|
|
14110
|
-
if (
|
|
14298
|
+
if (within7(key, path) || linked2(cached.value)) mount.attrs.delete(key);
|
|
14111
14299
|
mount.lists.delete(path);
|
|
14112
|
-
mount.lists.delete(
|
|
14300
|
+
mount.lists.delete(parentOf9(path));
|
|
14113
14301
|
for (const [key, cached] of [...mount.lists])
|
|
14114
|
-
if (
|
|
14302
|
+
if (within7(key, path) || cached.value.some((e) => linked2(e.attr))) mount.lists.delete(key);
|
|
14115
14303
|
}
|
|
14116
14304
|
async getattr(mount, path, rel2, settled = false) {
|
|
14117
14305
|
for (let round = 1; ; round++) {
|
|
@@ -14230,7 +14418,7 @@ var MountFs = class _MountFs {
|
|
|
14230
14418
|
const real = normalizePath(path);
|
|
14231
14419
|
if (this.at(real)) return real;
|
|
14232
14420
|
try {
|
|
14233
|
-
await this.base.stat(
|
|
14421
|
+
await this.base.stat(parentOf9(real));
|
|
14234
14422
|
return real;
|
|
14235
14423
|
} catch (err) {
|
|
14236
14424
|
const moved2 = redirectOf(err);
|
|
@@ -14252,7 +14440,7 @@ var MountFs = class _MountFs {
|
|
|
14252
14440
|
if (redirects >= MAX_LINKS7) throw errnoError("ELOOP", paths[0]);
|
|
14253
14441
|
const at = paths.map((path) => {
|
|
14254
14442
|
const real = normalizePath(path);
|
|
14255
|
-
return
|
|
14443
|
+
return within7(real, moved2.of) ? normalizePath(moved2.to + real.slice(moved2.of.length)) : real;
|
|
14256
14444
|
});
|
|
14257
14445
|
return again(at, redirects + 1);
|
|
14258
14446
|
}
|
|
@@ -14272,7 +14460,7 @@ var MountFs = class _MountFs {
|
|
|
14272
14460
|
if (this.rejectLinks) throw errnoError("ELOOP", path);
|
|
14273
14461
|
if (hops >= MAX_LINKS7) throw errnoError("ELOOP", path);
|
|
14274
14462
|
const target = await found.mount.conn.call({ op: "readlink", path: found.rel });
|
|
14275
|
-
return this.follow(this.base.resolvePath(
|
|
14463
|
+
return this.follow(this.base.resolvePath(parentOf9(real), target), hops + 1, create);
|
|
14276
14464
|
}
|
|
14277
14465
|
async open(mount, rel2, write, owner, create = write) {
|
|
14278
14466
|
return await mount.conn.call({
|
|
@@ -14288,8 +14476,8 @@ var MountFs = class _MountFs {
|
|
|
14288
14476
|
async driverOwner(found, real, owner, directory) {
|
|
14289
14477
|
const { mount, rel: rel2 } = found;
|
|
14290
14478
|
if (!owner || !mount.owners || !mount.caps.owners) return void 0;
|
|
14291
|
-
const dir =
|
|
14292
|
-
const above = statOf2(await this.table.getattr(mount, dir,
|
|
14479
|
+
const dir = parentOf9(real);
|
|
14480
|
+
const above = statOf2(await this.table.getattr(mount, dir, parentOf9(rel2)), dir, mount);
|
|
14293
14481
|
const setgid = (above.mode & S_ISGID4) !== 0;
|
|
14294
14482
|
let mode = owner.mode;
|
|
14295
14483
|
if (directory && setgid) mode = (mode ?? 493) | S_ISGID4;
|
|
@@ -14808,7 +14996,7 @@ var MountFs = class _MountFs {
|
|
|
14808
14996
|
}
|
|
14809
14997
|
async named(path) {
|
|
14810
14998
|
const at = normalizePath(path);
|
|
14811
|
-
return joinName(await realDir(this,
|
|
14999
|
+
return joinName(await realDir(this, parentOf9(at)), at.slice(at.lastIndexOf("/") + 1));
|
|
14812
15000
|
}
|
|
14813
15001
|
async link(source, target, follow2 = false) {
|
|
14814
15002
|
const from = follow2 ? await realTarget(this, normalizePath(source)) : await this.named(source);
|
|
@@ -16482,6 +16670,8 @@ var SYS_TREE = {
|
|
|
16482
16670
|
slicc_opfs_calls: (listing) => `${listing.opfsCalls ?? 0}
|
|
16483
16671
|
`,
|
|
16484
16672
|
slicc_opfs_ops: (listing) => `${listing.opfsOps ?? 0}
|
|
16673
|
+
`,
|
|
16674
|
+
slicc_meta_transactions: ({ meta }) => `${meta?.reads ?? 0} ${meta?.writes ?? 0}
|
|
16485
16675
|
`,
|
|
16486
16676
|
slicc_cwd_checks: (listing) => `${listing.cwdChecks ?? 0}
|
|
16487
16677
|
`,
|
|
@@ -22682,7 +22872,7 @@ function ranges(text) {
|
|
|
22682
22872
|
return [Number.parseInt(lo, 16), Number.parseInt(hi, 16)];
|
|
22683
22873
|
});
|
|
22684
22874
|
}
|
|
22685
|
-
function
|
|
22875
|
+
function within8(table, code) {
|
|
22686
22876
|
let lo = 0;
|
|
22687
22877
|
let hi = table.length - 1;
|
|
22688
22878
|
while (lo <= hi) {
|
|
@@ -22705,10 +22895,10 @@ var LCAT = ranges(LCAT_TEXT);
|
|
|
22705
22895
|
function prepFails(prepared) {
|
|
22706
22896
|
const codes = Array.from(prepared, (ch) => ch.codePointAt(0) ?? 0);
|
|
22707
22897
|
if (codes.length === 0) return true;
|
|
22708
|
-
if (codes.some((c) =>
|
|
22709
|
-
if (!codes.some((c) =>
|
|
22710
|
-
if (codes.some((c) =>
|
|
22711
|
-
return !
|
|
22898
|
+
if (codes.some((c) => within8(PROHIBITED, c) || within8(UNASSIGNED, c))) return true;
|
|
22899
|
+
if (!codes.some((c) => within8(RANDAL, c))) return false;
|
|
22900
|
+
if (codes.some((c) => within8(LCAT, c))) return true;
|
|
22901
|
+
return !within8(RANDAL, codes[0] ?? 0) || !within8(RANDAL, codes.at(-1) ?? 0);
|
|
22712
22902
|
}
|
|
22713
22903
|
|
|
22714
22904
|
// src/kernel/net/sealed-scram.ts
|
|
@@ -24683,7 +24873,7 @@ function isMissing(err) {
|
|
|
24683
24873
|
if (err?.code === "ENOENT") return true;
|
|
24684
24874
|
return err instanceof Error && err.message.startsWith("ENOENT");
|
|
24685
24875
|
}
|
|
24686
|
-
function
|
|
24876
|
+
function within9(path, root) {
|
|
24687
24877
|
return path === root || path.startsWith(root.endsWith("/") ? root : `${root}/`);
|
|
24688
24878
|
}
|
|
24689
24879
|
var VfsNode = class {
|
|
@@ -25064,7 +25254,7 @@ var VfsNodes = class {
|
|
|
25064
25254
|
return run2;
|
|
25065
25255
|
}
|
|
25066
25256
|
async entryKey(path) {
|
|
25067
|
-
const parent =
|
|
25257
|
+
const parent = parentOf5(path);
|
|
25068
25258
|
const dir = await this.real(parent, true, () => realDir(this.fs, parent));
|
|
25069
25259
|
return joinName(dir, path.slice(path.lastIndexOf("/") + 1));
|
|
25070
25260
|
}
|
|
@@ -25220,12 +25410,12 @@ var VfsNodes = class {
|
|
|
25220
25410
|
return node;
|
|
25221
25411
|
}
|
|
25222
25412
|
holds(prefix) {
|
|
25223
|
-
for (const path of this.byPath.keys()) if (
|
|
25413
|
+
for (const path of this.byPath.keys()) if (within9(path, prefix)) return true;
|
|
25224
25414
|
return false;
|
|
25225
25415
|
}
|
|
25226
25416
|
writes(prefix) {
|
|
25227
25417
|
for (const [path, node] of this.byPath)
|
|
25228
|
-
if (node.writers > 0 &&
|
|
25418
|
+
if (node.writers > 0 && within9(path, prefix)) return true;
|
|
25229
25419
|
return false;
|
|
25230
25420
|
}
|
|
25231
25421
|
closed(node, writable2 = false) {
|
|
@@ -25308,17 +25498,17 @@ var VfsNodes = class {
|
|
|
25308
25498
|
this.byPath.get(path)?.reread();
|
|
25309
25499
|
}
|
|
25310
25500
|
rewrittenUnder(tree2) {
|
|
25311
|
-
for (const [p, node] of this.byPath) if (
|
|
25501
|
+
for (const [p, node] of this.byPath) if (within9(p, tree2)) node.reread();
|
|
25312
25502
|
}
|
|
25313
25503
|
doubted(path) {
|
|
25314
|
-
for (const [p, node] of this.byPath) if (
|
|
25504
|
+
for (const [p, node] of this.byPath) if (within9(p, path)) node.doubted();
|
|
25315
25505
|
}
|
|
25316
25506
|
async flush(path) {
|
|
25317
|
-
for (const [p, node] of this.byPath) if (
|
|
25507
|
+
for (const [p, node] of this.byPath) if (within9(p, path)) await node.serial(() => node.flush());
|
|
25318
25508
|
}
|
|
25319
25509
|
async unlinking(path) {
|
|
25320
25510
|
for (const [held, node] of [...this.byPath]) {
|
|
25321
|
-
if (!
|
|
25511
|
+
if (!within9(held, path)) continue;
|
|
25322
25512
|
await node.serial(async () => {
|
|
25323
25513
|
await Promise.all([this.keepsOnDisk || node.keep(), node.limit()]);
|
|
25324
25514
|
});
|
|
@@ -25326,14 +25516,14 @@ var VfsNodes = class {
|
|
|
25326
25516
|
}
|
|
25327
25517
|
revoke(prefix) {
|
|
25328
25518
|
for (const [path, node] of [...this.byPath]) {
|
|
25329
|
-
if (!
|
|
25519
|
+
if (!within9(path, prefix)) continue;
|
|
25330
25520
|
node.revoke();
|
|
25331
25521
|
this.forget(node);
|
|
25332
25522
|
}
|
|
25333
25523
|
}
|
|
25334
25524
|
unlinked(path) {
|
|
25335
25525
|
for (const [held, node] of [...this.byPath]) {
|
|
25336
|
-
if (!
|
|
25526
|
+
if (!within9(held, path) || this.byPath.get(held) !== node) continue;
|
|
25337
25527
|
if (!this.dropName(held, node)) this.orphan(node);
|
|
25338
25528
|
}
|
|
25339
25529
|
}
|
|
@@ -25341,8 +25531,8 @@ var VfsNodes = class {
|
|
|
25341
25531
|
if (from === to) return;
|
|
25342
25532
|
const moved2 = [];
|
|
25343
25533
|
for (const [p, node] of [...this.byPath]) {
|
|
25344
|
-
if (
|
|
25345
|
-
else if (
|
|
25534
|
+
if (within9(p, from)) moved2.push([p, node]);
|
|
25535
|
+
else if (within9(p, to) && this.byPath.get(p) === node && !this.dropName(p, node)) {
|
|
25346
25536
|
this.orphan(node);
|
|
25347
25537
|
}
|
|
25348
25538
|
}
|
|
@@ -25368,7 +25558,7 @@ function errCode(err) {
|
|
|
25368
25558
|
return err?.code;
|
|
25369
25559
|
}
|
|
25370
25560
|
async function targetDir(fs, path) {
|
|
25371
|
-
return
|
|
25561
|
+
return parentOf5(await realTarget(fs, path).catch(() => path));
|
|
25372
25562
|
}
|
|
25373
25563
|
async function refuseReadonly(fs, path, flags2, opts = {}) {
|
|
25374
25564
|
const writes = (flags2 & O_ACCMODE) !== 0 || opts.truncate === true;
|
|
@@ -25631,7 +25821,7 @@ function isWatchSyscall(req) {
|
|
|
25631
25821
|
return WATCHING.has(req.op);
|
|
25632
25822
|
}
|
|
25633
25823
|
var WATCHES_MAX = 8192;
|
|
25634
|
-
var
|
|
25824
|
+
var parentOf10 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
25635
25825
|
function visibleTo2(watch, root, visible) {
|
|
25636
25826
|
return {
|
|
25637
25827
|
close: () => watch.close(),
|
|
@@ -25642,7 +25832,7 @@ function visibleTo2(watch, root, visible) {
|
|
|
25642
25832
|
notes.map(async (note) => {
|
|
25643
25833
|
if (!("filename" in note) || !note.filename.includes("/")) return true;
|
|
25644
25834
|
const at = watch.root?.() ?? root;
|
|
25645
|
-
const dir =
|
|
25835
|
+
const dir = parentOf10(`${at === "/" ? "" : at}/${note.filename}`);
|
|
25646
25836
|
if (!seen.has(dir)) seen.set(dir, visible(dir));
|
|
25647
25837
|
return seen.get(dir);
|
|
25648
25838
|
})
|
|
@@ -29587,7 +29777,7 @@ function sealedFetcher(hook, stop, idleMs = BODY_IDLE_MS) {
|
|
|
29587
29777
|
var SWAP_GAP_MS = 2e3;
|
|
29588
29778
|
var STAGES = ["_tmp_", "_pacquet-stage_"];
|
|
29589
29779
|
function staged(source, target) {
|
|
29590
|
-
if (
|
|
29780
|
+
if (parentOf5(source) !== parentOf5(target)) return false;
|
|
29591
29781
|
const name2 = target.slice(target.lastIndexOf("/") + 1);
|
|
29592
29782
|
const from = source.slice(source.lastIndexOf("/") + 1);
|
|
29593
29783
|
return from.startsWith(`.${name2}-`) || STAGES.some((stage) => from.startsWith(`${name2}${stage}`));
|
|
@@ -29684,7 +29874,7 @@ var PackageSwaps = class {
|
|
|
29684
29874
|
|
|
29685
29875
|
// src/kernel/rename-log.ts
|
|
29686
29876
|
var RENAME_LOG_SIZE = 4096;
|
|
29687
|
-
function
|
|
29877
|
+
function within10(path, root) {
|
|
29688
29878
|
return path === root || path.startsWith(root === "/" ? "/" : `${root}/`);
|
|
29689
29879
|
}
|
|
29690
29880
|
var RenameLog = class {
|
|
@@ -29711,9 +29901,9 @@ var RenameLog = class {
|
|
|
29711
29901
|
const renames = [];
|
|
29712
29902
|
let paths = [...held];
|
|
29713
29903
|
for (const { seq: seq2, from, to } of this.entries) {
|
|
29714
|
-
if (seq2 <= seen || !paths.some((path) =>
|
|
29904
|
+
if (seq2 <= seen || !paths.some((path) => within10(path, from))) continue;
|
|
29715
29905
|
renames.push([from, to]);
|
|
29716
|
-
paths = paths.map((path) =>
|
|
29906
|
+
paths = paths.map((path) => within10(path, from) ? to + path.slice(from.length) : path);
|
|
29717
29907
|
}
|
|
29718
29908
|
return { now, renames };
|
|
29719
29909
|
}
|
|
@@ -31587,6 +31777,104 @@ function splitWords(text) {
|
|
|
31587
31777
|
function quoteWord(word) {
|
|
31588
31778
|
return PLAIN3.test(word) ? word : `'${word.replaceAll("'", `'\\''`)}'`;
|
|
31589
31779
|
}
|
|
31780
|
+
function addPart(word, part) {
|
|
31781
|
+
const last = word.length - 1;
|
|
31782
|
+
if (part === null) {
|
|
31783
|
+
if (word[last] !== null) word.push(null);
|
|
31784
|
+
} else if (typeof word[last] === "string") word[last] += part;
|
|
31785
|
+
else word.push(part);
|
|
31786
|
+
}
|
|
31787
|
+
function addPlain(word, plain3) {
|
|
31788
|
+
for (const [i, part] of plain3.split("*").entries()) {
|
|
31789
|
+
if (i > 0) addPart(word, null);
|
|
31790
|
+
if (part !== "") addPart(word, part);
|
|
31791
|
+
}
|
|
31792
|
+
}
|
|
31793
|
+
function splitPatterns(text) {
|
|
31794
|
+
const piece = /'([^']*)'|"((?:[^"\\]|\\[\s\S])*)"|\\([\s\S])|([^\s'"\\]+)|(\s+)/y;
|
|
31795
|
+
const words2 = [];
|
|
31796
|
+
let word;
|
|
31797
|
+
while (piece.lastIndex < text.length) {
|
|
31798
|
+
const m = piece.exec(text);
|
|
31799
|
+
if (!m) return void 0;
|
|
31800
|
+
const [, single, double, escaped, plain3, space] = m;
|
|
31801
|
+
if (space !== void 0) {
|
|
31802
|
+
if (word !== void 0) words2.push(word);
|
|
31803
|
+
word = void 0;
|
|
31804
|
+
continue;
|
|
31805
|
+
}
|
|
31806
|
+
word ??= [];
|
|
31807
|
+
if (plain3 !== void 0) addPlain(word, plain3);
|
|
31808
|
+
else addPart(word, single ?? (double !== void 0 ? unescaped(double) : escaped));
|
|
31809
|
+
}
|
|
31810
|
+
if (word !== void 0) words2.push(word);
|
|
31811
|
+
return words2;
|
|
31812
|
+
}
|
|
31813
|
+
var literal2 = (pattern) => pattern.map((p) => p ?? "*").join("");
|
|
31814
|
+
var isAny = (pattern) => pattern?.length === 1 && pattern[0] === null;
|
|
31815
|
+
function literalWord(word) {
|
|
31816
|
+
if (!word.includes("*")) return quoteWord(word);
|
|
31817
|
+
const bare = word.replaceAll("*", "");
|
|
31818
|
+
return bare === "" || PLAIN3.test(bare) ? word.replaceAll("*", "\\*") : quoteWord(word);
|
|
31819
|
+
}
|
|
31820
|
+
function patternWord(pattern) {
|
|
31821
|
+
if (pattern.length === 1 && typeof pattern[0] === "string") return literalWord(pattern[0]);
|
|
31822
|
+
return pattern.map((p) => p === null ? "*" : literalWord(p)).join("");
|
|
31823
|
+
}
|
|
31824
|
+
function globMatch(items, subjects, star, one) {
|
|
31825
|
+
let i = 0;
|
|
31826
|
+
let j = 0;
|
|
31827
|
+
let back = -1;
|
|
31828
|
+
let from = 0;
|
|
31829
|
+
while (j < subjects) {
|
|
31830
|
+
if (i < items && star(i)) {
|
|
31831
|
+
back = i++;
|
|
31832
|
+
from = j;
|
|
31833
|
+
} else if (i < items && one(i, j)) {
|
|
31834
|
+
i++;
|
|
31835
|
+
j++;
|
|
31836
|
+
} else if (back >= 0) {
|
|
31837
|
+
i = back + 1;
|
|
31838
|
+
j = ++from;
|
|
31839
|
+
} else return false;
|
|
31840
|
+
}
|
|
31841
|
+
while (i < items && star(i)) i++;
|
|
31842
|
+
return i === items;
|
|
31843
|
+
}
|
|
31844
|
+
function wordMatch(pattern, arg) {
|
|
31845
|
+
if (pattern.every((p) => p !== null)) return literal2(pattern) === arg;
|
|
31846
|
+
const chars = pattern.flatMap((p) => p === null ? [null] : [...p]);
|
|
31847
|
+
const subject = [...arg];
|
|
31848
|
+
return globMatch(
|
|
31849
|
+
chars.length,
|
|
31850
|
+
subject.length,
|
|
31851
|
+
(i) => chars[i] === null,
|
|
31852
|
+
(i, j) => chars[i] === subject[j]
|
|
31853
|
+
);
|
|
31854
|
+
}
|
|
31855
|
+
function commandMatches(cmnd, argv) {
|
|
31856
|
+
if (cmnd === "*") return true;
|
|
31857
|
+
const [path, ...args] = argv;
|
|
31858
|
+
if (path !== cmnd.path) return false;
|
|
31859
|
+
const want = cmnd.args;
|
|
31860
|
+
if (want === void 0) return true;
|
|
31861
|
+
return globMatch(
|
|
31862
|
+
want.length,
|
|
31863
|
+
args.length,
|
|
31864
|
+
(i) => isAny(want[i]),
|
|
31865
|
+
(i, j) => wordMatch(want[i], args[j])
|
|
31866
|
+
);
|
|
31867
|
+
}
|
|
31868
|
+
function commandText(cmnd) {
|
|
31869
|
+
const path = quoteWord(cmnd.path);
|
|
31870
|
+
if (cmnd.args === void 0) return path;
|
|
31871
|
+
if (cmnd.args.length === 0) return `${path} ""`;
|
|
31872
|
+
return [path, ...cmnd.args.map(patternWord)].join(" ");
|
|
31873
|
+
}
|
|
31874
|
+
function recordedCommand(argv) {
|
|
31875
|
+
const [path = "", ...args] = argv;
|
|
31876
|
+
return commandText({ path, args: args.map((a) => [a]) });
|
|
31877
|
+
}
|
|
31590
31878
|
function validWho(who) {
|
|
31591
31879
|
if (who === "ALL") return true;
|
|
31592
31880
|
return NAME3.test(who.startsWith("%") ? who.slice(1) : who);
|
|
@@ -31607,9 +31895,23 @@ function parseRule(line) {
|
|
|
31607
31895
|
if (cwd === "") return void 0;
|
|
31608
31896
|
const rule = { nopasswd: !!nopasswd, who, target, ...cwd !== void 0 ? { cwd } : {} };
|
|
31609
31897
|
if (rest2.trim() === "*") return { ...rule, cmnd: "*" };
|
|
31610
|
-
const
|
|
31611
|
-
|
|
31612
|
-
|
|
31898
|
+
const words2 = splitPatterns(rest2);
|
|
31899
|
+
const [first, ...args] = words2 ?? [];
|
|
31900
|
+
const path = first ? literal2(first) : "";
|
|
31901
|
+
if (!path.startsWith("/")) return void 0;
|
|
31902
|
+
const only = args.length === 1 && args[0]?.length === 1 && args[0][0] === "";
|
|
31903
|
+
if (only && /\s""$/.test(rest2.trim())) return { ...rule, cmnd: { path, args: [] } };
|
|
31904
|
+
return { ...rule, cmnd: args.length === 0 ? { path } : { path, args } };
|
|
31905
|
+
}
|
|
31906
|
+
function recordedBare(line, file, rule) {
|
|
31907
|
+
if (rule.cmnd === "*" || rule.cmnd.args !== void 0 || !rule.nopasswd) return false;
|
|
31908
|
+
if (file !== `${SUDOERS_D}/${rule.who}` || !NAME3.test(rule.who) || !NAME3.test(rule.target)) {
|
|
31909
|
+
return false;
|
|
31910
|
+
}
|
|
31911
|
+
const head = `NOPASSWD ${rule.who} (${rule.target}) `;
|
|
31912
|
+
const cmnd = `Cmnd ${quoteWord(rule.cmnd.path)}`;
|
|
31913
|
+
const cwd = rule.cwd === void 0 ? "" : `Cwd ${quoteWord(rule.cwd)} `;
|
|
31914
|
+
return line === `${head}${cwd}${cmnd}`;
|
|
31613
31915
|
}
|
|
31614
31916
|
function flags(parsed2, arg, next3) {
|
|
31615
31917
|
for (let j = 1; j < arg.length; j++) {
|
|
@@ -31647,7 +31949,7 @@ function parseArgs(args) {
|
|
|
31647
31949
|
return parsed2;
|
|
31648
31950
|
}
|
|
31649
31951
|
function described(rule) {
|
|
31650
|
-
const cmnd = rule.cmnd === "*" ? "ALL" : rule.cmnd
|
|
31952
|
+
const cmnd = rule.cmnd === "*" ? "ALL" : commandText(rule.cmnd);
|
|
31651
31953
|
const cwd = rule.cwd === void 0 ? "" : `CWD=${quoteWord(rule.cwd)} `;
|
|
31652
31954
|
return ` (${rule.target}) ${cwd}${rule.nopasswd ? "NOPASSWD: " : ""}${cmnd}`;
|
|
31653
31955
|
}
|
|
@@ -31693,7 +31995,9 @@ var Sudo = class {
|
|
|
31693
31995
|
const rules = [];
|
|
31694
31996
|
for (const [n, line] of text.split("\n").entries()) {
|
|
31695
31997
|
const rule = parseRule(line);
|
|
31696
|
-
if (rule
|
|
31998
|
+
if (rule && recordedBare(line, path, rule) && rule.cmnd !== "*") {
|
|
31999
|
+
rules.push({ ...rule, cmnd: { path: rule.cmnd.path, args: [] } });
|
|
32000
|
+
} else if (rule) rules.push(rule);
|
|
31697
32001
|
else if (rule === void 0) this.warn(`sudo: ${path}:${n + 1}: bad line skipped: ${line}`);
|
|
31698
32002
|
}
|
|
31699
32003
|
return rules;
|
|
@@ -31789,7 +32093,7 @@ var Sudo = class {
|
|
|
31789
32093
|
if (untrusted2) return untrusted2;
|
|
31790
32094
|
const argv = [path, ...args];
|
|
31791
32095
|
const matching = rules.filter(
|
|
31792
|
-
(rule) => applies(rule) && (rule.target === "ALL" || rule.target === target.name) && (rule.cwd === void 0 || rule.cwd === cwd) && (rule.cmnd
|
|
32096
|
+
(rule) => applies(rule) && (rule.target === "ALL" || rule.target === target.name) && (rule.cwd === void 0 || rule.cwd === cwd) && commandMatches(rule.cmnd, argv)
|
|
31793
32097
|
);
|
|
31794
32098
|
const grant = () => this.grant(self, target, cred, parsed2.command, path, cwd, call.term);
|
|
31795
32099
|
if (root || matching.some((rule) => rule.nopasswd)) return grant();
|
|
@@ -31886,7 +32190,7 @@ ${lines2}
|
|
|
31886
32190
|
const st = await fs.lstat(path).catch(() => void 0);
|
|
31887
32191
|
if (st && !await this.trusted(path)) return false;
|
|
31888
32192
|
const old = st ? await fs.readFile(path) : "";
|
|
31889
|
-
const words2 = argv
|
|
32193
|
+
const words2 = recordedCommand(argv);
|
|
31890
32194
|
const line = `NOPASSWD ${self.name} (${target.name}) Cwd ${quoteWord(cwd)} Cmnd ${words2}
|
|
31891
32195
|
`;
|
|
31892
32196
|
const text = old === "" || old.endsWith("\n") ? `${old}${line}` : `${old}
|
|
@@ -32694,6 +32998,7 @@ var Launcher = class {
|
|
|
32694
32998
|
this.rewritten(change.paths, change.trees);
|
|
32695
32999
|
this.watchers.heard(change.content ? "change" : "rename", change.paths);
|
|
32696
33000
|
this.watchers.heard("rename", change.trees ?? []);
|
|
33001
|
+
this.watchers.peerChanged([...change.paths, ...change.trees ?? []]);
|
|
32697
33002
|
if (change.outside && this.catalogChanged([...change.paths, ...change.trees ?? []])) {
|
|
32698
33003
|
this.resetCatalogs();
|
|
32699
33004
|
}
|
|
@@ -33447,9 +33752,9 @@ var Launcher = class {
|
|
|
33447
33752
|
}
|
|
33448
33753
|
packageRootIs(path) {
|
|
33449
33754
|
const at = normalizePath(path);
|
|
33450
|
-
const
|
|
33755
|
+
const within11 = `${at}/`;
|
|
33451
33756
|
const roots = [this.modulesDir, ...this.appended];
|
|
33452
|
-
const root = PACKAGE_ROOT.exec(
|
|
33757
|
+
const root = PACKAGE_ROOT.exec(within11)?.[1] ?? packageRootOf(within11, roots);
|
|
33453
33758
|
return root === at;
|
|
33454
33759
|
}
|
|
33455
33760
|
packageRoots(planned) {
|
|
@@ -33648,6 +33953,7 @@ var Launcher = class {
|
|
|
33648
33953
|
fsCalls: servedFsCalls(),
|
|
33649
33954
|
opfsCalls: this.rootFs.opfsCalls?.() ?? 0,
|
|
33650
33955
|
opfsOps: this.rootFs.opfsOps?.() ?? 0,
|
|
33956
|
+
meta: this.rootFs.metaTransactions?.(),
|
|
33651
33957
|
cwdChecks: this.cwds.checks,
|
|
33652
33958
|
renameAcks: this.rootFs.renameWaits?.(),
|
|
33653
33959
|
swaps: this.swaps.counts(),
|
|
@@ -34391,7 +34697,7 @@ var Launcher = class {
|
|
|
34391
34697
|
const path = normalizePath(given);
|
|
34392
34698
|
if (!await this.base.exists(path)) return void 0;
|
|
34393
34699
|
if (path === "/") return path;
|
|
34394
|
-
return joinName(await realDir(this.base,
|
|
34700
|
+
return joinName(await realDir(this.base, parentOf5(path)), baseName2(path));
|
|
34395
34701
|
}
|
|
34396
34702
|
pnpmReady() {
|
|
34397
34703
|
if (this.pnpmMade !== void 0) return this.pnpmMade;
|