@ai-ecoverse/slicc-kernel 1.114.0 → 1.116.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.
@@ -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
- const fields = owner?.socket && !directory ? { ...owned4, socket: true } : owned4;
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),
@@ -2299,6 +2305,12 @@ var Incoming = class {
2299
2305
  this.buf = this.buf.subarray(n);
2300
2306
  return out;
2301
2307
  }
2308
+ async firstLine(max, signal) {
2309
+ while (this.buf.length < max && !this.buf.includes(10) && await this.fill(signal)) ;
2310
+ const end = this.buf.indexOf(10);
2311
+ const bytes = this.buf.subarray(0, end >= 0 ? end + 1 : Math.min(max, this.buf.length));
2312
+ return String.fromCharCode(...bytes);
2313
+ }
2302
2314
  async peek(signal) {
2303
2315
  if (this.buf.length === 0) await this.fill(signal);
2304
2316
  return this.buf[0];
@@ -3310,8 +3322,8 @@ async function access(fs, cred, path, want, options = {}) {
3310
3322
  if (await present(fs, walked.path, false)) return { ...walked, denied: walked.path };
3311
3323
  return { ...walked, missing: true };
3312
3324
  }
3313
- function refused(path, errno2 = "EACCES") {
3314
- return fsError(errno2, path);
3325
+ function refused(path, errno3 = "EACCES") {
3326
+ return fsError(errno3, path);
3315
3327
  }
3316
3328
 
3317
3329
  // src/fs/dac.ts
@@ -3371,9 +3383,9 @@ var Created = class {
3371
3383
  function linked(g, options) {
3372
3384
  return g.links === void 0 ? options : { ...options, links: g.links };
3373
3385
  }
3374
- function deny(g, op, path, errno2 = "EACCES") {
3386
+ function deny(g, op, path, errno3 = "EACCES") {
3375
3387
  const tag = g.tag === void 0 ? {} : { tag: g.tag };
3376
- g.dac.denied({ pid: g.pid, uid: g.cred.euid, op, path, errno: errno2, ...tag });
3388
+ g.dac.denied({ pid: g.pid, uid: g.cred.euid, op, path, errno: errno3, ...tag });
3377
3389
  }
3378
3390
  var TTY_MODE = 400;
3379
3391
  function ttyOpenable(g, tty) {
@@ -4086,7 +4098,7 @@ var WASI_SIGNAL_TO_POSIX = Object.fromEntries(
4086
4098
 
4087
4099
  // src/process/wasi-errno.ts
4088
4100
  var WASI_ERRNO = {
4089
- ...Object.fromEntries(Object.entries(E).map(([name2, errno2]) => [`E${name2}`, errno2])),
4101
+ ...Object.fromEntries(Object.entries(E).map(([name2, errno3]) => [`E${name2}`, errno3])),
4090
4102
  EWOULDBLOCK: E.AGAIN,
4091
4103
  ENOTSUP: 138,
4092
4104
  EOPNOTSUPP: 138,
@@ -4326,7 +4338,7 @@ function dialError(e, timedOut, closed) {
4326
4338
  if (timedOut) return new KernelError("ETIMEDOUT");
4327
4339
  if (closed) return new KernelError("ECONNABORTED");
4328
4340
  const code = e?.code;
4329
- const known = DIAL_ERRORS.find((errno2) => errno2 === code);
4341
+ const known = DIAL_ERRORS.find((errno3) => errno3 === code);
4330
4342
  return new KernelError(known ?? "EHOSTUNREACH");
4331
4343
  }
4332
4344
  function isLoopback(host) {
@@ -4702,6 +4714,14 @@ var LoopbackNet = class {
4702
4714
  facades = /* @__PURE__ */ new Map();
4703
4715
  nextEphemeral = EPHEMERAL_FIRST;
4704
4716
  route;
4717
+ origins;
4718
+ useOrigins(serve) {
4719
+ this.origins = serve;
4720
+ }
4721
+ serveOrigin(conn, origin) {
4722
+ if (!this.origins) throw new KernelError("ENETUNREACH");
4723
+ void this.origins(conn, origin).catch(() => conn.close());
4724
+ }
4705
4725
  useUplink(route) {
4706
4726
  this.route = route;
4707
4727
  }
@@ -6221,7 +6241,7 @@ function satisfies(version, range2) {
6221
6241
  }
6222
6242
 
6223
6243
  // src/version.ts
6224
- var KERNEL_VERSION = true ? "1.114.0" : "0.0.0-dev";
6244
+ var KERNEL_VERSION = true ? "1.116.0" : "0.0.0-dev";
6225
6245
  var OS_RELEASE = "6.0.0-slicc";
6226
6246
  function procVersion() {
6227
6247
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -7581,6 +7601,9 @@ var TLS_HANDSHAKE = 22;
7581
7601
  var TOKEN2 = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
7582
7602
  var NO_WEBSOCKET2 = "WebSocket not supported by this transport (fetchTransport needs { webSocket: true })";
7583
7603
  var REALM_PROXY_PORT = 3128;
7604
+ var REQUEST_LINE_MAX = 8192;
7605
+ var REQUEST_LINE = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+ \S+ HTTP\/1\.[01]\r?\n$/;
7606
+ var NOT_HTTP = "not HTTP/1.1: TLS through the transport carries only HTTP/1.1 and WebSocket";
7584
7607
  var DEFAULT_LIMITS = {
7585
7608
  maxConnections: 64,
7586
7609
  maxHead: 64 * 1024,
@@ -7869,6 +7892,26 @@ var RealmProxy = class {
7869
7892
  conn.close();
7870
7893
  }
7871
7894
  }
7895
+ async serveOrigin(conn, origin) {
7896
+ if (this.stop.signal.aborted) {
7897
+ conn.close();
7898
+ return;
7899
+ }
7900
+ this.connections.add(conn);
7901
+ const idle = { ms: this.limits.idleMs };
7902
+ const incoming = new Incoming(timedSource(conn, idle, this.stop.signal));
7903
+ try {
7904
+ const line = await incoming.firstLine(REQUEST_LINE_MAX).catch(() => "");
7905
+ if (line !== "" && !REQUEST_LINE.test(line)) {
7906
+ await this.refuse(conn, new HttpError(400, NOT_HTTP));
7907
+ return;
7908
+ }
7909
+ await this.requests({ sink: conn, incoming, origin, socket: conn, idle });
7910
+ } finally {
7911
+ this.connections.delete(conn);
7912
+ conn.close();
7913
+ }
7914
+ }
7872
7915
  async requests(ctx) {
7873
7916
  try {
7874
7917
  for (; ; ) {
@@ -9446,6 +9489,139 @@ var TicketBook = class {
9446
9489
  }
9447
9490
  };
9448
9491
 
9492
+ // src/kernel/fifo.ts
9493
+ function errno(e) {
9494
+ return e instanceof KernelError ? e : new KernelError(e.code ?? "EIO");
9495
+ }
9496
+ var FifoTable = class {
9497
+ fifos = /* @__PURE__ */ new Map();
9498
+ size() {
9499
+ return this.fifos.size;
9500
+ }
9501
+ async open(key, path, access2, nonblock, signal) {
9502
+ const fifo = this.entry(key);
9503
+ if (access2 === "write" && nonblock && fifo.readers === 0) {
9504
+ this.drop(key, fifo);
9505
+ throw new KernelError("ENXIO");
9506
+ }
9507
+ const reads = access2 !== "write";
9508
+ const writes = access2 !== "read";
9509
+ const seen = { readOpens: fifo.readOpens, writeOpens: fifo.writeOpens };
9510
+ if (reads) this.count(fifo, "readers", 1);
9511
+ if (writes) this.count(fifo, "writers", 1);
9512
+ this.notify(fifo);
9513
+ try {
9514
+ if (!nonblock && access2 === "read") {
9515
+ while (fifo.writers === 0 && fifo.writeOpens === seen.writeOpens) {
9516
+ await this.changed(fifo, signal);
9517
+ }
9518
+ }
9519
+ if (!nonblock && access2 === "write") {
9520
+ while (fifo.readers === 0 && fifo.readOpens === seen.readOpens) {
9521
+ await this.changed(fifo, signal);
9522
+ }
9523
+ }
9524
+ } catch (e) {
9525
+ this.release(key, fifo, reads, writes);
9526
+ throw errno(e);
9527
+ }
9528
+ return this.end(key, path, fifo, reads, writes);
9529
+ }
9530
+ entry(key) {
9531
+ let fifo = this.fifos.get(key);
9532
+ if (!fifo) {
9533
+ fifo = {
9534
+ pipe: new KernelPipe(),
9535
+ readers: 0,
9536
+ writers: 0,
9537
+ readOpens: 0,
9538
+ writeOpens: 0,
9539
+ waiters: []
9540
+ };
9541
+ this.fifos.set(key, fifo);
9542
+ }
9543
+ return fifo;
9544
+ }
9545
+ count(fifo, side, by) {
9546
+ fifo[side] += by;
9547
+ if (side === "readers") {
9548
+ if (by > 0) {
9549
+ fifo.readOpens += 1;
9550
+ fifo.pipe.openRead();
9551
+ } else fifo.pipe.closeRead();
9552
+ } else if (by > 0) {
9553
+ fifo.writeOpens += 1;
9554
+ fifo.pipe.openWrite();
9555
+ } else fifo.pipe.closeWrite();
9556
+ }
9557
+ notify(fifo) {
9558
+ const waiters = fifo.waiters;
9559
+ fifo.waiters = [];
9560
+ for (const wake of waiters) wake();
9561
+ }
9562
+ changed(fifo, signal) {
9563
+ if (signal.aborted) return Promise.reject(new KernelError("EINTR"));
9564
+ return new Promise((resolve2, reject) => {
9565
+ const onAbort = () => {
9566
+ fifo.waiters = fifo.waiters.filter((w) => w !== wake);
9567
+ reject(new KernelError("EINTR"));
9568
+ };
9569
+ const wake = () => {
9570
+ signal.removeEventListener("abort", onAbort);
9571
+ resolve2();
9572
+ };
9573
+ fifo.waiters.push(wake);
9574
+ signal.addEventListener("abort", onAbort, { once: true });
9575
+ });
9576
+ }
9577
+ release(key, fifo, reads, writes) {
9578
+ if (reads) this.count(fifo, "readers", -1);
9579
+ if (writes) this.count(fifo, "writers", -1);
9580
+ this.notify(fifo);
9581
+ this.drop(key, fifo);
9582
+ }
9583
+ drop(key, fifo) {
9584
+ const idle = fifo.readers === 0 && fifo.writers === 0 && fifo.waiters.length === 0;
9585
+ if (idle && this.fifos.get(key) === fifo) this.fifos.delete(key);
9586
+ }
9587
+ end(key, path, fifo, reads, writes) {
9588
+ const { pipe } = fifo;
9589
+ let open = true;
9590
+ return new OpenFile({
9591
+ fifo: path,
9592
+ ...reads ? {
9593
+ read: async (max, signal) => {
9594
+ try {
9595
+ return await pipe.read(max, signal);
9596
+ } catch (e) {
9597
+ throw errno(e);
9598
+ }
9599
+ }
9600
+ } : {},
9601
+ ...writes ? {
9602
+ write: async (bytes, signal) => {
9603
+ try {
9604
+ return await pipe.write(bytes, signal);
9605
+ } catch (e) {
9606
+ throw errno(e);
9607
+ }
9608
+ }
9609
+ } : {},
9610
+ close: () => {
9611
+ if (!open) return;
9612
+ open = false;
9613
+ this.release(key, fifo, reads, writes);
9614
+ },
9615
+ poll: () => ({
9616
+ readable: reads && pipe.readReady,
9617
+ writable: writes && pipe.writeReady,
9618
+ hangup: reads ? pipe.writersGone : pipe.readersGone
9619
+ }),
9620
+ changed: (signal) => pipe.changed(signal)
9621
+ });
9622
+ }
9623
+ };
9624
+
9449
9625
  // src/mount/protocol.ts
9450
9626
  var DRIVER_PROTOCOL = [1, 2];
9451
9627
  function driverVersionError(theirs) {
@@ -10306,6 +10482,7 @@ var MountFs = class _MountFs {
10306
10482
  }
10307
10483
  const { mount, rel: rel2 } = found;
10308
10484
  this.writable(mount, real);
10485
+ if (owner?.fifo) throw errnoError("EPERM", `${real}: this mount has no FIFOs`);
10309
10486
  const bytes = typeof content === "string" ? new TextEncoder().encode(content) : content;
10310
10487
  if (mount.maxFile > 0 && bytes.length > mount.maxFile) {
10311
10488
  throw errnoError(
@@ -10911,6 +11088,7 @@ var SYNC_FS_OPS = [
10911
11088
  "statfs",
10912
11089
  "hold",
10913
11090
  "create",
11091
+ "mkfifo",
10914
11092
  "kept",
10915
11093
  "pread",
10916
11094
  "pwrite",
@@ -10943,6 +11121,7 @@ function statJson(s) {
10943
11121
  isFile: s.isFile,
10944
11122
  isSymbolicLink: s.isSymbolicLink,
10945
11123
  ...s.isSocket ? { isSocket: true } : {},
11124
+ ...s.isFifo ? { isFifo: true } : {},
10946
11125
  size: s.size,
10947
11126
  mode: s.mode,
10948
11127
  mtimeMs: s.mtime.getTime(),
@@ -11092,6 +11271,12 @@ async function run(entry, path, req) {
11092
11271
  case "symlink":
11093
11272
  await fs.symlink(req.arg2 ?? "", path, ownerFor2(entry));
11094
11273
  return done;
11274
+ case "mkfifo": {
11275
+ const owner = ownerFor2(entry, req.mode ?? 438) ?? { uid: 0, gid: 0 };
11276
+ await createExclusive(fs, path, { ...owner, fifo: true });
11277
+ entry.fresh?.(path);
11278
+ return done;
11279
+ }
11095
11280
  case "create":
11096
11281
  await createExclusive(fs, path, ownerFor2(entry, req.mode ?? 438));
11097
11282
  if (req.opening) entry.created?.add(path);
@@ -11170,9 +11355,10 @@ async function guard(g, path, req, cwd) {
11170
11355
  return { path: await walkSafe(g, path, false) };
11171
11356
  }
11172
11357
  case "create":
11358
+ case "mkfifo":
11173
11359
  case "symlink":
11174
11360
  await inParent(g, op, path);
11175
- return { path: await walkSafe(g, path, op === "create") };
11361
+ return { path: await walkSafe(g, path, op !== "symlink") };
11176
11362
  case "unlink":
11177
11363
  case "rmdir": {
11178
11364
  await inParent(g, op, path, true);
@@ -11260,6 +11446,7 @@ async function accessOp(entry, path, req) {
11260
11446
  var CHANGING = /* @__PURE__ */ new Set([
11261
11447
  "mkdir",
11262
11448
  "create",
11449
+ "mkfifo",
11263
11450
  "symlink",
11264
11451
  "unlink",
11265
11452
  "rmdir",
@@ -11454,7 +11641,13 @@ async function guardAndResolve(entry, path, req) {
11454
11641
  };
11455
11642
  }
11456
11643
  var REMOVALS = /* @__PURE__ */ new Set(["unlink", "rmdir", "rm"]);
11457
- var CREATIONS = /* @__PURE__ */ new Set(["write", "mkdir", "symlink", "create"]);
11644
+ var CREATIONS = /* @__PURE__ */ new Set([
11645
+ "write",
11646
+ "mkdir",
11647
+ "symlink",
11648
+ "create",
11649
+ "mkfifo"
11650
+ ]);
11458
11651
  var NAMING = /* @__PURE__ */ new Set(["link", "rename"]);
11459
11652
  async function newDevName(entry, path, req) {
11460
11653
  const named = NAMING.has(req.op);
@@ -13201,16 +13394,16 @@ var TOKEN3 = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
13201
13394
  var SAFE_VALUE = /^[^\r\n\0]*$/;
13202
13395
  var CLOSE_WAIT_MS3 = 5e3;
13203
13396
  var MAX_UNREAD = 16 * 1024 * 1024;
13204
- function errno(code, message3) {
13397
+ function errno2(code, message3) {
13205
13398
  return Object.assign(new Error(`${code}: ${message3}`), { code });
13206
13399
  }
13207
13400
  function requestHead(method, url, headers, extra, first = []) {
13208
- if (!TOKEN3.test(method)) throw errno("EINVAL", `method ${method}`);
13401
+ if (!TOKEN3.test(method)) throw errno2("EINVAL", `method ${method}`);
13209
13402
  const lines2 = [`${method} ${url.pathname}${url.search} HTTP/1.1`, `host: ${url.host}`];
13210
13403
  for (const [name2, value2] of first) lines2.push(`${name2}: ${value2}`);
13211
13404
  for (const [name2, value2] of headers) {
13212
13405
  if (OWN_HEADERS.has(name2.toLowerCase())) continue;
13213
- if (!TOKEN3.test(name2) || !SAFE_VALUE.test(value2)) throw errno("EINVAL", `header ${name2}`);
13406
+ if (!TOKEN3.test(name2) || !SAFE_VALUE.test(value2)) throw errno2("EINVAL", `header ${name2}`);
13214
13407
  lines2.push(`${name2}: ${value2}`);
13215
13408
  }
13216
13409
  for (const [name2, value2] of extra) lines2.push(`${name2}: ${value2}`);
@@ -13221,7 +13414,7 @@ function requestHead(method, url, headers, extra, first = []) {
13221
13414
  function parseHead(bytes) {
13222
13415
  const [statusLine = "", ...lines2] = latin1(bytes).split(/\r?\n/);
13223
13416
  const match = /^HTTP\/1\.[01] (\d{3})(?: (.*))?$/.exec(statusLine);
13224
- if (!match) throw errno("EPROTO", `not an HTTP/1.x response: ${statusLine.slice(0, 80)}`);
13417
+ if (!match) throw errno2("EPROTO", `not an HTTP/1.x response: ${statusLine.slice(0, 80)}`);
13225
13418
  const headers = [];
13226
13419
  for (const line of lines2) {
13227
13420
  const colon = line.indexOf(":");
@@ -13236,9 +13429,9 @@ async function readHead(incoming, signal) {
13236
13429
  raw = await incoming.head(MAX_HEAD2, signal);
13237
13430
  } catch (err) {
13238
13431
  if (err instanceof KernelError) throw err;
13239
- throw errno("EPROTO", "the response head is malformed or too large");
13432
+ throw errno2("EPROTO", "the response head is malformed or too large");
13240
13433
  }
13241
- if (!raw) throw errno("ECONNRESET", "the connection closed before a response");
13434
+ if (!raw) throw errno2("ECONNRESET", "the connection closed before a response");
13242
13435
  const head = parseHead(raw);
13243
13436
  if (head.status < 100 || head.status >= 200 || head.status === 101) return head;
13244
13437
  }
@@ -13247,20 +13440,20 @@ async function* chunked(incoming, signal) {
13247
13440
  for (; ; ) {
13248
13441
  const line = await incoming.line(4096, signal);
13249
13442
  const size = /^([0-9A-Fa-f]{1,12})[ \t]*(;.*)?$/.exec(line);
13250
- if (!size) throw errno("EPROTO", "a malformed chunk size");
13443
+ if (!size) throw errno2("EPROTO", "a malformed chunk size");
13251
13444
  const n = Number.parseInt(size[1], 16);
13252
13445
  if (n === 0) {
13253
13446
  while (await incoming.line(MAX_HEAD2, signal) !== "") ;
13254
13447
  return;
13255
13448
  }
13256
13449
  yield await incoming.exactly(n, signal);
13257
- if (await incoming.line(2, signal) !== "") throw errno("EPROTO", "a malformed chunk");
13450
+ if (await incoming.line(2, signal) !== "") throw errno2("EPROTO", "a malformed chunk");
13258
13451
  }
13259
13452
  }
13260
13453
  async function* counted(incoming, length2, signal) {
13261
13454
  for (let left = length2; left > 0; ) {
13262
13455
  const data = await incoming.some(Math.min(left, 64 * 1024), signal);
13263
- if (data.length === 0) throw errno("EPROTO", "the body ended early");
13456
+ if (data.length === 0) throw errno2("EPROTO", "the body ended early");
13264
13457
  left -= data.length;
13265
13458
  yield data;
13266
13459
  }
@@ -13281,7 +13474,7 @@ function bodyOf(incoming, head, method, signal) {
13281
13474
  if (lengths.length === 0) return untilClose(incoming, signal);
13282
13475
  const length2 = lengths[0]?.trim() ?? "";
13283
13476
  if (!/^\d{1,15}$/.test(length2) || lengths.some((l) => l.trim() !== length2)) {
13284
- throw errno("EPROTO", `a malformed Content-Length: ${lengths.join(", ")}`);
13477
+ throw errno2("EPROTO", `a malformed Content-Length: ${lengths.join(", ")}`);
13285
13478
  }
13286
13479
  return counted(incoming, Number(length2), signal);
13287
13480
  }
@@ -13299,7 +13492,7 @@ var KernelLoopback = class {
13299
13492
  }
13300
13493
  async connect(url, port, signal) {
13301
13494
  if (url.protocol === "https:" || url.protocol === "wss:") {
13302
- throw errno("ENOTSUP", `TLS to the kernel's loopback is not supported: ${url.origin}`);
13495
+ throw errno2("ENOTSUP", `TLS to the kernel's loopback is not supported: ${url.origin}`);
13303
13496
  }
13304
13497
  signal.throwIfAborted();
13305
13498
  const socket = this.net.socket("inet");
@@ -13314,7 +13507,7 @@ var KernelLoopback = class {
13314
13507
  } catch (err) {
13315
13508
  socket.close();
13316
13509
  const refused2 = err instanceof KernelError && err.code === "ECONNREFUSED";
13317
- throw refused2 ? errno("ECONNREFUSED", `nothing listens on the kernel's port ${port}`) : err;
13510
+ throw refused2 ? errno2("ECONNREFUSED", `nothing listens on the kernel's port ${port}`) : err;
13318
13511
  }
13319
13512
  signal.addEventListener("abort", () => socket.close(), { once: true });
13320
13513
  return socket;
@@ -13360,7 +13553,7 @@ var KernelLoopback = class {
13360
13553
  const incoming = new Incoming(socket);
13361
13554
  const head = await readHead(incoming, req.signal);
13362
13555
  if (head.status !== 101) {
13363
- throw errno(
13556
+ throw errno2(
13364
13557
  "EPROTO",
13365
13558
  `the server answered the upgrade with ${head.status}${head.statusText ? ` ${head.statusText}` : ""}`
13366
13559
  );
@@ -13368,10 +13561,10 @@ var KernelLoopback = class {
13368
13561
  const upgraded = fieldTokens(head.headers, "upgrade").includes("websocket") && fieldTokens(head.headers, "connection").includes("upgrade");
13369
13562
  const accept2 = fieldValues(head.headers, "sec-websocket-accept")[0];
13370
13563
  if (!upgraded || accept2 !== await acceptFor(key)) {
13371
- throw errno("EPROTO", "the server did not accept the WebSocket key");
13564
+ throw errno2("EPROTO", "the server did not accept the WebSocket key");
13372
13565
  }
13373
13566
  if (fieldValues(head.headers, "sec-websocket-extensions").length > 0) {
13374
- throw errno("EPROTO", "the server offered an unsolicited extension");
13567
+ throw errno2("EPROTO", "the server offered an unsolicited extension");
13375
13568
  }
13376
13569
  const protocol = fieldValues(head.headers, "sec-websocket-protocol")[0] ?? "";
13377
13570
  return new LoopbackWebSocket(socket, incoming, protocol);
@@ -13389,7 +13582,7 @@ async function* closing(chunks, socket) {
13389
13582
  yield* chunks;
13390
13583
  } catch (err) {
13391
13584
  if (typeof err?.code === "string") throw err;
13392
- throw errno("EPROTO", err instanceof Error ? err.message : String(err));
13585
+ throw errno2("EPROTO", err instanceof Error ? err.message : String(err));
13393
13586
  } finally {
13394
13587
  socket.close();
13395
13588
  }
@@ -13518,7 +13711,7 @@ var LoopbackWebSocket = class {
13518
13711
  this.write(clientFrame(OP_CLOSE, payload));
13519
13712
  }
13520
13713
  send(data) {
13521
- if (this.sentClose) throw errno("EPIPE", "the websocket is closing");
13714
+ if (this.sentClose) throw errno2("EPIPE", "the websocket is closing");
13522
13715
  const text = typeof data === "string";
13523
13716
  const payload = text ? new TextEncoder().encode(data) : data;
13524
13717
  this.write(clientFrame(text ? OP_TEXT : OP_BINARY, payload));
@@ -14217,7 +14410,7 @@ async function writeCaFile(fs, ca, locks = globalThis.navigator?.locks) {
14217
14410
  function enableNetwork(net, options) {
14218
14411
  let proxy;
14219
14412
  const transport = options.transport ?? missingTransport();
14220
- net.activate({ family: "inet", host: "127.0.0.1", port: REALM_PROXY_PORT }, () => {
14413
+ const start2 = () => {
14221
14414
  const tls = new TlsTerminator({
14222
14415
  ca: options.ca,
14223
14416
  engine: options.engine,
@@ -14236,6 +14429,11 @@ function enableNetwork(net, options) {
14236
14429
  if (proxy === started) proxy = void 0;
14237
14430
  await tls.close();
14238
14431
  });
14432
+ };
14433
+ net.activate({ family: "inet", host: "127.0.0.1", port: REALM_PROXY_PORT }, start2);
14434
+ net.useOrigins((conn, origin) => {
14435
+ if (!proxy) start2();
14436
+ return proxy.serveOrigin(conn, origin);
14239
14437
  });
14240
14438
  return () => proxy;
14241
14439
  }
@@ -14258,8 +14456,8 @@ function errnoOf(e) {
14258
14456
  const code = e?.code;
14259
14457
  return typeof code === "string" && ERRNO.test(code) ? code : "ECONNREFUSED";
14260
14458
  }
14261
- function fail(errno2, text) {
14262
- return { ok: false, errno: errno2, message: text };
14459
+ function fail(errno3, text) {
14460
+ return { ok: false, errno: errno3, message: text };
14263
14461
  }
14264
14462
  var WsHandles = class {
14265
14463
  transport;
@@ -14533,8 +14731,8 @@ var HttpHandles = class {
14533
14731
  const status = e.status;
14534
14732
  if (text === NO_TRANSPORT || typeof status !== "number" || status === 502) {
14535
14733
  const code = codeOf2(e);
14536
- const errno2 = text === NO_TRANSPORT ? "ENETUNREACH" : code !== "EIO" ? code : "ECONNREFUSED";
14537
- return { ok: false, errno: errno2, message: text };
14734
+ const errno3 = text === NO_TRANSPORT ? "ENETUNREACH" : code !== "EIO" ? code : "ECONNREFUSED";
14735
+ return { ok: false, errno: errno3, message: text };
14538
14736
  }
14539
14737
  entry.body = once(new TextEncoder().encode(text))[Symbol.asyncIterator]();
14540
14738
  return this.headOf(handle, req.url, {
@@ -15739,7 +15937,7 @@ var UNREACHABLE = ["EACCES", "ENETUNREACH", "EHOSTUNREACH"];
15739
15937
  function sendError(e) {
15740
15938
  if (e instanceof KernelError) return e;
15741
15939
  const code = e?.code;
15742
- return new KernelError(SEND_ERRORS.find((errno2) => errno2 === code) ?? "EHOSTUNREACH");
15940
+ return new KernelError(SEND_ERRORS.find((errno3) => errno3 === code) ?? "EHOSTUNREACH");
15743
15941
  }
15744
15942
  function sameAddr(a, b) {
15745
15943
  return a.port === b.port && canonicalHost(a.host) === canonicalHost(b.host);
@@ -15868,7 +16066,7 @@ var KernelDgram = class {
15868
16066
  }
15869
16067
  unreachable(error, from) {
15870
16068
  if (!this.peer || !sameAddr(this.peer, from)) return;
15871
- this.pending = UNREACHABLE.find((errno2) => errno2 === error) ?? "EHOSTUNREACH";
16069
+ this.pending = UNREACHABLE.find((errno3) => errno3 === error) ?? "EHOSTUNREACH";
15872
16070
  this.changes.wake();
15873
16071
  }
15874
16072
  deliver(datagram2) {
@@ -16151,7 +16349,8 @@ var SOCKET_OPS = [
16151
16349
  "sock-setopt",
16152
16350
  "sock-resolve",
16153
16351
  "sock-sendto",
16154
- "sock-recvfrom"
16352
+ "sock-recvfrom",
16353
+ "sock-tls"
16155
16354
  ];
16156
16355
  function socketAt(fds, fd) {
16157
16356
  const file = anySocketAt(fds, fd);
@@ -16223,6 +16422,8 @@ async function socketSyscall(req, proc) {
16223
16422
  if (addresses.length === 0) throw new KernelError("ENOENT");
16224
16423
  return ok3(addresses);
16225
16424
  }
16425
+ case "sock-tls":
16426
+ return ok3(tlsOverTransport(req, proc));
16226
16427
  default:
16227
16428
  return datagram(req, proc);
16228
16429
  }
@@ -16326,6 +16527,48 @@ async function accept(proc, fd, nonblock) {
16326
16527
  const socket = await listener.accept(waits ? proc.blocking() : void 0, nonblock);
16327
16528
  return { fd: proc.fds.install(new OpenFile(socket), 3), peer: socket.peer };
16328
16529
  }
16530
+ var NOT_HTTP_PORTS = /* @__PURE__ */ new Set([
16531
+ 465,
16532
+ 563,
16533
+ 585,
16534
+ 636,
16535
+ 853,
16536
+ 989,
16537
+ 990,
16538
+ 992,
16539
+ 993,
16540
+ 994,
16541
+ 995,
16542
+ 5061,
16543
+ 5671,
16544
+ 6697,
16545
+ 8883
16546
+ ]);
16547
+ var HOST_NAME = /^[A-Za-z0-9.-]+$|^\[?[0-9A-Fa-f:.]+\]?$/;
16548
+ function tlsOverTransport(req, proc) {
16549
+ if (req.ca) throw new KernelError("ENOTSUP");
16550
+ if (req.alpn && req.alpn.length > 0 && !req.alpn.includes("http/1.1")) {
16551
+ throw new KernelError("EPROTONOSUPPORT");
16552
+ }
16553
+ if (!Number.isInteger(req.port) || req.port < 1 || req.port > 65535)
16554
+ throw new KernelError("EINVAL");
16555
+ if (NOT_HTTP_PORTS.has(req.port)) throw new KernelError("EPROTONOSUPPORT");
16556
+ const servername = req.servername || req.host;
16557
+ if (!HOST_NAME.test(servername)) throw new KernelError("EINVAL");
16558
+ if (isLoopbackHost(servername) || isLoopbackHost(req.host)) throw new KernelError("ENOTSUP");
16559
+ const host = servername.includes(":") && !servername.startsWith("[") ? `[${servername}]` : servername;
16560
+ const origin = req.port === 443 ? `https://${host}` : `https://${host}:${req.port}`;
16561
+ const [mine, theirs] = KernelSocket.pair(proc.net, "inet", proc.cred?.());
16562
+ mine.peer = { family: "inet", host: req.host, port: req.port };
16563
+ try {
16564
+ proc.net.serveOrigin(theirs, origin);
16565
+ } catch (err) {
16566
+ mine.close();
16567
+ theirs.close();
16568
+ throw err;
16569
+ }
16570
+ return { fd: proc.fds.install(new OpenFile(mine), 3), alpnProtocol: "http/1.1", servername };
16571
+ }
16329
16572
 
16330
16573
  // src/kernel/vfs-file.ts
16331
16574
  var O_ACCMODE = 3;
@@ -17200,6 +17443,7 @@ function isWasmSyscall(req) {
17200
17443
  return typeof op === "string" && SYSCALL_OPS.has(op);
17201
17444
  }
17202
17445
  var MAX_READ = 1024 * 1024;
17446
+ var O_NONBLOCK = 2048;
17203
17447
  var WRITE_ACCESS = 3;
17204
17448
  var KEYBOARD = /* @__PURE__ */ new Set([SIG.INT, SIG.QUIT, SIG.TSTP]);
17205
17449
  var DEFAULT_UMASK2 = 18;
@@ -17697,7 +17941,7 @@ var WasmProcess = class {
17697
17941
  this.options.hasPending?.() ? AbortSignal.abort() : this.cancelSignal(cancelled)
17698
17942
  );
17699
17943
  }
17700
- async openVfs(req) {
17944
+ async openVfs(req, cancelled) {
17701
17945
  if (inProc(req.path)) return this.openProc(req, req.path);
17702
17946
  const device = req.orphan ? void 0 : deviceAt(req.path);
17703
17947
  if (device) return this.openDevice(req, device);
@@ -17708,6 +17952,10 @@ var WasmProcess = class {
17708
17952
  await refuseReadonly(this.options.fs, req.path, req.flags, req);
17709
17953
  if (this.writesAt(req)) await this.options.fs.mayChange?.(req.path, !req.exclusive);
17710
17954
  await this.mayOpen(req);
17955
+ if (req.fifo && !req.exclusive) {
17956
+ const opened2 = await this.openFifo(req, cancelled);
17957
+ if (opened2 !== void 0) return opened2;
17958
+ }
17711
17959
  const marked = await this.markedPath(req);
17712
17960
  await this.sourceOpen(marked === void 0 ? req : { ...req, path: marked });
17713
17961
  const fs = marked === void 0 ? this.options.fs : this.options.noLinks;
@@ -17749,6 +17997,19 @@ var WasmProcess = class {
17749
17997
  }
17750
17998
  return fd;
17751
17999
  }
18000
+ async openFifo(req, cancelled) {
18001
+ const fifos = this.options.fifos;
18002
+ const path = await this.nodes.targetKey(req.path);
18003
+ const st = await this.heldFs().stat(path);
18004
+ if (!st.isFifo) return void 0;
18005
+ if (!fifos) throw new KernelError("ENXIO");
18006
+ const access2 = openAccess(req.flags);
18007
+ const nonblock = (req.flags & O_NONBLOCK) !== 0;
18008
+ const blocks = !nonblock && access2 !== "both";
18009
+ const signal = blocks ? this.blockingSignal(cancelled) : cancelled;
18010
+ const end = await fifos.open(`${st.dev ?? 0}:${st.ino}`, path, access2, nonblock, signal);
18011
+ return this.fds.install(end, 3);
18012
+ }
17752
18013
  openDevice(req, device) {
17753
18014
  if (req.exclusive) throw Object.assign(new Error(req.path), { code: "EEXIST" });
17754
18015
  const access2 = req.flags & WRITE_ACCESS;
@@ -17948,7 +18209,7 @@ var WasmProcess = class {
17948
18209
  case "fd-poll":
17949
18210
  return { ok: true, kind: "json", json: pollFile(this.fds.get(req.fd).file) };
17950
18211
  case "fd-open-vfs":
17951
- return { ok: true, kind: "json", json: await this.openVfs(req) };
18212
+ return { ok: true, kind: "json", json: await this.openVfs(req, cancelled) };
17952
18213
  case "fd-info":
17953
18214
  return { ok: true, kind: "json", json: this.fdInfo(req.fd) };
17954
18215
  case "fd-list":
@@ -18608,7 +18869,8 @@ function inheritedFds(fds) {
18608
18869
  ...kind === "device" && meta && "device" in meta ? { device: meta } : {},
18609
18870
  ...flags2 !== void 0 ? { flags: flags2 } : {},
18610
18871
  ...fds.closesOnExec(fd) ? { cloexec: true } : {},
18611
- ...kind === "stream" ? { desc: descId(open) } : {}
18872
+ ...kind === "stream" ? { desc: descId(open) } : {},
18873
+ ...open.file.fifo ? { fifo: open.file.fifo } : {}
18612
18874
  };
18613
18875
  });
18614
18876
  }
@@ -18814,6 +19076,7 @@ function processOptions(opts, header3, hooks, created3) {
18814
19076
  net: opts.net,
18815
19077
  http: opts.http,
18816
19078
  locks: opts.locks,
19079
+ fifos: opts.fifos,
18817
19080
  ...opts.sems ? { sems: opts.sems } : {},
18818
19081
  onReap: opts.onReap,
18819
19082
  resolver: opts.resolver,
@@ -20752,9 +21015,9 @@ var HostfsClient = class {
20752
21015
  throw fsError2("ESTALE", "the folder was granted again, so its open files are gone");
20753
21016
  return this.send(path, init, false, true);
20754
21017
  }
20755
- const errno2 = response.headers.get("X-Hostfs-Errno") ?? "EIO";
21018
+ const errno3 = response.headers.get("X-Hostfs-Errno") ?? "EIO";
20756
21019
  const body = await response.json().catch(() => ({}));
20757
- throw fsError2(errno2, typeof body.message === "string" ? body.message : errno2);
21020
+ throw fsError2(errno3, typeof body.message === "string" ? body.message : errno3);
20758
21021
  }
20759
21022
  async call(op, body = {}, handle = false) {
20760
21023
  const response = await this.send(
@@ -21839,8 +22102,8 @@ var RULE = new RegExp(
21839
22102
  var TERM = /^[A-Za-z0-9._+-]+$/;
21840
22103
  var PLAIN = /^[A-Za-z0-9_@%+=:,./-]+$/;
21841
22104
  var USAGE = "usage: sudo [-n] [-u user] [--] command [args...]\n sudo -l";
21842
- function failed2(errno2, error) {
21843
- return { error, errno: errno2 };
22105
+ function failed2(errno3, error) {
22106
+ return { error, errno: errno3 };
21844
22107
  }
21845
22108
  function unescaped(double) {
21846
22109
  return double.replace(/\\(["\\$`])/g, "$1");
@@ -22501,6 +22764,7 @@ var Launcher = class {
22501
22764
  sudoer;
22502
22765
  jobs = new JobTable();
22503
22766
  locks = new LockTable();
22767
+ fifos = new FifoTable();
22504
22768
  sems = new SemTable();
22505
22769
  settling = new SettlingChildren((pid) => this.jobs.pgidOf(pid));
22506
22770
  ptys = new PtyTable(
@@ -23498,6 +23762,7 @@ var Launcher = class {
23498
23762
  net: this.net,
23499
23763
  http: new HttpHandles(this.transport, pid, this.loopbackFor(pid)),
23500
23764
  locks: this.locks,
23765
+ fifos: this.fifos,
23501
23766
  sems: this.sems,
23502
23767
  resolver: this.resolver,
23503
23768
  onReap: (child) => this.reaped(child, pid),