@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/kernel-worker.js
CHANGED
|
@@ -429,11 +429,16 @@ var OpfsFs = class {
|
|
|
429
429
|
}
|
|
430
430
|
async ancestry(path) {
|
|
431
431
|
const entries = await this.meta.get(chain(path));
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
432
|
+
const out = [];
|
|
433
|
+
for (const [i, entry] of entries.entries()) {
|
|
434
|
+
const link2 = entry?.link !== void 0 && !await this.real(entry.path);
|
|
435
|
+
out.push({
|
|
436
|
+
...ownOf(entry) ?? (i === 0 ? ROOT_OWNER : inherit(entries.slice(0, i))),
|
|
437
|
+
...entry?.mode !== void 0 ? { mode: entry.mode } : {},
|
|
438
|
+
...link2 ? { link: entry.link } : {}
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
return out;
|
|
437
442
|
}
|
|
438
443
|
async handedTo(dir) {
|
|
439
444
|
return inherit(await this.meta.get(chain(dir)));
|
|
@@ -1397,15 +1402,24 @@ async function present(fs, path, directory) {
|
|
|
1397
1402
|
const st = await fs.lstat(path).catch(() => void 0);
|
|
1398
1403
|
return st !== void 0 && (!directory || st.isDirectory);
|
|
1399
1404
|
}
|
|
1405
|
+
async function finalOf(fs, walked, want, options) {
|
|
1406
|
+
const perm = walked.perm;
|
|
1407
|
+
if ((want & X_OK) === 0 || options.directory !== void 0) {
|
|
1408
|
+
return [perm, options.directory !== false];
|
|
1409
|
+
}
|
|
1410
|
+
const look = options.follow === false ? fs.lstat : fs.stat;
|
|
1411
|
+
const st = await look.call(fs, walked.path).catch(() => void 0);
|
|
1412
|
+
return st ? [permOf(st), st.isDirectory] : [perm, false];
|
|
1413
|
+
}
|
|
1400
1414
|
async function access(fs, cred, path, want, options = {}) {
|
|
1401
1415
|
const walked = await walk(fs, cred, path, options.follow !== false);
|
|
1402
1416
|
if (walked.denied !== void 0) {
|
|
1403
1417
|
if (await present(fs, walked.denied, true)) return walked;
|
|
1404
1418
|
return { path, perm: void 0, missing: true };
|
|
1405
1419
|
}
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
if (want === 0 || permits(cred, perm, want,
|
|
1420
|
+
if (!walked.perm) return { ...walked, missing: true };
|
|
1421
|
+
const [perm, directory] = await finalOf(fs, walked, want, options);
|
|
1422
|
+
if (want === 0 || permits(cred, perm, want, directory)) return walked;
|
|
1409
1423
|
if (await present(fs, walked.path, false)) return { ...walked, denied: walked.path };
|
|
1410
1424
|
return { ...walked, missing: true };
|
|
1411
1425
|
}
|
|
@@ -1416,6 +1430,7 @@ function refused(path, errno = "EACCES") {
|
|
|
1416
1430
|
// src/fs/dac.ts
|
|
1417
1431
|
var MAX_DENIAL_KEYS = 1e4;
|
|
1418
1432
|
var S_ISGID3 = 1024;
|
|
1433
|
+
var DIR = { directory: true };
|
|
1419
1434
|
var Dac = class {
|
|
1420
1435
|
mode;
|
|
1421
1436
|
hook;
|
|
@@ -1452,6 +1467,17 @@ var Dac = class {
|
|
|
1452
1467
|
);
|
|
1453
1468
|
}
|
|
1454
1469
|
};
|
|
1470
|
+
var MAX_CREATED = 1024;
|
|
1471
|
+
var Created = class {
|
|
1472
|
+
paths = /* @__PURE__ */ new Set();
|
|
1473
|
+
add(path) {
|
|
1474
|
+
if (this.paths.size >= MAX_CREATED) this.paths.clear();
|
|
1475
|
+
this.paths.add(normalizePath(path));
|
|
1476
|
+
}
|
|
1477
|
+
take(path) {
|
|
1478
|
+
return this.paths.delete(normalizePath(path));
|
|
1479
|
+
}
|
|
1480
|
+
};
|
|
1455
1481
|
function deny(g, op, path, errno = "EACCES") {
|
|
1456
1482
|
g.dac.denied({ pid: g.pid, uid: g.cred.euid, op, path, errno });
|
|
1457
1483
|
}
|
|
@@ -1460,20 +1486,30 @@ async function need(g, op, path, want, options = {}, shown = path) {
|
|
|
1460
1486
|
if (walked.denied !== void 0) deny(g, op, shown);
|
|
1461
1487
|
return walked;
|
|
1462
1488
|
}
|
|
1489
|
+
function entryIn(dir, path) {
|
|
1490
|
+
return joinName(dir.path, path.slice(path.lastIndexOf("/") + 1));
|
|
1491
|
+
}
|
|
1463
1492
|
async function stickyEntry(g, op, path, dir) {
|
|
1464
1493
|
const perm = dir.perm;
|
|
1465
1494
|
if (!perm || sticky(g.cred, perm, perm)) return;
|
|
1466
|
-
const entry =
|
|
1495
|
+
const entry = entryIn(dir, path);
|
|
1467
1496
|
if (sticky(g.cred, perm, (await ancestryOf(g.fs, entry)).at(-1))) return;
|
|
1468
1497
|
if (await present(g.fs, entry, false)) deny(g, op, path, "EPERM");
|
|
1469
1498
|
}
|
|
1470
1499
|
async function inParent(g, op, path, old = false) {
|
|
1471
|
-
|
|
1472
|
-
|
|
1500
|
+
if (old === "replaced") {
|
|
1501
|
+
const dir2 = await need(g, op, parentOf3(path), W_OK | X_OK, DIR, path);
|
|
1502
|
+
return dir2.denied === void 0 ? stickyEntry(g, op, path, dir2) : void 0;
|
|
1503
|
+
}
|
|
1504
|
+
if (!old) return void await need(g, op, parentOf3(path), W_OK | X_OK, DIR, path);
|
|
1505
|
+
const dir = await access(g.fs, g.cred, parentOf3(path), W_OK | X_OK, DIR);
|
|
1506
|
+
if (dir.denied === void 0) return stickyEntry(g, op, path, dir);
|
|
1507
|
+
const lookup = dir.denied === dir.path && dir.perm && permits(g.cred, dir.perm, X_OK);
|
|
1508
|
+
if (!lookup || await present(g.fs, entryIn(dir, path), false)) deny(g, op, path);
|
|
1473
1509
|
}
|
|
1474
1510
|
async function makeIn(g, op, path) {
|
|
1475
1511
|
for (let dir = parentOf3(path); ; dir = parentOf3(dir)) {
|
|
1476
|
-
const walked = await access(g.fs, g.cred, dir, W_OK | X_OK);
|
|
1512
|
+
const walked = await access(g.fs, g.cred, dir, W_OK | X_OK, DIR);
|
|
1477
1513
|
if (walked.denied !== void 0) {
|
|
1478
1514
|
if (!await present(g.fs, path, true)) deny(g, op, path);
|
|
1479
1515
|
return;
|
|
@@ -1499,7 +1535,7 @@ async function removable(g, op, path) {
|
|
|
1499
1535
|
async function renamable(g, from, to) {
|
|
1500
1536
|
if (from === to) return void await need(g, "rename", from, 0, { follow: false });
|
|
1501
1537
|
await inParent(g, "rename", from, true);
|
|
1502
|
-
await inParent(g, "rename", to,
|
|
1538
|
+
await inParent(g, "rename", to, "replaced");
|
|
1503
1539
|
if (g.cred.euid === 0 || parentOf3(from) === parentOf3(to)) return;
|
|
1504
1540
|
const st = await g.fs.lstat(from).catch(() => void 0);
|
|
1505
1541
|
if (st?.isDirectory && !permits(g.cred, permOf(st), W_OK)) deny(g, "rename", from);
|
|
@@ -1525,8 +1561,20 @@ async function chmodMode(g, path, mode) {
|
|
|
1525
1561
|
if (!g.dac.enforcing || !perm || g.cred.euid === 0 || inGroup(g.cred, perm.gid)) return mode;
|
|
1526
1562
|
return mode & ~S_ISGID3;
|
|
1527
1563
|
}
|
|
1528
|
-
async function retimable(g, op, path) {
|
|
1529
|
-
|
|
1564
|
+
async function retimable(g, op, path, now = false) {
|
|
1565
|
+
const follow2 = op !== "lutimes";
|
|
1566
|
+
if (!now) return void await ownerOnly(g, op, path, follow2);
|
|
1567
|
+
const walked = await need(g, op, path, 0, { follow: follow2 });
|
|
1568
|
+
const perm = walked.perm;
|
|
1569
|
+
if (!perm || g.cred.euid === 0 || perm.uid === g.cred.euid) return;
|
|
1570
|
+
if (permits(g.cred, perm, W_OK, false)) return;
|
|
1571
|
+
if (await present(g.fs, walked.path, false)) deny(g, op, path);
|
|
1572
|
+
}
|
|
1573
|
+
async function fileWritable(g, op, path) {
|
|
1574
|
+
await need(g, op, path, W_OK, { directory: false });
|
|
1575
|
+
}
|
|
1576
|
+
function realIds(cred) {
|
|
1577
|
+
return { ...cred, groups: [...cred.groups], euid: cred.ruid, egid: cred.rgid };
|
|
1530
1578
|
}
|
|
1531
1579
|
async function listable(g, op, path) {
|
|
1532
1580
|
await need(g, op, path, R_OK | X_OK, { directory: true });
|
|
@@ -1538,10 +1586,16 @@ async function readable(g, op, path) {
|
|
|
1538
1586
|
await need(g, op, path, R_OK, { directory: false });
|
|
1539
1587
|
}
|
|
1540
1588
|
async function writable(g, op, path) {
|
|
1541
|
-
|
|
1542
|
-
|
|
1589
|
+
await openable(g, op, path, W_OK, true);
|
|
1590
|
+
}
|
|
1591
|
+
async function creatable(g, op, path) {
|
|
1543
1592
|
const target = await need(g, op, path, 0);
|
|
1544
|
-
if (target.denied === void 0) await need(g, op, parentOf3(target.path), W_OK | X_OK,
|
|
1593
|
+
if (target.denied === void 0) await need(g, op, parentOf3(target.path), W_OK | X_OK, DIR, path);
|
|
1594
|
+
}
|
|
1595
|
+
async function openable(g, op, path, want, create) {
|
|
1596
|
+
const st = create ? await g.fs.stat(path).catch(() => void 0) : void 0;
|
|
1597
|
+
if (create && !st) return creatable(g, op, path);
|
|
1598
|
+
await need(g, op, path, want, { directory: st?.isDirectory ?? false });
|
|
1545
1599
|
}
|
|
1546
1600
|
|
|
1547
1601
|
// src/kernel/pipe.ts
|
|
@@ -4980,11 +5034,11 @@ function realmCa(owner, store) {
|
|
|
4980
5034
|
opened.set(store, cas);
|
|
4981
5035
|
let ca = cas.get(owner);
|
|
4982
5036
|
if (!ca) {
|
|
4983
|
-
const
|
|
4984
|
-
ca =
|
|
4985
|
-
cas.set(owner,
|
|
4986
|
-
|
|
4987
|
-
if (cas.get(owner) ===
|
|
5037
|
+
const opening2 = RealmCa.open(owner, store);
|
|
5038
|
+
ca = opening2;
|
|
5039
|
+
cas.set(owner, opening2);
|
|
5040
|
+
opening2.catch(() => {
|
|
5041
|
+
if (cas.get(owner) === opening2) cas.delete(owner);
|
|
4988
5042
|
});
|
|
4989
5043
|
}
|
|
4990
5044
|
return ca;
|
|
@@ -8052,6 +8106,9 @@ function revokeSyncFsToken(token) {
|
|
|
8052
8106
|
}
|
|
8053
8107
|
|
|
8054
8108
|
// src/realm/sync-fs-wire.ts
|
|
8109
|
+
var HOLD_READ = 4;
|
|
8110
|
+
var HOLD_WRITE = 8;
|
|
8111
|
+
var HOLD_CREATED = 16;
|
|
8055
8112
|
var SYNC_FS_REQUEST_TIMEOUT_MS = 25e3;
|
|
8056
8113
|
function syncError(code, label) {
|
|
8057
8114
|
return Object.assign(new Error(`${code}: ${label}`), { code });
|
|
@@ -8175,6 +8232,7 @@ async function run(entry, path, req) {
|
|
|
8175
8232
|
return done;
|
|
8176
8233
|
case "create":
|
|
8177
8234
|
await createExclusive(fs, path, ownerFor2(entry, req.mode ?? 438));
|
|
8235
|
+
entry.created?.add(path);
|
|
8178
8236
|
return done;
|
|
8179
8237
|
case "readlink":
|
|
8180
8238
|
return json2(await fs.readlink(path));
|
|
@@ -8231,11 +8289,47 @@ async function guard(g, path, req, cwd) {
|
|
|
8231
8289
|
return linkable(g, path, other(), req.mode === 1);
|
|
8232
8290
|
case "utimes":
|
|
8233
8291
|
case "lutimes":
|
|
8234
|
-
return retimable(g, op, path);
|
|
8292
|
+
return retimable(g, op, path, req.now === true);
|
|
8293
|
+
case "read":
|
|
8294
|
+
case "pread":
|
|
8295
|
+
return req.handle === void 0 ? readable(g, op, path) : void 0;
|
|
8296
|
+
case "pwrite":
|
|
8297
|
+
case "truncate":
|
|
8298
|
+
return req.handle === void 0 ? fileWritable(g, op, path) : void 0;
|
|
8299
|
+
case "write":
|
|
8300
|
+
return req.handle === void 0 && req.mode !== 1 ? writable(g, op, path) : void 0;
|
|
8235
8301
|
default:
|
|
8236
8302
|
return void 0;
|
|
8237
8303
|
}
|
|
8238
8304
|
}
|
|
8305
|
+
async function opening(entry, path, mode) {
|
|
8306
|
+
const g = guardOf(entry);
|
|
8307
|
+
const want = (mode & HOLD_READ ? R_OK : 0) | (mode & HOLD_WRITE ? W_OK : 0);
|
|
8308
|
+
const created3 = (mode & HOLD_CREATED) !== 0 && entry.created?.take(path) === true;
|
|
8309
|
+
if (g && want !== 0 && !created3) {
|
|
8310
|
+
await need(g, "open", path, want, { directory: false });
|
|
8311
|
+
}
|
|
8312
|
+
}
|
|
8313
|
+
async function holdOp(entry, path, req) {
|
|
8314
|
+
const mode = req.mode ?? 0;
|
|
8315
|
+
const [on, open] = [(mode & 1) === 1, (mode & 2) === 2];
|
|
8316
|
+
if (on && open) {
|
|
8317
|
+
await opening(entry, path, mode);
|
|
8318
|
+
const real = await entry.fs.realpath?.(path, true).catch(() => path);
|
|
8319
|
+
return json2(entry.hold?.(path, on, open, real) ?? null);
|
|
8320
|
+
}
|
|
8321
|
+
entry.hold?.(path, on, open, void 0, req.handle);
|
|
8322
|
+
return done;
|
|
8323
|
+
}
|
|
8324
|
+
async function accessOp(entry, path, req) {
|
|
8325
|
+
const g = guardOf(entry);
|
|
8326
|
+
if (!g) return done;
|
|
8327
|
+
const open = req.arg2 === "open";
|
|
8328
|
+
const cred = open || req.arg2 === "eaccess" ? g.cred : realIds(g.cred);
|
|
8329
|
+
const options = { follow: req.nofollow !== true, ...open ? { directory: false } : {} };
|
|
8330
|
+
await need({ ...g, cred }, open ? "open" : "access", path, req.mode ?? 0, options);
|
|
8331
|
+
return done;
|
|
8332
|
+
}
|
|
8239
8333
|
async function guarded(entry, path, req) {
|
|
8240
8334
|
const g = guardOf(entry);
|
|
8241
8335
|
if (!g) return void 0;
|
|
@@ -8299,16 +8393,6 @@ async function owned(entry, own, req, path, target) {
|
|
|
8299
8393
|
}
|
|
8300
8394
|
return own(target, () => run(entry, path, req));
|
|
8301
8395
|
}
|
|
8302
|
-
async function holdOp(entry, path, req) {
|
|
8303
|
-
const mode = req.mode ?? 0;
|
|
8304
|
-
const [on, open] = [(mode & 1) === 1, (mode & 2) === 2];
|
|
8305
|
-
if (on && open) {
|
|
8306
|
-
const real = await entry.fs.realpath?.(path, true).catch(() => path);
|
|
8307
|
-
return json2(entry.hold?.(path, on, open, real) ?? null);
|
|
8308
|
-
}
|
|
8309
|
-
entry.hold?.(path, on, open, void 0, req.handle);
|
|
8310
|
-
return done;
|
|
8311
|
-
}
|
|
8312
8396
|
var IDENTITY_OPS = /* @__PURE__ */ new Set([
|
|
8313
8397
|
"write",
|
|
8314
8398
|
"pwrite",
|
|
@@ -8345,7 +8429,8 @@ async function dispatchOne(entry, req) {
|
|
|
8345
8429
|
const path = fs.resolvePath(cwd, req.path);
|
|
8346
8430
|
if (req.op === "kept") return json2(entry.keptFor?.(req.handle ?? -1) !== void 0);
|
|
8347
8431
|
if (req.op === "stat" && req.handle !== void 0) return await keptStat(entry, req);
|
|
8348
|
-
if (req.op === "
|
|
8432
|
+
if (req.op === "access") return await accessOp(entry, path, req);
|
|
8433
|
+
if (req.op === "hold") return await holdOp(entry, path, req);
|
|
8349
8434
|
const refused2 = await guarded(entry, path, req);
|
|
8350
8435
|
if (refused2) return refused2;
|
|
8351
8436
|
if (req.op === "statfs") return json2(await entry.statfs?.(path) ?? await storageUsage());
|
|
@@ -8514,188 +8599,6 @@ function attachSyncSabResponder(port, sab, token, opts) {
|
|
|
8514
8599
|
};
|
|
8515
8600
|
}
|
|
8516
8601
|
|
|
8517
|
-
// src/process/process-fds.ts
|
|
8518
|
-
var field2 = (text) => (text || "none").replace(/[\s\\]/g, (c) => `\\${c.charCodeAt(0).toString(8).padStart(3, "0")}`);
|
|
8519
|
-
function mountTable(mounts = []) {
|
|
8520
|
-
const root = globalThis.navigator?.storage ? "opfs" : "memory";
|
|
8521
|
-
const lines2 = [`${root} / ${root} rw 0 0`, "devfs /dev devfs rw 0 0", "proc /proc proc rw 0 0"];
|
|
8522
|
-
for (const m of mounts) {
|
|
8523
|
-
const options = Object.entries(m.options).map(([k, v]) => v === "" ? k : `${k}=${v}`);
|
|
8524
|
-
if (m.state !== "ok") options.push(m.state);
|
|
8525
|
-
const access2 = options.includes("ro") ? [] : ["rw"];
|
|
8526
|
-
lines2.push(
|
|
8527
|
-
`${field2(m.source)} ${field2(m.target)} ${m.type} ${[...access2, ...options].join(",")} 0 0`
|
|
8528
|
-
);
|
|
8529
|
-
}
|
|
8530
|
-
return `${lines2.join("\n")}
|
|
8531
|
-
`;
|
|
8532
|
-
}
|
|
8533
|
-
|
|
8534
|
-
// src/process/procfs.ts
|
|
8535
|
-
var HZ = 100;
|
|
8536
|
-
var KIB = 1024;
|
|
8537
|
-
var FALLBACK_MEMORY = 4 * KIB * KIB * KIB;
|
|
8538
|
-
var PID_FILES = ["cmdline", "comm", "stat", "statm", "status"];
|
|
8539
|
-
var SYSTEM_FILES = ["loadavg", "meminfo", "stat", "uptime"];
|
|
8540
|
-
function commOf(info) {
|
|
8541
|
-
const name2 = info.argv[0] ?? "";
|
|
8542
|
-
return name2.slice(name2.lastIndexOf("/") + 1).slice(0, 15);
|
|
8543
|
-
}
|
|
8544
|
-
function ttyNumber(tty) {
|
|
8545
|
-
const pts = tty && /^\/dev\/pts\/(\d+)$/.exec(tty);
|
|
8546
|
-
if (pts) return 136 << 8 | Number(pts[1]);
|
|
8547
|
-
const vt = tty && /^\/dev\/tty(\d+)$/.exec(tty);
|
|
8548
|
-
return vt ? 4 << 8 | Number(vt[1]) : 0;
|
|
8549
|
-
}
|
|
8550
|
-
function pages(bytes) {
|
|
8551
|
-
return Math.ceil(bytes / 4096);
|
|
8552
|
-
}
|
|
8553
|
-
function ticks(ms) {
|
|
8554
|
-
return Math.max(0, Math.floor(ms * HZ / 1e3));
|
|
8555
|
-
}
|
|
8556
|
-
function pidStat(info, boot) {
|
|
8557
|
-
const fields = [
|
|
8558
|
-
info.pid,
|
|
8559
|
-
`(${commOf(info)})`,
|
|
8560
|
-
info.state,
|
|
8561
|
-
info.ppid,
|
|
8562
|
-
info.pgid,
|
|
8563
|
-
info.sid,
|
|
8564
|
-
ttyNumber(info.tty),
|
|
8565
|
-
info.tty ? info.pgid : -1,
|
|
8566
|
-
4194304,
|
|
8567
|
-
0,
|
|
8568
|
-
0,
|
|
8569
|
-
0,
|
|
8570
|
-
0,
|
|
8571
|
-
0,
|
|
8572
|
-
0,
|
|
8573
|
-
0,
|
|
8574
|
-
0,
|
|
8575
|
-
20,
|
|
8576
|
-
0,
|
|
8577
|
-
1,
|
|
8578
|
-
0,
|
|
8579
|
-
ticks(info.started - boot),
|
|
8580
|
-
info.memory,
|
|
8581
|
-
pages(info.memory),
|
|
8582
|
-
"18446744073709551615",
|
|
8583
|
-
...Array(12).fill(0),
|
|
8584
|
-
17,
|
|
8585
|
-
0,
|
|
8586
|
-
0,
|
|
8587
|
-
0,
|
|
8588
|
-
0,
|
|
8589
|
-
0,
|
|
8590
|
-
0,
|
|
8591
|
-
...Array(7).fill(0),
|
|
8592
|
-
0
|
|
8593
|
-
];
|
|
8594
|
-
return `${fields.join(" ")}
|
|
8595
|
-
`;
|
|
8596
|
-
}
|
|
8597
|
-
var sigMask = (mask = 0) => (mask >>> 1).toString(16).padStart(16, "0");
|
|
8598
|
-
function pidStatus(info) {
|
|
8599
|
-
const state = info.state === "Z" ? "Z (zombie)" : "S (sleeping)";
|
|
8600
|
-
const c = info.cred ?? ROOT;
|
|
8601
|
-
const ids = (r, e, s) => `${r} ${e} ${s} ${e}`;
|
|
8602
|
-
return [
|
|
8603
|
-
`Name: ${commOf(info)}`,
|
|
8604
|
-
`Umask: ${(info.umask ?? 18).toString(8).padStart(4, "0")}`,
|
|
8605
|
-
`State: ${state}`,
|
|
8606
|
-
`Tgid: ${info.pid}`,
|
|
8607
|
-
"Ngid: 0",
|
|
8608
|
-
`Pid: ${info.pid}`,
|
|
8609
|
-
`PPid: ${info.ppid}`,
|
|
8610
|
-
"TracerPid: 0",
|
|
8611
|
-
`Uid: ${ids(c.ruid, c.euid, c.suid)}`,
|
|
8612
|
-
`Gid: ${ids(c.rgid, c.egid, c.sgid)}`,
|
|
8613
|
-
"FDSize: 64",
|
|
8614
|
-
`VmSize: ${Math.ceil(info.memory / KIB)} kB`,
|
|
8615
|
-
`VmRSS: ${Math.ceil(info.memory / KIB)} kB`,
|
|
8616
|
-
`Groups: ${c.groups.join(" ")}`,
|
|
8617
|
-
`NSpid: ${info.pid}`,
|
|
8618
|
-
`NSpgid: ${info.pgid}`,
|
|
8619
|
-
`NSsid: ${info.sid}`,
|
|
8620
|
-
"Threads: 1",
|
|
8621
|
-
"SigQ: 0/0",
|
|
8622
|
-
"SigPnd: 0000000000000000",
|
|
8623
|
-
"ShdPnd: 0000000000000000",
|
|
8624
|
-
"SigBlk: 0000000000000000",
|
|
8625
|
-
`SigIgn: ${sigMask(info.sigIgn)}`,
|
|
8626
|
-
`SigCgt: ${sigMask(info.sigCgt)}`,
|
|
8627
|
-
""
|
|
8628
|
-
].join("\n");
|
|
8629
|
-
}
|
|
8630
|
-
function pidFile(name2, info, boot) {
|
|
8631
|
-
if (name2 === "cmdline") return info.state === "Z" ? "" : `${info.argv.join("\0")}\0`;
|
|
8632
|
-
if (name2 === "comm") return `${commOf(info)}
|
|
8633
|
-
`;
|
|
8634
|
-
if (name2 === "stat") return pidStat(info, boot);
|
|
8635
|
-
if (name2 === "statm") {
|
|
8636
|
-
const p = pages(info.memory);
|
|
8637
|
-
return `${p} ${p} 0 0 0 ${p} 0
|
|
8638
|
-
`;
|
|
8639
|
-
}
|
|
8640
|
-
return pidStatus(info);
|
|
8641
|
-
}
|
|
8642
|
-
function memoryInfo(source, used = 0) {
|
|
8643
|
-
const total = source.deviceMemory ? source.deviceMemory * KIB * KIB * KIB : FALLBACK_MEMORY;
|
|
8644
|
-
const free = Math.max(0, total - used - (source.usedHeap ?? 0));
|
|
8645
|
-
const kb = (bytes) => `${Math.floor(bytes / KIB)} kB`;
|
|
8646
|
-
return [
|
|
8647
|
-
["MemTotal", kb(total)],
|
|
8648
|
-
["MemFree", kb(free)],
|
|
8649
|
-
["MemAvailable", kb(free)],
|
|
8650
|
-
["Buffers", kb(0)],
|
|
8651
|
-
["Cached", kb(0)],
|
|
8652
|
-
["SwapCached", kb(0)],
|
|
8653
|
-
["Shmem", kb(0)],
|
|
8654
|
-
["SReclaimable", kb(0)],
|
|
8655
|
-
["SwapTotal", kb(0)],
|
|
8656
|
-
["SwapFree", kb(0)]
|
|
8657
|
-
].map(([key, value]) => `${`${key}:`.padEnd(16)}${value.padStart(12)}`).concat("").join("\n");
|
|
8658
|
-
}
|
|
8659
|
-
function systemFile(name2, listing, now, memory) {
|
|
8660
|
-
const up = Math.max(0, now - listing.boot) / 1e3;
|
|
8661
|
-
if (name2 === "uptime") return `${up.toFixed(2)} ${up.toFixed(2)}
|
|
8662
|
-
`;
|
|
8663
|
-
if (name2 === "meminfo") {
|
|
8664
|
-
return memoryInfo(
|
|
8665
|
-
memory,
|
|
8666
|
-
listing.processes.reduce((sum, p) => sum + p.memory, 0)
|
|
8667
|
-
);
|
|
8668
|
-
}
|
|
8669
|
-
const live = listing.processes.filter((p) => p.state !== "Z");
|
|
8670
|
-
if (name2 === "loadavg") {
|
|
8671
|
-
const last = Math.max(0, ...listing.processes.map((p) => p.pid));
|
|
8672
|
-
return `0.00 0.00 0.00 1/${live.length} ${last}
|
|
8673
|
-
`;
|
|
8674
|
-
}
|
|
8675
|
-
const idle = ticks(now - listing.boot);
|
|
8676
|
-
return [
|
|
8677
|
-
`cpu 0 0 0 ${idle} 0 0 0 0 0 0`,
|
|
8678
|
-
`cpu0 0 0 0 ${idle} 0 0 0 0 0 0`,
|
|
8679
|
-
"intr 0",
|
|
8680
|
-
"ctxt 0",
|
|
8681
|
-
`btime ${Math.floor(listing.boot / 1e3)}`,
|
|
8682
|
-
`processes ${listing.processes.length}`,
|
|
8683
|
-
"procs_running 1",
|
|
8684
|
-
"procs_blocked 0",
|
|
8685
|
-
""
|
|
8686
|
-
].join("\n");
|
|
8687
|
-
}
|
|
8688
|
-
function memorySource(scope = globalThis) {
|
|
8689
|
-
const nav = scope.navigator;
|
|
8690
|
-
const perf = scope.performance;
|
|
8691
|
-
const deviceMemory = nav?.deviceMemory;
|
|
8692
|
-
const used = perf?.memory?.usedJSHeapSize;
|
|
8693
|
-
return {
|
|
8694
|
-
...typeof deviceMemory === "number" && deviceMemory > 0 ? { deviceMemory } : {},
|
|
8695
|
-
...typeof used === "number" ? { usedHeap: used } : {}
|
|
8696
|
-
};
|
|
8697
|
-
}
|
|
8698
|
-
|
|
8699
8602
|
// src/fs/pages.ts
|
|
8700
8603
|
var PAGE = 64 * 1024;
|
|
8701
8604
|
var READAHEAD = 1024 * 1024;
|
|
@@ -8921,6 +8824,191 @@ var AsyncRangedFile = class {
|
|
|
8921
8824
|
}
|
|
8922
8825
|
};
|
|
8923
8826
|
|
|
8827
|
+
// src/realm/live-vfs-fs.ts
|
|
8828
|
+
var EARLY_WHOLE_FILE = 64 * 1024;
|
|
8829
|
+
|
|
8830
|
+
// src/process/process-fds.ts
|
|
8831
|
+
var field2 = (text) => (text || "none").replace(/[\s\\]/g, (c) => `\\${c.charCodeAt(0).toString(8).padStart(3, "0")}`);
|
|
8832
|
+
function mountTable(mounts = []) {
|
|
8833
|
+
const root = globalThis.navigator?.storage ? "opfs" : "memory";
|
|
8834
|
+
const lines2 = [`${root} / ${root} rw 0 0`, "devfs /dev devfs rw 0 0", "proc /proc proc rw 0 0"];
|
|
8835
|
+
for (const m of mounts) {
|
|
8836
|
+
const options = Object.entries(m.options).map(([k, v]) => v === "" ? k : `${k}=${v}`);
|
|
8837
|
+
if (m.state !== "ok") options.push(m.state);
|
|
8838
|
+
const access2 = options.includes("ro") ? [] : ["rw"];
|
|
8839
|
+
lines2.push(
|
|
8840
|
+
`${field2(m.source)} ${field2(m.target)} ${m.type} ${[...access2, ...options].join(",")} 0 0`
|
|
8841
|
+
);
|
|
8842
|
+
}
|
|
8843
|
+
return `${lines2.join("\n")}
|
|
8844
|
+
`;
|
|
8845
|
+
}
|
|
8846
|
+
|
|
8847
|
+
// src/process/procfs.ts
|
|
8848
|
+
var HZ = 100;
|
|
8849
|
+
var KIB = 1024;
|
|
8850
|
+
var FALLBACK_MEMORY = 4 * KIB * KIB * KIB;
|
|
8851
|
+
var PID_FILES = ["cmdline", "comm", "stat", "statm", "status"];
|
|
8852
|
+
var SYSTEM_FILES = ["loadavg", "meminfo", "stat", "uptime"];
|
|
8853
|
+
function commOf(info) {
|
|
8854
|
+
const name2 = info.argv[0] ?? "";
|
|
8855
|
+
return name2.slice(name2.lastIndexOf("/") + 1).slice(0, 15);
|
|
8856
|
+
}
|
|
8857
|
+
function ttyNumber(tty) {
|
|
8858
|
+
const pts = tty && /^\/dev\/pts\/(\d+)$/.exec(tty);
|
|
8859
|
+
if (pts) return 136 << 8 | Number(pts[1]);
|
|
8860
|
+
const vt = tty && /^\/dev\/tty(\d+)$/.exec(tty);
|
|
8861
|
+
return vt ? 4 << 8 | Number(vt[1]) : 0;
|
|
8862
|
+
}
|
|
8863
|
+
function pages(bytes) {
|
|
8864
|
+
return Math.ceil(bytes / 4096);
|
|
8865
|
+
}
|
|
8866
|
+
function ticks(ms) {
|
|
8867
|
+
return Math.max(0, Math.floor(ms * HZ / 1e3));
|
|
8868
|
+
}
|
|
8869
|
+
function pidStat(info, boot) {
|
|
8870
|
+
const fields = [
|
|
8871
|
+
info.pid,
|
|
8872
|
+
`(${commOf(info)})`,
|
|
8873
|
+
info.state,
|
|
8874
|
+
info.ppid,
|
|
8875
|
+
info.pgid,
|
|
8876
|
+
info.sid,
|
|
8877
|
+
ttyNumber(info.tty),
|
|
8878
|
+
info.tty ? info.pgid : -1,
|
|
8879
|
+
4194304,
|
|
8880
|
+
0,
|
|
8881
|
+
0,
|
|
8882
|
+
0,
|
|
8883
|
+
0,
|
|
8884
|
+
0,
|
|
8885
|
+
0,
|
|
8886
|
+
0,
|
|
8887
|
+
0,
|
|
8888
|
+
20,
|
|
8889
|
+
0,
|
|
8890
|
+
1,
|
|
8891
|
+
0,
|
|
8892
|
+
ticks(info.started - boot),
|
|
8893
|
+
info.memory,
|
|
8894
|
+
pages(info.memory),
|
|
8895
|
+
"18446744073709551615",
|
|
8896
|
+
...Array(12).fill(0),
|
|
8897
|
+
17,
|
|
8898
|
+
0,
|
|
8899
|
+
0,
|
|
8900
|
+
0,
|
|
8901
|
+
0,
|
|
8902
|
+
0,
|
|
8903
|
+
0,
|
|
8904
|
+
...Array(7).fill(0),
|
|
8905
|
+
0
|
|
8906
|
+
];
|
|
8907
|
+
return `${fields.join(" ")}
|
|
8908
|
+
`;
|
|
8909
|
+
}
|
|
8910
|
+
var sigMask = (mask = 0) => (mask >>> 1).toString(16).padStart(16, "0");
|
|
8911
|
+
function pidStatus(info) {
|
|
8912
|
+
const state = info.state === "Z" ? "Z (zombie)" : "S (sleeping)";
|
|
8913
|
+
const c = info.cred ?? ROOT;
|
|
8914
|
+
const ids = (r, e, s) => `${r} ${e} ${s} ${e}`;
|
|
8915
|
+
return [
|
|
8916
|
+
`Name: ${commOf(info)}`,
|
|
8917
|
+
`Umask: ${(info.umask ?? 18).toString(8).padStart(4, "0")}`,
|
|
8918
|
+
`State: ${state}`,
|
|
8919
|
+
`Tgid: ${info.pid}`,
|
|
8920
|
+
"Ngid: 0",
|
|
8921
|
+
`Pid: ${info.pid}`,
|
|
8922
|
+
`PPid: ${info.ppid}`,
|
|
8923
|
+
"TracerPid: 0",
|
|
8924
|
+
`Uid: ${ids(c.ruid, c.euid, c.suid)}`,
|
|
8925
|
+
`Gid: ${ids(c.rgid, c.egid, c.sgid)}`,
|
|
8926
|
+
"FDSize: 64",
|
|
8927
|
+
`VmSize: ${Math.ceil(info.memory / KIB)} kB`,
|
|
8928
|
+
`VmRSS: ${Math.ceil(info.memory / KIB)} kB`,
|
|
8929
|
+
`Groups: ${c.groups.join(" ")}`,
|
|
8930
|
+
`NSpid: ${info.pid}`,
|
|
8931
|
+
`NSpgid: ${info.pgid}`,
|
|
8932
|
+
`NSsid: ${info.sid}`,
|
|
8933
|
+
"Threads: 1",
|
|
8934
|
+
"SigQ: 0/0",
|
|
8935
|
+
"SigPnd: 0000000000000000",
|
|
8936
|
+
"ShdPnd: 0000000000000000",
|
|
8937
|
+
"SigBlk: 0000000000000000",
|
|
8938
|
+
`SigIgn: ${sigMask(info.sigIgn)}`,
|
|
8939
|
+
`SigCgt: ${sigMask(info.sigCgt)}`,
|
|
8940
|
+
""
|
|
8941
|
+
].join("\n");
|
|
8942
|
+
}
|
|
8943
|
+
function pidFile(name2, info, boot) {
|
|
8944
|
+
if (name2 === "cmdline") return info.state === "Z" ? "" : `${info.argv.join("\0")}\0`;
|
|
8945
|
+
if (name2 === "comm") return `${commOf(info)}
|
|
8946
|
+
`;
|
|
8947
|
+
if (name2 === "stat") return pidStat(info, boot);
|
|
8948
|
+
if (name2 === "statm") {
|
|
8949
|
+
const p = pages(info.memory);
|
|
8950
|
+
return `${p} ${p} 0 0 0 ${p} 0
|
|
8951
|
+
`;
|
|
8952
|
+
}
|
|
8953
|
+
return pidStatus(info);
|
|
8954
|
+
}
|
|
8955
|
+
function memoryInfo(source, used = 0) {
|
|
8956
|
+
const total = source.deviceMemory ? source.deviceMemory * KIB * KIB * KIB : FALLBACK_MEMORY;
|
|
8957
|
+
const free = Math.max(0, total - used - (source.usedHeap ?? 0));
|
|
8958
|
+
const kb = (bytes) => `${Math.floor(bytes / KIB)} kB`;
|
|
8959
|
+
return [
|
|
8960
|
+
["MemTotal", kb(total)],
|
|
8961
|
+
["MemFree", kb(free)],
|
|
8962
|
+
["MemAvailable", kb(free)],
|
|
8963
|
+
["Buffers", kb(0)],
|
|
8964
|
+
["Cached", kb(0)],
|
|
8965
|
+
["SwapCached", kb(0)],
|
|
8966
|
+
["Shmem", kb(0)],
|
|
8967
|
+
["SReclaimable", kb(0)],
|
|
8968
|
+
["SwapTotal", kb(0)],
|
|
8969
|
+
["SwapFree", kb(0)]
|
|
8970
|
+
].map(([key, value]) => `${`${key}:`.padEnd(16)}${value.padStart(12)}`).concat("").join("\n");
|
|
8971
|
+
}
|
|
8972
|
+
function systemFile(name2, listing, now, memory) {
|
|
8973
|
+
const up = Math.max(0, now - listing.boot) / 1e3;
|
|
8974
|
+
if (name2 === "uptime") return `${up.toFixed(2)} ${up.toFixed(2)}
|
|
8975
|
+
`;
|
|
8976
|
+
if (name2 === "meminfo") {
|
|
8977
|
+
return memoryInfo(
|
|
8978
|
+
memory,
|
|
8979
|
+
listing.processes.reduce((sum, p) => sum + p.memory, 0)
|
|
8980
|
+
);
|
|
8981
|
+
}
|
|
8982
|
+
const live = listing.processes.filter((p) => p.state !== "Z");
|
|
8983
|
+
if (name2 === "loadavg") {
|
|
8984
|
+
const last = Math.max(0, ...listing.processes.map((p) => p.pid));
|
|
8985
|
+
return `0.00 0.00 0.00 1/${live.length} ${last}
|
|
8986
|
+
`;
|
|
8987
|
+
}
|
|
8988
|
+
const idle = ticks(now - listing.boot);
|
|
8989
|
+
return [
|
|
8990
|
+
`cpu 0 0 0 ${idle} 0 0 0 0 0 0`,
|
|
8991
|
+
`cpu0 0 0 0 ${idle} 0 0 0 0 0 0`,
|
|
8992
|
+
"intr 0",
|
|
8993
|
+
"ctxt 0",
|
|
8994
|
+
`btime ${Math.floor(listing.boot / 1e3)}`,
|
|
8995
|
+
`processes ${listing.processes.length}`,
|
|
8996
|
+
"procs_running 1",
|
|
8997
|
+
"procs_blocked 0",
|
|
8998
|
+
""
|
|
8999
|
+
].join("\n");
|
|
9000
|
+
}
|
|
9001
|
+
function memorySource(scope = globalThis) {
|
|
9002
|
+
const nav = scope.navigator;
|
|
9003
|
+
const perf = scope.performance;
|
|
9004
|
+
const deviceMemory = nav?.deviceMemory;
|
|
9005
|
+
const used = perf?.memory?.usedJSHeapSize;
|
|
9006
|
+
return {
|
|
9007
|
+
...typeof deviceMemory === "number" && deviceMemory > 0 ? { deviceMemory } : {},
|
|
9008
|
+
...typeof used === "number" ? { usedHeap: used } : {}
|
|
9009
|
+
};
|
|
9010
|
+
}
|
|
9011
|
+
|
|
8924
9012
|
// src/process/wasi/wasi-files.ts
|
|
8925
9013
|
function normalize(path) {
|
|
8926
9014
|
const out = [];
|
|
@@ -11199,6 +11287,7 @@ var WasmProcess = class {
|
|
|
11199
11287
|
throw Object.assign(new Error(alias.refused), { code: alias.refused });
|
|
11200
11288
|
if (alias !== void 0) return this.openProc(req, alias);
|
|
11201
11289
|
await refuseReadonly(this.options.fs, req.path, req.flags, req);
|
|
11290
|
+
await this.mayOpen(req);
|
|
11202
11291
|
const fd = this.fds.install(heldFile(), 3);
|
|
11203
11292
|
try {
|
|
11204
11293
|
const nodes = this.nodes;
|
|
@@ -11244,6 +11333,17 @@ var WasmProcess = class {
|
|
|
11244
11333
|
};
|
|
11245
11334
|
return fs.exclusive ? fs.exclusive(first.path, look) : look();
|
|
11246
11335
|
}
|
|
11336
|
+
async mayOpen(req) {
|
|
11337
|
+
const { guard: guard2 } = this.options;
|
|
11338
|
+
const inherited2 = req.orphan || req.contents !== void 0 || req.handle !== void 0;
|
|
11339
|
+
if (!guard2 || inherited2 || req.pin !== void 0) return;
|
|
11340
|
+
const g = { fs: guard2.fs, dac: guard2.dac, cred: this.cred, pid: this.pid };
|
|
11341
|
+
if (req.exclusive) return inParent(g, "open", req.path);
|
|
11342
|
+
if (req.created && guard2.created?.take(req.path)) return;
|
|
11343
|
+
const access2 = req.flags & WRITE_ACCESS;
|
|
11344
|
+
const want = (access2 === 1 ? 0 : R_OK) | (access2 !== 0 || req.truncate ? W_OK : 0);
|
|
11345
|
+
await openable(g, "open", req.path, want, req.create === true);
|
|
11346
|
+
}
|
|
11247
11347
|
newOwner() {
|
|
11248
11348
|
if (!this.options.owners) return void 0;
|
|
11249
11349
|
return { uid: this.cred.euid, gid: this.cred.egid, mode: 438 & ~this.umask };
|
|
@@ -11928,7 +12028,7 @@ function inherited(opts) {
|
|
|
11928
12028
|
function holdingToken(opts, holds, caller) {
|
|
11929
12029
|
return mintSyncFsToken({
|
|
11930
12030
|
...opts.owners ? caller : {},
|
|
11931
|
-
...opts.dac ? { dac: opts.dac, pid: opts.pid } : {},
|
|
12031
|
+
...opts.dac ? { dac: opts.dac, pid: opts.pid, created: caller.created } : {},
|
|
11932
12032
|
fs: opts.fs,
|
|
11933
12033
|
cwd: opts.cwd,
|
|
11934
12034
|
...opts.statfs ? { statfs: opts.statfs } : {},
|
|
@@ -11941,10 +12041,11 @@ function holdingToken(opts, holds, caller) {
|
|
|
11941
12041
|
renamed: (from, to) => holds.renamed(from, to)
|
|
11942
12042
|
});
|
|
11943
12043
|
}
|
|
11944
|
-
function processOptions(opts, header3, hooks) {
|
|
12044
|
+
function processOptions(opts, header3, hooks, created3) {
|
|
11945
12045
|
return {
|
|
11946
12046
|
...inherited(opts),
|
|
11947
12047
|
...opts.owners ? { owners: true } : {},
|
|
12048
|
+
...opts.dac ? { guard: { dac: opts.dac, fs: opts.fs, created: created3 } } : {},
|
|
11948
12049
|
...opts.identity ? { identity: opts.identity } : {},
|
|
11949
12050
|
...opts.onSyscall ? { onSyscall: opts.onSyscall } : {},
|
|
11950
12051
|
...opts.settling ? { settling: opts.settling } : {},
|
|
@@ -11978,20 +12079,27 @@ function spawnWasmProcess(opts) {
|
|
|
11978
12079
|
const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
11979
12080
|
const header3 = new Int32Array(sab, 0, SAB_HEADER_I32);
|
|
11980
12081
|
const threadSignals = /* @__PURE__ */ new Map();
|
|
12082
|
+
const created3 = new Created();
|
|
11981
12083
|
const process = new WasmProcess(
|
|
11982
12084
|
opts.pid,
|
|
11983
12085
|
opts.fds,
|
|
11984
|
-
processOptions(
|
|
11985
|
-
|
|
11986
|
-
|
|
11987
|
-
|
|
12086
|
+
processOptions(
|
|
12087
|
+
opts,
|
|
12088
|
+
header3,
|
|
12089
|
+
{
|
|
12090
|
+
raise: (sig) => signal(sig),
|
|
12091
|
+
threadKill: (tid, sig) => killThread(threadSignals.get(tid), process.signalMasks().caught, sig)
|
|
12092
|
+
},
|
|
12093
|
+
created3
|
|
12094
|
+
)
|
|
11988
12095
|
);
|
|
11989
12096
|
publishStops(process, header3);
|
|
11990
12097
|
const holds = new HeldPaths();
|
|
11991
12098
|
opts.held?.add(holds);
|
|
11992
12099
|
const token = holdingToken(opts, holds, {
|
|
11993
12100
|
cred: () => process.cred,
|
|
11994
|
-
umask: () => process.umask
|
|
12101
|
+
umask: () => process.umask,
|
|
12102
|
+
created: created3
|
|
11995
12103
|
});
|
|
11996
12104
|
process.keptPath = (path) => holds.keptAt(path)?.hidden;
|
|
11997
12105
|
process.keptHandle = (handle2) => holds.keptFor(handle2)?.hidden;
|
|
@@ -13104,16 +13212,16 @@ function hostfsHandlers(current, againMs = RESTORE_AGAIN_MS) {
|
|
|
13104
13212
|
});
|
|
13105
13213
|
async function writable2(client, path, flags) {
|
|
13106
13214
|
const { ifMatch: _, ...asked } = flags;
|
|
13107
|
-
const
|
|
13215
|
+
const opening2 = () => client.call("open", { path: rel(path), ...asked });
|
|
13108
13216
|
try {
|
|
13109
|
-
return { opened: await
|
|
13217
|
+
return { opened: await opening2(), restore: void 0 };
|
|
13110
13218
|
} catch (err) {
|
|
13111
13219
|
if (!flags.write || codeOf4(err) !== "EACCES") throw err;
|
|
13112
13220
|
const was = await client.call("stat", { path: rel(path) });
|
|
13113
13221
|
const mode = was.mode ?? 0;
|
|
13114
13222
|
if (mode & 128) throw err;
|
|
13115
13223
|
const restore = { path: rel(path), mode, was };
|
|
13116
|
-
const opened2 = await client.call("setattr", { path: rel(path), mode: mode | 128 }).then(
|
|
13224
|
+
const opened2 = await client.call("setattr", { path: rel(path), mode: mode | 128 }).then(opening2).catch(async (again) => {
|
|
13117
13225
|
await settle3(client, restore).catch(() => {
|
|
13118
13226
|
});
|
|
13119
13227
|
throw again;
|
|
@@ -14371,15 +14479,33 @@ var Launcher = class {
|
|
|
14371
14479
|
return void 0;
|
|
14372
14480
|
}
|
|
14373
14481
|
const inner = await this.interpreted(interp, [interp, ...passed], cwd, scope, depth + 1);
|
|
14374
|
-
|
|
14482
|
+
const via = [interp, ...inner?.via ?? []];
|
|
14483
|
+
return inner && { ...inner, target: withScriptEnv(inner.target, command), via };
|
|
14375
14484
|
}
|
|
14376
14485
|
const target = withScriptEnv(found, command);
|
|
14377
|
-
return { target, args: [...target.prefix ?? [], ...passed] };
|
|
14486
|
+
return { target, args: [...target.prefix ?? [], ...passed], via: [interp] };
|
|
14378
14487
|
}
|
|
14379
14488
|
async plan(file, argv, cwd, scope) {
|
|
14380
14489
|
const direct = await this.resolve(file, argv[0] ?? file, cwd, scope);
|
|
14381
14490
|
if (direct) return { target: direct, args: [...direct.prefix ?? [], ...argv.slice(1)] };
|
|
14382
|
-
|
|
14491
|
+
const script = await this.interpreted(file, argv, cwd, scope);
|
|
14492
|
+
return script && { ...script, script: true };
|
|
14493
|
+
}
|
|
14494
|
+
async mayExec(cred, req, planned) {
|
|
14495
|
+
const { dac } = this;
|
|
14496
|
+
if (!dac) return;
|
|
14497
|
+
const g = { fs: this.fs, cred, pid: req.pid, dac };
|
|
14498
|
+
const byPath = (file) => file.includes("/") && !COMMAND2.test(file);
|
|
14499
|
+
if (byPath(req.file)) {
|
|
14500
|
+
const path = this.fs.resolvePath(req.cwd, req.file);
|
|
14501
|
+
await need(g, "exec", path, planned?.script ? R_OK | X_OK : X_OK);
|
|
14502
|
+
}
|
|
14503
|
+
const via = planned?.via ?? [];
|
|
14504
|
+
for (const [i, file] of via.entries()) {
|
|
14505
|
+
if (!byPath(file)) continue;
|
|
14506
|
+
const want = i < via.length - 1 ? R_OK | X_OK : X_OK;
|
|
14507
|
+
await need(g, "exec", this.fs.resolvePath(req.cwd, file), want);
|
|
14508
|
+
}
|
|
14383
14509
|
}
|
|
14384
14510
|
async unrunnable(file, cwd, scope) {
|
|
14385
14511
|
const path = this.fs.resolvePath(cwd, file);
|
|
@@ -14599,6 +14725,12 @@ var Launcher = class {
|
|
|
14599
14725
|
return async (req, fds) => {
|
|
14600
14726
|
const scope = await this.scopeOf(this.credOf(ppid).euid);
|
|
14601
14727
|
const planned = await this.plan(req.file, req.argv, req.cwd, scope);
|
|
14728
|
+
try {
|
|
14729
|
+
await this.mayExec(this.credOf(ppid), { ...req, pid: ppid }, planned);
|
|
14730
|
+
} catch (err) {
|
|
14731
|
+
await fds.closeAll();
|
|
14732
|
+
throw err.code === "EACCES" ? new SpawnError("EACCES") : err;
|
|
14733
|
+
}
|
|
14602
14734
|
if (!planned) {
|
|
14603
14735
|
await fds.closeAll();
|
|
14604
14736
|
throw new SpawnError(await this.unrunnable(req.file, req.cwd, scope));
|
|
@@ -14882,6 +15014,7 @@ var Launcher = class {
|
|
|
14882
15014
|
}
|
|
14883
15015
|
async prepare() {
|
|
14884
15016
|
for (const dir of SHARED_DIRS) await this.base.mkdir(dir, { recursive: true });
|
|
15017
|
+
if (this.owners) await this.base.chmod("/tmp", 1023);
|
|
14885
15018
|
await this.provisionPnpmHome();
|
|
14886
15019
|
await this.users.ensure();
|
|
14887
15020
|
await writeCaFile(this.base, this.ca).catch(() => void 0);
|
|
@@ -14929,7 +15062,9 @@ var Launcher = class {
|
|
|
14929
15062
|
const cwd = await physicalPathAsync(this.base, start2.startsWith("/") ? start2 : `/${start2}`);
|
|
14930
15063
|
const [file = ""] = argv;
|
|
14931
15064
|
await this.base.mkdir(cwd, { recursive: true });
|
|
14932
|
-
|
|
15065
|
+
const planned = await this.plan(file, argv, cwd, scope);
|
|
15066
|
+
await this.mayExec(credOf(account), { file, cwd, pid: 0 }, planned);
|
|
15067
|
+
return { cwd, file, planned };
|
|
14933
15068
|
}
|
|
14934
15069
|
async openTerminal(argv, options) {
|
|
14935
15070
|
const account = await this.account(options.user);
|