@ai-ecoverse/slicc-kernel 1.72.0 → 1.73.1
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 -7
- package/dist/index.js +13 -3
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +142 -37
- package/dist/kernel-worker.js.map +3 -3
- package/dist/node-process-worker.js +117 -78
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +137 -36
- package/dist/node.js.map +3 -3
- package/dist/process-worker.js +117 -78
- package/dist/process-worker.js.map +2 -2
- package/package.json +1 -1
package/dist/kernel-worker.js
CHANGED
|
@@ -361,7 +361,17 @@ async function chownAs(fs, cred, path, change) {
|
|
|
361
361
|
}
|
|
362
362
|
|
|
363
363
|
// src/fs/protect.ts
|
|
364
|
-
|
|
364
|
+
function protectInit(protection) {
|
|
365
|
+
const writers = [...writerTags(protection)];
|
|
366
|
+
return { paths: [...protection.paths], ...writers.length > 0 ? { writers } : {} };
|
|
367
|
+
}
|
|
368
|
+
function writerTags(protection) {
|
|
369
|
+
const writers = protection?.writers ?? [];
|
|
370
|
+
if (!Array.isArray(writers) || writers.some((tag) => typeof tag !== "string" || tag === "")) {
|
|
371
|
+
throw new TypeError("protect.writers must be a list of process tags");
|
|
372
|
+
}
|
|
373
|
+
return new Set(writers);
|
|
374
|
+
}
|
|
365
375
|
function protectedPrefixes(paths) {
|
|
366
376
|
return [...new Set(paths.map((p) => normalizePath(p)))];
|
|
367
377
|
}
|
|
@@ -873,6 +883,9 @@ var OpfsFs = class {
|
|
|
873
883
|
protect(prefixes2) {
|
|
874
884
|
this.guarded = prefixes2;
|
|
875
885
|
}
|
|
886
|
+
unguarded() {
|
|
887
|
+
return Object.create(this, { guarded: { value: [] } });
|
|
888
|
+
}
|
|
876
889
|
refuse(path, holding = false) {
|
|
877
890
|
if (isProtected(this.guarded, path) || holding && holdsProtected(this.guarded, path)) {
|
|
878
891
|
throw fsError("EROFS", path);
|
|
@@ -1042,15 +1055,15 @@ var OpfsFs = class {
|
|
|
1042
1055
|
}
|
|
1043
1056
|
dirTimes = /* @__PURE__ */ new Map();
|
|
1044
1057
|
dirDirty = /* @__PURE__ */ new Set();
|
|
1045
|
-
|
|
1058
|
+
flushing = {};
|
|
1046
1059
|
touch(...dirs) {
|
|
1047
1060
|
const now = Date.now();
|
|
1048
1061
|
for (const dir of dirs) {
|
|
1049
1062
|
this.dirTimes.set(dir, now);
|
|
1050
1063
|
this.dirDirty.add(dir);
|
|
1051
1064
|
}
|
|
1052
|
-
this.
|
|
1053
|
-
this.
|
|
1065
|
+
this.flushing.dir ??= Promise.resolve().then(() => this.flushDirTimes()).catch(() => void 0).finally(() => {
|
|
1066
|
+
this.flushing.dir = void 0;
|
|
1054
1067
|
});
|
|
1055
1068
|
}
|
|
1056
1069
|
async flushDirTimes() {
|
|
@@ -1294,7 +1307,7 @@ var OpfsFs = class {
|
|
|
1294
1307
|
const above = owner && {
|
|
1295
1308
|
uid: owner.uid,
|
|
1296
1309
|
gid: owner.gid,
|
|
1297
|
-
...mode ? { mode, parents: mode } : {}
|
|
1310
|
+
...mode !== void 0 ? { mode, parents: mode } : {}
|
|
1298
1311
|
};
|
|
1299
1312
|
await this.mkdir(parentOf3(path), { recursive: true, ...above ? { owner: above } : {} });
|
|
1300
1313
|
}
|
|
@@ -3569,6 +3582,9 @@ var UserDb = class {
|
|
|
3569
3582
|
const pnpm = `${home}/.local/share/pnpm`;
|
|
3570
3583
|
if (await this.realDir(pnpm)) await this.fs.chmod(pnpm, scoop ? 488 : 448);
|
|
3571
3584
|
}
|
|
3585
|
+
umaskFor(options) {
|
|
3586
|
+
return (options.umask ?? this.umasks.get(options.name) ?? 18) & 511;
|
|
3587
|
+
}
|
|
3572
3588
|
async realDir(path) {
|
|
3573
3589
|
const parts2 = path.split("/").filter(Boolean);
|
|
3574
3590
|
for (let n = 1; n <= parts2.length; n++) {
|
|
@@ -3592,9 +3608,11 @@ var UserDb = class {
|
|
|
3592
3608
|
group: parseGroup(await this.read(GROUP, DEFAULT_GROUP))
|
|
3593
3609
|
};
|
|
3594
3610
|
}
|
|
3595
|
-
async provision(row) {
|
|
3596
|
-
const
|
|
3597
|
-
const
|
|
3611
|
+
async provision(row, umask, shared) {
|
|
3612
|
+
const dirs = 511 & ~umask | (shared ? 1024 : 0);
|
|
3613
|
+
const gid = shared?.gid ?? row.gid;
|
|
3614
|
+
const owner = this.owners ? { uid: row.uid, gid } : void 0;
|
|
3615
|
+
const made2 = owner ? { recursive: true, owner: { ...owner, mode: dirs, parents: dirs } } : { recursive: true };
|
|
3598
3616
|
const pnpm = `${row.home}/.local/share/pnpm`;
|
|
3599
3617
|
if (!await this.fs.exists(pnpm)) {
|
|
3600
3618
|
await this.fs.mkdir(pnpm, made2);
|
|
@@ -3603,7 +3621,7 @@ var UserDb = class {
|
|
|
3603
3621
|
const config = `${row.home}/.config/pnpm/config.yaml`;
|
|
3604
3622
|
if (!await this.fs.exists(config)) {
|
|
3605
3623
|
await this.fs.mkdir(`${row.home}/.config/pnpm`, made2);
|
|
3606
|
-
await this.fs.writeFile(config, PNPM_CONFIG, owner);
|
|
3624
|
+
await this.fs.writeFile(config, PNPM_CONFIG, owner && { ...owner, mode: 438 & ~umask });
|
|
3607
3625
|
}
|
|
3608
3626
|
}
|
|
3609
3627
|
async commit(passwd, group, then) {
|
|
@@ -3694,7 +3712,7 @@ var UserDb = class {
|
|
|
3694
3712
|
throw fsError("EINVAL", `a user is no member of its own group ${name2}`);
|
|
3695
3713
|
}
|
|
3696
3714
|
if (found.uid >= FIRST_UID && found.uid <= LAST_UID) {
|
|
3697
|
-
await this.provision(found);
|
|
3715
|
+
await this.provision(found, this.umaskFor(options), shared);
|
|
3698
3716
|
await this.stampHome(found, shared, homeMode);
|
|
3699
3717
|
}
|
|
3700
3718
|
if (joined(name2, more)) await this.fs.writeFile(GROUP, formatGroup(group));
|
|
@@ -3712,7 +3730,7 @@ var UserDb = class {
|
|
|
3712
3730
|
const fresh2 = !await this.fs.exists(home);
|
|
3713
3731
|
await this.fs.mkdir(home, { recursive: true });
|
|
3714
3732
|
try {
|
|
3715
|
-
await this.provision(row);
|
|
3733
|
+
await this.provision(row, this.umaskFor(options), shared);
|
|
3716
3734
|
await this.stampHome(row, shared, homeMode);
|
|
3717
3735
|
await this.fs.mkdir("/etc", { recursive: true });
|
|
3718
3736
|
await this.commit(formatPasswd(passwd), formatGroup(group));
|
|
@@ -3821,6 +3839,12 @@ var CLIENT_CHECKS = {
|
|
|
3821
3839
|
readlink: (g, at) => searchable(g, "readlink", at(0), false),
|
|
3822
3840
|
exists: (g, at) => searchable(g, "exists", at(0), true)
|
|
3823
3841
|
};
|
|
3842
|
+
function clientFs(l, tag, self, req) {
|
|
3843
|
+
if (!FS_METHODS.includes(req.method)) {
|
|
3844
|
+
throw new Error(`unknown file system call ${req.method}`);
|
|
3845
|
+
}
|
|
3846
|
+
return fsCall(l.fsFor(tag), req.method, req.args, ownerFor(l, self), guardFor(l, self, tag));
|
|
3847
|
+
}
|
|
3824
3848
|
async function fsCall(fs, method, args, owner, g) {
|
|
3825
3849
|
const path = (i) => fs.resolvePath("/", String(args[i]));
|
|
3826
3850
|
if (g) {
|
|
@@ -4108,10 +4132,7 @@ function serveClient(port, host) {
|
|
|
4108
4132
|
case "ps":
|
|
4109
4133
|
return { result: processes(l, self) };
|
|
4110
4134
|
case "fs":
|
|
4111
|
-
|
|
4112
|
-
throw new Error(`unknown file system call ${req.method}`);
|
|
4113
|
-
}
|
|
4114
|
-
return fsCall(l.processFs, req.method, req.args, ownerFor(l, self), guard2(l));
|
|
4135
|
+
return clientFs(l, host.tag, self, req);
|
|
4115
4136
|
case "watch":
|
|
4116
4137
|
case "unwatch":
|
|
4117
4138
|
return watchOp(l, req, watches, send, guard2(l));
|
|
@@ -7816,6 +7837,11 @@ var HeldPaths = class extends Map {
|
|
|
7816
7837
|
keptFor(handle) {
|
|
7817
7838
|
return this.keptHandles.get(handle);
|
|
7818
7839
|
}
|
|
7840
|
+
keeps(hidden) {
|
|
7841
|
+
for (const file of this.uses.keys()) if (file.hidden === hidden) return true;
|
|
7842
|
+
for (const file of this.unlinked.values()) if (file.hidden === hidden) return true;
|
|
7843
|
+
return false;
|
|
7844
|
+
}
|
|
7819
7845
|
keep(path, file) {
|
|
7820
7846
|
const fresh2 = this.handlesAt(path).filter((id2) => !this.keptHandles.has(id2));
|
|
7821
7847
|
for (const id2 of fresh2) this.keptHandles.set(id2, file);
|
|
@@ -8917,6 +8943,7 @@ function guardOf(entry) {
|
|
|
8917
8943
|
return { fs: entry.fs, cred, pid: entry.pid ?? 0, dac: entry.dac };
|
|
8918
8944
|
}
|
|
8919
8945
|
var FOLLOWING = /* @__PURE__ */ new Set(["exists", "stat", "chown", "statfs"]);
|
|
8946
|
+
var LOOKS = /* @__PURE__ */ new Set(["exists", "stat", "lstat"]);
|
|
8920
8947
|
var NOT_FOLLOWING = /* @__PURE__ */ new Set(["lstat", "readlink", "lchown"]);
|
|
8921
8948
|
async function guard(g, path, req, cwd) {
|
|
8922
8949
|
const { op } = req;
|
|
@@ -8986,6 +9013,7 @@ async function accessOp(entry, path, req) {
|
|
|
8986
9013
|
async function guarded(entry, path, req) {
|
|
8987
9014
|
const g = guardOf(entry);
|
|
8988
9015
|
if (!g) return void 0;
|
|
9016
|
+
if (LOOKS.has(req.op) && await entry.holdsKept?.(path)) return void 0;
|
|
8989
9017
|
try {
|
|
8990
9018
|
await guard(g, path, req, entry.cwd);
|
|
8991
9019
|
return void 0;
|
|
@@ -12529,6 +12557,13 @@ var WasmProcess = class {
|
|
|
12529
12557
|
}
|
|
12530
12558
|
}
|
|
12531
12559
|
keptPath;
|
|
12560
|
+
async holds(path) {
|
|
12561
|
+
for (const fd of this.fds.numbers()) {
|
|
12562
|
+
const { file } = this.fds.get(fd);
|
|
12563
|
+
if ((await file.stat?.().catch(() => void 0))?.path === path) return true;
|
|
12564
|
+
}
|
|
12565
|
+
return false;
|
|
12566
|
+
}
|
|
12532
12567
|
keptHandle;
|
|
12533
12568
|
async keptOr(path, handle) {
|
|
12534
12569
|
const held = handle === void 0 ? void 0 : this.keptHandle?.(handle);
|
|
@@ -13172,7 +13207,8 @@ function spawnWasmProcess(opts) {
|
|
|
13172
13207
|
const token = holdingToken(opts, holds, {
|
|
13173
13208
|
cred: () => process.cred,
|
|
13174
13209
|
umask: () => process.umask,
|
|
13175
|
-
created: created3
|
|
13210
|
+
created: created3,
|
|
13211
|
+
holdsKept: async (path) => path.includes(`/${UNLINKED_DIR}/`) && (holds.keeps(path) || await process.holds(path))
|
|
13176
13212
|
});
|
|
13177
13213
|
process.keptPath = (path) => holds.keptAt(path)?.hidden;
|
|
13178
13214
|
process.keptHandle = (handle2) => holds.keptFor(handle2)?.hidden;
|
|
@@ -15534,9 +15570,14 @@ var Sudo = class {
|
|
|
15534
15570
|
if (walked.denied !== void 0 || walked.missing) return false;
|
|
15535
15571
|
return (await this.o.fs.stat(cwd).catch(() => void 0))?.isDirectory === true;
|
|
15536
15572
|
}
|
|
15537
|
-
async untrusted(path, cwd) {
|
|
15538
|
-
const files = await this.o.backing
|
|
15539
|
-
|
|
15573
|
+
async untrusted(path, cwd, word) {
|
|
15574
|
+
const files = this.o.backing ? await this.o.backing(path, cwd) : [];
|
|
15575
|
+
if (!files) return failed2("ENOENT", `sudo: ${word}: command not found`);
|
|
15576
|
+
for (const file of [path, ...files]) {
|
|
15577
|
+
if (!await this.trusted(file)) {
|
|
15578
|
+
return failed2("EPERM", `sudo: ${file} must be root's, and writable by root only`);
|
|
15579
|
+
}
|
|
15580
|
+
}
|
|
15540
15581
|
return void 0;
|
|
15541
15582
|
}
|
|
15542
15583
|
async locate(word, cwd) {
|
|
@@ -15577,10 +15618,8 @@ var Sudo = class {
|
|
|
15577
15618
|
}
|
|
15578
15619
|
const path = await this.locate(word, cwd);
|
|
15579
15620
|
if (!path) return failed2("ENOENT", `sudo: ${word}: command not found`);
|
|
15580
|
-
const untrusted = await this.untrusted(path, cwd);
|
|
15581
|
-
if (untrusted)
|
|
15582
|
-
return failed2("EPERM", `sudo: ${untrusted} must be root's, and writable by root only`);
|
|
15583
|
-
}
|
|
15621
|
+
const untrusted = await this.untrusted(path, cwd, word);
|
|
15622
|
+
if (untrusted) return untrusted;
|
|
15584
15623
|
const argv = [path, ...args];
|
|
15585
15624
|
const matching = rules.filter(
|
|
15586
15625
|
(rule) => applies(rule) && (rule.target === "ALL" || rule.target === target.name) && (rule.cmnd === "*" || rule.cmnd.length === argv.length && rule.cmnd.every((w, i) => w === argv[i]))
|
|
@@ -15603,10 +15642,8 @@ var Sudo = class {
|
|
|
15603
15642
|
if (await this.canonical(call.cwd) !== cwd || !await this.reachable(cred, cwd)) {
|
|
15604
15643
|
return failed2("EACCES", `sudo: ${call.cwd} changed while the request waited`);
|
|
15605
15644
|
}
|
|
15606
|
-
const changed = await this.untrusted(path, cwd);
|
|
15607
|
-
if (changed)
|
|
15608
|
-
return failed2("EPERM", `sudo: ${changed} must be root's, and writable by root only`);
|
|
15609
|
-
}
|
|
15645
|
+
const changed = await this.untrusted(path, cwd, word);
|
|
15646
|
+
if (changed) return changed;
|
|
15610
15647
|
if (answer === "always" && !await this.remember(self, target, argv)) {
|
|
15611
15648
|
return failed2("EIO", "sudo: the rule could not be recorded");
|
|
15612
15649
|
}
|
|
@@ -15880,6 +15917,10 @@ var Launcher = class {
|
|
|
15880
15917
|
fs;
|
|
15881
15918
|
processFs;
|
|
15882
15919
|
prefixes;
|
|
15920
|
+
writerTags;
|
|
15921
|
+
unguardedRoot;
|
|
15922
|
+
writers;
|
|
15923
|
+
unlinkOwnerOption;
|
|
15883
15924
|
base;
|
|
15884
15925
|
createWorker;
|
|
15885
15926
|
modulesDir;
|
|
@@ -15997,7 +16038,7 @@ var Launcher = class {
|
|
|
15997
16038
|
this.nodes = new VfsNodes(fs, (path) => this.released(path));
|
|
15998
16039
|
this.nodes.keepsOnDisk = true;
|
|
15999
16040
|
this.openFiles.add(this.nodes);
|
|
16000
|
-
const holders = [this.held,
|
|
16041
|
+
const holders = [this.held, this.openFiles];
|
|
16001
16042
|
this.unlinked = new UnlinkedKeeper(
|
|
16002
16043
|
fs,
|
|
16003
16044
|
{ [Symbol.iterator]: () => holders.flatMap((set2) => [...set2]).values() },
|
|
@@ -16010,7 +16051,12 @@ var Launcher = class {
|
|
|
16010
16051
|
}
|
|
16011
16052
|
);
|
|
16012
16053
|
this.fs = this.unlinked.wrap(keepingOpen(fs, this.nodes));
|
|
16013
|
-
|
|
16054
|
+
this.writerTags = writerTags(options.protect);
|
|
16055
|
+
this.unlinkOwnerOption = options.unlinkOwner;
|
|
16056
|
+
if (this.writerTags.size > 0 && options.fs.protect && !options.fs.unguarded) {
|
|
16057
|
+
throw new TypeError("protect.writers needs a root file system with an unguarded view");
|
|
16058
|
+
}
|
|
16059
|
+
this.unguardedRoot = options.fs.unguarded?.() ?? options.fs;
|
|
16014
16060
|
this.prefixes = protectedPrefixes(options.protect?.paths ?? []);
|
|
16015
16061
|
this.processFs = this.prefixes.length > 0 ? new ProtectedFs(this.prefixes).view(this.fs) : this.fs;
|
|
16016
16062
|
options.fs.protect?.(this.prefixes);
|
|
@@ -16227,7 +16273,7 @@ var Launcher = class {
|
|
|
16227
16273
|
}
|
|
16228
16274
|
async backing(file, cwd) {
|
|
16229
16275
|
const planned = await this.plan(file, [file], cwd, "");
|
|
16230
|
-
if (!planned) return
|
|
16276
|
+
if (!planned) return void 0;
|
|
16231
16277
|
const { glue, wasm, imports } = planned.target;
|
|
16232
16278
|
const files = [glue, wasm, ...imports ? [imports] : []];
|
|
16233
16279
|
const scripts = [];
|
|
@@ -16334,6 +16380,7 @@ var Launcher = class {
|
|
|
16334
16380
|
throw fsError("ESRCH", `no process group ${req.pgid}`);
|
|
16335
16381
|
}
|
|
16336
16382
|
const pid = this.nextPid++;
|
|
16383
|
+
const stack = this.stackFor(req.tag);
|
|
16337
16384
|
const terminal = req.fds.stdioTerminal();
|
|
16338
16385
|
const decided = req.decided ?? Promise.resolve(true);
|
|
16339
16386
|
const count = (byParent) => {
|
|
@@ -16364,8 +16411,8 @@ var Launcher = class {
|
|
|
16364
16411
|
env: req.env,
|
|
16365
16412
|
cwd: req.cwd,
|
|
16366
16413
|
fds: req.fds,
|
|
16367
|
-
fs:
|
|
16368
|
-
...this.prefixes.length > 0 ? { readonlyAt: (path) => isProtected(this.prefixes, path) } : {},
|
|
16414
|
+
fs: stack.fs,
|
|
16415
|
+
...this.prefixes.length > 0 && !stack.writer ? { readonlyAt: (path) => isProtected(this.prefixes, path) } : {},
|
|
16369
16416
|
createWorker: this.createWorker,
|
|
16370
16417
|
onError: req.report,
|
|
16371
16418
|
spawner: this.spawner(pid, req.report),
|
|
@@ -16380,9 +16427,9 @@ var Launcher = class {
|
|
|
16380
16427
|
}),
|
|
16381
16428
|
sudo: (call, signal) => this.sudo(pid, call, signal),
|
|
16382
16429
|
openFiles: this.openFiles,
|
|
16383
|
-
nodes:
|
|
16430
|
+
nodes: stack.nodes,
|
|
16384
16431
|
held: this.held,
|
|
16385
|
-
unlinkGate:
|
|
16432
|
+
unlinkGate: stack.unlinked.gate,
|
|
16386
16433
|
statfs: (path) => this.mounts.statfs(path),
|
|
16387
16434
|
mounts: () => this.mounts.list(),
|
|
16388
16435
|
mount: (call, signal) => this.processMount(pid, call, signal),
|
|
@@ -16683,6 +16730,7 @@ var Launcher = class {
|
|
|
16683
16730
|
released(path) {
|
|
16684
16731
|
const at = normalizePath(path);
|
|
16685
16732
|
this.unlinked.closed(at);
|
|
16733
|
+
this.writers?.unlinked.closed(at);
|
|
16686
16734
|
const open = [...this.openFiles].some((nodes) => nodes.writes(at)) || heldUnder(this.held, at);
|
|
16687
16735
|
if (!open) void this.mounts.commit(at).catch(() => void 0);
|
|
16688
16736
|
}
|
|
@@ -16833,6 +16881,27 @@ var Launcher = class {
|
|
|
16833
16881
|
await this.provisionPnpmHome();
|
|
16834
16882
|
return entry;
|
|
16835
16883
|
}
|
|
16884
|
+
async ownTmp() {
|
|
16885
|
+
const real = await this.realLayoutPath("/tmp");
|
|
16886
|
+
const st = real === void 0 ? void 0 : await this.base.lstat(real).catch(() => void 0);
|
|
16887
|
+
if (real !== void 0 && st?.isDirectory && this.base.hasOwner && !await this.base.hasOwner(real)) {
|
|
16888
|
+
let removed = 0;
|
|
16889
|
+
for (const name2 of await this.base.readdir(real).catch(() => [])) {
|
|
16890
|
+
const path = joinName(real, name2);
|
|
16891
|
+
if (await this.base.hasOwner(path) || this.inUse(path)) continue;
|
|
16892
|
+
const failed3 = await this.base.rm(path, { recursive: true, force: true }).catch(String);
|
|
16893
|
+
if (failed3 === void 0) removed++;
|
|
16894
|
+
}
|
|
16895
|
+
if (removed > 0) {
|
|
16896
|
+
console.warn(`slicc-kernel users: removed ${removed} entries from /tmp that had no owner`);
|
|
16897
|
+
}
|
|
16898
|
+
await this.base.chown?.(real, { uid: 0, gid: 0, mode: 1023, follow: false });
|
|
16899
|
+
}
|
|
16900
|
+
if (st?.isDirectory) await this.base.chmod(real, 1023);
|
|
16901
|
+
}
|
|
16902
|
+
inUse(path) {
|
|
16903
|
+
return [...this.openFiles].some((nodes) => nodes.holds(path)) || heldUnder(this.held, path);
|
|
16904
|
+
}
|
|
16836
16905
|
async stampLayout() {
|
|
16837
16906
|
const layout = [
|
|
16838
16907
|
...LAYOUT,
|
|
@@ -16952,7 +17021,7 @@ var Launcher = class {
|
|
|
16952
17021
|
async prepare() {
|
|
16953
17022
|
await this.resolvePrefixes();
|
|
16954
17023
|
for (const dir of SHARED_DIRS) await this.base.mkdir(dir, { recursive: true });
|
|
16955
|
-
if (this.owners) await this.
|
|
17024
|
+
if (this.owners) await this.ownTmp();
|
|
16956
17025
|
await this.provisionPnpmHome();
|
|
16957
17026
|
await this.users.ensure();
|
|
16958
17027
|
if (this.owners) await this.stampLayout();
|
|
@@ -17001,13 +17070,49 @@ var Launcher = class {
|
|
|
17001
17070
|
...account.umask !== void 0 ? { umask: account.umask } : {}
|
|
17002
17071
|
};
|
|
17003
17072
|
}
|
|
17073
|
+
fsFor(tag) {
|
|
17074
|
+
return this.stackFor(tag).fs;
|
|
17075
|
+
}
|
|
17076
|
+
isWriter(tag) {
|
|
17077
|
+
return tag !== void 0 && this.prefixes.length > 0 && this.writerTags.has(tag);
|
|
17078
|
+
}
|
|
17079
|
+
stackFor(tag) {
|
|
17080
|
+
if (!this.isWriter(tag)) {
|
|
17081
|
+
return { fs: this.processFs, nodes: this.nodes, unlinked: this.unlinked, writer: false };
|
|
17082
|
+
}
|
|
17083
|
+
this.writers ??= this.writerStack();
|
|
17084
|
+
return this.writers;
|
|
17085
|
+
}
|
|
17086
|
+
writerStack() {
|
|
17087
|
+
const fs = withCommandDirs(
|
|
17088
|
+
this.watchers.wrap(this.mounts.wrap(this.unguardedRoot)),
|
|
17089
|
+
async () => new Set((await this.commands()).keys()),
|
|
17090
|
+
(dir) => this.userCommandDir(dir),
|
|
17091
|
+
this.owners
|
|
17092
|
+
);
|
|
17093
|
+
const nodes = new VfsNodes(fs, (path) => this.released(path));
|
|
17094
|
+
nodes.keepsOnDisk = true;
|
|
17095
|
+
this.openFiles.add(nodes);
|
|
17096
|
+
const unlinked = new UnlinkedKeeper(
|
|
17097
|
+
fs,
|
|
17098
|
+
{ [Symbol.iterator]: () => [this.held, this.openFiles].flatMap((set2) => [...set2]).values() },
|
|
17099
|
+
(path) => this.mountRoot(path),
|
|
17100
|
+
{
|
|
17101
|
+
locks: webLocks(),
|
|
17102
|
+
busy: (path) => [...this.openFiles].some((open) => open.holds(path)),
|
|
17103
|
+
owner: this.unlinkOwnerOption,
|
|
17104
|
+
...this.owners ? { dirOwner: { uid: 0, gid: 0, mode: 448 } } : {}
|
|
17105
|
+
}
|
|
17106
|
+
);
|
|
17107
|
+
return { fs: unlinked.wrap(keepingOpen(fs, nodes)), nodes, unlinked, writer: true };
|
|
17108
|
+
}
|
|
17004
17109
|
async starting(argv, dir, account, tag) {
|
|
17005
17110
|
this.resetCatalogs();
|
|
17006
17111
|
const scope = account.uid === 0 ? "" : pnpmHomeOf(account, this.pnpmHome);
|
|
17007
17112
|
const start2 = dir ?? "/";
|
|
17008
17113
|
const cwd = await physicalPathAsync(this.base, start2.startsWith("/") ? start2 : `/${start2}`);
|
|
17009
17114
|
const [file = ""] = argv;
|
|
17010
|
-
if (!await this.base.exists(cwd)) await this.
|
|
17115
|
+
if (!await this.base.exists(cwd)) await this.stackFor(tag).fs.mkdir(cwd, { recursive: true });
|
|
17011
17116
|
const planned = await this.plan(file, argv, cwd, scope);
|
|
17012
17117
|
await this.mayExec(credOf(account), { file, cwd, pid: 0, tag }, planned);
|
|
17013
17118
|
return { cwd, file, planned };
|
|
@@ -17270,7 +17375,7 @@ function hostOptions(req, port, sealed) {
|
|
|
17270
17375
|
...req.hostname !== void 0 ? { hostname: req.hostname } : {},
|
|
17271
17376
|
...req.users !== void 0 ? { users: req.users } : {},
|
|
17272
17377
|
...req.denials ? { onDenial: (denial) => port.postMessage({ denial }) } : {},
|
|
17273
|
-
...req.protect ? { protect:
|
|
17378
|
+
...req.protect ? { protect: protectInit(req.protect) } : {},
|
|
17274
17379
|
...req.sealed ? { sealed } : {}
|
|
17275
17380
|
};
|
|
17276
17381
|
}
|