@ai-ecoverse/slicc-kernel 1.24.0 → 1.26.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.
@@ -4736,7 +4736,8 @@ function statOf(attr, path, mount) {
4736
4736
  dev: mount.dev,
4737
4737
  ...readonly(mount) ? { readonly: true } : {},
4738
4738
  ...mount.maxFile > 0 ? { maxFile: mount.maxFile } : {},
4739
- ...mount.caps.ranges ? { ranged: true } : {}
4739
+ ...mount.caps.ranges ? { ranged: true } : {},
4740
+ ...attr.etag !== void 0 ? { version: attr.etag } : {}
4740
4741
  };
4741
4742
  }
4742
4743
  function concat4(chunks, total) {
@@ -5071,7 +5072,7 @@ var MountFs = class {
5071
5072
  this.table.forget(mount, real);
5072
5073
  }
5073
5074
  }
5074
- async pread(path, offset, length2) {
5075
+ async pread(path, offset, length2, version) {
5075
5076
  const real = await this.follow(path);
5076
5077
  const found = this.at(real);
5077
5078
  if (!found && this.base.pread) return this.base.pread(real, offset, length2);
@@ -5080,7 +5081,15 @@ var MountFs = class {
5080
5081
  if ((await this.table.getattr(mount, real, rel2)).kind === "directory") {
5081
5082
  throw errnoError("EISDIR", real);
5082
5083
  }
5083
- const fh = await this.open(mount, rel2, false);
5084
+ const fh = await mount.conn.call({
5085
+ op: "open",
5086
+ path: rel2,
5087
+ write: false,
5088
+ create: false,
5089
+ truncate: false,
5090
+ exclusive: false,
5091
+ ...version !== void 0 ? { ifMatch: version } : {}
5092
+ });
5084
5093
  const chunk2 = mount.caps.maxIo ?? DEFAULT_IO;
5085
5094
  const chunks = [];
5086
5095
  let total = 0;
@@ -5342,7 +5351,8 @@ function statJson(s) {
5342
5351
  ...s.dev !== void 0 ? { dev: s.dev } : {},
5343
5352
  ...s.readonly ? { readonly: true } : {},
5344
5353
  ...s.maxFile ? { maxFile: s.maxFile } : {},
5345
- ...s.ranged ? { ranged: true } : {}
5354
+ ...s.ranged ? { ranged: true } : {},
5355
+ ...s.version !== void 0 ? { version: s.version } : {}
5346
5356
  };
5347
5357
  }
5348
5358
  async function readdirStat(fs, dir) {
@@ -5420,7 +5430,11 @@ async function ranged(fs, path, req) {
5420
5430
  if (!ops) throw syncError("ENOSYS", path);
5421
5431
  const offset = req.offset ?? 0;
5422
5432
  if (req.op === "pread")
5423
- return { ok: true, kind: "bytes", bytes: await ops.pread(path, offset, req.length ?? 0) };
5433
+ return {
5434
+ ok: true,
5435
+ kind: "bytes",
5436
+ bytes: await ops.pread(path, offset, req.length ?? 0, req.version)
5437
+ };
5424
5438
  if (req.op === "pwrite") await ops.pwrite(path, offset, req.body ?? new Uint8Array(0), true);
5425
5439
  else await ops.truncate(path, req.length ?? 0);
5426
5440
  return done;
@@ -6611,17 +6625,21 @@ var AsyncRangedFile = class {
6611
6625
  pages;
6612
6626
  io;
6613
6627
  pinned = false;
6628
+ version;
6614
6629
  path;
6615
- constructor(io, path, size) {
6630
+ constructor(io, path, size, version) {
6616
6631
  this.io = io;
6617
6632
  this.path = path;
6633
+ this.version = version;
6618
6634
  this.pages = new Pages(size);
6619
6635
  }
6620
6636
  size() {
6621
6637
  return this.pages.length;
6622
6638
  }
6623
6639
  async fetch(runs) {
6624
- for (const [start, n] of runs) this.pages.fill(start, await this.io.pread(this.path, start, n));
6640
+ for (const [start, n] of runs) {
6641
+ this.pages.fill(start, await this.io.pread(this.path, start, n, this.version));
6642
+ }
6625
6643
  }
6626
6644
  async read(at, length2) {
6627
6645
  await this.fetch(this.pages.missing(at, length2));
@@ -6641,6 +6659,7 @@ var AsyncRangedFile = class {
6641
6659
  if (plan.shrink !== void 0) await this.io.truncate(this.path, plan.shrink);
6642
6660
  for (const run2 of plan.runs) await this.io.pwrite(this.path, run2.offset, run2.bytes, true);
6643
6661
  if (plan.extend !== void 0) await this.io.truncate(this.path, plan.extend);
6662
+ this.version = void 0;
6644
6663
  this.pages.flushed();
6645
6664
  }
6646
6665
  async pin() {
@@ -6708,7 +6727,7 @@ var VfsNode = class {
6708
6727
  const io = rangedOps(this.fs);
6709
6728
  const st = io && !this.orphaned ? await this.fs.stat?.(this.path).catch(() => void 0) : void 0;
6710
6729
  if (io && st?.ranged) {
6711
- this.ranged = new AsyncRangedFile(io, this.path, st.size ?? 0);
6730
+ this.ranged = new AsyncRangedFile(io, this.path, st.size ?? 0, st.version);
6712
6731
  return this.ranged;
6713
6732
  }
6714
6733
  await this.load();
@@ -8002,7 +8021,8 @@ async function dispatch(h, req) {
8002
8021
  write: req.write,
8003
8022
  create: req.create,
8004
8023
  truncate: req.truncate,
8005
- exclusive: req.exclusive
8024
+ exclusive: req.exclusive,
8025
+ ...req.ifMatch !== void 0 ? { ifMatch: req.ifMatch } : {}
8006
8026
  });
8007
8027
  case "read":
8008
8028
  return h.read(req.fh, req.offset, req.size);
@@ -8543,7 +8563,8 @@ function hostfsHandlers(current) {
8543
8563
  };
8544
8564
  const call = (op, body = {}) => current().call(op, body);
8545
8565
  async function writable(client, path, flags) {
8546
- const opening = () => client.call("open", { path: rel(path), ...flags });
8566
+ const { ifMatch: _, ...asked } = flags;
8567
+ const opening = () => client.call("open", { path: rel(path), ...asked });
8547
8568
  try {
8548
8569
  return { opened: await opening(), restore: void 0 };
8549
8570
  } catch (err) {
@@ -8559,7 +8580,7 @@ function hostfsHandlers(current) {
8559
8580
  return { opened: opened2, restore };
8560
8581
  }
8561
8582
  }
8562
- return {
8583
+ const handlers = {
8563
8584
  getattr: async (path) => await call("stat", { path: rel(path) }),
8564
8585
  async readdir(path) {
8565
8586
  const { entries } = await call(
@@ -8572,6 +8593,10 @@ function hostfsHandlers(current) {
8572
8593
  const client = current();
8573
8594
  const token = client.token;
8574
8595
  const { opened: opened2, restore } = await writable(client, path, flags);
8596
+ if (flags.ifMatch !== void 0 && opened2.attr?.etag !== flags.ifMatch) {
8597
+ await client.call("release", { fh: opened2.fh }, true);
8598
+ throw fsError2("ESTALE", `${path} changed on the host while it was being read`);
8599
+ }
8575
8600
  handles.set(++nextFh, {
8576
8601
  client,
8577
8602
  token,
@@ -8613,9 +8638,44 @@ function hostfsHandlers(current) {
8613
8638
  rename: async (from, to) => void await call("rename", { from: rel(from), to: rel(to) }),
8614
8639
  symlink: async (target, path) => void await call("symlink", { target, path: rel(path) }),
8615
8640
  readlink: async (path) => (await call("readlink", { path: rel(path) })).target,
8616
- setattr: async (path, change) => void await call("setattr", { path: rel(path), ...change }),
8641
+ async setattr(path, { size, ...change }) {
8642
+ if (size !== void 0 && !current().capabilities.ranges) await resize(handlers, path, size);
8643
+ else if (size !== void 0) change = { ...change, size };
8644
+ if (Object.keys(change).length > 0) await call("setattr", { path: rel(path), ...change });
8645
+ },
8617
8646
  statfs: () => call("statfs")
8618
8647
  };
8648
+ return handlers;
8649
+ }
8650
+ var KEEP = { write: false, create: false, truncate: false, exclusive: false };
8651
+ async function resize(h, path, size) {
8652
+ const was = (await h.getattr(path)).size;
8653
+ if (size === was) return;
8654
+ const kept = [];
8655
+ if (size < was && size > 0) {
8656
+ const fh2 = await h.open(path, KEEP);
8657
+ try {
8658
+ for (let at = 0; at < size; ) {
8659
+ const bytes = await h.read(fh2, at, size - at);
8660
+ if (bytes.length === 0) break;
8661
+ kept.push(bytes);
8662
+ at += bytes.length;
8663
+ }
8664
+ } finally {
8665
+ await h.release(fh2);
8666
+ }
8667
+ }
8668
+ const fh = await h.open(path, { ...KEEP, write: true, truncate: size < was });
8669
+ try {
8670
+ if (size > was) await h.write(fh, size - 1, new Uint8Array(1));
8671
+ let at = 0;
8672
+ for (const bytes of kept) {
8673
+ await h.write(fh, at, bytes);
8674
+ at += bytes.length;
8675
+ }
8676
+ } finally {
8677
+ await h.release(fh);
8678
+ }
8619
8679
  }
8620
8680
  function sleep(ms, signal) {
8621
8681
  return new Promise((resolve) => {
@@ -8709,13 +8769,18 @@ async function openHostfs(spec, hook, fetch2, timing = {}) {
8709
8769
  const grant = () => hook(spec.source, { readonly: readonly2 });
8710
8770
  let active;
8711
8771
  const handlers = hostfsHandlers(() => active);
8712
- const served = serveFilesystem(port2, slot.handlers, {
8713
- symlinks: true,
8714
- chmod: true,
8715
- listingStats: true,
8716
- maxIo: HOSTFS_IO,
8717
- ...readonly2 ? { readonly: true } : {}
8718
- });
8772
+ const ranged2 = () => active?.capabilities.ranges === true ? { ranges: true } : {};
8773
+ const served = serveFilesystem(
8774
+ port2,
8775
+ { ...slot.handlers, mount: ranged2 },
8776
+ {
8777
+ symlinks: true,
8778
+ chmod: true,
8779
+ listingStats: true,
8780
+ maxIo: HOSTFS_IO,
8781
+ ...readonly2 ? { readonly: true } : {}
8782
+ }
8783
+ );
8719
8784
  const watching = keepWatching(
8720
8785
  {
8721
8786
  connect: async () => new HostfsClient(await grant(), grant, fetch2),