@ai-ecoverse/slicc-kernel 1.77.0 → 1.77.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.
@@ -373,6 +373,9 @@ function writerTags(protection) {
373
373
  return new Set(writers);
374
374
  }
375
375
  function protectedPrefixes(paths) {
376
+ if (!Array.isArray(paths) || paths.some((p) => typeof p !== "string" || !p.startsWith("/"))) {
377
+ throw new TypeError("protect.paths must be a list of absolute paths");
378
+ }
376
379
  return [...new Set(paths.map((p) => normalizePath(p)))];
377
380
  }
378
381
  function within(path, prefix) {
@@ -476,6 +479,9 @@ var ProtectedFs = class {
476
479
  await check(path, true);
477
480
  return fs.utimes(path, atime, mtime);
478
481
  },
482
+ async mayChange(path, follow2) {
483
+ await check(path, follow2);
484
+ },
479
485
  async stat(path) {
480
486
  return marked(path, await fs.stat(path));
481
487
  },
@@ -954,6 +960,7 @@ var OpfsFs = class {
954
960
  }
955
961
  }
956
962
  async current(path, dir) {
963
+ if (dir === this.root) return path === "/";
957
964
  if (performance.now() - (this.checked.get(dir) ?? -CHECK_MS) < CHECK_MS) return true;
958
965
  const where = await this.root.resolve(dir).catch(() => null);
959
966
  if (where === null || `/${where.join("/")}` !== path) return false;
@@ -1155,6 +1162,10 @@ var OpfsFs = class {
1155
1162
  };
1156
1163
  }
