@ai-ecoverse/slicc-kernel 1.39.1 → 1.39.3

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.
@@ -831,7 +831,10 @@ function createNodeOps(h) {
831
831
  const perm = mode & PERM_MASK & ~UMASK;
832
832
  if (perm !== DEFAULT_DIR_PERM) metadataCall(() => bridgeOf(parent).chmod(path, perm));
833
833
  } else if (Fs.isFile(mode)) {
834
- call2(() => bridgeOf(parent).writeFile(path, new Uint8Array(0)));
834
+ const bridge = bridgeOf(parent);
835
+ call2(
836
+ () => bridge.create ? bridge.create(path) : bridge.writeFile(path, new Uint8Array(0))
837
+ );
835
838
  } else {
836
839
  throw new Fs.ErrnoError(wasiErrno("EPERM"));
837
840
  }
@@ -1326,6 +1329,7 @@ var init_sync_fs_wire = __esm({
1326
1329
  "lutimes",
1327
1330
  "statfs",
1328
1331
  "hold",
1332
+ "create",
1329
1333
  "pread",
1330
1334
  "pwrite",
1331
1335
  "truncate"
@@ -1567,6 +1571,9 @@ function createSyncFsSabBridge(transport, opts = {}) {
1567
1571
  lutimes: (path, atimeMs, mtimeMs) => {
1568
1572
  run({ op: "lutimes", path, atimeMs, mtimeMs }, path);
1569
1573
  },
1574
+ create: (path) => {
1575
+ run({ op: "create", path }, path);
1576
+ },
1570
1577
  hold: (path, held, open) => {
1571
1578
  run({ op: "hold", path, mode: (held ? 1 : 0) | (open ? 2 : 0) }, path);
1572
1579
  },
@@ -1805,7 +1812,8 @@ var init_kernel_streams = __esm({
1805
1812
  }
1806
1813
  const pty = this.openPty(open, path, flags, mode);
1807
1814
  if (pty) return pty;
1808
- const stream = open(path, flags, mode);
1815
+ this.refuseExclusiveLink(path, flags);
1816
+ const stream = this.openRacing(open, path, flags, mode);
1809
1817
  if (!stream.tty) return stream;
1810
1818
  if (stream.path === "/dev/tty" && this.sys.openTty) {
1811
1819
  let kfd;
@@ -1834,6 +1842,24 @@ var init_kernel_streams = __esm({
1834
1842
  return stream;
1835
1843
  };
1836
1844
  }
1845
+ openRacing(open, path, flags, mode) {
1846
+ try {
1847
+ return open(path, flags, mode);
1848
+ } catch (err) {
1849
+ const lost = err.errno === wasiErrno("EEXIST") && !(flags & O_EXCL);
1850
+ if (!lost) throw err;
1851
+ return open(path, flags, mode);
1852
+ }
1853
+ }
1854
+ refuseExclusiveLink(path, flags) {
1855
+ if ((flags & (O_CREAT | O_EXCL)) !== (O_CREAT | O_EXCL)) return;
1856
+ let mode = 0;
1857
+ try {
1858
+ mode = this.Fs.stat?.(path, true)?.mode ?? 0;
1859
+ } catch {
1860
+ }
1861
+ if ((mode & 61440) === 40960) throw new this.Fs.ErrnoError(wasiErrno("EEXIST"));
1862
+ }
1837
1863
  openPty(open, path, flags, mode) {
1838
1864
  const pts = /^\/dev\/pts\/(\d+)$/.exec(path);
1839
1865
  if (path !== "/dev/ptmx" && !pts) return void 0;
@@ -2902,6 +2928,7 @@ function createProcessKernel(deps) {
2902
2928
  if (!stream) return { none: true };
2903
2929
  promote?.(stream);
2904
2930
  if (stream.sliccKernelFd !== void 0) return { fd: stream.sliccKernelFd };
2931
+ if (((stream.node?.mode ?? 0) & S_IFMT) === S_IFDIR2 && stream.path) return { dir: stream.path };
2905
2932
  const device2 = deviceOfStream(stream);
2906
2933
  if (device2) return device2;
2907
2934
  return n === 0 ? { input: drain(Fs, stream) } : { capture: true };
@@ -3045,12 +3072,14 @@ function createProcessKernel(deps) {
3045
3072
  }
3046
3073
  };
3047
3074
  }
3048
- var POLLIN2, POLLOUT2, POLLERR2, POLLHUP2, POLLNVAL, SELECT_SLICE_MS, WUNTRACED, WCONTINUED;
3075
+ var S_IFMT, S_IFDIR2, POLLIN2, POLLOUT2, POLLERR2, POLLHUP2, POLLNVAL, SELECT_SLICE_MS, WUNTRACED, WCONTINUED;
3049
3076
  var init_process_children = __esm({
3050
3077
  "src/process/process-children.ts"() {
3051
3078
  "use strict";
3052
3079
  init_process_fork();
3053
3080
  init_wasi_errno();
3081
+ S_IFMT = 61440;
3082
+ S_IFDIR2 = 16384;
3054
3083
  POLLIN2 = 1;
3055
3084
  POLLOUT2 = 4;
3056
3085
  POLLERR2 = 8;
@@ -3759,7 +3788,7 @@ function kernelSys(transport) {
3759
3788
  kind(fd) {
3760
3789
  return json(call2({ op: "fd-info", fd }, `fd-info ${fd}`))?.kind;
3761
3790
  },
3762
- device(fd) {
3791
+ heldMeta(fd) {
3763
3792
  return json(call2({ op: "fd-info", fd }, `fd-info ${fd}`)).meta;
3764
3793
  },
3765
3794
  size(fd) {
@@ -3823,9 +3852,15 @@ function wireKernelFd(Fs, streams, entry) {
3823
3852
  }
3824
3853
  function openDevice(Fs, fd, meta) {
3825
3854
  const flags = meta.access === "read" ? O_RDONLY : meta.access === "write" ? O_WRONLY3 : O_RDWR3;
3855
+ return openAt(Fs, fd, `/dev/${meta.device}`, flags);
3856
+ }
3857
+ function openHeld(Fs, fd, meta) {
3858
+ return "dir" in meta ? openAt(Fs, fd, meta.dir, O_RDONLY | O_DIRECTORY) : openDevice(Fs, fd, meta);
3859
+ }
3860
+ function openAt(Fs, fd, path, flags) {
3826
3861
  let stream;
3827
3862
  try {
3828
- stream = Fs.open(`/dev/${meta.device}`, flags);
3863
+ stream = Fs.open(path, flags);
3829
3864
  } catch {
3830
3865
  return false;
3831
3866
  }
@@ -3840,8 +3875,8 @@ function wireKernelStdio(Fs, streams, sys) {
3840
3875
  const stream = Fs.getStream(fd);
3841
3876
  if (!stream) continue;
3842
3877
  const kind = sys?.kind?.(fd);
3843
- const device2 = kind === "device" ? sys?.device?.(fd) : void 0;
3844
- if (device2 && openDevice(Fs, fd, device2)) continue;
3878
+ const meta = kind === "device" || kind === "held" ? sys?.heldMeta?.(fd) : void 0;
3879
+ if (meta && openHeld(Fs, fd, meta)) continue;
3845
3880
  if (kind && PLACED.has(kind)) {
3846
3881
  const { flags } = stream;
3847
3882
  Fs.closeStream(fd);
@@ -4093,7 +4128,7 @@ function runMain(running, init) {
4093
4128
  return status2;
4094
4129
  }
4095
4130
  }
4096
- var FS_OPS, O_RDONLY, O_WRONLY3, O_RDWR3, PLACED, GLUE_TRAILER, evaluateGlue, EVAL_BLOCKED;
4131
+ var FS_OPS, O_RDONLY, O_WRONLY3, O_RDWR3, O_DIRECTORY, PLACED, GLUE_TRAILER, evaluateGlue, EVAL_BLOCKED;
4097
4132
  var init_process_runtime = __esm({
4098
4133
  "src/process/process-runtime.ts"() {
4099
4134
  "use strict";
@@ -4118,6 +4153,7 @@ var init_process_runtime = __esm({
4118
4153
  O_RDONLY = 0;
4119
4154
  O_WRONLY3 = 1;
4120
4155
  O_RDWR3 = 2;
4156
+ O_DIRECTORY = 65536;
4121
4157
  PLACED = /* @__PURE__ */ new Set(["stream", "file", "socket"]);
4122
4158
  GLUE_TRAILER = [
4123
4159
  "if (typeof ENV !== 'undefined') Object.assign(ENV, Module.sliccEnv);",
@@ -4321,6 +4357,7 @@ function cachingBridge(bridge, now = () => performance.now()) {
4321
4357
  utimes: (p, a, m) => mutating(() => bridge.utimes(p, a, m)),
4322
4358
  lutimes: (p, a, m) => mutating(() => bridge.lutimes(p, a, m)),
4323
4359
  ...bridge.hold ? { hold: bridge.hold.bind(bridge) } : {},
4360
+ ...bridge.create ? { create: (p) => mutating(() => bridge.create?.(p)) } : {},
4324
4361
  ...bridge.pread && bridge.pwrite && bridge.truncate ? {
4325
4362
  pread: bridge.pread.bind(bridge),
4326
4363
  pwrite: (p, at, bytes, transfer) => mutating(() => bridge.pwrite?.(p, at, bytes, transfer)),
@@ -4613,7 +4650,7 @@ var init_wasi_fds = __esm({
4613
4650
  this.fs = fs;
4614
4651
  }
4615
4652
  setup(cwd, inherited, root = false) {
4616
- for (const fd of [0, 1, 2]) this.table.set(fd, kernelEntry2());
4653
+ for (const fd of [0, 1, 2]) this.table.set(fd, this.stdioEntry(fd));
4617
4654
  const preopens = this.preopens(cwd, root);
4618
4655
  const top = 3 + preopens.length;
4619
4656
  for (const { fd, kind, flags, device: device2 } of inherited) {
@@ -4700,6 +4737,15 @@ var init_wasi_fds = __esm({
4700
4737
  const gen = Atomics.add(this.shared, GEN, 1) + 1;
4701
4738
  if (gen - 1 === this.seen) this.seen = gen;
4702
4739
  }
4740
+ stdioEntry(fd) {
4741
+ let info;
4742
+ try {
4743
+ info = this.kernel.call({ op: "fd-info", fd });
4744
+ } catch {
4745
+ return kernelEntry2();
4746
+ }
4747
+ return info?.meta && "dir" in info.meta ? { type: "dir", path: info.meta.dir } : kernelEntry2();
4748
+ }
4703
4749
  fetch(fd) {
4704
4750
  let info;
4705
4751
  try {
@@ -4982,8 +5028,10 @@ var init_wasi_fds = __esm({
4982
5028
  }
4983
5029
  const alias = stdioAlias(path);
4984
5030
  if (alias !== void 0) return this.reopen(alias);
5031
+ const exclusive = (oflags & OFLAGS.CREAT) !== 0 && (oflags & OFLAGS.EXCL) !== 0;
5032
+ if (exclusive && this.isLink(path)) throw new WasiError("EEXIST");
4985
5033
  const s = this.statOrMissing(path);
4986
- if (s && oflags & OFLAGS.CREAT && oflags & OFLAGS.EXCL) throw new WasiError("EEXIST");
5034
+ if (exclusive && s) throw new WasiError("EEXIST");
4987
5035
  if (oflags & OFLAGS.DIRECTORY && !s?.isDirectory) {
4988
5036
  throw new WasiError(s ? "ENOTDIR" : "ENOENT");
4989
5037
  }
@@ -4998,8 +5046,8 @@ var init_wasi_fds = __esm({
4998
5046
  if (buffer) {
4999
5047
  if (oflags & OFLAGS.TRUNC) buffer.truncate(0);
5000
5048
  } else {
5001
- if (!existing) this.fs.writeFile(path, new Uint8Array(0));
5002
- const empty = !existing || (oflags & OFLAGS.TRUNC) !== 0;
5049
+ const made = !existing && this.createNew(path, oflags);
5050
+ const empty = made || (oflags & OFLAGS.TRUNC) !== 0;
5003
5051
  if (existing?.ranged) this.fs.invalidate?.();
5004
5052
  const st = existing?.ranged || !existing ? this.fs.stat(path) : existing;
5005
5053
  const ranged = st.ranged ? st.size : void 0;
@@ -5014,14 +5062,34 @@ var init_wasi_fds = __esm({
5014
5062
  const { readable, writable } = openAccess(existing, oflags, rights);
5015
5063
  const append = (fdflags & FDFLAGS.APPEND) !== 0;
5016
5064
  const flags = (writable ? readable ? O_RDWR4 : O_WRONLY4 : 0) | (append ? O_APPEND : 0);
5017
- if (!existing) this.fs.writeFile(path, new Uint8Array(0));
5018
- const truncate = !existing || (oflags & OFLAGS.TRUNC) !== 0;
5065
+ const made = !existing && this.createNew(path, oflags);
5066
+ const truncate = made || (oflags & OFLAGS.TRUNC) !== 0;
5019
5067
  const fd = this.kernel.sys.openVfs(path, flags, 0, truncate ? { truncate } : {});
5020
5068
  this.table.set(fd, { type: "kernel", kind: "file", nonblock: false, append });
5021
5069
  if (append) this.publishFlags(fd, { nonblock: false, append });
5022
5070
  this.bump();
5023
5071
  return fd;
5024
5072
  }
5073
+ createNew(path, oflags) {
5074
+ if (!this.fs.create) {
5075
+ this.fs.writeFile(path, new Uint8Array(0));
5076
+ return true;
5077
+ }
5078
+ try {
5079
+ this.fs.create(path);
5080
+ return true;
5081
+ } catch (err) {
5082
+ if (oflags & OFLAGS.EXCL || err.code !== "EEXIST") throw err;
5083
+ return false;
5084
+ }
5085
+ }
5086
+ isLink(path) {
5087
+ try {
5088
+ return this.fs.lstat(path).isSymbolicLink === true;
5089
+ } catch {
5090
+ return false;
5091
+ }
5092
+ }
5025
5093
  statOrMissing(path) {
5026
5094
  try {
5027
5095
  return this.fs.stat(path);