@ai-ecoverse/slicc-kernel 1.56.1 → 1.56.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.
package/README.md CHANGED
@@ -183,6 +183,8 @@ That's for programs that walk to the root, such as Go's (`GOOS=wasip1`) and esbu
183
183
 
184
184
  A descriptor a program inherits at one of those numbers (from bash's `3<file`, or a `posix_spawn` file action) moves to the first free number above them. One above the range keeps its number. A command that takes descriptors by number from its caller should leave `preopenRoot` off, which keeps the shorter range.
185
185
 
186
+ **Paths with `..`.** A `..` after a symlinked directory goes to the parent of the link's target, as on Linux: with `/a/link -> /x/y`, `/a/link/../f` is `/x/f`, for a WASI program as for bash. A `..` after a file or a missing name fails with `ENOTDIR` or `ENOENT`. Paths without `..` are joined as they are.
187
+
186
188
  On top of preview1 a WASI program gets:
187
189
 
188
190
  - **Threads**: `wasi.thread-spawn` (wasm32-wasip1-threads) and WASIX `thread_spawn_v2` start a worker per thread on the process's shared memory, sized from the module's own import (a 2 GiB maximum when the engine cannot reserve more). The threads share one descriptor table; `exit` or a trap in any thread ends the process. At most 64 threads per process; `SLICC_WASM_THREADS` sets another cap, up to 256.
@@ -438,12 +438,34 @@ var OpfsFs = class {
438
438
  const link2 = await this.linkAlong(current);
439
439
  if (!link2) throw err;
440
440
  if (link2.path === current && !follow2) return { path: current, link: link2 };
441
- const rest2 = current.slice(link2.path.length);
442
- current = resolvePath(parentOf2(link2.path), `${link2.link}${rest2}`);
441
+ const target = `${link2.link}${current.slice(link2.path.length)}`;
442
+ current = target.split("/").includes("..") ? await this.physical(parentOf2(link2.path), target, hops + 1) : resolvePath(parentOf2(link2.path), target);
443
443
  }
444
444
  }
445
445
  throw fsError("ELOOP", path);
446
446
  }
447
+ async physical(base, path, used) {
448
+ let done4 = [];
449
+ let todo = (path.startsWith("/") ? path : `${base}/${path}`).split("/").filter((p) => p !== "" && p !== ".");
450
+ for (let hops = used; todo.length > 0; ) {
451
+ const part = todo.shift();
452
+ if (part === "..") done4.pop();
453
+ else if (!todo.includes("..")) done4.push(part);
454
+ else {
455
+ const at = `/${[...done4, part].join("/")}`;
456
+ const st = await this.lstat(at);
457
+ if (!st.isSymbolicLink && !st.isDirectory) throw fsError("ENOTDIR", at);
458
+ if (!st.isSymbolicLink) done4.push(part);
459
+ else if (++hops > MAX_LINKS) throw fsError("ELOOP", path);
460
+ else {
461
+ const link2 = await this.readlink(at);
462
+ if (link2.startsWith("/")) done4 = [];
463
+ todo = [...link2.split("/").filter((p) => p !== "" && p !== "."), ...todo];
464
+ }
465
+ }
466
+ }
467
+ return `/${done4.join("/")}`;
468
+ }
447
469
  mode(path, directory, meta) {
448
470
  const fallback = directory || EXECUTABLE.test(path) ? 493 : 420;
449
471
  return (directory ? S_IFDIR : S_IFREG) | (meta?.mode ?? fallback);
@@ -9631,6 +9653,11 @@ var MAX_LINKS5 = 40;
9631
9653
  function parentOf6(path) {
9632
9654
  return path.slice(0, path.lastIndexOf("/")) || "/";
9633
9655
  }
9656
+ async function mustBeDir(fs, path) {
9657
+ if (!fs.lstat) return;
9658
+ const st = await fs.lstat(path);
9659
+ if (st.isDirectory !== true) throw fsError("ENOTDIR", path);
9660
+ }
9634
9661
  async function linkOf(fs, path) {
9635
9662
  return fs.readlink?.(path).catch(() => void 0);
9636
9663
  }
@@ -9647,6 +9674,7 @@ async function realDir(fs, dir, budget = { hops: 0 }) {
9647
9674
  const next2 = at === "/" ? `/${part}` : `${at}/${part}`;
9648
9675
  const link2 = await linkOf(fs, next2);
9649
9676
  if (link2 === void 0) {
9677
+ if (queue.find((p) => p !== ".") === "..") await mustBeDir(fs, next2);
9650
9678
  at = next2;
9651
9679
  continue;
9652
9680
  }