@ai-ecoverse/slicc-kernel 1.51.0 → 1.52.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.
@@ -4770,6 +4770,10 @@ function kernelEntry2() {
4770
4770
  function deviceEntry(meta) {
4771
4771
  return { type: "device", device: meta.device, ...meta.access ? { access: meta.access } : {} };
4772
4772
  }
4773
+ function refuseWrite(s, oflags, rights) {
4774
+ const writes = (rights & RIGHTS.FD_WRITE) !== 0n || (oflags & OFLAGS.TRUNC) !== 0;
4775
+ if (s?.readonly && writes) throw new WasiError("EROFS");
4776
+ }
4773
4777
  function preopenOf(e) {
4774
4778
  return {
4775
4779
  ...e.preopen ? { preopen: e.preopen } : {},
@@ -5237,6 +5241,7 @@ var init_wasi_fds = __esm({
5237
5241
  return this.install({ type: "dir", path });
5238
5242
  }
5239
5243
  if (!s && !(oflags & OFLAGS.CREAT)) throw new WasiError("ENOENT");
5244
+ refuseWrite(s, oflags, rights);
5240
5245
  if (this.shared) return this.kernelFile(path, s, oflags, rights, fdflags);
5241
5246
  return this.install({ type: "file", file: this.file(path, s, oflags, rights, fdflags) });
5242
5247
  }
@@ -6748,6 +6753,191 @@ var init_wasi_module = __esm({
6748
6753
  }
6749
6754
  });
6750
6755
 
6756
+ // src/process/wasi/wasi-procfs.ts
6757
+ function inProc(path) {
6758
+ return path === "/proc" || path.startsWith("/proc/");
6759
+ }
6760
+ function procfsBridge(fs, tree) {
6761
+ const over = {
6762
+ readFile: (p) => inProc(p) ? tree.read(p) : fs.readFile(p),
6763
+ stat: (p) => inProc(p) ? tree.stat(p) : fs.stat(p),
6764
+ lstat: (p) => inProc(p) ? tree.stat(p, false) : fs.lstat(p),
6765
+ readdir: (p) => {
6766
+ if (inProc(p)) return tree.readdir(p);
6767
+ const names = fs.readdir(p);
6768
+ return p === "/" && !names.includes("proc") ? [...names, "proc"] : names;
6769
+ },
6770
+ exists: (p) => inProc(p) ? tree.exists(p) : fs.exists(p),
6771
+ readlink: (p) => inProc(p) ? tree.readlink(p) : fs.readlink(p),
6772
+ readdirStat: (p) => {
6773
+ if (!inProc(p)) {
6774
+ const listed = fs.readdirStat(p);
6775
+ if (p !== "/" || listed.some(([name2]) => name2 === "proc")) return listed;
6776
+ return [...listed, ["proc", tree.stat("/proc")]];
6777
+ }
6778
+ return tree.readdir(p).map((name2) => {
6779
+ try {
6780
+ return [name2, tree.stat(`${p}/${name2}`, false)];
6781
+ } catch {
6782
+ return [name2, null];
6783
+ }
6784
+ });
6785
+ },
6786
+ rename: (from, to) => {
6787
+ if (inProc(from) || inProc(to)) throw syncError("EROFS", from);
6788
+ fs.rename(from, to);
6789
+ },
6790
+ hold: (p, ...rest2) => inProc(p) ? void 0 : fs.hold?.(p, ...rest2),
6791
+ ...fs.pread ? {
6792
+ pread: (p, at, n, version) => inProc(p) ? tree.read(p).subarray(at, at + n) : fs.pread(p, at, n, version)
6793
+ } : {}
6794
+ };
6795
+ for (const name2 of READ_ONLY) {
6796
+ const fn = fs[name2];
6797
+ if (!fn) continue;
6798
+ over[name2] = (p, ...rest2) => {
6799
+ if (inProc(p)) throw syncError("EROFS", p);
6800
+ return fn.call(fs, p, ...rest2);
6801
+ };
6802
+ }
6803
+ return new Proxy(fs, {
6804
+ get: (target, key, receiver) => key in over ? over[key] : Reflect.get(target, key, receiver)
6805
+ });
6806
+ }
6807
+ var DIR_MODE3, FILE_MODE2, LINK_MODE3, PID_NAMES, SYSTEM_NAMES, ProcTree, READ_ONLY;
6808
+ var init_wasi_procfs = __esm({
6809
+ "src/process/wasi/wasi-procfs.ts"() {
6810
+ "use strict";
6811
+ init_sync_fs_wire();
6812
+ init_process_fds();
6813
+ init_procfs();
6814
+ DIR_MODE3 = 16749;
6815
+ FILE_MODE2 = 33060;
6816
+ LINK_MODE3 = 41471;
6817
+ PID_NAMES = PID_FILES;
6818
+ SYSTEM_NAMES = SYSTEM_FILES;
6819
+ ProcTree = class {
6820
+ source;
6821
+ pid;
6822
+ memory;
6823
+ constructor(source, pid, memory = memorySource()) {
6824
+ this.source = source;
6825
+ this.pid = pid;
6826
+ this.memory = memory;
6827
+ }
6828
+ listing() {
6829
+ return this.source.procList();
6830
+ }
6831
+ alive(pid) {
6832
+ return this.listing().processes.some((p) => p.pid === pid);
6833
+ }
6834
+ node(parts) {
6835
+ const [top, leaf, ...rest2] = parts;
6836
+ if (top === void 0) {
6837
+ return {
6838
+ kind: "dir",
6839
+ names: () => [
6840
+ ...SYSTEM_NAMES,
6841
+ "mounts",
6842
+ "self",
6843
+ ...this.listing().processes.map((p) => String(p.pid))
6844
+ ]
6845
+ };
6846
+ }
6847
+ if (top === "self") {
6848
+ return leaf === void 0 ? { kind: "link", target: String(this.pid) } : void 0;
6849
+ }
6850
+ if (leaf === void 0 && top === "mounts") {
6851
+ return { kind: "file", content: () => mountTable(this.source.mountList()) };
6852
+ }
6853
+ if (leaf === void 0 && SYSTEM_NAMES.includes(top)) {
6854
+ return {
6855
+ kind: "file",
6856
+ content: () => systemFile(top, this.listing(), Date.now(), this.memory)
6857
+ };
6858
+ }
6859
+ if (!/^[1-9]\d*$/.test(top) || rest2.length > 0 || !this.alive(Number(top))) return void 0;
6860
+ if (leaf === void 0) return { kind: "dir", names: () => [...PID_NAMES] };
6861
+ if (!PID_NAMES.includes(leaf)) return void 0;
6862
+ return {
6863
+ kind: "file",
6864
+ content: () => {
6865
+ const listing = this.listing();
6866
+ const info = listing.processes.find((p) => p.pid === Number(top));
6867
+ if (!info) throw syncError("ENOENT", `/proc/${top}/${leaf}`);
6868
+ return pidFile(leaf, info, listing.boot);
6869
+ }
6870
+ };
6871
+ }
6872
+ parts(path, follow2) {
6873
+ const parts = path.split("/").filter((p) => p !== "").slice(1);
6874
+ if (parts[0] === "self" && (follow2 || parts.length > 1)) parts[0] = String(this.pid);
6875
+ return parts;
6876
+ }
6877
+ find(path, follow2) {
6878
+ const node = this.node(this.parts(path, follow2));
6879
+ if (!node) throw syncError("ENOENT", path);
6880
+ return node;
6881
+ }
6882
+ stat(path, follow2 = true) {
6883
+ const node = this.find(path, follow2);
6884
+ const base = {
6885
+ isFile: false,
6886
+ isDirectory: false,
6887
+ size: 0,
6888
+ mtimeMs: Date.now(),
6889
+ readonly: true
6890
+ };
6891
+ if (node.kind === "dir") return { ...base, isDirectory: true, mode: DIR_MODE3 };
6892
+ if (node.kind === "link") {
6893
+ return { ...base, isSymbolicLink: true, mode: LINK_MODE3, size: node.target.length };
6894
+ }
6895
+ return { ...base, isFile: true, mode: FILE_MODE2, size: this.bytes(node).length };
6896
+ }
6897
+ bytes(node) {
6898
+ return new TextEncoder().encode(node.kind === "file" ? node.content() : "");
6899
+ }
6900
+ read(path) {
6901
+ const node = this.find(path, true);
6902
+ if (node.kind !== "file") throw syncError("EISDIR", path);
6903
+ return this.bytes(node);
6904
+ }
6905
+ readdir(path) {
6906
+ const node = this.find(path, true);
6907
+ if (node.kind !== "dir") throw syncError("ENOTDIR", path);
6908
+ return node.names();
6909
+ }
6910
+ readlink(path) {
6911
+ const node = this.find(path, false);
6912
+ if (node.kind !== "link") throw syncError("EINVAL", path);
6913
+ return node.target;
6914
+ }
6915
+ exists(path) {
6916
+ try {
6917
+ this.find(path, true);
6918
+ return true;
6919
+ } catch {
6920
+ return false;
6921
+ }
6922
+ }
6923
+ };
6924
+ READ_ONLY = [
6925
+ "writeFile",
6926
+ "mkdir",
6927
+ "rm",
6928
+ "unlink",
6929
+ "rmdir",
6930
+ "symlink",
6931
+ "chmod",
6932
+ "utimes",
6933
+ "lutimes",
6934
+ "create",
6935
+ "pwrite",
6936
+ "truncate"
6937
+ ];
6938
+ }
6939
+ });
6940
+
6751
6941
  // src/process/wasi/wasi-signals.ts
6752
6942
  var DELIVERED_MASK, KERNEL_DEFAULTS, LIBC_DEFAULT_EXIT, SA_RESTART, DISPOSITION_IGNORE, DISPOSITION_HANDLER, withBit, WASIX_LIBC_DEFAULT_LINE, WasiSignals;
6753
6943
  var init_wasi_signals = __esm({
@@ -8891,6 +9081,15 @@ async function instantiate(host, module, memory, threads, {
8891
9081
  }
8892
9082
  return { instance, driver };
8893
9083
  }
9084
+ function procTree(call2, pid) {
9085
+ return new ProcTree(
9086
+ {
9087
+ procList: () => call2({ op: "proc-list" }),
9088
+ mountList: () => call2({ op: "mount-list" })
9089
+ },
9090
+ pid
9091
+ );
9092
+ }
8894
9093
  function exportedTable(instance) {
8895
9094
  const table = instance.exports.__indirect_function_table;
8896
9095
  return table instanceof WebAssembly.Table ? table : void 0;
@@ -8962,7 +9161,10 @@ async function runWasiProcess(init, port2) {
8962
9161
  ppid: id.ppid,
8963
9162
  parent: () => identify(transport, init).ppid,
8964
9163
  kernel: { sys: traced(stats, "kernel", sys), call: call2 },
8965
- fs: cachingBridge(traced(stats, "fs", createSyncFsSabBridge(transport))),
9164
+ fs: procfsBridge(
9165
+ cachingBridge(traced(stats, "fs", createSyncFsSabBridge(transport))),
9166
+ procTree(call2, id.pid)
9167
+ ),
8966
9168
  ...descriptors(init, fork, threads)
8967
9169
  });
8968
9170
  if (threads) {
@@ -9053,7 +9255,7 @@ async function runWasiThread(init, port2) {
9053
9255
  ppid: id.ppid,
9054
9256
  parent: () => identify(transport, init).ppid,
9055
9257
  kernel: { sys, call: call2 },
9056
- fs: cachingBridge(createSyncFsSabBridge(transport)),
9258
+ fs: procfsBridge(cachingBridge(createSyncFsSabBridge(transport)), procTree(call2, id.pid)),
9057
9259
  shared: threads.ids
9058
9260
  });
9059
9261
  const program = await programImports(init.program, host, transport, thread.tid);
@@ -9108,6 +9310,7 @@ var init_wasi_runtime = __esm({
9108
9310
  init_wasi_host();
9109
9311
  init_wasi_imports();
9110
9312
  init_wasi_module();
9313
+ init_wasi_procfs();
9111
9314
  init_wasi_signals();
9112
9315
  init_wasi_stats();
9113
9316
  init_wasi_threads();
@@ -10370,10 +10573,25 @@ function ttyOps(kernel) {
10370
10573
  await kernel.call({ op: "tty-pgrp-set", fd, pgrp });
10371
10574
  }
10372
10575
  };
10576
+ const openOn = async (terminal, fd) => {
10577
+ const open = await kernel.json({ op: "fd-list" });
10578
+ const on = open.filter((entry) => entry.terminal === terminal);
10579
+ return (on.find((entry) => entry.fd === fd) ?? on[0])?.fd;
10580
+ };
10581
+ const reopened = async (terminal, termios) => {
10582
+ const fd = await kernel.json({ op: "fd-open-tty", name: terminal });
10583
+ try {
10584
+ await setAttr(fd, termios);
10585
+ } finally {
10586
+ await kernel.call({ op: "fd-close", fd });
10587
+ }
10588
+ };
10373
10589
  const restore = async () => {
10374
10590
  for (const [terminal, { fd, termios }] of [...saved].reverse()) {
10375
10591
  saved.delete(terminal);
10376
- await setAttr(fd, termios).catch(() => void 0);
10592
+ const at = await openOn(terminal, fd).catch(() => void 0);
10593
+ const back = at === void 0 ? reopened(terminal, termios) : setAttr(at, termios);
10594
+ await back.catch(() => void 0);
10377
10595
  }
10378
10596
  };
10379
10597
  return { tty, restore };