1157
1164
  async describe(found) {
1165
+ const stat = await this.described(found);
1166
+ return isProtected(this.guarded, found.path) ? { ...stat, readonly: true } : stat;
1167
+ }
1168
+ async described(found) {
1158
1169
  if (found.link) return this.owned(this.linkStat(found.link), found.path, found.link);
1159
1170
  const touched = this.timesOf(found.path);
1160
1171
  if (!this.owners) {
@@ -7318,6 +7329,83 @@ function withCommandDirs(fs, names, userDir = async () => void 0, owners = false
7318
7329
  };
7319
7330
  }
7320
7331
 
7332
+ // src/fs/fresh-modules.ts
7333
+ var MAGIC = [0, 97, 115, 109];
7334
+ var MAX_FRESH = 65536;
7335
+ function isModule(bytes) {
7336
+ return MAGIC.every((b, i) => bytes[i] === b);
7337
+ }
7338
+ var FreshModules = class {
7339
+ fresh = /* @__PURE__ */ new Map();
7340
+ add(path, umask, pid) {
7341
+ const key = normalizePath(path);
7342
+ this.fresh.delete(key);
7343
+ const oldest = this.fresh.size >= MAX_FRESH ? this.fresh.keys().next().value : void 0;
7344
+ if (oldest !== void 0) this.fresh.delete(oldest);
7345
+ this.fresh.set(key, { umask: umask & 511, pid, added: 0 });
7346
+ }
7347
+ forget(pid) {
7348
+ for (const [path, fresh2] of this.fresh) if (fresh2.pid === pid) this.fresh.delete(path);
7349
+ }
7350
+ wrap(fs) {
7351
+ const decide = async (given, bytes) => {
7352
+ const path = normalizePath(given);
7353
+ const fresh2 = this.fresh.get(path);
7354
+ if (!fresh2 || typeof bytes === "string" || bytes.length < MAGIC.length) return;
7355
+ const want = isModule(bytes) ? 73 & ~fresh2.umask : 0;
7356
+ if (want === fresh2.added) return;
7357
+ const mode = (await fs.stat(path)).mode & 4095;
7358
+ await fs.chmod(path, mode & ~fresh2.added | want);
7359
+ fresh2.added = want;
7360
+ };
7361
+ const overrides = {
7362
+ writeFile: async (path, content, owner) => {
7363
+ await fs.writeFile(path, content, owner);
7364
+ await decide(path, content);
7365
+ },
7366
+ chmod: async (path, mode) => {
7367
+ const fresh2 = this.fresh.get(normalizePath(path));
7368
+ const creating = fresh2?.added === 0 && (mode & 4095) === (438 & ~fresh2.umask);
7369
+ if (!creating) this.fresh.delete(normalizePath(path));
7370
+ await fs.chmod(path, mode);
7371
+ },
7372
+ rm: async (path, options) => {
7373
+ this.fresh.delete(normalizePath(path));
7374
+ await fs.rm(path, options);
7375
+ },
7376
+ rename: async (from, to) => {
7377
+ await fs.rename(from, to);
7378
+ const fresh2 = this.fresh.get(normalizePath(from));
7379
+ this.fresh.delete(normalizePath(from));
7380
+ this.fresh.delete(normalizePath(to));
7381
+ if (fresh2) this.fresh.set(normalizePath(to), fresh2);
7382
+ }
7383
+ };
7384
+ const ranged2 = rangedOps(fs);
7385
+ if (ranged2) {
7386
+ overrides.pwrite = async (path, at, bytes, transfer) => {
7387
+ const head = at === 0 && this.fresh.has(normalizePath(path)) ? bytes.slice(0, 4) : void 0;
7388
+ await ranged2.pwrite(path, at, bytes, transfer);
7389
+ if (head) await decide(path, head);
7390
+ };
7391
+ }
7392
+ const bound = /* @__PURE__ */ new WeakMap();
7393
+ return new Proxy(fs, {
7394
+ get(target, key, receiver) {
7395
+ if (Object.hasOwn(overrides, key)) return overrides[key];
7396
+ const value = Reflect.get(target, key, receiver);
7397
+ if (typeof value !== "function") return value;
7398
+ let method = bound.get(value);
7399
+ if (method === void 0) {
7400
+ method = value.bind(target);
7401
+ bound.set(value, method);
7402
+ }
7403
+ return method;
7404
+ }
7405
+ });
7406
+ }
7407
+ };
7408
+
7321
7409
  // src/fs/physical-path.ts
7322
7410
  var MAX_HOPS = 40;
7323
7411
  function start(path) {
@@ -9194,6 +9282,7 @@ async function run(entry, path, req) {
9194
9282
  case "create":
9195
9283
  await createExclusive(fs, path, ownerFor2(entry, req.mode ?? 438));
9196
9284
  entry.created?.add(path);
9285
+ entry.fresh?.(path);
9197
9286
  return done;
9198
9287
  case "readlink":
9199
9288
  return json2(await fs.readlink(path));
@@ -9292,11 +9381,39 @@ async function accessOp(entry, path, req) {
9292
9381
  await need({ ...g, cred }, open ? "open" : "access", path, req.mode ?? 0, options);
9293
9382
  return done;
9294
9383
  }
9384
+ var CHANGING = /* @__PURE__ */ new Set([
9385
+ "mkdir",
9386
+ "create",
9387
+ "symlink",
9388
+ "unlink",
9389
+ "rmdir",
9390
+ "rm",
9391
+ "rename",
9392
+ "link",
9393
+ "utimes",
9394
+ "lutimes",
9395
+ "chmod",
9396
+ "chown",
9397
+ "lchown"
9398
+ ]);
9399
+ var CONTENT = /* @__PURE__ */ new Set(["write", "pwrite", "truncate"]);
9400
+ async function mayChange(entry, path, req) {
9401
+ const { mayChange: mayChange2 } = entry.fs;
9402
+ if (!mayChange2) return;
9403
+ const { op } = req;
9404
+ if (CONTENT.has(op) && req.handle === void 0) return mayChange2.call(entry.fs, path, true);
9405
+ if (!CHANGING.has(op)) return;
9406
+ await mayChange2.call(entry.fs, path, op === "utimes" || op === "chmod" || op === "chown");
9407
+ if (op === "rename" || op === "link") {
9408
+ await mayChange2.call(entry.fs, entry.fs.resolvePath(entry.cwd, req.arg2 ?? ""), false);
9409
+ }
9410
+ }
9295
9411
  async function guarded(entry, path, req) {
9296
9412
  const g = guardOf(entry);
9297
9413
  if (!g) return void 0;
9298
9414
  if (LOOKS.has(req.op) && await entry.holdsKept?.(path)) return void 0;
9299
9415
  try {
9416
+ await mayChange(entry, path, req);
9300
9417
  await guard(g, path, req, entry.cwd);
9301
9418
  return void 0;
9302
9419
  } catch (err) {
@@ -12613,6 +12730,7 @@ var WasmProcess = class {
12613
12730
  throw Object.assign(new Error(alias.refused), { code: alias.refused });
12614
12731
  if (alias !== void 0) return this.openProc(req, alias);
12615
12732
  await refuseReadonly(this.options.fs, req.path, req.flags, req);
12733
+ if (this.writesAt(req)) await this.options.fs.mayChange?.(req.path, !req.exclusive);
12616
12734
  await this.mayOpen(req);
12617
12735
  const fd = this.fds.install(heldFile(), 3);
12618
12736
  try {
@@ -13483,6 +13601,7 @@ function holdingToken(opts, holds, caller) {
13483
13601
  return mintSyncFsToken({
13484
13602
  ...opts.owners ? caller : {},
13485
13603
  ...opts.dac ? { dac: opts.dac, pid: opts.pid, created: caller.created } : {},
13604
+ ...opts.fresh ? { fresh: (path) => opts.fresh?.(path, caller.umask()) } : {},
13486
13605
  fs: opts.fs,
13487
13606
  cwd: opts.cwd,
13488
13607
  ...opts.statfs ? { statfs: opts.statfs } : {},
@@ -16321,6 +16440,7 @@ var Launcher = class {
16321
16440
  described = /* @__PURE__ */ new Map();
16322
16441
  creds = /* @__PURE__ */ new Map();
16323
16442
  tags = /* @__PURE__ */ new Map();
16443
+ freshModules = new FreshModules();
16324
16444
  granted = /* @__PURE__ */ new Map();
16325
16445
  users;
16326
16446
  sudoer;
@@ -16391,7 +16511,8 @@ var Launcher = class {
16391
16511
  changed: this.watchers.changed.bind(this.watchers),
16392
16512
  owners: this.owners
16393
16513
  });
16394
- this.base = this.watchers.wrap(this.mounts.wrap(options.fs));
16514
+ const watched = this.watchers.wrap(this.mounts.wrap(options.fs));
16515
+ this.base = this.owners ? this.freshModules.wrap(watched) : watched;
16395
16516
  this.createWorker = options.createWorker;
16396
16517
  this.createDriverWorker = options.createDriverWorker;
16397
16518
  this.media = options.media ?? memoryMedia();
@@ -16794,6 +16915,7 @@ var Launcher = class {
16794
16915
  ...req.ignored ? { ignored: req.ignored } : {},
16795
16916
  ...req.umask !== void 0 ? { umask: req.umask } : {},
16796
16917
  cred: req.cred,
16918
+ ...this.owners && req.program.abi === "wasi" ? { fresh: (path, umask) => this.freshModules.add(path, umask, pid) } : {},
16797
16919
  ...this.owners ? { owners: true } : {},
16798
16920
  sealed: this.sealed,
16799
16921
  clipboard: this.clipboard,
@@ -16856,6 +16978,7 @@ var Launcher = class {
16856
16978
  (state) => state === "stopped" ? this.stopped.add(pid) : this.stopped.delete(pid)
16857
16979
  );
16858
16980
  void handle.exited.then(() => {
16981
+ this.freshModules.forget(pid);
16859
16982
  const spent = handle.times?.();
16860
16983
  if (spent) this.spent.set(pid, spent);
16861
16984
  if (spent) addTimes(this.imageTimes, this.jobs.shown(pid), spent);
@@ -17522,8 +17645,9 @@ var Launcher = class {
17522
17645
  return this.writers;
17523
17646
  }
17524
17647
  writerStack() {
17648
+ const watched = this.watchers.wrap(this.mounts.wrap(this.unguardedRoot));
17525
17649
  const fs = withCommandDirs(
17526
- this.watchers.wrap(this.mounts.wrap(this.unguardedRoot)),
17650
+ this.owners ? this.freshModules.wrap(watched) : watched,
17527
17651
  async () => new Set((await this.commands()).keys()),
17528
17652
  (dir) => this.userCommandDir(dir),
17529
17653
  this.owners