@ai-ecoverse/slicc-kernel 1.113.0 → 1.115.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -1
- package/dist/driver-worker.js +7 -0
- package/dist/driver-worker.js.map +2 -2
- package/dist/index.js +7 -0
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +299 -62
- package/dist/kernel-worker.js.map +4 -4
- package/dist/meta.js.map +2 -2
- package/dist/node-driver-worker.js +7 -0
- package/dist/node-driver-worker.js.map +2 -2
- package/dist/node-process-worker.js +134 -16
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +299 -62
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +136 -18
- package/dist/process-worker.js.map +3 -3
- package/dist/types/fs/meta.d.ts +1 -0
- package/dist/types/fs/types.d.ts +2 -0
- package/dist/types/kernel/children.d.ts +9 -1
- package/dist/types/kernel/fd-table.d.ts +1 -0
- package/dist/types/kernel/fifo.d.ts +13 -0
- package/dist/types/kernel/host.d.ts +5 -2
- package/dist/types/kernel/jobs.d.ts +4 -3
- package/dist/types/kernel/process.d.ts +18 -4
- package/dist/types/kernel/protocol.d.ts +2 -0
- package/dist/types/kernel/signals.d.ts +21 -0
- package/dist/types/launcher.d.ts +4 -1
- package/dist/types/process/kernel-streams.d.ts +3 -0
- package/dist/types/process/process-fds.d.ts +1 -0
- package/dist/types/process/wasi/wasi-fds.d.ts +3 -0
- package/dist/types/process/wasi/wasi-host.d.ts +1 -0
- package/dist/types/realm/live-vfs-fs.d.ts +1 -0
- package/dist/types/realm/sync-fs-dispatch.d.ts +1 -0
- package/dist/types/realm/sync-fs-wire.d.ts +3 -1
- package/package.json +5 -4
package/dist/node.js
CHANGED
|
@@ -473,8 +473,8 @@ async function access(fs, cred, path, want, options = {}) {
|
|
|
473
473
|
if (await present(fs, walked.path, false)) return { ...walked, denied: walked.path };
|
|
474
474
|
return { ...walked, missing: true };
|
|
475
475
|
}
|
|
476
|
-
function refused(path,
|
|
477
|
-
return fsError(
|
|
476
|
+
function refused(path, errno3 = "EACCES") {
|
|
477
|
+
return fsError(errno3, path);
|
|
478
478
|
}
|
|
479
479
|
|
|
480
480
|
// src/fs/dac.ts
|
|
@@ -534,9 +534,9 @@ var Created = class {
|
|
|
534
534
|
function linked(g, options) {
|
|
535
535
|
return g.links === void 0 ? options : { ...options, links: g.links };
|
|
536
536
|
}
|
|
537
|
-
function deny(g, op, path,
|
|
537
|
+
function deny(g, op, path, errno3 = "EACCES") {
|
|
538
538
|
const tag = g.tag === void 0 ? {} : { tag: g.tag };
|
|
539
|
-
g.dac.denied({ pid: g.pid, uid: g.cred.euid, op, path, errno:
|
|
539
|
+
g.dac.denied({ pid: g.pid, uid: g.cred.euid, op, path, errno: errno3, ...tag });
|
|
540
540
|
}
|
|
541
541
|
var TTY_MODE = 400;
|
|
542
542
|
function ttyOpenable(g, tty) {
|
|
@@ -1249,7 +1249,7 @@ var WASI_SIGNAL_TO_POSIX = Object.fromEntries(
|
|
|
1249
1249
|
|
|
1250
1250
|
// src/process/wasi-errno.ts
|
|
1251
1251
|
var WASI_ERRNO = {
|
|
1252
|
-
...Object.fromEntries(Object.entries(E).map(([name2,
|
|
1252
|
+
...Object.fromEntries(Object.entries(E).map(([name2, errno3]) => [`E${name2}`, errno3])),
|
|
1253
1253
|
EWOULDBLOCK: E.AGAIN,
|
|
1254
1254
|
ENOTSUP: 138,
|
|
1255
1255
|
EOPNOTSUPP: 138,
|
|
@@ -1489,7 +1489,7 @@ function dialError(e, timedOut, closed) {
|
|
|
1489
1489
|
if (timedOut) return new KernelError("ETIMEDOUT");
|
|
1490
1490
|
if (closed) return new KernelError("ECONNABORTED");
|
|
1491
1491
|
const code = e?.code;
|
|
1492
|
-
const known = DIAL_ERRORS.find((
|
|
1492
|
+
const known = DIAL_ERRORS.find((errno3) => errno3 === code);
|
|
1493
1493
|
return new KernelError(known ?? "EHOSTUNREACH");
|
|
1494
1494
|
}
|
|
1495
1495
|
function isLoopback(host) {
|
|
@@ -2129,6 +2129,14 @@ var SIGNAL_BY_NAME = {
|
|
|
2129
2129
|
SIGSTOP: SIG.STOP,
|
|
2130
2130
|
SIGCONT: SIG.CONT
|
|
2131
2131
|
};
|
|
2132
|
+
var SI = { USER: 0, QUEUE: -1, TIMER: -2, TKILL: -6, KERNEL: 128 };
|
|
2133
|
+
var CLD = { EXITED: 1, KILLED: 2, DUMPED: 3, STOPPED: 5, CONTINUED: 6 };
|
|
2134
|
+
var KERNEL_SIGINFO = Object.freeze({
|
|
2135
|
+
code: SI.KERNEL,
|
|
2136
|
+
pid: 0,
|
|
2137
|
+
uid: 0,
|
|
2138
|
+
status: 0
|
|
2139
|
+
});
|
|
2132
2140
|
|
|
2133
2141
|
// src/body-idle.ts
|
|
2134
2142
|
var BODY_IDLE_MS = 5 * 60 * 1e3;
|
|
@@ -4094,6 +4102,7 @@ var S_IFDIR = 16384;
|
|
|
4094
4102
|
var S_IFREG = 32768;
|
|
4095
4103
|
var S_IFLNK = 40960;
|
|
4096
4104
|
var S_IFSOCK = 49152;
|
|
4105
|
+
var S_IFIFO = 4096;
|
|
4097
4106
|
var PERM_MASK = 4095;
|
|
4098
4107
|
var S_ISGID3 = 1024;
|
|
4099
4108
|
var READ_ATTEMPTS = 3;
|
|
@@ -4373,7 +4382,10 @@ var OpfsFs = class {
|
|
|
4373
4382
|
}
|
|
4374
4383
|
async stampNew(path, owner, directory) {
|
|
4375
4384
|
const owned4 = await this.newFields(path, owner, directory);
|
|
4376
|
-
|
|
4385
|
+
if (owner?.socket && owner.fifo) throw new Error("a new node is a socket or a FIFO, not both");
|
|
4386
|
+
const kind = directory ? void 0 : owner?.socket ? "socket" : owner?.fifo ? "fifo" : void 0;
|
|
4387
|
+
const unique = kind === "fifo" ? { ino: inodeOf(`${path}\0${crypto.randomUUID()}`) } : {};
|
|
4388
|
+
const fields = kind ? { ...owned4, ...unique, [kind]: true } : owned4;
|
|
4377
4389
|
if (fields) await this.meta.update(path, (entry) => ({ ...entry, path, ...fields }));
|
|
4378
4390
|
}
|
|
4379
4391
|
guarded = [];
|
|
@@ -4615,7 +4627,7 @@ var OpfsFs = class {
|
|
|
4615
4627
|
}
|
|
4616
4628
|
mode(path, directory, meta) {
|
|
4617
4629
|
const fallback = directory || EXECUTABLE.test(path) ? 493 : 420;
|
|
4618
|
-
const type = directory ? S_IFDIR : meta?.socket ? S_IFSOCK : S_IFREG;
|
|
4630
|
+
const type = directory ? S_IFDIR : meta?.socket ? S_IFSOCK : meta?.fifo ? S_IFIFO : S_IFREG;
|
|
4619
4631
|
return type | (meta?.mode ?? fallback);
|
|
4620
4632
|
}
|
|
4621
4633
|
id = crypto.randomUUID();
|
|
@@ -4716,11 +4728,13 @@ var OpfsFs = class {
|
|
|
4716
4728
|
const kept = meta?.mtimeMs !== void 0 && meta.mtimeFor === modified ? meta.mtimeMs : modified;
|
|
4717
4729
|
const mtime = touched ?? kept;
|
|
4718
4730
|
const socket = !directory && meta?.socket === true;
|
|
4731
|
+
const fifo = !directory && meta?.fifo === true;
|
|
4719
4732
|
return {
|
|
4720
|
-
isFile: !directory && !socket,
|
|
4733
|
+
isFile: !directory && !socket && !fifo,
|
|
4721
4734
|
isDirectory: directory,
|
|
4722
4735
|
isSymbolicLink: false,
|
|
4723
4736
|
...socket ? { isSocket: true } : {},
|
|
4737
|
+
...fifo ? { isFifo: true } : {},
|
|
4724
4738
|
size: file?.size ?? 0,
|
|
4725
4739
|
mode: this.mode(path, directory, meta),
|
|
4726
4740
|
mtime: new Date(mtime),
|
|
@@ -6531,7 +6545,7 @@ function satisfies(version, range2) {
|
|
|
6531
6545
|
}
|
|
6532
6546
|
|
|
6533
6547
|
// src/version.ts
|
|
6534
|
-
var KERNEL_VERSION = true ? "1.
|
|
6548
|
+
var KERNEL_VERSION = true ? "1.115.0" : "0.0.0-dev";
|
|
6535
6549
|
var OS_RELEASE = "6.0.0-slicc";
|
|
6536
6550
|
function procVersion() {
|
|
6537
6551
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -9185,8 +9199,16 @@ var ChildTable = class {
|
|
|
9185
9199
|
void handle.exited.then((code) => {
|
|
9186
9200
|
child.code = code;
|
|
9187
9201
|
this.watchers.delete(handle.pid);
|
|
9202
|
+
const termsig = handle.termsig?.();
|
|
9188
9203
|
if (!this.kept.delete(handle.pid) && this.autoReap?.()) this.reap(handle.pid, code);
|
|
9189
|
-
|
|
9204
|
+
const uid = handle.uid?.();
|
|
9205
|
+
this.onChildState?.({
|
|
9206
|
+
pid: handle.pid,
|
|
9207
|
+
state: "exited",
|
|
9208
|
+
status: termsig ?? code,
|
|
9209
|
+
termsig,
|
|
9210
|
+
uid
|
|
9211
|
+
});
|
|
9190
9212
|
});
|
|
9191
9213
|
handle.onState?.((state, sig) => {
|
|
9192
9214
|
child.stopReport = state === "stopped" ? sig : void 0;
|
|
@@ -9196,7 +9218,7 @@ var ChildTable = class {
|
|
|
9196
9218
|
const waiters = this.stateChanged;
|
|
9197
9219
|
this.stateChanged = [];
|
|
9198
9220
|
for (const wake of waiters) wake();
|
|
9199
|
-
this.onChildState?.();
|
|
9221
|
+
this.onChildState?.({ pid: handle.pid, state, status: sig, uid: handle.uid?.() });
|
|
9200
9222
|
});
|
|
9201
9223
|
this.children.set(handle.pid, child);
|
|
9202
9224
|
return handle.pid;
|
|
@@ -9526,6 +9548,139 @@ var TicketBook = class {
|
|
|
9526
9548
|
}
|
|
9527
9549
|
};
|
|
9528
9550
|
|
|
9551
|
+
// src/kernel/fifo.ts
|
|
9552
|
+
function errno(e) {
|
|
9553
|
+
return e instanceof KernelError ? e : new KernelError(e.code ?? "EIO");
|
|
9554
|
+
}
|
|
9555
|
+
var FifoTable = class {
|
|
9556
|
+
fifos = /* @__PURE__ */ new Map();
|
|
9557
|
+
size() {
|
|
9558
|
+
return this.fifos.size;
|
|
9559
|
+
}
|
|
9560
|
+
async open(key, path, access2, nonblock, signal) {
|
|
9561
|
+
const fifo = this.entry(key);
|
|
9562
|
+
if (access2 === "write" && nonblock && fifo.readers === 0) {
|
|
9563
|
+
this.drop(key, fifo);
|
|
9564
|
+
throw new KernelError("ENXIO");
|
|
9565
|
+
}
|
|
9566
|
+
const reads = access2 !== "write";
|
|
9567
|
+
const writes = access2 !== "read";
|
|
9568
|
+
const seen = { readOpens: fifo.readOpens, writeOpens: fifo.writeOpens };
|
|
9569
|
+
if (reads) this.count(fifo, "readers", 1);
|
|
9570
|
+
if (writes) this.count(fifo, "writers", 1);
|
|
9571
|
+
this.notify(fifo);
|
|
9572
|
+
try {
|
|
9573
|
+
if (!nonblock && access2 === "read") {
|
|
9574
|
+
while (fifo.writers === 0 && fifo.writeOpens === seen.writeOpens) {
|
|
9575
|
+
await this.changed(fifo, signal);
|
|
9576
|
+
}
|
|
9577
|
+
}
|
|
9578
|
+
if (!nonblock && access2 === "write") {
|
|
9579
|
+
while (fifo.readers === 0 && fifo.readOpens === seen.readOpens) {
|
|
9580
|
+
await this.changed(fifo, signal);
|
|
9581
|
+
}
|
|
9582
|
+
}
|
|
9583
|
+
} catch (e) {
|
|
9584
|
+
this.release(key, fifo, reads, writes);
|
|
9585
|
+
throw errno(e);
|
|
9586
|
+
}
|
|
9587
|
+
return this.end(key, path, fifo, reads, writes);
|
|
9588
|
+
}
|
|
9589
|
+
entry(key) {
|
|
9590
|
+
let fifo = this.fifos.get(key);
|
|
9591
|
+
if (!fifo) {
|
|
9592
|
+
fifo = {
|
|
9593
|
+
pipe: new KernelPipe(),
|
|
9594
|
+
readers: 0,
|
|
9595
|
+
writers: 0,
|
|
9596
|
+
readOpens: 0,
|
|
9597
|
+
writeOpens: 0,
|
|
9598
|
+
waiters: []
|
|
9599
|
+
};
|
|
9600
|
+
this.fifos.set(key, fifo);
|
|
9601
|
+
}
|
|
9602
|
+
return fifo;
|
|
9603
|
+
}
|
|
9604
|
+
count(fifo, side, by) {
|
|
9605
|
+
fifo[side] += by;
|
|
9606
|
+
if (side === "readers") {
|
|
9607
|
+
if (by > 0) {
|
|
9608
|
+
fifo.readOpens += 1;
|
|
9609
|
+
fifo.pipe.openRead();
|
|
9610
|
+
} else fifo.pipe.closeRead();
|
|
9611
|
+
} else if (by > 0) {
|
|
9612
|
+
fifo.writeOpens += 1;
|
|
9613
|
+
fifo.pipe.openWrite();
|
|
9614
|
+
} else fifo.pipe.closeWrite();
|
|
9615
|
+
}
|
|
9616
|
+
notify(fifo) {
|
|
9617
|
+
const waiters = fifo.waiters;
|
|
9618
|
+
fifo.waiters = [];
|
|
9619
|
+
for (const wake of waiters) wake();
|
|
9620
|
+
}
|
|
9621
|
+
changed(fifo, signal) {
|
|
9622
|
+
if (signal.aborted) return Promise.reject(new KernelError("EINTR"));
|
|
9623
|
+
return new Promise((resolve2, reject) => {
|
|
9624
|
+
const onAbort = () => {
|
|
9625
|
+
fifo.waiters = fifo.waiters.filter((w) => w !== wake);
|
|
9626
|
+
reject(new KernelError("EINTR"));
|
|
9627
|
+
};
|
|
9628
|
+
const wake = () => {
|
|
9629
|
+
signal.removeEventListener("abort", onAbort);
|
|
9630
|
+
resolve2();
|
|
9631
|
+
};
|
|
9632
|
+
fifo.waiters.push(wake);
|
|
9633
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
9634
|
+
});
|
|
9635
|
+
}
|
|
9636
|
+
release(key, fifo, reads, writes) {
|
|
9637
|
+
if (reads) this.count(fifo, "readers", -1);
|
|
9638
|
+
if (writes) this.count(fifo, "writers", -1);
|
|
9639
|
+
this.notify(fifo);
|
|
9640
|
+
this.drop(key, fifo);
|
|
9641
|
+
}
|
|
9642
|
+
drop(key, fifo) {
|
|
9643
|
+
const idle = fifo.readers === 0 && fifo.writers === 0 && fifo.waiters.length === 0;
|
|
9644
|
+
if (idle && this.fifos.get(key) === fifo) this.fifos.delete(key);
|
|
9645
|
+
}
|
|
9646
|
+
end(key, path, fifo, reads, writes) {
|
|
9647
|
+
const { pipe } = fifo;
|
|
9648
|
+
let open = true;
|
|
9649
|
+
return new OpenFile({
|
|
9650
|
+
fifo: path,
|
|
9651
|
+
...reads ? {
|
|
9652
|
+
read: async (max, signal) => {
|
|
9653
|
+
try {
|
|
9654
|
+
return await pipe.read(max, signal);
|
|
9655
|
+
} catch (e) {
|
|
9656
|
+
throw errno(e);
|
|
9657
|
+
}
|
|
9658
|
+
}
|
|
9659
|
+
} : {},
|
|
9660
|
+
...writes ? {
|
|
9661
|
+
write: async (bytes, signal) => {
|
|
9662
|
+
try {
|
|
9663
|
+
return await pipe.write(bytes, signal);
|
|
9664
|
+
} catch (e) {
|
|
9665
|
+
throw errno(e);
|
|
9666
|
+
}
|
|
9667
|
+
}
|
|
9668
|
+
} : {},
|
|
9669
|
+
close: () => {
|
|
9670
|
+
if (!open) return;
|
|
9671
|
+
open = false;
|
|
9672
|
+
this.release(key, fifo, reads, writes);
|
|
9673
|
+
},
|
|
9674
|
+
poll: () => ({
|
|
9675
|
+
readable: reads && pipe.readReady,
|
|
9676
|
+
writable: writes && pipe.writeReady,
|
|
9677
|
+
hangup: reads ? pipe.writersGone : pipe.readersGone
|
|
9678
|
+
}),
|
|
9679
|
+
changed: (signal) => pipe.changed(signal)
|
|
9680
|
+
});
|
|
9681
|
+
}
|
|
9682
|
+
};
|
|
9683
|
+
|
|
9529
9684
|
// src/mount/protocol.ts
|
|
9530
9685
|
var DRIVER_PROTOCOL = [1, 2];
|
|
9531
9686
|
function driverVersionError(theirs) {
|
|
@@ -10386,6 +10541,7 @@ var MountFs = class _MountFs {
|
|
|
10386
10541
|
}
|
|
10387
10542
|
const { mount, rel: rel2 } = found;
|
|
10388
10543
|
this.writable(mount, real);
|
|
10544
|
+
if (owner?.fifo) throw errnoError("EPERM", `${real}: this mount has no FIFOs`);
|
|
10389
10545
|
const bytes = typeof content === "string" ? new TextEncoder().encode(content) : content;
|
|
10390
10546
|
if (mount.maxFile > 0 && bytes.length > mount.maxFile) {
|
|
10391
10547
|
throw errnoError(
|
|
@@ -10991,6 +11147,7 @@ var SYNC_FS_OPS = [
|
|
|
10991
11147
|
"statfs",
|
|
10992
11148
|
"hold",
|
|
10993
11149
|
"create",
|
|
11150
|
+
"mkfifo",
|
|
10994
11151
|
"kept",
|
|
10995
11152
|
"pread",
|
|
10996
11153
|
"pwrite",
|
|
@@ -11023,6 +11180,7 @@ function statJson(s) {
|
|
|
11023
11180
|
isFile: s.isFile,
|
|
11024
11181
|
isSymbolicLink: s.isSymbolicLink,
|
|
11025
11182
|
...s.isSocket ? { isSocket: true } : {},
|
|
11183
|
+
...s.isFifo ? { isFifo: true } : {},
|
|
11026
11184
|
size: s.size,
|
|
11027
11185
|
mode: s.mode,
|
|
11028
11186
|
mtimeMs: s.mtime.getTime(),
|
|
@@ -11172,6 +11330,12 @@ async function run(entry, path, req) {
|
|
|
11172
11330
|
case "symlink":
|
|
11173
11331
|
await fs.symlink(req.arg2 ?? "", path, ownerFor2(entry));
|
|
11174
11332
|
return done;
|
|
11333
|
+
case "mkfifo": {
|
|
11334
|
+
const owner = ownerFor2(entry, req.mode ?? 438) ?? { uid: 0, gid: 0 };
|
|
11335
|
+
await createExclusive(fs, path, { ...owner, fifo: true });
|
|
11336
|
+
entry.fresh?.(path);
|
|
11337
|
+
return done;
|
|
11338
|
+
}
|
|
11175
11339
|
case "create":
|
|
11176
11340
|
await createExclusive(fs, path, ownerFor2(entry, req.mode ?? 438));
|
|
11177
11341
|
if (req.opening) entry.created?.add(path);
|
|
@@ -11250,9 +11414,10 @@ async function guard(g, path, req, cwd) {
|
|
|
11250
11414
|
return { path: await walkSafe(g, path, false) };
|
|
11251
11415
|
}
|
|
11252
11416
|
case "create":
|
|
11417
|
+
case "mkfifo":
|
|
11253
11418
|
case "symlink":
|
|
11254
11419
|
await inParent(g, op, path);
|
|
11255
|
-
return { path: await walkSafe(g, path, op
|
|
11420
|
+
return { path: await walkSafe(g, path, op !== "symlink") };
|
|
11256
11421
|
case "unlink":
|
|
11257
11422
|
case "rmdir": {
|
|
11258
11423
|
await inParent(g, op, path, true);
|
|
@@ -11340,6 +11505,7 @@ async function accessOp(entry, path, req) {
|
|
|
11340
11505
|
var CHANGING = /* @__PURE__ */ new Set([
|
|
11341
11506
|
"mkdir",
|
|
11342
11507
|
"create",
|
|
11508
|
+
"mkfifo",
|
|
11343
11509
|
"symlink",
|
|
11344
11510
|
"unlink",
|
|
11345
11511
|
"rmdir",
|
|
@@ -11534,7 +11700,13 @@ async function guardAndResolve(entry, path, req) {
|
|
|
11534
11700
|
};
|
|
11535
11701
|
}
|
|
11536
11702
|
var REMOVALS = /* @__PURE__ */ new Set(["unlink", "rmdir", "rm"]);
|
|
11537
|
-
var CREATIONS = /* @__PURE__ */ new Set([
|
|
11703
|
+
var CREATIONS = /* @__PURE__ */ new Set([
|
|
11704
|
+
"write",
|
|
11705
|
+
"mkdir",
|
|
11706
|
+
"symlink",
|
|
11707
|
+
"create",
|
|
11708
|
+
"mkfifo"
|
|
11709
|
+
]);
|
|
11538
11710
|
var NAMING = /* @__PURE__ */ new Set(["link", "rename"]);
|
|
11539
11711
|
async function newDevName(entry, path, req) {
|
|
11540
11712
|
const named = NAMING.has(req.op);
|
|
@@ -13281,16 +13453,16 @@ var TOKEN3 = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
|
13281
13453
|
var SAFE_VALUE = /^[^\r\n\0]*$/;
|
|
13282
13454
|
var CLOSE_WAIT_MS3 = 5e3;
|
|
13283
13455
|
var MAX_UNREAD = 16 * 1024 * 1024;
|
|
13284
|
-
function
|
|
13456
|
+
function errno2(code, message3) {
|
|
13285
13457
|
return Object.assign(new Error(`${code}: ${message3}`), { code });
|
|
13286
13458
|
}
|
|
13287
13459
|
function requestHead(method, url, headers, extra, first = []) {
|
|
13288
|
-
if (!TOKEN3.test(method)) throw
|
|
13460
|
+
if (!TOKEN3.test(method)) throw errno2("EINVAL", `method ${method}`);
|
|
13289
13461
|
const lines2 = [`${method} ${url.pathname}${url.search} HTTP/1.1`, `host: ${url.host}`];
|
|
13290
13462
|
for (const [name2, value2] of first) lines2.push(`${name2}: ${value2}`);
|
|
13291
13463
|
for (const [name2, value2] of headers) {
|
|
13292
13464
|
if (OWN_HEADERS.has(name2.toLowerCase())) continue;
|
|
13293
|
-
if (!TOKEN3.test(name2) || !SAFE_VALUE.test(value2)) throw
|
|
13465
|
+
if (!TOKEN3.test(name2) || !SAFE_VALUE.test(value2)) throw errno2("EINVAL", `header ${name2}`);
|
|
13294
13466
|
lines2.push(`${name2}: ${value2}`);
|
|
13295
13467
|
}
|
|
13296
13468
|
for (const [name2, value2] of extra) lines2.push(`${name2}: ${value2}`);
|
|
@@ -13301,7 +13473,7 @@ function requestHead(method, url, headers, extra, first = []) {
|
|
|
13301
13473
|
function parseHead(bytes) {
|
|
13302
13474
|
const [statusLine = "", ...lines2] = latin1(bytes).split(/\r?\n/);
|
|
13303
13475
|
const match = /^HTTP\/1\.[01] (\d{3})(?: (.*))?$/.exec(statusLine);
|
|
13304
|
-
if (!match) throw
|
|
13476
|
+
if (!match) throw errno2("EPROTO", `not an HTTP/1.x response: ${statusLine.slice(0, 80)}`);
|
|
13305
13477
|
const headers = [];
|
|
13306
13478
|
for (const line of lines2) {
|
|
13307
13479
|
const colon = line.indexOf(":");
|
|
@@ -13316,9 +13488,9 @@ async function readHead(incoming, signal) {
|
|
|
13316
13488
|
raw = await incoming.head(MAX_HEAD2, signal);
|
|
13317
13489
|
} catch (err) {
|
|
13318
13490
|
if (err instanceof KernelError) throw err;
|
|
13319
|
-
throw
|
|
13491
|
+
throw errno2("EPROTO", "the response head is malformed or too large");
|
|
13320
13492
|
}
|
|
13321
|
-
if (!raw) throw
|
|
13493
|
+
if (!raw) throw errno2("ECONNRESET", "the connection closed before a response");
|
|
13322
13494
|
const head = parseHead(raw);
|
|
13323
13495
|
if (head.status < 100 || head.status >= 200 || head.status === 101) return head;
|
|
13324
13496
|
}
|
|
@@ -13327,20 +13499,20 @@ async function* chunked(incoming, signal) {
|
|
|
13327
13499
|
for (; ; ) {
|
|
13328
13500
|
const line = await incoming.line(4096, signal);
|
|
13329
13501
|
const size = /^([0-9A-Fa-f]{1,12})[ \t]*(;.*)?$/.exec(line);
|
|
13330
|
-
if (!size) throw
|
|
13502
|
+
if (!size) throw errno2("EPROTO", "a malformed chunk size");
|
|
13331
13503
|
const n = Number.parseInt(size[1], 16);
|
|
13332
13504
|
if (n === 0) {
|
|
13333
13505
|
while (await incoming.line(MAX_HEAD2, signal) !== "") ;
|
|
13334
13506
|
return;
|
|
13335
13507
|
}
|
|
13336
13508
|
yield await incoming.exactly(n, signal);
|
|
13337
|
-
if (await incoming.line(2, signal) !== "") throw
|
|
13509
|
+
if (await incoming.line(2, signal) !== "") throw errno2("EPROTO", "a malformed chunk");
|
|
13338
13510
|
}
|
|
13339
13511
|
}
|
|
13340
13512
|
async function* counted(incoming, length2, signal) {
|
|
13341
13513
|
for (let left = length2; left > 0; ) {
|
|
13342
13514
|
const data = await incoming.some(Math.min(left, 64 * 1024), signal);
|
|
13343
|
-
if (data.length === 0) throw
|
|
13515
|
+
if (data.length === 0) throw errno2("EPROTO", "the body ended early");
|
|
13344
13516
|
left -= data.length;
|
|
13345
13517
|
yield data;
|
|
13346
13518
|
}
|
|
@@ -13361,7 +13533,7 @@ function bodyOf(incoming, head, method, signal) {
|
|
|
13361
13533
|
if (lengths.length === 0) return untilClose(incoming, signal);
|
|
13362
13534
|
const length2 = lengths[0]?.trim() ?? "";
|
|
13363
13535
|
if (!/^\d{1,15}$/.test(length2) || lengths.some((l) => l.trim() !== length2)) {
|
|
13364
|
-
throw
|
|
13536
|
+
throw errno2("EPROTO", `a malformed Content-Length: ${lengths.join(", ")}`);
|
|
13365
13537
|
}
|
|
13366
13538
|
return counted(incoming, Number(length2), signal);
|
|
13367
13539
|
}
|
|
@@ -13379,7 +13551,7 @@ var KernelLoopback = class {
|
|
|
13379
13551
|
}
|
|
13380
13552
|
async connect(url, port, signal) {
|
|
13381
13553
|
if (url.protocol === "https:" || url.protocol === "wss:") {
|
|
13382
|
-
throw
|
|
13554
|
+
throw errno2("ENOTSUP", `TLS to the kernel's loopback is not supported: ${url.origin}`);
|
|
13383
13555
|
}
|
|
13384
13556
|
signal.throwIfAborted();
|
|
13385
13557
|
const socket = this.net.socket("inet");
|
|
@@ -13394,7 +13566,7 @@ var KernelLoopback = class {
|
|
|
13394
13566
|
} catch (err) {
|
|
13395
13567
|
socket.close();
|
|
13396
13568
|
const refused2 = err instanceof KernelError && err.code === "ECONNREFUSED";
|
|
13397
|
-
throw refused2 ?
|
|
13569
|
+
throw refused2 ? errno2("ECONNREFUSED", `nothing listens on the kernel's port ${port}`) : err;
|
|
13398
13570
|
}
|
|
13399
13571
|
signal.addEventListener("abort", () => socket.close(), { once: true });
|
|
13400
13572
|
return socket;
|
|
@@ -13440,7 +13612,7 @@ var KernelLoopback = class {
|
|
|
13440
13612
|
const incoming = new Incoming(socket);
|
|
13441
13613
|
const head = await readHead(incoming, req.signal);
|
|
13442
13614
|
if (head.status !== 101) {
|
|
13443
|
-
throw
|
|
13615
|
+
throw errno2(
|
|
13444
13616
|
"EPROTO",
|
|
13445
13617
|
`the server answered the upgrade with ${head.status}${head.statusText ? ` ${head.statusText}` : ""}`
|
|
13446
13618
|
);
|
|
@@ -13448,10 +13620,10 @@ var KernelLoopback = class {
|
|
|
13448
13620
|
const upgraded = fieldTokens(head.headers, "upgrade").includes("websocket") && fieldTokens(head.headers, "connection").includes("upgrade");
|
|
13449
13621
|
const accept2 = fieldValues(head.headers, "sec-websocket-accept")[0];
|
|
13450
13622
|
if (!upgraded || accept2 !== await acceptFor(key)) {
|
|
13451
|
-
throw
|
|
13623
|
+
throw errno2("EPROTO", "the server did not accept the WebSocket key");
|
|
13452
13624
|
}
|
|
13453
13625
|
if (fieldValues(head.headers, "sec-websocket-extensions").length > 0) {
|
|
13454
|
-
throw
|
|
13626
|
+
throw errno2("EPROTO", "the server offered an unsolicited extension");
|
|
13455
13627
|
}
|
|
13456
13628
|
const protocol = fieldValues(head.headers, "sec-websocket-protocol")[0] ?? "";
|
|
13457
13629
|
return new LoopbackWebSocket(socket, incoming, protocol);
|
|
@@ -13469,7 +13641,7 @@ async function* closing(chunks2, socket) {
|
|
|
13469
13641
|
yield* chunks2;
|
|
13470
13642
|
} catch (err) {
|
|
13471
13643
|
if (typeof err?.code === "string") throw err;
|
|
13472
|
-
throw
|
|
13644
|
+
throw errno2("EPROTO", err instanceof Error ? err.message : String(err));
|
|
13473
13645
|
} finally {
|
|
13474
13646
|
socket.close();
|
|
13475
13647
|
}
|
|
@@ -13598,7 +13770,7 @@ var LoopbackWebSocket = class {
|
|
|
13598
13770
|
this.write(clientFrame(OP_CLOSE, payload));
|
|
13599
13771
|
}
|
|
13600
13772
|
send(data) {
|
|
13601
|
-
if (this.sentClose) throw
|
|
13773
|
+
if (this.sentClose) throw errno2("EPIPE", "the websocket is closing");
|
|
13602
13774
|
const text = typeof data === "string";
|
|
13603
13775
|
const payload = text ? new TextEncoder().encode(data) : data;
|
|
13604
13776
|
this.write(clientFrame(text ? OP_TEXT : OP_BINARY, payload));
|
|
@@ -14290,8 +14462,8 @@ function errnoOf(e) {
|
|
|
14290
14462
|
const code = e?.code;
|
|
14291
14463
|
return typeof code === "string" && ERRNO.test(code) ? code : "ECONNREFUSED";
|
|
14292
14464
|
}
|
|
14293
|
-
function fail(
|
|
14294
|
-
return { ok: false, errno:
|
|
14465
|
+
function fail(errno3, text) {
|
|
14466
|
+
return { ok: false, errno: errno3, message: text };
|
|
14295
14467
|
}
|
|
14296
14468
|
var WsHandles = class {
|
|
14297
14469
|
transport;
|
|
@@ -14565,8 +14737,8 @@ var HttpHandles = class {
|
|
|
14565
14737
|
const status = e.status;
|
|
14566
14738
|
if (text === NO_TRANSPORT || typeof status !== "number" || status === 502) {
|
|
14567
14739
|
const code = codeOf2(e);
|
|
14568
|
-
const
|
|
14569
|
-
return { ok: false, errno:
|
|
14740
|
+
const errno3 = text === NO_TRANSPORT ? "ENETUNREACH" : code !== "EIO" ? code : "ECONNREFUSED";
|
|
14741
|
+
return { ok: false, errno: errno3, message: text };
|
|
14570
14742
|
}
|
|
14571
14743
|
entry.body = once(new TextEncoder().encode(text))[Symbol.asyncIterator]();
|
|
14572
14744
|
return this.headOf(handle, req.url, {
|
|
@@ -15661,7 +15833,7 @@ var UNREACHABLE = ["EACCES", "ENETUNREACH", "EHOSTUNREACH"];
|
|
|
15661
15833
|
function sendError(e) {
|
|
15662
15834
|
if (e instanceof KernelError) return e;
|
|
15663
15835
|
const code = e?.code;
|
|
15664
|
-
return new KernelError(SEND_ERRORS.find((
|
|
15836
|
+
return new KernelError(SEND_ERRORS.find((errno3) => errno3 === code) ?? "EHOSTUNREACH");
|
|
15665
15837
|
}
|
|
15666
15838
|
function sameAddr(a, b) {
|
|
15667
15839
|
return a.port === b.port && canonicalHost(a.host) === canonicalHost(b.host);
|
|
@@ -15790,7 +15962,7 @@ var KernelDgram = class {
|
|
|
15790
15962
|
}
|
|
15791
15963
|
unreachable(error, from) {
|
|
15792
15964
|
if (!this.peer || !sameAddr(this.peer, from)) return;
|
|
15793
|
-
this.pending = UNREACHABLE.find((
|
|
15965
|
+
this.pending = UNREACHABLE.find((errno3) => errno3 === error) ?? "EHOSTUNREACH";
|
|
15794
15966
|
this.changes.wake();
|
|
15795
15967
|
}
|
|
15796
15968
|
deliver(datagram2) {
|
|
@@ -17108,6 +17280,7 @@ var SYSCALL_OPS = /* @__PURE__ */ new Set([
|
|
|
17108
17280
|
"sig-mask",
|
|
17109
17281
|
"sig-inherited",
|
|
17110
17282
|
"sig-waiting",
|
|
17283
|
+
"sig-info",
|
|
17111
17284
|
"sig-pause",
|
|
17112
17285
|
...SOCKET_OPS,
|
|
17113
17286
|
...EPOLL_OPS,
|
|
@@ -17121,6 +17294,7 @@ function isWasmSyscall(req) {
|
|
|
17121
17294
|
return typeof op === "string" && SYSCALL_OPS.has(op);
|
|
17122
17295
|
}
|
|
17123
17296
|
var MAX_READ = 1024 * 1024;
|
|
17297
|
+
var O_NONBLOCK = 2048;
|
|
17124
17298
|
var WRITE_ACCESS = 3;
|
|
17125
17299
|
var KEYBOARD = /* @__PURE__ */ new Set([SIG.INT, SIG.QUIT, SIG.TSTP]);
|
|
17126
17300
|
var DEFAULT_UMASK2 = 18;
|
|
@@ -17189,7 +17363,7 @@ var WasmProcess = class {
|
|
|
17189
17363
|
this.children = new ChildTable(fds, options.spawner, options.forker);
|
|
17190
17364
|
this.nodes = options.nodes ?? new VfsNodes(options.fs);
|
|
17191
17365
|
if (!options.nodes) options.openFiles?.add(this.nodes);
|
|
17192
|
-
this.children.onChildState = () => this.signal(SIG.CHLD);
|
|
17366
|
+
this.children.onChildState = (child) => this.signal(SIG.CHLD, child && this.childInfo(child));
|
|
17193
17367
|
this.children.autoReap = () => this.reapsChildren();
|
|
17194
17368
|
this.seedDl(options.dl);
|
|
17195
17369
|
this.children.onReap = (pid2) => {
|
|
@@ -17206,10 +17380,43 @@ var WasmProcess = class {
|
|
|
17206
17380
|
inheritable(fork = false) {
|
|
17207
17381
|
return ((fork ? 0 : this.ignored) | this.inherited) & ~this.caught;
|
|
17208
17382
|
}
|
|
17209
|
-
|
|
17383
|
+
sigInfos = /* @__PURE__ */ new Map();
|
|
17384
|
+
signal(sig, info) {
|
|
17385
|
+
const pending = ((this.options.pendingBits?.() ?? 0) & sigbit(sig)) !== 0;
|
|
17386
|
+
const outcome = this.signalOutcome(sig, info);
|
|
17387
|
+
if (outcome === "deliver" && !(pending && this.sigInfos.has(`0:${sig}`))) {
|
|
17388
|
+
this.sigInfos.set(`0:${sig}`, info ?? KERNEL_SIGINFO);
|
|
17389
|
+
}
|
|
17390
|
+
return outcome;
|
|
17391
|
+
}
|
|
17392
|
+
async threadKill(tid, sig) {
|
|
17393
|
+
const info = await this.threadSender(sig);
|
|
17394
|
+
if (this.options.threadKill?.(tid, sig)) this.sigInfos.set(`${tid}:${sig}`, info);
|
|
17395
|
+
else this.options.raise?.(sig, info);
|
|
17396
|
+
}
|
|
17397
|
+
async threadSender(sig) {
|
|
17398
|
+
const pid = (await this.options.identity?.())?.pid ?? this.pid;
|
|
17399
|
+
const code = sig === SIG.PIPE ? SI.USER : SI.TKILL;
|
|
17400
|
+
return { code, pid, uid: this.cred.ruid, status: 0 };
|
|
17401
|
+
}
|
|
17402
|
+
childInfo(child) {
|
|
17403
|
+
const code = child.state === "stopped" ? CLD.STOPPED : child.state === "continued" ? CLD.CONTINUED : child.termsig ? CLD.KILLED : CLD.EXITED;
|
|
17404
|
+
return { code, pid: child.pid, uid: child.uid ?? this.cred.ruid, status: child.status };
|
|
17405
|
+
}
|
|
17406
|
+
takeSigInfo(sig, tid) {
|
|
17407
|
+
for (const key of [`${tid}:${sig}`, `0:${sig}`]) {
|
|
17408
|
+
const info = this.sigInfos.get(key);
|
|
17409
|
+
if (info) {
|
|
17410
|
+
this.sigInfos.delete(key);
|
|
17411
|
+
return info;
|
|
17412
|
+
}
|
|
17413
|
+
}
|
|
17414
|
+
return null;
|
|
17415
|
+
}
|
|
17416
|
+
signalOutcome(sig, info) {
|
|
17210
17417
|
if (this.execChild !== void 0) {
|
|
17211
17418
|
if (sig === SIG.CONT) this.cont();
|
|
17212
|
-
void Promise.resolve(this.options.kill?.(this.execChild, sig)).catch(() => void 0);
|
|
17419
|
+
void Promise.resolve(this.options.kill?.(this.execChild, sig, info)).catch(() => void 0);
|
|
17213
17420
|
if (sig !== SIG.KILL) return "forward";
|
|
17214
17421
|
if (!this.options.writesBack?.(this.execChild)) return "terminate";
|
|
17215
17422
|
this.wake?.();
|
|
@@ -17585,7 +17792,7 @@ var WasmProcess = class {
|
|
|
17585
17792
|
this.options.hasPending?.() ? AbortSignal.abort() : this.cancelSignal(cancelled)
|
|
17586
17793
|
);
|
|
17587
17794
|
}
|
|
17588
|
-
async openVfs(req) {
|
|
17795
|
+
async openVfs(req, cancelled) {
|
|
17589
17796
|
if (inProc(req.path)) return this.openProc(req, req.path);
|
|
17590
17797
|
const device = req.orphan ? void 0 : deviceAt(req.path);
|
|
17591
17798
|
if (device) return this.openDevice(req, device);
|
|
@@ -17596,6 +17803,10 @@ var WasmProcess = class {
|
|
|
17596
17803
|
await refuseReadonly(this.options.fs, req.path, req.flags, req);
|
|
17597
17804
|
if (this.writesAt(req)) await this.options.fs.mayChange?.(req.path, !req.exclusive);
|
|
17598
17805
|
await this.mayOpen(req);
|
|
17806
|
+
if (req.fifo && !req.exclusive) {
|
|
17807
|
+
const opened2 = await this.openFifo(req, cancelled);
|
|
17808
|
+
if (opened2 !== void 0) return opened2;
|
|
17809
|
+
}
|
|
17599
17810
|
const marked = await this.markedPath(req);
|
|
17600
17811
|
await this.sourceOpen(marked === void 0 ? req : { ...req, path: marked });
|
|
17601
17812
|
const fs = marked === void 0 ? this.options.fs : this.options.noLinks;
|
|
@@ -17637,6 +17848,19 @@ var WasmProcess = class {
|
|
|
17637
17848
|
}
|
|
17638
17849
|
return fd;
|
|
17639
17850
|
}
|
|
17851
|
+
async openFifo(req, cancelled) {
|
|
17852
|
+
const fifos = this.options.fifos;
|
|
17853
|
+
const path = await this.nodes.targetKey(req.path);
|
|
17854
|
+
const st = await this.heldFs().stat(path);
|
|
17855
|
+
if (!st.isFifo) return void 0;
|
|
17856
|
+
if (!fifos) throw new KernelError("ENXIO");
|
|
17857
|
+
const access2 = openAccess(req.flags);
|
|
17858
|
+
const nonblock = (req.flags & O_NONBLOCK) !== 0;
|
|
17859
|
+
const blocks = !nonblock && access2 !== "both";
|
|
17860
|
+
const signal = blocks ? this.blockingSignal(cancelled) : cancelled;
|
|
17861
|
+
const end = await fifos.open(`${st.dev ?? 0}:${st.ino}`, path, access2, nonblock, signal);
|
|
17862
|
+
return this.fds.install(end, 3);
|
|
17863
|
+
}
|
|
17640
17864
|
openDevice(req, device) {
|
|
17641
17865
|
if (req.exclusive) throw Object.assign(new Error(req.path), { code: "EEXIST" });
|
|
17642
17866
|
const access2 = req.flags & WRITE_ACCESS;
|
|
@@ -17836,7 +18060,7 @@ var WasmProcess = class {
|
|
|
17836
18060
|
case "fd-poll":
|
|
17837
18061
|
return { ok: true, kind: "json", json: pollFile(this.fds.get(req.fd).file) };
|
|
17838
18062
|
case "fd-open-vfs":
|
|
17839
|
-
return { ok: true, kind: "json", json: await this.openVfs(req) };
|
|
18063
|
+
return { ok: true, kind: "json", json: await this.openVfs(req, cancelled) };
|
|
17840
18064
|
case "fd-info":
|
|
17841
18065
|
return { ok: true, kind: "json", json: this.fdInfo(req.fd) };
|
|
17842
18066
|
case "fd-list":
|
|
@@ -18270,8 +18494,10 @@ var WasmProcess = class {
|
|
|
18270
18494
|
case "sig-pause":
|
|
18271
18495
|
return this.pause(cancelled);
|
|
18272
18496
|
case "thread-kill":
|
|
18273
|
-
|
|
18497
|
+
await this.threadKill(req.tid, req.sig);
|
|
18274
18498
|
return { ok: true, kind: "void" };
|
|
18499
|
+
case "sig-info":
|
|
18500
|
+
return { ok: true, kind: "json", json: this.takeSigInfo(req.sig, req.tid ?? 0) };
|
|
18275
18501
|
case "proc-captured":
|
|
18276
18502
|
return { ok: true, kind: "bytes", bytes: this.children.captured(req.pid, req.slot) };
|
|
18277
18503
|
case "proc-sudo":
|
|
@@ -18494,7 +18720,8 @@ function inheritedFds(fds) {
|
|
|
18494
18720
|
...kind === "device" && meta && "device" in meta ? { device: meta } : {},
|
|
18495
18721
|
...flags2 !== void 0 ? { flags: flags2 } : {},
|
|
18496
18722
|
...fds.closesOnExec(fd) ? { cloexec: true } : {},
|
|
18497
|
-
...kind === "stream" ? { desc: descId(open) } : {}
|
|
18723
|
+
...kind === "stream" ? { desc: descId(open) } : {},
|
|
18724
|
+
...open.file.fifo ? { fifo: open.file.fifo } : {}
|
|
18498
18725
|
};
|
|
18499
18726
|
});
|
|
18500
18727
|
}
|
|
@@ -18700,6 +18927,7 @@ function processOptions(opts, header4, hooks, created3) {
|
|
|
18700
18927
|
net: opts.net,
|
|
18701
18928
|
http: opts.http,
|
|
18702
18929
|
locks: opts.locks,
|
|
18930
|
+
fifos: opts.fifos,
|
|
18703
18931
|
...opts.sems ? { sems: opts.sems } : {},
|
|
18704
18932
|
onReap: opts.onReap,
|
|
18705
18933
|
resolver: opts.resolver,
|
|
@@ -18750,7 +18978,7 @@ function spawnWasmProcess(opts) {
|
|
|
18750
18978
|
opts,
|
|
18751
18979
|
header4,
|
|
18752
18980
|
{
|
|
18753
|
-
raise: (sig) => signal(sig),
|
|
18981
|
+
raise: (sig, info) => signal(sig, info),
|
|
18754
18982
|
threadKill: (tid, sig) => killThread(threadSignals.get(tid), process2.signalMasks().caught, sig),
|
|
18755
18983
|
unblockedThread: (sig) => unblockedThread(threadSignals, sig),
|
|
18756
18984
|
...opts.program.abi === "js" ? {
|
|
@@ -18872,8 +19100,9 @@ function spawnWasmProcess(opts) {
|
|
|
18872
19100
|
if (opts.program.abi !== "wasi" || done4) finish(code, sig);
|
|
18873
19101
|
else dying.start(code, sig, header4, process2, () => finish(code, sig));
|
|
18874
19102
|
};
|
|
18875
|
-
const signal = (sig) => {
|
|
18876
|
-
if (process2.signal(sig) === "terminate")
|
|
19103
|
+
const signal = (sig, info) => {
|
|
19104
|
+
if (process2.signal(sig, info) === "terminate")
|
|
19105
|
+
terminate(sig === SIG.KILL ? 137 : 128 + sig, sig);
|
|
18877
19106
|
};
|
|
18878
19107
|
const kill = (code = 137) => finish(code, code > 128 && code < 160 ? code - 128 : void 0);
|
|
18879
19108
|
return {
|
|
@@ -19043,14 +19272,14 @@ var JobTable = class {
|
|
|
19043
19272
|
this.foreground.set(tty, member.pgid);
|
|
19044
19273
|
return true;
|
|
19045
19274
|
}
|
|
19046
|
-
killGroup(pgid, sig, may = () => true) {
|
|
19275
|
+
killGroup(pgid, sig, may = () => true, info) {
|
|
19047
19276
|
const group = [...this.members.values()].filter((m) => m.pgid === pgid);
|
|
19048
19277
|
const targets = group.filter((m) => may(m.pid));
|
|
19049
19278
|
if (targets.length === 0 && group.length > 0) throw new KernelError("EPERM");
|
|
19050
19279
|
const pids = new Set(targets.map((m) => m.pid));
|
|
19051
19280
|
if (sig !== 0) {
|
|
19052
19281
|
for (const m of targets)
|
|
19053
|
-
if (m.execParent === void 0 || !pids.has(m.execParent)) m.signal(sig);
|
|
19282
|
+
if (m.execParent === void 0 || !pids.has(m.execParent)) m.signal(sig, info);
|
|
19054
19283
|
}
|
|
19055
19284
|
return targets.length > 0;
|
|
19056
19285
|
}
|
|
@@ -20637,9 +20866,9 @@ var HostfsClient = class {
|
|
|
20637
20866
|
throw fsError2("ESTALE", "the folder was granted again, so its open files are gone");
|
|
20638
20867
|
return this.send(path, init, false, true);
|
|
20639
20868
|
}
|
|
20640
|
-
const
|
|
20869
|
+
const errno3 = response.headers.get("X-Hostfs-Errno") ?? "EIO";
|
|
20641
20870
|
const body = await response.json().catch(() => ({}));
|
|
20642
|
-
throw fsError2(
|
|
20871
|
+
throw fsError2(errno3, typeof body.message === "string" ? body.message : errno3);
|
|
20643
20872
|
}
|
|
20644
20873
|
async call(op, body = {}, handle = false) {
|
|
20645
20874
|
const response = await this.send(
|
|
@@ -21796,8 +22025,8 @@ var RULE = new RegExp(
|
|
|
21796
22025
|
var TERM = /^[A-Za-z0-9._+-]+$/;
|
|
21797
22026
|
var PLAIN = /^[A-Za-z0-9_@%+=:,./-]+$/;
|
|
21798
22027
|
var USAGE = "usage: sudo [-n] [-u user] [--] command [args...]\n sudo -l";
|
|
21799
|
-
function failed2(
|
|
21800
|
-
return { error, errno:
|
|
22028
|
+
function failed2(errno3, error) {
|
|
22029
|
+
return { error, errno: errno3 };
|
|
21801
22030
|
}
|
|
21802
22031
|
function unescaped(double) {
|
|
21803
22032
|
return double.replace(/\\(["\\$`])/g, "$1");
|
|
@@ -22389,7 +22618,8 @@ function childHandle(handle) {
|
|
|
22389
22618
|
pid: handle.pid,
|
|
22390
22619
|
exited: handle.exited,
|
|
22391
22620
|
termsig: handle.termsig,
|
|
22392
|
-
onState: (listener) => handle.onState(listener)
|
|
22621
|
+
onState: (listener) => handle.onState(listener),
|
|
22622
|
+
uid: () => handle.cred?.().ruid
|
|
22393
22623
|
};
|
|
22394
22624
|
}
|
|
22395
22625
|
function concat7(chunks2) {
|
|
@@ -22453,6 +22683,7 @@ var Launcher = class {
|
|
|
22453
22683
|
sudoer;
|
|
22454
22684
|
jobs = new JobTable();
|
|
22455
22685
|
locks = new LockTable();
|
|
22686
|
+
fifos = new FifoTable();
|
|
22456
22687
|
sems = new SemTable();
|
|
22457
22688
|
settling = new SettlingChildren((pid) => this.jobs.pgidOf(pid));
|
|
22458
22689
|
ptys = new PtyTable(
|
|
@@ -23427,7 +23658,7 @@ var Launcher = class {
|
|
|
23427
23658
|
onError: req.report,
|
|
23428
23659
|
spawner: this.spawner(pid, req.report),
|
|
23429
23660
|
forker: this.forker(pid, req),
|
|
23430
|
-
kill: (target, sig) => this.kill(target, sig, this.credOf(pid), pid),
|
|
23661
|
+
kill: (target, sig, info) => this.kill(target, sig, this.credOf(pid), pid, info),
|
|
23431
23662
|
writesBack: (target) => this.processes.get(target)?.writesBack() === true,
|
|
23432
23663
|
processes: () => ({
|
|
23433
23664
|
boot: this.boot,
|
|
@@ -23450,6 +23681,7 @@ var Launcher = class {
|
|
|
23450
23681
|
net: this.net,
|
|
23451
23682
|
http: new HttpHandles(this.transport, pid, this.loopbackFor(pid)),
|
|
23452
23683
|
locks: this.locks,
|
|
23684
|
+
fifos: this.fifos,
|
|
23453
23685
|
sems: this.sems,
|
|
23454
23686
|
resolver: this.resolver,
|
|
23455
23687
|
onReap: (child) => this.reaped(child, pid),
|
|
@@ -23462,7 +23694,7 @@ var Launcher = class {
|
|
|
23462
23694
|
this.creds.set(pid, () => handle.cred?.() ?? copyCred(cred));
|
|
23463
23695
|
this.marks(pid, req);
|
|
23464
23696
|
if (req.ppid !== void 0 && this.controlsJobs(req.ppid)) this.settling.started(pid, req.ppid);
|
|
23465
|
-
this.jobs.add(pid, req.ppid, (sig) => handle.signal(sig), terminal);
|
|
23697
|
+
this.jobs.add(pid, req.ppid, (sig, info) => handle.signal(sig, info), terminal);
|
|
23466
23698
|
if (req.exec && req.ppid !== void 0) this.jobs.exec(req.ppid, pid, true);
|
|
23467
23699
|
if (req.pgid !== void 0) this.jobs.join(pid, req.pgid);
|
|
23468
23700
|
if (req.group === "lead") this.jobs.lead(pid);
|
|
@@ -23843,21 +24075,26 @@ var Launcher = class {
|
|
|
23843
24075
|
ignoredBy(pid, fork = false) {
|
|
23844
24076
|
return this.processes.get(pid)?.ignoredSignals(fork) ?? 0;
|
|
23845
24077
|
}
|
|
23846
|
-
kill(pid, sig, sender, from) {
|
|
24078
|
+
kill(pid, sig, sender, from, forwarded) {
|
|
24079
|
+
const info = forwarded ?? this.senderInfo(sender, from);
|
|
23847
24080
|
const session = from === void 0 ? void 0 : this.jobs.sidOf(from);
|
|
23848
24081
|
const may = (target) => !sender || maySignal(sender, this.credOf(target)) || sig === SIG.CONT && session !== void 0 && this.jobs.sidOf(target) === session || from !== void 0 && this.imageOf(from) === this.imageOf(target) || from !== void 0 && this.granted.get(this.jobs.shown(target)) === from || from !== void 0 && this.granted.get(this.jobs.pgidOf(target) ?? 0) === from;
|
|
23849
24082
|
if (pid === -1) {
|
|
23850
24083
|
const sender2 = from === void 0 ? void 0 : this.imageOf(from);
|
|
23851
|
-
return this.killAll(sig, (member) => this.imageOf(member) !== sender2, may);
|
|
24084
|
+
return this.killAll(sig, (member) => this.imageOf(member) !== sender2, may, info);
|
|
23852
24085
|
}
|
|
23853
|
-
if (pid < 0) return this.jobs.killGroup(-pid, sig, (member) => may(this.imageOf(member)));
|
|
24086
|
+
if (pid < 0) return this.jobs.killGroup(-pid, sig, (member) => may(this.imageOf(member)), info);
|
|
23854
24087
|
const handle = this.processes.get(pid);
|
|
23855
24088
|
if (!handle) return false;
|
|
23856
24089
|
if (!may(this.imageOf(pid))) throw fsError("EPERM", `pid ${pid}`);
|
|
23857
|
-
if (sig !== 0) handle.signal(sig);
|
|
24090
|
+
if (sig !== 0) handle.signal(sig, info);
|
|
23858
24091
|
return true;
|
|
23859
24092
|
}
|
|
23860
|
-
|
|
24093
|
+
senderInfo(sender, from) {
|
|
24094
|
+
if (from === void 0) return void 0;
|
|
24095
|
+
return { code: SI.USER, pid: this.jobs.shown(from), uid: sender?.ruid ?? 0, status: 0 };
|
|
24096
|
+
}
|
|
24097
|
+
killAll(sig, other, may, info) {
|
|
23861
24098
|
const candidates = [...this.processes].filter(([pid]) => pid !== 1 && other(pid));
|
|
23862
24099
|
const targets = candidates.filter(([pid]) => may(this.imageOf(pid)));
|
|
23863
24100
|
if (targets.length === 0 && candidates.length > 0) throw fsError("EPERM", "kill -1");
|
|
@@ -23865,7 +24102,7 @@ var Launcher = class {
|
|
|
23865
24102
|
const parents = new Map(this.jobs.list().map((m) => [m.pid, m.execParent]));
|
|
23866
24103
|
for (const [pid, handle] of targets) {
|
|
23867
24104
|
const parent = parents.get(pid);
|
|
23868
|
-
if (sig !== 0 && (parent === void 0 || !pids.has(parent))) handle.signal(sig);
|
|
24105
|
+
if (sig !== 0 && (parent === void 0 || !pids.has(parent))) handle.signal(sig, info);
|
|
23869
24106
|
}
|
|
23870
24107
|
return targets.length > 0;
|
|
23871
24108
|
}
|