@ai-ecoverse/slicc-kernel 1.114.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 +18 -0
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +220 -42
- package/dist/kernel-worker.js.map +4 -4
- package/dist/meta.js.map +2 -2
- package/dist/node-process-worker.js +90 -13
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +220 -42
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +93 -16
- 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/fd-table.d.ts +1 -0
- package/dist/types/kernel/fifo.d.ts +13 -0
- package/dist/types/kernel/host.d.ts +2 -0
- package/dist/types/kernel/process.d.ts +4 -0
- package/dist/types/kernel/protocol.d.ts +2 -0
- package/dist/types/launcher.d.ts +1 -0
- 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/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 +2 -1
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) {
|
|
@@ -6221,7 +6227,7 @@ function satisfies(version, range2) {
|
|
|
6221
6227
|
}
|
|
6222
6228
|
|
|
6223
6229
|
// src/version.ts
|
|
6224
|
-
var KERNEL_VERSION = true ? "1.
|
|
6230
|
+
var KERNEL_VERSION = true ? "1.115.0" : "0.0.0-dev";
|
|
6225
6231
|
var OS_RELEASE = "6.0.0-slicc";
|
|
6226
6232
|
function procVersion() {
|
|
6227
6233
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -9446,6 +9452,139 @@ var TicketBook = class {
|
|
|
9446
9452
|
}
|
|
9447
9453
|
};
|
|
9448
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
|
+
|
|
9449
9588
|
// src/mount/protocol.ts
|
|
9450
9589
|
var DRIVER_PROTOCOL = [1, 2];
|
|
9451
9590
|
function driverVersionError(theirs) {
|
|
@@ -10306,6 +10445,7 @@ var MountFs = class _MountFs {
|
|
|
10306
10445
|
}
|
|
10307
10446
|
const { mount, rel: rel2 } = found;
|
|
10308
10447
|
this.writable(mount, real);
|
|
10448
|
+
if (owner?.fifo) throw errnoError("EPERM", `${real}: this mount has no FIFOs`);
|
|
10309
10449
|
const bytes = typeof content === "string" ? new TextEncoder().encode(content) : content;
|
|
10310
10450
|
if (mount.maxFile > 0 && bytes.length > mount.maxFile) {
|
|
10311
10451
|
throw errnoError(
|
|
@@ -10911,6 +11051,7 @@ var SYNC_FS_OPS = [
|
|
|
10911
11051
|
"statfs",
|
|
10912
11052
|
"hold",
|
|
10913
11053
|
"create",
|
|
11054
|
+
"mkfifo",
|
|
10914
11055
|
"kept",
|
|
10915
11056
|
"pread",
|
|
10916
11057
|
"pwrite",
|
|
@@ -10943,6 +11084,7 @@ function statJson(s) {
|
|
|
10943
11084
|
isFile: s.isFile,
|
|
10944
11085
|
isSymbolicLink: s.isSymbolicLink,
|
|
10945
11086
|
...s.isSocket ? { isSocket: true } : {},
|
|
11087
|
+
...s.isFifo ? { isFifo: true } : {},
|
|
10946
11088
|
size: s.size,
|
|
10947
11089
|
mode: s.mode,
|
|
10948
11090
|
mtimeMs: s.mtime.getTime(),
|
|
@@ -11092,6 +11234,12 @@ async function run(entry, path, req) {
|
|
|
11092
11234
|
case "symlink":
|
|
11093
11235
|
await fs.symlink(req.arg2 ?? "", path, ownerFor2(entry));
|
|
11094
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
|
+
}
|
|
11095
11243
|
case "create":
|
|
11096
11244
|
await createExclusive(fs, path, ownerFor2(entry, req.mode ?? 438));
|
|
11097
11245
|
if (req.opening) entry.created?.add(path);
|
|
@@ -11170,9 +11318,10 @@ async function guard(g, path, req, cwd) {
|
|
|
11170
11318
|
return { path: await walkSafe(g, path, false) };
|
|
11171
11319
|
}
|
|
11172
11320
|
case "create":
|
|
11321
|
+
case "mkfifo":
|
|
11173
11322
|
case "symlink":
|
|
11174
11323
|
await inParent(g, op, path);
|
|
11175
|
-
return { path: await walkSafe(g, path, op
|
|
11324
|
+
return { path: await walkSafe(g, path, op !== "symlink") };
|
|
11176
11325
|
case "unlink":
|
|
11177
11326
|
case "rmdir": {
|
|
11178
11327
|
await inParent(g, op, path, true);
|
|
@@ -11260,6 +11409,7 @@ async function accessOp(entry, path, req) {
|
|
|
11260
11409
|
var CHANGING = /* @__PURE__ */ new Set([
|
|
11261
11410
|
"mkdir",
|
|
11262
11411
|
"create",
|
|
11412
|
+
"mkfifo",
|
|
11263
11413
|
"symlink",
|
|
11264
11414
|
"unlink",
|
|
11265
11415
|
"rmdir",
|
|
@@ -11454,7 +11604,13 @@ async function guardAndResolve(entry, path, req) {
|
|
|
11454
11604
|
};
|
|
11455
11605
|
}
|
|
11456
11606
|
var REMOVALS = /* @__PURE__ */ new Set(["unlink", "rmdir", "rm"]);
|
|
11457
|
-
var CREATIONS = /* @__PURE__ */ new Set([
|
|
11607
|
+
var CREATIONS = /* @__PURE__ */ new Set([
|
|
11608
|
+
"write",
|
|
11609
|
+
"mkdir",
|
|
11610
|
+
"symlink",
|
|
11611
|
+
"create",
|
|
11612
|
+
"mkfifo"
|
|
11613
|
+
]);
|
|
11458
11614
|
var NAMING = /* @__PURE__ */ new Set(["link", "rename"]);
|
|
11459
11615
|
async function newDevName(entry, path, req) {
|
|
11460
11616
|
const named = NAMING.has(req.op);
|
|
@@ -13201,16 +13357,16 @@ var TOKEN3 = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
|
13201
13357
|
var SAFE_VALUE = /^[^\r\n\0]*$/;
|
|
13202
13358
|
var CLOSE_WAIT_MS3 = 5e3;
|
|
13203
13359
|
var MAX_UNREAD = 16 * 1024 * 1024;
|
|
13204
|
-
function
|
|
13360
|
+
function errno2(code, message3) {
|
|
13205
13361
|
return Object.assign(new Error(`${code}: ${message3}`), { code });
|
|
13206
13362
|
}
|
|
13207
13363
|
function requestHead(method, url, headers, extra, first = []) {
|
|
13208
|
-
if (!TOKEN3.test(method)) throw
|
|
13364
|
+
if (!TOKEN3.test(method)) throw errno2("EINVAL", `method ${method}`);
|
|
13209
13365
|
const lines2 = [`${method} ${url.pathname}${url.search} HTTP/1.1`, `host: ${url.host}`];
|
|
13210
13366
|
for (const [name2, value2] of first) lines2.push(`${name2}: ${value2}`);
|
|
13211
13367
|
for (const [name2, value2] of headers) {
|
|
13212
13368
|
if (OWN_HEADERS.has(name2.toLowerCase())) continue;
|
|
13213
|
-
if (!TOKEN3.test(name2) || !SAFE_VALUE.test(value2)) throw
|
|
13369
|
+
if (!TOKEN3.test(name2) || !SAFE_VALUE.test(value2)) throw errno2("EINVAL", `header ${name2}`);
|
|
13214
13370
|
lines2.push(`${name2}: ${value2}`);
|
|
13215
13371
|
}
|
|
13216
13372
|
for (const [name2, value2] of extra) lines2.push(`${name2}: ${value2}`);
|
|
@@ -13221,7 +13377,7 @@ function requestHead(method, url, headers, extra, first = []) {
|
|
|
13221
13377
|
function parseHead(bytes) {
|
|
13222
13378
|
const [statusLine = "", ...lines2] = latin1(bytes).split(/\r?\n/);
|
|
13223
13379
|
const match = /^HTTP\/1\.[01] (\d{3})(?: (.*))?$/.exec(statusLine);
|
|
13224
|
-
if (!match) throw
|
|
13380
|
+
if (!match) throw errno2("EPROTO", `not an HTTP/1.x response: ${statusLine.slice(0, 80)}`);
|
|
13225
13381
|
const headers = [];
|
|
13226
13382
|
for (const line of lines2) {
|
|
13227
13383
|
const colon = line.indexOf(":");
|
|
@@ -13236,9 +13392,9 @@ async function readHead(incoming, signal) {
|
|
|
13236
13392
|
raw = await incoming.head(MAX_HEAD2, signal);
|
|
13237
13393
|
} catch (err) {
|
|
13238
13394
|
if (err instanceof KernelError) throw err;
|
|
13239
|
-
throw
|
|
13395
|
+
throw errno2("EPROTO", "the response head is malformed or too large");
|
|
13240
13396
|
}
|
|
13241
|
-
if (!raw) throw
|
|
13397
|
+
if (!raw) throw errno2("ECONNRESET", "the connection closed before a response");
|
|
13242
13398
|
const head = parseHead(raw);
|
|
13243
13399
|
if (head.status < 100 || head.status >= 200 || head.status === 101) return head;
|
|
13244
13400
|
}
|
|
@@ -13247,20 +13403,20 @@ async function* chunked(incoming, signal) {
|
|
|
13247
13403
|
for (; ; ) {
|
|
13248
13404
|
const line = await incoming.line(4096, signal);
|
|
13249
13405
|
const size = /^([0-9A-Fa-f]{1,12})[ \t]*(;.*)?$/.exec(line);
|
|
13250
|
-
if (!size) throw
|
|
13406
|
+
if (!size) throw errno2("EPROTO", "a malformed chunk size");
|
|
13251
13407
|
const n = Number.parseInt(size[1], 16);
|
|
13252
13408
|
if (n === 0) {
|
|
13253
13409
|
while (await incoming.line(MAX_HEAD2, signal) !== "") ;
|
|
13254
13410
|
return;
|
|
13255
13411
|
}
|
|
13256
13412
|
yield await incoming.exactly(n, signal);
|
|
13257
|
-
if (await incoming.line(2, signal) !== "") throw
|
|
13413
|
+
if (await incoming.line(2, signal) !== "") throw errno2("EPROTO", "a malformed chunk");
|
|
13258
13414
|
}
|
|
13259
13415
|
}
|
|
13260
13416
|
async function* counted(incoming, length2, signal) {
|
|
13261
13417
|
for (let left = length2; left > 0; ) {
|
|
13262
13418
|
const data = await incoming.some(Math.min(left, 64 * 1024), signal);
|
|
13263
|
-
if (data.length === 0) throw
|
|
13419
|
+
if (data.length === 0) throw errno2("EPROTO", "the body ended early");
|
|
13264
13420
|
left -= data.length;
|
|
13265
13421
|
yield data;
|
|
13266
13422
|
}
|
|
@@ -13281,7 +13437,7 @@ function bodyOf(incoming, head, method, signal) {
|
|
|
13281
13437
|
if (lengths.length === 0) return untilClose(incoming, signal);
|
|
13282
13438
|
const length2 = lengths[0]?.trim() ?? "";
|
|
13283
13439
|
if (!/^\d{1,15}$/.test(length2) || lengths.some((l) => l.trim() !== length2)) {
|
|
13284
|
-
throw
|
|
13440
|
+
throw errno2("EPROTO", `a malformed Content-Length: ${lengths.join(", ")}`);
|
|
13285
13441
|
}
|
|
13286
13442
|
return counted(incoming, Number(length2), signal);
|
|
13287
13443
|
}
|
|
@@ -13299,7 +13455,7 @@ var KernelLoopback = class {
|
|
|
13299
13455
|
}
|
|
13300
13456
|
async connect(url, port, signal) {
|
|
13301
13457
|
if (url.protocol === "https:" || url.protocol === "wss:") {
|
|
13302
|
-
throw
|
|
13458
|
+
throw errno2("ENOTSUP", `TLS to the kernel's loopback is not supported: ${url.origin}`);
|
|
13303
13459
|
}
|
|
13304
13460
|
signal.throwIfAborted();
|
|
13305
13461
|
const socket = this.net.socket("inet");
|
|
@@ -13314,7 +13470,7 @@ var KernelLoopback = class {
|
|
|
13314
13470
|
} catch (err) {
|
|
13315
13471
|
socket.close();
|
|
13316
13472
|
const refused2 = err instanceof KernelError && err.code === "ECONNREFUSED";
|
|
13317
|
-
throw refused2 ?
|
|
13473
|
+
throw refused2 ? errno2("ECONNREFUSED", `nothing listens on the kernel's port ${port}`) : err;
|
|
13318
13474
|
}
|
|
13319
13475
|
signal.addEventListener("abort", () => socket.close(), { once: true });
|
|
13320
13476
|
return socket;
|
|
@@ -13360,7 +13516,7 @@ var KernelLoopback = class {
|
|
|
13360
13516
|
const incoming = new Incoming(socket);
|
|
13361
13517
|
const head = await readHead(incoming, req.signal);
|
|
13362
13518
|
if (head.status !== 101) {
|
|
13363
|
-
throw
|
|
13519
|
+
throw errno2(
|
|
13364
13520
|
"EPROTO",
|
|
13365
13521
|
`the server answered the upgrade with ${head.status}${head.statusText ? ` ${head.statusText}` : ""}`
|
|
13366
13522
|
);
|
|
@@ -13368,10 +13524,10 @@ var KernelLoopback = class {
|
|
|
13368
13524
|
const upgraded = fieldTokens(head.headers, "upgrade").includes("websocket") && fieldTokens(head.headers, "connection").includes("upgrade");
|
|
13369
13525
|
const accept2 = fieldValues(head.headers, "sec-websocket-accept")[0];
|
|
13370
13526
|
if (!upgraded || accept2 !== await acceptFor(key)) {
|
|
13371
|
-
throw
|
|
13527
|
+
throw errno2("EPROTO", "the server did not accept the WebSocket key");
|
|
13372
13528
|
}
|
|
13373
13529
|
if (fieldValues(head.headers, "sec-websocket-extensions").length > 0) {
|
|
13374
|
-
throw
|
|
13530
|
+
throw errno2("EPROTO", "the server offered an unsolicited extension");
|
|
13375
13531
|
}
|
|
13376
13532
|
const protocol = fieldValues(head.headers, "sec-websocket-protocol")[0] ?? "";
|
|
13377
13533
|
return new LoopbackWebSocket(socket, incoming, protocol);
|
|
@@ -13389,7 +13545,7 @@ async function* closing(chunks, socket) {
|
|
|
13389
13545
|
yield* chunks;
|
|
13390
13546
|
} catch (err) {
|
|
13391
13547
|
if (typeof err?.code === "string") throw err;
|
|
13392
|
-
throw
|
|
13548
|
+
throw errno2("EPROTO", err instanceof Error ? err.message : String(err));
|
|
13393
13549
|
} finally {
|
|
13394
13550
|
socket.close();
|
|
13395
13551
|
}
|
|
@@ -13518,7 +13674,7 @@ var LoopbackWebSocket = class {
|
|
|
13518
13674
|
this.write(clientFrame(OP_CLOSE, payload));
|
|
13519
13675
|
}
|
|
13520
13676
|
send(data) {
|
|
13521
|
-
if (this.sentClose) throw
|
|
13677
|
+
if (this.sentClose) throw errno2("EPIPE", "the websocket is closing");
|
|
13522
13678
|
const text = typeof data === "string";
|
|
13523
13679
|
const payload = text ? new TextEncoder().encode(data) : data;
|
|
13524
13680
|
this.write(clientFrame(text ? OP_TEXT : OP_BINARY, payload));
|
|
@@ -14258,8 +14414,8 @@ function errnoOf(e) {
|
|
|
14258
14414
|
const code = e?.code;
|
|
14259
14415
|
return typeof code === "string" && ERRNO.test(code) ? code : "ECONNREFUSED";
|
|
14260
14416
|
}
|
|
14261
|
-
function fail(
|
|
14262
|
-
return { ok: false, errno:
|
|
14417
|
+
function fail(errno3, text) {
|
|
14418
|
+
return { ok: false, errno: errno3, message: text };
|
|
14263
14419
|
}
|
|
14264
14420
|
var WsHandles = class {
|
|
14265
14421
|
transport;
|
|
@@ -14533,8 +14689,8 @@ var HttpHandles = class {
|
|
|
14533
14689
|
const status = e.status;
|
|
14534
14690
|
if (text === NO_TRANSPORT || typeof status !== "number" || status === 502) {
|
|
14535
14691
|
const code = codeOf2(e);
|
|
14536
|
-
const
|
|
14537
|
-
return { ok: false, errno:
|
|
14692
|
+
const errno3 = text === NO_TRANSPORT ? "ENETUNREACH" : code !== "EIO" ? code : "ECONNREFUSED";
|
|
14693
|
+
return { ok: false, errno: errno3, message: text };
|
|
14538
14694
|
}
|
|
14539
14695
|
entry.body = once(new TextEncoder().encode(text))[Symbol.asyncIterator]();
|
|
14540
14696
|
return this.headOf(handle, req.url, {
|
|
@@ -15739,7 +15895,7 @@ var UNREACHABLE = ["EACCES", "ENETUNREACH", "EHOSTUNREACH"];
|
|
|
15739
15895
|
function sendError(e) {
|
|
15740
15896
|
if (e instanceof KernelError) return e;
|
|
15741
15897
|
const code = e?.code;
|
|
15742
|
-
return new KernelError(SEND_ERRORS.find((
|
|
15898
|
+
return new KernelError(SEND_ERRORS.find((errno3) => errno3 === code) ?? "EHOSTUNREACH");
|
|
15743
15899
|
}
|
|
15744
15900
|
function sameAddr(a, b) {
|
|
15745
15901
|
return a.port === b.port && canonicalHost(a.host) === canonicalHost(b.host);
|
|
@@ -15868,7 +16024,7 @@ var KernelDgram = class {
|
|
|
15868
16024
|
}
|
|
15869
16025
|
unreachable(error, from) {
|
|
15870
16026
|
if (!this.peer || !sameAddr(this.peer, from)) return;
|
|
15871
|
-
this.pending = UNREACHABLE.find((
|
|
16027
|
+
this.pending = UNREACHABLE.find((errno3) => errno3 === error) ?? "EHOSTUNREACH";
|
|
15872
16028
|
this.changes.wake();
|
|
15873
16029
|
}
|
|
15874
16030
|
deliver(datagram2) {
|
|
@@ -17200,6 +17356,7 @@ function isWasmSyscall(req) {
|
|
|
17200
17356
|
return typeof op === "string" && SYSCALL_OPS.has(op);
|
|
17201
17357
|
}
|
|
17202
17358
|
var MAX_READ = 1024 * 1024;
|
|
17359
|
+
var O_NONBLOCK = 2048;
|
|
17203
17360
|
var WRITE_ACCESS = 3;
|
|
17204
17361
|
var KEYBOARD = /* @__PURE__ */ new Set([SIG.INT, SIG.QUIT, SIG.TSTP]);
|
|
17205
17362
|
var DEFAULT_UMASK2 = 18;
|
|
@@ -17697,7 +17854,7 @@ var WasmProcess = class {
|
|
|
17697
17854
|
this.options.hasPending?.() ? AbortSignal.abort() : this.cancelSignal(cancelled)
|
|
17698
17855
|
);
|
|
17699
17856
|
}
|
|
17700
|
-
async openVfs(req) {
|
|
17857
|
+
async openVfs(req, cancelled) {
|
|
17701
17858
|
if (inProc(req.path)) return this.openProc(req, req.path);
|
|
17702
17859
|
const device = req.orphan ? void 0 : deviceAt(req.path);
|
|
17703
17860
|
if (device) return this.openDevice(req, device);
|
|
@@ -17708,6 +17865,10 @@ var WasmProcess = class {
|
|
|
17708
17865
|
await refuseReadonly(this.options.fs, req.path, req.flags, req);
|
|
17709
17866
|
if (this.writesAt(req)) await this.options.fs.mayChange?.(req.path, !req.exclusive);
|
|
17710
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
|
+
}
|
|
17711
17872
|
const marked = await this.markedPath(req);
|
|
17712
17873
|
await this.sourceOpen(marked === void 0 ? req : { ...req, path: marked });
|
|
17713
17874
|
const fs = marked === void 0 ? this.options.fs : this.options.noLinks;
|
|
@@ -17749,6 +17910,19 @@ var WasmProcess = class {
|
|
|
17749
17910
|
}
|
|
17750
17911
|
return fd;
|
|
17751
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
|
+
}
|
|
17752
17926
|
openDevice(req, device) {
|
|
17753
17927
|
if (req.exclusive) throw Object.assign(new Error(req.path), { code: "EEXIST" });
|
|
17754
17928
|
const access2 = req.flags & WRITE_ACCESS;
|
|
@@ -17948,7 +18122,7 @@ var WasmProcess = class {
|
|
|
17948
18122
|
case "fd-poll":
|
|
17949
18123
|
return { ok: true, kind: "json", json: pollFile(this.fds.get(req.fd).file) };
|
|
17950
18124
|
case "fd-open-vfs":
|
|
17951
|
-
return { ok: true, kind: "json", json: await this.openVfs(req) };
|
|
18125
|
+
return { ok: true, kind: "json", json: await this.openVfs(req, cancelled) };
|
|
17952
18126
|
case "fd-info":
|
|
17953
18127
|
return { ok: true, kind: "json", json: this.fdInfo(req.fd) };
|
|
17954
18128
|
case "fd-list":
|
|
@@ -18608,7 +18782,8 @@ function inheritedFds(fds) {
|
|
|
18608
18782
|
...kind === "device" && meta && "device" in meta ? { device: meta } : {},
|
|
18609
18783
|
...flags2 !== void 0 ? { flags: flags2 } : {},
|
|
18610
18784
|
...fds.closesOnExec(fd) ? { cloexec: true } : {},
|
|
18611
|
-
...kind === "stream" ? { desc: descId(open) } : {}
|
|
18785
|
+
...kind === "stream" ? { desc: descId(open) } : {},
|
|
18786
|
+
...open.file.fifo ? { fifo: open.file.fifo } : {}
|
|
18612
18787
|
};
|
|
18613
18788
|
});
|
|
18614
18789
|
}
|
|
@@ -18814,6 +18989,7 @@ function processOptions(opts, header3, hooks, created3) {
|
|
|
18814
18989
|
net: opts.net,
|
|
18815
18990
|
http: opts.http,
|
|
18816
18991
|
locks: opts.locks,
|
|
18992
|
+
fifos: opts.fifos,
|
|
18817
18993
|
...opts.sems ? { sems: opts.sems } : {},
|
|
18818
18994
|
onReap: opts.onReap,
|
|
18819
18995
|
resolver: opts.resolver,
|
|
@@ -20752,9 +20928,9 @@ var HostfsClient = class {
|
|
|
20752
20928
|
throw fsError2("ESTALE", "the folder was granted again, so its open files are gone");
|
|
20753
20929
|
return this.send(path, init, false, true);
|
|
20754
20930
|
}
|
|
20755
|
-
const
|
|
20931
|
+
const errno3 = response.headers.get("X-Hostfs-Errno") ?? "EIO";
|
|
20756
20932
|
const body = await response.json().catch(() => ({}));
|
|
20757
|
-
throw fsError2(
|
|
20933
|
+
throw fsError2(errno3, typeof body.message === "string" ? body.message : errno3);
|
|
20758
20934
|
}
|
|
20759
20935
|
async call(op, body = {}, handle = false) {
|
|
20760
20936
|
const response = await this.send(
|
|
@@ -21839,8 +22015,8 @@ var RULE = new RegExp(
|
|
|
21839
22015
|
var TERM = /^[A-Za-z0-9._+-]+$/;
|
|
21840
22016
|
var PLAIN = /^[A-Za-z0-9_@%+=:,./-]+$/;
|
|
21841
22017
|
var USAGE = "usage: sudo [-n] [-u user] [--] command [args...]\n sudo -l";
|
|
21842
|
-
function failed2(
|
|
21843
|
-
return { error, errno:
|
|
22018
|
+
function failed2(errno3, error) {
|
|
22019
|
+
return { error, errno: errno3 };
|
|
21844
22020
|
}
|
|
21845
22021
|
function unescaped(double) {
|
|
21846
22022
|
return double.replace(/\\(["\\$`])/g, "$1");
|
|
@@ -22501,6 +22677,7 @@ var Launcher = class {
|
|
|
22501
22677
|
sudoer;
|
|
22502
22678
|
jobs = new JobTable();
|
|
22503
22679
|
locks = new LockTable();
|
|
22680
|
+
fifos = new FifoTable();
|
|
22504
22681
|
sems = new SemTable();
|
|
22505
22682
|
settling = new SettlingChildren((pid) => this.jobs.pgidOf(pid));
|
|
22506
22683
|
ptys = new PtyTable(
|
|
@@ -23498,6 +23675,7 @@ var Launcher = class {
|
|
|
23498
23675
|
net: this.net,
|
|
23499
23676
|
http: new HttpHandles(this.transport, pid, this.loopbackFor(pid)),
|
|
23500
23677
|
locks: this.locks,
|
|
23678
|
+
fifos: this.fifos,
|
|
23501
23679
|
sems: this.sems,
|
|
23502
23680
|
resolver: this.resolver,
|
|
23503
23681
|
onReap: (child) => this.reaped(child, pid),
|