@ai-ecoverse/slicc-kernel 1.62.4 → 1.64.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 +409 -233
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +290 -128
- package/dist/node-process-worker.js.map +4 -4
- package/dist/node.js +409 -233
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +290 -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
|
|
@@ -2981,13 +3030,21 @@ var OpfsFs = class {
|
|
|
2981
3030
|
trackOwners() {
|
|
2982
3031
|
this.owners = true;
|
|
2983
3032
|
}
|
|
3033
|
+
async hasOwner(path) {
|
|
3034
|
+
return ownOf((await this.meta.get([path]))[0]) !== void 0;
|
|
3035
|
+
}
|
|
2984
3036
|
async ancestry(path) {
|
|
2985
3037
|
const entries = await this.meta.get(chain(path));
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
3038
|
+
const out = [];
|
|
3039
|
+
for (const [i, entry] of entries.entries()) {
|
|
3040
|
+
const link2 = entry?.link !== void 0 && !await this.real(entry.path);
|
|
3041
|
+
out.push({
|
|
3042
|
+
...ownOf(entry) ?? (i === 0 ? ROOT_OWNER : inherit(entries.slice(0, i))),
|
|
3043
|
+
...entry?.mode !== void 0 ? { mode: entry.mode } : {},
|
|
3044
|
+
...link2 ? { link: entry.link } : {}
|
|
3045
|
+
});
|
|
3046
|
+
}
|
|
3047
|
+
return out;
|
|
2991
3048
|
}
|
|
2992
3049
|
async handedTo(dir) {
|
|
2993
3050
|
return inherit(await this.meta.get(chain(dir)));
|
|
@@ -3747,8 +3804,10 @@ var UnlinkedKeeper = class {
|
|
|
3747
3804
|
count = 0;
|
|
3748
3805
|
links = /* @__PURE__ */ new Map();
|
|
3749
3806
|
linked = /* @__PURE__ */ new Map();
|
|
3807
|
+
dirOwner;
|
|
3750
3808
|
constructor(fs, holders, rootOf, options = {}) {
|
|
3751
3809
|
const { locks, owner } = options;
|
|
3810
|
+
this.dirOwner = options.dirOwner;
|
|
3752
3811
|
this.fs = fs;
|
|
3753
3812
|
this.holders = holders;
|
|
3754
3813
|
this.rootOf = rootOf;
|
|
@@ -3859,7 +3918,8 @@ var UnlinkedKeeper = class {
|
|
|
3859
3918
|
const dir = dirOf(this.rootOf(path));
|
|
3860
3919
|
const hidden = `${dir}/${this.instance}.${++this.count}`;
|
|
3861
3920
|
try {
|
|
3862
|
-
|
|
3921
|
+
const owner = this.dirOwner;
|
|
3922
|
+
await this.fs.mkdir(dir, { recursive: true, ...owner ? { owner } : {} });
|
|
3863
3923
|
await this.fs.rename(path, hidden);
|
|
3864
3924
|
await this.linkedName(hidden);
|
|
3865
3925
|
return hidden;
|
|
@@ -5017,6 +5077,7 @@ function withCommandDirs(fs, names, userDir = async () => void 0, owners = false
|
|
|
5017
5077
|
...fs.realpath ? { realpath: fs.realpath.bind(fs) } : {},
|
|
5018
5078
|
...fs.chown ? { chown: fs.chown.bind(fs) } : {},
|
|
5019
5079
|
...fs.ancestry ? { ancestry: fs.ancestry.bind(fs) } : {},
|
|
5080
|
+
...fs.hasOwner ? { hasOwner: fs.hasOwner.bind(fs) } : {},
|
|
5020
5081
|
chmod: (path, mode) => fs.chmod(path, mode),
|
|
5021
5082
|
utimes: (path, atime, mtime) => fs.utimes(path, atime, mtime),
|
|
5022
5083
|
lutimes: (path, atime, mtime) => lutimesOf(fs, path, atime, mtime),
|
|
@@ -6388,6 +6449,10 @@ var MountFs = class {
|
|
|
6388
6449
|
if (this.at(real)) throw errnoError("ENOSYS", path);
|
|
6389
6450
|
return real;
|
|
6390
6451
|
}
|
|
6452
|
+
async hasOwner(path) {
|
|
6453
|
+
if (this.at(path)) return true;
|
|
6454
|
+
return await this.base.hasOwner?.(path) ?? true;
|
|
6455
|
+
}
|
|
6391
6456
|
async ancestry(path) {
|
|
6392
6457
|
const names = chain(normalizePath(path));
|
|
6393
6458
|
const first = names.findIndex((name2) => this.at(name2));
|
|
@@ -6477,6 +6542,9 @@ function revokeSyncFsToken(token) {
|
|
|
6477
6542
|
}
|
|
6478
6543
|
|
|
6479
6544
|
// src/realm/sync-fs-wire.ts
|
|
6545
|
+
var HOLD_READ = 4;
|
|
6546
|
+
var HOLD_WRITE = 8;
|
|
6547
|
+
var HOLD_CREATED = 16;
|
|
6480
6548
|
var SYNC_FS_REQUEST_TIMEOUT_MS = 25e3;
|
|
6481
6549
|
function syncError(code, label) {
|
|
6482
6550
|
return Object.assign(new Error(`${code}: ${label}`), { code });
|
|
@@ -6600,6 +6668,7 @@ async function run(entry, path, req) {
|
|
|
6600
6668
|
return done;
|
|
6601
6669
|
case "create":
|
|
6602
6670
|
await createExclusive(fs, path, ownerFor2(entry, req.mode ?? 438));
|
|
6671
|
+
entry.created?.add(path);
|
|
6603
6672
|
return done;
|
|
6604
6673
|
case "readlink":
|
|
6605
6674
|
return json2(await fs.readlink(path));
|
|
@@ -6656,11 +6725,47 @@ async function guard(g, path, req, cwd) {
|
|
|
6656
6725
|
return linkable(g, path, other(), req.mode === 1);
|
|
6657
6726
|
case "utimes":
|
|
6658
6727
|
case "lutimes":
|
|
6659
|
-
return retimable(g, op, path);
|
|
6728
|
+
return retimable(g, op, path, req.now === true);
|
|
6729
|
+
case "read":
|
|
6730
|
+
case "pread":
|
|
6731
|
+
return req.handle === void 0 ? readable(g, op, path) : void 0;
|
|
6732
|
+
case "pwrite":
|
|
6733
|
+
case "truncate":
|
|
6734
|
+
return req.handle === void 0 ? fileWritable(g, op, path) : void 0;
|
|
6735
|
+
case "write":
|
|
6736
|
+
return req.handle === void 0 && req.mode !== 1 ? writable(g, op, path) : void 0;
|
|
6660
6737
|
default:
|
|
6661
6738
|
return void 0;
|
|
6662
6739
|
}
|
|
6663
6740
|
}
|
|
6741
|
+
async function opening(entry, path, mode) {
|
|
6742
|
+
const g = guardOf(entry);
|
|
6743
|
+
const want = (mode & HOLD_READ ? R_OK : 0) | (mode & HOLD_WRITE ? W_OK : 0);
|
|
6744
|
+
const created3 = (mode & HOLD_CREATED) !== 0 && entry.created?.take(path) === true;
|
|
6745
|
+
if (g && want !== 0 && !created3) {
|
|
6746
|
+
await need(g, "open", path, want, { directory: false });
|
|
6747
|
+
}
|
|
6748
|
+
}
|
|
6749
|
+
async function holdOp(entry, path, req) {
|
|
6750
|
+
const mode = req.mode ?? 0;
|
|
6751
|
+
const [on, open] = [(mode & 1) === 1, (mode & 2) === 2];
|
|
6752
|
+
if (on && open) {
|
|
6753
|
+
await opening(entry, path, mode);
|
|
6754
|
+
const real = await entry.fs.realpath?.(path, true).catch(() => path);
|
|
6755
|
+
return json2(entry.hold?.(path, on, open, real) ?? null);
|
|
6756
|
+
}
|
|
6757
|
+
entry.hold?.(path, on, open, void 0, req.handle);
|
|
6758
|
+
return done;
|
|
6759
|
+
}
|
|
6760
|
+
async function accessOp(entry, path, req) {
|
|
6761
|
+
const g = guardOf(entry);
|
|
6762
|
+
if (!g) return done;
|
|
6763
|
+
const open = req.arg2 === "open";
|
|
6764
|
+
const cred = open || req.arg2 === "eaccess" ? g.cred : realIds(g.cred);
|
|
6765
|
+
const options = { follow: req.nofollow !== true, ...open ? { directory: false } : {} };
|
|
6766
|
+
await need({ ...g, cred }, open ? "open" : "access", path, req.mode ?? 0, options);
|
|
6767
|
+
return done;
|
|
6768
|
+
}
|
|
6664
6769
|
async function guarded(entry, path, req) {
|
|
6665
6770
|
const g = guardOf(entry);
|
|
6666
6771
|
if (!g) return void 0;
|
|
@@ -6724,16 +6829,6 @@ async function owned(entry, own, req, path, target) {
|
|
|
6724
6829
|
}
|
|
6725
6830
|
return own(target, () => run(entry, path, req));
|
|
6726
6831
|
}
|
|
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
6832
|
var IDENTITY_OPS = /* @__PURE__ */ new Set([
|
|
6738
6833
|
"write",
|
|
6739
6834
|
"pwrite",
|
|
@@ -6770,7 +6865,8 @@ async function dispatchOne(entry, req) {
|
|
|
6770
6865
|
const path = fs.resolvePath(cwd, req.path);
|
|
6771
6866
|
if (req.op === "kept") return json2(entry.keptFor?.(req.handle ?? -1) !== void 0);
|
|
6772
6867
|
if (req.op === "stat" && req.handle !== void 0) return await keptStat(entry, req);
|
|
6773
|
-
if (req.op === "
|
|
6868
|
+
if (req.op === "access") return await accessOp(entry, path, req);
|
|
6869
|
+
if (req.op === "hold") return await holdOp(entry, path, req);
|
|
6774
6870
|
const refused2 = await guarded(entry, path, req);
|
|
6775
6871
|
if (refused2) return refused2;
|
|
6776
6872
|
if (req.op === "statfs") return json2(await entry.statfs?.(path) ?? await storageUsage());
|
|
@@ -6966,188 +7062,6 @@ function ownNames(hostname) {
|
|
|
6966
7062
|
return [.../* @__PURE__ */ new Set([hostname.toLowerCase(), ...LIBC_HOSTNAMES])];
|
|
6967
7063
|
}
|
|
6968
7064
|
|
|
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
7065
|
// src/fs/pages.ts
|
|
7152
7066
|
var PAGE = 64 * 1024;
|
|
7153
7067
|
var READAHEAD = 1024 * 1024;
|
|
@@ -7373,6 +7287,191 @@ var AsyncRangedFile = class {
|
|
|
7373
7287
|
}
|
|
7374
7288
|
};
|
|
7375
7289
|
|
|
7290
|
+
// src/realm/live-vfs-fs.ts
|
|
7291
|
+
var EARLY_WHOLE_FILE = 64 * 1024;
|
|
7292
|
+
|
|
7293
|
+
// src/process/process-fds.ts
|
|
7294
|
+
var field2 = (text) => (text || "none").replace(/[\s\\]/g, (c) => `\\${c.charCodeAt(0).toString(8).padStart(3, "0")}`);
|
|
7295
|
+
function mountTable(mounts = []) {
|
|
7296
|
+
const root = globalThis.navigator?.storage ? "opfs" : "memory";
|
|
7297
|
+
const lines2 = [`${root} / ${root} rw 0 0`, "devfs /dev devfs rw 0 0", "proc /proc proc rw 0 0"];
|
|
7298
|
+
for (const m of mounts) {
|
|
7299
|
+
const options = Object.entries(m.options).map(([k, v]) => v === "" ? k : `${k}=${v}`);
|
|
7300
|
+
if (m.state !== "ok") options.push(m.state);
|
|
7301
|
+
const access2 = options.includes("ro") ? [] : ["rw"];
|
|
7302
|
+
lines2.push(
|
|
7303
|
+
`${field2(m.source)} ${field2(m.target)} ${m.type} ${[...access2, ...options].join(",")} 0 0`
|
|
7304
|
+
);
|
|
7305
|
+
}
|
|
7306
|
+
return `${lines2.join("\n")}
|
|
7307
|
+
`;
|
|
7308
|
+
}
|
|
7309
|
+
|
|
7310
|
+
// src/process/procfs.ts
|
|
7311
|
+
var HZ = 100;
|
|
7312
|
+
var KIB = 1024;
|
|
7313
|
+
var FALLBACK_MEMORY = 4 * KIB * KIB * KIB;
|
|
7314
|
+
var PID_FILES = ["cmdline", "comm", "stat", "statm", "status"];
|
|
7315
|
+
var SYSTEM_FILES = ["loadavg", "meminfo", "stat", "uptime"];
|
|
7316
|
+
function commOf(info) {
|
|
7317
|
+
const name2 = info.argv[0] ?? "";
|
|
7318
|
+
return name2.slice(name2.lastIndexOf("/") + 1).slice(0, 15);
|
|
7319
|
+
}
|
|
7320
|
+
function ttyNumber(tty) {
|
|
7321
|
+
const pts = tty && /^\/dev\/pts\/(\d+)$/.exec(tty);
|
|
7322
|
+
if (pts) return 136 << 8 | Number(pts[1]);
|
|
7323
|
+
const vt = tty && /^\/dev\/tty(\d+)$/.exec(tty);
|
|
7324
|
+
return vt ? 4 << 8 | Number(vt[1]) : 0;
|
|
7325
|
+
}
|
|
7326
|
+
function pages(bytes) {
|
|
7327
|
+
return Math.ceil(bytes / 4096);
|
|
7328
|
+
}
|
|
7329
|
+
function ticks(ms) {
|
|
7330
|
+
return Math.max(0, Math.floor(ms * HZ / 1e3));
|
|
7331
|
+
}
|
|
7332
|
+
function pidStat(info, boot) {
|
|
7333
|
+
const fields = [
|
|
7334
|
+
info.pid,
|
|
7335
|
+
`(${commOf(info)})`,
|
|
7336
|
+
info.state,
|
|
7337
|
+
info.ppid,
|
|
7338
|
+
info.pgid,
|
|
7339
|
+
info.sid,
|
|
7340
|
+
ttyNumber(info.tty),
|
|
7341
|
+
info.tty ? info.pgid : -1,
|
|
7342
|
+
4194304,
|
|
7343
|
+
0,
|
|
7344
|
+
0,
|
|
7345
|
+
0,
|
|
7346
|
+
0,
|
|
7347
|
+
0,
|
|
7348
|
+
0,
|
|
7349
|
+
0,
|
|
7350
|
+
0,
|
|
7351
|
+
20,
|
|
7352
|
+
0,
|
|
7353
|
+
1,
|
|
7354
|
+
0,
|
|
7355
|
+
ticks(info.started - boot),
|
|
7356
|
+
info.memory,
|
|
7357
|
+
pages(info.memory),
|
|
7358
|
+
"18446744073709551615",
|
|
7359
|
+
...Array(12).fill(0),
|
|
7360
|
+
17,
|
|
7361
|
+
0,
|
|
7362
|
+
0,
|
|
7363
|
+
0,
|
|
7364
|
+
0,
|
|
7365
|
+
0,
|
|
7366
|
+
0,
|
|
7367
|
+
...Array(7).fill(0),
|
|
7368
|
+
0
|
|
7369
|
+
];
|
|
7370
|
+
return `${fields.join(" ")}
|
|
7371
|
+
`;
|
|
7372
|
+
}
|
|
7373
|
+
var sigMask = (mask = 0) => (mask >>> 1).toString(16).padStart(16, "0");
|
|
7374
|
+
function pidStatus(info) {
|
|
7375
|
+
const state = info.state === "Z" ? "Z (zombie)" : "S (sleeping)";
|
|
7376
|
+
const c = info.cred ?? ROOT;
|
|
7377
|
+
const ids = (r, e, s) => `${r} ${e} ${s} ${e}`;
|
|
7378
|
+
return [
|
|
7379
|
+
`Name: ${commOf(info)}`,
|
|
7380
|
+
`Umask: ${(info.umask ?? 18).toString(8).padStart(4, "0")}`,
|
|
7381
|
+
`State: ${state}`,
|
|
7382
|
+
`Tgid: ${info.pid}`,
|
|
7383
|
+
"Ngid: 0",
|
|
7384
|
+
`Pid: ${info.pid}`,
|
|
7385
|
+
`PPid: ${info.ppid}`,
|
|
7386
|
+
"TracerPid: 0",
|
|
7387
|
+
`Uid: ${ids(c.ruid, c.euid, c.suid)}`,
|
|
7388
|
+
`Gid: ${ids(c.rgid, c.egid, c.sgid)}`,
|
|
7389
|
+
"FDSize: 64",
|
|
7390
|
+
`VmSize: ${Math.ceil(info.memory / KIB)} kB`,
|
|
7391
|
+
`VmRSS: ${Math.ceil(info.memory / KIB)} kB`,
|
|
7392
|
+
`Groups: ${c.groups.join(" ")}`,
|
|
7393
|
+
`NSpid: ${info.pid}`,
|
|
7394
|
+
`NSpgid: ${info.pgid}`,
|
|
7395
|
+
`NSsid: ${info.sid}`,
|
|
7396
|
+
"Threads: 1",
|
|
7397
|
+
"SigQ: 0/0",
|
|
7398
|
+
"SigPnd: 0000000000000000",
|
|
7399
|
+
"ShdPnd: 0000000000000000",
|
|
7400
|
+
"SigBlk: 0000000000000000",
|
|
7401
|
+
`SigIgn: ${sigMask(info.sigIgn)}`,
|
|
7402
|
+
`SigCgt: ${sigMask(info.sigCgt)}`,
|
|
7403
|
+
""
|
|
7404
|
+
].join("\n");
|
|
7405
|
+
}
|
|
7406
|
+
function pidFile(name2, info, boot) {
|
|
7407
|
+
if (name2 === "cmdline") return info.state === "Z" ? "" : `${info.argv.join("\0")}\0`;
|
|
7408
|
+
if (name2 === "comm") return `${commOf(info)}
|
|
7409
|
+
`;
|
|
7410
|
+
if (name2 === "stat") return pidStat(info, boot);
|
|
7411
|
+
if (name2 === "statm") {
|
|
7412
|
+
const p = pages(info.memory);
|
|
7413
|
+
return `${p} ${p} 0 0 0 ${p} 0
|
|
7414
|
+
`;
|
|
7415
|
+
}
|
|
7416
|
+
return pidStatus(info);
|
|
7417
|
+
}
|
|
7418
|
+
function memoryInfo(source, used = 0) {
|
|
7419
|
+
const total = source.deviceMemory ? source.deviceMemory * KIB * KIB * KIB : FALLBACK_MEMORY;
|
|
7420
|
+
const free = Math.max(0, total - used - (source.usedHeap ?? 0));
|
|
7421
|
+
const kb = (bytes) => `${Math.floor(bytes / KIB)} kB`;
|
|
7422
|
+
return [
|
|
7423
|
+
["MemTotal", kb(total)],
|
|
7424
|
+
["MemFree", kb(free)],
|
|
7425
|
+
["MemAvailable", kb(free)],
|
|
7426
|
+
["Buffers", kb(0)],
|
|
7427
|
+
["Cached", kb(0)],
|
|
7428
|
+
["SwapCached", kb(0)],
|
|
7429
|
+
["Shmem", kb(0)],
|
|
7430
|
+
["SReclaimable", kb(0)],
|
|
7431
|
+
["SwapTotal", kb(0)],
|
|
7432
|
+
["SwapFree", kb(0)]
|
|
7433
|
+
].map(([key, value]) => `${`${key}:`.padEnd(16)}${value.padStart(12)}`).concat("").join("\n");
|
|
7434
|
+
}
|
|
7435
|
+
function systemFile(name2, listing, now, memory) {
|
|
7436
|
+
const up = Math.max(0, now - listing.boot) / 1e3;
|
|
7437
|
+
if (name2 === "uptime") return `${up.toFixed(2)} ${up.toFixed(2)}
|
|
7438
|
+
`;
|
|
7439
|
+
if (name2 === "meminfo") {
|
|
7440
|
+
return memoryInfo(
|
|
7441
|
+
memory,
|
|
7442
|
+
listing.processes.reduce((sum, p) => sum + p.memory, 0)
|
|
7443
|
+
);
|
|
7444
|
+
}
|
|
7445
|
+
const live = listing.processes.filter((p) => p.state !== "Z");
|
|
7446
|
+
if (name2 === "loadavg") {
|
|
7447
|
+
const last = Math.max(0, ...listing.processes.map((p) => p.pid));
|
|
7448
|
+
return `0.00 0.00 0.00 1/${live.length} ${last}
|
|
7449
|
+
`;
|
|
7450
|
+
}
|
|
7451
|
+
const idle = ticks(now - listing.boot);
|
|
7452
|
+
return [
|
|
7453
|
+
`cpu 0 0 0 ${idle} 0 0 0 0 0 0`,
|
|
7454
|
+
`cpu0 0 0 0 ${idle} 0 0 0 0 0 0`,
|
|
7455
|
+
"intr 0",
|
|
7456
|
+
"ctxt 0",
|
|
7457
|
+
`btime ${Math.floor(listing.boot / 1e3)}`,
|
|
7458
|
+
`processes ${listing.processes.length}`,
|
|
7459
|
+
"procs_running 1",
|
|
7460
|
+
"procs_blocked 0",
|
|
7461
|
+
""
|
|
7462
|
+
].join("\n");
|
|
7463
|
+
}
|
|
7464
|
+
function memorySource(scope = globalThis) {
|
|
7465
|
+
const nav = scope.navigator;
|
|
7466
|
+
const perf = scope.performance;
|
|
7467
|
+
const deviceMemory = nav?.deviceMemory;
|
|
7468
|
+
const used = perf?.memory?.usedJSHeapSize;
|
|
7469
|
+
return {
|
|
7470
|
+
...typeof deviceMemory === "number" && deviceMemory > 0 ? { deviceMemory } : {},
|
|
7471
|
+
...typeof used === "number" ? { usedHeap: used } : {}
|
|
7472
|
+
};
|
|
7473
|
+
}
|
|
7474
|
+
|
|
7376
7475
|
// src/process/wasi/wasi-files.ts
|
|
7377
7476
|
function normalize(path) {
|
|
7378
7477
|
const out = [];
|
|
@@ -8561,11 +8660,11 @@ function realmCa(owner, store) {
|
|
|
8561
8660
|
opened.set(store, cas);
|
|
8562
8661
|
let ca = cas.get(owner);
|
|
8563
8662
|
if (!ca) {
|
|
8564
|
-
const
|
|
8565
|
-
ca =
|
|
8566
|
-
cas.set(owner,
|
|
8567
|
-
|
|
8568
|
-
if (cas.get(owner) ===
|
|
8663
|
+
const opening2 = RealmCa.open(owner, store);
|
|
8664
|
+
ca = opening2;
|
|
8665
|
+
cas.set(owner, opening2);
|
|
8666
|
+
opening2.catch(() => {
|
|
8667
|
+
if (cas.get(owner) === opening2) cas.delete(owner);
|
|
8569
8668
|
});
|
|
8570
8669
|
}
|
|
8571
8670
|
return ca;
|
|
@@ -10972,6 +11071,7 @@ var WasmProcess = class {
|
|
|
10972
11071
|
throw Object.assign(new Error(alias.refused), { code: alias.refused });
|
|
10973
11072
|
if (alias !== void 0) return this.openProc(req, alias);
|
|
10974
11073
|
await refuseReadonly(this.options.fs, req.path, req.flags, req);
|
|
11074
|
+
await this.mayOpen(req);
|
|
10975
11075
|
const fd = this.fds.install(heldFile(), 3);
|
|
10976
11076
|
try {
|
|
10977
11077
|
const nodes = this.nodes;
|
|
@@ -11017,6 +11117,17 @@ var WasmProcess = class {
|
|
|
11017
11117
|
};
|
|
11018
11118
|
return fs.exclusive ? fs.exclusive(first.path, look) : look();
|
|
11019
11119
|
}
|
|
11120
|
+
async mayOpen(req) {
|
|
11121
|
+
const { guard: guard2 } = this.options;
|
|
11122
|
+
const inherited2 = req.orphan || req.contents !== void 0 || req.handle !== void 0;
|
|
11123
|
+
if (!guard2 || inherited2 || req.pin !== void 0) return;
|
|
11124
|
+
const g = { fs: guard2.fs, dac: guard2.dac, cred: this.cred, pid: this.pid };
|
|
11125
|
+
if (req.exclusive) return inParent(g, "open", req.path);
|
|
11126
|
+
if (req.created && guard2.created?.take(req.path)) return;
|
|
11127
|
+
const access2 = req.flags & WRITE_ACCESS;
|
|
11128
|
+
const want = (access2 === 1 ? 0 : R_OK) | (access2 !== 0 || req.truncate ? W_OK : 0);
|
|
11129
|
+
await openable(g, "open", req.path, want, req.create === true);
|
|
11130
|
+
}
|
|
11020
11131
|
newOwner() {
|
|
11021
11132
|
if (!this.options.owners) return void 0;
|
|
11022
11133
|
return { uid: this.cred.euid, gid: this.cred.egid, mode: 438 & ~this.umask };
|
|
@@ -11701,7 +11812,7 @@ function inherited(opts) {
|
|
|
11701
11812
|
function holdingToken(opts, holds, caller) {
|
|
11702
11813
|
return mintSyncFsToken({
|
|
11703
11814
|
...opts.owners ? caller : {},
|
|
11704
|
-
...opts.dac ? { dac: opts.dac, pid: opts.pid } : {},
|
|
11815
|
+
...opts.dac ? { dac: opts.dac, pid: opts.pid, created: caller.created } : {},
|
|
11705
11816
|
fs: opts.fs,
|
|
11706
11817
|
cwd: opts.cwd,
|
|
11707
11818
|
...opts.statfs ? { statfs: opts.statfs } : {},
|
|
@@ -11714,10 +11825,11 @@ function holdingToken(opts, holds, caller) {
|
|
|
11714
11825
|
renamed: (from, to) => holds.renamed(from, to)
|
|
11715
11826
|
});
|
|
11716
11827
|
}
|
|
11717
|
-
function processOptions(opts, header4, hooks) {
|
|
11828
|
+
function processOptions(opts, header4, hooks, created3) {
|
|
11718
11829
|
return {
|
|
11719
11830
|
...inherited(opts),
|
|
11720
11831
|
...opts.owners ? { owners: true } : {},
|
|
11832
|
+
...opts.dac ? { guard: { dac: opts.dac, fs: opts.fs, created: created3 } } : {},
|
|
11721
11833
|
...opts.identity ? { identity: opts.identity } : {},
|
|
11722
11834
|
...opts.onSyscall ? { onSyscall: opts.onSyscall } : {},
|
|
11723
11835
|
...opts.settling ? { settling: opts.settling } : {},
|
|
@@ -11751,20 +11863,27 @@ function spawnWasmProcess(opts) {
|
|
|
11751
11863
|
const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
11752
11864
|
const header4 = new Int32Array(sab, 0, SAB_HEADER_I32);
|
|
11753
11865
|
const threadSignals = /* @__PURE__ */ new Map();
|
|
11866
|
+
const created3 = new Created();
|
|
11754
11867
|
const process2 = new WasmProcess(
|
|
11755
11868
|
opts.pid,
|
|
11756
11869
|
opts.fds,
|
|
11757
|
-
processOptions(
|
|
11758
|
-
|
|
11759
|
-
|
|
11760
|
-
|
|
11870
|
+
processOptions(
|
|
11871
|
+
opts,
|
|
11872
|
+
header4,
|
|
11873
|
+
{
|
|
11874
|
+
raise: (sig) => signal(sig),
|
|
11875
|
+
threadKill: (tid, sig) => killThread(threadSignals.get(tid), process2.signalMasks().caught, sig)
|
|
11876
|
+
},
|
|
11877
|
+
created3
|
|
11878
|
+
)
|
|
11761
11879
|
);
|
|
11762
11880
|
publishStops(process2, header4);
|
|
11763
11881
|
const holds = new HeldPaths();
|
|
11764
11882
|
opts.held?.add(holds);
|
|
11765
11883
|
const token = holdingToken(opts, holds, {
|
|
11766
11884
|
cred: () => process2.cred,
|
|
11767
|
-
umask: () => process2.umask
|
|
11885
|
+
umask: () => process2.umask,
|
|
11886
|
+
created: created3
|
|
11768
11887
|
});
|
|
11769
11888
|
process2.keptPath = (path) => holds.keptAt(path)?.hidden;
|
|
11770
11889
|
process2.keptHandle = (handle2) => holds.keptFor(handle2)?.hidden;
|
|
@@ -12877,16 +12996,16 @@ function hostfsHandlers(current, againMs = RESTORE_AGAIN_MS) {
|
|
|
12877
12996
|
});
|
|
12878
12997
|
async function writable2(client, path, flags) {
|
|
12879
12998
|
const { ifMatch: _, ...asked } = flags;
|
|
12880
|
-
const
|
|
12999
|
+
const opening2 = () => client.call("open", { path: rel(path), ...asked });
|
|
12881
13000
|
try {
|
|
12882
|
-
return { opened: await
|
|
13001
|
+
return { opened: await opening2(), restore: void 0 };
|
|
12883
13002
|
} catch (err) {
|
|
12884
13003
|
if (!flags.write || codeOf4(err) !== "EACCES") throw err;
|
|
12885
13004
|
const was = await client.call("stat", { path: rel(path) });
|
|
12886
13005
|
const mode = was.mode ?? 0;
|
|
12887
13006
|
if (mode & 128) throw err;
|
|
12888
13007
|
const restore = { path: rel(path), mode, was };
|
|
12889
|
-
const opened2 = await client.call("setattr", { path: rel(path), mode: mode | 128 }).then(
|
|
13008
|
+
const opened2 = await client.call("setattr", { path: rel(path), mode: mode | 128 }).then(opening2).catch(async (again) => {
|
|
12890
13009
|
await settle(client, restore).catch(() => {
|
|
12891
13010
|
});
|
|
12892
13011
|
throw again;
|
|
@@ -13894,6 +14013,16 @@ var NOT_FOUND = 127;
|
|
|
13894
14013
|
var DECIDE_MS = 100;
|
|
13895
14014
|
var INIT_PID = 1;
|
|
13896
14015
|
var SHARED_DIRS = ["/tmp", "/home"];
|
|
14016
|
+
var LAYOUT = [
|
|
14017
|
+
["/", 493],
|
|
14018
|
+
["/root", 448],
|
|
14019
|
+
["/home", 493],
|
|
14020
|
+
["/etc", 493],
|
|
14021
|
+
[PASSWD, 420],
|
|
14022
|
+
[GROUP, 420],
|
|
14023
|
+
["/usr", 493],
|
|
14024
|
+
["/usr/local", 493]
|
|
14025
|
+
];
|
|
13897
14026
|
var encoder3 = new TextEncoder();
|
|
13898
14027
|
var USERS_MODES = ["off", "report", "enforce"];
|
|
13899
14028
|
function usersMode(mode = "off") {
|
|
@@ -14087,7 +14216,8 @@ var Launcher = class {
|
|
|
14087
14216
|
{
|
|
14088
14217
|
locks: webLocks(),
|
|
14089
14218
|
busy: (path) => [...this.openFiles].some((nodes) => nodes.holds(path)),
|
|
14090
|
-
owner: options.unlinkOwner
|
|
14219
|
+
owner: options.unlinkOwner,
|
|
14220
|
+
...this.owners ? { dirOwner: { uid: 0, gid: 0, mode: 448 } } : {}
|
|
14091
14221
|
}
|
|
14092
14222
|
);
|
|
14093
14223
|
this.fs = this.unlinked.wrap(keepingOpen(fs, this.nodes));
|
|
@@ -14247,15 +14377,33 @@ var Launcher = class {
|
|
|
14247
14377
|
return void 0;
|
|
14248
14378
|
}
|
|
14249
14379
|
const inner = await this.interpreted(interp, [interp, ...passed], cwd, scope, depth + 1);
|
|
14250
|
-
|
|
14380
|
+
const via = [interp, ...inner?.via ?? []];
|
|
14381
|
+
return inner && { ...inner, target: withScriptEnv(inner.target, command), via };
|
|
14251
14382
|
}
|
|
14252
14383
|
const target = withScriptEnv(found, command);
|
|
14253
|
-
return { target, args: [...target.prefix ?? [], ...passed] };
|
|
14384
|
+
return { target, args: [...target.prefix ?? [], ...passed], via: [interp] };
|
|
14254
14385
|
}
|
|
14255
14386
|
async plan(file, argv, cwd, scope) {
|
|
14256
14387
|
const direct = await this.resolve(file, argv[0] ?? file, cwd, scope);
|
|
14257
14388
|
if (direct) return { target: direct, args: [...direct.prefix ?? [], ...argv.slice(1)] };
|
|
14258
|
-
|
|
14389
|
+
const script = await this.interpreted(file, argv, cwd, scope);
|
|
14390
|
+
return script && { ...script, script: true };
|
|
14391
|
+
}
|
|
14392
|
+
async mayExec(cred, req, planned) {
|
|
14393
|
+
const { dac } = this;
|
|
14394
|
+
if (!dac) return;
|
|
14395
|
+
const g = { fs: this.fs, cred, pid: req.pid, dac };
|
|
14396
|
+
const byPath = (file) => file.includes("/") && !COMMAND2.test(file);
|
|
14397
|
+
if (byPath(req.file)) {
|
|
14398
|
+
const path = this.fs.resolvePath(req.cwd, req.file);
|
|
14399
|
+
await need(g, "exec", path, planned?.script ? R_OK | X_OK : X_OK);
|
|
14400
|
+
}
|
|
14401
|
+
const via = planned?.via ?? [];
|
|
14402
|
+
for (const [i, file] of via.entries()) {
|
|
14403
|
+
if (!byPath(file)) continue;
|
|
14404
|
+
const want = i < via.length - 1 ? R_OK | X_OK : X_OK;
|
|
14405
|
+
await need(g, "exec", this.fs.resolvePath(req.cwd, file), want);
|
|
14406
|
+
}
|
|
14259
14407
|
}
|
|
14260
14408
|
async unrunnable(file, cwd, scope) {
|
|
14261
14409
|
const path = this.fs.resolvePath(cwd, file);
|
|
@@ -14475,6 +14623,12 @@ var Launcher = class {
|
|
|
14475
14623
|
return async (req, fds) => {
|
|
14476
14624
|
const scope = await this.scopeOf(this.credOf(ppid).euid);
|
|
14477
14625
|
const planned = await this.plan(req.file, req.argv, req.cwd, scope);
|
|
14626
|
+
try {
|
|
14627
|
+
await this.mayExec(this.credOf(ppid), { ...req, pid: ppid }, planned);
|
|
14628
|
+
} catch (err) {
|
|
14629
|
+
await fds.closeAll();
|
|
14630
|
+
throw err.code === "EACCES" ? new SpawnError("EACCES") : err;
|
|
14631
|
+
}
|
|
14478
14632
|
if (!planned) {
|
|
14479
14633
|
await fds.closeAll();
|
|
14480
14634
|
throw new SpawnError(await this.unrunnable(req.file, req.cwd, scope));
|
|
@@ -14688,6 +14842,24 @@ var Launcher = class {
|
|
|
14688
14842
|
await this.provisionPnpmHome();
|
|
14689
14843
|
return entry;
|
|
14690
14844
|
}
|
|
14845
|
+
async stampLayout() {
|
|
14846
|
+
const layout = [
|
|
14847
|
+
...LAYOUT,
|
|
14848
|
+
[this.modulesDir, 493],
|
|
14849
|
+
[this.pnpmHome, 493],
|
|
14850
|
+
[`/${UNLINKED_DIR}`, 448]
|
|
14851
|
+
];
|
|
14852
|
+
for (const [path, mode] of layout) {
|
|
14853
|
+
const real = await this.realLayoutPath(path);
|
|
14854
|
+
const fresh = real !== void 0 && !await this.base.hasOwner?.(real);
|
|
14855
|
+
if (fresh) await this.base.chown?.(real, { uid: 0, gid: 0, mode, follow: false });
|
|
14856
|
+
}
|
|
14857
|
+
}
|
|
14858
|
+
async realLayoutPath(path) {
|
|
14859
|
+
if (!await this.base.exists(path)) return void 0;
|
|
14860
|
+
if (path === "/") return path;
|
|
14861
|
+
return joinName(await realDir(this.base, parentOf(path)), baseName(path));
|
|
14862
|
+
}
|
|
14691
14863
|
async provisionPnpmHome() {
|
|
14692
14864
|
await this.base.mkdir(this.pnpmHome, { recursive: true }).catch(() => void 0);
|
|
14693
14865
|
}
|
|
@@ -14758,8 +14930,10 @@ var Launcher = class {
|
|
|
14758
14930
|
}
|
|
14759
14931
|
async prepare() {
|
|
14760
14932
|
for (const dir of SHARED_DIRS) await this.base.mkdir(dir, { recursive: true });
|
|
14933
|
+
if (this.owners) await this.base.chmod("/tmp", 1023);
|
|
14761
14934
|
await this.provisionPnpmHome();
|
|
14762
14935
|
await this.users.ensure();
|
|
14936
|
+
if (this.owners) await this.stampLayout();
|
|
14763
14937
|
await writeCaFile(this.base, this.ca).catch(() => void 0);
|
|
14764
14938
|
this.fstab = this.mountFstab();
|
|
14765
14939
|
}
|
|
@@ -14805,7 +14979,9 @@ var Launcher = class {
|
|
|
14805
14979
|
const cwd = await physicalPathAsync(this.base, start2.startsWith("/") ? start2 : `/${start2}`);
|
|
14806
14980
|
const [file = ""] = argv;
|
|
14807
14981
|
await this.base.mkdir(cwd, { recursive: true });
|
|
14808
|
-
|
|
14982
|
+
const planned = await this.plan(file, argv, cwd, scope);
|
|
14983
|
+
await this.mayExec(credOf(account), { file, cwd, pid: 0 }, planned);
|
|
14984
|
+
return { cwd, file, planned };
|
|
14809
14985
|
}
|
|
14810
14986
|
async openTerminal(argv, options) {
|
|
14811
14987
|
const account = await this.account(options.user);
|