@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/kernel-worker.js
CHANGED
|
@@ -988,6 +988,7 @@ var S_IFDIR = 16384;
|
|
|
988
988
|
var S_IFREG = 32768;
|
|
989
989
|
var S_IFLNK = 40960;
|
|
990
990
|
var S_IFSOCK = 49152;
|
|
991
|
+
var S_IFIFO = 4096;
|
|
991
992
|
var PERM_MASK = 4095;
|
|
992
993
|
var S_ISGID2 = 1024;
|
|
993
994
|
var READ_ATTEMPTS = 3;
|
|
@@ -1271,7 +1272,10 @@ var OpfsFs = class {
|
|
|
1271
1272
|
}
|
|
1272
1273
|
async stampNew(path, owner, directory) {
|
|
1273
1274
|
const owned4 = await this.newFields(path, owner, directory);
|
|
1274
|
-
|
|
1275
|
+
if (owner?.socket && owner.fifo) throw new Error("a new node is a socket or a FIFO, not both");
|
|
1276
|
+
const kind = directory ? void 0 : owner?.socket ? "socket" : owner?.fifo ? "fifo" : void 0;
|
|
1277
|
+
const unique = kind === "fifo" ? { ino: inodeOf(`${path}\0${crypto.randomUUID()}`) } : {};
|
|
1278
|
+
const fields = kind ? { ...owned4, ...unique, [kind]: true } : owned4;
|
|
1275
1279
|
if (fields) await this.meta.update(path, (entry) => ({ ...entry, path, ...fields }));
|
|
1276
1280
|
}
|
|
1277
1281
|
guarded = [];
|
|
@@ -1513,7 +1517,7 @@ var OpfsFs = class {
|
|
|
1513
1517
|
}
|
|
1514
1518
|
mode(path, directory, meta) {
|
|
1515
1519
|
const fallback = directory || EXECUTABLE.test(path) ? 493 : 420;
|
|
1516
|
-
const type = directory ? S_IFDIR : meta?.socket ? S_IFSOCK : S_IFREG;
|
|
1520
|
+
const type = directory ? S_IFDIR : meta?.socket ? S_IFSOCK : meta?.fifo ? S_IFIFO : S_IFREG;
|
|
1517
1521
|
return type | (meta?.mode ?? fallback);
|
|
1518
1522
|
}
|
|
1519
1523
|
id = crypto.randomUUID();
|
|
@@ -1614,11 +1618,13 @@ var OpfsFs = class {
|
|
|
1614
1618
|
const kept = meta?.mtimeMs !== void 0 && meta.mtimeFor === modified ? meta.mtimeMs : modified;
|
|
1615
1619
|
const mtime = touched ?? kept;
|
|
1616
1620
|
const socket = !directory && meta?.socket === true;
|
|
1621
|
+
const fifo = !directory && meta?.fifo === true;
|
|
1617
1622
|
return {
|
|
1618
|
-
isFile: !directory && !socket,
|
|
1623
|
+
isFile: !directory && !socket && !fifo,
|
|
1619
1624
|
isDirectory: directory,
|
|
1620
1625
|
isSymbolicLink: false,
|
|
1621
1626
|
...socket ? { isSocket: true } : {},
|
|
1627
|
+
...fifo ? { isFifo: true } : {},
|
|
1622
1628
|
size: file?.size ?? 0,
|
|
1623
1629
|
mode: this.mode(path, directory, meta),
|
|
1624
1630
|
mtime: new Date(mtime),
|
|
@@ -3310,8 +3316,8 @@ async function access(fs, cred, path, want, options = {}) {
|
|
|
3310
3316
|
if (await present(fs, walked.path, false)) return { ...walked, denied: walked.path };
|
|
3311
3317
|
return { ...walked, missing: true };
|
|
3312
3318
|
}
|
|
3313
|
-
function refused(path,
|
|
3314
|
-
return fsError(
|
|
3319
|
+
function refused(path, errno3 = "EACCES") {
|
|
3320
|
+
return fsError(errno3, path);
|
|
3315
3321
|
}
|
|
3316
3322
|
|
|
3317
3323
|
// src/fs/dac.ts
|
|
@@ -3371,9 +3377,9 @@ var Created = class {
|
|
|
3371
3377
|
function linked(g, options) {
|
|
3372
3378
|
return g.links === void 0 ? options : { ...options, links: g.links };
|
|
3373
3379
|
}
|
|
3374
|
-
function deny(g, op, path,
|
|
3380
|
+
function deny(g, op, path, errno3 = "EACCES") {
|
|
3375
3381
|
const tag = g.tag === void 0 ? {} : { tag: g.tag };
|
|
3376
|
-
g.dac.denied({ pid: g.pid, uid: g.cred.euid, op, path, errno:
|
|
3382
|
+
g.dac.denied({ pid: g.pid, uid: g.cred.euid, op, path, errno: errno3, ...tag });
|
|
3377
3383
|
}
|
|
3378
3384
|
var TTY_MODE = 400;
|
|
3379
3385
|
function ttyOpenable(g, tty) {
|
|
@@ -4086,7 +4092,7 @@ var WASI_SIGNAL_TO_POSIX = Object.fromEntries(
|
|
|
4086
4092
|
|
|
4087
4093
|
// src/process/wasi-errno.ts
|
|
4088
4094
|
var WASI_ERRNO = {
|
|
4089
|
-
...Object.fromEntries(Object.entries(E).map(([name2,
|
|
4095
|
+
...Object.fromEntries(Object.entries(E).map(([name2, errno3]) => [`E${name2}`, errno3])),
|
|
4090
4096
|
EWOULDBLOCK: E.AGAIN,
|
|
4091
4097
|
ENOTSUP: 138,
|
|
4092
4098
|
EOPNOTSUPP: 138,
|
|
@@ -4326,7 +4332,7 @@ function dialError(e, timedOut, closed) {
|
|
|
4326
4332
|
if (timedOut) return new KernelError("ETIMEDOUT");
|
|
4327
4333
|
if (closed) return new KernelError("ECONNABORTED");
|
|
4328
4334
|
const code = e?.code;
|
|
4329
|
-
const known = DIAL_ERRORS.find((
|
|
4335
|
+
const known = DIAL_ERRORS.find((errno3) => errno3 === code);
|
|
4330
4336
|
return new KernelError(known ?? "EHOSTUNREACH");
|
|
4331
4337
|
}
|
|
4332
4338
|
function isLoopback(host) {
|
|
@@ -4962,6 +4968,14 @@ var SIGNAL_BY_NAME = {
|
|
|
4962
4968
|
SIGSTOP: SIG.STOP,
|
|
4963
4969
|
SIGCONT: SIG.CONT
|
|
4964
4970
|
};
|
|
4971
|
+
var SI = { USER: 0, QUEUE: -1, TIMER: -2, TKILL: -6, KERNEL: 128 };
|
|
4972
|
+
var CLD = { EXITED: 1, KILLED: 2, DUMPED: 3, STOPPED: 5, CONTINUED: 6 };
|
|
4973
|
+
var KERNEL_SIGINFO = Object.freeze({
|
|
4974
|
+
code: SI.KERNEL,
|
|
4975
|
+
pid: 0,
|
|
4976
|
+
uid: 0,
|
|
4977
|
+
status: 0
|
|
4978
|
+
});
|
|
4965
4979
|
|
|
4966
4980
|
// src/body-idle.ts
|
|
4967
4981
|
var BODY_IDLE_MS = 5 * 60 * 1e3;
|
|
@@ -6213,7 +6227,7 @@ function satisfies(version, range2) {
|
|
|
6213
6227
|
}
|
|
6214
6228
|
|
|
6215
6229
|
// src/version.ts
|
|
6216
|
-
var KERNEL_VERSION = true ? "1.
|
|
6230
|
+
var KERNEL_VERSION = true ? "1.115.0" : "0.0.0-dev";
|
|
6217
6231
|
var OS_RELEASE = "6.0.0-slicc";
|
|
6218
6232
|
function procVersion() {
|
|
6219
6233
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -9089,8 +9103,16 @@ var ChildTable = class {
|
|
|
9089
9103
|
void handle.exited.then((code) => {
|
|
9090
9104
|
child.code = code;
|
|
9091
9105
|
this.watchers.delete(handle.pid);
|
|
9106
|
+
const termsig = handle.termsig?.();
|
|
9092
9107
|
if (!this.kept.delete(handle.pid) && this.autoReap?.()) this.reap(handle.pid, code);
|
|
9093
|
-
|
|
9108
|
+
const uid = handle.uid?.();
|
|
9109
|
+
this.onChildState?.({
|
|
9110
|
+
pid: handle.pid,
|
|
9111
|
+
state: "exited",
|
|
9112
|
+
status: termsig ?? code,
|
|
9113
|
+
termsig,
|
|
9114
|
+
uid
|
|
9115
|
+
});
|
|
9094
9116
|
});
|
|
9095
9117
|
handle.onState?.((state, sig) => {
|
|
9096
9118
|
child.stopReport = state === "stopped" ? sig : void 0;
|
|
@@ -9100,7 +9122,7 @@ var ChildTable = class {
|
|
|
9100
9122
|
const waiters = this.stateChanged;
|
|
9101
9123
|
this.stateChanged = [];
|
|
9102
9124
|
for (const wake of waiters) wake();
|
|
9103
|
-
this.onChildState?.();
|
|
9125
|
+
this.onChildState?.({ pid: handle.pid, state, status: sig, uid: handle.uid?.() });
|
|
9104
9126
|
});
|
|
9105
9127
|
this.children.set(handle.pid, child);
|
|
9106
9128
|
return handle.pid;
|
|
@@ -9430,6 +9452,139 @@ var TicketBook = class {
|
|
|
9430
9452
|
}
|
|
9431
9453
|
};
|
|
9432
9454
|
|
|
9455
|
+
// src/kernel/fifo.ts
|
|
9456
|
+
function errno(e) {
|
|
9457
|
+
return e instanceof KernelError ? e : new KernelError(e.code ?? "EIO");
|
|
9458
|
+
}
|
|
9459
|
+
var FifoTable = class {
|
|
9460
|
+
fifos = /* @__PURE__ */ new Map();
|
|
9461
|
+
size() {
|
|
9462
|
+
return this.fifos.size;
|
|
9463
|
+
}
|
|
9464
|
+
async open(key, path, access2, nonblock, signal) {
|
|
9465
|
+
const fifo = this.entry(key);
|
|
9466
|
+
if (access2 === "write" && nonblock && fifo.readers === 0) {
|
|
9467
|
+
this.drop(key, fifo);
|
|
9468
|
+
throw new KernelError("ENXIO");
|
|
9469
|
+
}
|
|
9470
|
+
const reads = access2 !== "write";
|
|
9471
|
+
const writes = access2 !== "read";
|
|
9472
|
+
const seen = { readOpens: fifo.readOpens, writeOpens: fifo.writeOpens };
|
|
9473
|
+
if (reads) this.count(fifo, "readers", 1);
|
|
9474
|
+
if (writes) this.count(fifo, "writers", 1);
|
|
9475
|
+
this.notify(fifo);
|
|
9476
|
+
try {
|
|
9477
|
+
if (!nonblock && access2 === "read") {
|
|
9478
|
+
while (fifo.writers === 0 && fifo.writeOpens === seen.writeOpens) {
|
|
9479
|
+
await this.changed(fifo, signal);
|
|
9480
|
+
}
|
|
9481
|
+
}
|
|
9482
|
+
if (!nonblock && access2 === "write") {
|
|
9483
|
+
while (fifo.readers === 0 && fifo.readOpens === seen.readOpens) {
|
|
9484
|
+
await this.changed(fifo, signal);
|
|
9485
|
+
}
|
|
9486
|
+
}
|
|
9487
|
+
} catch (e) {
|
|
9488
|
+
this.release(key, fifo, reads, writes);
|
|
9489
|
+
throw errno(e);
|
|
9490
|
+
}
|
|
9491
|
+
return this.end(key, path, fifo, reads, writes);
|
|
9492
|
+
}
|
|
9493
|
+
entry(key) {
|
|
9494
|
+
let fifo = this.fifos.get(key);
|
|
9495
|
+
if (!fifo) {
|
|
9496
|
+
fifo = {
|
|
9497
|
+
pipe: new KernelPipe(),
|
|
9498
|
+
readers: 0,
|
|
9499
|
+
writers: 0,
|
|
9500
|
+
readOpens: 0,
|
|
9501
|
+
writeOpens: 0,
|
|
9502
|
+
waiters: []
|
|
9503
|
+
};
|
|
9504
|
+
this.fifos.set(key, fifo);
|
|
9505
|
+
}
|
|
9506
|
+
return fifo;
|
|
9507
|
+
}
|
|
9508
|
+
count(fifo, side, by) {
|
|
9509
|
+
fifo[side] += by;
|
|
9510
|
+
if (side === "readers") {
|
|
9511
|
+
if (by > 0) {
|
|
9512
|
+
fifo.readOpens += 1;
|
|
9513
|
+
fifo.pipe.openRead();
|
|
9514
|
+
} else fifo.pipe.closeRead();
|
|
9515
|
+
} else if (by > 0) {
|
|
9516
|
+
fifo.writeOpens += 1;
|
|
9517
|
+
fifo.pipe.openWrite();
|
|
9518
|
+
} else fifo.pipe.closeWrite();
|
|
9519
|
+
}
|
|
9520
|
+
notify(fifo) {
|
|
9521
|
+
const waiters = fifo.waiters;
|
|
9522
|
+
fifo.waiters = [];
|
|
9523
|
+
for (const wake of waiters) wake();
|
|
9524
|
+
}
|
|
9525
|
+
changed(fifo, signal) {
|
|
9526
|
+
if (signal.aborted) return Promise.reject(new KernelError("EINTR"));
|
|
9527
|
+
return new Promise((resolve2, reject) => {
|
|
9528
|
+
const onAbort = () => {
|
|
9529
|
+
fifo.waiters = fifo.waiters.filter((w) => w !== wake);
|
|
9530
|
+
reject(new KernelError("EINTR"));
|
|
9531
|
+
};
|
|
9532
|
+
const wake = () => {
|
|
9533
|
+
signal.removeEventListener("abort", onAbort);
|
|
9534
|
+
resolve2();
|
|
9535
|
+
};
|
|
9536
|
+
fifo.waiters.push(wake);
|
|
9537
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
9538
|
+
});
|
|
9539
|
+
}
|
|
9540
|
+
release(key, fifo, reads, writes) {
|
|
9541
|
+
if (reads) this.count(fifo, "readers", -1);
|
|
9542
|
+
if (writes) this.count(fifo, "writers", -1);
|
|
9543
|
+
this.notify(fifo);
|
|
9544
|
+
this.drop(key, fifo);
|
|
9545
|
+
}
|
|
9546
|
+
drop(key, fifo) {
|
|
9547
|
+
const idle = fifo.readers === 0 && fifo.writers === 0 && fifo.waiters.length === 0;
|
|
9548
|
+
if (idle && this.fifos.get(key) === fifo) this.fifos.delete(key);
|
|
9549
|
+
}
|
|
9550
|
+
end(key, path, fifo, reads, writes) {
|
|
9551
|
+
const { pipe } = fifo;
|
|
9552
|
+
let open = true;
|
|
9553
|
+
return new OpenFile({
|
|
9554
|
+
fifo: path,
|
|
9555
|
+
...reads ? {
|
|
9556
|
+
read: async (max, signal) => {
|
|
9557
|
+
try {
|
|
9558
|
+
return await pipe.read(max, signal);
|
|
9559
|
+
} catch (e) {
|
|
9560
|
+
throw errno(e);
|
|
9561
|
+
}
|
|
9562
|
+
}
|
|
9563
|
+
} : {},
|
|
9564
|
+
...writes ? {
|
|
9565
|
+
write: async (bytes, signal) => {
|
|
9566
|
+
try {
|
|
9567
|
+
return await pipe.write(bytes, signal);
|
|
9568
|
+
} catch (e) {
|
|
9569
|
+
throw errno(e);
|
|
9570
|
+
}
|
|
9571
|
+
}
|
|
9572
|
+
} : {},
|
|
9573
|
+
close: () => {
|
|
9574
|
+
if (!open) return;
|
|
9575
|
+
open = false;
|
|
9576
|
+
this.release(key, fifo, reads, writes);
|
|
9577
|
+
},
|
|
9578
|
+
poll: () => ({
|
|
9579
|
+
readable: reads && pipe.readReady,
|
|
9580
|
+
writable: writes && pipe.writeReady,
|
|
9581
|
+
hangup: reads ? pipe.writersGone : pipe.readersGone
|
|
9582
|
+
}),
|
|
9583
|
+
changed: (signal) => pipe.changed(signal)
|
|
9584
|
+
});
|
|
9585
|
+
}
|
|
9586
|
+
};
|
|
9587
|
+
|
|
9433
9588
|
// src/mount/protocol.ts
|
|
9434
9589
|
var DRIVER_PROTOCOL = [1, 2];
|
|
9435
9590
|
function driverVersionError(theirs) {
|
|
@@ -10290,6 +10445,7 @@ var MountFs = class _MountFs {
|
|
|
10290
10445
|
}
|
|
10291
10446
|
const { mount, rel: rel2 } = found;
|
|
10292
10447
|
this.writable(mount, real);
|
|
10448
|
+
if (owner?.fifo) throw errnoError("EPERM", `${real}: this mount has no FIFOs`);
|
|
10293
10449
|
const bytes = typeof content === "string" ? new TextEncoder().encode(content) : content;
|
|
10294
10450
|
if (mount.maxFile > 0 && bytes.length > mount.maxFile) {
|
|
10295
10451
|
throw errnoError(
|
|
@@ -10895,6 +11051,7 @@ var SYNC_FS_OPS = [
|
|
|
10895
11051
|
"statfs",
|
|
10896
11052
|
"hold",
|
|
10897
11053
|
"create",
|
|
11054
|
+
"mkfifo",
|
|
10898
11055
|
"kept",
|
|
10899
11056
|
"pread",
|
|
10900
11057
|
"pwrite",
|
|
@@ -10927,6 +11084,7 @@ function statJson(s) {
|
|
|
10927
11084
|
isFile: s.isFile,
|
|
10928
11085
|
isSymbolicLink: s.isSymbolicLink,
|
|
10929
11086
|
...s.isSocket ? { isSocket: true } : {},
|
|
11087
|
+
...s.isFifo ? { isFifo: true } : {},
|
|
10930
11088
|
size: s.size,
|
|
10931
11089
|
mode: s.mode,
|
|
10932
11090
|
mtimeMs: s.mtime.getTime(),
|
|
@@ -11076,6 +11234,12 @@ async function run(entry, path, req) {
|
|
|
11076
11234
|
case "symlink":
|
|
11077
11235
|
await fs.symlink(req.arg2 ?? "", path, ownerFor2(entry));
|
|
11078
11236
|
return done;
|
|
11237
|
+
case "mkfifo": {
|
|
11238
|
+
const owner = ownerFor2(entry, req.mode ?? 438) ?? { uid: 0, gid: 0 };
|
|
11239
|
+
await createExclusive(fs, path, { ...owner, fifo: true });
|
|
11240
|
+
entry.fresh?.(path);
|
|
11241
|
+
return done;
|
|
11242
|
+
}
|
|
11079
11243
|
case "create":
|
|
11080
11244
|
await createExclusive(fs, path, ownerFor2(entry, req.mode ?? 438));
|
|
11081
11245
|
if (req.opening) entry.created?.add(path);
|
|
@@ -11154,9 +11318,10 @@ async function guard(g, path, req, cwd) {
|
|
|
11154
11318
|
return { path: await walkSafe(g, path, false) };
|
|
11155
11319
|
}
|
|
11156
11320
|
case "create":
|
|
11321
|
+
case "mkfifo":
|
|
11157
11322
|
case "symlink":
|
|
11158
11323
|
await inParent(g, op, path);
|
|
11159
|
-
return { path: await walkSafe(g, path, op
|
|
11324
|
+
return { path: await walkSafe(g, path, op !== "symlink") };
|
|
11160
11325
|
case "unlink":
|
|
11161
11326
|
case "rmdir": {
|
|
11162
11327
|
await inParent(g, op, path, true);
|
|
@@ -11244,6 +11409,7 @@ async function accessOp(entry, path, req) {
|
|
|
11244
11409
|
var CHANGING = /* @__PURE__ */ new Set([
|
|
11245
11410
|
"mkdir",
|
|
11246
11411
|
"create",
|
|
11412
|
+
"mkfifo",
|
|
11247
11413
|
"symlink",
|
|
11248
11414
|
"unlink",
|
|
11249
11415
|
"rmdir",
|
|
@@ -11438,7 +11604,13 @@ async function guardAndResolve(entry, path, req) {
|
|
|
11438
11604
|
};
|
|
11439
11605
|
}
|
|
11440
11606
|
var REMOVALS = /* @__PURE__ */ new Set(["unlink", "rmdir", "rm"]);
|
|
11441
|
-
var CREATIONS = /* @__PURE__ */ new Set([
|
|
11607
|
+
var CREATIONS = /* @__PURE__ */ new Set([
|
|
11608
|
+
"write",
|
|
11609
|
+
"mkdir",
|
|
11610
|
+
"symlink",
|
|
11611
|
+
"create",
|
|
11612
|
+
"mkfifo"
|
|
11613
|
+
]);
|
|
11442
11614
|
var NAMING = /* @__PURE__ */ new Set(["link", "rename"]);
|
|
11443
11615
|
async function newDevName(entry, path, req) {
|
|
11444
11616
|
const named = NAMING.has(req.op);
|
|
@@ -13185,16 +13357,16 @@ var TOKEN3 = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
|
13185
13357
|
var SAFE_VALUE = /^[^\r\n\0]*$/;
|
|
13186
13358
|
var CLOSE_WAIT_MS3 = 5e3;
|
|
13187
13359
|
var MAX_UNREAD = 16 * 1024 * 1024;
|
|
13188
|
-
function
|
|
13360
|
+
function errno2(code, message3) {
|
|
13189
13361
|
return Object.assign(new Error(`${code}: ${message3}`), { code });
|
|
13190
13362
|
}
|
|
13191
13363
|
function requestHead(method, url, headers, extra, first = []) {
|
|
13192
|
-
if (!TOKEN3.test(method)) throw
|
|
13364
|
+
if (!TOKEN3.test(method)) throw errno2("EINVAL", `method ${method}`);
|
|
13193
13365
|
const lines2 = [`${method} ${url.pathname}${url.search} HTTP/1.1`, `host: ${url.host}`];
|
|
13194
13366
|
for (const [name2, value2] of first) lines2.push(`${name2}: ${value2}`);
|
|
13195
13367
|
for (const [name2, value2] of headers) {
|
|
13196
13368
|
if (OWN_HEADERS.has(name2.toLowerCase())) continue;
|
|
13197
|
-
if (!TOKEN3.test(name2) || !SAFE_VALUE.test(value2)) throw
|
|
13369
|
+
if (!TOKEN3.test(name2) || !SAFE_VALUE.test(value2)) throw errno2("EINVAL", `header ${name2}`);
|
|
13198
13370
|
lines2.push(`${name2}: ${value2}`);
|
|
13199
13371
|
}
|
|
13200
13372
|
for (const [name2, value2] of extra) lines2.push(`${name2}: ${value2}`);
|
|
@@ -13205,7 +13377,7 @@ function requestHead(method, url, headers, extra, first = []) {
|
|
|
13205
13377
|
function parseHead(bytes) {
|
|
13206
13378
|
const [statusLine = "", ...lines2] = latin1(bytes).split(/\r?\n/);
|
|
13207
13379
|
const match = /^HTTP\/1\.[01] (\d{3})(?: (.*))?$/.exec(statusLine);
|
|
13208
|
-
if (!match) throw
|
|
13380
|
+
if (!match) throw errno2("EPROTO", `not an HTTP/1.x response: ${statusLine.slice(0, 80)}`);
|
|
13209
13381
|
const headers = [];
|
|
13210
13382
|
for (const line of lines2) {
|
|
13211
13383
|
const colon = line.indexOf(":");
|
|
@@ -13220,9 +13392,9 @@ async function readHead(incoming, signal) {
|
|
|
13220
13392
|
raw = await incoming.head(MAX_HEAD2, signal);
|
|
13221
13393
|
} catch (err) {
|
|
13222
13394
|
if (err instanceof KernelError) throw err;
|
|
13223
|
-
throw
|
|
13395
|
+
throw errno2("EPROTO", "the response head is malformed or too large");
|
|
13224
13396
|
}
|
|
13225
|
-
if (!raw) throw
|
|
13397
|
+
if (!raw) throw errno2("ECONNRESET", "the connection closed before a response");
|
|
13226
13398
|
const head = parseHead(raw);
|
|
13227
13399
|
if (head.status < 100 || head.status >= 200 || head.status === 101) return head;
|
|
13228
13400
|
}
|
|
@@ -13231,20 +13403,20 @@ async function* chunked(incoming, signal) {
|
|
|
13231
13403
|
for (; ; ) {
|
|
13232
13404
|
const line = await incoming.line(4096, signal);
|
|
13233
13405
|
const size = /^([0-9A-Fa-f]{1,12})[ \t]*(;.*)?$/.exec(line);
|
|
13234
|
-
if (!size) throw
|
|
13406
|
+
if (!size) throw errno2("EPROTO", "a malformed chunk size");
|
|
13235
13407
|
const n = Number.parseInt(size[1], 16);
|
|
13236
13408
|
if (n === 0) {
|
|
13237
13409
|
while (await incoming.line(MAX_HEAD2, signal) !== "") ;
|
|
13238
13410
|
return;
|
|
13239
13411
|
}
|
|
13240
13412
|
yield await incoming.exactly(n, signal);
|
|
13241
|
-
if (await incoming.line(2, signal) !== "") throw
|
|
13413
|
+
if (await incoming.line(2, signal) !== "") throw errno2("EPROTO", "a malformed chunk");
|
|
13242
13414
|
}
|
|
13243
13415
|
}
|
|
13244
13416
|
async function* counted(incoming, length2, signal) {
|
|
13245
13417
|
for (let left = length2; left > 0; ) {
|
|
13246
13418
|
const data = await incoming.some(Math.min(left, 64 * 1024), signal);
|
|
13247
|
-
if (data.length === 0) throw
|
|
13419
|
+
if (data.length === 0) throw errno2("EPROTO", "the body ended early");
|
|
13248
13420
|
left -= data.length;
|
|
13249
13421
|
yield data;
|
|
13250
13422
|
}
|
|
@@ -13265,7 +13437,7 @@ function bodyOf(incoming, head, method, signal) {
|
|
|
13265
13437
|
if (lengths.length === 0) return untilClose(incoming, signal);
|
|
13266
13438
|
const length2 = lengths[0]?.trim() ?? "";
|
|
13267
13439
|
if (!/^\d{1,15}$/.test(length2) || lengths.some((l) => l.trim() !== length2)) {
|
|
13268
|
-
throw
|
|
13440
|
+
throw errno2("EPROTO", `a malformed Content-Length: ${lengths.join(", ")}`);
|
|
13269
13441
|
}
|
|
13270
13442
|
return counted(incoming, Number(length2), signal);
|
|
13271
13443
|
}
|
|
@@ -13283,7 +13455,7 @@ var KernelLoopback = class {
|
|
|
13283
13455
|
}
|
|
13284
13456
|
async connect(url, port, signal) {
|
|
13285
13457
|
if (url.protocol === "https:" || url.protocol === "wss:") {
|
|
13286
|
-
throw
|
|
13458
|
+
throw errno2("ENOTSUP", `TLS to the kernel's loopback is not supported: ${url.origin}`);
|
|
13287
13459
|
}
|
|
13288
13460
|
signal.throwIfAborted();
|
|
13289
13461
|
const socket = this.net.socket("inet");
|
|
@@ -13298,7 +13470,7 @@ var KernelLoopback = class {
|
|
|
13298
13470
|
} catch (err) {
|
|
13299
13471
|
socket.close();
|
|
13300
13472
|
const refused2 = err instanceof KernelError && err.code === "ECONNREFUSED";
|
|
13301
|
-
throw refused2 ?
|
|
13473
|
+
throw refused2 ? errno2("ECONNREFUSED", `nothing listens on the kernel's port ${port}`) : err;
|
|
13302
13474
|
}
|
|
13303
13475
|
signal.addEventListener("abort", () => socket.close(), { once: true });
|
|
13304
13476
|
return socket;
|
|
@@ -13344,7 +13516,7 @@ var KernelLoopback = class {
|
|
|
13344
13516
|
const incoming = new Incoming(socket);
|
|
13345
13517
|
const head = await readHead(incoming, req.signal);
|
|
13346
13518
|
if (head.status !== 101) {
|
|
13347
|
-
throw
|
|
13519
|
+
throw errno2(
|
|
13348
13520
|
"EPROTO",
|
|
13349
13521
|
`the server answered the upgrade with ${head.status}${head.statusText ? ` ${head.statusText}` : ""}`
|
|
13350
13522
|
);
|
|
@@ -13352,10 +13524,10 @@ var KernelLoopback = class {
|
|
|
13352
13524
|
const upgraded = fieldTokens(head.headers, "upgrade").includes("websocket") && fieldTokens(head.headers, "connection").includes("upgrade");
|
|
13353
13525
|
const accept2 = fieldValues(head.headers, "sec-websocket-accept")[0];
|
|
13354
13526
|
if (!upgraded || accept2 !== await acceptFor(key)) {
|
|
13355
|
-
throw
|
|
13527
|
+
throw errno2("EPROTO", "the server did not accept the WebSocket key");
|
|
13356
13528
|
}
|
|
13357
13529
|
if (fieldValues(head.headers, "sec-websocket-extensions").length > 0) {
|
|
13358
|
-
throw
|
|
13530
|
+
throw errno2("EPROTO", "the server offered an unsolicited extension");
|
|
13359
13531
|
}
|
|
13360
13532
|
const protocol = fieldValues(head.headers, "sec-websocket-protocol")[0] ?? "";
|
|
13361
13533
|
return new LoopbackWebSocket(socket, incoming, protocol);
|
|
@@ -13373,7 +13545,7 @@ async function* closing(chunks, socket) {
|
|
|
13373
13545
|
yield* chunks;
|
|
13374
13546
|
} catch (err) {
|
|
13375
13547
|
if (typeof err?.code === "string") throw err;
|
|
13376
|
-
throw
|
|
13548
|
+
throw errno2("EPROTO", err instanceof Error ? err.message : String(err));
|
|
13377
13549
|
} finally {
|
|
13378
13550
|
socket.close();
|
|
13379
13551
|
}
|
|
@@ -13502,7 +13674,7 @@ var LoopbackWebSocket = class {
|
|
|
13502
13674
|
this.write(clientFrame(OP_CLOSE, payload));
|
|
13503
13675
|
}
|
|
13504
13676
|
send(data) {
|
|
13505
|
-
if (this.sentClose) throw
|
|
13677
|
+
if (this.sentClose) throw errno2("EPIPE", "the websocket is closing");
|
|
13506
13678
|
const text = typeof data === "string";
|
|
13507
13679
|
const payload = text ? new TextEncoder().encode(data) : data;
|
|
13508
13680
|
this.write(clientFrame(text ? OP_TEXT : OP_BINARY, payload));
|
|
@@ -14242,8 +14414,8 @@ function errnoOf(e) {
|
|
|
14242
14414
|
const code = e?.code;
|
|
14243
14415
|
return typeof code === "string" && ERRNO.test(code) ? code : "ECONNREFUSED";
|
|
14244
14416
|
}
|
|
14245
|
-
function fail(
|
|
14246
|
-
return { ok: false, errno:
|
|
14417
|
+
function fail(errno3, text) {
|
|
14418
|
+
return { ok: false, errno: errno3, message: text };
|
|
14247
14419
|
}
|
|
14248
14420
|
var WsHandles = class {
|
|
14249
14421
|
transport;
|
|
@@ -14517,8 +14689,8 @@ var HttpHandles = class {
|
|
|
14517
14689
|
const status = e.status;
|
|
14518
14690
|
if (text === NO_TRANSPORT || typeof status !== "number" || status === 502) {
|
|
14519
14691
|
const code = codeOf2(e);
|
|
14520
|
-
const
|
|
14521
|
-
return { ok: false, errno:
|
|
14692
|
+
const errno3 = text === NO_TRANSPORT ? "ENETUNREACH" : code !== "EIO" ? code : "ECONNREFUSED";
|
|
14693
|
+
return { ok: false, errno: errno3, message: text };
|
|
14522
14694
|
}
|
|
14523
14695
|
entry.body = once(new TextEncoder().encode(text))[Symbol.asyncIterator]();
|
|
14524
14696
|
return this.headOf(handle, req.url, {
|
|
@@ -15723,7 +15895,7 @@ var UNREACHABLE = ["EACCES", "ENETUNREACH", "EHOSTUNREACH"];
|
|
|
15723
15895
|
function sendError(e) {
|
|
15724
15896
|
if (e instanceof KernelError) return e;
|
|
15725
15897
|
const code = e?.code;
|
|
15726
|
-
return new KernelError(SEND_ERRORS.find((
|
|
15898
|
+
return new KernelError(SEND_ERRORS.find((errno3) => errno3 === code) ?? "EHOSTUNREACH");
|
|
15727
15899
|
}
|
|
15728
15900
|
function sameAddr(a, b) {
|
|
15729
15901
|
return a.port === b.port && canonicalHost(a.host) === canonicalHost(b.host);
|
|
@@ -15852,7 +16024,7 @@ var KernelDgram = class {
|
|
|
15852
16024
|
}
|
|
15853
16025
|
unreachable(error, from) {
|
|
15854
16026
|
if (!this.peer || !sameAddr(this.peer, from)) return;
|
|
15855
|
-
this.pending = UNREACHABLE.find((
|
|
16027
|
+
this.pending = UNREACHABLE.find((errno3) => errno3 === error) ?? "EHOSTUNREACH";
|
|
15856
16028
|
this.changes.wake();
|
|
15857
16029
|
}
|
|
15858
16030
|
deliver(datagram2) {
|
|
@@ -17170,6 +17342,7 @@ var SYSCALL_OPS = /* @__PURE__ */ new Set([
|
|
|
17170
17342
|
"sig-mask",
|
|
17171
17343
|
"sig-inherited",
|
|
17172
17344
|
"sig-waiting",
|
|
17345
|
+
"sig-info",
|
|
17173
17346
|
"sig-pause",
|
|
17174
17347
|
...SOCKET_OPS,
|
|
17175
17348
|
...EPOLL_OPS,
|
|
@@ -17183,6 +17356,7 @@ function isWasmSyscall(req) {
|
|
|
17183
17356
|
return typeof op === "string" && SYSCALL_OPS.has(op);
|
|
17184
17357
|
}
|
|
17185
17358
|
var MAX_READ = 1024 * 1024;
|
|
17359
|
+
var O_NONBLOCK = 2048;
|
|
17186
17360
|
var WRITE_ACCESS = 3;
|
|
17187
17361
|
var KEYBOARD = /* @__PURE__ */ new Set([SIG.INT, SIG.QUIT, SIG.TSTP]);
|
|
17188
17362
|
var DEFAULT_UMASK2 = 18;
|
|
@@ -17251,7 +17425,7 @@ var WasmProcess = class {
|
|
|
17251
17425
|
this.children = new ChildTable(fds, options.spawner, options.forker);
|
|
17252
17426
|
this.nodes = options.nodes ?? new VfsNodes(options.fs);
|
|
17253
17427
|
if (!options.nodes) options.openFiles?.add(this.nodes);
|
|
17254
|
-
this.children.onChildState = () => this.signal(SIG.CHLD);
|
|
17428
|
+
this.children.onChildState = (child) => this.signal(SIG.CHLD, child && this.childInfo(child));
|
|
17255
17429
|
this.children.autoReap = () => this.reapsChildren();
|
|
17256
17430
|
this.seedDl(options.dl);
|
|
17257
17431
|
this.children.onReap = (pid2) => {
|
|
@@ -17268,10 +17442,43 @@ var WasmProcess = class {
|
|
|
17268
17442
|
inheritable(fork = false) {
|
|
17269
17443
|
return ((fork ? 0 : this.ignored) | this.inherited) & ~this.caught;
|
|
17270
17444
|
}
|
|
17271
|
-
|
|
17445
|
+
sigInfos = /* @__PURE__ */ new Map();
|
|
17446
|
+
signal(sig, info) {
|
|
17447
|
+
const pending = ((this.options.pendingBits?.() ?? 0) & sigbit(sig)) !== 0;
|
|
17448
|
+
const outcome = this.signalOutcome(sig, info);
|
|
17449
|
+
if (outcome === "deliver" && !(pending && this.sigInfos.has(`0:${sig}`))) {
|
|
17450
|
+
this.sigInfos.set(`0:${sig}`, info ?? KERNEL_SIGINFO);
|
|
17451
|
+
}
|
|
17452
|
+
return outcome;
|
|
17453
|
+
}
|
|
17454
|
+
async threadKill(tid, sig) {
|
|
17455
|
+
const info = await this.threadSender(sig);
|
|
17456
|
+
if (this.options.threadKill?.(tid, sig)) this.sigInfos.set(`${tid}:${sig}`, info);
|
|
17457
|
+
else this.options.raise?.(sig, info);
|
|
17458
|
+
}
|
|
17459
|
+
async threadSender(sig) {
|
|
17460
|
+
const pid = (await this.options.identity?.())?.pid ?? this.pid;
|
|
17461
|
+
const code = sig === SIG.PIPE ? SI.USER : SI.TKILL;
|
|
17462
|
+
return { code, pid, uid: this.cred.ruid, status: 0 };
|
|
17463
|
+
}
|
|
17464
|
+
childInfo(child) {
|
|
17465
|
+
const code = child.state === "stopped" ? CLD.STOPPED : child.state === "continued" ? CLD.CONTINUED : child.termsig ? CLD.KILLED : CLD.EXITED;
|
|
17466
|
+
return { code, pid: child.pid, uid: child.uid ?? this.cred.ruid, status: child.status };
|
|
17467
|
+
}
|
|
17468
|
+
takeSigInfo(sig, tid) {
|
|
17469
|
+
for (const key of [`${tid}:${sig}`, `0:${sig}`]) {
|
|
17470
|
+
const info = this.sigInfos.get(key);
|
|
17471
|
+
if (info) {
|
|
17472
|
+
this.sigInfos.delete(key);
|
|
17473
|
+
return info;
|
|
17474
|
+
}
|
|
17475
|
+
}
|
|
17476
|
+
return null;
|
|
17477
|
+
}
|
|
17478
|
+
signalOutcome(sig, info) {
|
|
17272
17479
|
if (this.execChild !== void 0) {
|
|
17273
17480
|
if (sig === SIG.CONT) this.cont();
|
|
17274
|
-
void Promise.resolve(this.options.kill?.(this.execChild, sig)).catch(() => void 0);
|
|
17481
|
+
void Promise.resolve(this.options.kill?.(this.execChild, sig, info)).catch(() => void 0);
|
|
17275
17482
|
if (sig !== SIG.KILL) return "forward";
|
|
17276
17483
|
if (!this.options.writesBack?.(this.execChild)) return "terminate";
|
|
17277
17484
|
this.wake?.();
|
|
@@ -17647,7 +17854,7 @@ var WasmProcess = class {
|
|
|
17647
17854
|
this.options.hasPending?.() ? AbortSignal.abort() : this.cancelSignal(cancelled)
|
|
17648
17855
|
);
|
|
17649
17856
|
}
|
|
17650
|
-
async openVfs(req) {
|
|
17857
|
+
async openVfs(req, cancelled) {
|
|
17651
17858
|
if (inProc(req.path)) return this.openProc(req, req.path);
|
|
17652
17859
|
const device = req.orphan ? void 0 : deviceAt(req.path);
|
|
17653
17860
|
if (device) return this.openDevice(req, device);
|
|
@@ -17658,6 +17865,10 @@ var WasmProcess = class {
|
|
|
17658
17865
|
await refuseReadonly(this.options.fs, req.path, req.flags, req);
|
|
17659
17866
|
if (this.writesAt(req)) await this.options.fs.mayChange?.(req.path, !req.exclusive);
|
|
17660
17867
|
await this.mayOpen(req);
|
|
17868
|
+
if (req.fifo && !req.exclusive) {
|
|
17869
|
+
const opened2 = await this.openFifo(req, cancelled);
|
|
17870
|
+
if (opened2 !== void 0) return opened2;
|
|
17871
|
+
}
|
|
17661
17872
|
const marked = await this.markedPath(req);
|
|
17662
17873
|
await this.sourceOpen(marked === void 0 ? req : { ...req, path: marked });
|
|
17663
17874
|
const fs = marked === void 0 ? this.options.fs : this.options.noLinks;
|
|
@@ -17699,6 +17910,19 @@ var WasmProcess = class {
|
|
|
17699
17910
|
}
|
|
17700
17911
|
return fd;
|
|
17701
17912
|
}
|
|
17913
|
+
async openFifo(req, cancelled) {
|
|
17914
|
+
const fifos = this.options.fifos;
|
|
17915
|
+
const path = await this.nodes.targetKey(req.path);
|
|
17916
|
+
const st = await this.heldFs().stat(path);
|
|
17917
|
+
if (!st.isFifo) return void 0;
|
|
17918
|
+
if (!fifos) throw new KernelError("ENXIO");
|
|
17919
|
+
const access2 = openAccess(req.flags);
|
|
17920
|
+
const nonblock = (req.flags & O_NONBLOCK) !== 0;
|
|
17921
|
+
const blocks = !nonblock && access2 !== "both";
|
|
17922
|
+
const signal = blocks ? this.blockingSignal(cancelled) : cancelled;
|
|
17923
|
+
const end = await fifos.open(`${st.dev ?? 0}:${st.ino}`, path, access2, nonblock, signal);
|
|
17924
|
+
return this.fds.install(end, 3);
|
|
17925
|
+
}
|
|
17702
17926
|
openDevice(req, device) {
|
|
17703
17927
|
if (req.exclusive) throw Object.assign(new Error(req.path), { code: "EEXIST" });
|
|
17704
17928
|
const access2 = req.flags & WRITE_ACCESS;
|
|
@@ -17898,7 +18122,7 @@ var WasmProcess = class {
|
|
|
17898
18122
|
case "fd-poll":
|
|
17899
18123
|
return { ok: true, kind: "json", json: pollFile(this.fds.get(req.fd).file) };
|
|
17900
18124
|
case "fd-open-vfs":
|
|
17901
|
-
return { ok: true, kind: "json", json: await this.openVfs(req) };
|
|
18125
|
+
return { ok: true, kind: "json", json: await this.openVfs(req, cancelled) };
|
|
17902
18126
|
case "fd-info":
|
|
17903
18127
|
return { ok: true, kind: "json", json: this.fdInfo(req.fd) };
|
|
17904
18128
|
case "fd-list":
|
|
@@ -18332,8 +18556,10 @@ var WasmProcess = class {
|
|
|
18332
18556
|
case "sig-pause":
|
|
18333
18557
|
return this.pause(cancelled);
|
|
18334
18558
|
case "thread-kill":
|
|
18335
|
-
|
|
18559
|
+
await this.threadKill(req.tid, req.sig);
|
|
18336
18560
|
return { ok: true, kind: "void" };
|
|
18561
|
+
case "sig-info":
|
|
18562
|
+
return { ok: true, kind: "json", json: this.takeSigInfo(req.sig, req.tid ?? 0) };
|
|
18337
18563
|
case "proc-captured":
|
|
18338
18564
|
return { ok: true, kind: "bytes", bytes: this.children.captured(req.pid, req.slot) };
|
|
18339
18565
|
case "proc-sudo":
|
|
@@ -18556,7 +18782,8 @@ function inheritedFds(fds) {
|
|
|
18556
18782
|
...kind === "device" && meta && "device" in meta ? { device: meta } : {},
|
|
18557
18783
|
...flags2 !== void 0 ? { flags: flags2 } : {},
|
|
18558
18784
|
...fds.closesOnExec(fd) ? { cloexec: true } : {},
|
|
18559
|
-
...kind === "stream" ? { desc: descId(open) } : {}
|
|
18785
|
+
...kind === "stream" ? { desc: descId(open) } : {},
|
|
18786
|
+
...open.file.fifo ? { fifo: open.file.fifo } : {}
|
|
18560
18787
|
};
|
|
18561
18788
|
});
|
|
18562
18789
|
}
|
|
@@ -18762,6 +18989,7 @@ function processOptions(opts, header3, hooks, created3) {
|
|
|
18762
18989
|
net: opts.net,
|
|
18763
18990
|
http: opts.http,
|
|
18764
18991
|
locks: opts.locks,
|
|
18992
|
+
fifos: opts.fifos,
|
|
18765
18993
|
...opts.sems ? { sems: opts.sems } : {},
|
|
18766
18994
|
onReap: opts.onReap,
|
|
18767
18995
|
resolver: opts.resolver,
|
|
@@ -18812,7 +19040,7 @@ function spawnWasmProcess(opts) {
|
|
|
18812
19040
|
opts,
|
|
18813
19041
|
header3,
|
|
18814
19042
|
{
|
|
18815
|
-
raise: (sig) => signal(sig),
|
|
19043
|
+
raise: (sig, info) => signal(sig, info),
|
|
18816
19044
|
threadKill: (tid, sig) => killThread(threadSignals.get(tid), process.signalMasks().caught, sig),
|
|
18817
19045
|
unblockedThread: (sig) => unblockedThread(threadSignals, sig),
|
|
18818
19046
|
...opts.program.abi === "js" ? {
|
|
@@ -18934,8 +19162,9 @@ function spawnWasmProcess(opts) {
|
|
|
18934
19162
|
if (opts.program.abi !== "wasi" || done4) finish(code, sig);
|
|
18935
19163
|
else dying.start(code, sig, header3, process, () => finish(code, sig));
|
|
18936
19164
|
};
|
|
18937
|
-
const signal = (sig) => {
|
|
18938
|
-
if (process.signal(sig) === "terminate")
|
|
19165
|
+
const signal = (sig, info) => {
|
|
19166
|
+
if (process.signal(sig, info) === "terminate")
|
|
19167
|
+
terminate(sig === SIG.KILL ? 137 : 128 + sig, sig);
|
|
18939
19168
|
};
|
|
18940
19169
|
const kill = (code = 137) => finish(code, code > 128 && code < 160 ? code - 128 : void 0);
|
|
18941
19170
|
return {
|
|
@@ -19105,14 +19334,14 @@ var JobTable = class {
|
|
|
19105
19334
|
this.foreground.set(tty, member.pgid);
|
|
19106
19335
|
return true;
|
|
19107
19336
|
}
|
|
19108
|
-
killGroup(pgid, sig, may = () => true) {
|
|
19337
|
+
killGroup(pgid, sig, may = () => true, info) {
|
|
19109
19338
|
const group = [...this.members.values()].filter((m) => m.pgid === pgid);
|
|
19110
19339
|
const targets = group.filter((m) => may(m.pid));
|
|
19111
19340
|
if (targets.length === 0 && group.length > 0) throw new KernelError("EPERM");
|
|
19112
19341
|
const pids = new Set(targets.map((m) => m.pid));
|
|
19113
19342
|
if (sig !== 0) {
|
|
19114
19343
|
for (const m of targets)
|
|
19115
|
-
if (m.execParent === void 0 || !pids.has(m.execParent)) m.signal(sig);
|
|
19344
|
+
if (m.execParent === void 0 || !pids.has(m.execParent)) m.signal(sig, info);
|
|
19116
19345
|
}
|
|
19117
19346
|
return targets.length > 0;
|
|
19118
19347
|
}
|
|
@@ -20699,9 +20928,9 @@ var HostfsClient = class {
|
|
|
20699
20928
|
throw fsError2("ESTALE", "the folder was granted again, so its open files are gone");
|
|
20700
20929
|
return this.send(path, init, false, true);
|
|
20701
20930
|
}
|
|
20702
|
-
const
|
|
20931
|
+
const errno3 = response.headers.get("X-Hostfs-Errno") ?? "EIO";
|
|
20703
20932
|
const body = await response.json().catch(() => ({}));
|
|
20704
|
-
throw fsError2(
|
|
20933
|
+
throw fsError2(errno3, typeof body.message === "string" ? body.message : errno3);
|
|
20705
20934
|
}
|
|
20706
20935
|
async call(op, body = {}, handle = false) {
|
|
20707
20936
|
const response = await this.send(
|
|
@@ -21786,8 +22015,8 @@ var RULE = new RegExp(
|
|
|
21786
22015
|
var TERM = /^[A-Za-z0-9._+-]+$/;
|
|
21787
22016
|
var PLAIN = /^[A-Za-z0-9_@%+=:,./-]+$/;
|
|
21788
22017
|
var USAGE = "usage: sudo [-n] [-u user] [--] command [args...]\n sudo -l";
|
|
21789
|
-
function failed2(
|
|
21790
|
-
return { error, errno:
|
|
22018
|
+
function failed2(errno3, error) {
|
|
22019
|
+
return { error, errno: errno3 };
|
|
21791
22020
|
}
|
|
21792
22021
|
function unescaped(double) {
|
|
21793
22022
|
return double.replace(/\\(["\\$`])/g, "$1");
|
|
@@ -22383,7 +22612,8 @@ function childHandle(handle) {
|
|
|
22383
22612
|
pid: handle.pid,
|
|
22384
22613
|
exited: handle.exited,
|
|
22385
22614
|
termsig: handle.termsig,
|
|
22386
|
-
onState: (listener) => handle.onState(listener)
|
|
22615
|
+
onState: (listener) => handle.onState(listener),
|
|
22616
|
+
uid: () => handle.cred?.().ruid
|
|
22387
22617
|
};
|
|
22388
22618
|
}
|
|
22389
22619
|
function concat7(chunks) {
|
|
@@ -22447,6 +22677,7 @@ var Launcher = class {
|
|
|
22447
22677
|
sudoer;
|
|
22448
22678
|
jobs = new JobTable();
|
|
22449
22679
|
locks = new LockTable();
|
|
22680
|
+
fifos = new FifoTable();
|
|
22450
22681
|
sems = new SemTable();
|
|
22451
22682
|
settling = new SettlingChildren((pid) => this.jobs.pgidOf(pid));
|
|
22452
22683
|
ptys = new PtyTable(
|
|
@@ -23421,7 +23652,7 @@ var Launcher = class {
|
|
|
23421
23652
|
onError: req.report,
|
|
23422
23653
|
spawner: this.spawner(pid, req.report),
|
|
23423
23654
|
forker: this.forker(pid, req),
|
|
23424
|
-
kill: (target, sig) => this.kill(target, sig, this.credOf(pid), pid),
|
|
23655
|
+
kill: (target, sig, info) => this.kill(target, sig, this.credOf(pid), pid, info),
|
|
23425
23656
|
writesBack: (target) => this.processes.get(target)?.writesBack() === true,
|
|
23426
23657
|
processes: () => ({
|
|
23427
23658
|
boot: this.boot,
|
|
@@ -23444,6 +23675,7 @@ var Launcher = class {
|
|
|
23444
23675
|
net: this.net,
|
|
23445
23676
|
http: new HttpHandles(this.transport, pid, this.loopbackFor(pid)),
|
|
23446
23677
|
locks: this.locks,
|
|
23678
|
+
fifos: this.fifos,
|
|
23447
23679
|
sems: this.sems,
|
|
23448
23680
|
resolver: this.resolver,
|
|
23449
23681
|
onReap: (child) => this.reaped(child, pid),
|
|
@@ -23456,7 +23688,7 @@ var Launcher = class {
|
|
|
23456
23688
|
this.creds.set(pid, () => handle.cred?.() ?? copyCred(cred));
|
|
23457
23689
|
this.marks(pid, req);
|
|
23458
23690
|
if (req.ppid !== void 0 && this.controlsJobs(req.ppid)) this.settling.started(pid, req.ppid);
|
|
23459
|
-
this.jobs.add(pid, req.ppid, (sig) => handle.signal(sig), terminal);
|
|
23691
|
+
this.jobs.add(pid, req.ppid, (sig, info) => handle.signal(sig, info), terminal);
|
|
23460
23692
|
if (req.exec && req.ppid !== void 0) this.jobs.exec(req.ppid, pid, true);
|
|
23461
23693
|
if (req.pgid !== void 0) this.jobs.join(pid, req.pgid);
|
|
23462
23694
|
if (req.group === "lead") this.jobs.lead(pid);
|
|
@@ -23837,21 +24069,26 @@ var Launcher = class {
|
|
|
23837
24069
|
ignoredBy(pid, fork = false) {
|
|
23838
24070
|
return this.processes.get(pid)?.ignoredSignals(fork) ?? 0;
|
|
23839
24071
|
}
|
|
23840
|
-
kill(pid, sig, sender, from) {
|
|
24072
|
+
kill(pid, sig, sender, from, forwarded) {
|
|
24073
|
+
const info = forwarded ?? this.senderInfo(sender, from);
|
|
23841
24074
|
const session = from === void 0 ? void 0 : this.jobs.sidOf(from);
|
|
23842
24075
|
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;
|
|
23843
24076
|
if (pid === -1) {
|
|
23844
24077
|
const sender2 = from === void 0 ? void 0 : this.imageOf(from);
|
|
23845
|
-
return this.killAll(sig, (member) => this.imageOf(member) !== sender2, may);
|
|
24078
|
+
return this.killAll(sig, (member) => this.imageOf(member) !== sender2, may, info);
|
|
23846
24079
|
}
|
|
23847
|
-
if (pid < 0) return this.jobs.killGroup(-pid, sig, (member) => may(this.imageOf(member)));
|
|
24080
|
+
if (pid < 0) return this.jobs.killGroup(-pid, sig, (member) => may(this.imageOf(member)), info);
|
|
23848
24081
|
const handle = this.processes.get(pid);
|
|
23849
24082
|
if (!handle) return false;
|
|
23850
24083
|
if (!may(this.imageOf(pid))) throw fsError("EPERM", `pid ${pid}`);
|
|
23851
|
-
if (sig !== 0) handle.signal(sig);
|
|
24084
|
+
if (sig !== 0) handle.signal(sig, info);
|
|
23852
24085
|
return true;
|
|
23853
24086
|
}
|
|
23854
|
-
|
|
24087
|
+
senderInfo(sender, from) {
|
|
24088
|
+
if (from === void 0) return void 0;
|
|
24089
|
+
return { code: SI.USER, pid: this.jobs.shown(from), uid: sender?.ruid ?? 0, status: 0 };
|
|
24090
|
+
}
|
|
24091
|
+
killAll(sig, other, may, info) {
|
|
23855
24092
|
const candidates = [...this.processes].filter(([pid]) => pid !== 1 && other(pid));
|
|
23856
24093
|
const targets = candidates.filter(([pid]) => may(this.imageOf(pid)));
|
|
23857
24094
|
if (targets.length === 0 && candidates.length > 0) throw fsError("EPERM", "kill -1");
|
|
@@ -23859,7 +24096,7 @@ var Launcher = class {
|
|
|
23859
24096
|
const parents = new Map(this.jobs.list().map((m) => [m.pid, m.execParent]));
|
|
23860
24097
|
for (const [pid, handle] of targets) {
|
|
23861
24098
|
const parent = parents.get(pid);
|
|
23862
|
-
if (sig !== 0 && (parent === void 0 || !pids.has(parent))) handle.signal(sig);
|
|
24099
|
+
if (sig !== 0 && (parent === void 0 || !pids.has(parent))) handle.signal(sig, info);
|
|
23863
24100
|
}
|
|
23864
24101
|
return targets.length > 0;
|
|
23865
24102
|
}
|