@ai-ecoverse/slicc-kernel 1.34.1 → 1.35.1

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
@@ -2245,6 +2245,9 @@ var OpfsFs = class {
2245
2245
  ctimeMs: now
2246
2246
  }));
2247
2247
  }
2248
+ async realpath(path, follow) {
2249
+ return (await this.locate(path, follow)).path;
2250
+ }
2248
2251
  async readlink(path) {
2249
2252
  const found = await this.locate(path, false);
2250
2253
  if (found.link) return found.link.link;
@@ -3303,6 +3306,7 @@ function withCommandDirs(fs, names) {
3303
3306
  rename: (from, to) => fs.rename(from, to),
3304
3307
  symlink: (target, path) => fs.symlink(target, path),
3305
3308
  readlink: (path) => fs.readlink(path),
3309
+ ...fs.realpath ? { realpath: fs.realpath.bind(fs) } : {},
3306
3310
  chmod: (path, mode) => fs.chmod(path, mode),
3307
3311
  utimes: (path, atime, mtime) => fs.utimes(path, atime, mtime),
3308
3312
  lutimes: (path, atime, mtime) => lutimesOf(fs, path, atime, mtime),
@@ -4300,6 +4304,12 @@ var MountFs = class {
4300
4304
  this.table.forget(found.mount, normalizePath(path));
4301
4305
  await found.mount.conn.call({ op: "symlink", target, path: found.rel });
4302
4306
  }
4307
+ async realpath(path, follow) {
4308
+ if (this.at(path) || !this.base.realpath) throw errnoError("ENOSYS", path);
4309
+ const real = await this.base.realpath(path, follow);
4310
+ if (this.at(real)) throw errnoError("ENOSYS", path);
4311
+ return real;
4312
+ }
4303
4313
  async readlink(path) {
4304
4314
  const found = this.at(path);
4305
4315
  if (!found) return this.base.readlink(path);
@@ -7274,9 +7284,21 @@ var VfsNodes = class {
7274
7284
  }
7275
7285
  async entryKey(path) {
7276
7286
  const parent = parentOf5(path);
7277
- const dir = await realDir(this.fs, parent).catch(() => parent);
7278
- const name2 = path.slice(path.lastIndexOf("/") + 1);
7279
- return dir === "/" ? `/${name2}` : `${dir}/${name2}`;
7287
+ const dir = await this.real(parent, true, () => realDir(this.fs, parent));
7288
+ return joinName(dir, path.slice(path.lastIndexOf("/") + 1));
7289
+ }
7290
+ targetKey(path) {
7291
+ return this.real(path, true, () => realTarget(this.fs, path));
7292
+ }
7293
+ async real(path, follow, walk) {
7294
+ if (this.fs.realpath) {
7295
+ try {
7296
+ return await this.fs.realpath(path, follow);
7297
+ } catch (err) {
7298
+ if (errCode(err) === "ELOOP") throw err;
7299
+ }
7300
+ }
7301
+ return walk();
7280
7302
  }
7281
7303
  createExclusive(path) {
7282
7304
  return this.onEntry(path, async () => {
@@ -7371,10 +7393,9 @@ function parentOf5(path) {
7371
7393
  async function linkOf(fs, path) {
7372
7394
  return fs.readlink?.(path).catch(() => void 0);
7373
7395
  }
7374
- async function realDir(fs, dir) {
7396
+ async function realDir(fs, dir, budget = { hops: 0 }) {
7375
7397
  const queue = dir.split("/").filter(Boolean);
7376
7398
  let at = "/";
7377
- let hops = 0;
7378
7399
  while (queue.length > 0) {
7379
7400
  const part = queue.shift();
7380
7401
  if (part === ".") continue;
@@ -7383,28 +7404,41 @@ async function realDir(fs, dir) {
7383
7404
  continue;
7384
7405
  }
7385
7406
  const next = at === "/" ? `/${part}` : `${at}/${part}`;
7386
- const link2 = hops < MAX_LINKS5 ? await linkOf(fs, next) : void 0;
7407
+ const link2 = await linkOf(fs, next);
7387
7408
  if (link2 === void 0) {
7388
7409
  at = next;
7389
7410
  continue;
7390
7411
  }
7391
- hops++;
7412
+ if (budget.hops >= MAX_LINKS5) throw fsError("ELOOP", dir);
7413
+ budget.hops++;
7392
7414
  queue.unshift(...link2.split("/").filter(Boolean));
7393
7415
  if (link2.startsWith("/")) at = "/";
7394
7416
  }
7395
7417
  return at;
7396
7418
  }
7397
- async function targetDir(fs, path) {
7398
- let dir = await realDir(fs, parentOf5(path));
7419
+ function errCode(err) {
7420
+ return err?.code;
7421
+ }
7422
+ function joinName(dir, name2) {
7423
+ return dir === "/" ? `/${name2}` : `${dir}/${name2}`;
7424
+ }
7425
+ async function realTarget(fs, path) {
7426
+ const budget = { hops: 0 };
7427
+ let dir = await realDir(fs, parentOf5(path), budget);
7399
7428
  let name2 = path.slice(path.lastIndexOf("/") + 1);
7400
- for (let hops = 0; hops < MAX_LINKS5; hops++) {
7401
- const link2 = await linkOf(fs, dir === "/" ? `/${name2}` : `${dir}/${name2}`);
7402
- if (link2 === void 0) return dir;
7403
- const target = link2.startsWith("/") ? link2 : `${dir}/${link2}`;
7404
- dir = await realDir(fs, parentOf5(target));
7429
+ for (; ; ) {
7430
+ const link2 = await linkOf(fs, joinName(dir, name2));
7431
+ if (link2 === void 0) break;
7432
+ if (budget.hops >= MAX_LINKS5) throw fsError("ELOOP", path);
7433
+ budget.hops++;
7434
+ const target = link2.startsWith("/") ? link2 : joinName(dir, link2);
7435
+ dir = await realDir(fs, parentOf5(target), budget);
7405
7436
  name2 = target.slice(target.lastIndexOf("/") + 1);
7406
7437
  }
7407
- return dir;
7438
+ return joinName(dir, name2);
7439
+ }
7440
+ async function targetDir(fs, path) {
7441
+ return parentOf5(await realTarget(fs, path).catch(() => path));
7408
7442
  }
7409
7443
  async function refuseReadonly(fs, path, flags, opts = {}) {
7410
7444
  const writes = (flags & O_ACCMODE) !== 0 || opts.truncate === true;
@@ -7423,13 +7457,14 @@ function keepingOpen(fs, nodes) {
7423
7457
  return {
7424
7458
  ...fs,
7425
7459
  async rm(path, options) {
7426
- const at = fs.resolvePath("/", path);
7460
+ const at = await nodes.entryKey(fs.resolvePath("/", path));
7427
7461
  await nodes.unlinking(at);
7428
7462
  await fs.rm(path, options);
7429
7463
  nodes.unlinked(at);
7430
7464
  },
7431
- rename(from, to) {
7432
- const [a, b] = [fs.resolvePath("/", from), fs.resolvePath("/", to)];
7465
+ async rename(from, to) {
7466
+ const a = await nodes.entryKey(fs.resolvePath("/", from));
7467
+ const b = await nodes.entryKey(fs.resolvePath("/", to));
7433
7468
  return nodes.onEntry(b, async () => {
7434
7469
  await nodes.unlinking(b);
7435
7470
  await fs.rename(from, to);
@@ -7575,10 +7610,12 @@ var SYSCALL_OPS = /* @__PURE__ */ new Set([
7575
7610
  "fd-cloexec",
7576
7611
  "fd-list",
7577
7612
  "proc-alarm",
7613
+ "proc-umask",
7578
7614
  "dl-log",
7579
7615
  "fd-renumber",
7580
7616
  "fd-promote",
7581
7617
  "fd-open-tty",
7618
+ "fd-tty-names",
7582
7619
  "tty-get",
7583
7620
  "tty-set",
7584
7621
  "tty-winsz",
@@ -7612,6 +7649,7 @@ function isWasmSyscall(req) {
7612
7649
  return typeof op === "string" && SYSCALL_OPS.has(op);
7613
7650
  }
7614
7651
  var MAX_READ = 1024 * 1024;
7652
+ var DEFAULT_UMASK = 18;
7615
7653
  var DYING = { ok: false, errno: "EINTR", message: "the process is being killed" };
7616
7654
  var HOSTS_ONLY = new Resolver({ routes: new Routes() });
7617
7655
  var WasmProcess = class {
@@ -7622,6 +7660,7 @@ var WasmProcess = class {
7622
7660
  inherited = 0;
7623
7661
  interrupt = new AbortController();
7624
7662
  dying = false;
7663
+ umask = DEFAULT_UMASK;
7625
7664
  execChild;
7626
7665
  execTermsig;
7627
7666
  stopped = 0;
@@ -7639,6 +7678,7 @@ var WasmProcess = class {
7639
7678
  this.fds = fds;
7640
7679
  this.options = options;
7641
7680
  this.inherited = options.ignored ?? 0;
7681
+ this.umask = options.umask ?? DEFAULT_UMASK;
7642
7682
  this.children = new ChildTable(fds, options.spawner, options.forker);
7643
7683
  this.nodes = options.nodes ?? new VfsNodes(options.fs);
7644
7684
  if (!options.nodes) options.openFiles?.add(this.nodes);
@@ -7711,6 +7751,11 @@ var WasmProcess = class {
7711
7751
  return result;
7712
7752
  }
7713
7753
  }
7754
+ setUmask(mask) {
7755
+ const old = this.umask;
7756
+ if (mask !== void 0) this.umask = mask & 511;
7757
+ return old;
7758
+ }
7714
7759
  die() {
7715
7760
  if (this.dying) return;
7716
7761
  this.dying = true;
@@ -7781,9 +7826,21 @@ var WasmProcess = class {
7781
7826
  await refuseReadonly(this.options.fs, req.path, req.flags, req);
7782
7827
  const fd = this.fds.install(heldFile(), 3);
7783
7828
  try {
7784
- if (req.exclusive) await this.nodes.createExclusive(req.path);
7785
- this.fds.installAt(fd, this.openVfsFile(req));
7786
- if (req.existing && !await present(this.options.fs, req.path, true)) {
7829
+ const nodes = this.nodes;
7830
+ const path = req.orphan ? req.path : req.exclusive ? await nodes.entryKey(req.path) : await nodes.targetKey(req.path);
7831
+ const open = { ...req, path };
7832
+ if (req.exclusive) {
7833
+ await nodes.createExclusive(path);
7834
+ this.fds.installAt(fd, this.openVfsFile(open));
7835
+ } else if (req.create) {
7836
+ await nodes.onEntry(path, async () => {
7837
+ this.fds.installAt(fd, this.openVfsFile(open));
7838
+ await this.fds.get(fd).file.stat?.();
7839
+ });
7840
+ } else {
7841
+ this.fds.installAt(fd, this.openVfsFile(open));
7842
+ }
7843
+ if (req.existing && !await present(this.options.fs, path, true)) {
7787
7844
  throw new KernelError("ENOENT");
7788
7845
  }
7789
7846
  } catch (err) {
@@ -7862,7 +7919,7 @@ var WasmProcess = class {
7862
7919
  case "fd-reserve":
7863
7920
  return { ok: true, kind: "json", json: this.reserve(req.fd, req.min, req.meta) };
7864
7921
  case "fd-promote":
7865
- this.promote(req);
7922
+ await this.promote(req);
7866
7923
  return { ok: true, kind: "void" };
7867
7924
  case "fd-renumber":
7868
7925
  if (req.from !== req.to) {
@@ -7875,6 +7932,8 @@ var WasmProcess = class {
7875
7932
  if (!tty) throw new KernelError("ENXIO");
7876
7933
  return { ok: true, kind: "json", json: this.fds.install(tty.file(), 3) };
7877
7934
  }
7935
+ case "fd-tty-names":
7936
+ return { ok: true, kind: "json", json: this.options.jobs?.terminalNames() ?? [] };
7878
7937
  case "fd-select": {
7879
7938
  const { read, write, timeoutMs } = req;
7880
7939
  const signal = this.blockingSignal();
@@ -7896,10 +7955,14 @@ var WasmProcess = class {
7896
7955
  async vfsSyscall(req) {
7897
7956
  if ("path" in req || "from" in req) {
7898
7957
  const nodes = this.nodes;
7899
- if (req.op === "fd-path-flush") await nodes.flush(req.path);
7900
- else if (req.op === "fd-path-unlinking") await nodes.unlinking(req.path);
7901
- else if (req.op === "fd-path-unlinked") nodes.unlinked(req.path);
7902
- else if (req.op === "fd-path-renamed") nodes.renamed(req.from, req.to);
7958
+ if (req.op === "fd-path-flush") {
7959
+ await nodes.flush(await nodes.targetKey(req.path).catch(() => req.path));
7960
+ } else if (req.op === "fd-path-unlinking")
7961
+ await nodes.unlinking(await nodes.entryKey(req.path));
7962
+ else if (req.op === "fd-path-unlinked") nodes.unlinked(await nodes.entryKey(req.path));
7963
+ else if (req.op === "fd-path-renamed") {
7964
+ nodes.renamed(await nodes.entryKey(req.from), await nodes.entryKey(req.to));
7965
+ }
7903
7966
  return { ok: true, kind: "void" };
7904
7967
  }
7905
7968
  const file = this.fds.get(req.fd).file;
@@ -7920,17 +7983,19 @@ var WasmProcess = class {
7920
7983
  return { ok: true, kind: "json", json: await file.stat() };
7921
7984
  }
7922
7985
  }
7923
- promote(req) {
7986
+ async promote(req) {
7924
7987
  if (!this.fds.get(req.fd).file.held) throw new KernelError("EBADF");
7925
7988
  if (req.share !== void 0) {
7926
7989
  this.fds.dup2(req.share, req.fd);
7927
7990
  return;
7928
7991
  }
7929
7992
  if (req.path === void 0) throw new KernelError("EINVAL");
7993
+ const path = req.orphan ? req.path : await this.nodes.targetKey(req.path);
7994
+ if (!this.fds.get(req.fd).file.held) throw new KernelError("EBADF");
7930
7995
  const file = vfsFile(
7931
7996
  this.options.fs,
7932
7997
  {
7933
- path: req.path,
7998
+ path,
7934
7999
  flags: req.flags ?? 0,
7935
8000
  position: req.position ?? 0,
7936
8001
  ...req.contents !== void 0 ? { contents: req.contents } : {},
@@ -8106,6 +8171,8 @@ var WasmProcess = class {
8106
8171
  case "proc-alarm":
8107
8172
  this.setAlarm(req.sig, req.firstMs ?? req.ms, req.repeat ? req.ms : 0, req.timer);
8108
8173
  return { ok: true, kind: "void" };
8174
+ case "proc-umask":
8175
+ return { ok: true, kind: "json", json: this.setUmask(req.mask) };
8109
8176
  case "dl-log":
8110
8177
  if (req.append) this.dlLog.push(req.append);
8111
8178
  return { ok: true, kind: "json", json: this.dlLog.slice(req.from) };
@@ -8255,7 +8322,7 @@ var Dying = class {
8255
8322
  return [typeof reported === "number" ? reported : CRASHED, void 0];
8256
8323
  }
8257
8324
  };
8258
- function processInit(opts, sab) {
8325
+ function processInit(opts, sab, umask) {
8259
8326
  const base = {
8260
8327
  type: WASM_PROCESS_INIT,
8261
8328
  pid: opts.shownPid ?? opts.pid,
@@ -8264,6 +8331,7 @@ function processInit(opts, sab) {
8264
8331
  env: opts.env,
8265
8332
  cwd: opts.cwd,
8266
8333
  sab,
8334
+ umask,
8267
8335
  ...opts.ppid !== void 0 ? { ppid: opts.ppid } : {}
8268
8336
  };
8269
8337
  if (opts.program.abi === "js") {
@@ -8275,11 +8343,17 @@ function processInit(opts, sab) {
8275
8343
  ...opts.fork ? { fork: opts.fork } : { fds: inheritedFds(opts.fds) }
8276
8344
  };
8277
8345
  }
8346
+ function inherited(opts) {
8347
+ return {
8348
+ ...opts.ignored ? { ignored: opts.ignored } : {},
8349
+ ...opts.umask !== void 0 ? { umask: opts.umask } : {}
8350
+ };
8351
+ }
8278
8352
  function spawnWasmProcess(opts) {
8279
8353
  const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
8280
8354
  const header3 = new Int32Array(sab, 0, SAB_HEADER_I32);
8281
8355
  const process = new WasmProcess(opts.pid, opts.fds, {
8282
- ...opts.ignored ? { ignored: opts.ignored } : {},
8356
+ ...inherited(opts),
8283
8357
  ...opts.identity ? { identity: opts.identity } : {},
8284
8358
  ...opts.onSyscall ? { onSyscall: opts.onSyscall } : {},
8285
8359
  spawner: opts.spawner,
@@ -8413,7 +8487,7 @@ function spawnWasmProcess(opts) {
8413
8487
  };
8414
8488
  tw.postMessage(tinit);
8415
8489
  };
8416
- const init = processInit(opts, sab);
8490
+ const init = processInit(opts, sab, process.umask);
8417
8491
  worker.postMessage(init, opts.fork ? [opts.fork.memory.buffer] : []);
8418
8492
  const signal = (sig) => {
8419
8493
  if (process.signal(sig) !== "terminate") return;
@@ -8431,6 +8505,7 @@ function spawnWasmProcess(opts) {
8431
8505
  onState: (listener) => process.onState(listener),
8432
8506
  memory: () => Atomics.load(header3, SAB_I_MEMORY) * 65536,
8433
8507
  ignoredSignals: (fork) => process.inheritable(fork),
8508
+ umask: () => process.umask,
8434
8509
  writesBack: () => opts.program.abi === "wasi" && !done4
8435
8510
  };
8436
8511
  }
@@ -8536,8 +8611,13 @@ var JobTable = class {
8536
8611
  return id;
8537
8612
  }
8538
8613
  terminalNamed(name2) {
8539
- const known = /* @__PURE__ */ new Set([...this.terminals.values(), ...this.foreground.keys()]);
8540
- return [...known].find((tty) => tty.name === name2);
8614
+ return this.knownTerminals().find((tty) => tty.name === name2);
8615
+ }
8616
+ terminalNames() {
8617
+ return this.knownTerminals().flatMap((tty) => tty.name ? [tty.name] : []);
8618
+ }
8619
+ knownTerminals() {
8620
+ return [.../* @__PURE__ */ new Set([...this.terminals.values(), ...this.foreground.keys()])];
8541
8621
  }
8542
8622
  controllingTerminal(pid) {
8543
8623
  const member = this.members.get(pid);
@@ -10180,6 +10260,7 @@ var Launcher = class {
10180
10260
  this.settling.syscall(pid, call.op);
10181
10261
  },
10182
10262
  ...req.ignored ? { ignored: req.ignored } : {},
10263
+ ...req.umask !== void 0 ? { umask: req.umask } : {},
10183
10264
  program: req.program,
10184
10265
  argv0: req.argv0,
10185
10266
  args: req.args,
@@ -10271,7 +10352,8 @@ var Launcher = class {
10271
10352
  ...described,
10272
10353
  started: (this.described.get(root.pid) ?? described).started,
10273
10354
  state: this.processes.has(member.pid) ? "S" : "Z",
10274
- memory: this.processes.get(member.pid)?.memory() ?? 0
10355
+ memory: this.processes.get(member.pid)?.memory() ?? 0,
10356
+ umask: this.umaskOf(member.pid)
10275
10357
  });
10276
10358
  }
10277
10359
  return listed;
@@ -10293,6 +10375,7 @@ var Launcher = class {
10293
10375
  report,
10294
10376
  ppid,
10295
10377
  ignored: this.ignoredBy(ppid),
10378
+ umask: this.umaskOf(ppid),
10296
10379
  ...exec
10297
10380
  });
10298
10381
  deciding?.attach();
@@ -10337,7 +10420,8 @@ var Launcher = class {
10337
10420
  fds,
10338
10421
  ppid,
10339
10422
  fork: state,
10340
- ignored: this.ignoredBy(ppid, true)
10423
+ ignored: this.ignoredBy(ppid, true),
10424
+ umask: this.umaskOf(ppid)
10341
10425
  })
10342
10426
  );
10343
10427
  }
@@ -10346,6 +10430,9 @@ var Launcher = class {
10346
10430
  const foreground = () => this.jobs.tcgetpgrp(tty, fallback);
10347
10431
  this.settling.deliver(sig, pgid, send, tty.reading ? void 0 : foreground);
10348
10432
  }
10433
+ umaskOf(pid) {
10434
+ return this.processes.get(pid)?.umask?.() ?? DEFAULT_UMASK;
10435
+ }
10349
10436
  ignoredBy(pid, fork = false) {
10350
10437
  return this.processes.get(pid)?.ignoredSignals(fork) ?? 0;
10351
10438
  }