@ai-ecoverse/slicc-kernel 1.54.1 → 1.54.3

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.
@@ -3289,6 +3289,7 @@ var init_process_signals = __esm({
3289
3289
  }
3290
3290
  }
3291
3291
  interrupt() {
3292
+ this.report();
3292
3293
  const header = this.header;
3293
3294
  const pending = Atomics.load(header, SAB_I_SIGNALS) | Atomics.load(header, SAB_I_TIMERS) | Atomics.load(header, SAB_I_KILLED);
3294
3295
  if (pending === 0) return false;
@@ -4812,7 +4813,7 @@ function openAccess(existing, oflags, rights) {
4812
4813
  return { readable: (rights & RIGHTS.FD_READ) !== 0n || !writable2, writable: writable2 };
4813
4814
  }
4814
4815
  function promoteRequest(fd, f, handed) {
4815
- const orphan = f.buffer.isOrphan();
4816
+ const orphan = f.buffer.isOrphan() || (f.buffer.handle ?? 0) < 0;
4816
4817
  if (!orphan && f.buffer.isRanged) f.buffer.flush();
4817
4818
  const joins = !orphan && (handed.has(f.buffer) || f.buffer.isRanged);
4818
4819
  return {
@@ -5550,7 +5551,7 @@ function readTermios(mem, ptr) {
5550
5551
  c_cc: Array.from({ length: NCCS }, (_, i) => v.getUint8(ptr + C_CC + i))
5551
5552
  };
5552
5553
  }
5553
- function sliccTty(mem, fds, kernel) {
5554
+ function sliccTty(mem, fds, kernel, interrupted = () => void 0) {
5554
5555
  const { sys } = kernel;
5555
5556
  const terminal = (fd) => {
5556
5557
  const e = fds.find(fd);
@@ -5562,13 +5563,19 @@ function sliccTty(mem, fds, kernel) {
5562
5563
  if (value2 === void 0) throw new WasiError("ENOTTY");
5563
5564
  return value2;
5564
5565
  };
5566
+ const getAttr = (fd, ptr) => {
5567
+ interrupted();
5568
+ writeTermios(mem, ptr, needs(sys.tcgets?.(terminal(fd))));
5569
+ };
5565
5570
  const setAttr = (fd, actions, ptr) => {
5571
+ interrupted();
5566
5572
  if (actions < 0 || actions > TCSAFLUSH) throw new WasiError("EINVAL");
5567
5573
  const at = terminal(fd);
5568
5574
  needs(sys.tcsets);
5569
5575
  sys.tcsets?.(at, readTermios(mem, ptr), actions === TCSAFLUSH);
5570
5576
  };
5571
5577
  const size = (fd, ptr) => {
5578
+ interrupted();
5572
5579
  const [rows, cols] = needs(sys.winsize?.(terminal(fd)));
5573
5580
  mem.bytes(ptr, 8).fill(0);
5574
5581
  const v = mem.view();
@@ -5576,7 +5583,7 @@ function sliccTty(mem, fds, kernel) {
5576
5583
  v.setUint16(ptr + 2, cols, true);
5577
5584
  };
5578
5585
  return {
5579
- tcgetattr: (fd, ptr) => void writeTermios(mem, ptr, needs(sys.tcgets?.(terminal(fd)))),
5586
+ tcgetattr: (fd, ptr) => void getAttr(fd, ptr),
5580
5587
  tcsetattr: (fd, actions, ptr) => void setAttr(fd, actions, ptr),
5581
5588
  winsize: (fd, ptr) => void size(fd, ptr)
5582
5589
  };
@@ -5725,7 +5732,7 @@ var init_wasi_host = __esm({
5725
5732
  if (umask !== DEFAULT_UMASK) this.o.fs.chmod(path, mode & ~umask);
5726
5733
  }
5727
5734
  sliccTtyImports() {
5728
- return wrap(sliccTty(this.mem, this.fds, this.o.kernel));
5735
+ return wrap(sliccTty(this.mem, this.fds, this.o.kernel, () => this.interrupted?.()));
5729
5736
  }
5730
5737
  sliccFsImports() {
5731
5738
  const { mem, fds } = this;
@@ -5946,6 +5953,7 @@ var init_wasi_host = __esm({
5946
5953
  return {
5947
5954
  path_open: (dirfd, _lookup, p, l, oflags, rights, _inheriting, fdflags, out) => {
5948
5955
  const path = at(dirfd, p, l);
5956
+ if (deviceOf(path)) this.interrupted?.();
5949
5957
  const fresh = (oflags & OFLAGS.CREAT) !== 0 && !o.fs.exists(path);
5950
5958
  mem.view().setUint32(out, fds.open(path, oflags, rights, fdflags), true);
5951
5959
  if (fresh) this.created(path, 438);
@@ -6061,7 +6069,9 @@ var init_wasi_host = __esm({
6061
6069
  }
6062
6070
  positional(fd, access) {
6063
6071
  const e = this.fds.get(fd);
6064
- if (e.type !== "kernel" || this.fds.kind(fd, e) !== "file") return this.file(fd, access);
6072
+ const kind = e.type === "kernel" ? this.fds.kind(fd, e) : e.type;
6073
+ if (kind === "device") this.interrupted?.();
6074
+ if (kind !== "file" || e.type !== "kernel") return this.file(fd, access);
6065
6075
  const kernel = this.o.kernel;
6066
6076
  return {
6067
6077
  pread: (max, at) => {
@@ -6089,6 +6099,7 @@ var init_wasi_host = __esm({
6089
6099
  }
6090
6100
  }
6091
6101
  if (e.type === "device") {
6102
+ this.interrupted?.();
6092
6103
  if (e.access === "read") throw new WasiError("EBADF");
6093
6104
  if (e.device === "full" && data.length > 0) throw new WasiError("ENOSPC");
6094
6105
  return data.length;
@@ -6101,6 +6112,7 @@ var init_wasi_host = __esm({
6101
6112
  return this.o.kernel.sys.read(fd, Math.min(max, MAX_READ), { nonblock: e.nonblock });
6102
6113
  }
6103
6114
  if (e.type === "device") {
6115
+ this.interrupted?.();
6104
6116
  if (e.access === "write") throw new WasiError("EBADF");
6105
6117
  if (e.device === "null") return new Uint8Array(0);
6106
6118
  const out = new Uint8Array(Math.min(max, 65536));
@@ -6108,15 +6120,19 @@ var init_wasi_host = __esm({
6108
6120
  }
6109
6121
  return this.file(fd, "read").read(max);
6110
6122
  }
6123
+ local(answer2) {
6124
+ this.interrupted?.();
6125
+ return answer2;
6126
+ }
6111
6127
  seek(fd, offset, whence) {
6112
6128
  const e = this.fds.get(fd);
6113
6129
  if (e.type === "kernel") {
6114
6130
  const kind = this.fds.kind(fd, e);
6115
- if (kind === "device") return 0;
6131
+ if (kind === "device") return this.local(0);
6116
6132
  if (kind !== "file") throw new WasiError("ESPIPE");
6117
6133
  return this.o.kernel.sys.seek(fd, offset, whence);
6118
6134
  }
6119
- if (e.type === "device") return 0;
6135
+ if (e.type === "device") return this.local(0);
6120
6136
  const file = this.file(fd);
6121
6137
  const base = whence === WHENCE.SET ? 0 : whence === WHENCE.CUR ? file.offset : file.size();
6122
6138
  if (whence > WHENCE.END || base + offset < 0) throw new WasiError("EINVAL");
@@ -6126,15 +6142,23 @@ var init_wasi_host = __esm({
6126
6142
  sync(fd) {
6127
6143
  const e = this.fds.get(fd);
6128
6144
  if (e.type === "file") e.file.flush();
6129
- else if (e.type === "kernel" && this.fds.kind(fd, e) === "file") this.o.kernel.sys.flush(fd);
6145
+ else if (e.type === "device") this.interrupted?.();
6146
+ else if (e.type === "kernel") {
6147
+ const kind = this.fds.kind(fd, e);
6148
+ if (kind === "file") this.o.kernel.sys.flush(fd);
6149
+ else if (kind === "device") this.interrupted?.();
6150
+ }
6130
6151
  }
6131
6152
  fdstat(fd, out) {
6132
6153
  const e = this.fds.get(fd);
6154
+ if (e.type === "device") this.interrupted?.();
6133
6155
  let filetype = FILETYPE.CHARACTER_DEVICE;
6134
6156
  let seeks = true;
6135
6157
  let flags = 0;
6136
6158
  if (e.type === "kernel") {
6137
- ({ filetype, seeks } = kernelFiletype(this.fds.kind(fd, e)));
6159
+ const kind = this.fds.kind(fd, e);
6160
+ if (kind === "device") this.interrupted?.();
6161
+ ({ filetype, seeks } = kernelFiletype(kind));
6138
6162
  if (e.nonblock) flags |= FDFLAGS.NONBLOCK;
6139
6163
  if (e.append) flags |= FDFLAGS.APPEND;
6140
6164
  } else if (e.type === "file") {
@@ -6169,7 +6193,7 @@ var init_wasi_host = __esm({
6169
6193
  if (vfs.path) return this.statOrphanable(vfs.path, vfs.size, vfs.orphan);
6170
6194
  }
6171
6195
  const filetype = kind ? kernelFiletype(kind).filetype : FILETYPE.CHARACTER_DEVICE;
6172
- return { filetype, size: 0n, ino: BigInt(fd + 1), mtimeNs: 0n };
6196
+ return this.local({ filetype, size: 0n, ino: BigInt(fd + 1), mtimeNs: 0n });
6173
6197
  }
6174
6198
  statOrphanable(path, size, orphan = false) {
6175
6199
  let s;
@@ -6186,7 +6210,12 @@ var init_wasi_host = __esm({
6186
6210
  }
6187
6211
  pathFilestat(path, lookup) {
6188
6212
  if (deviceOf(path)) {
6189
- return { filetype: FILETYPE.CHARACTER_DEVICE, size: 0n, ino: pathInode(path), mtimeNs: 0n };
6213
+ return this.local({
6214
+ filetype: FILETYPE.CHARACTER_DEVICE,
6215
+ size: 0n,
6216
+ ino: pathInode(path),
6217
+ mtimeNs: 0n
6218
+ });
6190
6219
  }
6191
6220
  this.fds.flushPath(path);
6192
6221
  const follow2 = (lookup & LOOKUP_SYMLINK_FOLLOW) !== 0;
@@ -6771,60 +6800,201 @@ var init_wasi_module = __esm({
6771
6800
  function inProc(path) {
6772
6801
  return path === "/proc" || path.startsWith("/proc/");
6773
6802
  }
6803
+ function* procWalk(path, follow2) {
6804
+ let done = [];
6805
+ let todo = path.split("/").filter((part) => part !== "");
6806
+ let hops = 0;
6807
+ while (todo.length > 0) {
6808
+ const part = todo.shift();
6809
+ if (part === ".") continue;
6810
+ if (part === "..") {
6811
+ done.pop();
6812
+ continue;
6813
+ }
6814
+ const at = `/${[...done, part].join("/")}`;
6815
+ const whole = normalize(`/${[...done, part, ...todo].join("/")}`);
6816
+ if (inProc(at) && inProc(whole)) return whole;
6817
+ if (!follow2 && todo.length === 0) return void 0;
6818
+ const target = yield at;
6819
+ if (target === null) return void 0;
6820
+ if (target === void 0) done.push(part);
6821
+ else {
6822
+ if (++hops > MAX_HOPS2) return void 0;
6823
+ if (target.startsWith("/")) done = [];
6824
+ todo = [...target.split("/").filter((part2) => part2 !== ""), ...todo];
6825
+ }
6826
+ }
6827
+ return void 0;
6828
+ }
6829
+ function procPath(fs, path, follow2) {
6830
+ const walk = procWalk(path, follow2);
6831
+ let step = walk.next();
6832
+ while (!step.done) {
6833
+ let target;
6834
+ try {
6835
+ target = fs.lstat(step.value).isSymbolicLink ? fs.readlink(step.value) : void 0;
6836
+ } catch {
6837
+ target = null;
6838
+ }
6839
+ step = walk.next(target);
6840
+ }
6841
+ return step.value;
6842
+ }
6843
+ function frozen(bytes) {
6844
+ const refuse = () => {
6845
+ throw syncError("EROFS", "/proc");
6846
+ };
6847
+ return {
6848
+ readFile: () => bytes,
6849
+ pread: (_p, at, n) => bytes.subarray(at, at + n),
6850
+ writeFile: refuse,
6851
+ pwrite: refuse,
6852
+ truncate: refuse
6853
+ };
6854
+ }
6774
6855
  function procfsBridge(fs, tree) {
6856
+ const toProc = (path, follow2) => procPath(fs, path, follow2);
6857
+ const shadowing = () => {
6858
+ try {
6859
+ return fs.exists("/proc");
6860
+ } catch {
6861
+ return false;
6862
+ }
6863
+ };
6864
+ const via = (p, proc, own, follow2 = true) => {
6865
+ if (inProc(p)) return proc(p);
6866
+ if (shadowing()) {
6867
+ const real = toProc(p, follow2);
6868
+ if (real !== void 0) return proc(real);
6869
+ }
6870
+ try {
6871
+ return own();
6872
+ } catch (err) {
6873
+ const real = toProc(p, follow2);
6874
+ if (real === void 0) throw err;
6875
+ return proc(real);
6876
+ }
6877
+ };
6878
+ const readOnly = (paths, run) => {
6879
+ const physical = shadowing();
6880
+ for (const [p, follow2] of paths) {
6881
+ if (inProc(p) || physical && toProc(p, follow2) !== void 0) throw syncError("EROFS", p);
6882
+ }
6883
+ return run();
6884
+ };
6885
+ const snapshots = /* @__PURE__ */ new Map();
6886
+ let lastSnapshot = 0;
6887
+ const snapshot = (q) => {
6888
+ lastSnapshot--;
6889
+ snapshots.set(lastSnapshot, tree.read(q));
6890
+ return lastSnapshot;
6891
+ };
6892
+ const late = (p) => {
6893
+ const q = toProc(p, true);
6894
+ return q === void 0 ? void 0 : snapshot(q);
6895
+ };
6775
6896
  const over = {
6776
- readFile: (p) => inProc(p) ? tree.read(p) : fs.readFile(p),
6777
- stat: (p) => inProc(p) ? tree.stat(p) : fs.stat(p),
6778
- lstat: (p) => inProc(p) ? tree.stat(p, false) : fs.lstat(p),
6779
- readdir: (p) => {
6780
- if (inProc(p)) return tree.readdir(p);
6781
- const names = fs.readdir(p);
6782
- return p === "/" && !names.includes("proc") ? [...names, "proc"] : names;
6783
- },
6784
- exists: (p) => inProc(p) ? tree.exists(p) : fs.exists(p),
6785
- readlink: (p) => inProc(p) ? tree.readlink(p) : fs.readlink(p),
6786
- readdirStat: (p) => {
6787
- if (!inProc(p)) {
6788
- const listed = fs.readdirStat(p);
6789
- if (p !== "/" || listed.some(([name2]) => name2 === "proc")) return listed;
6790
- return [...listed, ["proc", tree.stat("/proc")]];
6897
+ readFile: (p) => via(
6898
+ p,
6899
+ (q) => tree.read(q),
6900
+ () => fs.readFile(p)
6901
+ ),
6902
+ stat: (p) => via(
6903
+ p,
6904
+ (q) => tree.stat(q),
6905
+ () => fs.stat(p)
6906
+ ),
6907
+ lstat: (p) => via(
6908
+ p,
6909
+ (q) => tree.stat(q, false),
6910
+ () => fs.lstat(p),
6911
+ false
6912
+ ),
6913
+ readdir: (p) => via(
6914
+ p,
6915
+ (q) => tree.readdir(q),
6916
+ () => {
6917
+ const names = fs.readdir(p);
6918
+ return p === "/" && !names.includes("proc") ? [...names, "proc"] : names;
6791
6919
  }
6792
- return tree.readdir(p).map((name2) => {
6920
+ ),
6921
+ exists: (p) => {
6922
+ if (inProc(p)) return tree.exists(p);
6923
+ const real = shadowing() ? toProc(p, true) : void 0;
6924
+ if (real !== void 0) return tree.exists(real);
6925
+ if (fs.exists(p)) return true;
6926
+ const late2 = toProc(p, true);
6927
+ return late2 !== void 0 && tree.exists(late2);
6928
+ },
6929
+ readlink: (p) => via(
6930
+ p,
6931
+ (q) => tree.readlink(q),
6932
+ () => fs.readlink(p),
6933
+ false
6934
+ ),
6935
+ readdirStat: (p) => via(
6936
+ p,
6937
+ (q) => tree.readdir(q).map((name2) => {
6793
6938
  try {
6794
- return [name2, tree.stat(`${p}/${name2}`, false)];
6939
+ return [name2, tree.stat(`${q}/${name2}`, false)];
6795
6940
  } catch {
6796
6941
  return [name2, null];
6797
6942
  }
6798
- });
6943
+ }),
6944
+ () => {
6945
+ const listed = fs.readdirStat(p);
6946
+ if (p !== "/" || listed.some(([name2]) => name2 === "proc")) return listed;
6947
+ return [...listed, ["proc", tree.stat("/proc")]];
6948
+ }
6949
+ ),
6950
+ rename: (from, to) => readOnly(
6951
+ [
6952
+ [from, false],
6953
+ [to, false]
6954
+ ],
6955
+ () => fs.rename(from, to)
6956
+ ),
6957
+ symlink: (target, link) => readOnly([[link, false]], () => fs.symlink(target, link)),
6958
+ hold: (p, held, open, handle) => {
6959
+ if (handle !== void 0 && snapshots.delete(handle)) return void 0;
6960
+ if (!held) return fs.hold?.(p, held, open, handle);
6961
+ return via(p, snapshot, () => fs.hold?.(p, held, open) ?? late(p));
6799
6962
  },
6800
- rename: (from, to) => {
6801
- if (inProc(from) || inProc(to)) throw syncError("EROFS", from);
6802
- fs.rename(from, to);
6963
+ kept: (handle) => snapshots.has(handle) || fs.kept?.(handle) === true,
6964
+ pinned: (handle) => {
6965
+ const bytes = snapshots.get(handle);
6966
+ return bytes ? frozen(bytes) : fs.pinned?.(handle) ?? fs;
6803
6967
  },
6804
- hold: (p, ...rest2) => inProc(p) ? void 0 : fs.hold?.(p, ...rest2),
6805
6968
  ...fs.pread ? {
6806
- pread: (p, at, n, version) => inProc(p) ? tree.read(p).subarray(at, at + n) : fs.pread(p, at, n, version)
6969
+ pread: (p, at, n, version) => via(
6970
+ p,
6971
+ (q) => tree.read(q).subarray(at, at + n),
6972
+ () => fs.pread(p, at, n, version)
6973
+ )
6807
6974
  } : {}
6808
6975
  };
6809
- for (const name2 of READ_ONLY) {
6810
- const fn = fs[name2];
6811
- if (!fn) continue;
6812
- over[name2] = (p, ...rest2) => {
6813
- if (inProc(p)) throw syncError("EROFS", p);
6814
- return fn.call(fs, p, ...rest2);
6815
- };
6976
+ for (const [names, follow2] of [
6977
+ [FOLLOWING, true],
6978
+ [NOT_FOLLOWING, false]
6979
+ ]) {
6980
+ for (const name2 of names) {
6981
+ const fn = fs[name2];
6982
+ if (!fn) continue;
6983
+ over[name2] = (p, ...rest2) => readOnly([[p, follow2]], () => fn.call(fs, p, ...rest2));
6984
+ }
6816
6985
  }
6817
6986
  return new Proxy(fs, {
6818
6987
  get: (target, key, receiver) => key in over ? over[key] : Reflect.get(target, key, receiver)
6819
6988
  });
6820
6989
  }
6821
- var DIR_MODE3, FILE_MODE2, LINK_MODE3, PID_NAMES, SYSTEM_NAMES, ProcTree, READ_ONLY;
6990
+ var DIR_MODE3, FILE_MODE2, LINK_MODE3, PID_NAMES, SYSTEM_NAMES, ProcTree, FOLLOWING, NOT_FOLLOWING, MAX_HOPS2;
6822
6991
  var init_wasi_procfs = __esm({
6823
6992
  "src/process/wasi/wasi-procfs.ts"() {
6824
6993
  "use strict";
6825
6994
  init_sync_fs_wire();
6826
6995
  init_process_fds();
6827
6996
  init_procfs();
6997
+ init_wasi_files();
6828
6998
  DIR_MODE3 = 16749;
6829
6999
  FILE_MODE2 = 33060;
6830
7000
  LINK_MODE3 = 41471;
@@ -6935,20 +7105,9 @@ var init_wasi_procfs = __esm({
6935
7105
  }
6936
7106
  }
6937
7107
  };
6938
- READ_ONLY = [
6939
- "writeFile",
6940
- "mkdir",
6941
- "rm",
6942
- "unlink",
6943
- "rmdir",
6944
- "symlink",
6945
- "chmod",
6946
- "utimes",
6947
- "lutimes",
6948
- "create",
6949
- "pwrite",
6950
- "truncate"
6951
- ];
7108
+ FOLLOWING = ["writeFile", "chmod", "utimes", "pwrite", "truncate"];
7109
+ NOT_FOLLOWING = ["mkdir", "rm", "unlink", "rmdir", "lutimes", "create"];
7110
+ MAX_HOPS2 = 40;
6952
7111
  }
6953
7112
  });
6954
7113
 
@@ -8762,6 +8921,7 @@ var init_wasix_host = __esm({
8762
8921
  }
8763
8922
  ttyGet(ptr) {
8764
8923
  const { host, mem } = this;
8924
+ host.interrupted?.();
8765
8925
  const v = mem.view();
8766
8926
  mem.bytes(ptr, 24).fill(0);
8767
8927
  const fd = this.ttyFd();
@@ -8781,6 +8941,7 @@ var init_wasix_host = __esm({
8781
8941
  v.setUint8(ptr + 20, termios && termios.c_lflag & ICANON ? 1 : 0);
8782
8942
  }
8783
8943
  ttySet(ptr) {
8944
+ this.host.interrupted?.();
8784
8945
  const fd = this.ttyFd();
8785
8946
  if (fd === void 0) throw new WasiError("ENOTTY");
8786
8947
  const { sys } = this.host.o.kernel;