@ai-ecoverse/slicc-kernel 1.127.1 → 1.128.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.
@@ -795,6 +795,12 @@ var ProtectedFs = class {
795
795
  st && marked(`${dir}/${name2}`, st)
796
796
  ]);
797
797
  },
798
+ ...fs.copyFile ? {
799
+ async copyFile(...args) {
800
+ await check(args[1], false);
801
+ return fs.copyFile?.(...args);
802
+ }
803
+ } : {},
798
804
  ...fs.createExclusive ? {
799
805
  async createExclusive(...args) {
800
806
  await check(args[0], true);
@@ -2440,10 +2446,11 @@ var OpfsFs = class {
2440
2446
  return intents.length;
2441
2447
  }
2442
2448
  async settledRename(path) {
2443
- if (this.renamingDirs.size === 0 || typeof path !== "string") return;
2449
+ if (this.renamingDirs.size === 0 && this.copying.size === 0 || typeof path !== "string")
2450
+ return;
2444
2451
  const at = normalizePath(path);
2445
2452
  for (let real; ; ) {
2446
- const busy = this.renameAt(at) ?? (real === void 0 ? void 0 : this.renameAt(real));
2453
+ const busy = this.busyAt(at) ?? (real === void 0 ? void 0 : this.busyAt(real));
2447
2454
  if (busy) {
2448
2455
  await busy.done;
2449
2456
  continue;
@@ -2454,6 +2461,62 @@ var OpfsFs = class {
2454
2461
  if (real === at) return;
2455
2462
  }
2456
2463
  }
2464
+ busyAt(at) {
2465
+ return this.renameAt(at) ?? this.copying.get(at);
2466
+ }
2467
+ copying = /* @__PURE__ */ new Map();
2468
+ async copyFile(from, to, options) {
2469
+ const source = await this.locate(from, true);
2470
+ if (source.handle?.kind !== "file") throw fsError("EINVAL", `${from}: not a regular file`);
2471
+ const [entry] = await this.meta.get([source.path]);
2472
+ if (entry?.fifo || entry?.socket) throw fsError("EINVAL", `${from}: not a regular file`);
2473
+ const parent = await this.locate(parentOf3(to), true);
2474
+ if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", to);
2475
+ const destination = resolvePath(parent.path, baseOf(to));
2476
+ if (destination === source.path) throw fsError("EINVAL", `${from}: copied onto itself`);
2477
+ const file = await this.reading(source.path, (handle) => handle.getFile());
2478
+ const { promise, resolve: resolve2 } = Promise.withResolvers();
2479
+ while (this.copying.has(destination)) await this.copying.get(destination)?.done;
2480
+ this.copying.set(destination, { done: promise });
2481
+ try {
2482
+ await this.copyInto(file, destination, to, options);
2483
+ } finally {
2484
+ this.copying.delete(destination);
2485
+ resolve2();
2486
+ }
2487
+ }
2488
+ async copyInto(file, destination, to, options) {
2489
+ let created4 = false;
2490
+ if (options.exclusive) {
2491
+ await this.createExclusive(destination, options.owner);
2492
+ created4 = true;
2493
+ }
2494
+ let target = destination;
2495
+ let writable2;
2496
+ let handle;
2497
+ try {
2498
+ const [made2, existed, at] = await this.fileFor(destination);
2499
+ handle = made2;
2500
+ target = at;
2501
+ if (!existed && !created4) {
2502
+ created4 = true;
2503
+ await this.stampNew(target, options.owner, false);
2504
+ }
2505
+ const [entry] = await this.meta.get([target]);
2506
+ if (entry?.fifo || entry?.socket) throw fsError("ENXIO", to);
2507
+ this.wrote(handle);
2508
+ writable2 = await handle.createWritable();
2509
+ await writable2.write(file);
2510
+ await writable2.close();
2511
+ } catch (err) {
2512
+ await writable2?.abort().catch(() => void 0);
2513
+ if (created4) await this.rm(target, { file: true }).catch(() => void 0);
2514
+ throw translate(err, to, "commit", false);
2515
+ } finally {
2516
+ if (handle) this.wrote(handle);
2517
+ }
2518
+ this.committed(target);
2519
+ }
2457
2520
  renameAt(at) {
2458
2521
  for (const m of this.renamingDirs) {
2459
2522
  if (within2(at, m.from) || within2(at, m.to) || at === parentOf3(m.from) || at === parentOf3(m.to))
@@ -2701,6 +2764,7 @@ var READS = [
2701
2764
  "readVersioned"
2702
2765
  ];
2703
2766
  var WRITES = [
2767
+ "copyFile",
2704
2768
  "writeFile",
2705
2769
  "pwrite",
2706
2770
  "truncate",
@@ -6874,7 +6938,7 @@ function satisfies(version, range2) {
6874
6938
  }
6875
6939
 
6876
6940
  // src/version.ts
6877
- var KERNEL_VERSION = true ? "1.127.1" : "0.0.0-dev";
6941
+ var KERNEL_VERSION = true ? "1.128.0" : "0.0.0-dev";
6878
6942
  var OS_RELEASE = "6.0.0-slicc";
6879
6943
  function procVersion() {
6880
6944
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -9498,6 +9562,7 @@ function withCommandDirs(fs, names2, userDir = async () => void 0, owners = fals
9498
9562
  ...fs.realpath ? { realpath: fs.realpath.bind(fs) } : {},
9499
9563
  ...fs.chown ? { chown: fs.chown.bind(fs) } : {},
9500
9564
  ...fs.createExclusive ? { createExclusive: fs.createExclusive.bind(fs) } : {},
9565
+ ...fs.copyFile ? { copyFile: fs.copyFile.bind(fs) } : {},
9501
9566
  ...fs.ancestry ? { ancestry: fs.ancestry.bind(fs) } : {},
9502
9567
  ...fs.hasOwner ? { hasOwner: fs.hasOwner.bind(fs) } : {},
9503
9568
  chmod: (path, mode) => fs.chmod(path, mode),
@@ -9899,6 +9964,12 @@ var FsWatchers = class {
9899
9964
  const overrides = {
9900
9965
  writeFile: content(fs.writeFile.bind(fs), written2),
9901
9966
  ...fs.createExclusive ? { createExclusive: content(fs.createExclusive.bind(fs), () => ["rename"]) } : {},
9967
+ ...fs.copyFile ? {
9968
+ copyFile: (from, to, options) => content(
9969
+ (_to) => fs.copyFile?.(from, to, options),
9970
+ written2
9971
+ )(to)
9972
+ } : {},
9902
9973
  mkdir: async (path, options) => {
9903
9974
  const created4 = [];
9904
9975
  if (options?.recursive) {
@@ -10556,6 +10627,33 @@ var FifoTable = class {
10556
10627
  }
10557
10628
  };
10558
10629
 
10630
+ // src/fs/copy.ts
10631
+ async function present2(fs, path) {
10632
+ return fs.lstat(path).then(
10633
+ () => true,
10634
+ (err) => {
10635
+ if (err?.code === "ENOENT") return false;
10636
+ throw err;
10637
+ }
10638
+ );
10639
+ }
10640
+ async function copyByBytes(fs, from, to, options) {
10641
+ if (!(await fs.stat(from)).isFile) throw fsError("EINVAL", `${from}: not a regular file`);
10642
+ const bytes = await fs.readFileBuffer(from);
10643
+ let created4 = false;
10644
+ if (options.exclusive) {
10645
+ if (fs.createExclusive) await fs.createExclusive(to, options.owner);
10646
+ else if (await present2(fs, to)) throw fsError("EEXIST", to);
10647
+ created4 = true;
10648
+ } else created4 = !await present2(fs, to);
10649
+ try {
10650
+ await fs.writeFile(to, bytes, options.owner);
10651
+ } catch (err) {
10652
+ if (created4) await fs.rm(to, { file: true }).catch(() => void 0);
10653
+ throw err;
10654
+ }
10655
+ }
10656
+
10559
10657
  // src/mount/protocol.ts
10560
10658
  var DRIVER_PROTOCOL = [1, 3];
10561
10659
  function driverVersionError(theirs) {
@@ -10939,12 +11037,12 @@ var MountTable = class {
10939
11037
  }
10940
11038
  list() {
10941
11039
  const mounted = [...this.mounts.values()].map(
10942
- ({ type, source, target, options, state, error, present: present3 }) => ({
11040
+ ({ type, source, target, options, state, error, present: present4 }) => ({
10943
11041
  type,
10944
11042
  source,
10945
11043
  target,
10946
11044
  options: { ...options },
10947
- state: state === "ok" && present3?.() === false ? "nomedium" : state,
11045
+ state: state === "ok" && present4?.() === false ? "nomedium" : state,
10948
11046
  ...error ? { error } : {}
10949
11047
  })
10950
11048
  );
@@ -11619,6 +11717,23 @@ var MountFs = class _MountFs {
11619
11717
  throw err;
11620
11718
  }
11621
11719
  }
11720
+ async copyFile(from, to, options, redirects = 0) {
11721
+ const source = await realTarget(this, normalizePath(from));
11722
+ const a = this.at(source);
11723
+ const b = this.at(to);
11724
+ const copy = this.base.copyFile?.bind(this.base);
11725
+ if (!a && !b && copy) {
11726
+ return this.based(
11727
+ [source, to],
11728
+ redirects,
11729
+ () => copy(source, to, options),
11730
+ ([f, t], n) => this.copyFile(f, t, options, n)
11731
+ );
11732
+ }
11733
+ if (a?.mount !== b?.mount) throw errnoError("EXDEV", `${from} -> ${to}`);
11734
+ if (a) this.writable(a.mount, normalizePath(to));
11735
+ return copyByBytes(this, source, to, options);
11736
+ }
11622
11737
  async createExclusive(path, owner, redirects = 0) {
11623
11738
  const exclusive = this.base.createExclusive?.bind(this.base);
11624
11739
  if (!this.at(path) && exclusive) {
@@ -12046,6 +12161,7 @@ var SYNC_FS_OPS = [
12046
12161
  "rm",
12047
12162
  "rename",
12048
12163
  "link",
12164
+ "copy",
12049
12165
  "unlink",
12050
12166
  "rmdir",
12051
12167
  "symlink",
@@ -12245,6 +12361,8 @@ async function run(entry, path, req) {
12245
12361
  case "symlink":
12246
12362
  await fs.symlink(req.arg2 ?? "", path, ownerFor2(entry));
12247
12363
  return done;
12364
+ case "copy":
12365
+ return copyOp(entry, path, req);
12248
12366
  case "mkfifo": {
12249
12367
  const owner = ownerFor2(entry, req.mode ?? 438) ?? { uid: 0, gid: 0 };
12250
12368
  await createExclusive(fs, path, { ...owner, fifo: true });
@@ -12351,6 +12469,16 @@ async function guard(g, path, req, cwd) {
12351
12469
  const toWalked = await walkSafe(g, to, false);
12352
12470
  return { path: fromWalked, arg2: toWalked };
12353
12471
  }
12472
+ case "copy": {
12473
+ const to = other();
12474
+ await readable(g, op, path);
12475
+ const there = !req.exclusive && await g.fs.lstat(to).then(
12476
+ () => true,
12477
+ () => false
12478
+ );
12479
+ await (there ? writable(g, op, to) : inParent(g, op, to));
12480
+ return { path: await walkSafe(g, path, true), arg2: await walkSafe(g, to, false) };
12481
+ }
12354
12482
  case "link": {
12355
12483
  const to = other();
12356
12484
  const follow2 = req.mode === 1;
@@ -12451,6 +12579,9 @@ async function mayChange(entry, path, req) {
12451
12579
  const { mayChange: mayChange2 } = entry.fs;
12452
12580
  if (!mayChange2) return;
12453
12581
  const { op } = req;
12582
+ if (op === "copy") {
12583
+ return mayChange2.call(entry.fs, entry.fs.resolvePath(entry.cwd, req.arg2 ?? ""), false);
12584
+ }
12454
12585
  if (CONTENT.has(op) && req.handle === void 0) return mayChange2.call(entry.fs, path, true);
12455
12586
  if (!CHANGING.has(op)) return;
12456
12587
  const follow2 = op === "utimes" || op === "chmod" || op === "chown";
@@ -12474,6 +12605,17 @@ async function guarded(entry, path, req) {
12474
12605
  return { refused: refused3 };
12475
12606
  }
12476
12607
  }
12608
+ async function copyOp(entry, path, req) {
12609
+ const { fs, cwd } = entry;
12610
+ const to = fs.resolvePath(cwd, req.arg2 ?? "");
12611
+ const mode = (req.mode ?? 438) & 4095 & ~(entry.umask?.() ?? 18);
12612
+ const owner = ownerFor2(entry, mode);
12613
+ const options = { exclusive: req.exclusive === true, ...owner ? { owner } : {} };
12614
+ await (fs.copyFile ? fs.copyFile(path, to, options) : copyByBytes(fs, path, to, options));
12615
+ if (!owner) await fs.chmod(to, mode);
12616
+ entry.fresh?.(to);
12617
+ return done;
12618
+ }
12477
12619
  async function createExclusive(fs, path, owner) {
12478
12620
  if (fs.createExclusive) return fs.createExclusive(path, owner);
12479
12621
  if (await fs.lstat(path).then(
@@ -12648,7 +12790,7 @@ var CREATIONS = /* @__PURE__ */ new Set([
12648
12790
  "create",
12649
12791
  "mkfifo"
12650
12792
  ]);
12651
- var NAMING = /* @__PURE__ */ new Set(["link", "rename"]);
12793
+ var NAMING = /* @__PURE__ */ new Set(["link", "rename", "copy"]);
12652
12794
  async function newDevName(entry, path, req) {
12653
12795
  const named = NAMING.has(req.op);
12654
12796
  if (!named && !CREATIONS.has(req.op)) return void 0;
@@ -19925,7 +20067,7 @@ var VfsNodes = class {
19925
20067
  if (held) throw fsError("EEXIST", path);
19926
20068
  const exclusive = this.fs.createExclusive;
19927
20069
  if (exclusive) return exclusive.call(this.fs, path, owner);
19928
- if (await present2(this.fs, path)) throw fsError("EEXIST", path);
20070
+ if (await present3(this.fs, path)) throw fsError("EEXIST", path);
19929
20071
  await this.fs.writeFile(path, new Uint8Array(0), owner);
19930
20072
  });
19931
20073
  }
@@ -20156,7 +20298,7 @@ var VfsNodes = class {
20156
20298
  }
20157
20299
  }
20158
20300
  };
20159
- async function present2(fs, path, follow2 = false) {
20301
+ async function present3(fs, path, follow2 = false) {
20160
20302
  const look = (follow2 ? void 0 : fs.lstat) ?? fs.stat;
20161
20303
  try {
20162
20304
  await (look ? look.call(fs, path) : fs.readFileBuffer(path));
@@ -20334,7 +20476,18 @@ function keepingOpen(fs, nodes, changed = () => {
20334
20476
  await nodes.onEntry(key, () => fs.link(from, to, follow2));
20335
20477
  await nodes.linked(at, key);
20336
20478
  },
20337
- mkdir: (path, options) => nodes.onEntry(fs.resolvePath("/", path), () => fs.mkdir(path, options))
20479
+ mkdir: (path, options) => nodes.onEntry(fs.resolvePath("/", path), () => fs.mkdir(path, options)),
20480
+ ...fs.copyFile ? {
20481
+ async copyFile(from, to, options) {
20482
+ const source = await nodes.targetKey(fs.resolvePath("/", from));
20483
+ await nodes.flush(source);
20484
+ await nodes.flushLinked(source);
20485
+ const at = fs.resolvePath("/", to);
20486
+ const key = await nodes.entryKey(at);
20487
+ if (await heldAt(fs, nodes, at)) return copyByBytes(this, from, to, options);
20488
+ await nodes.onEntry(key, () => fs.copyFile?.(from, to, options));
20489
+ }
20490
+ } : {}
20338
20491
  };
20339
20492
  }
20340
20493
  function vfsFile(fs, opts, nodes) {
@@ -21194,7 +21347,7 @@ var WasmProcess = class {
21194
21347
  } else if (req.create) {
21195
21348
  await nodes.onEntry(path, async () => {
21196
21349
  const marks = this.options.owners || plain2 !== void 0;
21197
- const fresh2 = marks && !await present2(fs, path, true);
21350
+ const fresh2 = marks && !await present3(fs, path, true);
21198
21351
  this.fds.installAt(fd, this.openVfsFile(open, await nodes.identify(path), fs));
21199
21352
  await this.fds.get(fd).file.stat?.();
21200
21353
  if (fresh2 && plain2 !== void 0) await fs.chmod?.(path, plain2);
@@ -21213,7 +21366,7 @@ var WasmProcess = class {
21213
21366
  { at: path, gen }
21214
21367
  );
21215
21368
  }
21216
- if (req.existing && !await present2(fs, path, true)) {
21369
+ if (req.existing && !await present3(fs, path, true)) {
21217
21370
  throw new KernelError("ENOENT");
21218
21371
  }
21219
21372
  } catch (err) {
@@ -21581,12 +21734,12 @@ var WasmProcess = class {
21581
21734
  async stillOpen(at, handle) {
21582
21735
  if (handle === void 0 || this.keptHandle?.(handle) !== void 0) return;
21583
21736
  if (this.holdsHandle?.(handle) !== false) return;
21584
- if (!await present2(this.options.fs, at, true)) throw new KernelError("ENOENT");
21737
+ if (!await present3(this.options.fs, at, true)) throw new KernelError("ENOENT");
21585
21738
  }
21586
21739
  async keptOr(path, handle) {
21587
21740
  if (handle !== void 0) return this.keptHandle?.(handle) ?? path;
21588
21741
  const kept = this.keptPath?.(path);
21589
- return kept !== void 0 && !await present2(this.options.fs, path, true) ? kept : path;
21742
+ return kept !== void 0 && !await present3(this.options.fs, path, true) ? kept : path;
21590
21743
  }
21591
21744
  async promote(req) {
21592
21745
  if (!this.fds.get(req.fd).file.held) throw new KernelError("EBADF");