@ai-ecoverse/slicc-kernel 1.85.0 → 1.86.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.
- package/README.md +14 -8
- package/dist/index.js +1 -0
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +97 -20
- package/dist/kernel-worker.js.map +2 -2
- package/dist/meta.js +384 -0
- package/dist/meta.js.map +7 -0
- package/dist/node-process-worker.js +69 -15
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +74 -20
- package/dist/node.js.map +2 -2
- package/dist/process-worker.js +69 -15
- package/dist/process-worker.js.map +3 -3
- package/package.json +3 -2
package/dist/node.js
CHANGED
|
@@ -107,6 +107,12 @@ async function lutimesOf(fs, path, atime, mtime) {
|
|
|
107
107
|
function mayLink(fs, path) {
|
|
108
108
|
return fs.links?.(path) ?? true;
|
|
109
109
|
}
|
|
110
|
+
function modeOption(mode) {
|
|
111
|
+
if (!Number.isInteger(mode) || mode < 0 || mode > 4095) {
|
|
112
|
+
throw fsError("EINVAL", `not a mode: ${String(mode)}`);
|
|
113
|
+
}
|
|
114
|
+
return mode;
|
|
115
|
+
}
|
|
110
116
|
function fsError(code, path) {
|
|
111
117
|
return Object.assign(new Error(`${code}: ${path}`), { code });
|
|
112
118
|
}
|
|
@@ -570,7 +576,9 @@ function id(value) {
|
|
|
570
576
|
return value;
|
|
571
577
|
}
|
|
572
578
|
function changeCred(cur, change) {
|
|
573
|
-
if (typeof change !== "object" || change === null
|
|
579
|
+
if (typeof change !== "object" || change === null || Array.isArray(change)) {
|
|
580
|
+
throw fsError("EINVAL", "not a change");
|
|
581
|
+
}
|
|
574
582
|
const privileged = cur.euid === 0;
|
|
575
583
|
const next2 = copyCred(cur);
|
|
576
584
|
for (const keys of [UIDS, GIDS]) {
|
|
@@ -3002,6 +3010,9 @@ var MemoryMeta = class {
|
|
|
3002
3010
|
async get(paths) {
|
|
3003
3011
|
return paths.map((path) => this.entries.get(path));
|
|
3004
3012
|
}
|
|
3013
|
+
async fresh(path) {
|
|
3014
|
+
return this.entries.get(path);
|
|
3015
|
+
}
|
|
3005
3016
|
async update(path, change) {
|
|
3006
3017
|
this.set(path, change(this.entries.get(path)));
|
|
3007
3018
|
}
|
|
@@ -3473,7 +3484,8 @@ function sidecar(meta) {
|
|
|
3473
3484
|
const guarded3 = (op) => (...args) => meta[op].apply(meta, args).catch((err) => {
|
|
3474
3485
|
throw translate(err, pathOf(args), "sidecar", false);
|
|
3475
3486
|
});
|
|
3476
|
-
const
|
|
3487
|
+
const names = meta.fresh ? [...META_OPS, "fresh"] : META_OPS;
|
|
3488
|
+
const ops = Object.fromEntries(names.map((op) => [op, guarded3(op)]));
|
|
3477
3489
|
if (meta.absent) ops.absent = meta.absent.bind(meta);
|
|
3478
3490
|
const { removeFile } = meta;
|
|
3479
3491
|
if (removeFile)
|
|
@@ -3597,6 +3609,24 @@ var OpfsFs = class {
|
|
|
3597
3609
|
committed(target) {
|
|
3598
3610
|
if (this.remote?.watched()) this.remote.wrote(target);
|
|
3599
3611
|
}
|
|
3612
|
+
counted = [];
|
|
3613
|
+
async stamp(path) {
|
|
3614
|
+
const entry = this.meta.fresh ? await this.meta.fresh(path) : (await this.meta.get([path]))[0];
|
|
3615
|
+
return String(entry?.writes ?? 0);
|
|
3616
|
+
}
|
|
3617
|
+
async counting(target) {
|
|
3618
|
+
if (!isProtected(this.counted, target)) return;
|
|
3619
|
+
await this.meta.update(target, (entry) => ({
|
|
3620
|
+
...entry,
|
|
3621
|
+
path: target,
|
|
3622
|
+
writes: (entry?.writes ?? 0) + 1
|
|
3623
|
+
}));
|
|
3624
|
+
}
|
|
3625
|
+
async recounting(handle, target) {
|
|
3626
|
+
if (this.counted.length === 0) return;
|
|
3627
|
+
const where = await this.root.resolve(handle).catch(() => null);
|
|
3628
|
+
await this.counting(where ? `/${where.join("/")}` : target);
|
|
3629
|
+
}
|
|
3600
3630
|
resolvePath(base, path) {
|
|
3601
3631
|
return resolvePath(base, path);
|
|
3602
3632
|
}
|
|
@@ -3655,6 +3685,7 @@ var OpfsFs = class {
|
|
|
3655
3685
|
guarded = [];
|
|
3656
3686
|
protect(prefixes2) {
|
|
3657
3687
|
this.guarded = prefixes2;
|
|
3688
|
+
this.counted = prefixes2;
|
|
3658
3689
|
}
|
|
3659
3690
|
unguarded() {
|
|
3660
3691
|
return Object.create(this, { guarded: { value: [] } });
|
|
@@ -3991,9 +4022,10 @@ var OpfsFs = class {
|
|
|
3991
4022
|
return this.retrying(
|
|
3992
4023
|
path,
|
|
3993
4024
|
async () => {
|
|
4025
|
+
const stamp = await this.stamp(path);
|
|
3994
4026
|
const file = await handle.getFile();
|
|
3995
4027
|
const bytes = new Uint8Array(await file.arrayBuffer());
|
|
3996
|
-
return { bytes, version: `${file.lastModified}:${file.size}` };
|
|
4028
|
+
return { bytes, version: `${file.lastModified}:${file.size}:${stamp}` };
|
|
3997
4029
|
},
|
|
3998
4030
|
false
|
|
3999
4031
|
);
|
|
@@ -4003,8 +4035,9 @@ var OpfsFs = class {
|
|
|
4003
4035
|
return this.retrying(
|
|
4004
4036
|
path,
|
|
4005
4037
|
async () => {
|
|
4038
|
+
const stamp = await this.stamp(path);
|
|
4006
4039
|
const file = await handle.getFile();
|
|
4007
|
-
return `${file.lastModified}:${file.size}`;
|
|
4040
|
+
return `${file.lastModified}:${file.size}:${stamp}`;
|
|
4008
4041
|
},
|
|
4009
4042
|
false
|
|
4010
4043
|
);
|
|
@@ -4019,14 +4052,24 @@ var OpfsFs = class {
|
|
|
4019
4052
|
}
|
|
4020
4053
|
async pwrite(path, offset, bytes) {
|
|
4021
4054
|
const [handle, , target] = await this.fileFor(path);
|
|
4022
|
-
await this.
|
|
4055
|
+
await this.counting(target);
|
|
4056
|
+
try {
|
|
4057
|
+
await this.retrying(path, () => positioned(handle, (io) => io.write(offset, bytes)), true);
|
|
4058
|
+
} finally {
|
|
4059
|
+
await this.recounting(handle, target);
|
|
4060
|
+
}
|
|
4023
4061
|
this.written(target);
|
|
4024
4062
|
}
|
|
4025
4063
|
async truncate(path, size) {
|
|
4026
4064
|
const handle = await this.existing(path, true);
|
|
4027
4065
|
const resolve2 = this.ranged || this.remote?.watched();
|
|
4028
|
-
const target = resolve2 ? (await this.locate(path, true)).path : path;
|
|
4029
|
-
await this.
|
|
4066
|
+
const target = resolve2 || this.counted.length > 0 ? (await this.locate(path, true)).path : path;
|
|
4067
|
+
await this.counting(target);
|
|
4068
|
+
try {
|
|
4069
|
+
await this.retrying(path, () => positioned(handle, (io) => io.truncate(size)), true);
|
|
4070
|
+
} finally {
|
|
4071
|
+
await this.recounting(handle, target);
|
|
4072
|
+
}
|
|
4030
4073
|
this.written(target);
|
|
4031
4074
|
}
|
|
4032
4075
|
async writeSession(path, truncate) {
|
|
@@ -11508,7 +11551,7 @@ function ptySyscall(req, ctx) {
|
|
|
11508
11551
|
const pair = ctx.ptys.get(req.n);
|
|
11509
11552
|
ttyOpenable(ctx.guard, pair.slave);
|
|
11510
11553
|
const slave = pair.openSlave();
|
|
11511
|
-
const fd = ctx.fds.install(ctx.
|
|
11554
|
+
const fd = ctx.fds.install(ctx.outputFilter?.(slave) ?? slave, 3);
|
|
11512
11555
|
if (!req.noctty) ctx.jobs?.acquireTerminal(ctx.pid, pair.slave);
|
|
11513
11556
|
return json4(fd);
|
|
11514
11557
|
}
|
|
@@ -12674,8 +12717,8 @@ var WasmProcess = class {
|
|
|
12674
12717
|
const { ptys, jobs } = this.options;
|
|
12675
12718
|
const owner = this.options.owners ? this.ttyOwner() : void 0;
|
|
12676
12719
|
const guard2 = this.guarded();
|
|
12677
|
-
const {
|
|
12678
|
-
const ctx = { pid: this.pid, fds: this.fds, ptys, jobs, guard: guard2, owner,
|
|
12720
|
+
const { outputFilter } = this.options;
|
|
12721
|
+
const ctx = { pid: this.pid, fds: this.fds, ptys, jobs, guard: guard2, owner, outputFilter };
|
|
12679
12722
|
return ptySyscall(req, ctx);
|
|
12680
12723
|
}
|
|
12681
12724
|
return await this.procSyscall(req, cancelled);
|
|
@@ -12852,7 +12895,7 @@ var WasmProcess = class {
|
|
|
12852
12895
|
if (!tty) throw new KernelError("ENXIO");
|
|
12853
12896
|
if (name2 !== void 0) ttyOpenable(this.guarded(), tty);
|
|
12854
12897
|
const file = tty.file();
|
|
12855
|
-
return this.fds.install(this.options.
|
|
12898
|
+
return this.fds.install(this.options.outputFilter?.(file) ?? file, 3);
|
|
12856
12899
|
}
|
|
12857
12900
|
openSealed() {
|
|
12858
12901
|
const broker = this.options.sealed;
|
|
@@ -12864,7 +12907,8 @@ var WasmProcess = class {
|
|
|
12864
12907
|
if (!broker) throw new KernelError("ENOENT");
|
|
12865
12908
|
const mode = flags2 & WRITE_ACCESS;
|
|
12866
12909
|
const access2 = mode === 0 ? "read" : mode === 1 ? "write" : "both";
|
|
12867
|
-
|
|
12910
|
+
const file = broker.open(access2, await this.clipboardStamp());
|
|
12911
|
+
return this.fds.install(this.options.outputFilter?.(file) ?? file, 3);
|
|
12868
12912
|
}
|
|
12869
12913
|
async clipboardStamp() {
|
|
12870
12914
|
const shown = await this.options.identity?.();
|
|
@@ -13663,7 +13707,7 @@ function processOptions(opts, header4, hooks, created3) {
|
|
|
13663
13707
|
...inherited(opts),
|
|
13664
13708
|
...opts.owners ? { owners: true } : {},
|
|
13665
13709
|
...opts.sealed ? { sealed: opts.sealed } : {},
|
|
13666
|
-
...opts.
|
|
13710
|
+
...opts.outputFilter ? { outputFilter: opts.outputFilter } : {},
|
|
13667
13711
|
...opts.clipboard ? { clipboard: opts.clipboard, ...clipboardName(opts) } : {},
|
|
13668
13712
|
...opts.readonlyAt ? { readonlyAt: opts.readonlyAt } : {},
|
|
13669
13713
|
...opts.dac ? { guard: { dac: opts.dac, fs: opts.fs, created: created3 } } : {},
|
|
@@ -14665,7 +14709,7 @@ function scrubStdio(fds, scrubber) {
|
|
|
14665
14709
|
const stdio = stdioFiles(fds);
|
|
14666
14710
|
for (const fd of fds.numbers()) {
|
|
14667
14711
|
const original = fds.get(fd);
|
|
14668
|
-
if (!stdio.has(original) && !original.file.tty) continue;
|
|
14712
|
+
if (!stdio.has(original) && !original.file.tty && !original.file.clipboard) continue;
|
|
14669
14713
|
const known = wrapped.get(original);
|
|
14670
14714
|
const flags2 = fds.statusFlags(fd);
|
|
14671
14715
|
const wrapper = known ? known.retain() : scrubbed(original.retain(), scrubber);
|
|
@@ -17847,7 +17891,7 @@ var Launcher = class {
|
|
|
17847
17891
|
...this.owners && req.program.abi === "wasi" ? { fresh: (path, umask) => this.freshModules.add(path, umask, pid) } : {},
|
|
17848
17892
|
...this.owners ? { owners: true } : {},
|
|
17849
17893
|
sealed: this.sealed,
|
|
17850
|
-
...scrubs ? {
|
|
17894
|
+
...scrubs ? { outputFilter: (file) => scrubbedAll(file, scrubs) } : {},
|
|
17851
17895
|
clipboard: this.clipboard,
|
|
17852
17896
|
...this.dac ? { dac: this.dac } : {},
|
|
17853
17897
|
program: req.program,
|
|
@@ -18380,17 +18424,21 @@ var Launcher = class {
|
|
|
18380
18424
|
const real = await this.realLayoutPath("/tmp");
|
|
18381
18425
|
const st = real === void 0 ? void 0 : await this.base.lstat(real).catch(() => void 0);
|
|
18382
18426
|
if (real !== void 0 && st?.isDirectory && this.base.hasOwner && !await this.base.hasOwner(real)) {
|
|
18427
|
+
const names = await this.base.readdir(real).catch(() => void 0);
|
|
18383
18428
|
let removed = 0;
|
|
18384
|
-
|
|
18429
|
+
let left = names === void 0 ? 1 : 0;
|
|
18430
|
+
for (const name2 of names ?? []) {
|
|
18385
18431
|
const path = joinName(real, name2);
|
|
18386
|
-
if (await this.base.hasOwner(path)
|
|
18387
|
-
const failed3 = await this.base.rm(path, { recursive: true, force: true }).catch(String);
|
|
18432
|
+
if (await this.base.hasOwner(path)) continue;
|
|
18433
|
+
const failed3 = this.inUse(path) ? "busy" : await this.base.rm(path, { recursive: true, force: true }).catch(String);
|
|
18388
18434
|
if (failed3 === void 0) removed++;
|
|
18435
|
+
else left++;
|
|
18389
18436
|
}
|
|
18390
18437
|
if (removed > 0) {
|
|
18391
18438
|
console.warn(`slicc-kernel users: removed ${removed} entries from /tmp that had no owner`);
|
|
18392
18439
|
}
|
|
18393
|
-
|
|
18440
|
+
if (left === 0)
|
|
18441
|
+
await this.base.chown?.(real, { uid: 0, gid: 0, mode: 1023, follow: false });
|
|
18394
18442
|
}
|
|
18395
18443
|
if (st?.isDirectory) await this.base.chmod(real, 1023);
|
|
18396
18444
|
}
|
|
@@ -20059,11 +20107,17 @@ async function createNodeKernel(options = {}) {
|
|
|
20059
20107
|
close: () => session.close()
|
|
20060
20108
|
};
|
|
20061
20109
|
},
|
|
20062
|
-
async writeFile(path, data) {
|
|
20110
|
+
async writeFile(path, data, options2 = {}) {
|
|
20111
|
+
const mode = options2.mode === void 0 ? void 0 : modeOption(options2.mode);
|
|
20063
20112
|
const parent = path.slice(0, path.lastIndexOf("/")) || "/";
|
|
20064
20113
|
await launcher.fs.mkdir(parent, { recursive: true });
|
|
20114
|
+
if (mode !== void 0) {
|
|
20115
|
+
await launcher.fs.writeFile(path, "");
|
|
20116
|
+
await launcher.fs.chmod(path, mode);
|
|
20117
|
+
}
|
|
20065
20118
|
await launcher.fs.writeFile(path, data);
|
|
20066
20119
|
},
|
|
20120
|
+
chmod: async (path, mode) => launcher.fs.chmod(path, modeOption(mode)),
|
|
20067
20121
|
readFile: async (path) => launcher.fs.readFileBuffer(path),
|
|
20068
20122
|
mount: (spec) => guard2(() => launcher.mount(spec)),
|
|
20069
20123
|
umount: (target) => guard2(async () => launcher.umount(target)),
|