@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/dist/node.js CHANGED
@@ -473,8 +473,8 @@ async function access(fs, cred, path, want, options = {}) {
473
473
  if (await present(fs, walked.path, false)) return { ...walked, denied: walked.path };
474
474
  return { ...walked, missing: true };
475
475
  }
476
- function refused(path, errno2 = "EACCES") {
477
- return fsError(errno2, path);
476
+ function refused(path, errno3 = "EACCES") {
477
+ return fsError(errno3, path);
478
478
  }
479
479
 
480
480
  // src/fs/dac.ts
@@ -534,9 +534,9 @@ var Created = class {
534
534
  function linked(g, options) {
535
535
  return g.links === void 0 ? options : { ...options, links: g.links };
536
536
  }
537
- function deny(g, op, path, errno2 = "EACCES") {
537
+ function deny(g, op, path, errno3 = "EACCES") {
538
538
  const tag = g.tag === void 0 ? {} : { tag: g.tag };
539
- g.dac.denied({ pid: g.pid, uid: g.cred.euid, op, path, errno: errno2, ...tag });
539
+ g.dac.denied({ pid: g.pid, uid: g.cred.euid, op, path, errno: errno3, ...tag });
540
540
  }
541
541
  var TTY_MODE = 400;
542
542
  function ttyOpenable(g, tty) {
@@ -1249,7 +1249,7 @@ var WASI_SIGNAL_TO_POSIX = Object.fromEntries(
1249
1249
 
1250
1250
  // src/process/wasi-errno.ts
1251
1251
  var WASI_ERRNO = {
1252
- ...Object.fromEntries(Object.entries(E).map(([name2, errno2]) => [`E${name2}`, errno2])),
1252
+ ...Object.fromEntries(Object.entries(E).map(([name2, errno3]) => [`E${name2}`, errno3])),
1253
1253
  EWOULDBLOCK: E.AGAIN,
1254
1254
  ENOTSUP: 138,
1255
1255
  EOPNOTSUPP: 138,
@@ -1489,7 +1489,7 @@ function dialError(e, timedOut, closed) {
1489
1489
  if (timedOut) return new KernelError("ETIMEDOUT");
1490
1490
  if (closed) return new KernelError("ECONNABORTED");
1491
1491
  const code = e?.code;
1492
- const known = DIAL_ERRORS.find((errno2) => errno2 === code);
1492
+ const known = DIAL_ERRORS.find((errno3) => errno3 === code);
1493
1493
  return new KernelError(known ?? "EHOSTUNREACH");
1494
1494
  }
1495
1495
  function isLoopback(host) {
@@ -4102,6 +4102,7 @@ var S_IFDIR = 16384;
4102
4102
  var S_IFREG = 32768;
4103
4103
  var S_IFLNK = 40960;
4104
4104
  var S_IFSOCK = 49152;
4105
+ var S_IFIFO = 4096;
4105
4106
  var PERM_MASK = 4095;
4106
4107
  var S_ISGID3 = 1024;
4107
4108
  var READ_ATTEMPTS = 3;
@@ -4381,7 +4382,10 @@ var OpfsFs = class {
4381
4382
  }
4382
4383
  async stampNew(path, owner, directory) {
4383
4384
  const owned4 = await this.newFields(path, owner, directory);
4384
- const fields = owner?.socket && !directory ? { ...owned4, socket: true } : owned4;
4385
+ if (owner?.socket && owner.fifo) throw new Error("a new node is a socket or a FIFO, not both");
4386
+ const kind = directory ? void 0 : owner?.socket ? "socket" : owner?.fifo ? "fifo" : void 0;
4387
+ const unique = kind === "fifo" ? { ino: inodeOf(`${path}\0${crypto.randomUUID()}`) } : {};
4388
+ const fields = kind ? { ...owned4, ...unique, [kind]: true } : owned4;
4385
4389
  if (fields) await this.meta.update(path, (entry) => ({ ...entry, path, ...fields }));
4386
4390
  }
4387
4391
  guarded = [];
@@ -4623,7 +4627,7 @@ var OpfsFs = class {
4623
4627
  }
4624
4628
  mode(path, directory, meta) {
4625
4629
  const fallback = directory || EXECUTABLE.test(path) ? 493 : 420;
4626
- const type = directory ? S_IFDIR : meta?.socket ? S_IFSOCK : S_IFREG;
4630
+ const type = directory ? S_IFDIR : meta?.socket ? S_IFSOCK : meta?.fifo ? S_IFIFO : S_IFREG;
4627
4631
  return type | (meta?.mode ?? fallback);
4628
4632
  }
4629
4633
  id = crypto.randomUUID();
@@ -4724,11 +4728,13 @@ var OpfsFs = class {
4724
4728
  const kept = meta?.mtimeMs !== void 0 && meta.mtimeFor === modified ? meta.mtimeMs : modified;
4725
4729
  const mtime = touched ?? kept;
4726
4730
  const socket = !directory && meta?.socket === true;
4731
+ const fifo = !directory && meta?.fifo === true;
4727
4732
  return {
4728
- isFile: !directory && !socket,
4733
+ isFile: !directory && !socket && !fifo,
4729
4734
  isDirectory: directory,
4730
4735
  isSymbolicLink: false,
4731
4736
  ...socket ? { isSocket: true } : {},
4737
+ ...fifo ? { isFifo: true } : {},
4732
4738
  size: file?.size ?? 0,
4733
4739
  mode: this.mode(path, directory, meta),
4734
4740
  mtime: new Date(mtime),
@@ -6539,7 +6545,7 @@ function satisfies(version, range2) {
6539
6545
  }
6540
6546
 
6541
6547
  // src/version.ts
6542
- var KERNEL_VERSION = true ? "1.114.0" : "0.0.0-dev";
6548
+ var KERNEL_VERSION = true ? "1.115.0" : "0.0.0-dev";
6543
6549
  var OS_RELEASE = "6.0.0-slicc";
6544
6550
  function procVersion() {
6545
6551
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -9542,6 +9548,139 @@ var TicketBook = class {
9542
9548
  }
9543
9549
  };
9544
9550
 
9551
+ // src/kernel/fifo.ts
9552
+ function errno(e) {
9553
+ return e instanceof KernelError ? e : new KernelError(e.code ?? "EIO");
9554
+ }
9555
+ var FifoTable = class {
9556
+ fifos = /* @__PURE__ */ new Map();
9557
+ size() {
9558
+ return this.fifos.size;
9559
+ }
9560
+ async open(key, path, access2, nonblock, signal) {
9561
+ const fifo = this.entry(key);
9562
+ if (access2 === "write" && nonblock && fifo.readers === 0) {
9563
+ this.drop(key, fifo);
9564
+ throw new KernelError("ENXIO");
9565
+ }
9566
+ const reads = access2 !== "write";
9567
+ const writes = access2 !== "read";
9568
+ const seen = { readOpens: fifo.readOpens, writeOpens: fifo.writeOpens };
9569
+ if (reads) this.count(fifo, "readers", 1);
9570
+ if (writes) this.count(fifo, "writers", 1);
9571
+ this.notify(fifo);
9572
+ try {
9573
+ if (!nonblock && access2 === "read") {
9574
+ while (fifo.writers === 0 && fifo.writeOpens === seen.writeOpens) {
9575
+ await this.changed(fifo, signal);
9576
+ }
9577
+ }
9578
+ if (!nonblock && access2 === "write") {
9579
+ while (fifo.readers === 0 && fifo.readOpens === seen.readOpens) {
9580
+ await this.changed(fifo, signal);
9581
+ }
9582
+ }
9583
+ } catch (e) {
9584
+ this.release(key, fifo, reads, writes);
9585
+ throw errno(e);
9586
+ }
9587
+ return this.end(key, path, fifo, reads, writes);
9588
+ }
9589
+ entry(key) {
9590
+ let fifo = this.fifos.get(key);
9591
+ if (!fifo) {
9592
+ fifo = {
9593
+ pipe: new KernelPipe(),
9594
+ readers: 0,
9595
+ writers: 0,
9596
+ readOpens: 0,
9597
+ writeOpens: 0,
9598
+ waiters: []
9599
+ };
9600
+ this.fifos.set(key, fifo);
9601
+ }
9602
+ return fifo;
9603
+ }
9604
+ count(fifo, side, by) {
9605
+ fifo[side] += by;
9606
+ if (side === "readers") {
9607
+ if (by > 0) {
9608
+ fifo.readOpens += 1;
9609
+ fifo.pipe.openRead();
9610
+ } else fifo.pipe.closeRead();
9611
+ } else if (by > 0) {
9612
+ fifo.writeOpens += 1;
9613
+ fifo.pipe.openWrite();
9614
+ } else fifo.pipe.closeWrite();
9615
+ }
9616
+ notify(fifo) {
9617
+ const waiters = fifo.waiters;
9618
+ fifo.waiters = [];
9619
+ for (const wake of waiters) wake();
9620
+ }
9621
+ changed(fifo, signal) {
9622
+ if (signal.aborted) return Promise.reject(new KernelError("EINTR"));
9623
+ return new Promise((resolve2, reject) => {
9624
+ const onAbort = () => {
9625
+ fifo.waiters = fifo.waiters.filter((w) => w !== wake);
9626
+ reject(new KernelError("EINTR"));
9627
+ };
9628
+ const wake = () => {
9629
+ signal.removeEventListener("abort", onAbort);
9630
+ resolve2();
9631
+ };
9632
+ fifo.waiters.push(wake);
9633
+ signal.addEventListener("abort", onAbort, { once: true });
9634
+ });
9635
+ }
9636
+ release(key, fifo, reads, writes) {
9637
+ if (reads) this.count(fifo, "readers", -1);
9638
+ if (writes) this.count(fifo, "writers", -1);
9639
+ this.notify(fifo);
9640
+ this.drop(key, fifo);
9641
+ }
9642
+ drop(key, fifo) {
9643
+ const idle = fifo.readers === 0 && fifo.writers === 0 && fifo.waiters.length === 0;
9644
+ if (idle && this.fifos.get(key) === fifo) this.fifos.delete(key);
9645
+ }
9646
+ end(key, path, fifo, reads, writes) {
9647
+ const { pipe } = fifo;
9648
+ let open = true;
9649
+ return new OpenFile({
9650
+ fifo: path,
9651
+ ...reads ? {
9652
+ read: async (max, signal) => {
9653
+ try {
9654
+ return await pipe.read(max, signal);
9655
+ } catch (e) {
9656
+ throw errno(e);
9657
+ }
9658
+ }
9659
+ } : {},
9660
+ ...writes ? {
9661
+ write: async (bytes, signal) => {
9662
+ try {
9663
+ return await pipe.write(bytes, signal);
9664
+ } catch (e) {
9665
+ throw errno(e);
9666
+ }
9667
+ }
9668
+ } : {},
9669
+ close: () => {
9670
+ if (!open) return;
9671
+ open = false;
9672
+ this.release(key, fifo, reads, writes);
9673
+ },
9674
+ poll: () => ({
9675
+ readable: reads && pipe.readReady,
9676
+ writable: writes && pipe.writeReady,
9677
+ hangup: reads ? pipe.writersGone : pipe.readersGone
9678
+ }),
9679
+ changed: (signal) => pipe.changed(signal)
9680
+ });
9681
+ }
9682
+ };
9683
+
9545
9684
  // src/mount/protocol.ts
9546
9685
  var DRIVER_PROTOCOL = [1, 2];
9547
9686
  function driverVersionError(theirs) {
@@ -10402,6 +10541,7 @@ var MountFs = class _MountFs {
10402
10541
  }
10403
10542
  const { mount, rel: rel2 } = found;
10404
10543
  this.writable(mount, real);
10544
+ if (owner?.fifo) throw errnoError("EPERM", `${real}: this mount has no FIFOs`);
10405
10545
  const bytes = typeof content === "string" ? new TextEncoder().encode(content) : content;
10406
10546
  if (mount.maxFile > 0 && bytes.length > mount.maxFile) {
10407
10547
  throw errnoError(
@@ -11007,6 +11147,7 @@ var SYNC_FS_OPS = [
11007
11147
  "statfs",
11008
11148
  "hold",
11009
11149
  "create",
11150
+ "mkfifo",
11010
11151
  "kept",
11011
11152
  "pread",
11012
11153
  "pwrite",
@@ -11039,6 +11180,7 @@ function statJson(s) {
11039
11180
  isFile: s.isFile,
11040
11181
  isSymbolicLink: s.isSymbolicLink,
11041
11182
  ...s.isSocket ? { isSocket: true } : {},
11183
+ ...s.isFifo ? { isFifo: true } : {},
11042
11184
  size: s.size,
11043
11185
  mode: s.mode,
11044
11186
  mtimeMs: s.mtime.getTime(),
@@ -11188,6 +11330,12 @@ async function run(entry, path, req) {
11188
11330
  case "symlink":
11189
11331
  await fs.symlink(req.arg2 ?? "", path, ownerFor2(entry));
11190
11332
  return done;
11333
+ case "mkfifo": {
11334
+ const owner = ownerFor2(entry, req.mode ?? 438) ?? { uid: 0, gid: 0 };
11335
+ await createExclusive(fs, path, { ...owner, fifo: true });
11336
+ entry.fresh?.(path);
11337
+ return done;
11338
+ }
11191
11339
  case "create":
11192
11340
  await createExclusive(fs, path, ownerFor2(entry, req.mode ?? 438));
11193
11341
  if (req.opening) entry.created?.add(path);
@@ -11266,9 +11414,10 @@ async function guard(g, path, req, cwd) {
11266
11414
  return { path: await walkSafe(g, path, false) };
11267
11415
  }
11268
11416
  case "create":
11417
+ case "mkfifo":
11269
11418
  case "symlink":
11270
11419
  await inParent(g, op, path);
11271
- return { path: await walkSafe(g, path, op === "create") };
11420
+ return { path: await walkSafe(g, path, op !== "symlink") };
11272
11421
  case "unlink":
11273
11422
  case "rmdir": {
11274
11423
  await inParent(g, op, path, true);
@@ -11356,6 +11505,7 @@ async function accessOp(entry, path, req) {
11356
11505
  var CHANGING = /* @__PURE__ */ new Set([
11357
11506
  "mkdir",
11358
11507
  "create",
11508
+ "mkfifo",
11359
11509
  "symlink",
11360
11510
  "unlink",
11361
11511
  "rmdir",
@@ -11550,7 +11700,13 @@ async function guardAndResolve(entry, path, req) {
11550
11700
  };
11551
11701
  }
11552
11702
  var REMOVALS = /* @__PURE__ */ new Set(["unlink", "rmdir", "rm"]);
11553
- var CREATIONS = /* @__PURE__ */ new Set(["write", "mkdir", "symlink", "create"]);
11703
+ var CREATIONS = /* @__PURE__ */ new Set([
11704
+ "write",
11705
+ "mkdir",
11706
+ "symlink",
11707
+ "create",
11708
+ "mkfifo"
11709
+ ]);
11554
11710
  var NAMING = /* @__PURE__ */ new Set(["link", "rename"]);
11555
11711
  async function newDevName(entry, path, req) {
11556
11712
  const named = NAMING.has(req.op);
@@ -13297,16 +13453,16 @@ var TOKEN3 = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
13297
13453
  var SAFE_VALUE = /^[^\r\n\0]*$/;
13298
13454
  var CLOSE_WAIT_MS3 = 5e3;
13299
13455
  var MAX_UNREAD = 16 * 1024 * 1024;
13300
- function errno(code, message3) {
13456
+ function errno2(code, message3) {
13301
13457
  return Object.assign(new Error(`${code}: ${message3}`), { code });
13302
13458
  }
13303
13459
  function requestHead(method, url, headers, extra, first = []) {
13304
- if (!TOKEN3.test(method)) throw errno("EINVAL", `method ${method}`);
13460
+ if (!TOKEN3.test(method)) throw errno2("EINVAL", `method ${method}`);
13305
13461
  const lines2 = [`${method} ${url.pathname}${url.search} HTTP/1.1`, `host: ${url.host}`];
13306
13462
  for (const [name2, value2] of first) lines2.push(`${name2}: ${value2}`);
13307
13463
  for (const [name2, value2] of headers) {
13308
13464
  if (OWN_HEADERS.has(name2.toLowerCase())) continue;
13309
- if (!TOKEN3.test(name2) || !SAFE_VALUE.test(value2)) throw errno("EINVAL", `header ${name2}`);
13465
+ if (!TOKEN3.test(name2) || !SAFE_VALUE.test(value2)) throw errno2("EINVAL", `header ${name2}`);
13310
13466
  lines2.push(`${name2}: ${value2}`);
13311
13467
  }
13312
13468
  for (const [name2, value2] of extra) lines2.push(`${name2}: ${value2}`);
@@ -13317,7 +13473,7 @@ function requestHead(method, url, headers, extra, first = []) {
13317
13473
  function parseHead(bytes) {
13318
13474
  const [statusLine = "", ...lines2] = latin1(bytes).split(/\r?\n/);
13319
13475
  const match = /^HTTP\/1\.[01] (\d{3})(?: (.*))?$/.exec(statusLine);
13320
- if (!match) throw errno("EPROTO", `not an HTTP/1.x response: ${statusLine.slice(0, 80)}`);
13476
+ if (!match) throw errno2("EPROTO", `not an HTTP/1.x response: ${statusLine.slice(0, 80)}`);
13321
13477
  const headers = [];
13322
13478
  for (const line of lines2) {
13323
13479
  const colon = line.indexOf(":");
@@ -13332,9 +13488,9 @@ async function readHead(incoming, signal) {
13332
13488
  raw = await incoming.head(MAX_HEAD2, signal);
13333
13489
  } catch (err) {
13334
13490
  if (err instanceof KernelError) throw err;
13335
- throw errno("EPROTO", "the response head is malformed or too large");
13491
+ throw errno2("EPROTO", "the response head is malformed or too large");
13336
13492
  }
13337
- if (!raw) throw errno("ECONNRESET", "the connection closed before a response");
13493
+ if (!raw) throw errno2("ECONNRESET", "the connection closed before a response");
13338
13494
  const head = parseHead(raw);
13339
13495
  if (head.status < 100 || head.status >= 200 || head.status === 101) return head;
13340
13496
  }
@@ -13343,20 +13499,20 @@ async function* chunked(incoming, signal) {
13343
13499
  for (; ; ) {
13344
13500
  const line = await incoming.line(4096, signal);
13345
13501
  const size = /^([0-9A-Fa-f]{1,12})[ \t]*(;.*)?$/.exec(line);
13346
- if (!size) throw errno("EPROTO", "a malformed chunk size");
13502
+ if (!size) throw errno2("EPROTO", "a malformed chunk size");
13347
13503
  const n = Number.parseInt(size[1], 16);
13348
13504
  if (n === 0) {
13349
13505
  while (await incoming.line(MAX_HEAD2, signal) !== "") ;
13350
13506
  return;
13351
13507
  }
13352
13508
  yield await incoming.exactly(n, signal);
13353
- if (await incoming.line(2, signal) !== "") throw errno("EPROTO", "a malformed chunk");
13509
+ if (await incoming.line(2, signal) !== "") throw errno2("EPROTO", "a malformed chunk");
13354
13510
  }
13355
13511
  }
13356
13512
  async function* counted(incoming, length2, signal) {
13357
13513
  for (let left = length2; left > 0; ) {
13358
13514
  const data = await incoming.some(Math.min(left, 64 * 1024), signal);
13359
- if (data.length === 0) throw errno("EPROTO", "the body ended early");
13515
+ if (data.length === 0) throw errno2("EPROTO", "the body ended early");
13360
13516
  left -= data.length;
13361
13517
  yield data;
13362
13518
  }
@@ -13377,7 +13533,7 @@ function bodyOf(incoming, head, method, signal) {
13377
13533
  if (lengths.length === 0) return untilClose(incoming, signal);
13378
13534
  const length2 = lengths[0]?.trim() ?? "";
13379
13535
  if (!/^\d{1,15}$/.test(length2) || lengths.some((l) => l.trim() !== length2)) {
13380
- throw errno("EPROTO", `a malformed Content-Length: ${lengths.join(", ")}`);
13536
+ throw errno2("EPROTO", `a malformed Content-Length: ${lengths.join(", ")}`);
13381
13537
  }
13382
13538
  return counted(incoming, Number(length2), signal);
13383
13539
  }
@@ -13395,7 +13551,7 @@ var KernelLoopback = class {
13395
13551
  }
13396
13552
  async connect(url, port, signal) {
13397
13553
  if (url.protocol === "https:" || url.protocol === "wss:") {
13398
- throw errno("ENOTSUP", `TLS to the kernel's loopback is not supported: ${url.origin}`);
13554
+ throw errno2("ENOTSUP", `TLS to the kernel's loopback is not supported: ${url.origin}`);
13399
13555
  }
13400
13556
  signal.throwIfAborted();
13401
13557
  const socket = this.net.socket("inet");
@@ -13410,7 +13566,7 @@ var KernelLoopback = class {
13410
13566
  } catch (err) {
13411
13567
  socket.close();
13412
13568
  const refused2 = err instanceof KernelError && err.code === "ECONNREFUSED";
13413
- throw refused2 ? errno("ECONNREFUSED", `nothing listens on the kernel's port ${port}`) : err;
13569
+ throw refused2 ? errno2("ECONNREFUSED", `nothing listens on the kernel's port ${port}`) : err;
13414
13570
  }
13415
13571
  signal.addEventListener("abort", () => socket.close(), { once: true });
13416
13572
  return socket;
@@ -13456,7 +13612,7 @@ var KernelLoopback = class {
13456
13612
  const incoming = new Incoming(socket);
13457
13613
  const head = await readHead(incoming, req.signal);
13458
13614
  if (head.status !== 101) {
13459
- throw errno(
13615
+ throw errno2(
13460
13616
  "EPROTO",
13461
13617
  `the server answered the upgrade with ${head.status}${head.statusText ? ` ${head.statusText}` : ""}`
13462
13618
  );
@@ -13464,10 +13620,10 @@ var KernelLoopback = class {
13464
13620
  const upgraded = fieldTokens(head.headers, "upgrade").includes("websocket") && fieldTokens(head.headers, "connection").includes("upgrade");
13465
13621
  const accept2 = fieldValues(head.headers, "sec-websocket-accept")[0];
13466
13622
  if (!upgraded || accept2 !== await acceptFor(key)) {
13467
- throw errno("EPROTO", "the server did not accept the WebSocket key");
13623
+ throw errno2("EPROTO", "the server did not accept the WebSocket key");
13468
13624
  }
13469
13625
  if (fieldValues(head.headers, "sec-websocket-extensions").length > 0) {
13470
- throw errno("EPROTO", "the server offered an unsolicited extension");
13626
+ throw errno2("EPROTO", "the server offered an unsolicited extension");
13471
13627
  }
13472
13628
  const protocol = fieldValues(head.headers, "sec-websocket-protocol")[0] ?? "";
13473
13629
  return new LoopbackWebSocket(socket, incoming, protocol);
@@ -13485,7 +13641,7 @@ async function* closing(chunks2, socket) {
13485
13641
  yield* chunks2;
13486
13642
  } catch (err) {
13487
13643
  if (typeof err?.code === "string") throw err;
13488
- throw errno("EPROTO", err instanceof Error ? err.message : String(err));
13644
+ throw errno2("EPROTO", err instanceof Error ? err.message : String(err));
13489
13645
  } finally {
13490
13646
  socket.close();
13491
13647
  }
@@ -13614,7 +13770,7 @@ var LoopbackWebSocket = class {
13614
13770
  this.write(clientFrame(OP_CLOSE, payload));
13615
13771
  }
13616
13772
  send(data) {
13617
- if (this.sentClose) throw errno("EPIPE", "the websocket is closing");
13773
+ if (this.sentClose) throw errno2("EPIPE", "the websocket is closing");
13618
13774
  const text = typeof data === "string";
13619
13775
  const payload = text ? new TextEncoder().encode(data) : data;
13620
13776
  this.write(clientFrame(text ? OP_TEXT : OP_BINARY, payload));
@@ -14306,8 +14462,8 @@ function errnoOf(e) {
14306
14462
  const code = e?.code;
14307
14463
  return typeof code === "string" && ERRNO.test(code) ? code : "ECONNREFUSED";
14308
14464
  }
14309
- function fail(errno2, text) {
14310
- return { ok: false, errno: errno2, message: text };
14465
+ function fail(errno3, text) {
14466
+ return { ok: false, errno: errno3, message: text };
14311
14467
  }
14312
14468
  var WsHandles = class {
14313
14469
  transport;
@@ -14581,8 +14737,8 @@ var HttpHandles = class {
14581
14737
  const status = e.status;
14582
14738
  if (text === NO_TRANSPORT || typeof status !== "number" || status === 502) {
14583
14739
  const code = codeOf2(e);
14584
- const errno2 = text === NO_TRANSPORT ? "ENETUNREACH" : code !== "EIO" ? code : "ECONNREFUSED";
14585
- return { ok: false, errno: errno2, message: text };
14740
+ const errno3 = text === NO_TRANSPORT ? "ENETUNREACH" : code !== "EIO" ? code : "ECONNREFUSED";
14741
+ return { ok: false, errno: errno3, message: text };
14586
14742
  }
14587
14743
  entry.body = once(new TextEncoder().encode(text))[Symbol.asyncIterator]();
14588
14744
  return this.headOf(handle, req.url, {
@@ -15677,7 +15833,7 @@ var UNREACHABLE = ["EACCES", "ENETUNREACH", "EHOSTUNREACH"];
15677
15833
  function sendError(e) {
15678
15834
  if (e instanceof KernelError) return e;
15679
15835
  const code = e?.code;
15680
- return new KernelError(SEND_ERRORS.find((errno2) => errno2 === code) ?? "EHOSTUNREACH");
15836
+ return new KernelError(SEND_ERRORS.find((errno3) => errno3 === code) ?? "EHOSTUNREACH");
15681
15837
  }
15682
15838
  function sameAddr(a, b) {
15683
15839
  return a.port === b.port && canonicalHost(a.host) === canonicalHost(b.host);
@@ -15806,7 +15962,7 @@ var KernelDgram = class {
15806
15962
  }
15807
15963
  unreachable(error, from) {
15808
15964
  if (!this.peer || !sameAddr(this.peer, from)) return;
15809
- this.pending = UNREACHABLE.find((errno2) => errno2 === error) ?? "EHOSTUNREACH";
15965
+ this.pending = UNREACHABLE.find((errno3) => errno3 === error) ?? "EHOSTUNREACH";
15810
15966
  this.changes.wake();
15811
15967
  }
15812
15968
  deliver(datagram2) {
@@ -17138,6 +17294,7 @@ function isWasmSyscall(req) {
17138
17294
  return typeof op === "string" && SYSCALL_OPS.has(op);
17139
17295
  }
17140
17296
  var MAX_READ = 1024 * 1024;
17297
+ var O_NONBLOCK = 2048;
17141
17298
  var WRITE_ACCESS = 3;
17142
17299
  var KEYBOARD = /* @__PURE__ */ new Set([SIG.INT, SIG.QUIT, SIG.TSTP]);
17143
17300
  var DEFAULT_UMASK2 = 18;
@@ -17635,7 +17792,7 @@ var WasmProcess = class {
17635
17792
  this.options.hasPending?.() ? AbortSignal.abort() : this.cancelSignal(cancelled)
17636
17793
  );
17637
17794
  }
17638
- async openVfs(req) {
17795
+ async openVfs(req, cancelled) {
17639
17796
  if (inProc(req.path)) return this.openProc(req, req.path);
17640
17797
  const device = req.orphan ? void 0 : deviceAt(req.path);
17641
17798
  if (device) return this.openDevice(req, device);
@@ -17646,6 +17803,10 @@ var WasmProcess = class {
17646
17803
  await refuseReadonly(this.options.fs, req.path, req.flags, req);
17647
17804
  if (this.writesAt(req)) await this.options.fs.mayChange?.(req.path, !req.exclusive);
17648
17805
  await this.mayOpen(req);
17806
+ if (req.fifo && !req.exclusive) {
17807
+ const opened2 = await this.openFifo(req, cancelled);
17808
+ if (opened2 !== void 0) return opened2;
17809
+ }
17649
17810
  const marked = await this.markedPath(req);
17650
17811
  await this.sourceOpen(marked === void 0 ? req : { ...req, path: marked });
17651
17812
  const fs = marked === void 0 ? this.options.fs : this.options.noLinks;
@@ -17687,6 +17848,19 @@ var WasmProcess = class {
17687
17848
  }
17688
17849
  return fd;
17689
17850
  }
17851
+ async openFifo(req, cancelled) {
17852
+ const fifos = this.options.fifos;
17853
+ const path = await this.nodes.targetKey(req.path);
17854
+ const st = await this.heldFs().stat(path);
17855
+ if (!st.isFifo) return void 0;
17856
+ if (!fifos) throw new KernelError("ENXIO");
17857
+ const access2 = openAccess(req.flags);
17858
+ const nonblock = (req.flags & O_NONBLOCK) !== 0;
17859
+ const blocks = !nonblock && access2 !== "both";
17860
+ const signal = blocks ? this.blockingSignal(cancelled) : cancelled;
17861
+ const end = await fifos.open(`${st.dev ?? 0}:${st.ino}`, path, access2, nonblock, signal);
17862
+ return this.fds.install(end, 3);
17863
+ }
17690
17864
  openDevice(req, device) {
17691
17865
  if (req.exclusive) throw Object.assign(new Error(req.path), { code: "EEXIST" });
17692
17866
  const access2 = req.flags & WRITE_ACCESS;
@@ -17886,7 +18060,7 @@ var WasmProcess = class {
17886
18060
  case "fd-poll":
17887
18061
  return { ok: true, kind: "json", json: pollFile(this.fds.get(req.fd).file) };
17888
18062
  case "fd-open-vfs":
17889
- return { ok: true, kind: "json", json: await this.openVfs(req) };
18063
+ return { ok: true, kind: "json", json: await this.openVfs(req, cancelled) };
17890
18064
  case "fd-info":
17891
18065
  return { ok: true, kind: "json", json: this.fdInfo(req.fd) };
17892
18066
  case "fd-list":
@@ -18546,7 +18720,8 @@ function inheritedFds(fds) {
18546
18720
  ...kind === "device" && meta && "device" in meta ? { device: meta } : {},
18547
18721
  ...flags2 !== void 0 ? { flags: flags2 } : {},
18548
18722
  ...fds.closesOnExec(fd) ? { cloexec: true } : {},
18549
- ...kind === "stream" ? { desc: descId(open) } : {}
18723
+ ...kind === "stream" ? { desc: descId(open) } : {},
18724
+ ...open.file.fifo ? { fifo: open.file.fifo } : {}
18550
18725
  };
18551
18726
  });
18552
18727
  }
@@ -18752,6 +18927,7 @@ function processOptions(opts, header4, hooks, created3) {
18752
18927
  net: opts.net,
18753
18928
  http: opts.http,
18754
18929
  locks: opts.locks,
18930
+ fifos: opts.fifos,
18755
18931
  ...opts.sems ? { sems: opts.sems } : {},
18756
18932
  onReap: opts.onReap,
18757
18933
  resolver: opts.resolver,
@@ -20690,9 +20866,9 @@ var HostfsClient = class {
20690
20866
  throw fsError2("ESTALE", "the folder was granted again, so its open files are gone");
20691
20867
  return this.send(path, init, false, true);
20692
20868
  }
20693
- const errno2 = response.headers.get("X-Hostfs-Errno") ?? "EIO";
20869
+ const errno3 = response.headers.get("X-Hostfs-Errno") ?? "EIO";
20694
20870
  const body = await response.json().catch(() => ({}));
20695
- throw fsError2(errno2, typeof body.message === "string" ? body.message : errno2);
20871
+ throw fsError2(errno3, typeof body.message === "string" ? body.message : errno3);
20696
20872
  }
20697
20873
  async call(op, body = {}, handle = false) {
20698
20874
  const response = await this.send(
@@ -21849,8 +22025,8 @@ var RULE = new RegExp(
21849
22025
  var TERM = /^[A-Za-z0-9._+-]+$/;
21850
22026
  var PLAIN = /^[A-Za-z0-9_@%+=:,./-]+$/;
21851
22027
  var USAGE = "usage: sudo [-n] [-u user] [--] command [args...]\n sudo -l";
21852
- function failed2(errno2, error) {
21853
- return { error, errno: errno2 };
22028
+ function failed2(errno3, error) {
22029
+ return { error, errno: errno3 };
21854
22030
  }
21855
22031
  function unescaped(double) {
21856
22032
  return double.replace(/\\(["\\$`])/g, "$1");
@@ -22507,6 +22683,7 @@ var Launcher = class {
22507
22683
  sudoer;
22508
22684
  jobs = new JobTable();
22509
22685
  locks = new LockTable();
22686
+ fifos = new FifoTable();
22510
22687
  sems = new SemTable();
22511
22688
  settling = new SettlingChildren((pid) => this.jobs.pgidOf(pid));
22512
22689
  ptys = new PtyTable(
@@ -23504,6 +23681,7 @@ var Launcher = class {
23504
23681
  net: this.net,
23505
23682
  http: new HttpHandles(this.transport, pid, this.loopbackFor(pid)),
23506
23683
  locks: this.locks,
23684
+ fifos: this.fifos,
23507
23685
  sems: this.sems,
23508
23686
  resolver: this.resolver,
23509
23687
  onReap: (child) => this.reaped(child, pid),