@ai-ecoverse/slicc-kernel 1.56.1 → 1.57.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.
@@ -493,6 +493,35 @@ function normalize(path) {
493
493
  }
494
494
  return `/${out.join("/")}`;
495
495
  }
496
+ function physical(fs, path) {
497
+ let done = [];
498
+ let todo = path.split("/").filter((part) => part !== "" && part !== ".");
499
+ let hops = 0;
500
+ while (todo.length > 0) {
501
+ const part = todo.shift();
502
+ if (part === "..") {
503
+ done.pop();
504
+ continue;
505
+ }
506
+ if (!todo.includes("..")) {
507
+ done.push(part);
508
+ continue;
509
+ }
510
+ const at = `/${[...done, part].join("/")}`;
511
+ const st = fs.lstat(at);
512
+ if (st.isSymbolicLink) {
513
+ if (++hops > MAX_LINKS) throw new WasiError("ELOOP");
514
+ const target = fs.readlink(at);
515
+ if (target.startsWith("/")) done = [];
516
+ todo = [...target.split("/").filter((p) => p !== "" && p !== "."), ...todo];
517
+ } else if (!st.isDirectory) {
518
+ throw new WasiError("ENOTDIR");
519
+ } else {
520
+ done.push(part);
521
+ }
522
+ }
523
+ return `/${done.join("/")}`;
524
+ }
496
525
  function resolveUnder(dir, path) {
497
526
  return normalize(path.startsWith("/") ? path : `${dir}/${path}`);
498
527
  }
@@ -588,7 +617,7 @@ function pinnedIo(bridge, handle, mutating) {
588
617
  truncate: (p, size) => mutating(() => truncate(p, size))
589
618
  };
590
619
  }
591
- var WasiError, FileBuffer, LocalFile, MISS_TTL_MS;
620
+ var WasiError, FileBuffer, LocalFile, MAX_LINKS, MISS_TTL_MS;
592
621
  var init_wasi_files = __esm({
593
622
  "src/process/wasi/wasi-files.ts"() {
594
623
  "use strict";
@@ -776,6 +805,7 @@ var init_wasi_files = __esm({
776
805
  this.buffer.flush();
777
806
  }
778
807
  };
808
+ MAX_LINKS = 40;
779
809
  MISS_TTL_MS = 20;
780
810
  }
781
811
  });
@@ -1429,8 +1459,8 @@ var init_wasi_fds = __esm({
1429
1459
  }
1430
1460
  }
1431
1461
  resolve(dirfd, path) {
1432
- if (path.startsWith("/")) return normalize(path);
1433
- return resolveUnder(this.dir(dirfd).path, path);
1462
+ const joined2 = path.startsWith("/") ? path : `${this.dir(dirfd).path}/${path}`;
1463
+ return joined2.split("/").includes("..") ? physical(this.fs, joined2) : normalize(joined2);
1434
1464
  }
1435
1465
  open(path, oflags, rights, fdflags) {
1436
1466
  const device2 = deviceOf(path);
@@ -3154,7 +3184,9 @@ function parseSyncFsStat(json) {
3154
3184
  ...s.readonly === true ? { readonly: true } : {},
3155
3185
  ...typeof s.maxFile === "number" ? { maxFile: s.maxFile } : {},
3156
3186
  ...s.ranged === true ? { ranged: true } : {},
3157
- ...typeof s.version === "string" ? { version: s.version } : {}
3187
+ ...typeof s.version === "string" ? { version: s.version } : {},
3188
+ ...typeof s.uid === "number" ? { uid: s.uid } : {},
3189
+ ...typeof s.gid === "number" ? { gid: s.gid } : {}
3158
3190
  };
3159
3191
  }
3160
3192
  var SYNC_FS_OPS, SYNC_FS_REQUEST_TIMEOUT_MS;
@@ -3185,7 +3217,9 @@ var init_sync_fs_wire = __esm({
3185
3217
  "kept",
3186
3218
  "pread",
3187
3219
  "pwrite",
3188
- "truncate"
3220
+ "truncate",
3221
+ "chown",
3222
+ "lchown"
3189
3223
  ];
3190
3224
  SYNC_FS_REQUEST_TIMEOUT_MS = 25e3;
3191
3225
  }
@@ -4177,8 +4211,8 @@ function createSyncFsSabBridge(transport, opts = {}) {
4177
4211
  if (typeof v !== "boolean") throw errnoError("EIO", path);
4178
4212
  return v;
4179
4213
  },
