@ai-ecoverse/slicc-kernel 1.34.1 → 1.36.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.
@@ -1607,7 +1607,7 @@ function ptyStat(path) {
1607
1607
  function nonblocking(stream) {
1608
1608
  return (stream.flags & O_NONBLOCK) !== 0 ? { nonblock: true } : void 0;
1609
1609
  }
1610
- var POLLIN, POLLOUT, POLLERR, POLLHUP, POLLRDNORM, POLLWRNORM, O_NONBLOCK, SOCKET_MODE, PTY_PATH, TTY_PATH, O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC, KILLED_BY_SIGPIPE, ProcessExit, SyscallError, KernelStreams;
1610
+ var POLLIN, POLLOUT, POLLERR, POLLHUP, POLLRDNORM, POLLWRNORM, O_NONBLOCK, SOCKET_MODE, PTY_PATH, TTY_PATH, TTY_NAME, O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC, KILLED_BY_SIGPIPE, ProcessExit, SyscallError, KernelStreams;
1611
1611
  var init_kernel_streams = __esm({
1612
1612
  "src/process/kernel-streams.ts"() {
1613
1613
  "use strict";
@@ -1622,6 +1622,7 @@ var init_kernel_streams = __esm({
1622
1622
  SOCKET_MODE = 49663;
1623
1623
  PTY_PATH = /^\/dev\/(?:ptmx|pts\/(\d+))$/;
1624
1624
  TTY_PATH = /^\/dev\/tty\d+$/;
1625
+ TTY_NAME = /^tty\d+$/;
1625
1626
  O_CREAT = 64;
1626
1627
  O_EXCL = 128;
1627
1628
  O_NOCTTY = 256;
@@ -1695,6 +1696,36 @@ var init_kernel_streams = __esm({
1695
1696
  if (typeof this.Fs.stat !== "function") return;
1696
1697
  stream.stream_ops = { ...stream.stream_ops, getattr: () => this.Fs.stat?.(name) ?? {} };
1697
1698
  }
1699
+ creatingTerminal = false;
1700
+ useTerminalNodes() {
1701
+ const fs = this.Fs;
1702
+ const { lookupNode, readdir, getPath, mkdev, makedev } = fs;
1703
+ const ttyNames = this.sys.ttyNames?.bind(this.sys);
1704
+ if (!lookupNode || !readdir || !getPath || !mkdev || !makedev || !ttyNames) return;
1705
+ fs.lookupNode = (parent, name) => {
1706
+ try {
1707
+ return lookupNode.call(fs, parent, name);
1708
+ } catch (e) {
1709
+ const path = `/dev/${name}`;
1710
+ if (this.creatingTerminal || !TTY_NAME.test(name) || getPath.call(fs, parent) !== "/dev")
1711
+ throw e;
1712
+ if (!ttyNames().includes(path)) throw e;
1713
+ this.creatingTerminal = true;
1714
+ try {
1715
+ mkdev.call(fs, path, makedev.call(fs, 6, 0));
1716
+ } finally {
1717
+ this.creatingTerminal = false;
1718
+ }
1719
+ return lookupNode.call(fs, parent, name);
1720
+ }
1721
+ };
1722
+ fs.readdir = (path) => {
1723
+ const names = readdir.call(fs, path);
1724
+ if (path.replace(/\/+$/, "") !== "/dev") return names;
1725
+ const missing = ttyNames().map((tty) => tty.slice("/dev/".length)).filter((name) => TTY_NAME.test(name) && !names.includes(name));
1726
+ return [...names, ...missing];
1727
+ };
1728
+ }
1698
1729
  ttyNode(name) {
1699
1730
  const { analyzePath, mkdev, makedev } = this.Fs;
1700
1731
  if (!TTY_PATH.test(name) || !analyzePath || !mkdev || !makedev) return;
@@ -1756,8 +1787,13 @@ var init_kernel_streams = __esm({
1756
1787
  useControllingTerminal() {
1757
1788
  if (typeof this.Fs.open !== "function") return;
1758
1789
  this.usePtyPaths();
1790
+ this.useTerminalNodes();
1759
1791
  const open = this.Fs.open.bind(this.Fs);
1760
1792
  this.Fs.open = (path, flags, mode) => {
1793
+ const device = typeof path === "string" ? this.devicePath(path) : void 0;
1794
+ if (device !== void 0 && TTY_PATH.test(device) && !this.terminalExists(device)) {
1795
+ throw new this.Fs.ErrnoError(wasiErrno("ENOENT"));
1796
+ }
1761
1797
  const pty = this.openPty(open, path, flags, mode);
1762
1798
  if (pty) return pty;
1763
1799
  const stream = open(path, flags, mode);
@@ -1830,6 +1866,23 @@ var init_kernel_streams = __esm({
1830
1866
  const exists = n === void 0 ? this.sys.openPty !== void 0 : this.sys.ptyNumbers?.().includes(Number(n)) ?? false;
1831
1867
  if (!exists) throw new this.Fs.ErrnoError(wasiErrno("ENOENT"));
1832
1868
  }
1869
+ devicePath(path) {
1870
+ const name = path.slice(path.lastIndexOf("/") + 1);
1871
+ if (!TTY_NAME.test(name)) return void 0;
1872
+ const { lookupPath, cwd } = this.Fs;
1873
+ const absolute = path.startsWith("/") ? path : `${cwd?.call(this.Fs) ?? "/"}/${path}`;
1874
+ const dir = absolute.slice(0, absolute.lastIndexOf("/")) || "/";
1875
+ try {
1876
+ const real = lookupPath?.call(this.Fs, dir, { follow: true }).path ?? dir;
1877
+ return `${real === "/" ? "" : real}/${name}`;
1878
+ } catch {
1879
+ return absolute;
1880
+ }
1881
+ }
1882
+ terminalExists(path) {
1883
+ const { analyzePath } = this.Fs;
1884
+ return analyzePath?.call(this.Fs, path).exists ?? true;
1885
+ }
1833
1886
  openNamedTerminal(path) {
1834
1887
  const { openTty } = this.sys;
1835
1888
  if (!openTty) return void 0;
@@ -2144,6 +2197,37 @@ function pathOpensLinks(Fs) {
2144
2197
  if (!mayOpen || !isLink) return;
2145
2198
  fs.mayOpen = (node, flags) => flags & O_PATH && isLink.call(fs, node.mode) ? 0 : mayOpen.call(fs, node, flags);
2146
2199
  }
2200
+ function kernelUmask(imports, deps) {
2201
+ let umask = deps.initial & 511;
2202
+ for (const ns of namespaces(imports)) {
2203
+ const { __syscall_openat: openat, __syscall_mkdirat: mkdirat } = ns;
2204
+ const { __syscall_mknodat: mknodat, __syscall_umask: own } = ns;
2205
+ if (typeof openat === "function") {
2206
+ ns.__syscall_openat = (dirfd, path, flags, varargs) => {
2207
+ const memory = deps.memory();
2208
+ if (flags & O_CREAT2 && varargs && memory)
2209
+ new Int32Array(memory.buffer)[varargs >> 2] &= ~umask;
2210
+ return openat(dirfd, path, flags, varargs);
2211
+ };
2212
+ }
2213
+ if (typeof mkdirat === "function") {
2214
+ ns.__syscall_mkdirat = (dirfd, path, mode) => mkdirat(dirfd, path, mode & ~umask);
2215
+ }
2216
+ if (typeof mknodat === "function") {
2217
+ ns.__syscall_mknodat = (dirfd, path, mode, dev) => mknodat(dirfd, path, mode & ~umask, dev);
2218
+ }
2219
+ if (typeof own === "function") {
2220
+ own(umask);
2221
+ ns.__syscall_umask = (mask) => {
2222
+ const old = umask;
2223
+ umask = mask & 511;
2224
+ own(umask);
2225
+ deps.set(umask);
2226
+ return old;
2227
+ };
2228
+ }
2229
+ }
2230
+ }
2147
2231
  function noFollowUtimes(imports, fs, glue) {
2148
2232
  for (const namespace of namespaces(imports)) {
2149
2233
  const key = Object.keys(namespace).find(
@@ -3323,7 +3407,7 @@ function pidStatus(info) {
3323
3407
  const ids = `${UID} ${UID} ${UID} ${UID}`;
3324
3408
  return [
3325
3409
  `Name: ${commOf(info)}`,
3326
- "Umask: 0022",
3410
+ `Umask: ${(info.umask ?? 18).toString(8).padStart(4, "0")}`,
3327
3411
  `State: ${state}`,
3328
3412
  `Tgid: ${info.pid}`,
3329
3413
  "Ngid: 0",
@@ -3672,6 +3756,9 @@ function kernelSys(transport) {
3672
3756
  size(fd) {
3673
3757
  return json(call2({ op: "fd-vfs-stat", fd }, `fd-vfs-stat ${fd}`)).size;
3674
3758
  },
3759
+ ttyNames() {
3760
+ return json(call2({ op: "fd-tty-names" }, "fd-tty-names"));
3761
+ },
3675
3762
  openTty(name) {
3676
3763
  const req = name === void 0 ? { op: "fd-open-tty" } : { op: "fd-open-tty", name };
3677
3764
  return json(call2(req, `fd-open-tty ${name ?? ""}`));
@@ -3851,6 +3938,11 @@ async function runWasmProcess(init, port, deps = {}) {
3851
3938
  }
3852
3939
  });
3853
3940
  liveParent(imports, () => identify(transport, init).ppid);
3941
+ kernelUmask(imports, {
3942
+ initial: init.umask ?? 18,
3943
+ memory: () => memory,
3944
+ set: (mask) => void transport.call({ op: "proc-umask", mask }, Number.POSITIVE_INFINITY, "umask")
3945
+ });
3854
3946
  noFollowUtimes(
3855
3947
  imports,
3856
3948
  () => ownValue(module, "FS"),
@@ -5191,7 +5283,7 @@ function wrap(table) {
5191
5283
  }
5192
5284
  return out;
5193
5285
  }
5194
- var WasiExit, NS_PER_MS, MONOTONIC_BASE, MAX_READ, SIGPIPE_EXIT, WasiHost;
5286
+ var WasiExit, NS_PER_MS, AT_SYMLINK_NOFOLLOW2, DEFAULT_UMASK, MONOTONIC_BASE, MAX_READ, SIGPIPE_EXIT, WasiHost;
5195
5287
  var init_wasi_host = __esm({
5196
5288
  "src/process/wasi/wasi-host.ts"() {
5197
5289
  "use strict";
@@ -5208,6 +5300,8 @@ var init_wasi_host = __esm({
5208
5300
  }
5209
5301
  };
5210
5302
  NS_PER_MS = 1000000n;
5303
+ AT_SYMLINK_NOFOLLOW2 = 1;
5304
+ DEFAULT_UMASK = 18;
5211
5305
  MONOTONIC_BASE = BigInt(Math.round(performance.timeOrigin)) * NS_PER_MS;
5212
5306
  MAX_READ = 1024 * 1024;
5213
5307
  SIGPIPE_EXIT = 141;
@@ -5248,6 +5342,43 @@ var init_wasi_host = __esm({
5248
5342
  get cwd() {
5249
5343
  return this.fds.cwd() ?? this.startCwd;
5250
5344
  }
5345
+ created(path, mode) {
5346
+ const umask = this.o.kernel.call({ op: "proc-umask" });
5347
+ if (umask !== DEFAULT_UMASK) this.o.fs.chmod(path, mode & ~umask);
5348
+ }
5349
+ sliccFsImports() {
5350
+ const { mem, fds } = this;
5351
+ const at = (dirfd, p, l) => fds.resolve(dirfd, mem.string(p, l));
5352
+ const pathOf = (fd) => {
5353
+ const e = fds.get(fd);
5354
+ if (e.type === "dir") return e.path;
5355
+ if (e.type === "file") return e.file.path;
5356
+ const path = e.type === "kernel" && fds.kind(fd, e) === "file" ? this.kernelStat(fd).path : void 0;
5357
+ if (path === void 0) throw new WasiError("EBADF");
5358
+ return path;
5359
+ };
5360
+ const target = (path, flags) => {
5361
+ if (flags & AT_SYMLINK_NOFOLLOW2 && this.o.fs.lstat(path).isSymbolicLink) {
5362
+ throw new WasiError("ENOTSUP");
5363
+ }
5364
+ return path;
5365
+ };
5366
+ const modeOf = (st) => (st.mode ?? 0) & 4095;
5367
+ return wrap({
5368
+ fd_chmod: (fd, mode) => void this.o.fs.chmod(pathOf(fd), mode & 4095),
5369
+ path_chmod: (dirfd, p, l, mode, flags) => void this.o.fs.chmod(target(at(dirfd, p, l), flags), mode & 4095),
5370
+ umask: (mask, out) => {
5371
+ const old = this.o.kernel.call({ op: "proc-umask", mask });
5372
+ mem.view().setUint32(out, old, true);
5373
+ },
5374
+ fd_mode: (fd, out) => void mem.view().setUint32(out, modeOf(this.o.fs.stat(pathOf(fd))), true),
5375
+ path_mode: (dirfd, p, l, flags, out) => {
5376
+ const path = at(dirfd, p, l);
5377
+ const st = flags & AT_SYMLINK_NOFOLLOW2 ? this.o.fs.lstat(path) : this.o.fs.stat(path);
5378
+ mem.view().setUint32(out, modeOf(st), true);
5379
+ }
5380
+ });
5381
+ }
5251
5382
  sliccImports() {
5252
5383
  const { mem } = this;
5253
5384
  const path = (p, l) => {
@@ -5397,7 +5528,12 @@ var init_wasi_host = __esm({
5397
5528
  const { mem, fds, o } = this;
5398
5529
  const at = (dirfd, p, l) => fds.resolve(dirfd, mem.string(p, l));
5399
5530
  return {
5400
- path_open: (dirfd, _lookup, p, l, oflags, rights, _inheriting, fdflags, out) => void mem.view().setUint32(out, fds.open(at(dirfd, p, l), oflags, rights, fdflags), true),
5531
+ path_open: (dirfd, _lookup, p, l, oflags, rights, _inheriting, fdflags, out) => {
5532
+ const path = at(dirfd, p, l);
5533
+ const fresh = (oflags & OFLAGS.CREAT) !== 0 && !o.fs.exists(path);
5534
+ mem.view().setUint32(out, fds.open(path, oflags, rights, fdflags), true);
5535
+ if (fresh) this.created(path, 438);
5536
+ },
5401
5537
  path_filestat_get: (dirfd, lookup, p, l, out) => void this.writeFilestat(out, this.pathFilestat(at(dirfd, p, l), lookup)),
5402
5538
  path_filestat_set_times: (dirfd, lookup, p, l, atim, mtim, flags) => {
5403
5539
  const path = at(dirfd, p, l);
@@ -5408,6 +5544,7 @@ var init_wasi_host = __esm({
5408
5544
  const path = at(dirfd, p, l);
5409
5545
  if (o.fs.exists(path)) throw new WasiError("EEXIST");
5410
5546
  o.fs.mkdir(path);
5547
+ this.created(path, 511);
5411
5548
  },
5412
5549
  path_remove_directory: (dirfd, p, l) => void o.fs.rmdir(at(dirfd, p, l)),
5413
5550
  path_unlink_file: (dirfd, p, l) => {
@@ -7503,14 +7640,15 @@ function unsupportedImport(module, memory, extended = false, foreign = {}) {
7503
7640
  }
7504
7641
  return void 0;
7505
7642
  }
7506
- function linkImports(module, preview1, wasix, memory, threads, program = {}, foreign, slicc = {}) {
7643
+ function linkImports(module, preview1, wasix, memory, threads, program = {}, foreign, slicc = {}, sliccFs = {}) {
7507
7644
  for (const ns of Object.keys(program)) {
7508
- if (RESERVED2.has(ns) || ns === SLICC)
7645
+ if (RESERVED2.has(ns) || ns === SLICC || ns === SLICC_FS)
7509
7646
  throw new Error(`the imports module may not define ${ns}`);
7510
7647
  }
7511
7648
  const imports = {
7512
7649
  ...program,
7513
7650
  [SLICC]: { ...slicc },
7651
+ [SLICC_FS]: { ...sliccFs },
7514
7652
  [PREVIEW1]: preview1,
7515
7653
  ...wasix ? { [WASIX]: { ...wasix } } : {},
7516
7654
  ...threads ? { wasi: { "thread-spawn": (arg) => threads.spawn(arg) } } : {}
@@ -7637,7 +7775,18 @@ async function instantiate(host, module, memory, threads, {
7637
7775
  () => instance
7638
7776
  );
7639
7777
  const slicc = traced(stats, "slicc", host.sliccImports());
7640
- const hostImports = linkImports(module, preview1, wasix, memory, threads, extra, foreign, slicc);
7778
+ const sliccFs = traced(stats, "slicc_fs", host.sliccFsImports());
7779
+ const hostImports = linkImports(
7780
+ module,
7781
+ preview1,
7782
+ wasix,
7783
+ memory,
7784
+ threads,
7785
+ extra,
7786
+ foreign,
7787
+ slicc,
7788
+ sliccFs
7789
+ );
7641
7790
  const imports = sync ? merge(hostImports, sync.linker.mainImports(module)) : hostImports;
7642
7791
  instance = await WebAssembly.instantiate(module, imports);
7643
7792
  stats?.phase("instantiate");
@@ -7827,7 +7976,7 @@ async function runWasiThread(init, port) {
7827
7976
  throw e;
7828
7977
  }
7829
7978
  }
7830
- var TRAPPED, PREVIEW1, WASIX, SLICC, RESERVED2, noErrno, FALLBACK_MAXIMUM_PAGES, LinkSync, DL_GEN, BACKTRACE_FRAMES;
7979
+ var TRAPPED, PREVIEW1, WASIX, SLICC, SLICC_FS, RESERVED2, noErrno, FALLBACK_MAXIMUM_PAGES, LinkSync, DL_GEN, BACKTRACE_FRAMES;
7831
7980
  var init_wasi_runtime = __esm({
7832
7981
  "src/process/wasi/wasi-runtime.ts"() {
7833
7982
  "use strict";
@@ -7853,6 +8002,7 @@ var init_wasi_runtime = __esm({
7853
8002
  PREVIEW1 = "wasi_snapshot_preview1";
7854
8003
  WASIX = "wasix_32v1";
7855
8004
  SLICC = "slicc";
8005
+ SLICC_FS = "slicc_fs";
7856
8006
  RESERVED2 = RESERVED_NAMESPACES;
7857
8007
  noErrno = (key) => `imports ${key}: its result cannot carry ENOSYS, and this host does not provide it`;
7858
8008
  FALLBACK_MAXIMUM_PAGES = 32768;