@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.
@@ -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),
@@ -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, errno2 = "EACCES") {
3314
- return fsError(errno2, path);
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, errno2 = "EACCES") {
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: errno2, ...tag });
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, errno2]) => [`E${name2}`, errno2])),
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((errno2) => errno2 === code);
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.114.0" : "0.0.0-dev";
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 === "create") };
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(["write", "mkdir", "symlink", "create"]);
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 errno(code, message3) {
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 errno("EINVAL", `method ${method}`);
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 errno("EINVAL", `header ${name2}`);
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 errno("EPROTO", `not an HTTP/1.x response: ${statusLine.slice(0, 80)}`);
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 errno("EPROTO", "the response head is malformed or too large");
13395
+ throw errno2("EPROTO", "the response head is malformed or too large");
13240
13396
  }
13241
- if (!raw) throw errno("ECONNRESET", "the connection closed before a response");
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 errno("EPROTO", "a malformed chunk size");
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 errno("EPROTO", "a malformed chunk");
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 errno("EPROTO", "the body ended early");
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 errno("EPROTO", `a malformed Content-Length: ${lengths.join(", ")}`);
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 errno("ENOTSUP", `TLS to the kernel's loopback is not supported: ${url.origin}`);
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 ? errno("ECONNREFUSED", `nothing listens on the kernel's port ${port}`) : err;
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 errno(
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 errno("EPROTO", "the server did not accept the WebSocket key");
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 errno("EPROTO", "the server offered an unsolicited extension");
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 errno("EPROTO", err instanceof Error ? err.message : String(err));
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 errno("EPIPE", "the websocket is closing");
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(errno2, text) {
14262
- return { ok: false, errno: errno2, message: text };
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 errno2 = text === NO_TRANSPORT ? "ENETUNREACH" : code !== "EIO" ? code : "ECONNREFUSED";
14537
- return { ok: false, errno: errno2, message: text };
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((errno2) => errno2 === code) ?? "EHOSTUNREACH");
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((errno2) => errno2 === error) ?? "EHOSTUNREACH";
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 errno2 = response.headers.get("X-Hostfs-Errno") ?? "EIO";
20931
+ const errno3 = response.headers.get("X-Hostfs-Errno") ?? "EIO";
20756
20932
  const body = await response.json().catch(() => ({}));
20757
- throw fsError2(errno2, typeof body.message === "string" ? body.message : errno2);
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(errno2, error) {
21843
- return { error, errno: errno2 };
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),