4180
- mkdir: (path) => {
4181
- run({ op: "mkdir", path }, path);
4214
+ mkdir: (path, mode) => {
4215
+ run({ op: "mkdir", path, ...mode !== void 0 ? { mode } : {} }, path);
4182
4216
  },
4183
4217
  rm: (path) => {
4184
4218
  run({ op: "rm", path }, path);
@@ -4209,9 +4243,14 @@ function createSyncFsSabBridge(transport, opts = {}) {
4209
4243
  lutimes: (path, atimeMs, mtimeMs) => {
4210
4244
  run({ op: "lutimes", path, atimeMs, mtimeMs }, path);
4211
4245
  },
4212
- create: (path) => {
4213
- run({ op: "create", path }, path);
4246
+ create: (path, mode) => {
4247
+ run({ op: "create", path, ...mode !== void 0 ? { mode } : {} }, path);
4248
+ },
4249
+ chown: (path, uid, gid) => {
4250
+ const ids = { ...uid !== void 0 ? { uid } : {}, ...gid !== void 0 ? { gid } : {} };
4251
+ run({ op: "lchown", path, ...ids }, path);
4214
4252
  },
4253
+ ...opts.owners ? { owners: true } : {},
4215
4254
  hold: (path, held, open, handle) => {
4216
4255
  const mode = (held ? 1 : 0) | (open ? 2 : 0);
4217
4256
  if (mode === 3) return json({ op: "hold", path, mode }, path);
@@ -5417,6 +5456,7 @@ function createNodeOps(h) {
5417
5456
  return {
5418
5457
  getattr(node) {
5419
5458
  const st = statOf(node);
5459
+ const owned = bridgeOf(node).owners === true;
5420
5460
  const s = node.live;
5421
5461
  const size = Fs.isDir(node.mode) ? 4096 : s.ranged?.size() ?? (s.loaded ? s.len : st.size);
5422
5462
  const mtime = new Date(st.mtimeMs ?? 0);
@@ -5425,8 +5465,8 @@ function createNodeOps(h) {
5425
5465
  ino: st.ino ?? inodeOf(liveNodePath(node)),
5426
5466
  mode: node.mode,
5427
5467
  nlink: 1,
5428
- uid: 0,
5429
- gid: 0,
5468
+ uid: owned ? st.uid ?? 0 : 0,
5469
+ gid: owned ? st.gid ?? 0 : 0,
5430
5470
  rdev: 0,
5431
5471
  size,
5432
5472
  atime: new Date(st.atimeMs ?? mtime.getTime()),
@@ -5469,14 +5509,17 @@ function createNodeOps(h) {
5469
5509
  mknod(parent, name2, mode) {
5470
5510
  parent.live.listed = void 0;
5471
5511
  const path = childPath(parent, name2);
5472
- if (Fs.isDir(mode)) {
5473
- call2(() => bridgeOf(parent).mkdir(path));
5474
- const perm = mode & PERM_MASK & ~UMASK;
5475
- if (perm !== DEFAULT_DIR_PERM) metadataCall(() => bridgeOf(parent).chmod(path, perm));
5512
+ const bridge = bridgeOf(parent);
5513
+ const perm = bridge.owners ? mode & PERM_MASK : void 0;
5514
+ if (Fs.isDir(mode) && perm !== void 0) {
5515
+ call2(() => bridge.mkdir(path, perm));
5516
+ } else if (Fs.isDir(mode)) {
5517
+ call2(() => bridge.mkdir(path));
5518
+ const masked = mode & PERM_MASK & ~UMASK;
5519
+ if (masked !== DEFAULT_DIR_PERM) metadataCall(() => bridge.chmod(path, masked));
5476
5520
  } else if (Fs.isFile(mode)) {
5477
- const bridge = bridgeOf(parent);
5478
5521
  call2(
5479
- () => bridge.create ? bridge.create(path) : bridge.writeFile(path, new Uint8Array(0))
5522
+ () => bridge.create ? bridge.create(path, perm) : bridge.writeFile(path, new Uint8Array(0))
5480
5523
  );
5481
5524
  } else {
5482
5525
  throw new Fs.ErrnoError(wasiErrno("EPERM"));
@@ -5879,6 +5922,32 @@ function guardRenames(Fs) {
5879
5922
  rename(from, to);
5880
5923
  };
5881
5924
  }
5925
+ function idOf(value2) {
5926
+ return value2 === -1 || value2 === 4294967295 ? void 0 : value2 >>> 0;
5927
+ }
5928
+ function useLiveChown(Fs) {
5929
+ const chown = Fs.chown?.bind(Fs);
5930
+ if (!chown) return;
5931
+ Fs.chown = (path, uid, gid, dontFollow) => {
5932
+ const node = typeof path === "string" ? Fs.lookupPath(path, { follow: !dontFollow }).node : path;
5933
+ if (!node.live || node.live.orphan) return chown(path, uid, gid, dontFollow);
5934
+ try {
5935
+ node.mount.opts.bridge.chown?.(liveNodePath(node), idOf(uid), idOf(gid));
5936
+ } catch (err) {
5937
+ throw toErrno(Fs, err);
5938
+ }
5939
+ node.live.stat = void 0;
5940
+ if (node.parent?.live) node.parent.live.listed = void 0;
5941
+ };
5942
+ const { getStreamChecked } = Fs;
5943
+ if (!Fs.fchown || !getStreamChecked) return;
5944
+ Fs.fchown = (fd, uid, gid) => {
5945
+ const stream = getStreamChecked.call(Fs, fd);
5946
+ const live = stream.node.live !== void 0;
5947
+ const target = live || stream.path === void 0 ? stream.node : stream.path;
5948
+ Fs.chown(target, uid, gid);
5949
+ };
5950
+ }
5882
5951
  var S_IFDIR, S_IFREG, S_IFLNK, PERM_MASK, DEFAULT_DIR_PERM, UMASK, SEEK_CUR, SEEK_END, EARLY_WHOLE_FILE;
5883
5952
  var init_live_vfs_fs = __esm({
5884
5953
  "src/realm/live-vfs-fs.ts"() {
@@ -5923,6 +5992,7 @@ function mountVfsIntoEmscripten(Fs, deps) {
5923
5992
  const dirs = topLevelDirs(bridge, warn);
5924
5993
  const { plugin, mounted } = mountLiveVfsDirs(Fs, bridge, dirs ?? [], warn);
5925
5994
  if (dirs) liveRoot(Fs, bridge);
5995
+ if (bridge.owners && Fs.lookupPath) useLiveChown(Fs);
5926
5996
  try {
5927
5997
  Fs.chdir(deps.cwd);
5928
5998
  } catch (err) {
@@ -8328,6 +8398,9 @@ function reportGrowth(imports, publish) {
8328
8398
  return grown;
8329
8399
  };
8330
8400
  }
8401
+ function callerOwner(Fs, init) {
8402
+ return init.owners ? {} : { owner: ownByCaller(Fs, init.cred, credAbi(init.program.glue)) };
8403
+ }
8331
8404
  async function runWasmProcess(init, port3, deps = {}) {
8332
8405
  const signals = new SignalGate(
8333
8406
  createSyncSabTransport(init.sab, port3, {
@@ -8438,7 +8511,7 @@ async function runWasmProcess(init, port3, deps = {}) {
8438
8511
  const running = module;
8439
8512
  if (!hasStreams(running)) return runStdioOnly(running, init);
8440
8513
  const vfs = mountVfsIntoEmscripten(running.FS, {
8441
- bridge: createSyncFsSabBridge(transport),
8514
+ bridge: createSyncFsSabBridge(transport, init.owners ? { owners: true } : {}),
8442
8515
  cwd: init.cwd,
8443
8516
  warn: deps.warn ?? say(2)
8444
8517
  });
@@ -8480,7 +8553,7 @@ async function runWasmProcess(init, port3, deps = {}) {
8480
8553
  describeFork: () => describeForFork(running.FS, sys, streams, livePath),
8481
8554
  inherit: (actions) => describeInherited(running.FS, sys, streams, livePath, actions),
8482
8555
  stdioPromoter: () => vfsPromoter(running.FS, sys, streams, livePath),
8483
- owner: ownByCaller(running.FS, init.cred, credAbi(init.program.glue))
8556
+ ...callerOwner(running.FS, init)
8484
8557
  });
8485
8558
  running.sliccKernel.http = createHttpKernel(transport);
8486
8559
  running.sliccKernel.hostname = hostnameOf(init.env);
@@ -8805,9 +8878,9 @@ function procfsBridge(fs, tree) {
8805
8878
  }
8806
8879
  };
8807
8880
  const readOnly = (paths, run) => {
8808
- const physical = shadowing();
8881
+ const physical2 = shadowing();
8809
8882
  for (const [p, follow2] of paths) {
8810
- if (inProc(p) || physical && toProc(p, follow2) !== void 0) throw syncError("EROFS", p);
8883
+ if (inProc(p) || physical2 && toProc(p, follow2) !== void 0) throw syncError("EROFS", p);
8811
8884
  }
8812
8885
  return run();
8813
8886
  };