@ai-ecoverse/slicc-kernel 1.62.3 → 1.63.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 +9 -3
- package/dist/kernel-worker.js +374 -242
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +289 -128
- package/dist/node-process-worker.js.map +4 -4
- package/dist/node.js +374 -242
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +289 -128
- package/dist/process-worker.js.map +4 -4
- package/package.json +1 -1
package/dist/node.js
CHANGED
|
@@ -331,15 +331,24 @@ async function present(fs, path, directory) {
|
|
|
331
331
|
const st = await fs.lstat(path).catch(() => void 0);
|
|
332
332
|
return st !== void 0 && (!directory || st.isDirectory);
|
|
333
333
|
}
|
|
334
|
+
async function finalOf(fs, walked, want, options) {
|
|
335
|
+
const perm = walked.perm;
|
|
336
|
+
if ((want & X_OK) === 0 || options.directory !== void 0) {
|
|
337
|
+
return [perm, options.directory !== false];
|
|
338
|
+
}
|
|
339
|
+
const look = options.follow === false ? fs.lstat : fs.stat;
|
|
340
|
+
const st = await look.call(fs, walked.path).catch(() => void 0);
|
|
341
|
+
return st ? [permOf(st), st.isDirectory] : [perm, false];
|
|
342
|
+
}
|
|
334
343
|
async function access(fs, cred, path, want, options = {}) {
|
|
335
344
|
const walked = await walk(fs, cred, path, options.follow !== false);
|
|
336
345
|
if (walked.denied !== void 0) {
|
|
337
346
|
if (await present(fs, walked.denied, true)) return walked;
|
|
338
347
|
return { path, perm: void 0, missing: true };
|
|
339
348
|
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
if (want === 0 || permits(cred, perm, want,
|
|
349
|
+
if (!walked.perm) return { ...walked, missing: true };
|
|
350
|
+
const [perm, directory] = await finalOf(fs, walked, want, options);
|
|
351
|
+
if (want === 0 || permits(cred, perm, want, directory)) return walked;
|
|
343
352
|
if (await present(fs, walked.path, false)) return { ...walked, denied: walked.path };
|
|
344
353
|
return { ...walked, missing: true };
|
|
345
354
|
}
|
|
@@ -350,6 +359,7 @@ function refused(path, errno = "EACCES") {
|
|
|
350
359
|
// src/fs/dac.ts
|
|
351
360
|
var MAX_DENIAL_KEYS = 1e4;
|
|
352
361
|
var S_ISGID2 = 1024;
|
|
362
|
+
var DIR = { directory: true };
|
|
353
363
|
var Dac = class {
|
|
354
364
|
mode;
|
|
355
365
|
hook;
|
|
@@ -386,6 +396,17 @@ var Dac = class {
|
|
|
386
396
|
);
|
|
387
397
|
}
|
|
388
398
|
};
|
|
399
|
+
var MAX_CREATED = 1024;
|
|
400
|
+
var Created = class {
|
|
401
|
+
paths = /* @__PURE__ */ new Set();
|
|
402
|
+
add(path) {
|
|
403
|
+
if (this.paths.size >= MAX_CREATED) this.paths.clear();
|
|
404
|
+
this.paths.add(normalizePath(path));
|
|
405
|
+
}
|
|
406
|
+
take(path) {
|
|
407
|
+
return this.paths.delete(normalizePath(path));
|
|
408
|
+
}
|
|
409
|
+
};
|
|
389
410
|
function deny(g, op, path, errno = "EACCES") {
|
|
390
411
|
g.dac.denied({ pid: g.pid, uid: g.cred.euid, op, path, errno });
|
|
391
412
|
}
|
|
@@ -394,20 +415,30 @@ async function need(g, op, path, want, options = {}, shown = path) {
|
|
|
394
415
|
if (walked.denied !== void 0) deny(g, op, shown);
|
|
395
416
|
return walked;
|
|
396
417
|
}
|
|
418
|
+
function entryIn(dir, path) {
|
|
419
|
+
return joinName(dir.path, path.slice(path.lastIndexOf("/") + 1));
|
|
420
|
+
}
|
|
397
421
|
async function stickyEntry(g, op, path, dir) {
|
|
398
422
|
const perm = dir.perm;
|
|
399
423
|
if (!perm || sticky(g.cred, perm, perm)) return;
|
|
400
|
-
const entry =
|
|
424
|
+
const entry = entryIn(dir, path);
|
|
401
425
|
if (sticky(g.cred, perm, (await ancestryOf(g.fs, entry)).at(-1))) return;
|
|
402
426
|
if (await present(g.fs, entry, false)) deny(g, op, path, "EPERM");
|
|
403
427
|
}
|
|
404
428
|
async function inParent(g, op, path, old = false) {
|
|
405
|
-
|
|
406
|
-
|
|
429
|
+
if (old === "replaced") {
|
|
430
|
+
const dir2 = await need(g, op, parentOf(path), W_OK | X_OK, DIR, path);
|
|
431
|
+
return dir2.denied === void 0 ? stickyEntry(g, op, path, dir2) : void 0;
|
|
432
|
+
}
|
|
433
|
+
if (!old) return void await need(g, op, parentOf(path), W_OK | X_OK, DIR, path);
|
|
434
|
+
const dir = await access(g.fs, g.cred, parentOf(path), W_OK | X_OK, DIR);
|
|
435
|
+
if (dir.denied === void 0) return stickyEntry(g, op, path, dir);
|
|
436
|
+
const lookup2 = dir.denied === dir.path && dir.perm && permits(g.cred, dir.perm, X_OK);
|
|
437
|
+
if (!lookup2 || await present(g.fs, entryIn(dir, path), false)) deny(g, op, path);
|
|
407
438
|
}
|
|
408
439
|
async function makeIn(g, op, path) {
|
|
409
440
|
for (let dir = parentOf(path); ; dir = parentOf(dir)) {
|
|
410
|
-
const walked = await access(g.fs, g.cred, dir, W_OK | X_OK);
|
|
441
|
+
const walked = await access(g.fs, g.cred, dir, W_OK | X_OK, DIR);
|
|
411
442
|
if (walked.denied !== void 0) {
|
|
412
443
|
if (!await present(g.fs, path, true)) deny(g, op, path);
|
|
413
444
|
return;
|
|
@@ -433,7 +464,7 @@ async function removable(g, op, path) {
|
|
|
433
464
|
async function renamable(g, from, to) {
|
|
434
465
|
if (from === to) return void await need(g, "rename", from, 0, { follow: false });
|
|
435
466
|
await inParent(g, "rename", from, true);
|
|
436
|
-
await inParent(g, "rename", to,
|
|
467
|
+
await inParent(g, "rename", to, "replaced");
|
|
437
468
|
if (g.cred.euid === 0 || parentOf(from) === parentOf(to)) return;
|
|
438
469
|
const st = await g.fs.lstat(from).catch(() => void 0);
|
|
439
470
|
if (st?.isDirectory && !permits(g.cred, permOf(st), W_OK)) deny(g, "rename", from);
|
|
@@ -459,8 +490,20 @@ async function chmodMode(g, path, mode) {
|
|
|
459
490
|
if (!g.dac.enforcing || !perm || g.cred.euid === 0 || inGroup(g.cred, perm.gid)) return mode;
|
|
460
491
|
return mode & ~S_ISGID2;
|
|
461
492
|
}
|
|
462
|
-
async function retimable(g, op, path) {
|
|
463
|
-
|
|
493
|
+
async function retimable(g, op, path, now = false) {
|
|
494
|
+
const follow2 = op !== "lutimes";
|
|
495
|
+
if (!now) return void await ownerOnly(g, op, path, follow2);
|
|
496
|
+
const walked = await need(g, op, path, 0, { follow: follow2 });
|
|
497
|
+
const perm = walked.perm;
|
|
498
|
+
if (!perm || g.cred.euid === 0 || perm.uid === g.cred.euid) return;
|
|
499
|
+
if (permits(g.cred, perm, W_OK, false)) return;
|
|
500
|
+
if (await present(g.fs, walked.path, false)) deny(g, op, path);
|
|
501
|
+
}
|
|
502
|
+
async function fileWritable(g, op, path) {
|
|
503
|
+
await need(g, op, path, W_OK, { directory: false });
|
|
504
|
+
}
|
|
505
|
+
function realIds(cred) {
|
|
506
|
+
return { ...cred, groups: [...cred.groups], euid: cred.ruid, egid: cred.rgid };
|
|
464
507
|
}
|
|
465
508
|
async function listable(g, op, path) {
|
|
466
509
|
await need(g, op, path, R_OK | X_OK, { directory: true });
|
|
@@ -472,10 +515,16 @@ async function readable(g, op, path) {
|
|
|
472
515
|
await need(g, op, path, R_OK, { directory: false });
|
|
473
516
|
}
|
|
474
517
|
async function writable(g, op, path) {
|
|
475
|
-
|
|
476
|
-
|
|
518
|
+
await openable(g, op, path, W_OK, true);
|
|
519
|
+
}
|
|
520
|
+
async function creatable(g, op, path) {
|
|
477
521
|
const target = await need(g, op, path, 0);
|
|
478
|
-
if (target.denied === void 0) await need(g, op, parentOf(target.path), W_OK | X_OK,
|
|
522
|
+
if (target.denied === void 0) await need(g, op, parentOf(target.path), W_OK | X_OK, DIR, path);
|
|
523
|
+
}
|
|
524
|
+
async function openable(g, op, path, want, create) {
|
|
525
|
+
const st = create ? await g.fs.stat(path).catch(() => void 0) : void 0;
|
|
526
|
+
if (create && !st) return creatable(g, op, path);
|
|
527
|
+
await need(g, op, path, want, { directory: st?.isDirectory ?? false });
|
|
479
528
|
}
|
|
480
529
|
|
|
481
530
|
// src/kernel/pipe.ts
|
|
@@ -2983,11 +3032,16 @@ var OpfsFs = class {
|
|
|
2983
3032
|
}
|
|
2984
3033
|
async ancestry(path) {
|
|
2985
3034
|
const entries = await this.meta.get(chain(path));
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
3035
|
+
const out = [];
|
|
3036
|
+
for (const [i, entry] of entries.entries()) {
|
|
3037
|
+
const link2 = entry?.link !== void 0 && !await this.real(entry.path);
|
|
3038
|
+
out.push({
|
|
3039
|
+
...ownOf(entry) ?? (i === 0 ? ROOT_OWNER : inherit(entries.slice(0, i))),
|
|
3040
|
+
...entry?.mode !== void 0 ? { mode: entry.mode } : {},
|
|
3041
|
+
...link2 ? { link: entry.link } : {}
|
|
3042
|
+
});
|
|
3043
|
+
}
|
|
3044
|
+
return out;
|
|
2991
3045
|
}
|
|
2992
3046
|
async handedTo(dir) {
|
|
2993
3047
|
return inherit(await this.meta.get(chain(dir)));
|
|
@@ -6477,6 +6531,9 @@ function revokeSyncFsToken(token) {
|
|
|
6477
6531
|
}
|
|
6478
6532
|
|
|
6479
6533
|
// src/realm/sync-fs-wire.ts
|
|
6534
|
+
var HOLD_READ = 4;
|
|
6535
|
+
var HOLD_WRITE = 8;
|
|
6536
|
+
var HOLD_CREATED = 16;
|
|
6480
6537
|
var SYNC_FS_REQUEST_TIMEOUT_MS = 25e3;
|
|
6481
6538
|
function syncError(code, label) {
|
|
6482
6539
|
return Object.assign(new Error(`${code}: ${label}`), { code });
|
|
@@ -6537,17 +6594,8 @@ function mkdirOptions(entry, mode = 511) {
|
|
|
6537
6594
|
return { recursive: true, owner: { ...owner, parents } };
|
|
6538
6595
|
}
|
|
6539
6596
|
async function mkdirExclusive(entry, path, mode) {
|
|
6540
|
-
const
|
|
6541
|
-
|
|
6542
|
-
const own = owner ? { owner } : {};
|
|
6543
|
-
try {
|
|
6544
|
-
await fs.mkdir(path, own);
|
|
6545
|
-
} catch (err) {
|
|
6546
|
-
if (err?.code !== "ENOENT") throw err;
|
|
6547
|
-
const above = owner ? { owner: { ...owner, mode: owner.parents } } : {};
|
|
6548
|
-
await fs.mkdir(path.slice(0, path.lastIndexOf("/")) || "/", { recursive: true, ...above });
|
|
6549
|
-
await fs.mkdir(path, own);
|
|
6550
|
-
}
|
|
6597
|
+
const owner = ownerFor2(entry, mode ?? 511);
|
|
6598
|
+
await entry.fs.mkdir(path, owner ? { owner } : {});
|
|
6551
6599
|
}
|
|
6552
6600
|
async function chown(entry, path, req) {
|
|
6553
6601
|
const cred = entry.cred?.();
|
|
@@ -6609,6 +6657,7 @@ async function run(entry, path, req) {
|
|
|
6609
6657
|
return done;
|
|
6610
6658
|
case "create":
|
|
6611
6659
|
await createExclusive(fs, path, ownerFor2(entry, req.mode ?? 438));
|
|
6660
|
+
entry.created?.add(path);
|
|
6612
6661
|
return done;
|
|
6613
6662
|
case "readlink":
|
|
6614
6663
|
return json2(await fs.readlink(path));
|
|
@@ -6665,11 +6714,47 @@ async function guard(g, path, req, cwd) {
|
|
|
6665
6714
|
return linkable(g, path, other(), req.mode === 1);
|
|
6666
6715
|
case "utimes":
|
|
6667
6716
|
case "lutimes":
|
|
6668
|
-
return retimable(g, op, path);
|
|
6717
|
+
return retimable(g, op, path, req.now === true);
|
|
6718
|
+
case "read":
|
|
6719
|
+
case "pread":
|
|
6720
|
+
return req.handle === void 0 ? readable(g, op, path) : void 0;
|
|
6721
|
+
case "pwrite":
|
|
6722
|
+
case "truncate":
|
|
6723
|
+
return req.handle === void 0 ? fileWritable(g, op, path) : void 0;
|
|
6724
|
+
case "write":
|
|
6725
|
+
return req.handle === void 0 && req.mode !== 1 ? writable(g, op, path) : void 0;
|
|
6669
6726
|
default:
|
|
6670
6727
|
return void 0;
|
|
6671
6728
|
}
|
|
6672
6729
|
}
|
|
6730
|
+
async function opening(entry, path, mode) {
|
|
6731
|
+
const g = guardOf(entry);
|
|
6732
|
+
const want = (mode & HOLD_READ ? R_OK : 0) | (mode & HOLD_WRITE ? W_OK : 0);
|
|
6733
|
+
const created3 = (mode & HOLD_CREATED) !== 0 && entry.created?.take(path) === true;
|
|
6734
|
+
if (g && want !== 0 && !created3) {
|
|
6735
|
+
await need(g, "open", path, want, { directory: false });
|
|
6736
|
+
}
|
|
6737
|
+
}
|
|
6738
|
+
async function holdOp(entry, path, req) {
|
|
6739
|
+
const mode = req.mode ?? 0;
|
|
6740
|
+
const [on, open] = [(mode & 1) === 1, (mode & 2) === 2];
|
|
6741
|
+
if (on && open) {
|
|
6742
|
+
await opening(entry, path, mode);
|
|
6743
|
+
const real = await entry.fs.realpath?.(path, true).catch(() => path);
|
|
6744
|
+
return json2(entry.hold?.(path, on, open, real) ?? null);
|
|
6745
|
+
}
|
|
6746
|
+
entry.hold?.(path, on, open, void 0, req.handle);
|
|
6747
|
+
return done;
|
|
6748
|
+
}
|
|
6749
|
+
async function accessOp(entry, path, req) {
|
|
6750
|
+
const g = guardOf(entry);
|
|
6751
|
+
if (!g) return done;
|
|
6752
|
+
const open = req.arg2 === "open";
|
|
6753
|
+
const cred = open || req.arg2 === "eaccess" ? g.cred : realIds(g.cred);
|
|
6754
|
+
const options = { follow: req.nofollow !== true, ...open ? { directory: false } : {} };
|
|
6755
|
+
await need({ ...g, cred }, open ? "open" : "access", path, req.mode ?? 0, options);
|
|
6756
|
+
return done;
|
|
6757
|
+
}
|
|
6673
6758
|
async function guarded(entry, path, req) {
|
|
6674
6759
|
const g = guardOf(entry);
|
|
6675
6760
|
if (!g) return void 0;
|
|
@@ -6733,16 +6818,6 @@ async function owned(entry, own, req, path, target) {
|
|
|
6733
6818
|
}
|
|
6734
6819
|
return own(target, () => run(entry, path, req));
|
|
6735
6820
|
}
|
|
6736
|
-
async function holdOp(entry, path, req) {
|
|
6737
|
-
const mode = req.mode ?? 0;
|
|
6738
|
-
const [on, open] = [(mode & 1) === 1, (mode & 2) === 2];
|
|
6739
|
-
if (on && open) {
|
|
6740
|
-
const real = await entry.fs.realpath?.(path, true).catch(() => path);
|
|
6741
|
-
return json2(entry.hold?.(path, on, open, real) ?? null);
|
|
6742
|
-
}
|
|
6743
|
-
entry.hold?.(path, on, open, void 0, req.handle);
|
|
6744
|
-
return done;
|
|
6745
|
-
}
|
|
6746
6821
|
var IDENTITY_OPS = /* @__PURE__ */ new Set([
|
|
6747
6822
|
"write",
|
|
6748
6823
|
"pwrite",
|
|
@@ -6779,7 +6854,8 @@ async function dispatchOne(entry, req) {
|
|
|
6779
6854
|
const path = fs.resolvePath(cwd, req.path);
|
|
6780
6855
|
if (req.op === "kept") return json2(entry.keptFor?.(req.handle ?? -1) !== void 0);
|
|
6781
6856
|
if (req.op === "stat" && req.handle !== void 0) return await keptStat(entry, req);
|
|
6782
|
-
if (req.op === "
|
|
6857
|
+
if (req.op === "access") return await accessOp(entry, path, req);
|
|
6858
|
+
if (req.op === "hold") return await holdOp(entry, path, req);
|
|
6783
6859
|
const refused2 = await guarded(entry, path, req);
|
|
6784
6860
|
if (refused2) return refused2;
|
|
6785
6861
|
if (req.op === "statfs") return json2(await entry.statfs?.(path) ?? await storageUsage());
|
|
@@ -6975,188 +7051,6 @@ function ownNames(hostname) {
|
|
|
6975
7051
|
return [.../* @__PURE__ */ new Set([hostname.toLowerCase(), ...LIBC_HOSTNAMES])];
|
|
6976
7052
|
}
|
|
6977
7053
|
|
|
6978
|
-
// src/process/process-fds.ts
|
|
6979
|
-
var field2 = (text) => (text || "none").replace(/[\s\\]/g, (c) => `\\${c.charCodeAt(0).toString(8).padStart(3, "0")}`);
|
|
6980
|
-
function mountTable(mounts = []) {
|
|
6981
|
-
const root = globalThis.navigator?.storage ? "opfs" : "memory";
|
|
6982
|
-
const lines2 = [`${root} / ${root} rw 0 0`, "devfs /dev devfs rw 0 0", "proc /proc proc rw 0 0"];
|
|
6983
|
-
for (const m of mounts) {
|
|
6984
|
-
const options = Object.entries(m.options).map(([k, v]) => v === "" ? k : `${k}=${v}`);
|
|
6985
|
-
if (m.state !== "ok") options.push(m.state);
|
|
6986
|
-
const access2 = options.includes("ro") ? [] : ["rw"];
|
|
6987
|
-
lines2.push(
|
|
6988
|
-
`${field2(m.source)} ${field2(m.target)} ${m.type} ${[...access2, ...options].join(",")} 0 0`
|
|
6989
|
-
);
|
|
6990
|
-
}
|
|
6991
|
-
return `${lines2.join("\n")}
|
|
6992
|
-
`;
|
|
6993
|
-
}
|
|
6994
|
-
|
|
6995
|
-
// src/process/procfs.ts
|
|
6996
|
-
var HZ = 100;
|
|
6997
|
-
var KIB = 1024;
|
|
6998
|
-
var FALLBACK_MEMORY = 4 * KIB * KIB * KIB;
|
|
6999
|
-
var PID_FILES = ["cmdline", "comm", "stat", "statm", "status"];
|
|
7000
|
-
var SYSTEM_FILES = ["loadavg", "meminfo", "stat", "uptime"];
|
|
7001
|
-
function commOf(info) {
|
|
7002
|
-
const name2 = info.argv[0] ?? "";
|
|
7003
|
-
return name2.slice(name2.lastIndexOf("/") + 1).slice(0, 15);
|
|
7004
|
-
}
|
|
7005
|
-
function ttyNumber(tty) {
|
|
7006
|
-
const pts = tty && /^\/dev\/pts\/(\d+)$/.exec(tty);
|
|
7007
|
-
if (pts) return 136 << 8 | Number(pts[1]);
|
|
7008
|
-
const vt = tty && /^\/dev\/tty(\d+)$/.exec(tty);
|
|
7009
|
-
return vt ? 4 << 8 | Number(vt[1]) : 0;
|
|
7010
|
-
}
|
|
7011
|
-
function pages(bytes) {
|
|
7012
|
-
return Math.ceil(bytes / 4096);
|
|
7013
|
-
}
|
|
7014
|
-
function ticks(ms) {
|
|
7015
|
-
return Math.max(0, Math.floor(ms * HZ / 1e3));
|
|
7016
|
-
}
|
|
7017
|
-
function pidStat(info, boot) {
|
|
7018
|
-
const fields = [
|
|
7019
|
-
info.pid,
|
|
7020
|
-
`(${commOf(info)})`,
|
|
7021
|
-
info.state,
|
|
7022
|
-
info.ppid,
|
|
7023
|
-
info.pgid,
|
|
7024
|
-
info.sid,
|
|
7025
|
-
ttyNumber(info.tty),
|
|
7026
|
-
info.tty ? info.pgid : -1,
|
|
7027
|
-
4194304,
|
|
7028
|
-
0,
|
|
7029
|
-
0,
|
|
7030
|
-
0,
|
|
7031
|
-
0,
|
|
7032
|
-
0,
|
|
7033
|
-
0,
|
|
7034
|
-
0,
|
|
7035
|
-
0,
|
|
7036
|
-
20,
|
|
7037
|
-
0,
|
|
7038
|
-
1,
|
|
7039
|
-
0,
|
|
7040
|
-
ticks(info.started - boot),
|
|
7041
|
-
info.memory,
|
|
7042
|
-
pages(info.memory),
|
|
7043
|
-
"18446744073709551615",
|
|
7044
|
-
...Array(12).fill(0),
|
|
7045
|
-
17,
|
|
7046
|
-
0,
|
|
7047
|
-
0,
|
|
7048
|
-
0,
|
|
7049
|
-
0,
|
|
7050
|
-
0,
|
|
7051
|
-
0,
|
|
7052
|
-
...Array(7).fill(0),
|
|
7053
|
-
0
|
|
7054
|
-
];
|
|
7055
|
-
return `${fields.join(" ")}
|
|
7056
|
-
`;
|
|
7057
|
-
}
|
|
7058
|
-
var sigMask = (mask = 0) => (mask >>> 1).toString(16).padStart(16, "0");
|
|
7059
|
-
function pidStatus(info) {
|
|
7060
|
-
const state = info.state === "Z" ? "Z (zombie)" : "S (sleeping)";
|
|
7061
|
-
const c = info.cred ?? ROOT;
|
|
7062
|
-
const ids = (r, e, s) => `${r} ${e} ${s} ${e}`;
|
|
7063
|
-
return [
|
|
7064
|
-
`Name: ${commOf(info)}`,
|
|
7065
|
-
`Umask: ${(info.umask ?? 18).toString(8).padStart(4, "0")}`,
|
|
7066
|
-
`State: ${state}`,
|
|
7067
|
-
`Tgid: ${info.pid}`,
|
|
7068
|
-
"Ngid: 0",
|
|
7069
|
-
`Pid: ${info.pid}`,
|
|
7070
|
-
`PPid: ${info.ppid}`,
|
|
7071
|
-
"TracerPid: 0",
|
|
7072
|
-
`Uid: ${ids(c.ruid, c.euid, c.suid)}`,
|
|
7073
|
-
`Gid: ${ids(c.rgid, c.egid, c.sgid)}`,
|
|
7074
|
-
"FDSize: 64",
|
|
7075
|
-
`VmSize: ${Math.ceil(info.memory / KIB)} kB`,
|
|
7076
|
-
`VmRSS: ${Math.ceil(info.memory / KIB)} kB`,
|
|
7077
|
-
`Groups: ${c.groups.join(" ")}`,
|
|
7078
|
-
`NSpid: ${info.pid}`,
|
|
7079
|
-
`NSpgid: ${info.pgid}`,
|
|
7080
|
-
`NSsid: ${info.sid}`,
|
|
7081
|
-
"Threads: 1",
|
|
7082
|
-
"SigQ: 0/0",
|
|
7083
|
-
"SigPnd: 0000000000000000",
|
|
7084
|
-
"ShdPnd: 0000000000000000",
|
|
7085
|
-
"SigBlk: 0000000000000000",
|
|
7086
|
-
`SigIgn: ${sigMask(info.sigIgn)}`,
|
|
7087
|
-
`SigCgt: ${sigMask(info.sigCgt)}`,
|
|
7088
|
-
""
|
|
7089
|
-
].join("\n");
|
|
7090
|
-
}
|
|
7091
|
-
function pidFile(name2, info, boot) {
|
|
7092
|
-
if (name2 === "cmdline") return info.state === "Z" ? "" : `${info.argv.join("\0")}\0`;
|
|
7093
|
-
if (name2 === "comm") return `${commOf(info)}
|
|
7094
|
-
`;
|
|
7095
|
-
if (name2 === "stat") return pidStat(info, boot);
|
|
7096
|
-
if (name2 === "statm") {
|
|
7097
|
-
const p = pages(info.memory);
|
|
7098
|
-
return `${p} ${p} 0 0 0 ${p} 0
|
|
7099
|
-
`;
|
|
7100
|
-
}
|
|
7101
|
-
return pidStatus(info);
|
|
7102
|
-
}
|
|
7103
|
-
function memoryInfo(source, used = 0) {
|
|
7104
|
-
const total = source.deviceMemory ? source.deviceMemory * KIB * KIB * KIB : FALLBACK_MEMORY;
|
|
7105
|
-
const free = Math.max(0, total - used - (source.usedHeap ?? 0));
|
|
7106
|
-
const kb = (bytes) => `${Math.floor(bytes / KIB)} kB`;
|
|
7107
|
-
return [
|
|
7108
|
-
["MemTotal", kb(total)],
|
|
7109
|
-
["MemFree", kb(free)],
|
|
7110
|
-
["MemAvailable", kb(free)],
|
|
7111
|
-
["Buffers", kb(0)],
|
|
7112
|
-
["Cached", kb(0)],
|
|
7113
|
-
["SwapCached", kb(0)],
|
|
7114
|
-
["Shmem", kb(0)],
|
|
7115
|
-
["SReclaimable", kb(0)],
|
|
7116
|
-
["SwapTotal", kb(0)],
|
|
7117
|
-
["SwapFree", kb(0)]
|
|
7118
|
-
].map(([key, value]) => `${`${key}:`.padEnd(16)}${value.padStart(12)}`).concat("").join("\n");
|
|
7119
|
-
}
|
|
7120
|
-
function systemFile(name2, listing, now, memory) {
|
|
7121
|
-
const up = Math.max(0, now - listing.boot) / 1e3;
|
|
7122
|
-
if (name2 === "uptime") return `${up.toFixed(2)} ${up.toFixed(2)}
|
|
7123
|
-
`;
|
|
7124
|
-
if (name2 === "meminfo") {
|
|
7125
|
-
return memoryInfo(
|
|
7126
|
-
memory,
|
|
7127
|
-
listing.processes.reduce((sum, p) => sum + p.memory, 0)
|
|
7128
|
-
);
|
|
7129
|
-
}
|
|
7130
|
-
const live = listing.processes.filter((p) => p.state !== "Z");
|
|
7131
|
-
if (name2 === "loadavg") {
|
|
7132
|
-
const last = Math.max(0, ...listing.processes.map((p) => p.pid));
|
|
7133
|
-
return `0.00 0.00 0.00 1/${live.length} ${last}
|
|
7134
|
-
`;
|
|
7135
|
-
}
|
|
7136
|
-
const idle = ticks(now - listing.boot);
|
|
7137
|
-
return [
|
|
7138
|
-
`cpu 0 0 0 ${idle} 0 0 0 0 0 0`,
|
|
7139
|
-
`cpu0 0 0 0 ${idle} 0 0 0 0 0 0`,
|
|
7140
|
-
"intr 0",
|
|
7141
|
-
"ctxt 0",
|
|
7142
|
-
`btime ${Math.floor(listing.boot / 1e3)}`,
|
|
7143
|
-
`processes ${listing.processes.length}`,
|
|
7144
|
-
"procs_running 1",
|
|
7145
|
-
"procs_blocked 0",
|
|
7146
|
-
""
|
|
7147
|
-
].join("\n");
|
|
7148
|
-
}
|
|
7149
|
-
function memorySource(scope = globalThis) {
|
|
7150
|
-
const nav = scope.navigator;
|
|
7151
|
-
const perf = scope.performance;
|
|
7152
|
-
const deviceMemory = nav?.deviceMemory;
|
|
7153
|
-
const used = perf?.memory?.usedJSHeapSize;
|
|
7154
|
-
return {
|
|
7155
|
-
...typeof deviceMemory === "number" && deviceMemory > 0 ? { deviceMemory } : {},
|
|
7156
|
-
...typeof used === "number" ? { usedHeap: used } : {}
|
|
7157
|
-
};
|
|
7158
|
-
}
|
|
7159
|
-
|
|
7160
7054
|
// src/fs/pages.ts
|
|
7161
7055
|
var PAGE = 64 * 1024;
|
|
7162
7056
|
var READAHEAD = 1024 * 1024;
|
|
@@ -7382,6 +7276,191 @@ var AsyncRangedFile = class {
|
|
|
7382
7276
|
}
|
|
7383
7277
|
};
|
|
7384
7278
|
|
|
7279
|
+
// src/realm/live-vfs-fs.ts
|
|
7280
|
+
var EARLY_WHOLE_FILE = 64 * 1024;
|
|
7281
|
+
|
|
7282
|
+
// src/process/process-fds.ts
|
|
7283
|
+
var field2 = (text) => (text || "none").replace(/[\s\\]/g, (c) => `\\${c.charCodeAt(0).toString(8).padStart(3, "0")}`);
|
|
7284
|
+
function mountTable(mounts = []) {
|
|
7285
|
+
const root = globalThis.navigator?.storage ? "opfs" : "memory";
|
|
7286
|
+
const lines2 = [`${root} / ${root} rw 0 0`, "devfs /dev devfs rw 0 0", "proc /proc proc rw 0 0"];
|
|
7287
|
+
for (const m of mounts) {
|
|
7288
|
+
const options = Object.entries(m.options).map(([k, v]) => v === "" ? k : `${k}=${v}`);
|
|
7289
|
+
if (m.state !== "ok") options.push(m.state);
|
|
7290
|
+
const access2 = options.includes("ro") ? [] : ["rw"];
|
|
7291
|
+
lines2.push(
|
|
7292
|
+
`${field2(m.source)} ${field2(m.target)} ${m.type} ${[...access2, ...options].join(",")} 0 0`
|
|
7293
|
+
);
|
|
7294
|
+
}
|
|
7295
|
+
return `${lines2.join("\n")}
|
|
7296
|
+
`;
|
|
7297
|
+
}
|
|
7298
|
+
|
|
7299
|
+
// src/process/procfs.ts
|
|
7300
|
+
var HZ = 100;
|
|
7301
|
+
var KIB = 1024;
|
|
7302
|
+
var FALLBACK_MEMORY = 4 * KIB * KIB * KIB;
|
|
7303
|
+
var PID_FILES = ["cmdline", "comm", "stat", "statm", "status"];
|
|
7304
|
+
var SYSTEM_FILES = ["loadavg", "meminfo", "stat", "uptime"];
|
|
7305
|
+
function commOf(info) {
|
|
7306
|
+
const name2 = info.argv[0] ?? "";
|
|
7307
|
+
return name2.slice(name2.lastIndexOf("/") + 1).slice(0, 15);
|
|
7308
|
+
}
|
|
7309
|
+
function ttyNumber(tty) {
|
|
7310
|
+
const pts = tty && /^\/dev\/pts\/(\d+)$/.exec(tty);
|
|
7311
|
+
if (pts) return 136 << 8 | Number(pts[1]);
|
|
7312
|
+
const vt = tty && /^\/dev\/tty(\d+)$/.exec(tty);
|
|
7313
|
+
return vt ? 4 << 8 | Number(vt[1]) : 0;
|
|
7314
|
+
}
|
|
7315
|
+
function pages(bytes) {
|
|
7316
|
+
return Math.ceil(bytes / 4096);
|
|
7317
|
+
}
|
|
7318
|
+
function ticks(ms) {
|
|
7319
|
+
return Math.max(0, Math.floor(ms * HZ / 1e3));
|
|
7320
|
+
}
|
|
7321
|
+
function pidStat(info, boot) {
|
|
7322
|
+
const fields = [
|
|
7323
|
+
info.pid,
|
|
7324
|
+
`(${commOf(info)})`,
|
|
7325
|
+
info.state,
|
|
7326
|
+
info.ppid,
|
|
7327
|
+
info.pgid,
|
|
7328
|
+
info.sid,
|
|
7329
|
+
ttyNumber(info.tty),
|
|
7330
|
+
info.tty ? info.pgid : -1,
|
|
7331
|
+
4194304,
|
|
7332
|
+
0,
|
|
7333
|
+
0,
|
|
7334
|
+
0,
|
|
7335
|
+
0,
|
|
7336
|
+
0,
|
|
7337
|
+
0,
|
|
7338
|
+
0,
|
|
7339
|
+
0,
|
|
7340
|
+
20,
|
|
7341
|
+
0,
|
|
7342
|
+
1,
|
|
7343
|
+
0,
|
|
7344
|
+
ticks(info.started - boot),
|
|
7345
|
+
info.memory,
|
|
7346
|
+
pages(info.memory),
|
|
7347
|
+
"18446744073709551615",
|
|
7348
|
+
...Array(12).fill(0),
|
|
7349
|
+
17,
|
|
7350
|
+
0,
|
|
7351
|
+
0,
|
|
7352
|
+
0,
|
|
7353
|
+
0,
|
|
7354
|
+
0,
|
|
7355
|
+
0,
|
|
7356
|
+
...Array(7).fill(0),
|
|
7357
|
+
0
|
|
7358
|
+
];
|
|
7359
|
+
return `${fields.join(" ")}
|
|
7360
|
+
`;
|
|
7361
|
+
}
|
|
7362
|
+
var sigMask = (mask = 0) => (mask >>> 1).toString(16).padStart(16, "0");
|
|
7363
|
+
function pidStatus(info) {
|
|
7364
|
+
const state = info.state === "Z" ? "Z (zombie)" : "S (sleeping)";
|
|
7365
|
+
const c = info.cred ?? ROOT;
|
|
7366
|
+
const ids = (r, e, s) => `${r} ${e} ${s} ${e}`;
|
|
7367
|
+
return [
|
|
7368
|
+
`Name: ${commOf(info)}`,
|
|
7369
|
+
`Umask: ${(info.umask ?? 18).toString(8).padStart(4, "0")}`,
|
|
7370
|
+
`State: ${state}`,
|
|
7371
|
+
`Tgid: ${info.pid}`,
|
|
7372
|
+
"Ngid: 0",
|
|
7373
|
+
`Pid: ${info.pid}`,
|
|
7374
|
+
`PPid: ${info.ppid}`,
|
|
7375
|
+
"TracerPid: 0",
|
|
7376
|
+
`Uid: ${ids(c.ruid, c.euid, c.suid)}`,
|
|
7377
|
+
`Gid: ${ids(c.rgid, c.egid, c.sgid)}`,
|
|
7378
|
+
"FDSize: 64",
|
|
7379
|
+
`VmSize: ${Math.ceil(info.memory / KIB)} kB`,
|
|
7380
|
+
`VmRSS: ${Math.ceil(info.memory / KIB)} kB`,
|
|
7381
|
+
`Groups: ${c.groups.join(" ")}`,
|
|
7382
|
+
`NSpid: ${info.pid}`,
|
|
7383
|
+
`NSpgid: ${info.pgid}`,
|
|
7384
|
+
`NSsid: ${info.sid}`,
|
|
7385
|
+
"Threads: 1",
|
|
7386
|
+
"SigQ: 0/0",
|
|
7387
|
+
"SigPnd: 0000000000000000",
|
|
7388
|
+
"ShdPnd: 0000000000000000",
|
|
7389
|
+
"SigBlk: 0000000000000000",
|
|
7390
|
+
`SigIgn: ${sigMask(info.sigIgn)}`,
|
|
7391
|
+
`SigCgt: ${sigMask(info.sigCgt)}`,
|
|
7392
|
+
""
|
|
7393
|
+
].join("\n");
|
|
7394
|
+
}
|
|
7395
|
+
function pidFile(name2, info, boot) {
|
|
7396
|
+
if (name2 === "cmdline") return info.state === "Z" ? "" : `${info.argv.join("\0")}\0`;
|
|
7397
|
+
if (name2 === "comm") return `${commOf(info)}
|
|
7398
|
+
`;
|
|
7399
|
+
if (name2 === "stat") return pidStat(info, boot);
|
|
7400
|
+
if (name2 === "statm") {
|
|
7401
|
+
const p = pages(info.memory);
|
|
7402
|
+
return `${p} ${p} 0 0 0 ${p} 0
|
|
7403
|
+
`;
|
|
7404
|
+
}
|
|
7405
|
+
return pidStatus(info);
|
|
7406
|
+
}
|
|
7407
|
+
function memoryInfo(source, used = 0) {
|
|
7408
|
+
const total = source.deviceMemory ? source.deviceMemory * KIB * KIB * KIB : FALLBACK_MEMORY;
|
|
7409
|
+
const free = Math.max(0, total - used - (source.usedHeap ?? 0));
|
|
7410
|
+
const kb = (bytes) => `${Math.floor(bytes / KIB)} kB`;
|
|
7411
|
+
return [
|
|
7412
|
+
["MemTotal", kb(total)],
|
|
7413
|
+
["MemFree", kb(free)],
|
|
7414
|
+
["MemAvailable", kb(free)],
|
|
7415
|
+
["Buffers", kb(0)],
|
|
7416
|
+
["Cached", kb(0)],
|
|
7417
|
+
["SwapCached", kb(0)],
|
|
7418
|
+
["Shmem", kb(0)],
|
|
7419
|
+
["SReclaimable", kb(0)],
|
|
7420
|
+
["SwapTotal", kb(0)],
|
|
7421
|
+
["SwapFree", kb(0)]
|
|
7422
|
+
].map(([key, value]) => `${`${key}:`.padEnd(16)}${value.padStart(12)}`).concat("").join("\n");
|
|
7423
|
+
}
|
|
7424
|
+
function systemFile(name2, listing, now, memory) {
|
|
7425
|
+
const up = Math.max(0, now - listing.boot) / 1e3;
|
|
7426
|
+
if (name2 === "uptime") return `${up.toFixed(2)} ${up.toFixed(2)}
|
|
7427
|
+
`;
|
|
7428
|
+
if (name2 === "meminfo") {
|
|
7429
|
+
return memoryInfo(
|
|
7430
|
+
memory,
|
|
7431
|
+
listing.processes.reduce((sum, p) => sum + p.memory, 0)
|
|
7432
|
+
);
|
|
7433
|
+
}
|
|
7434
|
+
const live = listing.processes.filter((p) => p.state !== "Z");
|
|
7435
|
+
if (name2 === "loadavg") {
|
|
7436
|
+
const last = Math.max(0, ...listing.processes.map((p) => p.pid));
|
|
7437
|
+
return `0.00 0.00 0.00 1/${live.length} ${last}
|
|
7438
|
+
`;
|
|
7439
|
+
}
|
|
7440
|
+
const idle = ticks(now - listing.boot);
|
|
7441
|
+
return [
|
|
7442
|
+
`cpu 0 0 0 ${idle} 0 0 0 0 0 0`,
|
|
7443
|
+
`cpu0 0 0 0 ${idle} 0 0 0 0 0 0`,
|
|
7444
|
+
"intr 0",
|
|
7445
|
+
"ctxt 0",
|
|
7446
|
+
`btime ${Math.floor(listing.boot / 1e3)}`,
|
|
7447
|
+
`processes ${listing.processes.length}`,
|
|
7448
|
+
"procs_running 1",
|
|
7449
|
+
"procs_blocked 0",
|
|
7450
|
+
""
|
|
7451
|
+
].join("\n");
|
|
7452
|
+
}
|
|
7453
|
+
function memorySource(scope = globalThis) {
|
|
7454
|
+
const nav = scope.navigator;
|
|
7455
|
+
const perf = scope.performance;
|
|
7456
|
+
const deviceMemory = nav?.deviceMemory;
|
|
7457
|
+
const used = perf?.memory?.usedJSHeapSize;
|
|
7458
|
+
return {
|
|
7459
|
+
...typeof deviceMemory === "number" && deviceMemory > 0 ? { deviceMemory } : {},
|
|
7460
|
+
...typeof used === "number" ? { usedHeap: used } : {}
|
|
7461
|
+
};
|
|
7462
|
+
}
|
|
7463
|
+
|
|
7385
7464
|
// src/process/wasi/wasi-files.ts
|
|
7386
7465
|
function normalize(path) {
|
|
7387
7466
|
const out = [];
|
|
@@ -8570,11 +8649,11 @@ function realmCa(owner, store) {
|
|
|
8570
8649
|
opened.set(store, cas);
|
|
8571
8650
|
let ca = cas.get(owner);
|
|
8572
8651
|
if (!ca) {
|
|
8573
|
-
const
|
|
8574
|
-
ca =
|
|
8575
|
-
cas.set(owner,
|
|
8576
|
-
|
|
8577
|
-
if (cas.get(owner) ===
|
|
8652
|
+
const opening2 = RealmCa.open(owner, store);
|
|
8653
|
+
ca = opening2;
|
|
8654
|
+
cas.set(owner, opening2);
|
|
8655
|
+
opening2.catch(() => {
|
|
8656
|
+
if (cas.get(owner) === opening2) cas.delete(owner);
|
|
8578
8657
|
});
|
|
8579
8658
|
}
|
|
8580
8659
|
return ca;
|
|
@@ -10981,6 +11060,7 @@ var WasmProcess = class {
|
|
|
10981
11060
|
throw Object.assign(new Error(alias.refused), { code: alias.refused });
|
|
10982
11061
|
if (alias !== void 0) return this.openProc(req, alias);
|
|
10983
11062
|
await refuseReadonly(this.options.fs, req.path, req.flags, req);
|
|
11063
|
+
await this.mayOpen(req);
|
|
10984
11064
|
const fd = this.fds.install(heldFile(), 3);
|
|
10985
11065
|
try {
|
|
10986
11066
|
const nodes = this.nodes;
|
|
@@ -11026,6 +11106,17 @@ var WasmProcess = class {
|
|
|
11026
11106
|
};
|
|
11027
11107
|
return fs.exclusive ? fs.exclusive(first.path, look) : look();
|
|
11028
11108
|
}
|
|
11109
|
+
async mayOpen(req) {
|
|
11110
|
+
const { guard: guard2 } = this.options;
|
|
11111
|
+
const inherited2 = req.orphan || req.contents !== void 0 || req.handle !== void 0;
|
|
11112
|
+
if (!guard2 || inherited2 || req.pin !== void 0) return;
|
|
11113
|
+
const g = { fs: guard2.fs, dac: guard2.dac, cred: this.cred, pid: this.pid };
|
|
11114
|
+
if (req.exclusive) return inParent(g, "open", req.path);
|
|
11115
|
+
if (req.created && guard2.created?.take(req.path)) return;
|
|
11116
|
+
const access2 = req.flags & WRITE_ACCESS;
|
|
11117
|
+
const want = (access2 === 1 ? 0 : R_OK) | (access2 !== 0 || req.truncate ? W_OK : 0);
|
|
11118
|
+
await openable(g, "open", req.path, want, req.create === true);
|
|
11119
|
+
}
|
|
11029
11120
|
newOwner() {
|
|
11030
11121
|
if (!this.options.owners) return void 0;
|
|
11031
11122
|
return { uid: this.cred.euid, gid: this.cred.egid, mode: 438 & ~this.umask };
|
|
@@ -11710,7 +11801,7 @@ function inherited(opts) {
|
|
|
11710
11801
|
function holdingToken(opts, holds, caller) {
|
|
11711
11802
|
return mintSyncFsToken({
|
|
11712
11803
|
...opts.owners ? caller : {},
|
|
11713
|
-
...opts.dac ? { dac: opts.dac, pid: opts.pid } : {},
|
|
11804
|
+
...opts.dac ? { dac: opts.dac, pid: opts.pid, created: caller.created } : {},
|
|
11714
11805
|
fs: opts.fs,
|
|
11715
11806
|
cwd: opts.cwd,
|
|
11716
11807
|
...opts.statfs ? { statfs: opts.statfs } : {},
|
|
@@ -11723,10 +11814,11 @@ function holdingToken(opts, holds, caller) {
|
|
|
11723
11814
|
renamed: (from, to) => holds.renamed(from, to)
|
|
11724
11815
|
});
|
|
11725
11816
|
}
|
|
11726
|
-
function processOptions(opts, header4, hooks) {
|
|
11817
|
+
function processOptions(opts, header4, hooks, created3) {
|
|
11727
11818
|
return {
|
|
11728
11819
|
...inherited(opts),
|
|
11729
11820
|
...opts.owners ? { owners: true } : {},
|
|
11821
|
+
...opts.dac ? { guard: { dac: opts.dac, fs: opts.fs, created: created3 } } : {},
|
|
11730
11822
|
...opts.identity ? { identity: opts.identity } : {},
|
|
11731
11823
|
...opts.onSyscall ? { onSyscall: opts.onSyscall } : {},
|
|
11732
11824
|
...opts.settling ? { settling: opts.settling } : {},
|
|
@@ -11760,20 +11852,27 @@ function spawnWasmProcess(opts) {
|
|
|
11760
11852
|
const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
11761
11853
|
const header4 = new Int32Array(sab, 0, SAB_HEADER_I32);
|
|
11762
11854
|
const threadSignals = /* @__PURE__ */ new Map();
|
|
11855
|
+
const created3 = new Created();
|
|
11763
11856
|
const process2 = new WasmProcess(
|
|
11764
11857
|
opts.pid,
|
|
11765
11858
|
opts.fds,
|
|
11766
|
-
processOptions(
|
|
11767
|
-
|
|
11768
|
-
|
|
11769
|
-
|
|
11859
|
+
processOptions(
|
|
11860
|
+
opts,
|
|
11861
|
+
header4,
|
|
11862
|
+
{
|
|
11863
|
+
raise: (sig) => signal(sig),
|
|
11864
|
+
threadKill: (tid, sig) => killThread(threadSignals.get(tid), process2.signalMasks().caught, sig)
|
|
11865
|
+
},
|
|
11866
|
+
created3
|
|
11867
|
+
)
|
|
11770
11868
|
);
|
|
11771
11869
|
publishStops(process2, header4);
|
|
11772
11870
|
const holds = new HeldPaths();
|
|
11773
11871
|
opts.held?.add(holds);
|
|
11774
11872
|
const token = holdingToken(opts, holds, {
|
|
11775
11873
|
cred: () => process2.cred,
|
|
11776
|
-
umask: () => process2.umask
|
|
11874
|
+
umask: () => process2.umask,
|
|
11875
|
+
created: created3
|
|
11777
11876
|
});
|
|
11778
11877
|
process2.keptPath = (path) => holds.keptAt(path)?.hidden;
|
|
11779
11878
|
process2.keptHandle = (handle2) => holds.keptFor(handle2)?.hidden;
|
|
@@ -12886,16 +12985,16 @@ function hostfsHandlers(current, againMs = RESTORE_AGAIN_MS) {
|
|
|
12886
12985
|
});
|
|
12887
12986
|
async function writable2(client, path, flags) {
|
|
12888
12987
|
const { ifMatch: _, ...asked } = flags;
|
|
12889
|
-
const
|
|
12988
|
+
const opening2 = () => client.call("open", { path: rel(path), ...asked });
|
|
12890
12989
|
try {
|
|
12891
|
-
return { opened: await
|
|
12990
|
+
return { opened: await opening2(), restore: void 0 };
|
|
12892
12991
|
} catch (err) {
|
|
12893
12992
|
if (!flags.write || codeOf4(err) !== "EACCES") throw err;
|
|
12894
12993
|
const was = await client.call("stat", { path: rel(path) });
|
|
12895
12994
|
const mode = was.mode ?? 0;
|
|
12896
12995
|
if (mode & 128) throw err;
|
|
12897
12996
|
const restore = { path: rel(path), mode, was };
|
|
12898
|
-
const opened2 = await client.call("setattr", { path: rel(path), mode: mode | 128 }).then(
|
|
12997
|
+
const opened2 = await client.call("setattr", { path: rel(path), mode: mode | 128 }).then(opening2).catch(async (again) => {
|
|
12899
12998
|
await settle(client, restore).catch(() => {
|
|
12900
12999
|
});
|
|
12901
13000
|
throw again;
|
|
@@ -14256,15 +14355,33 @@ var Launcher = class {
|
|
|
14256
14355
|
return void 0;
|
|
14257
14356
|
}
|
|
14258
14357
|
const inner = await this.interpreted(interp, [interp, ...passed], cwd, scope, depth + 1);
|
|
14259
|
-
|
|
14358
|
+
const via = [interp, ...inner?.via ?? []];
|
|
14359
|
+
return inner && { ...inner, target: withScriptEnv(inner.target, command), via };
|
|
14260
14360
|
}
|
|
14261
14361
|
const target = withScriptEnv(found, command);
|
|
14262
|
-
return { target, args: [...target.prefix ?? [], ...passed] };
|
|
14362
|
+
return { target, args: [...target.prefix ?? [], ...passed], via: [interp] };
|
|
14263
14363
|
}
|
|
14264
14364
|
async plan(file, argv, cwd, scope) {
|
|
14265
14365
|
const direct = await this.resolve(file, argv[0] ?? file, cwd, scope);
|
|
14266
14366
|
if (direct) return { target: direct, args: [...direct.prefix ?? [], ...argv.slice(1)] };
|
|
14267
|
-
|
|
14367
|
+
const script = await this.interpreted(file, argv, cwd, scope);
|
|
14368
|
+
return script && { ...script, script: true };
|
|
14369
|
+
}
|
|
14370
|
+
async mayExec(cred, req, planned) {
|
|
14371
|
+
const { dac } = this;
|
|
14372
|
+
if (!dac) return;
|
|
14373
|
+
const g = { fs: this.fs, cred, pid: req.pid, dac };
|
|
14374
|
+
const byPath = (file) => file.includes("/") && !COMMAND2.test(file);
|
|
14375
|
+
if (byPath(req.file)) {
|
|
14376
|
+
const path = this.fs.resolvePath(req.cwd, req.file);
|
|
14377
|
+
await need(g, "exec", path, planned?.script ? R_OK | X_OK : X_OK);
|
|
14378
|
+
}
|
|
14379
|
+
const via = planned?.via ?? [];
|
|
14380
|
+
for (const [i, file] of via.entries()) {
|
|
14381
|
+
if (!byPath(file)) continue;
|
|
14382
|
+
const want = i < via.length - 1 ? R_OK | X_OK : X_OK;
|
|
14383
|
+
await need(g, "exec", this.fs.resolvePath(req.cwd, file), want);
|
|
14384
|
+
}
|
|
14268
14385
|
}
|
|
14269
14386
|
async unrunnable(file, cwd, scope) {
|
|
14270
14387
|
const path = this.fs.resolvePath(cwd, file);
|
|
@@ -14484,6 +14601,12 @@ var Launcher = class {
|
|
|
14484
14601
|
return async (req, fds) => {
|
|
14485
14602
|
const scope = await this.scopeOf(this.credOf(ppid).euid);
|
|
14486
14603
|
const planned = await this.plan(req.file, req.argv, req.cwd, scope);
|
|
14604
|
+
try {
|
|
14605
|
+
await this.mayExec(this.credOf(ppid), { ...req, pid: ppid }, planned);
|
|
14606
|
+
} catch (err) {
|
|
14607
|
+
await fds.closeAll();
|
|
14608
|
+
throw err.code === "EACCES" ? new SpawnError("EACCES") : err;
|
|
14609
|
+
}
|
|
14487
14610
|
if (!planned) {
|
|
14488
14611
|
await fds.closeAll();
|
|
14489
14612
|
throw new SpawnError(await this.unrunnable(req.file, req.cwd, scope));
|
|
@@ -14693,8 +14816,13 @@ var Launcher = class {
|
|
|
14693
14816
|
this.fs
|
|
14694
14817
|
);
|
|
14695
14818
|
void this.unlinked.sweep(entry.target);
|
|
14819
|
+
if (this.pnpmHome.startsWith(`${entry.target.replace(/\/$/, "")}/`))
|
|
14820
|
+
await this.provisionPnpmHome();
|
|
14696
14821
|
return entry;
|
|
14697
14822
|
}
|
|
14823
|
+
async provisionPnpmHome() {
|
|
14824
|
+
await this.base.mkdir(this.pnpmHome, { recursive: true }).catch(() => void 0);
|
|
14825
|
+
}
|
|
14698
14826
|
mountedBy(spec, cred) {
|
|
14699
14827
|
if (!this.owners || cred.euid === 0 && cred.egid === 0) return spec;
|
|
14700
14828
|
const ids = { uid: String(cred.euid), gid: String(cred.egid) };
|
|
@@ -14762,6 +14890,8 @@ var Launcher = class {
|
|
|
14762
14890
|
}
|
|
14763
14891
|
async prepare() {
|
|
14764
14892
|
for (const dir of SHARED_DIRS) await this.base.mkdir(dir, { recursive: true });
|
|
14893
|
+
if (this.owners) await this.base.chmod("/tmp", 1023);
|
|
14894
|
+
await this.provisionPnpmHome();
|
|
14765
14895
|
await this.users.ensure();
|
|
14766
14896
|
await writeCaFile(this.base, this.ca).catch(() => void 0);
|
|
14767
14897
|
this.fstab = this.mountFstab();
|
|
@@ -14808,7 +14938,9 @@ var Launcher = class {
|
|
|
14808
14938
|
const cwd = await physicalPathAsync(this.base, start2.startsWith("/") ? start2 : `/${start2}`);
|
|
14809
14939
|
const [file = ""] = argv;
|
|
14810
14940
|
await this.base.mkdir(cwd, { recursive: true });
|
|
14811
|
-
|
|
14941
|
+
const planned = await this.plan(file, argv, cwd, scope);
|
|
14942
|
+
await this.mayExec(credOf(account), { file, cwd, pid: 0 }, planned);
|
|
14943
|
+
return { cwd, file, planned };
|
|
14812
14944
|
}
|
|
14813
14945
|
async openTerminal(argv, options) {
|
|
14814
14946
|
const account = await this.account(options.user);
|