@ai-ecoverse/slicc-kernel 1.62.4 → 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 +8 -2
- package/dist/kernel-worker.js +366 -231
- 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 +366 -231
- 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 });
|
|
@@ -6600,6 +6657,7 @@ async function run(entry, path, req) {
|
|
|
6600
6657
|
return done;
|
|
6601
6658
|
case "create":
|
|
6602
6659
|
await createExclusive(fs, path, ownerFor2(entry, req.mode ?? 438));
|
|
6660
|
+
entry.created?.add(path);
|
|
6603
6661
|
return done;
|
|
6604
6662
|
case "readlink":
|
|
6605
6663
|
return json2(await fs.readlink(path));
|
|
@@ -6656,11 +6714,47 @@ async function guard(g, path, req, cwd) {
|
|
|
6656
6714
|
return linkable(g, path, other(), req.mode === 1);
|
|
6657
6715
|
case "utimes":
|
|
6658
6716
|
case "lutimes":
|
|
6659
|
-
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;
|
|
6660
6726
|
default:
|
|
6661
6727
|
return void 0;
|
|
6662
6728
|
}
|
|
6663
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
|
+
}
|
|
6664
6758
|
async function guarded(entry, path, req) {
|
|
6665
6759
|
const g = guardOf(entry);
|
|
6666
6760
|
if (!g) return void 0;
|
|
@@ -6724,16 +6818,6 @@ async function owned(entry, own, req, path, target) {
|
|
|
6724
6818
|
}
|
|
6725
6819
|
return own(target, () => run(entry, path, req));
|
|
6726
6820
|
}
|
|
6727
|
-
async function holdOp(entry, path, req) {
|
|
6728
|
-
const mode = req.mode ?? 0;
|
|
6729
|
-
const [on, open] = [(mode & 1) === 1, (mode & 2) === 2];
|
|
6730
|
-
if (on && open) {
|
|
6731
|
-
const real = await entry.fs.realpath?.(path, true).catch(() => path);
|
|
6732
|
-
return json2(entry.hold?.(path, on, open, real) ?? null);
|
|
6733
|
-
}
|
|
6734
|
-
entry.hold?.(path, on, open, void 0, req.handle);
|
|
6735
|
-
return done;
|
|
6736
|
-
}
|
|
6737
6821
|
var IDENTITY_OPS = /* @__PURE__ */ new Set([
|
|
6738
6822
|
"write",
|
|
6739
6823
|
"pwrite",
|
|
@@ -6770,7 +6854,8 @@ async function dispatchOne(entry, req) {
|
|
|
6770
6854
|
const path = fs.resolvePath(cwd, req.path);
|
|
6771
6855
|
if (req.op === "kept") return json2(entry.keptFor?.(req.handle ?? -1) !== void 0);
|
|
6772
6856
|
if (req.op === "stat" && req.handle !== void 0) return await keptStat(entry, req);
|
|
6773
|
-
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);
|
|
6774
6859
|
const refused2 = await guarded(entry, path, req);
|
|
6775
6860
|
if (refused2) return refused2;
|
|
6776
6861
|
if (req.op === "statfs") return json2(await entry.statfs?.(path) ?? await storageUsage());
|
|
@@ -6966,188 +7051,6 @@ function ownNames(hostname) {
|
|
|
6966
7051
|
return [.../* @__PURE__ */ new Set([hostname.toLowerCase(), ...LIBC_HOSTNAMES])];
|
|
6967
7052
|
}
|
|
6968
7053
|
|
|
6969
|
-
// src/process/process-fds.ts
|
|
6970
|
-
var field2 = (text) => (text || "none").replace(/[\s\\]/g, (c) => `\\${c.charCodeAt(0).toString(8).padStart(3, "0")}`);
|
|
6971
|
-
function mountTable(mounts = []) {
|
|
6972
|
-
const root = globalThis.navigator?.storage ? "opfs" : "memory";
|
|
6973
|
-
const lines2 = [`${root} / ${root} rw 0 0`, "devfs /dev devfs rw 0 0", "proc /proc proc rw 0 0"];
|
|
6974
|
-
for (const m of mounts) {
|
|
6975
|
-
const options = Object.entries(m.options).map(([k, v]) => v === "" ? k : `${k}=${v}`);
|
|
6976
|
-
if (m.state !== "ok") options.push(m.state);
|
|
6977
|
-
const access2 = options.includes("ro") ? [] : ["rw"];
|
|
6978
|
-
lines2.push(
|
|
6979
|
-
`${field2(m.source)} ${field2(m.target)} ${m.type} ${[...access2, ...options].join(",")} 0 0`
|
|
6980
|
-
);
|
|
6981
|
-
}
|
|
6982
|
-
return `${lines2.join("\n")}
|
|
6983
|
-
`;
|
|
6984
|
-
}
|
|
6985
|
-
|
|
6986
|
-
// src/process/procfs.ts
|
|
6987
|
-
var HZ = 100;
|
|
6988
|
-
var KIB = 1024;
|
|
6989
|
-
var FALLBACK_MEMORY = 4 * KIB * KIB * KIB;
|
|
6990
|
-
var PID_FILES = ["cmdline", "comm", "stat", "statm", "status"];
|
|
6991
|
-
var SYSTEM_FILES = ["loadavg", "meminfo", "stat", "uptime"];
|
|
6992
|
-
function commOf(info) {
|
|
6993
|
-
const name2 = info.argv[0] ?? "";
|
|
6994
|
-
return name2.slice(name2.lastIndexOf("/") + 1).slice(0, 15);
|
|
6995
|
-
}
|
|
6996
|
-
function ttyNumber(tty) {
|
|
6997
|
-
const pts = tty && /^\/dev\/pts\/(\d+)$/.exec(tty);
|
|
6998
|
-
if (pts) return 136 << 8 | Number(pts[1]);
|
|
6999
|
-
const vt = tty && /^\/dev\/tty(\d+)$/.exec(tty);
|
|
7000
|
-
return vt ? 4 << 8 | Number(vt[1]) : 0;
|
|
7001
|
-
}
|
|
7002
|
-
function pages(bytes) {
|
|
7003
|
-
return Math.ceil(bytes / 4096);
|
|
7004
|
-
}
|
|
7005
|
-
function ticks(ms) {
|
|
7006
|
-
return Math.max(0, Math.floor(ms * HZ / 1e3));
|
|
7007
|
-
}
|
|
7008
|
-
function pidStat(info, boot) {
|
|
7009
|
-
const fields = [
|
|
7010
|
-
info.pid,
|
|
7011
|
-
`(${commOf(info)})`,
|
|
7012
|
-
info.state,
|
|
7013
|
-
info.ppid,
|
|
7014
|
-
info.pgid,
|
|
7015
|
-
info.sid,
|
|
7016
|
-
ttyNumber(info.tty),
|
|
7017
|
-
info.tty ? info.pgid : -1,
|
|
7018
|
-
4194304,
|
|
7019
|
-
0,
|
|
7020
|
-
0,
|
|
7021
|
-
0,
|
|
7022
|
-
0,
|
|
7023
|
-
0,
|
|
7024
|
-
0,
|
|
7025
|
-
0,
|
|
7026
|
-
0,
|
|
7027
|
-
20,
|
|
7028
|
-
0,
|
|
7029
|
-
1,
|
|
7030
|
-
0,
|
|
7031
|
-
ticks(info.started - boot),
|
|
7032
|
-
info.memory,
|
|
7033
|
-
pages(info.memory),
|
|
7034
|
-
"18446744073709551615",
|
|
7035
|
-
...Array(12).fill(0),
|
|
7036
|
-
17,
|
|
7037
|
-
0,
|
|
7038
|
-
0,
|
|
7039
|
-
0,
|
|
7040
|
-
0,
|
|
7041
|
-
0,
|
|
7042
|
-
0,
|
|
7043
|
-
...Array(7).fill(0),
|
|
7044
|
-
0
|
|
7045
|
-
];
|
|
7046
|
-
return `${fields.join(" ")}
|
|
7047
|
-
`;
|
|
7048
|
-
}
|
|
7049
|
-
var sigMask = (mask = 0) => (mask >>> 1).toString(16).padStart(16, "0");
|
|
7050
|
-
function pidStatus(info) {
|
|
7051
|
-
const state = info.state === "Z" ? "Z (zombie)" : "S (sleeping)";
|
|
7052
|
-
const c = info.cred ?? ROOT;
|
|
7053
|
-
const ids = (r, e, s) => `${r} ${e} ${s} ${e}`;
|
|
7054
|
-
return [
|
|
7055
|
-
`Name: ${commOf(info)}`,
|
|
7056
|
-
`Umask: ${(info.umask ?? 18).toString(8).padStart(4, "0")}`,
|
|
7057
|
-
`State: ${state}`,
|
|
7058
|
-
`Tgid: ${info.pid}`,
|
|
7059
|
-
"Ngid: 0",
|
|
7060
|
-
`Pid: ${info.pid}`,
|
|
7061
|
-
`PPid: ${info.ppid}`,
|
|
7062
|
-
"TracerPid: 0",
|
|
7063
|
-
`Uid: ${ids(c.ruid, c.euid, c.suid)}`,
|
|
7064
|
-
`Gid: ${ids(c.rgid, c.egid, c.sgid)}`,
|
|
7065
|
-
"FDSize: 64",
|
|
7066
|
-
`VmSize: ${Math.ceil(info.memory / KIB)} kB`,
|
|
7067
|
-
`VmRSS: ${Math.ceil(info.memory / KIB)} kB`,
|
|
7068
|
-
`Groups: ${c.groups.join(" ")}`,
|
|
7069
|
-
`NSpid: ${info.pid}`,
|
|
7070
|
-
`NSpgid: ${info.pgid}`,
|
|
7071
|
-
`NSsid: ${info.sid}`,
|
|
7072
|
-
"Threads: 1",
|
|
7073
|
-
"SigQ: 0/0",
|
|
7074
|
-
"SigPnd: 0000000000000000",
|
|
7075
|
-
"ShdPnd: 0000000000000000",
|
|
7076
|
-
"SigBlk: 0000000000000000",
|
|
7077
|
-
`SigIgn: ${sigMask(info.sigIgn)}`,
|
|
7078
|
-
`SigCgt: ${sigMask(info.sigCgt)}`,
|
|
7079
|
-
""
|
|
7080
|
-
].join("\n");
|
|
7081
|
-
}
|
|
7082
|
-
function pidFile(name2, info, boot) {
|
|
7083
|
-
if (name2 === "cmdline") return info.state === "Z" ? "" : `${info.argv.join("\0")}\0`;
|
|
7084
|
-
if (name2 === "comm") return `${commOf(info)}
|
|
7085
|
-
`;
|
|
7086
|
-
if (name2 === "stat") return pidStat(info, boot);
|
|
7087
|
-
if (name2 === "statm") {
|
|
7088
|
-
const p = pages(info.memory);
|
|
7089
|
-
return `${p} ${p} 0 0 0 ${p} 0
|
|
7090
|
-
`;
|
|
7091
|
-
}
|
|
7092
|
-
return pidStatus(info);
|
|
7093
|
-
}
|
|
7094
|
-
function memoryInfo(source, used = 0) {
|
|
7095
|
-
const total = source.deviceMemory ? source.deviceMemory * KIB * KIB * KIB : FALLBACK_MEMORY;
|
|
7096
|
-
const free = Math.max(0, total - used - (source.usedHeap ?? 0));
|
|
7097
|
-
const kb = (bytes) => `${Math.floor(bytes / KIB)} kB`;
|
|
7098
|
-
return [
|
|
7099
|
-
["MemTotal", kb(total)],
|
|
7100
|
-
["MemFree", kb(free)],
|
|
7101
|
-
["MemAvailable", kb(free)],
|
|
7102
|
-
["Buffers", kb(0)],
|
|
7103
|
-
["Cached", kb(0)],
|
|
7104
|
-
["SwapCached", kb(0)],
|
|
7105
|
-
["Shmem", kb(0)],
|
|
7106
|
-
["SReclaimable", kb(0)],
|
|
7107
|
-
["SwapTotal", kb(0)],
|
|
7108
|
-
["SwapFree", kb(0)]
|
|
7109
|
-
].map(([key, value]) => `${`${key}:`.padEnd(16)}${value.padStart(12)}`).concat("").join("\n");
|
|
7110
|
-
}
|
|
7111
|
-
function systemFile(name2, listing, now, memory) {
|
|
7112
|
-
const up = Math.max(0, now - listing.boot) / 1e3;
|
|
7113
|
-
if (name2 === "uptime") return `${up.toFixed(2)} ${up.toFixed(2)}
|
|
7114
|
-
`;
|
|
7115
|
-
if (name2 === "meminfo") {
|
|
7116
|
-
return memoryInfo(
|
|
7117
|
-
memory,
|
|
7118
|
-
listing.processes.reduce((sum, p) => sum + p.memory, 0)
|
|
7119
|
-
);
|
|
7120
|
-
}
|
|
7121
|
-
const live = listing.processes.filter((p) => p.state !== "Z");
|
|
7122
|
-
if (name2 === "loadavg") {
|
|
7123
|
-
const last = Math.max(0, ...listing.processes.map((p) => p.pid));
|
|
7124
|
-
return `0.00 0.00 0.00 1/${live.length} ${last}
|
|
7125
|
-
`;
|
|
7126
|
-
}
|
|
7127
|
-
const idle = ticks(now - listing.boot);
|
|
7128
|
-
return [
|
|
7129
|
-
`cpu 0 0 0 ${idle} 0 0 0 0 0 0`,
|
|
7130
|
-
`cpu0 0 0 0 ${idle} 0 0 0 0 0 0`,
|
|
7131
|
-
"intr 0",
|
|
7132
|
-
"ctxt 0",
|
|
7133
|
-
`btime ${Math.floor(listing.boot / 1e3)}`,
|
|
7134
|
-
`processes ${listing.processes.length}`,
|
|
7135
|
-
"procs_running 1",
|
|
7136
|
-
"procs_blocked 0",
|
|
7137
|
-
""
|
|
7138
|
-
].join("\n");
|
|
7139
|
-
}
|
|
7140
|
-
function memorySource(scope = globalThis) {
|
|
7141
|
-
const nav = scope.navigator;
|
|
7142
|
-
const perf = scope.performance;
|
|
7143
|
-
const deviceMemory = nav?.deviceMemory;
|
|
7144
|
-
const used = perf?.memory?.usedJSHeapSize;
|
|
7145
|
-
return {
|
|
7146
|
-
...typeof deviceMemory === "number" && deviceMemory > 0 ? { deviceMemory } : {},
|
|
7147
|
-
...typeof used === "number" ? { usedHeap: used } : {}
|
|
7148
|
-
};
|
|
7149
|
-
}
|
|
7150
|
-
|
|
7151
7054
|
// src/fs/pages.ts
|
|
7152
7055
|
var PAGE = 64 * 1024;
|
|
7153
7056
|
var READAHEAD = 1024 * 1024;
|
|
@@ -7373,6 +7276,191 @@ var AsyncRangedFile = class {
|
|
|
7373
7276
|
}
|
|
7374
7277
|
};
|
|
7375
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
|
+
|
|
7376
7464
|
// src/process/wasi/wasi-files.ts
|
|
7377
7465
|
function normalize(path) {
|
|
7378
7466
|
const out = [];
|
|
@@ -8561,11 +8649,11 @@ function realmCa(owner, store) {
|
|
|
8561
8649
|
opened.set(store, cas);
|
|
8562
8650
|
let ca = cas.get(owner);
|
|
8563
8651
|
if (!ca) {
|
|
8564
|
-
const
|
|
8565
|
-
ca =
|
|
8566
|
-
cas.set(owner,
|
|
8567
|
-
|
|
8568
|
-
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);
|
|
8569
8657
|
});
|
|
8570
8658
|
}
|
|
8571
8659
|
return ca;
|
|
@@ -10972,6 +11060,7 @@ var WasmProcess = class {
|
|
|
10972
11060
|
throw Object.assign(new Error(alias.refused), { code: alias.refused });
|
|
10973
11061
|
if (alias !== void 0) return this.openProc(req, alias);
|
|
10974
11062
|
await refuseReadonly(this.options.fs, req.path, req.flags, req);
|
|
11063
|
+
await this.mayOpen(req);
|
|
10975
11064
|
const fd = this.fds.install(heldFile(), 3);
|
|
10976
11065
|
try {
|
|
10977
11066
|
const nodes = this.nodes;
|
|
@@ -11017,6 +11106,17 @@ var WasmProcess = class {
|
|
|
11017
11106
|
};
|
|
11018
11107
|
return fs.exclusive ? fs.exclusive(first.path, look) : look();
|
|
11019
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
|
+
}
|
|
11020
11120
|
newOwner() {
|
|
11021
11121
|
if (!this.options.owners) return void 0;
|
|
11022
11122
|
return { uid: this.cred.euid, gid: this.cred.egid, mode: 438 & ~this.umask };
|
|
@@ -11701,7 +11801,7 @@ function inherited(opts) {
|
|
|
11701
11801
|
function holdingToken(opts, holds, caller) {
|
|
11702
11802
|
return mintSyncFsToken({
|
|
11703
11803
|
...opts.owners ? caller : {},
|
|
11704
|
-
...opts.dac ? { dac: opts.dac, pid: opts.pid } : {},
|
|
11804
|
+
...opts.dac ? { dac: opts.dac, pid: opts.pid, created: caller.created } : {},
|
|
11705
11805
|
fs: opts.fs,
|
|
11706
11806
|
cwd: opts.cwd,
|
|
11707
11807
|
...opts.statfs ? { statfs: opts.statfs } : {},
|
|
@@ -11714,10 +11814,11 @@ function holdingToken(opts, holds, caller) {
|
|
|
11714
11814
|
renamed: (from, to) => holds.renamed(from, to)
|
|
11715
11815
|
});
|
|
11716
11816
|
}
|
|
11717
|
-
function processOptions(opts, header4, hooks) {
|
|
11817
|
+
function processOptions(opts, header4, hooks, created3) {
|
|
11718
11818
|
return {
|
|
11719
11819
|
...inherited(opts),
|
|
11720
11820
|
...opts.owners ? { owners: true } : {},
|
|
11821
|
+
...opts.dac ? { guard: { dac: opts.dac, fs: opts.fs, created: created3 } } : {},
|
|
11721
11822
|
...opts.identity ? { identity: opts.identity } : {},
|
|
11722
11823
|
...opts.onSyscall ? { onSyscall: opts.onSyscall } : {},
|
|
11723
11824
|
...opts.settling ? { settling: opts.settling } : {},
|
|
@@ -11751,20 +11852,27 @@ function spawnWasmProcess(opts) {
|
|
|
11751
11852
|
const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
11752
11853
|
const header4 = new Int32Array(sab, 0, SAB_HEADER_I32);
|
|
11753
11854
|
const threadSignals = /* @__PURE__ */ new Map();
|
|
11855
|
+
const created3 = new Created();
|
|
11754
11856
|
const process2 = new WasmProcess(
|
|
11755
11857
|
opts.pid,
|
|
11756
11858
|
opts.fds,
|
|
11757
|
-
processOptions(
|
|
11758
|
-
|
|
11759
|
-
|
|
11760
|
-
|
|
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
|
+
)
|
|
11761
11868
|
);
|
|
11762
11869
|
publishStops(process2, header4);
|
|
11763
11870
|
const holds = new HeldPaths();
|
|
11764
11871
|
opts.held?.add(holds);
|
|
11765
11872
|
const token = holdingToken(opts, holds, {
|
|
11766
11873
|
cred: () => process2.cred,
|
|
11767
|
-
umask: () => process2.umask
|
|
11874
|
+
umask: () => process2.umask,
|
|
11875
|
+
created: created3
|
|
11768
11876
|
});
|
|
11769
11877
|
process2.keptPath = (path) => holds.keptAt(path)?.hidden;
|
|
11770
11878
|
process2.keptHandle = (handle2) => holds.keptFor(handle2)?.hidden;
|
|
@@ -12877,16 +12985,16 @@ function hostfsHandlers(current, againMs = RESTORE_AGAIN_MS) {
|
|
|
12877
12985
|
});
|
|
12878
12986
|
async function writable2(client, path, flags) {
|
|
12879
12987
|
const { ifMatch: _, ...asked } = flags;
|
|
12880
|
-
const
|
|
12988
|
+
const opening2 = () => client.call("open", { path: rel(path), ...asked });
|
|
12881
12989
|
try {
|
|
12882
|
-
return { opened: await
|
|
12990
|
+
return { opened: await opening2(), restore: void 0 };
|
|
12883
12991
|
} catch (err) {
|
|
12884
12992
|
if (!flags.write || codeOf4(err) !== "EACCES") throw err;
|
|
12885
12993
|
const was = await client.call("stat", { path: rel(path) });
|
|
12886
12994
|
const mode = was.mode ?? 0;
|
|
12887
12995
|
if (mode & 128) throw err;
|
|
12888
12996
|
const restore = { path: rel(path), mode, was };
|
|
12889
|
-
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) => {
|
|
12890
12998
|
await settle(client, restore).catch(() => {
|
|
12891
12999
|
});
|
|
12892
13000
|
throw again;
|
|
@@ -14247,15 +14355,33 @@ var Launcher = class {
|
|
|
14247
14355
|
return void 0;
|
|
14248
14356
|
}
|
|
14249
14357
|
const inner = await this.interpreted(interp, [interp, ...passed], cwd, scope, depth + 1);
|
|
14250
|
-
|
|
14358
|
+
const via = [interp, ...inner?.via ?? []];
|
|
14359
|
+
return inner && { ...inner, target: withScriptEnv(inner.target, command), via };
|
|
14251
14360
|
}
|
|
14252
14361
|
const target = withScriptEnv(found, command);
|
|
14253
|
-
return { target, args: [...target.prefix ?? [], ...passed] };
|
|
14362
|
+
return { target, args: [...target.prefix ?? [], ...passed], via: [interp] };
|
|
14254
14363
|
}
|
|
14255
14364
|
async plan(file, argv, cwd, scope) {
|
|
14256
14365
|
const direct = await this.resolve(file, argv[0] ?? file, cwd, scope);
|
|
14257
14366
|
if (direct) return { target: direct, args: [...direct.prefix ?? [], ...argv.slice(1)] };
|
|
14258
|
-
|
|
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
|
+
}
|
|
14259
14385
|
}
|
|
14260
14386
|
async unrunnable(file, cwd, scope) {
|
|
14261
14387
|
const path = this.fs.resolvePath(cwd, file);
|
|
@@ -14475,6 +14601,12 @@ var Launcher = class {
|
|
|
14475
14601
|
return async (req, fds) => {
|
|
14476
14602
|
const scope = await this.scopeOf(this.credOf(ppid).euid);
|
|
14477
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
|
+
}
|
|
14478
14610
|
if (!planned) {
|
|
14479
14611
|
await fds.closeAll();
|
|
14480
14612
|
throw new SpawnError(await this.unrunnable(req.file, req.cwd, scope));
|
|
@@ -14758,6 +14890,7 @@ var Launcher = class {
|
|
|
14758
14890
|
}
|
|
14759
14891
|
async prepare() {
|
|
14760
14892
|
for (const dir of SHARED_DIRS) await this.base.mkdir(dir, { recursive: true });
|
|
14893
|
+
if (this.owners) await this.base.chmod("/tmp", 1023);
|
|
14761
14894
|
await this.provisionPnpmHome();
|
|
14762
14895
|
await this.users.ensure();
|
|
14763
14896
|
await writeCaFile(this.base, this.ca).catch(() => void 0);
|
|
@@ -14805,7 +14938,9 @@ var Launcher = class {
|
|
|
14805
14938
|
const cwd = await physicalPathAsync(this.base, start2.startsWith("/") ? start2 : `/${start2}`);
|
|
14806
14939
|
const [file = ""] = argv;
|
|
14807
14940
|
await this.base.mkdir(cwd, { recursive: true });
|
|
14808
|
-
|
|
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 };
|
|
14809
14944
|
}
|
|
14810
14945
|
async openTerminal(argv, options) {
|
|
14811
14946
|
const account = await this.account(options.user);
|