@ai-ecoverse/slicc-kernel 1.103.4 → 1.106.2
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 +56 -15
- package/dist/driver-worker.js +36 -1
- package/dist/driver-worker.js.map +2 -2
- package/dist/index.js +89 -5
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +783 -289
- package/dist/kernel-worker.js.map +4 -4
- package/dist/meta.js.map +2 -2
- package/dist/node-driver-worker.js +36 -1
- package/dist/node-driver-worker.js.map +2 -2
- package/dist/node-process-worker.js +447 -224
- package/dist/node-process-worker.js.map +4 -4
- package/dist/node.js +831 -309
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +384 -161
- package/dist/process-worker.js.map +4 -4
- package/dist/types/commands.d.ts +6 -1
- package/dist/types/fs/command-stat.d.ts +3 -0
- package/dist/types/fs/commands.d.ts +7 -1
- package/dist/types/fs/engines.d.ts +5 -0
- package/dist/types/fs/types.d.ts +1 -0
- package/dist/types/kernel/host.d.ts +1 -0
- package/dist/types/kernel/net/http-syscalls.d.ts +10 -0
- package/dist/types/kernel/net/http1.d.ts +1 -0
- package/dist/types/kernel/net/remote-transport.d.ts +18 -0
- package/dist/types/kernel/net/transport.d.ts +2 -0
- package/dist/types/kernel/process.d.ts +8 -0
- package/dist/types/launcher.d.ts +4 -0
- package/dist/types/process/process-signals.d.ts +3 -0
- package/dist/types/process/wasi/wasi-cred.d.ts +11 -0
- package/dist/types/process/wasi/wasi-files.d.ts +1 -0
- package/dist/types/process/wasi/wasi-host.d.ts +9 -0
- package/dist/types/process/wasi/wasi-sigmask.d.ts +7 -1
- package/dist/types/process/wasi/wasix-epoll.d.ts +3 -0
- package/dist/types/refused-command.d.ts +4 -0
- package/dist/types/transport.d.ts +1 -0
- package/package.json +12 -12
package/dist/kernel-worker.js
CHANGED
|
@@ -58,9 +58,9 @@ var PathMap = class {
|
|
|
58
58
|
}
|
|
59
59
|
link(path) {
|
|
60
60
|
for (let child = path, parent = parentOf(path); parent !== void 0; ) {
|
|
61
|
-
const
|
|
62
|
-
if (
|
|
63
|
-
if (
|
|
61
|
+
const set3 = this.children.get(parent);
|
|
62
|
+
if (set3?.has(child)) return;
|
|
63
|
+
if (set3) set3.add(child);
|
|
64
64
|
else this.children.set(parent, /* @__PURE__ */ new Set([child]));
|
|
65
65
|
child = parent;
|
|
66
66
|
parent = parentOf(parent);
|
|
@@ -69,9 +69,9 @@ var PathMap = class {
|
|
|
69
69
|
prune(path) {
|
|
70
70
|
for (let child = path, parent = parentOf(path); parent !== void 0; ) {
|
|
71
71
|
if (this.values.has(child) || this.children.has(child)) return;
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
if (
|
|
72
|
+
const set3 = this.children.get(parent);
|
|
73
|
+
set3?.delete(child);
|
|
74
|
+
if (set3 && set3.size > 0) return;
|
|
75
75
|
this.children.delete(parent);
|
|
76
76
|
child = parent;
|
|
77
77
|
parent = parentOf(parent);
|
|
@@ -208,15 +208,15 @@ var IndexedDbMeta = class {
|
|
|
208
208
|
this.settleRemoves();
|
|
209
209
|
const [transaction, store] = this.transaction("readwrite");
|
|
210
210
|
const request2 = store.get(path);
|
|
211
|
-
let
|
|
211
|
+
let next3;
|
|
212
212
|
request2.onsuccess = () => {
|
|
213
|
-
|
|
214
|
-
if (
|
|
213
|
+
next3 = change(request2.result);
|
|
214
|
+
if (next3) store.put(next3);
|
|
215
215
|
else store.delete(path);
|
|
216
216
|
};
|
|
217
217
|
await settle(transaction, () => void 0);
|
|
218
218
|
this.changed({ paths: [path] });
|
|
219
|
-
this.cache.set(path,
|
|
219
|
+
this.cache.set(path, next3 ?? null);
|
|
220
220
|
}
|
|
221
221
|
async updateMany(changes) {
|
|
222
222
|
const [transaction, store] = this.transaction("readwrite");
|
|
@@ -530,14 +530,14 @@ var Integrity = class {
|
|
|
530
530
|
if (!this.root.version) return void 0;
|
|
531
531
|
return `${real}\0${await this.root.version(real)}`;
|
|
532
532
|
}
|
|
533
|
-
async read(path, caller,
|
|
534
|
-
return (await this.readKeyed(path, caller,
|
|
533
|
+
async read(path, caller, plain2, asked) {
|
|
534
|
+
return (await this.readKeyed(path, caller, plain2, asked)).bytes;
|
|
535
535
|
}
|
|
536
|
-
async readKeyed(path, caller,
|
|
536
|
+
async readKeyed(path, caller, plain2, asked) {
|
|
537
537
|
const found = await this.real(path, asked);
|
|
538
|
-
if (found === void 0) return { bytes: await
|
|
538
|
+
if (found === void 0) return { bytes: await plain2() };
|
|
539
539
|
const { real, name: name2 } = found;
|
|
540
|
-
const read = name2 !== real ? { bytes: await
|
|
540
|
+
const read = name2 !== real ? { bytes: await plain2(), version: void 0 } : this.root.readVersioned ? await this.root.readVersioned(real) : { bytes: await this.root.readFileBuffer(real), version: void 0 };
|
|
541
541
|
const { bytes } = read;
|
|
542
542
|
const keyed = read.version === void 0 ? { bytes } : { bytes, key: `${real}\0${read.version}` };
|
|
543
543
|
await this.verify(name2, bytes, caller, EXEC_OPS);
|
|
@@ -546,9 +546,9 @@ var Integrity = class {
|
|
|
546
546
|
get readsChecked() {
|
|
547
547
|
return this.sources.length > 0;
|
|
548
548
|
}
|
|
549
|
-
async readSource(path, caller,
|
|
549
|
+
async readSource(path, caller, plain2) {
|
|
550
550
|
const found = await this.source(path);
|
|
551
|
-
return found === void 0 ?
|
|
551
|
+
return found === void 0 ? plain2() : this.checked(found, caller, plain2);
|
|
552
552
|
}
|
|
553
553
|
async openSource(path, caller, real) {
|
|
554
554
|
const found = await this.source(path, real);
|
|
@@ -558,10 +558,10 @@ var Integrity = class {
|
|
|
558
558
|
}
|
|
559
559
|
await this.checked(found, caller, () => this.root.readFileBuffer(found.real));
|
|
560
560
|
}
|
|
561
|
-
async checked(found, caller,
|
|
561
|
+
async checked(found, caller, plain2) {
|
|
562
562
|
const { real, name: name2 } = found;
|
|
563
563
|
if (name2 !== real || !this.root.readVersioned) {
|
|
564
|
-
const bytes2 = await
|
|
564
|
+
const bytes2 = await plain2();
|
|
565
565
|
await this.verify(name2, bytes2, caller, READ_OPS);
|
|
566
566
|
return bytes2;
|
|
567
567
|
}
|
|
@@ -1287,8 +1287,8 @@ var OpfsFs = class {
|
|
|
1287
1287
|
this.refuse(found.path);
|
|
1288
1288
|
const [stored] = found.link ? [found.link] : await this.meta.get([found.path]);
|
|
1289
1289
|
const current = await this.ownerAt(found.path, stored);
|
|
1290
|
-
const
|
|
1291
|
-
const handing = found.handle?.kind === "directory" && !sameOwner(
|
|
1290
|
+
const next3 = { uid: change.uid ?? current.uid, gid: change.gid ?? current.gid };
|
|
1291
|
+
const handing = found.handle?.kind === "directory" && !sameOwner(next3, current);
|
|
1292
1292
|
const heir = change.kind === "adopt" ? void 0 : stored?.heir ?? (handing ? [current.uid, current.gid] : void 0);
|
|
1293
1293
|
const ctimeMs = Date.now();
|
|
1294
1294
|
await this.meta.update(found.path, (entry) => {
|
|
@@ -1296,7 +1296,7 @@ var OpfsFs = class {
|
|
|
1296
1296
|
return {
|
|
1297
1297
|
...rest2,
|
|
1298
1298
|
path: found.path,
|
|
1299
|
-
...
|
|
1299
|
+
...next3,
|
|
1300
1300
|
...heir ? { heir } : {},
|
|
1301
1301
|
...change.mode !== void 0 ? { mode: change.mode & PERM_MASK } : {},
|
|
1302
1302
|
ctimeMs
|
|
@@ -2342,11 +2342,11 @@ async function realDir(fs, dir, budget = { hops: 0 }) {
|
|
|
2342
2342
|
at = parentOf4(at);
|
|
2343
2343
|
continue;
|
|
2344
2344
|
}
|
|
2345
|
-
const
|
|
2346
|
-
const link2 = await linkOf(fs,
|
|
2345
|
+
const next3 = at === "/" ? `/${part}` : `${at}/${part}`;
|
|
2346
|
+
const link2 = await linkOf(fs, next3);
|
|
2347
2347
|
if (link2 === void 0) {
|
|
2348
|
-
if (queue.find((p) => p !== ".") === "..") await mustBeDir(fs,
|
|
2349
|
-
at =
|
|
2348
|
+
if (queue.find((p) => p !== ".") === "..") await mustBeDir(fs, next3);
|
|
2349
|
+
at = next3;
|
|
2350
2350
|
continue;
|
|
2351
2351
|
}
|
|
2352
2352
|
if (budget.hops >= MAX_LINKS3) throw fsError("ELOOP", dir);
|
|
@@ -2449,18 +2449,18 @@ async function walk(fs, cred, path, follow2, links) {
|
|
|
2449
2449
|
at = parentOf4(at);
|
|
2450
2450
|
continue;
|
|
2451
2451
|
}
|
|
2452
|
-
const
|
|
2453
|
-
const perm = await perms.at(
|
|
2452
|
+
const next3 = joinName(at, part);
|
|
2453
|
+
const perm = await perms.at(next3);
|
|
2454
2454
|
const last = queue.length === 0;
|
|
2455
2455
|
if (perm?.link !== void 0 && (!last || follow2)) {
|
|
2456
|
-
if (!trustedLink(perm, links)) return { path, perm: void 0, denied:
|
|
2457
|
-
if (++hops > MAX_LINKS4) return { path:
|
|
2456
|
+
if (!trustedLink(perm, links)) return { path, perm: void 0, denied: next3, link: true };
|
|
2457
|
+
if (++hops > MAX_LINKS4) return { path: next3, perm: void 0 };
|
|
2458
2458
|
queue.unshift(...parts(perm.link));
|
|
2459
2459
|
if (perm.link.startsWith("/")) at = "/";
|
|
2460
2460
|
continue;
|
|
2461
2461
|
}
|
|
2462
|
-
if (last) return { path:
|
|
2463
|
-
at =
|
|
2462
|
+
if (last) return { path: next3, perm };
|
|
2463
|
+
at = next3;
|
|
2464
2464
|
}
|
|
2465
2465
|
return { path: at, perm: await perms.at(at) };
|
|
2466
2466
|
}
|
|
@@ -2565,8 +2565,13 @@ function ttyOpenable(g, tty) {
|
|
|
2565
2565
|
async function need(g, op, path, want, options = {}, shown = path) {
|
|
2566
2566
|
const walked = await access(g.fs, g.cred, path, want, linked(g, options));
|
|
2567
2567
|
if (walked.denied !== void 0) deny(g, op, walked.link ? walked.denied : shown);
|
|
2568
|
+
else if (want & R_OK && g.fs.commandTarget) await readsAs(g, op, walked.path, shown);
|
|
2568
2569
|
return walked;
|
|
2569
2570
|
}
|
|
2571
|
+
async function readsAs(g, op, path, shown) {
|
|
2572
|
+
const target = await g.fs.commandTarget?.(path);
|
|
2573
|
+
if (target !== void 0) await need(g, op, target, R_OK, { directory: false }, shown);
|
|
2574
|
+
}
|
|
2570
2575
|
function entryIn(dir, path) {
|
|
2571
2576
|
return joinName(dir.path, path.slice(path.lastIndexOf("/") + 1));
|
|
2572
2577
|
}
|
|
@@ -2725,14 +2730,14 @@ function changeCred(cur, change) {
|
|
|
2725
2730
|
throw fsError("EINVAL", "not a change");
|
|
2726
2731
|
}
|
|
2727
2732
|
const privileged = cur.euid === 0;
|
|
2728
|
-
const
|
|
2733
|
+
const next3 = copyCred(cur);
|
|
2729
2734
|
for (const keys of [UIDS, GIDS]) {
|
|
2730
2735
|
const own = keys.map((key) => cur[key]);
|
|
2731
2736
|
for (const key of keys) {
|
|
2732
2737
|
const value = id(change[key]);
|
|
2733
2738
|
if (value === void 0) continue;
|
|
2734
2739
|
if (!privileged && !own.includes(value)) throw fsError("EPERM", `${key} ${value}`);
|
|
2735
|
-
|
|
2740
|
+
next3[key] = value;
|
|
2736
2741
|
}
|
|
2737
2742
|
}
|
|
2738
2743
|
if (change.groups !== void 0) {
|
|
@@ -2742,9 +2747,9 @@ function changeCred(cur, change) {
|
|
|
2742
2747
|
const groups = change.groups.map((g) => id(g) ?? Number.NaN);
|
|
2743
2748
|
if (groups.some(Number.isNaN)) throw fsError("EINVAL", "not a group list");
|
|
2744
2749
|
if (!privileged) throw fsError("EPERM", "setgroups");
|
|
2745
|
-
|
|
2750
|
+
next3.groups = groups;
|
|
2746
2751
|
}
|
|
2747
|
-
return
|
|
2752
|
+
return next3;
|
|
2748
2753
|
}
|
|
2749
2754
|
function maySignal(sender, target) {
|
|
2750
2755
|
if (sender.euid === 0) return true;
|
|
@@ -3657,10 +3662,10 @@ var KernelSocket = class _KernelSocket {
|
|
|
3657
3662
|
async accept(signal, nonblock = false) {
|
|
3658
3663
|
for (; ; ) {
|
|
3659
3664
|
if (this.state !== "listening") throw new KernelError("EINVAL");
|
|
3660
|
-
const
|
|
3661
|
-
if (
|
|
3665
|
+
const next3 = this.queue.shift();
|
|
3666
|
+
if (next3) {
|
|
3662
3667
|
this.room.wake();
|
|
3663
|
-
return
|
|
3668
|
+
return next3;
|
|
3664
3669
|
}
|
|
3665
3670
|
if (nonblock) throw new KernelError("EAGAIN");
|
|
3666
3671
|
await this.changes.wait(signal);
|
|
@@ -4179,12 +4184,12 @@ var MessageQueue = class {
|
|
|
4179
4184
|
}
|
|
4180
4185
|
async *[Symbol.asyncIterator]() {
|
|
4181
4186
|
for (; ; ) {
|
|
4182
|
-
const
|
|
4183
|
-
if (
|
|
4184
|
-
const n = payloadSize(
|
|
4187
|
+
const next3 = this.items.shift();
|
|
4188
|
+
if (next3 !== void 0) {
|
|
4189
|
+
const n = payloadSize(next3);
|
|
4185
4190
|
this.size -= n;
|
|
4186
4191
|
this.taken?.(n);
|
|
4187
|
-
yield
|
|
4192
|
+
yield next3;
|
|
4188
4193
|
continue;
|
|
4189
4194
|
}
|
|
4190
4195
|
if (this.ended) return;
|
|
@@ -4200,6 +4205,29 @@ var SEND_BUFFER = 1024 * 1024;
|
|
|
4200
4205
|
var CLOSE_WAIT_MS = 5e3;
|
|
4201
4206
|
var NO_WEBSOCKET = "WebSocket not supported by this transport (fetchTransport needs { webSocket: true })";
|
|
4202
4207
|
var MAX_REQUEST_BODY = 64 * 1024 * 1024;
|
|
4208
|
+
function uploadsFor(peer) {
|
|
4209
|
+
const pulls = /* @__PURE__ */ new Map();
|
|
4210
|
+
const of = (nid, signal) => ({
|
|
4211
|
+
async *[Symbol.asyncIterator]() {
|
|
4212
|
+
for (; ; ) {
|
|
4213
|
+
signal.throwIfAborted();
|
|
4214
|
+
const got = await new Promise((resolve2, reject) => {
|
|
4215
|
+
const stop = () => reject(signal.reason);
|
|
4216
|
+
signal.addEventListener("abort", stop, { once: true });
|
|
4217
|
+
pulls.set(nid, (call) => {
|
|
4218
|
+
signal.removeEventListener("abort", stop);
|
|
4219
|
+
resolve2(call);
|
|
4220
|
+
});
|
|
4221
|
+
peer.postMessage({ net: "body-pull", nid });
|
|
4222
|
+
}).finally(() => pulls.delete(nid));
|
|
4223
|
+
if (got.net === "body-end") return;
|
|
4224
|
+
if (got.net === "body-error") throw new Error(got.message);
|
|
4225
|
+
if (got.net === "body-chunk") yield got.bytes;
|
|
4226
|
+
}
|
|
4227
|
+
}
|
|
4228
|
+
});
|
|
4229
|
+
return { of, answer: (call) => pulls.get(call.nid)?.(call) };
|
|
4230
|
+
}
|
|
4203
4231
|
function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
4204
4232
|
const open = /* @__PURE__ */ new Map();
|
|
4205
4233
|
const fail2 = (nid, e) => {
|
|
@@ -4213,6 +4241,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
4213
4241
|
...typeof code === "string" ? { code } : {}
|
|
4214
4242
|
});
|
|
4215
4243
|
};
|
|
4244
|
+
const uploads = uploadsFor(peer);
|
|
4216
4245
|
const start2 = async (call) => {
|
|
4217
4246
|
const abort = new AbortController();
|
|
4218
4247
|
const entry = { abort };
|
|
@@ -4222,7 +4251,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
4222
4251
|
url: call.url,
|
|
4223
4252
|
method: call.method,
|
|
4224
4253
|
headers: call.headers,
|
|
4225
|
-
...call.body ? { body: call.body } : {},
|
|
4254
|
+
...call.streamed ? { bodyStream: uploads.of(call.nid, abort.signal) } : call.body ? { body: call.body } : {},
|
|
4226
4255
|
signal: abort.signal
|
|
4227
4256
|
});
|
|
4228
4257
|
if (!open.has(call.nid)) {
|
|
@@ -4294,9 +4323,9 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
4294
4323
|
try {
|
|
4295
4324
|
const messages = socket.messages[Symbol.asyncIterator]();
|
|
4296
4325
|
for (; ; ) {
|
|
4297
|
-
const
|
|
4298
|
-
if (
|
|
4299
|
-
const data =
|
|
4326
|
+
const next3 = await Promise.race([messages.next(), unanswered]);
|
|
4327
|
+
if (next3 === "late" || next3.done) break;
|
|
4328
|
+
const data = next3.value;
|
|
4300
4329
|
if (flow.closing) continue;
|
|
4301
4330
|
if (payloadSize(data) > MESSAGE_LIMIT) {
|
|
4302
4331
|
oversize = true;
|
|
@@ -4337,12 +4366,12 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
4337
4366
|
const body = open.get(nid)?.body;
|
|
4338
4367
|
if (!body) return;
|
|
4339
4368
|
try {
|
|
4340
|
-
const
|
|
4341
|
-
if (
|
|
4369
|
+
const next3 = await body.next();
|
|
4370
|
+
if (next3.done) {
|
|
4342
4371
|
open.delete(nid);
|
|
4343
4372
|
peer.postMessage({ net: "end", nid });
|
|
4344
4373
|
} else {
|
|
4345
|
-
const bytes = fresh(
|
|
4374
|
+
const bytes = fresh(next3.value);
|
|
4346
4375
|
peer.postMessage({ net: "chunk", nid, bytes }, [bytes.buffer]);
|
|
4347
4376
|
}
|
|
4348
4377
|
} catch (e) {
|
|
@@ -4360,7 +4389,9 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
4360
4389
|
return {
|
|
4361
4390
|
answer(call) {
|
|
4362
4391
|
if (call.net === "fetch") void start2(call);
|
|
4363
|
-
else if (call.net === "
|
|
4392
|
+
else if (call.net === "body-chunk" || call.net === "body-end" || call.net === "body-error") {
|
|
4393
|
+
uploads.answer(call);
|
|
4394
|
+
} else if (call.net === "read") void read(call.nid);
|
|
4364
4395
|
else if (call.net === "ws-open") void openSocket(call);
|
|
4365
4396
|
else if (call.net === "ws-send") void sendOn(call);
|
|
4366
4397
|
else if (call.net === "ws-close") {
|
|
@@ -4570,9 +4601,9 @@ var UserDb = class {
|
|
|
4570
4601
|
}
|
|
4571
4602
|
}
|
|
4572
4603
|
serial(work) {
|
|
4573
|
-
const
|
|
4574
|
-
this.writing =
|
|
4575
|
-
return
|
|
4604
|
+
const next3 = this.writing.then(work);
|
|
4605
|
+
this.writing = next3.catch(() => void 0);
|
|
4606
|
+
return next3;
|
|
4576
4607
|
}
|
|
4577
4608
|
async ensure() {
|
|
4578
4609
|
await this.fs.mkdir("/etc", { recursive: true });
|
|
@@ -4744,14 +4775,14 @@ async function realpath(fs, path) {
|
|
|
4744
4775
|
let resolved2 = "";
|
|
4745
4776
|
for (let hops = 0; parts2.length > 0; ) {
|
|
4746
4777
|
const [name2, ...rest2] = parts2;
|
|
4747
|
-
const
|
|
4748
|
-
if (!(await fs.lstat(
|
|
4749
|
-
resolved2 =
|
|
4778
|
+
const next3 = `${resolved2}/${name2}`;
|
|
4779
|
+
if (!(await fs.lstat(next3)).isSymbolicLink) {
|
|
4780
|
+
resolved2 = next3;
|
|
4750
4781
|
parts2 = rest2;
|
|
4751
4782
|
continue;
|
|
4752
4783
|
}
|
|
4753
4784
|
if (++hops > MAX_LINKS5) throw fsError("ELOOP", path);
|
|
4754
|
-
const target = await fs.readlink(
|
|
4785
|
+
const target = await fs.readlink(next3);
|
|
4755
4786
|
const base = target.startsWith("/") ? "/" : resolved2 || "/";
|
|
4756
4787
|
parts2 = [...fs.resolvePath(base, target).split("/").filter(Boolean), ...rest2];
|
|
4757
4788
|
resolved2 = "";
|
|
@@ -5344,9 +5375,9 @@ var ClipboardBroker = class {
|
|
|
5344
5375
|
// src/clipboard-relay.ts
|
|
5345
5376
|
function clipboardAsker(port) {
|
|
5346
5377
|
const asks = /* @__PURE__ */ new Map();
|
|
5347
|
-
let
|
|
5378
|
+
let next3 = 0;
|
|
5348
5379
|
const ask = (op, stamp, text) => {
|
|
5349
|
-
const id2 = ++
|
|
5380
|
+
const id2 = ++next3;
|
|
5350
5381
|
const waiting = Promise.withResolvers();
|
|
5351
5382
|
asks.set(id2, waiting);
|
|
5352
5383
|
const timer = setTimeout(() => {
|
|
@@ -5374,9 +5405,9 @@ function clipboardAsker(port) {
|
|
|
5374
5405
|
// src/integrity-relay.ts
|
|
5375
5406
|
function integrityAsker(port) {
|
|
5376
5407
|
const asks = /* @__PURE__ */ new Map();
|
|
5377
|
-
let
|
|
5408
|
+
let next3 = 0;
|
|
5378
5409
|
const lookup2 = (path) => {
|
|
5379
|
-
const id2 = ++
|
|
5410
|
+
const id2 = ++next3;
|
|
5380
5411
|
const waiting = Promise.withResolvers();
|
|
5381
5412
|
asks.set(id2, waiting);
|
|
5382
5413
|
port.postMessage({ integrityAsk: { id: id2, path } });
|
|
@@ -5440,10 +5471,10 @@ var Incoming = class {
|
|
|
5440
5471
|
this.eof = true;
|
|
5441
5472
|
return false;
|
|
5442
5473
|
}
|
|
5443
|
-
const
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
this.buf =
|
|
5474
|
+
const next3 = new Uint8Array(this.buf.length + chunk2.length);
|
|
5475
|
+
next3.set(this.buf);
|
|
5476
|
+
next3.set(chunk2, this.buf.length);
|
|
5477
|
+
this.buf = next3;
|
|
5447
5478
|
return true;
|
|
5448
5479
|
}
|
|
5449
5480
|
take(n) {
|
|
@@ -5583,23 +5614,50 @@ async function readBody(incoming, framing, cap, signal) {
|
|
|
5583
5614
|
const chunks = [];
|
|
5584
5615
|
let total = 0;
|
|
5585
5616
|
for (; ; ) {
|
|
5586
|
-
const
|
|
5587
|
-
const size = /^([0-9A-Fa-f]{1,12})[ \t]*(;.*)?$/.exec(sizeLine);
|
|
5588
|
-
if (!size) throw new HttpError(400, "malformed chunk size");
|
|
5589
|
-
const n = Number.parseInt(size[1], 16);
|
|
5617
|
+
const n = await chunkSize(incoming, signal);
|
|
5590
5618
|
if (n === 0) break;
|
|
5591
5619
|
total += n;
|
|
5592
5620
|
if (total > cap) throw new HttpError(413, `request body over ${cap} bytes`);
|
|
5593
5621
|
chunks.push(await incoming.exactly(n, signal));
|
|
5594
5622
|
if (await incoming.line(2, signal) !== "") throw new HttpError(400, "malformed chunk");
|
|
5595
5623
|
}
|
|
5624
|
+
await skipTrailers(incoming, signal);
|
|
5625
|
+
return concat(chunks, total);
|
|
5626
|
+
}
|
|
5627
|
+
async function chunkSize(incoming, signal) {
|
|
5628
|
+
const sizeLine = await incoming.line(MAX_CHUNK_LINE, signal);
|
|
5629
|
+
const size = /^([0-9A-Fa-f]{1,12})[ \t]*(;.*)?$/.exec(sizeLine);
|
|
5630
|
+
if (!size) throw new HttpError(400, "malformed chunk size");
|
|
5631
|
+
return Number.parseInt(size[1], 16);
|
|
5632
|
+
}
|
|
5633
|
+
async function skipTrailers(incoming, signal) {
|
|
5596
5634
|
let trailers = 0;
|
|
5597
5635
|
for (let line = await incoming.line(MAX_TRAILERS, signal); line !== ""; ) {
|
|
5598
5636
|
trailers += line.length;
|
|
5599
5637
|
if (trailers > MAX_TRAILERS) throw new HttpError(431, "trailers too large");
|
|
5600
5638
|
line = await incoming.line(MAX_TRAILERS, signal);
|
|
5601
5639
|
}
|
|
5602
|
-
|
|
5640
|
+
}
|
|
5641
|
+
var STREAM_PIECE = 64 * 1024;
|
|
5642
|
+
async function* pieces(incoming, n, signal) {
|
|
5643
|
+
for (let left = n; left > 0; ) {
|
|
5644
|
+
const piece = await incoming.some(Math.min(left, STREAM_PIECE), signal);
|
|
5645
|
+
if (piece.length === 0) throw new HttpError(400, "connection closed inside a body");
|
|
5646
|
+
left -= piece.length;
|
|
5647
|
+
yield piece;
|
|
5648
|
+
}
|
|
5649
|
+
}
|
|
5650
|
+
async function* streamBody(incoming, framing, signal) {
|
|
5651
|
+
if (framing.kind === "none") return;
|
|
5652
|
+
if (framing.kind === "length") {
|
|
5653
|
+
yield* pieces(incoming, framing.length, signal);
|
|
5654
|
+
return;
|
|
5655
|
+
}
|
|
5656
|
+
for (let n = await chunkSize(incoming, signal); n !== 0; n = await chunkSize(incoming, signal)) {
|
|
5657
|
+
yield* pieces(incoming, n, signal);
|
|
5658
|
+
if (await incoming.line(2, signal) !== "") throw new HttpError(400, "malformed chunk");
|
|
5659
|
+
}
|
|
5660
|
+
await skipTrailers(incoming, signal);
|
|
5603
5661
|
}
|
|
5604
5662
|
function concat(chunks, total = chunks.reduce((n, c) => n + c.length, 0)) {
|
|
5605
5663
|
const out = new Uint8Array(total);
|
|
@@ -5708,11 +5766,11 @@ function frame(opcode, payload) {
|
|
|
5708
5766
|
return out;
|
|
5709
5767
|
}
|
|
5710
5768
|
function clientFrame(opcode, payload) {
|
|
5711
|
-
const
|
|
5712
|
-
const head =
|
|
5769
|
+
const plain2 = frame(opcode, payload);
|
|
5770
|
+
const head = plain2.length - payload.length;
|
|
5713
5771
|
const mask = crypto.getRandomValues(new Uint8Array(4));
|
|
5714
|
-
const out = new Uint8Array(
|
|
5715
|
-
out.set(
|
|
5772
|
+
const out = new Uint8Array(plain2.length + 4);
|
|
5773
|
+
out.set(plain2.subarray(0, head));
|
|
5716
5774
|
out[1] = out[1] | 128;
|
|
5717
5775
|
out.set(mask, head);
|
|
5718
5776
|
for (let i = 0; i < payload.length; i++) {
|
|
@@ -6045,6 +6103,11 @@ async function watchHangup(conn, abort, until) {
|
|
|
6045
6103
|
}
|
|
6046
6104
|
}
|
|
6047
6105
|
}
|
|
6106
|
+
var BODILESS_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD"]);
|
|
6107
|
+
async function* drain(body, done4) {
|
|
6108
|
+
yield* body;
|
|
6109
|
+
done4();
|
|
6110
|
+
}
|
|
6048
6111
|
function untilAborted(response, signal) {
|
|
6049
6112
|
return new Promise((resolve2, reject) => {
|
|
6050
6113
|
const onAbort = () => {
|
|
@@ -6187,7 +6250,8 @@ var RealmProxy = class {
|
|
|
6187
6250
|
const url = ctx.origin ? tunnelRequestUrl(req, ctx.origin) : requestUrl(req);
|
|
6188
6251
|
const keep2 = keepsAlive(req);
|
|
6189
6252
|
const framing = requestFraming(req.headers);
|
|
6190
|
-
const
|
|
6253
|
+
const streaming = this.options.transport.traits.streamingBodies === true && framing.kind !== "none" && !BODILESS_METHODS.has(req.method);
|
|
6254
|
+
const reserve = streaming ? 0 : framing.kind === "length" ? framing.length : framing.kind === "chunked" ? this.cap() : 0;
|
|
6191
6255
|
if (reserve > this.cap()) throw new HttpError(413, `request body over ${this.cap()} bytes`);
|
|
6192
6256
|
await this.expectContinue(conn, req, framing.kind !== "none");
|
|
6193
6257
|
await this.bodies.acquire(reserve, this.stop.signal);
|
|
@@ -6195,9 +6259,12 @@ var RealmProxy = class {
|
|
|
6195
6259
|
const abort = new AbortController();
|
|
6196
6260
|
const stopExchange = () => abort.abort();
|
|
6197
6261
|
this.stop.signal.addEventListener("abort", stopExchange, { once: true });
|
|
6262
|
+
let drained = !streaming;
|
|
6198
6263
|
try {
|
|
6199
6264
|
try {
|
|
6200
|
-
const body =
|
|
6265
|
+
const body = streaming ? drain(streamBody(incoming, framing, abort.signal), () => {
|
|
6266
|
+
drained = true;
|
|
6267
|
+
}) : await readBody(incoming, framing, this.cap());
|
|
6201
6268
|
const waiting = new AbortController();
|
|
6202
6269
|
void watchHangup(ctx.socket, abort, waiting.signal);
|
|
6203
6270
|
try {
|
|
@@ -6208,7 +6275,8 @@ var RealmProxy = class {
|
|
|
6208
6275
|
} finally {
|
|
6209
6276
|
this.bodies.release(reserve);
|
|
6210
6277
|
}
|
|
6211
|
-
|
|
6278
|
+
const kept = await this.relay(conn, req.method, req.minor, response, keep2 && drained);
|
|
6279
|
+
return kept && drained;
|
|
6212
6280
|
} finally {
|
|
6213
6281
|
this.stop.signal.removeEventListener("abort", stopExchange);
|
|
6214
6282
|
abort.abort();
|
|
@@ -6228,13 +6296,14 @@ var RealmProxy = class {
|
|
|
6228
6296
|
}
|
|
6229
6297
|
}
|
|
6230
6298
|
async upstream(req, url, body, signal, owner) {
|
|
6299
|
+
const sent = BODILESS_METHODS.has(req.method) ? void 0 : body;
|
|
6231
6300
|
try {
|
|
6232
6301
|
const fetching = this.options.transport.fetch(
|
|
6233
6302
|
{
|
|
6234
6303
|
url: toHostLoopback(url),
|
|
6235
6304
|
method: req.method.toUpperCase(),
|
|
6236
6305
|
headers: forwardRequestHeaders(req.headers),
|
|
6237
|
-
body:
|
|
6306
|
+
...sent instanceof Uint8Array ? { body: sent } : sent ? { bodyStream: sent } : {},
|
|
6238
6307
|
signal
|
|
6239
6308
|
},
|
|
6240
6309
|
owner
|
|
@@ -7152,12 +7221,17 @@ var RemoteTransport = class {
|
|
|
7152
7221
|
waiting = /* @__PURE__ */ new Map();
|
|
7153
7222
|
nextId = 0;
|
|
7154
7223
|
sockets = /* @__PURE__ */ new Map();
|
|
7224
|
+
uploads = /* @__PURE__ */ new Map();
|
|
7155
7225
|
failure;
|
|
7156
7226
|
constructor(port, traits) {
|
|
7157
7227
|
this.port = port;
|
|
7158
7228
|
this.traits = traits;
|
|
7159
7229
|
}
|
|
7160
7230
|
receive(reply) {
|
|
7231
|
+
if (reply.net === "body-pull") {
|
|
7232
|
+
void this.pull(reply.nid);
|
|
7233
|
+
return;
|
|
7234
|
+
}
|
|
7161
7235
|
const socket = this.sockets.get(reply.nid);
|
|
7162
7236
|
if (socket && this.toSocket(reply, socket)) return;
|
|
7163
7237
|
const waiter = this.waiting.get(reply.nid);
|
|
@@ -7176,8 +7250,35 @@ var RemoteTransport = class {
|
|
|
7176
7250
|
} else return false;
|
|
7177
7251
|
return true;
|
|
7178
7252
|
}
|
|
7253
|
+
async pull(nid) {
|
|
7254
|
+
const upload = this.uploads.get(nid);
|
|
7255
|
+
if (!upload) {
|
|
7256
|
+
this.port.postMessage({ net: "body-error", nid, message: "the request body is gone" });
|
|
7257
|
+
return;
|
|
7258
|
+
}
|
|
7259
|
+
try {
|
|
7260
|
+
const next3 = await upload.next();
|
|
7261
|
+
if (next3.done) {
|
|
7262
|
+
this.uploads.delete(nid);
|
|
7263
|
+
this.port.postMessage({ net: "body-end", nid });
|
|
7264
|
+
} else this.port.postMessage({ net: "body-chunk", nid, bytes: next3.value });
|
|
7265
|
+
} catch (e) {
|
|
7266
|
+
this.uploads.delete(nid);
|
|
7267
|
+
this.port.postMessage({
|
|
7268
|
+
net: "body-error",
|
|
7269
|
+
nid,
|
|
7270
|
+
message: e instanceof Error ? e.message : String(e)
|
|
7271
|
+
});
|
|
7272
|
+
}
|
|
7273
|
+
}
|
|
7274
|
+
dropUpload(nid) {
|
|
7275
|
+
const upload = this.uploads.get(nid);
|
|
7276
|
+
this.uploads.delete(nid);
|
|
7277
|
+
void upload?.return?.().catch(() => void 0);
|
|
7278
|
+
}
|
|
7179
7279
|
fail(error) {
|
|
7180
7280
|
this.failure = error;
|
|
7281
|
+
for (const nid of [...this.uploads.keys()]) this.dropUpload(nid);
|
|
7181
7282
|
for (const waiter of this.waiting.values()) waiter.reject(error);
|
|
7182
7283
|
this.waiting.clear();
|
|
7183
7284
|
for (const socket of this.sockets.values())
|
|
@@ -7204,14 +7305,17 @@ var RemoteTransport = class {
|
|
|
7204
7305
|
let finished = false;
|
|
7205
7306
|
const abort = () => {
|
|
7206
7307
|
finished = true;
|
|
7308
|
+
this.dropUpload(nid);
|
|
7207
7309
|
this.cancel(nid);
|
|
7208
7310
|
};
|
|
7209
7311
|
signal.addEventListener("abort", abort, { once: true });
|
|
7210
7312
|
const finish = () => {
|
|
7313
|
+
this.dropUpload(nid);
|
|
7211
7314
|
if (finished) return;
|
|
7212
7315
|
finished = true;
|
|
7213
7316
|
signal.removeEventListener("abort", abort);
|
|
7214
7317
|
};
|
|
7318
|
+
if (request2.bodyStream) this.uploads.set(nid, request2.bodyStream[Symbol.asyncIterator]());
|
|
7215
7319
|
let head;
|
|
7216
7320
|
try {
|
|
7217
7321
|
head = await this.ask({
|
|
@@ -7220,7 +7324,7 @@ var RemoteTransport = class {
|
|
|
7220
7324
|
url: request2.url,
|
|
7221
7325
|
method: request2.method,
|
|
7222
7326
|
headers: request2.headers,
|
|
7223
|
-
...request2.body ? { body: request2.body } : {}
|
|
7327
|
+
...request2.bodyStream ? { streamed: true } : request2.body ? { body: request2.body } : {}
|
|
7224
7328
|
});
|
|
7225
7329
|
} catch (e) {
|
|
7226
7330
|
finish();
|
|
@@ -7730,6 +7834,164 @@ function closeAll(entry) {
|
|
|
7730
7834
|
}
|
|
7731
7835
|
}
|
|
7732
7836
|
|
|
7837
|
+
// src/fs/engines.ts
|
|
7838
|
+
var NUMBER = /^(0|[1-9]\d*)$/;
|
|
7839
|
+
var PART = /^(?:0|[1-9]\d*|[xX*])$/;
|
|
7840
|
+
var IDENTIFIER = /^(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)$/;
|
|
7841
|
+
function identifiers(pre) {
|
|
7842
|
+
if (pre === void 0) return [];
|
|
7843
|
+
const ids = pre.split(".");
|
|
7844
|
+
return ids.every((id2) => IDENTIFIER.test(id2)) ? ids : void 0;
|
|
7845
|
+
}
|
|
7846
|
+
function parseVersion(text) {
|
|
7847
|
+
const m = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(text.trim());
|
|
7848
|
+
const pre = identifiers(m?.[4]);
|
|
7849
|
+
if (!m || !pre || ![m[1], m[2], m[3]].every((n) => NUMBER.test(n))) return void 0;
|
|
7850
|
+
return [Number(m[1]), Number(m[2]), Number(m[3]), pre];
|
|
7851
|
+
}
|
|
7852
|
+
function comparePre(a, b) {
|
|
7853
|
+
if (a.length === 0 || b.length === 0) return b.length - a.length;
|
|
7854
|
+
for (let i = 0; i < Math.max(a.length, b.length); i++) {
|
|
7855
|
+
const [x, y] = [a[i], b[i]];
|
|
7856
|
+
if (x === void 0 || y === void 0) return x === void 0 ? -1 : 1;
|
|
7857
|
+
if (x === y) continue;
|
|
7858
|
+
const [nx, ny] = [NUMBER.test(x), NUMBER.test(y)];
|
|
7859
|
+
if (nx && ny) return Number(x) - Number(y);
|
|
7860
|
+
if (nx !== ny) return nx ? -1 : 1;
|
|
7861
|
+
return x < y ? -1 : 1;
|
|
7862
|
+
}
|
|
7863
|
+
return 0;
|
|
7864
|
+
}
|
|
7865
|
+
function compare(a, b) {
|
|
7866
|
+
return a[0] - b[0] || a[1] - b[1] || a[2] - b[2] || comparePre(a[3], b[3]);
|
|
7867
|
+
}
|
|
7868
|
+
function partial(text) {
|
|
7869
|
+
const m = /^v?([^.+-]+)(?:\.([^.+-]+))?(?:\.([^.+-]+))?(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(
|
|
7870
|
+
text
|
|
7871
|
+
);
|
|
7872
|
+
if (!m) return void 0;
|
|
7873
|
+
const raw = [m[1], m[2], m[3]];
|
|
7874
|
+
if (!raw.every((p) => p === void 0 || PART.test(p))) return void 0;
|
|
7875
|
+
const parts2 = [];
|
|
7876
|
+
for (const p of raw) {
|
|
7877
|
+
if (p === void 0 || /^[xX*]$/.test(p) || parts2.includes(void 0)) parts2.push(void 0);
|
|
7878
|
+
else parts2.push(Number(p));
|
|
7879
|
+
}
|
|
7880
|
+
const pre = identifiers(m[4]);
|
|
7881
|
+
return pre && { parts: parts2, pre };
|
|
7882
|
+
}
|
|
7883
|
+
function floor(p) {
|
|
7884
|
+
const [a = 0, b = 0, c = 0] = p.parts;
|
|
7885
|
+
return [a, b, c, p.parts.includes(void 0) ? [] : p.pre];
|
|
7886
|
+
}
|
|
7887
|
+
function next(p) {
|
|
7888
|
+
const [a, b] = p.parts;
|
|
7889
|
+
if (a === void 0) return void 0;
|
|
7890
|
+
if (b === void 0) return [a + 1, 0, 0, ["0"]];
|
|
7891
|
+
return [a, b + 1, 0, ["0"]];
|
|
7892
|
+
}
|
|
7893
|
+
var ANY = [[">=", [0, 0, 0, []]]];
|
|
7894
|
+
var NOTHING = [["<", [0, 0, 0, ["0"]]]];
|
|
7895
|
+
function plain(op, p) {
|
|
7896
|
+
const exact = !p.parts.includes(void 0);
|
|
7897
|
+
const low = floor(p);
|
|
7898
|
+
const high = next(p);
|
|
7899
|
+
if (op === ">=") return [[">=", low]];
|
|
7900
|
+
if (op === "<") return [["<", exact ? low : [low[0], low[1], low[2], ["0"]]]];
|
|
7901
|
+
if (exact) return [[op === "" ? "=" : op, low]];
|
|
7902
|
+
if (op === ">") return high ? [[">=", high]] : NOTHING;
|
|
7903
|
+
if (op === "<=") return high ? [["<", high]] : ANY;
|
|
7904
|
+
return high ? [
|
|
7905
|
+
[">=", low],
|
|
7906
|
+
["<", high]
|
|
7907
|
+
] : ANY;
|
|
7908
|
+
}
|
|
7909
|
+
function caret(p) {
|
|
7910
|
+
const [a = 0, b, c] = p.parts;
|
|
7911
|
+
const low = floor(p);
|
|
7912
|
+
if (b === void 0)
|
|
7913
|
+
return [
|
|
7914
|
+
[">=", low],
|
|
7915
|
+
["<", [a + 1, 0, 0, ["0"]]]
|
|
7916
|
+
];
|
|
7917
|
+
if (a > 0)
|
|
7918
|
+
return [
|
|
7919
|
+
[">=", low],
|
|
7920
|
+
["<", [a + 1, 0, 0, ["0"]]]
|
|
7921
|
+
];
|
|
7922
|
+
if (c === void 0 || b > 0)
|
|
7923
|
+
return [
|
|
7924
|
+
[">=", low],
|
|
7925
|
+
["<", [0, b + 1, 0, ["0"]]]
|
|
7926
|
+
];
|
|
7927
|
+
return [
|
|
7928
|
+
[">=", low],
|
|
7929
|
+
["<", [0, b, c + 1, ["0"]]]
|
|
7930
|
+
];
|
|
7931
|
+
}
|
|
7932
|
+
function tilde(p) {
|
|
7933
|
+
const [a = 0, b] = p.parts;
|
|
7934
|
+
const low = floor(p);
|
|
7935
|
+
return [
|
|
7936
|
+
[">=", low],
|
|
7937
|
+
["<", b === void 0 ? [a + 1, 0, 0, ["0"]] : [a, b + 1, 0, ["0"]]]
|
|
7938
|
+
];
|
|
7939
|
+
}
|
|
7940
|
+
function hyphen(from, to) {
|
|
7941
|
+
const high = to.parts.includes(void 0) ? next(to) : void 0;
|
|
7942
|
+
const upper = to.parts.includes(void 0) ? high ? [["<", high]] : [] : [["<=", floor(to)]];
|
|
7943
|
+
return [[">=", floor(from)], ...upper];
|
|
7944
|
+
}
|
|
7945
|
+
function comparator(token) {
|
|
7946
|
+
const m = /^(<=|>=|<|>|=|\^|~>?)?\s*(.*)$/.exec(token);
|
|
7947
|
+
const op = m?.[1] ?? "";
|
|
7948
|
+
const p = partial(m?.[2] ?? "");
|
|
7949
|
+
if (!p) return void 0;
|
|
7950
|
+
const wild = p.parts[0] === void 0;
|
|
7951
|
+
if (op === "^") return wild ? ANY : caret(p);
|
|
7952
|
+
if (op.startsWith("~")) return wild ? ANY : tilde(p);
|
|
7953
|
+
return plain(op, p);
|
|
7954
|
+
}
|
|
7955
|
+
function set2(text) {
|
|
7956
|
+
const trimmed = text.trim().replace(/(<=|>=|<|>|=|\^|~>?)\s+/g, "$1");
|
|
7957
|
+
if (trimmed === "") return ANY;
|
|
7958
|
+
const range = /^(\S+)\s+-\s+(\S+)$/.exec(trimmed);
|
|
7959
|
+
if (range) {
|
|
7960
|
+
const [from, to] = [partial(range[1]), partial(range[2])];
|
|
7961
|
+
return from && to ? hyphen(from, to) : void 0;
|
|
7962
|
+
}
|
|
7963
|
+
const out = [];
|
|
7964
|
+
for (const token of trimmed.split(/\s+/)) {
|
|
7965
|
+
const found = comparator(token);
|
|
7966
|
+
if (!found) return void 0;
|
|
7967
|
+
out.push(...found);
|
|
7968
|
+
}
|
|
7969
|
+
return out;
|
|
7970
|
+
}
|
|
7971
|
+
function holds(v, [op, w]) {
|
|
7972
|
+
const c = compare(v, w);
|
|
7973
|
+
if (op === "<") return c < 0;
|
|
7974
|
+
if (op === "<=") return c <= 0;
|
|
7975
|
+
if (op === ">") return c > 0;
|
|
7976
|
+
if (op === ">=") return c >= 0;
|
|
7977
|
+
return c === 0;
|
|
7978
|
+
}
|
|
7979
|
+
function satisfies(version, range) {
|
|
7980
|
+
const v = parseVersion(version);
|
|
7981
|
+
if (!v) return void 0;
|
|
7982
|
+
const sets = range.split("||").map(set2);
|
|
7983
|
+
if (sets.some((s) => s === void 0)) return void 0;
|
|
7984
|
+
return sets.some((s) => s.every((c) => holds(v, c)));
|
|
7985
|
+
}
|
|
7986
|
+
|
|
7987
|
+
// src/version.ts
|
|
7988
|
+
var KERNEL_VERSION = true ? "1.106.2" : "0.0.0-dev";
|
|
7989
|
+
var OS_RELEASE = "6.0.0-slicc";
|
|
7990
|
+
function procVersion() {
|
|
7991
|
+
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
7992
|
+
`;
|
|
7993
|
+
}
|
|
7994
|
+
|
|
7733
7995
|
// src/commands.ts
|
|
7734
7996
|
var NAME2 = /^[A-Za-z0-9._+-]+$/;
|
|
7735
7997
|
var COMMAND_NAME = /^[^/\s\p{Cc}]+$/u;
|
|
@@ -7941,13 +8203,25 @@ async function binCommandsOf(physical, pkg, manifest, taken) {
|
|
|
7941
8203
|
}
|
|
7942
8204
|
return out;
|
|
7943
8205
|
}
|
|
8206
|
+
function engineRefusal(manifest, kernel) {
|
|
8207
|
+
const engines = manifest.engines;
|
|
8208
|
+
const range = engines && typeof engines === "object" ? engines["slicc-kernel"] : void 0;
|
|
8209
|
+
const running = parseVersion(kernel);
|
|
8210
|
+
if (typeof range !== "string" || !running || running.slice(0, 3).every((n) => n === 0)) {
|
|
8211
|
+
return void 0;
|
|
8212
|
+
}
|
|
8213
|
+
const fits = satisfies(kernel, range);
|
|
8214
|
+
if (fits) return void 0;
|
|
8215
|
+
const who = `${String(manifest.name ?? "?")}@${String(manifest.version ?? "?")}`;
|
|
8216
|
+
return fits === false ? `${who} needs slicc-kernel ${range}; this kernel is ${kernel}` : `${who} has an engines.slicc-kernel range this kernel can't read: ${JSON.stringify(range)}`;
|
|
8217
|
+
}
|
|
7944
8218
|
var PACKAGE_NAME = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
|
|
7945
8219
|
function replacesOf(manifest) {
|
|
7946
8220
|
const replaces = manifest.slicc?.replaces;
|
|
7947
8221
|
if (!Array.isArray(replaces)) return [];
|
|
7948
8222
|
return replaces.every((name2) => typeof name2 === "string" && PACKAGE_NAME.test(name2)) ? replaces : [];
|
|
7949
8223
|
}
|
|
7950
|
-
async function tierPackages(fs, physical, roots, bins) {
|
|
8224
|
+
async function tierPackages(fs, physical, roots, bins, kernel) {
|
|
7951
8225
|
const out = [];
|
|
7952
8226
|
for (const root of roots) {
|
|
7953
8227
|
for (const pkg of await packages(fs, root)) {
|
|
@@ -7960,11 +8234,13 @@ async function tierPackages(fs, physical, roots, bins) {
|
|
|
7960
8234
|
const own = commandsOf(pkg, manifest);
|
|
7961
8235
|
const named = new Set(own.map((command) => command.name));
|
|
7962
8236
|
const extra = bins ? await binCommandsOf(physical, pkg, manifest, named) : [];
|
|
8237
|
+
const refused2 = engineRefusal(manifest, kernel);
|
|
8238
|
+
const commands = [...own, ...extra];
|
|
7963
8239
|
out.push({
|
|
7964
8240
|
name: pkg.slice(root.length + 1),
|
|
7965
8241
|
pkg,
|
|
7966
8242
|
replaces: replacesOf(manifest),
|
|
7967
|
-
commands:
|
|
8243
|
+
commands: refused2 ? commands.map((command) => ({ ...command, refused: refused2 })) : commands
|
|
7968
8244
|
});
|
|
7969
8245
|
}
|
|
7970
8246
|
}
|
|
@@ -7990,14 +8266,14 @@ function winners(tier) {
|
|
|
7990
8266
|
}
|
|
7991
8267
|
return out;
|
|
7992
8268
|
}
|
|
7993
|
-
async function scanCommands(fs, modules, binsFrom = Number.POSITIVE_INFINITY) {
|
|
8269
|
+
async function scanCommands(fs, modules, binsFrom = Number.POSITIVE_INFINITY, kernel = KERNEL_VERSION) {
|
|
7994
8270
|
const found = /* @__PURE__ */ new Map();
|
|
7995
8271
|
const physical = physicalResolver(fs);
|
|
7996
8272
|
const tiers = (typeof modules === "string" ? [modules] : modules).map(
|
|
7997
8273
|
(tier) => typeof tier === "string" ? [tier] : tier
|
|
7998
8274
|
);
|
|
7999
8275
|
for (const [index, roots] of tiers.entries()) {
|
|
8000
|
-
const tier = await tierPackages(fs, physical, roots, index >= binsFrom);
|
|
8276
|
+
const tier = await tierPackages(fs, physical, roots, index >= binsFrom, kernel);
|
|
8001
8277
|
for (const [name2, { pkg, command }] of winners(tier)) {
|
|
8002
8278
|
if (!found.has(name2)) found.set(name2, await withPackagePaths(fs, pkg, command));
|
|
8003
8279
|
}
|
|
@@ -8374,6 +8650,7 @@ var S_IFDIR2 = 16384;
|
|
|
8374
8650
|
var S_IFREG2 = 32768;
|
|
8375
8651
|
var COMMAND = /^\/(?:usr\/)?bin\/([^/]+)$/;
|
|
8376
8652
|
var MAX_LINKS6 = 40;
|
|
8653
|
+
var BIN_ENTRY = /\/bin\/[^/]+$/;
|
|
8377
8654
|
function missing3(err) {
|
|
8378
8655
|
return err?.code === "ENOENT";
|
|
8379
8656
|
}
|
|
@@ -8401,7 +8678,20 @@ async function followLinks(fs, path) {
|
|
|
8401
8678
|
}
|
|
8402
8679
|
return current;
|
|
8403
8680
|
}
|
|
8404
|
-
|
|
8681
|
+
var NOBODY = { ruid: -1, euid: -1, suid: -1, rgid: -1, egid: -1, sgid: -1, groups: [] };
|
|
8682
|
+
var EMPTY = new Uint8Array(0);
|
|
8683
|
+
function quiet(promise) {
|
|
8684
|
+
return promise.catch(() => void 0);
|
|
8685
|
+
}
|
|
8686
|
+
async function readsAs2(fs, cred, target) {
|
|
8687
|
+
const walked = await quiet(access(fs, cred, target, R_OK, { directory: false }));
|
|
8688
|
+
return walked !== void 0 && walked.denied === void 0 && !walked.missing;
|
|
8689
|
+
}
|
|
8690
|
+
async function shownTarget(fs, target) {
|
|
8691
|
+
const st = await quiet(fs.stat(target));
|
|
8692
|
+
return st?.isFile && await readsAs2(fs, NOBODY, target) ? st : void 0;
|
|
8693
|
+
}
|
|
8694
|
+
function withCommandDirs(fs, names, userDir = async () => void 0, owners = false, targetOf2 = async () => void 0) {
|
|
8405
8695
|
async function nearest(path) {
|
|
8406
8696
|
const st = await fs.stat(path).catch(() => void 0);
|
|
8407
8697
|
if (st || path === "/") return st ?? {};
|
|
@@ -8433,9 +8723,54 @@ function withCommandDirs(fs, names, userDir = async () => void 0, owners = false
|
|
|
8433
8723
|
const own = await userDir(dir);
|
|
8434
8724
|
return own?.has(path.slice(slash + 1)) ? owned4(synthetic(false, path), dir) : void 0;
|
|
8435
8725
|
}
|
|
8726
|
+
let generation;
|
|
8727
|
+
const targets = /* @__PURE__ */ new Map();
|
|
8728
|
+
async function targetStat(target) {
|
|
8729
|
+
const now = await names();
|
|
8730
|
+
if (now !== generation) {
|
|
8731
|
+
generation = now;
|
|
8732
|
+
targets.clear();
|
|
8733
|
+
}
|
|
8734
|
+
let found = targets.get(target);
|
|
8735
|
+
if (!found) {
|
|
8736
|
+
found = shownTarget(fs, target);
|
|
8737
|
+
targets.set(target, found);
|
|
8738
|
+
}
|
|
8739
|
+
return found;
|
|
8740
|
+
}
|
|
8741
|
+
async function shown(path) {
|
|
8742
|
+
const st = await virtual(path);
|
|
8743
|
+
if (!st?.isFile) return st;
|
|
8744
|
+
const target = await targetOf2(path);
|
|
8745
|
+
const real = target === void 0 ? void 0 : await targetStat(target.path);
|
|
8746
|
+
return real ? { ...st, size: real.size, mtime: real.mtime, ctime: real.mtime, atime: real.mtime } : st;
|
|
8747
|
+
}
|
|
8436
8748
|
async function linked2(path) {
|
|
8437
|
-
return await
|
|
8749
|
+
return await shown(path) ?? shown(await followLinks(fs, path));
|
|
8750
|
+
}
|
|
8751
|
+
async function entryTarget(path) {
|
|
8752
|
+
if (!BIN_ENTRY.test(path) || !(await virtual(path))?.isFile) return void 0;
|
|
8753
|
+
if (!await fs.lstat(path).then(() => false, missing3)) return void 0;
|
|
8754
|
+
const target = await targetOf2(path);
|
|
8755
|
+
return target?.path === path ? void 0 : target;
|
|
8756
|
+
}
|
|
8757
|
+
async function redirected2(path) {
|
|
8758
|
+
const target = await entryTarget(path) ?? await entryTarget(await followLinks(fs, path));
|
|
8759
|
+
if (owners && target?.owner && !await readsAs2(fs, target.owner, target.path)) {
|
|
8760
|
+
throw fsError("EACCES", path);
|
|
8761
|
+
}
|
|
8762
|
+
return target?.path;
|
|
8438
8763
|
}
|
|
8764
|
+
const absent2 = (err) => {
|
|
8765
|
+
if (missing3(err)) return EMPTY;
|
|
8766
|
+
throw err;
|
|
8767
|
+
};
|
|
8768
|
+
async function content(path, err) {
|
|
8769
|
+
if (!missing3(err) || !(await linked2(path))?.isFile) throw err;
|
|
8770
|
+
const target = await redirected2(path);
|
|
8771
|
+
return target === void 0 ? EMPTY : fs.readFileBuffer(target).catch(absent2);
|
|
8772
|
+
}
|
|
8773
|
+
const ranged2 = rangedOps(fs);
|
|
8439
8774
|
async function stat(path, real) {
|
|
8440
8775
|
try {
|
|
8441
8776
|
return await real(path);
|
|
@@ -8447,16 +8782,13 @@ function withCommandDirs(fs, names, userDir = async () => void 0, owners = false
|
|
|
8447
8782
|
}
|
|
8448
8783
|
return {
|
|
8449
8784
|
resolvePath: (base, path) => fs.resolvePath(base, path),
|
|
8450
|
-
readFile: (path) => fs.readFile(path)
|
|
8451
|
-
|
|
8452
|
-
|
|
8453
|
-
|
|
8454
|
-
|
|
8455
|
-
|
|
8456
|
-
|
|
8457
|
-
}
|
|
8458
|
-
},
|
|
8459
|
-
writeFile: (path, content, owner) => fs.writeFile(path, content, owner),
|
|
8785
|
+
readFile: (path) => fs.readFile(path).catch(async (err) => {
|
|
8786
|
+
if (!BIN_ENTRY.test(await followLinks(fs, path))) throw err;
|
|
8787
|
+
return new TextDecoder().decode(await content(path, err));
|
|
8788
|
+
}),
|
|
8789
|
+
readFileBuffer: (path) => fs.readFileBuffer(path).catch((err) => content(path, err)),
|
|
8790
|
+
commandTarget: async (path) => (await entryTarget(path))?.path,
|
|
8791
|
+
writeFile: (path, content2, owner) => fs.writeFile(path, content2, owner),
|
|
8460
8792
|
link: (from, to, follow2) => fs.link(from, to, follow2),
|
|
8461
8793
|
links: (path) => mayLink(fs, path),
|
|
8462
8794
|
async exists(path) {
|
|
@@ -8487,7 +8819,7 @@ function withCommandDirs(fs, names, userDir = async () => void 0, owners = false
|
|
|
8487
8819
|
added.map(
|
|
8488
8820
|
async (name2) => [
|
|
8489
8821
|
name2,
|
|
8490
|
-
await
|
|
8822
|
+
await shown(`${base}/${name2}`)
|
|
8491
8823
|
]
|
|
8492
8824
|
)
|
|
8493
8825
|
);
|
|
@@ -8505,7 +8837,14 @@ function withCommandDirs(fs, names, userDir = async () => void 0, owners = false
|
|
|
8505
8837
|
chmod: (path, mode) => fs.chmod(path, mode),
|
|
8506
8838
|
utimes: (path, atime, mtime) => fs.utimes(path, atime, mtime),
|
|
8507
8839
|
lutimes: (path, atime, mtime) => lutimesOf(fs, path, atime, mtime),
|
|
8508
|
-
...
|
|
8840
|
+
...ranged2 ? {
|
|
8841
|
+
...ranged2,
|
|
8842
|
+
pread: (path, offset, length2, version) => ranged2.pread(path, offset, length2, version).catch(async (err) => {
|
|
8843
|
+
const target = missing3(err) ? await redirected2(path) : void 0;
|
|
8844
|
+
if (target === void 0) throw err;
|
|
8845
|
+
return ranged2.pread(target, offset, length2).catch(absent2);
|
|
8846
|
+
})
|
|
8847
|
+
} : {}
|
|
8509
8848
|
};
|
|
8510
8849
|
}
|
|
8511
8850
|
|
|
@@ -8650,7 +8989,7 @@ var MAX_HOPS2 = 40;
|
|
|
8650
8989
|
function start(path) {
|
|
8651
8990
|
return { done: [], todo: path.split("/").filter((p) => p !== ""), hops: 0 };
|
|
8652
8991
|
}
|
|
8653
|
-
function
|
|
8992
|
+
function next2(walk2) {
|
|
8654
8993
|
while (walk2.todo.length > 0) {
|
|
8655
8994
|
const part = walk2.todo.shift();
|
|
8656
8995
|
if (part === ".") continue;
|
|
@@ -8664,7 +9003,7 @@ function next(walk2) {
|
|
|
8664
9003
|
}
|
|
8665
9004
|
function lexical(path) {
|
|
8666
9005
|
const walk2 = start(path);
|
|
8667
|
-
for (let part =
|
|
9006
|
+
for (let part = next2(walk2); part !== void 0; part = next2(walk2)) walk2.done.push(part);
|
|
8668
9007
|
return `/${walk2.done.join("/")}`;
|
|
8669
9008
|
}
|
|
8670
9009
|
function rest(walk2, part) {
|
|
@@ -8678,7 +9017,7 @@ function follow(walk2, target) {
|
|
|
8678
9017
|
}
|
|
8679
9018
|
async function physicalPathAsync(fs, path) {
|
|
8680
9019
|
const walk2 = start(path);
|
|
8681
|
-
for (let part =
|
|
9020
|
+
for (let part = next2(walk2); part !== void 0; part = next2(walk2)) {
|
|
8682
9021
|
const at = `/${[...walk2.done, part].join("/")}`;
|
|
8683
9022
|
let target;
|
|
8684
9023
|
try {
|
|
@@ -8751,9 +9090,9 @@ var UnlinkedKeeper = class {
|
|
|
8751
9090
|
void locks?.request(lockName(this.instance), () => new Promise(() => void 0));
|
|
8752
9091
|
}
|
|
8753
9092
|
serial(op) {
|
|
8754
|
-
const
|
|
8755
|
-
this.queue =
|
|
8756
|
-
return
|
|
9093
|
+
const next3 = this.queue.then(op);
|
|
9094
|
+
this.queue = next3.catch(() => void 0);
|
|
9095
|
+
return next3;
|
|
8757
9096
|
}
|
|
8758
9097
|
wrap(fs = this.fs) {
|
|
8759
9098
|
const keeper = this;
|
|
@@ -9198,7 +9537,8 @@ var ChildTable = class {
|
|
|
9198
9537
|
const child = this.children.get(pid);
|
|
9199
9538
|
if (!child) return;
|
|
9200
9539
|
this.watchers.set(pid, listener);
|
|
9201
|
-
if (child.stoppedBy !== void 0
|
|
9540
|
+
if (child.stoppedBy !== void 0 && child.code === void 0)
|
|
9541
|
+
listener("stopped", child.stoppedBy);
|
|
9202
9542
|
}
|
|
9203
9543
|
openSlot(slot2, n, captured) {
|
|
9204
9544
|
if ("fd" in slot2) return this.parentFds.get(slot2.fd).retain();
|
|
@@ -9496,14 +9836,14 @@ var HeldSet = class extends Set {
|
|
|
9496
9836
|
super();
|
|
9497
9837
|
this.idle = idle;
|
|
9498
9838
|
}
|
|
9499
|
-
add(
|
|
9500
|
-
|
|
9501
|
-
return super.add(
|
|
9839
|
+
add(holds2) {
|
|
9840
|
+
holds2.onIdle = this.idle;
|
|
9841
|
+
return super.add(holds2);
|
|
9502
9842
|
}
|
|
9503
|
-
delete(
|
|
9504
|
-
const removed = super.delete(
|
|
9505
|
-
for (const path of /* @__PURE__ */ new Set([...
|
|
9506
|
-
|
|
9843
|
+
delete(holds2) {
|
|
9844
|
+
const removed = super.delete(holds2);
|
|
9845
|
+
for (const path of /* @__PURE__ */ new Set([...holds2.keys(), ...holds2.opens.keys()])) this.idle(path);
|
|
9846
|
+
holds2.releaseAll();
|
|
9507
9847
|
return removed;
|
|
9508
9848
|
}
|
|
9509
9849
|
};
|
|
@@ -10690,9 +11030,9 @@ var MountFs = class _MountFs {
|
|
|
10690
11030
|
this.writable(mount, real);
|
|
10691
11031
|
const { uid, gid, mode } = change;
|
|
10692
11032
|
const fresh2 = change.kind === "new" && { uid, gid, mode };
|
|
10693
|
-
const
|
|
11033
|
+
const set3 = fresh2 ? await this.driverOwner(found, real, fresh2, false) : change;
|
|
10694
11034
|
this.table.forget(mount, real);
|
|
10695
|
-
const attrs = Object.entries({ uid:
|
|
11035
|
+
const attrs = Object.entries({ uid: set3.uid, gid: set3.gid, mode: set3.mode });
|
|
10696
11036
|
await mount.conn.call({
|
|
10697
11037
|
op: "setattr",
|
|
10698
11038
|
path: rel2,
|
|
@@ -10719,11 +11059,11 @@ var MountFs = class _MountFs {
|
|
|
10719
11059
|
const real = await this.follow(path);
|
|
10720
11060
|
const found = this.at(real);
|
|
10721
11061
|
if (!found) {
|
|
10722
|
-
const
|
|
11062
|
+
const set3 = () => this.base.utimes(real, atime, mtime);
|
|
10723
11063
|
return this.based(
|
|
10724
11064
|
[real],
|
|
10725
11065
|
redirects,
|
|
10726
|
-
|
|
11066
|
+
set3,
|
|
10727
11067
|
([to], n) => this.utimes(to, atime, mtime, n)
|
|
10728
11068
|
);
|
|
10729
11069
|
}
|
|
@@ -10732,11 +11072,11 @@ var MountFs = class _MountFs {
|
|
|
10732
11072
|
async lutimes(path, atime, mtime, redirects = 0) {
|
|
10733
11073
|
const found = this.at(path);
|
|
10734
11074
|
if (!found) {
|
|
10735
|
-
const
|
|
11075
|
+
const set3 = () => lutimesOf(this.base, path, atime, mtime);
|
|
10736
11076
|
return this.based(
|
|
10737
11077
|
[path],
|
|
10738
11078
|
redirects,
|
|
10739
|
-
|
|
11079
|
+
set3,
|
|
10740
11080
|
([to], n) => this.lutimes(to, atime, mtime, n)
|
|
10741
11081
|
);
|
|
10742
11082
|
}
|
|
@@ -10758,6 +11098,20 @@ var MountFs = class _MountFs {
|
|
|
10758
11098
|
}
|
|
10759
11099
|
};
|
|
10760
11100
|
|
|
11101
|
+
// src/fs/command-stat.ts
|
|
11102
|
+
async function callerStat(g, path, st) {
|
|
11103
|
+
if (!g?.fs.commandTarget || !st.isFile || st.size > 0) return st;
|
|
11104
|
+
const target = await g.fs.commandTarget(path);
|
|
11105
|
+
if (target === void 0) return st;
|
|
11106
|
+
const options = { directory: false, ...g.links === void 0 ? {} : { links: g.links } };
|
|
11107
|
+
const walked = await access(g.fs, g.cred, target, R_OK, options).catch(() => void 0);
|
|
11108
|
+
if (!walked || walked.denied !== void 0 || walked.missing) return st;
|
|
11109
|
+
const real = await g.fs.stat(target).catch(() => void 0);
|
|
11110
|
+
if (!real?.isFile) return st;
|
|
11111
|
+
const { size, mtime } = real;
|
|
11112
|
+
return { ...st, size, mtime, atime: mtime, ctime: mtime };
|
|
11113
|
+
}
|
|
11114
|
+
|
|
10761
11115
|
// src/realm/sync-fs-token-registry.ts
|
|
10762
11116
|
var registry = /* @__PURE__ */ new Map();
|
|
10763
11117
|
function mintSyncFsToken(entry) {
|
|
@@ -10844,8 +11198,10 @@ function statJson(s) {
|
|
|
10844
11198
|
...s.gid !== void 0 ? { gid: s.gid } : {}
|
|
10845
11199
|
};
|
|
10846
11200
|
}
|
|
10847
|
-
async function readdirStat(fs, dir) {
|
|
10848
|
-
|
|
11201
|
+
async function readdirStat(fs, dir, g) {
|
|
11202
|
+
const listed = await fs.readdirStat(dir);
|
|
11203
|
+
const shown = async (name2, stat) => stat && statJson(await callerStat(g, joinName(dir, name2), stat));
|
|
11204
|
+
return Promise.all(listed.map(async ([name2, stat]) => [name2, await shown(name2, stat)]));
|
|
10849
11205
|
}
|
|
10850
11206
|
async function usageAt(entry, path) {
|
|
10851
11207
|
if (!entry.statfs) return void 0;
|
|
@@ -10914,18 +11270,22 @@ async function chown(entry, path, req) {
|
|
|
10914
11270
|
}
|
|
10915
11271
|
async function runMkdir(entry, path, req) {
|
|
10916
11272
|
const { fs } = entry;
|
|
10917
|
-
const
|
|
11273
|
+
const plain2 = plainDirMode(entry, req.mode);
|
|
10918
11274
|
const parentsMode = !req.exclusive ? plainParentsMode(entry) : void 0;
|
|
10919
11275
|
const fixParents = parentsMode !== void 0 ? await missingParents(fs, path, parentsMode) : void 0;
|
|
10920
|
-
const fresh2 =
|
|
11276
|
+
const fresh2 = plain2 !== void 0 && !await fs.exists(path);
|
|
10921
11277
|
await (req.exclusive ? mkdirExclusive(entry, path, req.mode) : fs.mkdir(path, mkdirOptions(entry, req.mode)));
|
|
10922
11278
|
await fixParents?.();
|
|
10923
|
-
if (fresh2) await fs.chmod(path,
|
|
11279
|
+
if (fresh2) await fs.chmod(path, plain2);
|
|
10924
11280
|
return done;
|
|
10925
11281
|
}
|
|
11282
|
+
async function shownAs(entry, path, st) {
|
|
11283
|
+
const real = st.isFile && st.size === 0 ? entry.fs.realpath?.(path, true) : void 0;
|
|
11284
|
+
return callerStat(guardOf(entry), await real?.catch(() => path) ?? path, st);
|
|
11285
|
+
}
|
|
10926
11286
|
function readSource(entry, path) {
|
|
10927
|
-
const
|
|
10928
|
-
return entry.source ? entry.source.read(path,
|
|
11287
|
+
const plain2 = () => entry.fs.readFileBuffer(path);
|
|
11288
|
+
return entry.source ? entry.source.read(path, plain2) : plain2();
|
|
10929
11289
|
}
|
|
10930
11290
|
async function run(entry, path, req) {
|
|
10931
11291
|
const { fs, cwd } = entry;
|
|
@@ -10938,13 +11298,13 @@ async function run(entry, path, req) {
|
|
|
10938
11298
|
case "exists":
|
|
10939
11299
|
return json2(await fs.exists(path));
|
|
10940
11300
|
case "stat":
|
|
10941
|
-
return json2(statJson(await fs.stat(path)));
|
|
11301
|
+
return json2(statJson(await shownAs(entry, path, await fs.stat(path))));
|
|
10942
11302
|
case "lstat":
|
|
10943
|
-
return json2(statJson(await fs.lstat(path)));
|
|
11303
|
+
return json2(statJson(await shownAs(entry, path, await fs.lstat(path))));
|
|
10944
11304
|
case "readdir":
|
|
10945
11305
|
return json2(await fs.readdir(path));
|
|
10946
11306
|
case "readdir-stat":
|
|
10947
|
-
return json2(await readdirStat(fs, path));
|
|
11307
|
+
return json2(await readdirStat(fs, path, guardOf(entry)));
|
|
10948
11308
|
case "mkdir":
|
|
10949
11309
|
return runMkdir(entry, path, req);
|
|
10950
11310
|
case "rm":
|
|
@@ -11866,18 +12226,18 @@ var KernelDgram = class {
|
|
|
11866
12226
|
const pending = this.takeError();
|
|
11867
12227
|
if (pending) throw new KernelError(pending);
|
|
11868
12228
|
if (this.closed) throw new KernelError("EBADF");
|
|
11869
|
-
const
|
|
11870
|
-
if (
|
|
12229
|
+
const next3 = this.queue[0];
|
|
12230
|
+
if (next3) {
|
|
11871
12231
|
if (!peek) {
|
|
11872
12232
|
this.queue.shift();
|
|
11873
|
-
this.queued -=
|
|
12233
|
+
this.queued -= next3.bytes.length;
|
|
11874
12234
|
this.changes.wake();
|
|
11875
12235
|
}
|
|
11876
12236
|
const size = Math.max(0, max);
|
|
11877
12237
|
return {
|
|
11878
|
-
bytes:
|
|
11879
|
-
from:
|
|
11880
|
-
truncated:
|
|
12238
|
+
bytes: next3.bytes.slice(0, size),
|
|
12239
|
+
from: next3.from,
|
|
12240
|
+
truncated: next3.bytes.length > size
|
|
11881
12241
|
};
|
|
11882
12242
|
}
|
|
11883
12243
|
await this.changes.wait(signal);
|
|
@@ -12196,14 +12556,6 @@ var PATH_OPS = new Set(SYNC_FS_OPS);
|
|
|
12196
12556
|
// src/realm/live-vfs-fs.ts
|
|
12197
12557
|
var EARLY_WHOLE_FILE = 64 * 1024;
|
|
12198
12558
|
|
|
12199
|
-
// src/version.ts
|
|
12200
|
-
var KERNEL_VERSION = true ? "1.103.4" : "0.0.0-dev";
|
|
12201
|
-
var OS_RELEASE = "6.0.0-slicc";
|
|
12202
|
-
function procVersion() {
|
|
12203
|
-
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
12204
|
-
`;
|
|
12205
|
-
}
|
|
12206
|
-
|
|
12207
12559
|
// src/process/process-fds.ts
|
|
12208
12560
|
var field2 = (text) => (text || "none").replace(/[\s\\]/g, (c) => `\\${c.charCodeAt(0).toString(8).padStart(3, "0")}`);
|
|
12209
12561
|
var pinnedRoot;
|
|
@@ -12595,7 +12947,7 @@ function* procWalk(path, follow2) {
|
|
|
12595
12947
|
const whole = normalize(`/${[...done4, part, ...todo].join("/")}`);
|
|
12596
12948
|
if (inProc(at) && inProc(whole)) return broken ?? whole;
|
|
12597
12949
|
if (!follow2 && todo.length === 0) return void 0;
|
|
12598
|
-
const target = yield { at, check: todo.find((
|
|
12950
|
+
const target = yield { at, check: todo.find((next3) => next3 !== ".") === ".." };
|
|
12599
12951
|
if (typeof target === "string") {
|
|
12600
12952
|
if (++hops > MAX_HOPS3) return void 0;
|
|
12601
12953
|
[done4, todo] = throughLink(target, done4, todo);
|
|
@@ -12731,18 +13083,18 @@ function timerAfter(ms, fire) {
|
|
|
12731
13083
|
return timerAt(performance.now() + ms, fire);
|
|
12732
13084
|
}
|
|
12733
13085
|
function repeating(first, every, fire) {
|
|
12734
|
-
let
|
|
13086
|
+
let next3 = performance.now() + first;
|
|
12735
13087
|
let cancel = () => {
|
|
12736
13088
|
};
|
|
12737
13089
|
const tick = () => {
|
|
12738
13090
|
fire();
|
|
12739
13091
|
if (every <= 0) return;
|
|
12740
|
-
|
|
13092
|
+
next3 += every;
|
|
12741
13093
|
const now = performance.now();
|
|
12742
|
-
if (
|
|
12743
|
-
cancel = timerAt(
|
|
13094
|
+
if (next3 <= now) next3 += (Math.floor((now - next3) / every) + 1) * every;
|
|
13095
|
+
cancel = timerAt(next3, tick);
|
|
12744
13096
|
};
|
|
12745
|
-
cancel = timerAt(
|
|
13097
|
+
cancel = timerAt(next3, tick);
|
|
12746
13098
|
return () => cancel();
|
|
12747
13099
|
}
|
|
12748
13100
|
|
|
@@ -13033,11 +13385,11 @@ var LockTable = class {
|
|
|
13033
13385
|
}
|
|
13034
13386
|
changed(key, signal) {
|
|
13035
13387
|
return new Promise((resolve2, reject) => {
|
|
13036
|
-
const
|
|
13037
|
-
this.wakers.set(key,
|
|
13388
|
+
const set3 = this.wakers.get(key) ?? /* @__PURE__ */ new Set();
|
|
13389
|
+
this.wakers.set(key, set3);
|
|
13038
13390
|
const done4 = () => {
|
|
13039
|
-
|
|
13040
|
-
if (
|
|
13391
|
+
set3.delete(wake);
|
|
13392
|
+
if (set3.size === 0 && this.wakers.get(key) === set3) this.wakers.delete(key);
|
|
13041
13393
|
signal.removeEventListener("abort", abort);
|
|
13042
13394
|
};
|
|
13043
13395
|
const wake = () => {
|
|
@@ -13048,7 +13400,7 @@ var LockTable = class {
|
|
|
13048
13400
|
done4();
|
|
13049
13401
|
reject(new KernelError("EINTR"));
|
|
13050
13402
|
};
|
|
13051
|
-
|
|
13403
|
+
set3.add(wake);
|
|
13052
13404
|
signal.addEventListener("abort", abort, { once: true });
|
|
13053
13405
|
});
|
|
13054
13406
|
}
|
|
@@ -13577,10 +13929,10 @@ var LoopbackWebSocket = class {
|
|
|
13577
13929
|
this.messages = {
|
|
13578
13930
|
[Symbol.asyncIterator]: async function* () {
|
|
13579
13931
|
for (; ; ) {
|
|
13580
|
-
const
|
|
13581
|
-
if (
|
|
13582
|
-
taken(
|
|
13583
|
-
yield
|
|
13932
|
+
const next3 = queue.shift();
|
|
13933
|
+
if (next3 !== void 0) {
|
|
13934
|
+
taken(next3);
|
|
13935
|
+
yield next3;
|
|
13584
13936
|
continue;
|
|
13585
13937
|
}
|
|
13586
13938
|
if (ended) return;
|
|
@@ -13690,9 +14042,9 @@ var WsHandles = class {
|
|
|
13690
14042
|
open = /* @__PURE__ */ new Map();
|
|
13691
14043
|
next;
|
|
13692
14044
|
local;
|
|
13693
|
-
constructor(transport,
|
|
14045
|
+
constructor(transport, next3, local) {
|
|
13694
14046
|
this.transport = transport;
|
|
13695
|
-
this.next =
|
|
14047
|
+
this.next = next3;
|
|
13696
14048
|
this.local = local;
|
|
13697
14049
|
}
|
|
13698
14050
|
owns(handle) {
|
|
@@ -13754,9 +14106,9 @@ var WsHandles = class {
|
|
|
13754
14106
|
}
|
|
13755
14107
|
async recv(socket, entry) {
|
|
13756
14108
|
try {
|
|
13757
|
-
const
|
|
13758
|
-
if (!
|
|
13759
|
-
return typeof
|
|
14109
|
+
const next3 = await entry.messages.next();
|
|
14110
|
+
if (!next3.done) {
|
|
14111
|
+
return typeof next3.value === "string" ? { ok: true, kind: "json", json: { text: next3.value } } : { ok: true, kind: "bytes", bytes: next3.value };
|
|
13760
14112
|
}
|
|
13761
14113
|
const closed = await socket.closed;
|
|
13762
14114
|
return {
|
|
@@ -13804,11 +14156,49 @@ var HTTP_OPS = [
|
|
|
13804
14156
|
"net-open",
|
|
13805
14157
|
"net-head",
|
|
13806
14158
|
"net-read",
|
|
14159
|
+
"net-write",
|
|
14160
|
+
"net-end",
|
|
13807
14161
|
"net-close",
|
|
13808
14162
|
"net-traits",
|
|
13809
14163
|
...WS_OPS
|
|
13810
14164
|
];
|
|
13811
|
-
var
|
|
14165
|
+
var Upload = class {
|
|
14166
|
+
queue = [];
|
|
14167
|
+
ended = false;
|
|
14168
|
+
wake;
|
|
14169
|
+
write(bytes) {
|
|
14170
|
+
if (this.ended) return Promise.resolve(false);
|
|
14171
|
+
return new Promise((taken) => {
|
|
14172
|
+
this.queue.push({ bytes, taken });
|
|
14173
|
+
this.wake?.();
|
|
14174
|
+
});
|
|
14175
|
+
}
|
|
14176
|
+
end() {
|
|
14177
|
+
this.ended = true;
|
|
14178
|
+
this.wake?.();
|
|
14179
|
+
}
|
|
14180
|
+
cancel() {
|
|
14181
|
+
this.ended = true;
|
|
14182
|
+
for (const { taken } of this.queue.splice(0)) taken(false);
|
|
14183
|
+
this.wake?.();
|
|
14184
|
+
}
|
|
14185
|
+
async *[Symbol.asyncIterator]() {
|
|
14186
|
+
for (; ; ) {
|
|
14187
|
+
const next3 = this.queue.shift();
|
|
14188
|
+
if (next3) {
|
|
14189
|
+
next3.taken(true);
|
|
14190
|
+
yield next3.bytes;
|
|
14191
|
+
continue;
|
|
14192
|
+
}
|
|
14193
|
+
if (this.ended) return;
|
|
14194
|
+
await new Promise((resolve2) => {
|
|
14195
|
+
this.wake = resolve2;
|
|
14196
|
+
});
|
|
14197
|
+
this.wake = void 0;
|
|
14198
|
+
}
|
|
14199
|
+
}
|
|
14200
|
+
};
|
|
14201
|
+
var EMPTY2 = new Uint8Array(0);
|
|
13812
14202
|
function message2(e) {
|
|
13813
14203
|
return e instanceof Error ? e.message : String(e);
|
|
13814
14204
|
}
|
|
@@ -13838,6 +14228,8 @@ var HttpHandles = class {
|
|
|
13838
14228
|
if (req.op === "net-open") return Promise.resolve(this.opened(req));
|
|
13839
14229
|
if (req.op === "net-head") return this.head(req.handle);
|
|
13840
14230
|
if (req.op === "net-read") return this.read(req.handle, req.max);
|
|
14231
|
+
if (req.op === "net-write") return this.write(req.handle, req.bytes);
|
|
14232
|
+
if (req.op === "net-end") return Promise.resolve(this.end(req.handle));
|
|
13841
14233
|
if (req.op === "net-traits") return Promise.resolve(this.traits(req.url));
|
|
13842
14234
|
return this.close(req.handle);
|
|
13843
14235
|
}
|
|
@@ -13856,19 +14248,37 @@ var HttpHandles = class {
|
|
|
13856
14248
|
return result;
|
|
13857
14249
|
}
|
|
13858
14250
|
opened(req) {
|
|
14251
|
+
if (req.stream && (this.local?.port(req.url) !== void 0 || !this.transport.traits.streamingBodies)) {
|
|
14252
|
+
return { ok: false, errno: "ENOTSUP", message: "this transport takes whole request bodies" };
|
|
14253
|
+
}
|
|
13859
14254
|
return { ok: true, kind: "json", json: this.start(req).handle };
|
|
13860
14255
|
}
|
|
14256
|
+
async write(handle, bytes) {
|
|
14257
|
+
const upload = this.open.get(handle)?.upload;
|
|
14258
|
+
if (!upload) return { ok: false, errno: "EBADF", message: `no upload ${handle}` };
|
|
14259
|
+
if (!await upload.write(bytes)) {
|
|
14260
|
+
return { ok: false, errno: "EPIPE", message: "the request no longer takes a body" };
|
|
14261
|
+
}
|
|
14262
|
+
return { ok: true, kind: "void" };
|
|
14263
|
+
}
|
|
14264
|
+
end(handle) {
|
|
14265
|
+
const upload = this.open.get(handle)?.upload;
|
|
14266
|
+
if (!upload) return { ok: false, errno: "EBADF", message: `no upload ${handle}` };
|
|
14267
|
+
upload.end();
|
|
14268
|
+
return { ok: true, kind: "void" };
|
|
14269
|
+
}
|
|
13861
14270
|
start(req) {
|
|
13862
14271
|
const handle = ++this.nextHandle;
|
|
13863
14272
|
const abort = new AbortController();
|
|
13864
14273
|
const entry = {
|
|
13865
14274
|
abort,
|
|
13866
14275
|
head: Promise.resolve({ ok: true, kind: "void" }),
|
|
13867
|
-
body: once(
|
|
13868
|
-
left:
|
|
14276
|
+
body: once(EMPTY2),
|
|
14277
|
+
left: EMPTY2,
|
|
13869
14278
|
done: false,
|
|
13870
14279
|
reading: Promise.resolve(),
|
|
13871
|
-
cancel: async () => void 0
|
|
14280
|
+
cancel: async () => void 0,
|
|
14281
|
+
...req.stream ? { upload: new Upload() } : {}
|
|
13872
14282
|
};
|
|
13873
14283
|
this.open.set(handle, entry);
|
|
13874
14284
|
entry.head = this.respond(handle, req, entry);
|
|
@@ -13882,7 +14292,7 @@ var HttpHandles = class {
|
|
|
13882
14292
|
url: target,
|
|
13883
14293
|
method: req.method,
|
|
13884
14294
|
headers: req.headers,
|
|
13885
|
-
...req.body ? { body: req.body } : {},
|
|
14295
|
+
...entry.upload ? { bodyStream: entry.upload } : req.body ? { body: req.body } : {},
|
|
13886
14296
|
signal: entry.abort.signal
|
|
13887
14297
|
};
|
|
13888
14298
|
const response = port === void 0 ? await this.transport.fetch(request2, this.owner) : await this.local.fetch(request2, port);
|
|
@@ -13893,6 +14303,7 @@ var HttpHandles = class {
|
|
|
13893
14303
|
const head = this.headOf(handle, shown, response);
|
|
13894
14304
|
return response.redirected ? { ...head, json: { ...head.json, redirected: true } } : head;
|
|
13895
14305
|
} catch (e) {
|
|
14306
|
+
entry.upload?.cancel();
|
|
13896
14307
|
const text = message2(e);
|
|
13897
14308
|
if (port !== void 0) return { ok: false, errno: codeOf2(e), message: text };
|
|
13898
14309
|
const status = e.status;
|
|
@@ -13929,9 +14340,9 @@ var HttpHandles = class {
|
|
|
13929
14340
|
async take(entry, max) {
|
|
13930
14341
|
if (entry.left.length === 0 && !entry.done) {
|
|
13931
14342
|
try {
|
|
13932
|
-
const
|
|
13933
|
-
if (
|
|
13934
|
-
else entry.left =
|
|
14343
|
+
const next3 = await entry.body.next();
|
|
14344
|
+
if (next3.done) entry.done = true;
|
|
14345
|
+
else entry.left = next3.value;
|
|
13935
14346
|
} catch (e) {
|
|
13936
14347
|
entry.done = true;
|
|
13937
14348
|
const timedOut = e?.code === "ETIMEDOUT";
|
|
@@ -13950,6 +14361,7 @@ var HttpHandles = class {
|
|
|
13950
14361
|
const entry = this.open.get(handle);
|
|
13951
14362
|
if (!entry) return { ok: false, errno: "EBADF", message: `no request ${handle}` };
|
|
13952
14363
|
this.open.delete(handle);
|
|
14364
|
+
entry.upload?.cancel();
|
|
13953
14365
|
entry.abort.abort();
|
|
13954
14366
|
await entry.cancel().catch(() => void 0);
|
|
13955
14367
|
return { ok: true, kind: "void" };
|
|
@@ -14304,12 +14716,12 @@ var KernelTty = class {
|
|
|
14304
14716
|
const chunks = [];
|
|
14305
14717
|
let n = 0;
|
|
14306
14718
|
while (this.readable.length > 0 && n < max) {
|
|
14307
|
-
const
|
|
14308
|
-
if (
|
|
14309
|
-
const take =
|
|
14719
|
+
const next3 = this.readable[0];
|
|
14720
|
+
if (next3 === null || next3 === void 0) break;
|
|
14721
|
+
const take = next3.subarray(0, max - n);
|
|
14310
14722
|
chunks.push(take);
|
|
14311
14723
|
n += take.length;
|
|
14312
|
-
if (take.length <
|
|
14724
|
+
if (take.length < next3.length) this.readable[0] = next3.subarray(take.length);
|
|
14313
14725
|
else this.readable.shift();
|
|
14314
14726
|
if (this.canonical) break;
|
|
14315
14727
|
}
|
|
@@ -14406,11 +14818,11 @@ var PtyPair = class {
|
|
|
14406
14818
|
const chunks = [];
|
|
14407
14819
|
let n = 0;
|
|
14408
14820
|
while (this.queue.length > 0 && n < max - status) {
|
|
14409
|
-
const
|
|
14410
|
-
const take =
|
|
14821
|
+
const next3 = this.queue[0];
|
|
14822
|
+
const take = next3.subarray(0, max - status - n);
|
|
14411
14823
|
chunks.push(take);
|
|
14412
14824
|
n += take.length;
|
|
14413
|
-
if (take.length <
|
|
14825
|
+
if (take.length < next3.length) this.queue[0] = next3.subarray(take.length);
|
|
14414
14826
|
else this.queue.shift();
|
|
14415
14827
|
}
|
|
14416
14828
|
const out = new Uint8Array(status + n);
|
|
@@ -14730,8 +15142,8 @@ var Semaphore = class {
|
|
|
14730
15142
|
this.mode = mode;
|
|
14731
15143
|
}
|
|
14732
15144
|
post() {
|
|
14733
|
-
const
|
|
14734
|
-
if (
|
|
15145
|
+
const next3 = this.waiters.shift();
|
|
15146
|
+
if (next3) next3.grant();
|
|
14735
15147
|
else if (this.value >= SEM_VALUE_MAX) throw new KernelError("EOVERFLOW");
|
|
14736
15148
|
else this.value++;
|
|
14737
15149
|
}
|
|
@@ -15159,9 +15571,9 @@ var VfsNode = class {
|
|
|
15159
15571
|
if (dirty && contents2 !== void 0) this.markDirty();
|
|
15160
15572
|
}
|
|
15161
15573
|
serial(op) {
|
|
15162
|
-
const
|
|
15163
|
-
this.queue =
|
|
15164
|
-
return
|
|
15574
|
+
const next3 = this.queue.then(op);
|
|
15575
|
+
this.queue = next3.catch(() => void 0);
|
|
15576
|
+
return next3;
|
|
15165
15577
|
}
|
|
15166
15578
|
revoke() {
|
|
15167
15579
|
this.revoked = true;
|
|
@@ -15583,9 +15995,9 @@ var VfsNodes = class {
|
|
|
15583
15995
|
}
|
|
15584
15996
|
for (const [p] of moved2) this.byPath.delete(p);
|
|
15585
15997
|
for (const [p, node] of moved2) {
|
|
15586
|
-
const
|
|
15587
|
-
if (node.path === p) node.renamedTo(
|
|
15588
|
-
this.byPath.set(
|
|
15998
|
+
const next3 = to + p.slice(from.length);
|
|
15999
|
+
if (node.path === p) node.renamedTo(next3);
|
|
16000
|
+
this.byPath.set(next3, node);
|
|
15589
16001
|
}
|
|
15590
16002
|
}
|
|
15591
16003
|
};
|
|
@@ -15960,6 +16372,7 @@ var SYSCALL_OPS = /* @__PURE__ */ new Set([
|
|
|
15960
16372
|
"tty-pgrp-get",
|
|
15961
16373
|
"tty-pgrp-set",
|
|
15962
16374
|
"sig-mask",
|
|
16375
|
+
"sig-waiting",
|
|
15963
16376
|
"sig-pause",
|
|
15964
16377
|
...SOCKET_OPS,
|
|
15965
16378
|
...EPOLL_OPS,
|
|
@@ -16073,16 +16486,8 @@ var WasmProcess = class {
|
|
|
16073
16486
|
if (sig === SIG.STOP) return this.stop(sig);
|
|
16074
16487
|
const bit = sigbit(sig);
|
|
16075
16488
|
if (this.ignores(bit)) return "ignore";
|
|
16076
|
-
if (((this.options.blockedBits?.() ?? 0) & bit) !== 0) {
|
|
16077
|
-
|
|
16078
|
-
if (tid === void 0) {
|
|
16079
|
-
this.options.onPending?.(sig);
|
|
16080
|
-
return "deliver";
|
|
16081
|
-
}
|
|
16082
|
-
if (this.caught & bit) {
|
|
16083
|
-
this.options.threadKill?.(tid, sig);
|
|
16084
|
-
return "deliver";
|
|
16085
|
-
}
|
|
16489
|
+
if (((this.options.blockedBits?.() ?? 0) & bit) !== 0 && this.routeBlocked(sig, bit)) {
|
|
16490
|
+
return "deliver";
|
|
16086
16491
|
}
|
|
16087
16492
|
if (!(this.caught & bit)) {
|
|
16088
16493
|
const action = defaultAction(sig);
|
|
@@ -16099,6 +16504,17 @@ var WasmProcess = class {
|
|
|
16099
16504
|
blocked2.abort();
|
|
16100
16505
|
return "deliver";
|
|
16101
16506
|
}
|
|
16507
|
+
routeBlocked(sig, bit) {
|
|
16508
|
+
const waiter = this.waiterFor(bit);
|
|
16509
|
+
const tid = waiter ?? this.options.unblockedThread?.(sig);
|
|
16510
|
+
if (tid === void 0 || tid === 1) {
|
|
16511
|
+
this.options.onPending?.(sig);
|
|
16512
|
+
return true;
|
|
16513
|
+
}
|
|
16514
|
+
if (waiter === void 0 && !(this.caught & bit)) return false;
|
|
16515
|
+
this.options.threadKill?.(tid, sig);
|
|
16516
|
+
return true;
|
|
16517
|
+
}
|
|
16102
16518
|
async spawn(req) {
|
|
16103
16519
|
const { file, argv, argv0, env, cwd, chdir, stdio, inherit: inherit2, exec, pgid, session, deathSignal } = req;
|
|
16104
16520
|
if (deathSignal !== void 0 && (exec || !isSignal(deathSignal))) {
|
|
@@ -16179,6 +16595,16 @@ var WasmProcess = class {
|
|
|
16179
16595
|
}
|
|
16180
16596
|
blocks = /* @__PURE__ */ new WeakMap();
|
|
16181
16597
|
sizesRead = /* @__PURE__ */ new WeakMap();
|
|
16598
|
+
sigwaiters = /* @__PURE__ */ new Map();
|
|
16599
|
+
setSigwaiter(tid, set3) {
|
|
16600
|
+
if (set3 === 0) this.sigwaiters.delete(tid);
|
|
16601
|
+
else this.sigwaiters.set(tid, set3);
|
|
16602
|
+
}
|
|
16603
|
+
waiterFor(bit) {
|
|
16604
|
+
if (((this.sigwaiters.get(1) ?? 0) & bit) !== 0) return 1;
|
|
16605
|
+
for (const [tid, set3] of this.sigwaiters) if (set3 & bit) return tid;
|
|
16606
|
+
return void 0;
|
|
16607
|
+
}
|
|
16182
16608
|
async syscall(req, cancelled, block) {
|
|
16183
16609
|
this.options.onSyscall?.(req);
|
|
16184
16610
|
const started = performance.now();
|
|
@@ -16435,18 +16861,18 @@ var WasmProcess = class {
|
|
|
16435
16861
|
}
|
|
16436
16862
|
if (this.writesAt(req) && this.options.readonlyAt?.(path)) throw new KernelError("EROFS");
|
|
16437
16863
|
const open = { ...req, path };
|
|
16438
|
-
const
|
|
16864
|
+
const plain2 = this.plainMode(req.mode);
|
|
16439
16865
|
if (req.exclusive) {
|
|
16440
16866
|
await nodes.createExclusive(path, this.newOwner(req.mode));
|
|
16441
|
-
if (
|
|
16867
|
+
if (plain2 !== void 0) await fs.chmod?.(path, plain2);
|
|
16442
16868
|
this.fds.installAt(fd, this.openVfsFile(open, void 0, fs));
|
|
16443
16869
|
} else if (req.create) {
|
|
16444
16870
|
await nodes.onEntry(path, async () => {
|
|
16445
|
-
const marks = this.options.owners ||
|
|
16871
|
+
const marks = this.options.owners || plain2 !== void 0;
|
|
16446
16872
|
const fresh2 = marks && !await present2(fs, path, true);
|
|
16447
16873
|
this.fds.installAt(fd, this.openVfsFile(open, await nodes.identify(path), fs));
|
|
16448
16874
|
await this.fds.get(fd).file.stat?.();
|
|
16449
|
-
if (fresh2 &&
|
|
16875
|
+
if (fresh2 && plain2 !== void 0) await fs.chmod?.(path, plain2);
|
|
16450
16876
|
else if (fresh2) {
|
|
16451
16877
|
await fs.chown?.(path, { ...this.newOwner(req.mode), kind: "new" });
|
|
16452
16878
|
}
|
|
@@ -17087,6 +17513,9 @@ var WasmProcess = class {
|
|
|
17087
17513
|
case "dl-unlock":
|
|
17088
17514
|
this.unlockDl(req.owner);
|
|
17089
17515
|
return { ok: true, kind: "void" };
|
|
17516
|
+
case "sig-waiting":
|
|
17517
|
+
this.setSigwaiter(req.tid, req.set);
|
|
17518
|
+
return { ok: true, kind: "void" };
|
|
17090
17519
|
case "sig-mask":
|
|
17091
17520
|
this.caught = req.caught;
|
|
17092
17521
|
this.ignored = req.ignored;
|
|
@@ -17154,8 +17583,8 @@ var WasmProcess = class {
|
|
|
17154
17583
|
};
|
|
17155
17584
|
withDl(state) {
|
|
17156
17585
|
if (this.dlLog.length === 0) return state;
|
|
17157
|
-
const { next:
|
|
17158
|
-
const dl = { log: [...this.dlLog], next:
|
|
17586
|
+
const { next: next3, handle, free, live } = this.closures;
|
|
17587
|
+
const dl = { log: [...this.dlLog], next: next3, handle, free: [...free], live: [...live] };
|
|
17159
17588
|
return { ...state, dl };
|
|
17160
17589
|
}
|
|
17161
17590
|
seedDl(dl) {
|
|
@@ -17166,8 +17595,8 @@ var WasmProcess = class {
|
|
|
17166
17595
|
this.closures.free.push(...dl.free);
|
|
17167
17596
|
for (const index of dl.live) this.closures.live.add(index);
|
|
17168
17597
|
}
|
|
17169
|
-
allocateClosure(
|
|
17170
|
-
const index = this.closures.free.pop() ?? Math.max(
|
|
17598
|
+
allocateClosure(floor2) {
|
|
17599
|
+
const index = this.closures.free.pop() ?? Math.max(floor2, this.closures.next);
|
|
17171
17600
|
this.closures.next = Math.max(this.closures.next, index + 1);
|
|
17172
17601
|
this.closures.live.add(index);
|
|
17173
17602
|
this.dlLog.push({ kind: "closure", index });
|
|
@@ -17219,8 +17648,8 @@ var WasmProcess = class {
|
|
|
17219
17648
|
wakeDl() {
|
|
17220
17649
|
for (const waiter of [...this.dlLock.waiters]) waiter.wake(false);
|
|
17221
17650
|
}
|
|
17222
|
-
reserveSlots(
|
|
17223
|
-
const base = Math.max(
|
|
17651
|
+
reserveSlots(floor2, size) {
|
|
17652
|
+
const base = Math.max(floor2, this.closures.next);
|
|
17224
17653
|
this.closures.next = base + size;
|
|
17225
17654
|
return base;
|
|
17226
17655
|
}
|
|
@@ -17277,6 +17706,7 @@ var WASM_MAX_THREADS = 256;
|
|
|
17277
17706
|
// src/kernel/host.ts
|
|
17278
17707
|
var CRASHED = 70;
|
|
17279
17708
|
var KILL_GRACE_MS = 2e3;
|
|
17709
|
+
var KILL_HARD_MS = 5e3;
|
|
17280
17710
|
var descIds = /* @__PURE__ */ new WeakMap();
|
|
17281
17711
|
var nextDescId = 1;
|
|
17282
17712
|
function descId(file) {
|
|
@@ -17303,16 +17733,21 @@ function inheritedFds(fds) {
|
|
|
17303
17733
|
var Dying = class {
|
|
17304
17734
|
ending;
|
|
17305
17735
|
timer;
|
|
17736
|
+
hard;
|
|
17306
17737
|
busy = 0;
|
|
17307
17738
|
finish;
|
|
17308
17739
|
start(code, sig, header3, process, finish) {
|
|
17309
17740
|
if (this.ending) return;
|
|
17310
17741
|
this.ending = { code, sig };
|
|
17311
17742
|
this.finish = finish;
|
|
17743
|
+
this.hard = setTimeout(finish, KILL_HARD_MS);
|
|
17312
17744
|
this.arm();
|
|
17313
17745
|
Atomics.store(header3, SAB_I_KILLED, code);
|
|
17314
17746
|
process.die();
|
|
17315
17747
|
}
|
|
17748
|
+
serve(req, work) {
|
|
17749
|
+
return this.ending && isWasmSyscall(req) ? work() : this.serving(work);
|
|
17750
|
+
}
|
|
17316
17751
|
async serving(work) {
|
|
17317
17752
|
this.busy++;
|
|
17318
17753
|
clearTimeout(this.timer);
|
|
@@ -17329,6 +17764,7 @@ var Dying = class {
|
|
|
17329
17764
|
}
|
|
17330
17765
|
clear() {
|
|
17331
17766
|
clearTimeout(this.timer);
|
|
17767
|
+
clearTimeout(this.hard);
|
|
17332
17768
|
}
|
|
17333
17769
|
status(reported2) {
|
|
17334
17770
|
if (this.ending) return [this.ending.code, this.ending.sig];
|
|
@@ -17340,8 +17776,8 @@ function killThread(thread, caught, sig) {
|
|
|
17340
17776
|
const held = (Atomics.load(thread.header, SAB_I_BLOCKED) & sigbit(sig)) !== 0;
|
|
17341
17777
|
if (!held && (caught & sigbit(sig)) === 0) return false;
|
|
17342
17778
|
Atomics.or(thread.header, SAB_I_SIGNALS, sigbit(sig));
|
|
17343
|
-
if (held) return true;
|
|
17344
17779
|
Atomics.notify(thread.header, SAB_I_SIGNALS);
|
|
17780
|
+
if (held) return true;
|
|
17345
17781
|
const blocked2 = thread.interrupt;
|
|
17346
17782
|
thread.interrupt = new AbortController();
|
|
17347
17783
|
blocked2.abort();
|
|
@@ -17437,7 +17873,7 @@ function inherited(opts) {
|
|
|
17437
17873
|
...opts.cred ? { cred: opts.cred } : {}
|
|
17438
17874
|
};
|
|
17439
17875
|
}
|
|
17440
|
-
function holdingToken(opts,
|
|
17876
|
+
function holdingToken(opts, holds2, caller) {
|
|
17441
17877
|
return mintSyncFsToken({
|
|
17442
17878
|
...opts.owners ? caller : { umask: caller.umask },
|
|
17443
17879
|
...opts.dac ? { dac: opts.dac, pid: opts.pid, created: caller.created } : {},
|
|
@@ -17448,13 +17884,13 @@ function holdingToken(opts, holds, caller) {
|
|
|
17448
17884
|
noLinks: opts.noLinks,
|
|
17449
17885
|
cwd: opts.cwd,
|
|
17450
17886
|
...opts.statfs ? { statfs: opts.statfs } : {},
|
|
17451
|
-
hold: (path, on, open, real, handle) =>
|
|
17452
|
-
keptFor: (handle) =>
|
|
17453
|
-
unlinked: (path) =>
|
|
17454
|
-
gate: (path, op) => opts.unlinkGate &&
|
|
17455
|
-
own: (path, op) =>
|
|
17456
|
-
revoked: (path) =>
|
|
17457
|
-
renamed: (from, to) =>
|
|
17887
|
+
hold: (path, on, open, real, handle) => holds2.hold(path, on, open, real, handle),
|
|
17888
|
+
keptFor: (handle) => holds2.keptFor(handle),
|
|
17889
|
+
unlinked: (path) => holds2.keptAt(path),
|
|
17890
|
+
gate: (path, op) => opts.unlinkGate && holds2.holding(path) ? opts.unlinkGate.run(holds2.keyOf(path), op) : op(),
|
|
17891
|
+
own: (path, op) => holds2.own(path, op),
|
|
17892
|
+
revoked: (path) => holds2.isRevoked(path),
|
|
17893
|
+
renamed: (from, to) => holds2.renamed(from, to)
|
|
17458
17894
|
});
|
|
17459
17895
|
}
|
|
17460
17896
|
function linksOf(opts) {
|
|
@@ -17528,6 +17964,9 @@ function threadInit(opts, program, sab, cred, thread, main) {
|
|
|
17528
17964
|
signals: main
|
|
17529
17965
|
};
|
|
17530
17966
|
}
|
|
17967
|
+
function settleExit(exit, settle3, code) {
|
|
17968
|
+
void exit.catch(() => void 0).then(() => settle3(code & 255));
|
|
17969
|
+
}
|
|
17531
17970
|
function spawnWasmProcess(opts) {
|
|
17532
17971
|
const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
17533
17972
|
const header3 = new Int32Array(sab, 0, SAB_HEADER_I32);
|
|
@@ -17554,19 +17993,20 @@ function spawnWasmProcess(opts) {
|
|
|
17554
17993
|
)
|
|
17555
17994
|
);
|
|
17556
17995
|
publishStops(process, header3);
|
|
17557
|
-
const
|
|
17558
|
-
opts.held?.add(
|
|
17559
|
-
const token = holdingToken(opts,
|
|
17996
|
+
const holds2 = new HeldPaths();
|
|
17997
|
+
opts.held?.add(holds2);
|
|
17998
|
+
const token = holdingToken(opts, holds2, {
|
|
17560
17999
|
cred: () => process.cred,
|
|
17561
18000
|
umask: () => process.umask,
|
|
17562
18001
|
created: created3,
|
|
17563
|
-
holdsKept: async (path) => path.includes(`/${UNLINKED_DIR}/`) && (
|
|
18002
|
+
holdsKept: async (path) => path.includes(`/${UNLINKED_DIR}/`) && (holds2.keeps(path) || await process.holds(path))
|
|
17564
18003
|
});
|
|
17565
|
-
process.keptPath = (path) =>
|
|
17566
|
-
process.keptHandle = (handle2) =>
|
|
18004
|
+
process.keptPath = (path) => holds2.keptAt(path)?.hidden;
|
|
18005
|
+
process.keptHandle = (handle2) => holds2.keptFor(handle2)?.hidden;
|
|
17567
18006
|
const worker = opts.createWorker();
|
|
17568
18007
|
const dying = new Dying();
|
|
17569
|
-
const dispatch2 = (req, block) => dying.
|
|
18008
|
+
const dispatch2 = (req, block) => dying.serve(
|
|
18009
|
+
req,
|
|
17570
18010
|
() => isWasmSyscall(req) ? process.syscall(req, void 0, block) : dispatchSyncFs(req)
|
|
17571
18011
|
);
|
|
17572
18012
|
const clocks = new ProcessClocks(sab, opts.program.abi !== "js", process);
|
|
@@ -17589,12 +18029,9 @@ function spawnWasmProcess(opts) {
|
|
|
17589
18029
|
responder.dispose();
|
|
17590
18030
|
lane?.dispose();
|
|
17591
18031
|
revokeSyncFsToken(token);
|
|
17592
|
-
opts.held?.delete(
|
|
18032
|
+
opts.held?.delete(holds2);
|
|
17593
18033
|
worker.terminate();
|
|
17594
|
-
|
|
17595
|
-
() => settle3(code),
|
|
17596
|
-
() => settle3(code)
|
|
17597
|
-
);
|
|
18034
|
+
settleExit(process.exit(), settle3, code);
|
|
17598
18035
|
};
|
|
17599
18036
|
const exitNow = (code) => {
|
|
17600
18037
|
queueMicrotask(() => finish(...dying.status(code)));
|
|
@@ -17638,7 +18075,7 @@ function spawnWasmProcess(opts) {
|
|
|
17638
18075
|
const tsignals = threadSignalsOf(tsab);
|
|
17639
18076
|
if (thread.blocked) storeBlocked(tsignals.header, thread.blocked);
|
|
17640
18077
|
threadSignals.set(thread.tid, tsignals);
|
|
17641
|
-
const tdispatch = (req, block) => dying.
|
|
18078
|
+
const tdispatch = (req, block) => dying.serve(req, () => threadCall(process, req, threadCancel(tsignals), block));
|
|
17642
18079
|
const tresponder = attachSyncSabResponder(tw, tsab, token, {
|
|
17643
18080
|
dispatch: clocks.timed(clocks.thread(thread.tid, tsab), tdispatch)
|
|
17644
18081
|
});
|
|
@@ -18108,10 +18545,10 @@ var Automaton = class {
|
|
|
18108
18545
|
let node = 0;
|
|
18109
18546
|
for (const byte of bytes) {
|
|
18110
18547
|
const key = node * 256 + byte;
|
|
18111
|
-
let
|
|
18112
|
-
if (
|
|
18113
|
-
|
|
18114
|
-
this.edges.set(key,
|
|
18548
|
+
let next3 = this.edges.get(key);
|
|
18549
|
+
if (next3 === void 0) {
|
|
18550
|
+
next3 = this.depth.length;
|
|
18551
|
+
this.edges.set(key, next3);
|
|
18115
18552
|
this.fail.push(0);
|
|
18116
18553
|
this.depth.push(this.depth[node] + 1);
|
|
18117
18554
|
this.children.push(0);
|
|
@@ -18119,7 +18556,7 @@ var Automaton = class {
|
|
|
18119
18556
|
this.out.push([]);
|
|
18120
18557
|
this.dict.push(-1);
|
|
18121
18558
|
}
|
|
18122
|
-
node =
|
|
18559
|
+
node = next3;
|
|
18123
18560
|
}
|
|
18124
18561
|
const id2 = this.lengths.length;
|
|
18125
18562
|
this.lengths.push(bytes.length);
|
|
@@ -18155,8 +18592,8 @@ var Automaton = class {
|
|
|
18155
18592
|
step(state, byte) {
|
|
18156
18593
|
let current = state;
|
|
18157
18594
|
for (; ; ) {
|
|
18158
|
-
const
|
|
18159
|
-
if (
|
|
18595
|
+
const next3 = this.edges.get(current * 256 + byte);
|
|
18596
|
+
if (next3 !== void 0) return next3;
|
|
18160
18597
|
if (current === 0) return 0;
|
|
18161
18598
|
current = this.fail[current];
|
|
18162
18599
|
}
|
|
@@ -18184,7 +18621,7 @@ var RANK = {
|
|
|
18184
18621
|
};
|
|
18185
18622
|
var CR2 = 13;
|
|
18186
18623
|
var LF2 = 10;
|
|
18187
|
-
var
|
|
18624
|
+
var EMPTY3 = new Uint8Array(0);
|
|
18188
18625
|
function register(automaton, sources, ids, bytes, source) {
|
|
18189
18626
|
const key = Array.from(bytes).join(",");
|
|
18190
18627
|
let id2 = ids.get(key);
|
|
@@ -18310,7 +18747,7 @@ function pass(c, input, final) {
|
|
|
18310
18747
|
const partials = [];
|
|
18311
18748
|
scanMain(c, input, best, partials);
|
|
18312
18749
|
scanWrapped(c, input, best, partials);
|
|
18313
|
-
const
|
|
18750
|
+
const holds2 = final ? [] : [...new Set(partials)].sort((a, b) => a - b);
|
|
18314
18751
|
const starts = [...best.keys()].sort((a, b) => a - b);
|
|
18315
18752
|
const parts2 = [];
|
|
18316
18753
|
const hits = /* @__PURE__ */ new Map();
|
|
@@ -18320,16 +18757,16 @@ function pass(c, input, final) {
|
|
|
18320
18757
|
let h = 0;
|
|
18321
18758
|
for (; ; ) {
|
|
18322
18759
|
while (s < starts.length && starts[s] < pos) s++;
|
|
18323
|
-
while (h <
|
|
18324
|
-
const hold = h <
|
|
18325
|
-
const
|
|
18326
|
-
if (hold <=
|
|
18760
|
+
while (h < holds2.length && holds2[h] < pos) h++;
|
|
18761
|
+
const hold = h < holds2.length ? holds2[h] : Infinity;
|
|
18762
|
+
const next3 = s < starts.length ? starts[s] : Infinity;
|
|
18763
|
+
if (hold <= next3) {
|
|
18327
18764
|
cut = Math.min(hold, input.length);
|
|
18328
18765
|
break;
|
|
18329
18766
|
}
|
|
18330
|
-
const candidate = best.get(
|
|
18767
|
+
const candidate = best.get(next3);
|
|
18331
18768
|
parts2.push(
|
|
18332
|
-
input.subarray(pos,
|
|
18769
|
+
input.subarray(pos, next3),
|
|
18333
18770
|
c.replacements[candidate.secret][candidate.form === "raw" ? 0 : 1]
|
|
18334
18771
|
);
|
|
18335
18772
|
count(c, hits, candidate);
|
|
@@ -18364,12 +18801,12 @@ function compile(secrets, options = {}) {
|
|
|
18364
18801
|
return { text: decoder4.decode(bytes), hits };
|
|
18365
18802
|
},
|
|
18366
18803
|
stream() {
|
|
18367
|
-
let pending =
|
|
18804
|
+
let pending = EMPTY3;
|
|
18368
18805
|
const hits = /* @__PURE__ */ new Map();
|
|
18369
18806
|
const run2 = (final) => {
|
|
18370
18807
|
if (c.secrets.length === 0 || pending.length === 0) {
|
|
18371
18808
|
const out = pending;
|
|
18372
|
-
pending =
|
|
18809
|
+
pending = EMPTY3;
|
|
18373
18810
|
return out;
|
|
18374
18811
|
}
|
|
18375
18812
|
const result = pass(c, pending, final);
|
|
@@ -18383,7 +18820,7 @@ function compile(secrets, options = {}) {
|
|
|
18383
18820
|
return run2(false);
|
|
18384
18821
|
},
|
|
18385
18822
|
idle() {
|
|
18386
|
-
return pending.length < FRAGMENT ? run2(true) :
|
|
18823
|
+
return pending.length < FRAGMENT ? run2(true) : EMPTY3;
|
|
18387
18824
|
},
|
|
18388
18825
|
end() {
|
|
18389
18826
|
return run2(true);
|
|
@@ -18425,7 +18862,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
18425
18862
|
let timer;
|
|
18426
18863
|
let failed3;
|
|
18427
18864
|
const waiters = /* @__PURE__ */ new Set();
|
|
18428
|
-
const
|
|
18865
|
+
const quiet2 = () => !busy && pending === 0;
|
|
18429
18866
|
const wake = () => {
|
|
18430
18867
|
for (const waiter of [...waiters]) waiter();
|
|
18431
18868
|
};
|
|
@@ -18442,7 +18879,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
18442
18879
|
if (failed3 === void 0) failed3 = err;
|
|
18443
18880
|
}).finally(() => {
|
|
18444
18881
|
pending -= 1;
|
|
18445
|
-
if (
|
|
18882
|
+
if (quiet2()) wake();
|
|
18446
18883
|
});
|
|
18447
18884
|
};
|
|
18448
18885
|
const settling = (signal) => new Promise((resolve2, reject) => {
|
|
@@ -18460,7 +18897,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
18460
18897
|
signal?.addEventListener("abort", stop, { once: true });
|
|
18461
18898
|
});
|
|
18462
18899
|
const settled = async () => {
|
|
18463
|
-
while (!
|
|
18900
|
+
while (!quiet2()) await settling();
|
|
18464
18901
|
};
|
|
18465
18902
|
const changed = async (signal) => {
|
|
18466
18903
|
const round = new AbortController();
|
|
@@ -18476,7 +18913,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
18476
18913
|
};
|
|
18477
18914
|
const turn = async (signal) => {
|
|
18478
18915
|
for (let waited = false; ; waited = true) {
|
|
18479
|
-
if (
|
|
18916
|
+
if (quiet2() && (pollFile(file).writable || !file.changed)) {
|
|
18480
18917
|
busy = true;
|
|
18481
18918
|
return;
|
|
18482
18919
|
}
|
|
@@ -18505,7 +18942,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
18505
18942
|
...bound(file, "stat"),
|
|
18506
18943
|
poll: () => {
|
|
18507
18944
|
const state = pollFile(file);
|
|
18508
|
-
return
|
|
18945
|
+
return quiet2() ? state : { ...state, writable: false };
|
|
18509
18946
|
},
|
|
18510
18947
|
changed,
|
|
18511
18948
|
...file.tty ? { tty: file.tty } : {},
|
|
@@ -18521,7 +18958,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
18521
18958
|
await send(stream.push(taken), signal);
|
|
18522
18959
|
} finally {
|
|
18523
18960
|
busy = false;
|
|
18524
|
-
if (
|
|
18961
|
+
if (quiet2()) wake();
|
|
18525
18962
|
}
|
|
18526
18963
|
timer = setTimeout(release, idleMs);
|
|
18527
18964
|
return taken.length;
|
|
@@ -18622,15 +19059,15 @@ function isRecord(value) {
|
|
|
18622
19059
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
18623
19060
|
}
|
|
18624
19061
|
function serialized(reply) {
|
|
18625
|
-
let
|
|
19062
|
+
let plain2;
|
|
18626
19063
|
try {
|
|
18627
19064
|
const text = JSON.stringify(reply);
|
|
18628
|
-
|
|
19065
|
+
plain2 = text === void 0 ? void 0 : JSON.parse(text);
|
|
18629
19066
|
} catch (err) {
|
|
18630
19067
|
return JSON.stringify(errorReply("EIO", lineOf2(err)));
|
|
18631
19068
|
}
|
|
18632
|
-
if (!isRecord(
|
|
18633
|
-
const { v: _, ...rest2 } =
|
|
19069
|
+
if (!isRecord(plain2)) return JSON.stringify(errorReply("EIO", "the vault gave no reply"));
|
|
19070
|
+
const { v: _, ...rest2 } = plain2;
|
|
18634
19071
|
return JSON.stringify({ v: 1, ...rest2 });
|
|
18635
19072
|
}
|
|
18636
19073
|
function lineOf2(err) {
|
|
@@ -19649,22 +20086,22 @@ function keepWatching(loop, signal) {
|
|
|
19649
20086
|
const stop = () => session2.abort();
|
|
19650
20087
|
signal.addEventListener("abort", stop);
|
|
19651
20088
|
let timer;
|
|
19652
|
-
const
|
|
20089
|
+
const quiet2 = () => {
|
|
19653
20090
|
clearTimeout(timer);
|
|
19654
20091
|
timer = setTimeout(stop, silenceMs);
|
|
19655
20092
|
};
|
|
19656
20093
|
let opened2 = false;
|
|
19657
20094
|
try {
|
|
19658
20095
|
const client = await loop.connect();
|
|
19659
|
-
|
|
20096
|
+
quiet2();
|
|
19660
20097
|
await client.watch(
|
|
19661
20098
|
session2.signal,
|
|
19662
20099
|
(event) => {
|
|
19663
|
-
|
|
20100
|
+
quiet2();
|
|
19664
20101
|
if (!event.ping) loop.event(event);
|
|
19665
20102
|
},
|
|
19666
20103
|
() => {
|
|
19667
|
-
|
|
20104
|
+
quiet2();
|
|
19668
20105
|
opened2 = true;
|
|
19669
20106
|
up = true;
|
|
19670
20107
|
loop.up(client);
|
|
@@ -20106,9 +20543,9 @@ function tmpfs() {
|
|
|
20106
20543
|
let node = root;
|
|
20107
20544
|
for (const name2 of parts2(path)) {
|
|
20108
20545
|
if (node.kind !== "directory") throw fsError2("ENOTDIR", path);
|
|
20109
|
-
const
|
|
20110
|
-
if (!
|
|
20111
|
-
node =
|
|
20546
|
+
const next3 = node.children.get(name2);
|
|
20547
|
+
if (!next3) throw fsError2("ENOENT", path);
|
|
20548
|
+
node = next3;
|
|
20112
20549
|
}
|
|
20113
20550
|
return node;
|
|
20114
20551
|
}
|
|
@@ -20414,6 +20851,28 @@ function foreignImports(bytes) {
|
|
|
20414
20851
|
return {};
|
|
20415
20852
|
}
|
|
20416
20853
|
|
|
20854
|
+
// src/refused-command.ts
|
|
20855
|
+
var REFUSED_PATH = "/usr/lib/slicc/refused";
|
|
20856
|
+
var REFUSED_SOURCE = [
|
|
20857
|
+
"export default async function refused(ctx) {",
|
|
20858
|
+
" await ctx.write(2, ctx.argv[1] + '\\n').catch(() => undefined);",
|
|
20859
|
+
" return 126;",
|
|
20860
|
+
"}"
|
|
20861
|
+
].join("\n");
|
|
20862
|
+
function refusing(command) {
|
|
20863
|
+
if (!command.refused) return command;
|
|
20864
|
+
return {
|
|
20865
|
+
name: command.name,
|
|
20866
|
+
abi: "js",
|
|
20867
|
+
glue: REFUSED_PATH,
|
|
20868
|
+
wasm: REFUSED_PATH,
|
|
20869
|
+
argv0: command.name,
|
|
20870
|
+
args: [`${command.name}: ${command.refused}`],
|
|
20871
|
+
refused: command.refused,
|
|
20872
|
+
shows: command.script ?? command.wasm
|
|
20873
|
+
};
|
|
20874
|
+
}
|
|
20875
|
+
|
|
20417
20876
|
// src/sudo.ts
|
|
20418
20877
|
var SUDOERS = "/etc/sudoers";
|
|
20419
20878
|
var SUDOERS_D = "/etc/sudoers.d";
|
|
@@ -20441,13 +20900,13 @@ function splitWords(text) {
|
|
|
20441
20900
|
while (piece.lastIndex < text.length) {
|
|
20442
20901
|
const m = piece.exec(text);
|
|
20443
20902
|
if (!m) return void 0;
|
|
20444
|
-
const [, single, double, escaped,
|
|
20903
|
+
const [, single, double, escaped, plain2, space] = m;
|
|
20445
20904
|
if (space !== void 0) {
|
|
20446
20905
|
if (word !== void 0) words2.push(word);
|
|
20447
20906
|
word = void 0;
|
|
20448
20907
|
continue;
|
|
20449
20908
|
}
|
|
20450
|
-
word = (word ?? "") + (single ?? (double !== void 0 ? unescaped(double) : escaped ??
|
|
20909
|
+
word = (word ?? "") + (single ?? (double !== void 0 ? unescaped(double) : escaped ?? plain2));
|
|
20451
20910
|
}
|
|
20452
20911
|
if (word !== void 0) words2.push(word);
|
|
20453
20912
|
return words2;
|
|
@@ -20479,7 +20938,7 @@ function parseRule(line) {
|
|
|
20479
20938
|
if (!cmnd?.[0]?.startsWith("/")) return void 0;
|
|
20480
20939
|
return { ...rule, cmnd };
|
|
20481
20940
|
}
|
|
20482
|
-
function flags(parsed2, arg,
|
|
20941
|
+
function flags(parsed2, arg, next3) {
|
|
20483
20942
|
for (let j = 1; j < arg.length; j++) {
|
|
20484
20943
|
const flag = arg[j];
|
|
20485
20944
|
if (flag === "n") parsed2.nonInteractive = true;
|
|
@@ -20487,7 +20946,7 @@ function flags(parsed2, arg, next2) {
|
|
|
20487
20946
|
else if (flag !== "u") return `sudo: invalid option -- '${flag}'
|
|
20488
20947
|
${USAGE}`;
|
|
20489
20948
|
else {
|
|
20490
|
-
const user = arg.slice(j + 1) ||
|
|
20949
|
+
const user = arg.slice(j + 1) || next3;
|
|
20491
20950
|
if (!user) return `sudo: option requires an argument -- 'u'
|
|
20492
20951
|
${USAGE}`;
|
|
20493
20952
|
parsed2.user = user;
|
|
@@ -20937,9 +21396,9 @@ function appendedRoots(given) {
|
|
|
20937
21396
|
return [...roots];
|
|
20938
21397
|
}
|
|
20939
21398
|
function plainEnv(words2) {
|
|
20940
|
-
const
|
|
20941
|
-
if (baseName2(words2[0] ?? "") !== "env" ||
|
|
20942
|
-
return
|
|
21399
|
+
const next3 = words2[1];
|
|
21400
|
+
if (baseName2(words2[0] ?? "") !== "env" || next3 === void 0) return false;
|
|
21401
|
+
return next3 === "-S" || !next3.startsWith("-") && !next3.includes("=");
|
|
20943
21402
|
}
|
|
20944
21403
|
function shebangCommand(words2) {
|
|
20945
21404
|
if (!plainEnv(words2)) {
|
|
@@ -20963,9 +21422,9 @@ function expandDefaults(defaults, env) {
|
|
|
20963
21422
|
for (const [key, value] of Object.entries(defaults ?? {})) {
|
|
20964
21423
|
let missing4 = false;
|
|
20965
21424
|
const expanded = value.replace(ENV_REFERENCE, (_, name2) => {
|
|
20966
|
-
const
|
|
20967
|
-
if (
|
|
20968
|
-
return
|
|
21425
|
+
const set3 = Object.hasOwn(env, name2) ? env[name2] : void 0;
|
|
21426
|
+
if (set3 === void 0) missing4 = true;
|
|
21427
|
+
return set3 ?? "";
|
|
20969
21428
|
});
|
|
20970
21429
|
if (!missing4) out[key] = expanded;
|
|
20971
21430
|
}
|
|
@@ -21190,7 +21649,7 @@ var Launcher = class {
|
|
|
21190
21649
|
const holders = [this.held, this.openFiles];
|
|
21191
21650
|
this.unlinked = new UnlinkedKeeper(
|
|
21192
21651
|
fs,
|
|
21193
|
-
{ [Symbol.iterator]: () => holders.flatMap((
|
|
21652
|
+
{ [Symbol.iterator]: () => holders.flatMap((set3) => [...set3]).values() },
|
|
21194
21653
|
(path) => this.mountRoot(path),
|
|
21195
21654
|
{
|
|
21196
21655
|
locks: webLocks(),
|
|
@@ -21275,11 +21734,21 @@ var Launcher = class {
|
|
|
21275
21734
|
found = this.trustedAppended().then(async (appended2) => {
|
|
21276
21735
|
const tiers = await this.tiers(scope, appended2);
|
|
21277
21736
|
return scanCommands(this.scanned, tiers, tiers.length - appended2.length);
|
|
21278
|
-
}).then((commands) => commands.set(SUDO_COMMAND.name, SUDO_COMMAND));
|
|
21737
|
+
}).then((commands) => this.refusals(commands).set(SUDO_COMMAND.name, SUDO_COMMAND));
|
|
21279
21738
|
this.catalogs.set(scope, found);
|
|
21280
21739
|
}
|
|
21281
21740
|
return found;
|
|
21282
21741
|
}
|
|
21742
|
+
refusals(commands) {
|
|
21743
|
+
for (const [name2, command] of commands) {
|
|
21744
|
+
if (!command.refused) continue;
|
|
21745
|
+
commands.set(name2, refusing(command));
|
|
21746
|
+
if (this.warned.has(command.refused)) continue;
|
|
21747
|
+
this.warned.add(command.refused);
|
|
21748
|
+
console.warn(`slicc-kernel: refusing the commands of ${command.refused}`);
|
|
21749
|
+
}
|
|
21750
|
+
return commands;
|
|
21751
|
+
}
|
|
21283
21752
|
ownCommands(scope) {
|
|
21284
21753
|
let found = this.ownCatalogs.get(scope);
|
|
21285
21754
|
if (!found) {
|
|
@@ -21354,7 +21823,8 @@ var Launcher = class {
|
|
|
21354
21823
|
);
|
|
21355
21824
|
return {
|
|
21356
21825
|
byUid: new Map(users.map((account, i) => [account.uid, homes[i]])),
|
|
21357
|
-
byBin: new Map(homes.map((home) => [`${home}/bin`, home]))
|
|
21826
|
+
byBin: new Map(homes.map((home) => [`${home}/bin`, home])),
|
|
21827
|
+
owners: new Map(homes.map((home, i) => [home, credOf(users[i])]))
|
|
21358
21828
|
};
|
|
21359
21829
|
},
|
|
21360
21830
|
() => ({ byUid: /* @__PURE__ */ new Map(), byBin: /* @__PURE__ */ new Map() })
|
|
@@ -21696,12 +22166,12 @@ var Launcher = class {
|
|
|
21696
22166
|
return `${path}:${st.size}:${st.mtime.getTime()}`;
|
|
21697
22167
|
}
|
|
21698
22168
|
verified(path, caller, fs = this.base) {
|
|
21699
|
-
const
|
|
21700
|
-
return this.integrity ? this.integrity.read(path, caller,
|
|
22169
|
+
const plain2 = () => fs.readFileBuffer(path);
|
|
22170
|
+
return this.integrity ? this.integrity.read(path, caller, plain2) : plain2();
|
|
21701
22171
|
}
|
|
21702
22172
|
keyed(path, caller, asked) {
|
|
21703
|
-
const
|
|
21704
|
-
return this.integrity ? this.integrity.readKeyed(path, caller,
|
|
22173
|
+
const plain2 = async () => this.base.readFileBuffer(path);
|
|
22174
|
+
return this.integrity ? this.integrity.readKeyed(path, caller, plain2, asked) : plain2().then((bytes) => ({ bytes }));
|
|
21705
22175
|
}
|
|
21706
22176
|
cached(cache, key, load) {
|
|
21707
22177
|
const hit = cache.get(key);
|
|
@@ -21772,6 +22242,9 @@ var Launcher = class {
|
|
|
21772
22242
|
if (target.abi === "js" && target.wasm === SUDO_PATH) {
|
|
21773
22243
|
return { abi: "js", glue: SUDO_SOURCE, path: SUDO_PATH };
|
|
21774
22244
|
}
|
|
22245
|
+
if (target.abi === "js" && target.wasm === REFUSED_PATH) {
|
|
22246
|
+
return { abi: "js", glue: REFUSED_SOURCE, path: REFUSED_PATH };
|
|
22247
|
+
}
|
|
21775
22248
|
const { asked } = target;
|
|
21776
22249
|
if (target.abi === "js") {
|
|
21777
22250
|
return { abi: "js", glue: await this.text(target.wasm, caller, asked), path: target.wasm };
|
|
@@ -21841,7 +22314,7 @@ var Launcher = class {
|
|
|
21841
22314
|
});
|
|
21842
22315
|
return {
|
|
21843
22316
|
source: {
|
|
21844
|
-
read: (path,
|
|
22317
|
+
read: (path, plain2) => integrity.readSource(path, caller(), plain2),
|
|
21845
22318
|
open: (path, real) => integrity.openSource(path, caller(), real)
|
|
21846
22319
|
}
|
|
21847
22320
|
};
|
|
@@ -22280,9 +22753,9 @@ var Launcher = class {
|
|
|
22280
22753
|
const members = this.jobs.list();
|
|
22281
22754
|
let image = pid;
|
|
22282
22755
|
for (; ; ) {
|
|
22283
|
-
const
|
|
22284
|
-
if (!
|
|
22285
|
-
image =
|
|
22756
|
+
const next3 = members.find((m) => m.execParent === image);
|
|
22757
|
+
if (!next3) return image;
|
|
22758
|
+
image = next3.pid;
|
|
22286
22759
|
}
|
|
22287
22760
|
}
|
|
22288
22761
|
credOf(pid) {
|
|
@@ -22569,7 +23042,7 @@ var Launcher = class {
|
|
|
22569
23042
|
this.pnpmStale();
|
|
22570
23043
|
if (!detach) return;
|
|
22571
23044
|
for (const nodes of this.openFiles) nodes.revoke(at);
|
|
22572
|
-
for (const
|
|
23045
|
+
for (const holds2 of this.held) holds2.revoke(at);
|
|
22573
23046
|
}
|
|
22574
23047
|
unmountAll() {
|
|
22575
23048
|
this.booting.abort();
|
|
@@ -22715,7 +23188,7 @@ var Launcher = class {
|
|
|
22715
23188
|
this.openFiles.add(nodes);
|
|
22716
23189
|
const unlinked = new UnlinkedKeeper(
|
|
22717
23190
|
fs,
|
|
22718
|
-
{ [Symbol.iterator]: () => [this.held, this.openFiles].flatMap((
|
|
23191
|
+
{ [Symbol.iterator]: () => [this.held, this.openFiles].flatMap((set3) => [...set3]).values() },
|
|
22719
23192
|
(path) => this.mountRoot(path),
|
|
22720
23193
|
{
|
|
22721
23194
|
locks: webLocks(),
|
|
@@ -22743,11 +23216,32 @@ var Launcher = class {
|
|
|
22743
23216
|
commandFs(root) {
|
|
22744
23217
|
return withCommandDirs(
|
|
22745
23218
|
root,
|
|
22746
|
-
async () =>
|
|
23219
|
+
async () => this.commandNames(await this.commands()),
|
|
22747
23220
|
(dir) => this.userCommandDir(dir),
|
|
22748
|
-
this.owners
|
|
23221
|
+
this.owners,
|
|
23222
|
+
(path) => this.entryTarget(path)
|
|
22749
23223
|
);
|
|
22750
23224
|
}
|
|
23225
|
+
named = /* @__PURE__ */ new WeakMap();
|
|
23226
|
+
commandNames(commands) {
|
|
23227
|
+
let names = this.named.get(commands);
|
|
23228
|
+
if (!names) {
|
|
23229
|
+
names = new Set(commands.keys());
|
|
23230
|
+
this.named.set(commands, names);
|
|
23231
|
+
}
|
|
23232
|
+
return names;
|
|
23233
|
+
}
|
|
23234
|
+
async entryTarget(path) {
|
|
23235
|
+
const system = COMMAND2.exec(path)?.[1];
|
|
23236
|
+
const slash = path.lastIndexOf("/");
|
|
23237
|
+
const scopes = await this.userScopes();
|
|
23238
|
+
const scope = system === void 0 ? scopes.byBin.get(path.slice(0, slash)) : "";
|
|
23239
|
+
const name2 = system ?? path.slice(slash + 1);
|
|
23240
|
+
const command = scope === void 0 ? void 0 : (await this.commands(scope)).get(name2);
|
|
23241
|
+
const owner = scope ? scopes.owners?.get(scope) : void 0;
|
|
23242
|
+
const target = command && (command.shows ?? command.script ?? command.wasm);
|
|
23243
|
+
return target === void 0 ? void 0 : { path: target, ...owner ? { owner } : {} };
|
|
23244
|
+
}
|
|
22751
23245
|
processChain(fs, nodes, unlinked) {
|
|
22752
23246
|
nodes.changed = (path) => this.changes.publish(path);
|
|
22753
23247
|
nodes.dirtied = (delta) => this.changes.dirtied(delta);
|
|
@@ -22862,9 +23356,9 @@ var Launcher = class {
|
|
|
22862
23356
|
// src/sealed-relay.ts
|
|
22863
23357
|
function sealedAsker(port) {
|
|
22864
23358
|
const asks = /* @__PURE__ */ new Map();
|
|
22865
|
-
let
|
|
23359
|
+
let next3 = 0;
|
|
22866
23360
|
const hook = (req, { signal }) => {
|
|
22867
|
-
const id2 = ++
|
|
23361
|
+
const id2 = ++next3;
|
|
22868
23362
|
const waiting = Promise.withResolvers();
|
|
22869
23363
|
asks.set(id2, waiting);
|
|
22870
23364
|
const abort = () => {
|