@ai-ecoverse/slicc-kernel 1.103.0 → 1.103.2

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.
@@ -978,6 +978,7 @@ function view(target, overrides) {
978
978
  var S_IFDIR = 16384;
979
979
  var S_IFREG = 32768;
980
980
  var S_IFLNK = 40960;
981
+ var S_IFSOCK = 49152;
981
982
  var PERM_MASK = 4095;
982
983
  var S_ISGID2 = 1024;
983
984
  var READ_ATTEMPTS = 3;
@@ -1245,7 +1246,8 @@ var OpfsFs = class {
1245
1246
  return Object.keys(fields).length > 0 ? fields : void 0;
1246
1247
  }
1247
1248
  async stampNew(path, owner, directory) {
1248
- const fields = await this.newFields(path, owner, directory);
1249
+ const owned4 = await this.newFields(path, owner, directory);
1250
+ const fields = owner?.socket && !directory ? { ...owned4, socket: true } : owned4;
1249
1251
  if (fields) await this.meta.update(path, (entry) => ({ ...entry, path, ...fields }));
1250
1252
  }
1251
1253
  guarded = [];
@@ -1445,7 +1447,8 @@ var OpfsFs = class {
1445
1447
  }
1446
1448
  mode(path, directory, meta) {
1447
1449
  const fallback = directory || EXECUTABLE.test(path) ? 493 : 420;
1448
- return (directory ? S_IFDIR : S_IFREG) | (meta?.mode ?? fallback);
1450
+ const type = directory ? S_IFDIR : meta?.socket ? S_IFSOCK : S_IFREG;
1451
+ return type | (meta?.mode ?? fallback);
1449
1452
  }
1450
1453
  id = crypto.randomUUID();
1451
1454
  dirTimes = /* @__PURE__ */ new Map();
@@ -1524,10 +1527,12 @@ var OpfsFs = class {
1524
1527
  const modified = file?.lastModified ?? 0;
1525
1528
  const kept = meta?.mtimeMs !== void 0 && meta.mtimeFor === modified ? meta.mtimeMs : modified;
1526
1529
  const mtime = touched ?? kept;
1530
+ const socket = !directory && meta?.socket === true;
1527
1531
  return {
1528
- isFile: !directory,
1532
+ isFile: !directory && !socket,
1529
1533
  isDirectory: directory,
1530
1534
  isSymbolicLink: false,
1535
+ ...socket ? { isSocket: true } : {},
1531
1536
  size: file?.size ?? 0,
1532
1537
  mode: this.mode(path, directory, meta),
1533
1538
  mtime: new Date(mtime),
@@ -3563,6 +3568,7 @@ var KernelSocket = class _KernelSocket {
3563
3568
  queue = [];
3564
3569
  backlog = 0;
3565
3570
  boundAt;
3571
+ named;
3566
3572
  changes = new Changes();
3567
3573
  room = new Changes();
3568
3574
  options = /* @__PURE__ */ new Map();
@@ -3628,10 +3634,13 @@ var KernelSocket = class _KernelSocket {
3628
3634
  for (const wait2 of waits) wait2.catch(() => void 0);
3629
3635
  return pipeCall(() => Promise.race(waits));
3630
3636
  }
3631
- bind(addr, kernel = false) {
3637
+ bindable(addr) {
3632
3638
  if (this.state !== "open" || this.local) throw new KernelError("EINVAL");
3633
3639
  if (addr.family !== this.domain) throw new KernelError("EAFNOSUPPORT");
3634
- this.local = this.net.bind(this, addr, kernel);
3640
+ }
3641
+ bind(addr, kernel = false, name2) {
3642
+ this.bindable(addr);
3643
+ this.local = this.net.bind(this, addr, kernel, name2);
3635
3644
  this.boundAt = this.local;
3636
3645
  }
3637
3646
  listen(backlog, cred) {
@@ -3669,7 +3678,7 @@ var KernelSocket = class _KernelSocket {
3669
3678
  waitRoom(signal) {
3670
3679
  return this.room.wait(signal);
3671
3680
  }
3672
- connect(addr, viaUplink = true, cred, stamp, waits = true) {
3681
+ connect(addr, viaUplink = true, cred, stamp, waits = true, name2) {
3673
3682
  if (this.state === "connected") throw new KernelError("EISCONN");
3674
3683
  if (this.state === "connecting") throw new KernelError("EALREADY");
3675
3684
  if (this.state !== "open") throw new KernelError("EINVAL");
@@ -3677,7 +3686,7 @@ var KernelSocket = class _KernelSocket {
3677
3686
  this.failed = void 0;
3678
3687
  const route = viaUplink && addr.family === "inet" ? this.net.uplinkFor(addr.host) : void 0;
3679
3688
  if (route) return this.dial(addr, route);
3680
- const target = this.net.target(addr);
3689
+ const target = this.net.target(addr, name2);
3681
3690
  if (!this.local) {
3682
3691
  if (addr.family === "inet") {
3683
3692
  this.local = this.net.bind(this, { family: "inet", host: "127.0.0.1", port: 0 });
@@ -3838,7 +3847,7 @@ var KernelSocket = class _KernelSocket {
3838
3847
  this.readShut = true;
3839
3848
  this.writeShut = true;
3840
3849
  }
3841
- if (this.boundAt) this.net.release(this.boundAt, this);
3850
+ if (this.boundAt) this.net.release(this.boundAt, this, this.named);
3842
3851
  this.boundAt = void 0;
3843
3852
  this.changes.wake();
3844
3853
  }
@@ -3855,7 +3864,8 @@ var KernelSocket = class _KernelSocket {
3855
3864
  function canonicalHost(host) {
3856
3865
  return host === "0.0.0.0" ? "127.0.0.1" : host;
3857
3866
  }
3858
- function keyOf(addr) {
3867
+ function keyOf(addr, name2) {
3868
+ if (name2) return `node:${name2.key}`;
3859
3869
  return addr.family === "inet" ? `inet:${addr.port}` : `unix:${addr.path}`;
3860
3870
  }
3861
3871
  var LOCAL_ONLY = new Routes();
@@ -3934,28 +3944,30 @@ var LoopbackNet = class {
3934
3944
  void socket.connect(addr, false, void 0, void 0, false);
3935
3945
  return socket;
3936
3946
  }
3937
- bind(socket, addr, kernel = false) {
3947
+ bind(socket, addr, kernel = false, name2) {
3938
3948
  if (addr.family === "unix") {
3939
3949
  if (addr.path === "") throw new KernelError("EINVAL");
3940
3950
  } else this.bindable(addr, kernel);
3941
3951
  const named = addr.family === "inet" && addr.port === 0 ? { ...addr, port: this.ephemeral() } : addr;
3942
- const key = keyOf(named);
3943
- if (this.bound.has(key)) throw new KernelError("EADDRINUSE");
3952
+ const key = keyOf(named, name2);
3953
+ if (this.bound.has(key) && !name2) throw new KernelError("EADDRINUSE");
3944
3954
  this.bound.set(key, socket);
3955
+ socket.named = name2;
3945
3956
  return named;
3946
3957
  }
3947
- release(addr, socket) {
3948
- const key = keyOf(addr);
3958
+ release(addr, socket, name2) {
3959
+ const key = keyOf(addr, name2);
3949
3960
  if (this.bound.get(key) === socket) this.bound.delete(key);
3950
3961
  }
3951
- target(addr) {
3962
+ target(addr, name2) {
3952
3963
  if (addr.family === "inet" && !isLoopback(canonicalHost(addr.host))) {
3953
3964
  throw new KernelError("ENETUNREACH");
3954
3965
  }
3955
- const key = keyOf(addr);
3966
+ const key = keyOf(addr, name2);
3956
3967
  if (!this.bound.has(key)) this.activators.get(key)?.();
3957
3968
  const socket = this.bound.get(key);
3958
3969
  if (!socket?.listening) throw new KernelError("ECONNREFUSED");
3970
+ if (name2 && socket.named?.typed && !name2.typed) throw new KernelError("ECONNREFUSED");
3959
3971
  return socket;
3960
3972
  }
3961
3973
  ephemeral() {
@@ -10814,6 +10826,7 @@ function statJson(s) {
10814
10826
  isDirectory: s.isDirectory,
10815
10827
  isFile: s.isFile,
10816
10828
  isSymbolicLink: s.isSymbolicLink,
10829
+ ...s.isSocket ? { isSocket: true } : {},
10817
10830
  size: s.size,
10818
10831
  mode: s.mode,
10819
10832
  mtimeMs: s.mtime.getTime(),
@@ -12184,7 +12197,7 @@ var PATH_OPS = new Set(SYNC_FS_OPS);
12184
12197
  var EARLY_WHOLE_FILE = 64 * 1024;
12185
12198
 
12186
12199
  // src/version.ts
12187
- var KERNEL_VERSION = true ? "1.103.0" : "0.0.0-dev";
12200
+ var KERNEL_VERSION = true ? "1.103.2" : "0.0.0-dev";
12188
12201
  var OS_RELEASE = "6.0.0-slicc";
12189
12202
  function procVersion() {
12190
12203
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -14604,6 +14617,7 @@ async function runChild(req, deps) {
14604
14617
  ...req.argv0 !== void 0 ? { argv0: req.argv0 } : {},
14605
14618
  env: req.env,
14606
14619
  cwd: req.cwd,
14620
+ ...req.chdir ? { chdir: req.chdir } : {},
14607
14621
  ...req.pgid !== void 0 ? { pgid: req.pgid } : {},
14608
14622
  ...req.session ? { session: req.session } : {}
14609
14623
  },
@@ -14889,6 +14903,47 @@ async function semSyscall(req, proc) {
14889
14903
  }
14890
14904
  }
14891
14905
 
14906
+ // src/kernel/socket-nodes.ts
14907
+ function filePath(addr) {
14908
+ if (addr.family !== "unix" || addr.path === "" || addr.path.startsWith("\0")) return void 0;
14909
+ return normalizePath(addr.path);
14910
+ }
14911
+ function nameOf(st) {
14912
+ return { key: `${st.dev ?? 0}:${st.ino}`, typed: st.isSocket === true };
14913
+ }
14914
+ function codeOf3(err) {
14915
+ return err?.code;
14916
+ }
14917
+ function socketNames(deps) {
14918
+ const { fs } = deps;
14919
+ return {
14920
+ async make(path) {
14921
+ const g = deps.guard();
14922
+ if (g) await inParent(g, "bind", path);
14923
+ const owner = deps.owner();
14924
+ try {
14925
+ await deps.create(path, owner);
14926
+ } catch (err) {
14927
+ if (codeOf3(err) === "EEXIST") throw new KernelError("EADDRINUSE");
14928
+ throw err;
14929
+ }
14930
+ const remove = () => fs.rm(path, { file: true }).catch(() => void 0);
14931
+ try {
14932
+ if (!deps.owners && owner.mode !== void 0) await fs.chmod(path, owner.mode);
14933
+ return { ...nameOf(await fs.lstat(path)), remove };
14934
+ } catch (err) {
14935
+ await remove();
14936
+ throw err;
14937
+ }
14938
+ },
14939
+ async find(path) {
14940
+ const g = deps.guard();
14941
+ if (g) await need(g, "connect", path, W_OK, { directory: false });
14942
+ return nameOf(await fs.stat(path));
14943
+ }
14944
+ };
14945
+ }
14946
+
14892
14947
  // src/kernel/net/datagram-wire.ts
14893
14948
  function encodeReceived(got) {
14894
14949
  const host = new TextEncoder().encode(got.host);
@@ -14955,7 +15010,7 @@ async function socketSyscall(req, proc) {
14955
15010
  }
14956
15011
  }
14957
15012
  case "sock-bind":
14958
- anySocketAt(fds, req.fd).bind(req.addr);
15013
+ await bind(proc, req.fd, req.addr);
14959
15014
  return ok3();
14960
15015
  case "sock-listen":
14961
15016
  socketAt(fds, req.fd).listen(req.backlog, proc.cred?.());
@@ -14993,8 +15048,10 @@ async function connect(req, proc) {
14993
15048
  target.connectTo(req.addr);
14994
15049
  return ok3();
14995
15050
  }
15051
+ const path = filePath(req.addr);
15052
+ const name2 = path !== void 0 ? await proc.names?.find(path) : void 0;
14996
15053
  const stamp = proc.net.facadeAt(req.addr) && await proc.stamp?.();
14997
- const dialing = target.connect(req.addr, true, proc.cred?.(), stamp || void 0);
15054
+ const dialing = target.connect(req.addr, true, proc.cred?.(), stamp || void 0, true, name2);
14998
15055
  if (req.nonblock) {
14999
15056
  dialing?.catch(() => void 0);
15000
15057
  throw new KernelError("EINPROGRESS");
@@ -15002,6 +15059,22 @@ async function connect(req, proc) {
15002
15059
  if (dialing !== void 0) await interruptible2(dialing, proc.blocking());
15003
15060
  return ok3();
15004
15061
  }
15062
+ async function bind(proc, fd, addr) {
15063
+ const socket = anySocketAt(proc.fds, fd);
15064
+ const path = filePath(addr);
15065
+ if (!(socket instanceof KernelSocket) || path === void 0 || !proc.names) {
15066
+ socket.bind(addr);
15067
+ return;
15068
+ }
15069
+ socket.bindable(addr);
15070
+ const name2 = await proc.names.make(path);
15071
+ try {
15072
+ socket.bind({ family: "unix", path }, false, name2);
15073
+ } catch (err) {
15074
+ await name2.remove();
15075
+ throw err;
15076
+ }
15077
+ }
15005
15078
  async function datagram(req, proc) {
15006
15079
  const dgram = dgramAt(proc.fds, req.fd);
15007
15080
  if (req.op === "sock-sendto") {
@@ -15609,6 +15682,11 @@ function heldIo(fs, nodes, changed) {
15609
15682
  const held = st.isFile ? await node(path) : void 0;
15610
15683
  return held ? { ...st, size: await held.serial(() => held.size()) } : st;
15611
15684
  },
15685
+ async lstat(path) {
15686
+ const st = await fs.lstat(path);
15687
+ const held = st.isFile && !st.isSymbolicLink ? await node(path) : void 0;
15688
+ return held ? { ...st, size: await held.serial(() => held.size()) } : st;
15689
+ },
15612
15690
  async readFileBuffer(path) {
15613
15691
  const held = await node(path);
15614
15692
  if (!held) return fs.readFileBuffer(path);
@@ -16022,13 +16100,23 @@ var WasmProcess = class {
16022
16100
  return "deliver";
16023
16101
  }
16024
16102
  async spawn(req) {
16025
- const { file, argv, argv0, env, cwd, stdio, inherit: inherit2, exec, pgid, session, deathSignal } = req;
16103
+ const { file, argv, argv0, env, cwd, chdir, stdio, inherit: inherit2, exec, pgid, session, deathSignal } = req;
16026
16104
  if (deathSignal !== void 0 && (exec || !isSignal(deathSignal))) {
16027
16105
  throw new KernelError("EINVAL");
16028
16106
  }
16029
16107
  const group = { ...pgid !== void 0 ? { pgid } : {}, ...session ? { session } : {} };
16030
16108
  const named = argv0 !== void 0 ? { argv0 } : {};
16031
- const spawned = { file, argv, ...named, env, cwd, ...group, ...exec ? { exec } : {} };
16109
+ const moved2 = chdir ? { chdir } : {};
16110
+ const spawned = {
16111
+ file,
16112
+ argv,
16113
+ ...named,
16114
+ env,
16115
+ cwd,
16116
+ ...moved2,
16117
+ ...group,
16118
+ ...exec ? { exec } : {}
16119
+ };
16032
16120
  const pid = await this.children.spawn(spawned, stdio, inherit2);
16033
16121
  if (deathSignal !== void 0) this.onDeath(pgid === 0 || session ? -pid : pid, deathSignal);
16034
16122
  if (!exec) return pid;
@@ -16895,7 +16983,19 @@ var WasmProcess = class {
16895
16983
  blocking: () => this.blockingSignal(cancelled),
16896
16984
  resolve: (name2, family, blocking) => resolver.resolve(name2, family, blocking),
16897
16985
  cred: () => ({ pid: this.pid, uid: this.cred.euid, gid: this.cred.egid }),
16898
- stamp: () => this.connectorStamp()
16986
+ stamp: () => this.connectorStamp(),
16987
+ names: socketNames({
16988
+ fs: this.heldFs(),
16989
+ guard: () => this.guarded(),
16990
+ create: (path, owner) => this.nodes.createExclusive(path, owner),
16991
+ owner: () => ({
16992
+ uid: this.cred.euid,
16993
+ gid: this.cred.egid,
16994
+ mode: 511 & ~this.umask,
16995
+ socket: true
16996
+ }),
16997
+ owners: this.options.owners === true
16998
+ })
16899
16999
  });
16900
17000
  }
16901
17001
  tty(fd) {
@@ -18969,8 +19069,8 @@ var FSA_CAPABILITIES = {
18969
19069
  ranges: true,
18970
19070
  sessions: true
18971
19071
  };
18972
- var codeOf3 = (err) => err?.code;
18973
- var denied = (err) => codeOf3(err) === "EACCES" || err?.name === "NotAllowedError";
19072
+ var codeOf4 = (err) => err?.code;
19073
+ var denied = (err) => codeOf4(err) === "EACCES" || err?.name === "NotAllowedError";
18974
19074
  function attrOf(st) {
18975
19075
  return {
18976
19076
  kind: st.isDirectory ? "directory" : st.isSymbolicLink ? "symlink" : "file",
@@ -18992,7 +19092,7 @@ function kernelFsHandlers(fs) {
18992
19092
  try {
18993
19093
  return await fs.stat(path);
18994
19094
  } catch (err) {
18995
- if (codeOf3(err) === "ENOENT") return void 0;
19095
+ if (codeOf4(err) === "ENOENT") return void 0;
18996
19096
  throw err;
18997
19097
  }
18998
19098
  }
@@ -19185,7 +19285,7 @@ function parseFstab(text) {
19185
19285
  });
19186
19286
  return lines2;
19187
19287
  }
19188
- function codeOf4(err) {
19288
+ function codeOf5(err) {
19189
19289
  const code = err?.code;
19190
19290
  return typeof code === "string" ? code : "EIO";
19191
19291
  }
@@ -19223,18 +19323,18 @@ async function mountLine({ line, spec, invalid }, mount, signal, retries, discar
19223
19323
  break;
19224
19324
  } catch (err) {
19225
19325
  failed3 = err;
19226
- if (FINAL.has(codeOf4(err)) || attempt === retries.length) break;
19326
+ if (FINAL.has(codeOf5(err)) || attempt === retries.length) break;
19227
19327
  await wait(retries[attempt], signal);
19228
19328
  }
19229
19329
  }
19230
- const code = codeOf4(failed3);
19330
+ const code = codeOf5(failed3);
19231
19331
  return { line, target: spec.target, code, error: String(failed3?.message ?? code) };
19232
19332
  }
19233
19333
 
19234
19334
  // src/mount/hostfs.ts
19235
19335
  var HOSTFS_IO = 16 * 1024 * 1024;
19236
- var codeOf5 = (err) => err?.code;
19237
- var unreachable = (err) => codeOf5(err) === "ENOTCONN";
19336
+ var codeOf6 = (err) => err?.code;
19337
+ var unreachable = (err) => codeOf6(err) === "ENOTCONN";
19238
19338
  function rel(path) {
19239
19339
  return path.replace(/^\/+/, "");
19240
19340
  }
@@ -19411,7 +19511,7 @@ function hostfsHandlers(current, againMs = RESTORE_AGAIN_MS) {
19411
19511
  try {
19412
19512
  return { opened: await opening2(), restore: void 0 };
19413
19513
  } catch (err) {
19414
- if (!flags2.write || codeOf5(err) !== "EACCES") throw err;
19514
+ if (!flags2.write || codeOf6(err) !== "EACCES") throw err;
19415
19515
  const was = await client.call("stat", { path: rel(path) });
19416
19516
  const mode = was.mode ?? 0;
19417
19517
  if (mode & 128) throw err;
@@ -21432,6 +21532,13 @@ var Launcher = class {
21432
21532
  await fds.closeAll();
21433
21533
  throw new SpawnError(await this.unrunnable(file, req.cwd, scope));
21434
21534
  }
21535
+ async enterable(g, cwd) {
21536
+ if (!g) return;
21537
+ const denied2 = new Error(`cannot change to ${cwd}: Permission denied`);
21538
+ await need(g, "chdir", cwd, X_OK, { directory: true }).catch((err) => {
21539
+ throw err.code === "EACCES" ? Object.assign(denied2, { code: "EACCES" }) : err;
21540
+ });
21541
+ }
21435
21542
  execGuard(cred, pid, tag) {
21436
21543
  const { dac } = this;
21437
21544
  return dac && { fs: this.fs, cred, pid, dac, tag, links: this.links.get(pid) };
@@ -22048,6 +22155,13 @@ var Launcher = class {
22048
22155
  throw new SpawnError(group);
22049
22156
  }
22050
22157
  const cred = grant ? grant.cred : this.credOf(ppid);
22158
+ if (req.chdir && !grant) {
22159
+ const g = this.execGuard(cred, ppid);
22160
+ await this.enterable(g, req.cwd).catch(async (err) => {
22161
+ await fds.closeAll();
22162
+ throw err.code === "EACCES" ? new SpawnError("EACCES") : err;
22163
+ });
22164
+ }
22051
22165
  const scope = grant ? "" : await this.scopeOf(cred.euid);
22052
22166
  const file = booked === void 0 ? req.file : await this.ticketFile(req, fds);
22053
22167
  const planned = await this.checkedPlan({ ...req, file }, { ppid, cred, scope }, fds);
@@ -22644,6 +22758,7 @@ var Launcher = class {
22644
22758
  const scope = account.uid === 0 ? "" : pnpmHomeOf(account, this.pnpmHome);
22645
22759
  const start2 = dir ?? "/";
22646
22760
  const cwd = await physicalPathAsync(this.base, start2.startsWith("/") ? start2 : `/${start2}`);
22761
+ await this.enterable(this.execGuard(credOf(account), 0, tag), cwd);
22647
22762
  const file = await this.execFile(argv[0] ?? "", cwd, this.execGuard(credOf(account), 0, tag));
22648
22763
  if (!await this.base.exists(cwd)) await this.stackFor(tag).fs.mkdir(cwd, { recursive: true });
22649
22764
  const planned = await this.plan(file, argv, cwd, scope);