@ai-ecoverse/slicc-kernel 1.56.2 → 1.57.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 +19 -5
- package/dist/driver-worker.js +1 -0
- package/dist/driver-worker.js.map +2 -2
- package/dist/index.js +5 -2
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +310 -62
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-driver-worker.js +1 -0
- package/dist/node-driver-worker.js.map +2 -2
- package/dist/node-process-worker.js +311 -95
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +307 -62
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +311 -95
- package/dist/process-worker.js.map +3 -3
- package/package.json +1 -1
package/dist/kernel-worker.js
CHANGED
|
@@ -216,11 +216,69 @@ function inodeOf(path) {
|
|
|
216
216
|
return 4294967296 * (2097151 & h2) + (h1 >>> 0) || 1;
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
+
// src/fs/owners.ts
|
|
220
|
+
var ROOT_OWNER = Object.freeze({ uid: 0, gid: 0 });
|
|
221
|
+
var S_ISUID = 2048;
|
|
222
|
+
var S_ISGID = 1024;
|
|
223
|
+
var S_IXGRP = 8;
|
|
224
|
+
function ownOf(entry) {
|
|
225
|
+
if (entry?.uid === void 0 || entry.gid === void 0) return void 0;
|
|
226
|
+
return { uid: entry.uid, gid: entry.gid };
|
|
227
|
+
}
|
|
228
|
+
function handedBy(entry) {
|
|
229
|
+
return entry?.heir ? { uid: entry.heir[0], gid: entry.heir[1] } : ownOf(entry);
|
|
230
|
+
}
|
|
231
|
+
function inherit(entries) {
|
|
232
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
233
|
+
const found = handedBy(entries[i]);
|
|
234
|
+
if (found) return found;
|
|
235
|
+
}
|
|
236
|
+
return { ...ROOT_OWNER };
|
|
237
|
+
}
|
|
238
|
+
function chain(path) {
|
|
239
|
+
const parts = path.split("/").filter(Boolean);
|
|
240
|
+
return ["/", ...parts.map((_, i) => `/${parts.slice(0, i + 1).join("/")}`)];
|
|
241
|
+
}
|
|
242
|
+
function sameOwner(a, b) {
|
|
243
|
+
return a.uid === b.uid && a.gid === b.gid;
|
|
244
|
+
}
|
|
245
|
+
function ownerOf(cred, mode) {
|
|
246
|
+
return { uid: cred.euid, gid: cred.egid, ...mode !== void 0 ? { mode } : {} };
|
|
247
|
+
}
|
|
248
|
+
function inGroup(cred, gid) {
|
|
249
|
+
return cred.egid === gid || cred.groups.includes(gid);
|
|
250
|
+
}
|
|
251
|
+
function mayChown(cred, current, uid, gid) {
|
|
252
|
+
if (cred.euid === 0) return true;
|
|
253
|
+
const owner = cred.euid === current.uid;
|
|
254
|
+
if (uid !== void 0 && !(owner && uid === current.uid)) return false;
|
|
255
|
+
if (gid !== void 0 && !(owner && (gid === current.gid || inGroup(cred, gid)))) return false;
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
function clearedSetId(mode) {
|
|
259
|
+
const bits2 = S_ISUID | (mode & S_IXGRP ? S_ISGID : 0);
|
|
260
|
+
return mode & 4095 & ~bits2;
|
|
261
|
+
}
|
|
262
|
+
async function chownAs(fs, cred, path, change) {
|
|
263
|
+
const { uid, gid, follow: follow2 } = change;
|
|
264
|
+
const st = follow2 ? await fs.stat(path) : await fs.lstat(path);
|
|
265
|
+
const current = { uid: st.uid ?? 0, gid: st.gid ?? 0 };
|
|
266
|
+
if (!fs.chown || !mayChown(cred, current, uid, gid)) throw fsError("EPERM", path);
|
|
267
|
+
const clear = st.isFile && (uid !== void 0 || gid !== void 0) ? clearedSetId(st.mode) : void 0;
|
|
268
|
+
await fs.chown(path, {
|
|
269
|
+
...uid !== void 0 ? { uid } : {},
|
|
270
|
+
...gid !== void 0 ? { gid } : {},
|
|
271
|
+
follow: follow2,
|
|
272
|
+
...clear !== void 0 && clear !== (st.mode & 4095) ? { mode: clear } : {}
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
|
|
219
276
|
// src/fs/opfs.ts
|
|
220
277
|
var S_IFDIR = 16384;
|
|
221
278
|
var S_IFREG = 32768;
|
|
222
279
|
var S_IFLNK = 40960;
|
|
223
280
|
var PERM_MASK = 4095;
|
|
281
|
+
var S_ISGID2 = 1024;
|
|
224
282
|
var READ_ATTEMPTS = 3;
|
|
225
283
|
var MAX_LINKS = 40;
|
|
226
284
|
var CHECK_MS = 1e3;
|
|
@@ -322,6 +380,7 @@ var OpfsFs = class {
|
|
|
322
380
|
checked = /* @__PURE__ */ new WeakMap();
|
|
323
381
|
channel;
|
|
324
382
|
ranged;
|
|
383
|
+
owners = false;
|
|
325
384
|
constructor(root, meta = new MemoryMeta(), channel, options = {}) {
|
|
326
385
|
this.root = root;
|
|
327
386
|
this.meta = meta;
|
|
@@ -341,6 +400,73 @@ var OpfsFs = class {
|
|
|
341
400
|
resolvePath(base, path) {
|
|
342
401
|
return resolvePath(base, path);
|
|
343
402
|
}
|
|
403
|
+
trackOwners() {
|
|
404
|
+
this.owners = true;
|
|
405
|
+
}
|
|
406
|
+
async handedTo(dir) {
|
|
407
|
+
return inherit(await this.meta.get(chain(dir)));
|
|
408
|
+
}
|
|
409
|
+
async ownerAt(path, entry) {
|
|
410
|
+
const own = ownOf(entry);
|
|
411
|
+
if (own) return own;
|
|
412
|
+
return path === "/" ? { ...ROOT_OWNER } : this.handedTo(parentOf2(path));
|
|
413
|
+
}
|
|
414
|
+
async owned(stat, path, entry) {
|
|
415
|
+
return this.owners ? { ...stat, ...await this.ownerAt(path, entry) } : stat;
|
|
416
|
+
}
|
|
417
|
+
async newFields(path, owner, directory) {
|
|
418
|
+
if (!this.owners || !owner) return void 0;
|
|
419
|
+
const entries = await this.meta.get(chain(path));
|
|
420
|
+
const self = entries.pop();
|
|
421
|
+
const parent = entries.at(-1);
|
|
422
|
+
const setgid = ((parent?.mode ?? 0) & S_ISGID2) !== 0;
|
|
423
|
+
const parentGid = (ownOf(parent) ?? inherit(entries.slice(0, -1))).gid;
|
|
424
|
+
const want = { uid: owner.uid, gid: setgid ? parentGid : owner.gid };
|
|
425
|
+
let mode = owner.mode === void 0 ? void 0 : owner.mode & PERM_MASK;
|
|
426
|
+
if (directory && setgid) mode = (mode ?? 493) | S_ISGID2;
|
|
427
|
+
const fields = {};
|
|
428
|
+
if (mode !== void 0 && mode !== (this.mode(path, directory, void 0) & PERM_MASK)) {
|
|
429
|
+
fields.mode = mode;
|
|
430
|
+
}
|
|
431
|
+
if (self) fields.heir = void 0;
|
|
432
|
+
if (ownOf(self) || !sameOwner(want, inherit(entries))) Object.assign(fields, want);
|
|
433
|
+
return Object.keys(fields).length > 0 ? fields : void 0;
|
|
434
|
+
}
|
|
435
|
+
async stampNew(path, owner, directory) {
|
|
436
|
+
const fields = await this.newFields(path, owner, directory);
|
|
437
|
+
if (fields) await this.meta.update(path, (entry) => ({ ...entry, path, ...fields }));
|
|
438
|
+
}
|
|
439
|
+
async chown(path, change) {
|
|
440
|
+
if (!this.owners) return;
|
|
441
|
+
if (change.kind === "new") {
|
|
442
|
+
const at = resolvePath((await this.locate(parentOf2(path), true)).path, baseOf(path));
|
|
443
|
+
const { uid = 0, gid = 0, mode } = change;
|
|
444
|
+
return this.stampNew(at, { uid, gid, ...mode !== void 0 ? { mode } : {} }, false);
|
|
445
|
+
}
|
|
446
|
+
const found = await this.locate(path, change.follow !== false);
|
|
447
|
+
const [stored] = found.link ? [found.link] : await this.meta.get([found.path]);
|
|
448
|
+
const current = await this.ownerAt(found.path, stored);
|
|
449
|
+
const next2 = { uid: change.uid ?? current.uid, gid: change.gid ?? current.gid };
|
|
450
|
+
const handing = found.handle?.kind === "directory" && !sameOwner(next2, current);
|
|
451
|
+
const heir = change.kind === "adopt" ? void 0 : stored?.heir ?? (handing ? [current.uid, current.gid] : void 0);
|
|
452
|
+
const ctimeMs = Date.now();
|
|
453
|
+
await this.meta.update(found.path, (entry) => {
|
|
454
|
+
const { heir: _, ...rest2 } = entry ?? found.link ?? { path: found.path };
|
|
455
|
+
return {
|
|
456
|
+
...rest2,
|
|
457
|
+
path: found.path,
|
|
458
|
+
...next2,
|
|
459
|
+
...heir ? { heir } : {},
|
|
460
|
+
...change.mode !== void 0 ? { mode: change.mode & PERM_MASK } : {},
|
|
461
|
+
ctimeMs
|
|
462
|
+
};
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
async movedOwner(source) {
|
|
466
|
+
if (!this.owners) return void 0;
|
|
467
|
+
const [stored] = source.link ? [source.link] : await this.meta.get([source.path]);
|
|
468
|
+
return ownOf(stored) ? void 0 : this.ownerAt(source.path, stored);
|
|
469
|
+
}
|
|
344
470
|
async walk(parts, from, start2) {
|
|
345
471
|
let dir = start2;
|
|
346
472
|
for (let at = from; at < parts.length; at++) {
|
|
@@ -533,9 +659,15 @@ var OpfsFs = class {
|
|
|
533
659
|
};
|
|
534
660
|
}
|
|
535
661
|
async describe(found) {
|
|
536
|
-
if (found.link) return this.linkStat(found.link);
|
|
537
|
-
|
|
538
|
-
|
|
662
|
+
if (found.link) return this.owned(this.linkStat(found.link), found.path, found.link);
|
|
663
|
+
if (!this.owners) {
|
|
664
|
+
const [meta2] = await this.meta.get([found.path]);
|
|
665
|
+
return this.statOf(found.path, found.handle, meta2);
|
|
666
|
+
}
|
|
667
|
+
const entries = await this.meta.get(chain(found.path));
|
|
668
|
+
const meta = entries.pop();
|
|
669
|
+
const stat = await this.statOf(found.path, found.handle, meta);
|
|
670
|
+
return { ...stat, ...ownOf(meta) ?? inherit(entries) };
|
|
539
671
|
}
|
|
540
672
|
async stat(path) {
|
|
541
673
|
return this.describe(await this.locate(path, true));
|
|
@@ -625,14 +757,15 @@ var OpfsFs = class {
|
|
|
625
757
|
(parent) => parent.getFileHandle(name2, { create: true })
|
|
626
758
|
);
|
|
627
759
|
if (!existed) this.touch(parentOf2(target));
|
|
628
|
-
return [handle, existed];
|
|
760
|
+
return [handle, existed, target];
|
|
629
761
|
} catch (err) {
|
|
630
762
|
const code = err?.name === "TypeMismatchError" ? "EISDIR" : null;
|
|
631
763
|
throw code ? fsError(code, path) : translate(err, path);
|
|
632
764
|
}
|
|
633
765
|
}
|
|
634
|
-
async writeFile(path, content) {
|
|
635
|
-
const [file, existed] = await this.fileFor(path);
|
|
766
|
+
async writeFile(path, content, owner) {
|
|
767
|
+
const [file, existed, target] = await this.fileFor(path);
|
|
768
|
+
if (!existed) await this.stampNew(target, owner, false);
|
|
636
769
|
if (!existed && content.length === 0) return;
|
|
637
770
|
const writable = await file.createWritable();
|
|
638
771
|
await writable.write(content);
|
|
@@ -657,11 +790,13 @@ var OpfsFs = class {
|
|
|
657
790
|
const [dir, children2] = await this.listing(path);
|
|
658
791
|
const base = dir === "/" ? "" : dir;
|
|
659
792
|
const metas = await this.meta.get(children2.map(([name2]) => `${base}/${name2}`));
|
|
793
|
+
const handed2 = this.owners ? await this.handedTo(dir) : void 0;
|
|
794
|
+
const owned = (stat, entry) => handed2 ? { ...stat, ...ownOf(entry) ?? handed2 } : stat;
|
|
660
795
|
return Promise.all(
|
|
661
796
|
children2.map(async ([name2, child], i) => {
|
|
662
|
-
if (!isHandle(child)) return [name2, this.linkStat(child)];
|
|
797
|
+
if (!isHandle(child)) return [name2, owned(this.linkStat(child), child)];
|
|
663
798
|
const stat = await this.statOf(`${base}/${name2}`, child, metas[i]).catch(() => null);
|
|
664
|
-
return [name2, stat];
|
|
799
|
+
return [name2, stat && owned(stat, metas[i])];
|
|
665
800
|
})
|
|
666
801
|
);
|
|
667
802
|
}
|
|
@@ -679,11 +814,22 @@ var OpfsFs = class {
|
|
|
679
814
|
}
|
|
680
815
|
const [entry] = await this.meta.get([path]);
|
|
681
816
|
if (entry?.link !== void 0) throw fsError("EEXIST", path);
|
|
682
|
-
|
|
817
|
+
const { owner } = options;
|
|
818
|
+
if (options.recursive) {
|
|
819
|
+
const mode = owner?.parents;
|
|
820
|
+
const above = owner && {
|
|
821
|
+
uid: owner.uid,
|
|
822
|
+
gid: owner.gid,
|
|
823
|
+
...mode ? { mode, parents: mode } : {}
|
|
824
|
+
};
|
|
825
|
+
await this.mkdir(parentOf2(path), { recursive: true, ...above ? { owner: above } : {} });
|
|
826
|
+
}
|
|
683
827
|
const parent = await this.locate(parentOf2(path), true);
|
|
684
828
|
if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
|
|
685
829
|
await parent.handle.getDirectoryHandle(baseOf(path), { create: true });
|
|
686
|
-
|
|
830
|
+
const made = `${parent.path === "/" ? "" : parent.path}/${baseOf(path)}`;
|
|
831
|
+
await this.stampNew(made, owner, true);
|
|
832
|
+
this.touch(parent.path, made);
|
|
687
833
|
}
|
|
688
834
|
async rm(path, options = {}) {
|
|
689
835
|
let found;
|
|
@@ -730,9 +876,11 @@ var OpfsFs = class {
|
|
|
730
876
|
throw fsError("ENOTEMPTY", to);
|
|
731
877
|
}
|
|
732
878
|
const now = Date.now();
|
|
879
|
+
const moving = await this.movedOwner(source);
|
|
733
880
|
const carry = (entry) => ({
|
|
734
881
|
ino: inodeOf(source.path),
|
|
735
882
|
...entry,
|
|
883
|
+
...moving,
|
|
736
884
|
path: destination,
|
|
737
885
|
ctimeMs: now
|
|
738
886
|
});
|
|
@@ -806,7 +954,7 @@ var OpfsFs = class {
|
|
|
806
954
|
const target = await dir.getDirectoryHandle(name2, { create: true });
|
|
807
955
|
for await (const child of handle.values()) await this.copy(child, target, child.name);
|
|
808
956
|
}
|
|
809
|
-
async symlink(target, path) {
|
|
957
|
+
async symlink(target, path, owner) {
|
|
810
958
|
const parent = await this.locate(parentOf2(path), true);
|
|
811
959
|
if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
|
|
812
960
|
const at = resolvePath(parent.path, baseOf(path));
|
|
@@ -817,13 +965,15 @@ var OpfsFs = class {
|
|
|
817
965
|
throw fsError("EEXIST", path);
|
|
818
966
|
}
|
|
819
967
|
const now = Date.now();
|
|
968
|
+
const fields = await this.newFields(at, owner && { uid: owner.uid, gid: owner.gid }, false);
|
|
820
969
|
await this.meta.update(at, () => ({
|
|
821
970
|
path: at,
|
|
822
971
|
link: target,
|
|
823
972
|
dir: parent.path,
|
|
824
973
|
ino: inodeOf(at),
|
|
825
974
|
mtimeMs: now,
|
|
826
|
-
ctimeMs: now
|
|
975
|
+
ctimeMs: now,
|
|
976
|
+
...fields
|
|
827
977
|
}));
|
|
828
978
|
this.touch(parent.path);
|
|
829
979
|
}
|
|
@@ -2467,12 +2617,30 @@ function userEnv(account, system) {
|
|
|
2467
2617
|
PATH: `${pnpm}/bin:/usr/local/bin:/usr/bin:/bin`
|
|
2468
2618
|
};
|
|
2469
2619
|
}
|
|
2620
|
+
function homeGroupOf(groups, name2) {
|
|
2621
|
+
if (name2 === void 0) return void 0;
|
|
2622
|
+
const found = groups.find((g) => g.name === name2);
|
|
2623
|
+
if (!found) throw fsError("ENOENT", `no group ${name2}`);
|
|
2624
|
+
return found;
|
|
2625
|
+
}
|
|
2470
2626
|
var UserDb = class {
|
|
2471
2627
|
fs;
|
|
2628
|
+
owners;
|
|
2472
2629
|
umasks = /* @__PURE__ */ new Map();
|
|
2473
2630
|
writing = Promise.resolve();
|
|
2474
|
-
constructor(fs) {
|
|
2631
|
+
constructor(fs, owners = false) {
|
|
2475
2632
|
this.fs = fs;
|
|
2633
|
+
this.owners = owners;
|
|
2634
|
+
}
|
|
2635
|
+
async stampHome(row, shared) {
|
|
2636
|
+
const home = this.fs.resolvePath("/", row.home);
|
|
2637
|
+
if (!this.owners || !this.fs.chown || !HOME_DIR.test(home)) return;
|
|
2638
|
+
if (await this.fs.realpath?.(home, false).catch(() => void 0) !== home) return;
|
|
2639
|
+
if (!(await this.fs.lstat(home)).isDirectory) return;
|
|
2640
|
+
const gid = shared?.gid ?? row.gid;
|
|
2641
|
+
await this.fs.chown(home, { uid: row.uid, gid, follow: false, kind: "adopt" });
|
|
2642
|
+
const mode = shared ? 1512 : row.name.startsWith("scoop-") ? 488 : 448;
|
|
2643
|
+
await this.fs.chmod(home, mode);
|
|
2476
2644
|
}
|
|
2477
2645
|
async read(path, fallback) {
|
|
2478
2646
|
try {
|
|
@@ -2572,8 +2740,12 @@ var UserDb = class {
|
|
|
2572
2740
|
const users = parsed(passwd);
|
|
2573
2741
|
const groups = parsed(group);
|
|
2574
2742
|
const found = users.find((r) => r.name === name2);
|
|
2743
|
+
const shared = homeGroupOf(groups, options.homeGroup);
|
|
2575
2744
|
if (found) {
|
|
2576
|
-
if (found.uid >= FIRST_UID && found.uid <= LAST_UID)
|
|
2745
|
+
if (found.uid >= FIRST_UID && found.uid <= LAST_UID) {
|
|
2746
|
+
await this.provision(found);
|
|
2747
|
+
await this.stampHome(found, shared);
|
|
2748
|
+
}
|
|
2577
2749
|
remember();
|
|
2578
2750
|
return this.account(found, groups);
|
|
2579
2751
|
}
|
|
@@ -2593,6 +2765,7 @@ var UserDb = class {
|
|
|
2593
2765
|
await this.fs.mkdir(home, { recursive: true });
|
|
2594
2766
|
try {
|
|
2595
2767
|
await this.provision(row);
|
|
2768
|
+
await this.stampHome(row, shared);
|
|
2596
2769
|
await this.fs.mkdir("/etc", { recursive: true });
|
|
2597
2770
|
await this.commit(formatPasswd(passwd), formatGroup(group));
|
|
2598
2771
|
} catch (err) {
|
|
@@ -2661,7 +2834,7 @@ async function realpath(fs, path) {
|
|
|
2661
2834
|
}
|
|
2662
2835
|
return resolved || "/";
|
|
2663
2836
|
}
|
|
2664
|
-
async function fsCall(fs, method, args) {
|
|
2837
|
+
async function fsCall(fs, method, args, owner) {
|
|
2665
2838
|
const path = (i) => fs.resolvePath("/", String(args[i]));
|
|
2666
2839
|
switch (method) {
|
|
2667
2840
|
case "readFile": {
|
|
@@ -2669,7 +2842,7 @@ async function fsCall(fs, method, args) {
|
|
|
2669
2842
|
return { result: bytes, transfer: [bytes.buffer] };
|
|
2670
2843
|
}
|
|
2671
2844
|
case "writeFile":
|
|
2672
|
-
await fs.writeFile(path(0), args[1]);
|
|
2845
|
+
await fs.writeFile(path(0), args[1], owner);
|
|
2673
2846
|
return { result: true };
|
|
2674
2847
|
case "stat":
|
|
2675
2848
|
return { result: await fs.stat(path(0)) };
|
|
@@ -2678,7 +2851,7 @@ async function fsCall(fs, method, args) {
|
|
|
2678
2851
|
case "readdir":
|
|
2679
2852
|
return { result: await fs.readdir(path(0)) };
|
|
2680
2853
|
case "mkdir":
|
|
2681
|
-
await fs.mkdir(path(0), { recursive: true });
|
|
2854
|
+
await fs.mkdir(path(0), owner ? { recursive: true, owner } : { recursive: true });
|
|
2682
2855
|
return { result: true };
|
|
2683
2856
|
case "rm":
|
|
2684
2857
|
await fs.rm(path(0), { recursive: true, force: args[1] === true });
|
|
@@ -2689,7 +2862,7 @@ async function fsCall(fs, method, args) {
|
|
|
2689
2862
|
case "realpath":
|
|
2690
2863
|
return { result: await realpath(fs, String(args[0])) };
|
|
2691
2864
|
case "symlink":
|
|
2692
|
-
await fs.symlink(String(args[0]), path(1));
|
|
2865
|
+
await fs.symlink(String(args[0]), path(1), owner);
|
|
2693
2866
|
return { result: true };
|
|
2694
2867
|
case "readlink":
|
|
2695
2868
|
return { result: await fs.readlink(path(0)) };
|
|
@@ -2711,6 +2884,9 @@ function dialFor(l, req, open) {
|
|
|
2711
2884
|
);
|
|
2712
2885
|
return { result: port2, transfer: [port2] };
|
|
2713
2886
|
}
|
|
2887
|
+
function ownerFor(l, self) {
|
|
2888
|
+
return l.owners && self ? { uid: self.uid, gid: self.gid } : void 0;
|
|
2889
|
+
}
|
|
2714
2890
|
async function accountOf(l, user) {
|
|
2715
2891
|
const found = await l.users.lookup(user);
|
|
2716
2892
|
if (!found) throw fsError("ENOENT", `no user ${String(user)}`);
|
|
@@ -2838,6 +3014,7 @@ function serveClient(port, host) {
|
|
|
2838
3014
|
hello: {
|
|
2839
3015
|
protocol: PROTOCOL,
|
|
2840
3016
|
traits: transport.traits,
|
|
3017
|
+
...launcher.usersMode ? { users: launcher.usersMode } : {},
|
|
2841
3018
|
...host.lock ? { lock: host.lock } : {}
|
|
2842
3019
|
}
|
|
2843
3020
|
});
|
|
@@ -2903,7 +3080,7 @@ function serveClient(port, host) {
|
|
|
2903
3080
|
if (!FS_METHODS.includes(req.method)) {
|
|
2904
3081
|
throw new Error(`unknown file system call ${req.method}`);
|
|
2905
3082
|
}
|
|
2906
|
-
return fsCall(l.fs, req.method, req.args);
|
|
3083
|
+
return fsCall(l.fs, req.method, req.args, ownerFor(l, self));
|
|
2907
3084
|
case "watch":
|
|
2908
3085
|
case "unwatch":
|
|
2909
3086
|
return watchOp(l, req, watches, send);
|
|
@@ -3926,10 +4103,10 @@ var RealmProxy = class {
|
|
|
3926
4103
|
}
|
|
3927
4104
|
async bridge(ctx, socket, hangup) {
|
|
3928
4105
|
const stop = this.stop.signal;
|
|
3929
|
-
let
|
|
4106
|
+
let chain2 = Promise.resolve();
|
|
3930
4107
|
const toGuest = (bytes) => {
|
|
3931
|
-
|
|
3932
|
-
return
|
|
4108
|
+
chain2 = chain2.then(() => ctx.sink.write(bytes, stop));
|
|
4109
|
+
return chain2;
|
|
3933
4110
|
};
|
|
3934
4111
|
const done4 = new AbortController();
|
|
3935
4112
|
const reading = AbortSignal.any([stop, done4.signal, hangup]);
|
|
@@ -5636,7 +5813,7 @@ function withCommandDirs(fs, names, userDir = async () => void 0) {
|
|
|
5636
5813
|
throw err;
|
|
5637
5814
|
}
|
|
5638
5815
|
},
|
|
5639
|
-
writeFile: (path, content) => fs.writeFile(path, content),
|
|
5816
|
+
writeFile: (path, content, owner) => fs.writeFile(path, content, owner),
|
|
5640
5817
|
async exists(path) {
|
|
5641
5818
|
return await fs.exists(path) || await linked(path) !== void 0;
|
|
5642
5819
|
},
|
|
@@ -5674,9 +5851,10 @@ function withCommandDirs(fs, names, userDir = async () => void 0) {
|
|
|
5674
5851
|
mkdir: (path, options) => fs.mkdir(path, options),
|
|
5675
5852
|
rm: (path, options) => fs.rm(path, options),
|
|
5676
5853
|
rename: (from, to) => fs.rename(from, to),
|
|
5677
|
-
symlink: (target, path) => fs.symlink(target, path),
|
|
5854
|
+
symlink: (target, path, owner) => fs.symlink(target, path, owner),
|
|
5678
5855
|
readlink: (path) => fs.readlink(path),
|
|
5679
5856
|
...fs.realpath ? { realpath: fs.realpath.bind(fs) } : {},
|
|
5857
|
+
...fs.chown ? { chown: fs.chown.bind(fs) } : {},
|
|
5680
5858
|
chmod: (path, mode) => fs.chmod(path, mode),
|
|
5681
5859
|
utimes: (path, atime, mtime) => fs.utimes(path, atime, mtime),
|
|
5682
5860
|
lutimes: (path, atime, mtime) => lutimesOf(fs, path, atime, mtime),
|
|
@@ -5993,6 +6171,7 @@ var FsWatchers = class {
|
|
|
5993
6171
|
rename: after(fs.rename.bind(fs), (from, to) => [from, to]),
|
|
5994
6172
|
symlink: after(fs.symlink.bind(fs), (_target, path) => [path]),
|
|
5995
6173
|
chmod: after(fs.chmod.bind(fs), (path) => [path]),
|
|
6174
|
+
...fs.chown ? { chown: after(fs.chown.bind(fs), (path) => [path]) } : {},
|
|
5996
6175
|
utimes: after(fs.utimes.bind(fs), (path) => [path]),
|
|
5997
6176
|
lutimes: after(
|
|
5998
6177
|
(path, atime, mtime) => lutimesOf(fs, path, atime, mtime),
|
|
@@ -6064,13 +6243,13 @@ var ChildTable = class {
|
|
|
6064
6243
|
if (!this.forker) throw new SpawnError("ENOSYS");
|
|
6065
6244
|
return this.track(state, this.parentFds.fork(), /* @__PURE__ */ new Map(), this.forker);
|
|
6066
6245
|
}
|
|
6067
|
-
async spawn(req, stdio,
|
|
6246
|
+
async spawn(req, stdio, inherit2 = []) {
|
|
6068
6247
|
if (!this.spawner) throw new SpawnError("ENOSYS");
|
|
6069
6248
|
const fds = new FdTable();
|
|
6070
6249
|
const captured = /* @__PURE__ */ new Map();
|
|
6071
6250
|
try {
|
|
6072
6251
|
for (const [n, slot] of stdio.entries()) fds.installAt(n, this.openSlot(slot, n, captured));
|
|
6073
|
-
for (const slot of
|
|
6252
|
+
for (const slot of inherit2) {
|
|
6074
6253
|
if (slot.fd <= 2) continue;
|
|
6075
6254
|
if ("device" in slot) {
|
|
6076
6255
|
fds.installAt(slot.fd, deviceFile(slot.device, slot.access));
|
|
@@ -6151,8 +6330,8 @@ var ChildTable = class {
|
|
|
6151
6330
|
candidates(pid, flags) {
|
|
6152
6331
|
const all = [...this.children];
|
|
6153
6332
|
if (pid > 0) return all.filter(([p]) => p === pid);
|
|
6154
|
-
const
|
|
6155
|
-
return pid === -1 || !
|
|
6333
|
+
const inGroup2 = flags.inGroup;
|
|
6334
|
+
return pid === -1 || !inGroup2 ? all : all.filter(([p]) => inGroup2(p));
|
|
6156
6335
|
}
|
|
6157
6336
|
async nextChange(candidates, flags, interrupt) {
|
|
6158
6337
|
let wake;
|
|
@@ -6873,10 +7052,10 @@ var MountFs = class {
|
|
|
6873
7052
|
}
|
|
6874
7053
|
return concat4(chunks, total);
|
|
6875
7054
|
}
|
|
6876
|
-
async writeFile(path, content) {
|
|
7055
|
+
async writeFile(path, content, owner) {
|
|
6877
7056
|
const real = await this.follow(path, 0, true);
|
|
6878
7057
|
const found = this.at(real);
|
|
6879
|
-
if (!found) return this.base.writeFile(real, content);
|
|
7058
|
+
if (!found) return this.base.writeFile(real, content, owner);
|
|
6880
7059
|
const { mount, rel: rel2 } = found;
|
|
6881
7060
|
this.writable(mount, real);
|
|
6882
7061
|
const bytes = typeof content === "string" ? new TextEncoder().encode(content) : content;
|
|
@@ -7143,9 +7322,9 @@ var MountFs = class {
|
|
|
7143
7322
|
this.table.forget(a.mount, normalizePath(to));
|
|
7144
7323
|
}
|
|
7145
7324
|
}
|
|
7146
|
-
async symlink(target, path) {
|
|
7325
|
+
async symlink(target, path, owner) {
|
|
7147
7326
|
const found = this.at(path);
|
|
7148
|
-
if (!found) return this.base.symlink(target, path);
|
|
7327
|
+
if (!found) return this.base.symlink(target, path, owner);
|
|
7149
7328
|
this.writable(found.mount, normalizePath(path));
|
|
7150
7329
|
if (!found.mount.caps.symlinks)
|
|
7151
7330
|
throw errnoError("EPERM", `${path}: this file system has no symlinks`);
|
|
@@ -7163,6 +7342,15 @@ var MountFs = class {
|
|
|
7163
7342
|
if (!found) return this.base.readlink(path);
|
|
7164
7343
|
return await found.mount.conn.call({ op: "readlink", path: found.rel });
|
|
7165
7344
|
}
|
|
7345
|
+
async chown(path, change) {
|
|
7346
|
+
const real = change.follow === false || change.kind === "new" ? path : await this.follow(path);
|
|
7347
|
+
if (this.at(real)) {
|
|
7348
|
+
if (change.kind === "new") return;
|
|
7349
|
+
throw errnoError("EPERM", `${path}: this file system keeps no owners`);
|
|
7350
|
+
}
|
|
7351
|
+
if (!this.base.chown) throw errnoError("EPERM", path);
|
|
7352
|
+
return this.base.chown(real, change);
|
|
7353
|
+
}
|
|
7166
7354
|
async chmod(path, mode) {
|
|
7167
7355
|
const found = this.at(path);
|
|
7168
7356
|
if (!found) return this.base.chmod(path, mode);
|
|
@@ -7237,7 +7425,9 @@ function statJson(s) {
|
|
|
7237
7425
|
...s.readonly ? { readonly: true } : {},
|
|
7238
7426
|
...s.maxFile ? { maxFile: s.maxFile } : {},
|
|
7239
7427
|
...s.ranged ? { ranged: true } : {},
|
|
7240
|
-
...s.version !== void 0 ? { version: s.version } : {}
|
|
7428
|
+
...s.version !== void 0 ? { version: s.version } : {},
|
|
7429
|
+
...s.uid !== void 0 ? { uid: s.uid } : {},
|
|
7430
|
+
...s.gid !== void 0 ? { gid: s.gid } : {}
|
|
7241
7431
|
};
|
|
7242
7432
|
}
|
|
7243
7433
|
async function readdirStat(fs, dir) {
|
|
@@ -7252,13 +7442,34 @@ var done = { ok: true, kind: "void" };
|
|
|
7252
7442
|
function json2(value) {
|
|
7253
7443
|
return { ok: true, kind: "json", json: value };
|
|
7254
7444
|
}
|
|
7445
|
+
function ownerFor2(entry, mode) {
|
|
7446
|
+
const cred = entry.cred?.();
|
|
7447
|
+
if (!cred) return void 0;
|
|
7448
|
+
return ownerOf(cred, mode === void 0 ? void 0 : mode & ~(entry.umask?.() ?? 18));
|
|
7449
|
+
}
|
|
7450
|
+
function mkdirOptions(entry, mode = 511) {
|
|
7451
|
+
const owner = ownerFor2(entry, mode);
|
|
7452
|
+
if (!owner) return { recursive: true };
|
|
7453
|
+
const parents = 511 & ~(entry.umask?.() ?? 18) | 192;
|
|
7454
|
+
return { recursive: true, owner: { ...owner, parents } };
|
|
7455
|
+
}
|
|
7456
|
+
async function chown(entry, path, req) {
|
|
7457
|
+
const cred = entry.cred?.();
|
|
7458
|
+
if (!cred) return done;
|
|
7459
|
+
await chownAs(entry.fs, cred, path, {
|
|
7460
|
+
...req.uid !== void 0 ? { uid: req.uid } : {},
|
|
7461
|
+
...req.gid !== void 0 ? { gid: req.gid } : {},
|
|
7462
|
+
follow: req.op === "chown"
|
|
7463
|
+
});
|
|
7464
|
+
return done;
|
|
7465
|
+
}
|
|
7255
7466
|
async function run(entry, path, req) {
|
|
7256
7467
|
const { fs, cwd } = entry;
|
|
7257
7468
|
switch (req.op) {
|
|
7258
7469
|
case "read":
|
|
7259
7470
|
return { ok: true, kind: "bytes", bytes: await fs.readFileBuffer(path) };
|
|
7260
7471
|
case "write":
|
|
7261
|
-
await fs.writeFile(path, req.body ?? new Uint8Array(0));
|
|
7472
|
+
await fs.writeFile(path, req.body ?? new Uint8Array(0), ownerFor2(entry, 438));
|
|
7262
7473
|
return done;
|
|
7263
7474
|
case "exists":
|
|
7264
7475
|
return json2(await fs.exists(path));
|
|
@@ -7271,7 +7482,7 @@ async function run(entry, path, req) {
|
|
|
7271
7482
|
case "readdir-stat":
|
|
7272
7483
|
return json2(await readdirStat(fs, path));
|
|
7273
7484
|
case "mkdir":
|
|
7274
|
-
await fs.mkdir(path,
|
|
7485
|
+
await fs.mkdir(path, mkdirOptions(entry, req.mode));
|
|
7275
7486
|
return done;
|
|
7276
7487
|
case "rm":
|
|
7277
7488
|
await fs.rm(path, { recursive: true });
|
|
@@ -7292,10 +7503,10 @@ async function run(entry, path, req) {
|
|
|
7292
7503
|
await fs.rm(path, { recursive: true });
|
|
7293
7504
|
return done;
|
|
7294
7505
|
case "symlink":
|
|
7295
|
-
await fs.symlink(req.arg2 ?? "", path);
|
|
7506
|
+
await fs.symlink(req.arg2 ?? "", path, ownerFor2(entry));
|
|
7296
7507
|
return done;
|
|
7297
7508
|
case "create":
|
|
7298
|
-
await createExclusive(fs, path);
|
|
7509
|
+
await createExclusive(fs, path, ownerFor2(entry, req.mode ?? 438));
|
|
7299
7510
|
return done;
|
|
7300
7511
|
case "readlink":
|
|
7301
7512
|
return json2(await fs.readlink(path));
|
|
@@ -7308,6 +7519,9 @@ async function run(entry, path, req) {
|
|
|
7308
7519
|
case "lutimes":
|
|
7309
7520
|
await lutimesOf(fs, path, new Date(req.atimeMs ?? 0), new Date(req.mtimeMs ?? 0));
|
|
7310
7521
|
return done;
|
|
7522
|
+
case "chown":
|
|
7523
|
+
case "lchown":
|
|
7524
|
+
return chown(entry, path, req);
|
|
7311
7525
|
case "pread":
|
|
7312
7526
|
case "pwrite":
|
|
7313
7527
|
case "truncate":
|
|
@@ -7316,14 +7530,14 @@ async function run(entry, path, req) {
|
|
|
7316
7530
|
return { ok: false, errno: "EINVAL", message: `sync-fs: unknown op '${req.op}'` };
|
|
7317
7531
|
}
|
|
7318
7532
|
}
|
|
7319
|
-
async function createExclusive(fs, path) {
|
|
7320
|
-
if (fs.createExclusive) return fs.createExclusive(path);
|
|
7533
|
+
async function createExclusive(fs, path, owner) {
|
|
7534
|
+
if (fs.createExclusive) return fs.createExclusive(path, owner);
|
|
7321
7535
|
if (await fs.lstat(path).then(
|
|
7322
7536
|
() => true,
|
|
7323
7537
|
() => false
|
|
7324
7538
|
))
|
|
7325
7539
|
throw syncError("EEXIST", path);
|
|
7326
|
-
await fs.writeFile(path, new Uint8Array(0));
|
|
7540
|
+
await fs.writeFile(path, new Uint8Array(0), owner);
|
|
7327
7541
|
}
|
|
7328
7542
|
async function ranged(fs, path, req) {
|
|
7329
7543
|
const ops = rangedOps(fs);
|
|
@@ -7945,6 +8159,10 @@ function normalize(path) {
|
|
|
7945
8159
|
}
|
|
7946
8160
|
return `/${out.join("/")}`;
|
|
7947
8161
|
}
|
|
8162
|
+
var RING = 8;
|
|
8163
|
+
var RING_SIZE = 64;
|
|
8164
|
+
var SLOT = 3;
|
|
8165
|
+
var SHARED_IDS_BYTES = (RING + RING_SIZE * SLOT) * 4;
|
|
7948
8166
|
|
|
7949
8167
|
// src/process/wasi/wasi-procfs.ts
|
|
7950
8168
|
var DIR_MODE = 16749;
|
|
@@ -9518,12 +9736,12 @@ var VfsNodes = class {
|
|
|
9518
9736
|
}
|
|
9519
9737
|
return walk();
|
|
9520
9738
|
}
|
|
9521
|
-
createExclusive(path) {
|
|
9739
|
+
createExclusive(path, owner) {
|
|
9522
9740
|
return this.onEntry(path, async () => {
|
|
9523
9741
|
const node = this.byPath.get(path);
|
|
9524
9742
|
const held = node ? await node.serial(async () => node.holds()) : false;
|
|
9525
9743
|
if (held || await present(this.fs, path)) throw fsError("EEXIST", path);
|
|
9526
|
-
await this.fs.writeFile(path, new Uint8Array(0));
|
|
9744
|
+
await this.fs.writeFile(path, new Uint8Array(0), owner);
|
|
9527
9745
|
});
|
|
9528
9746
|
}
|
|
9529
9747
|
open(path, pin, writable = false) {
|
|
@@ -9740,9 +9958,9 @@ function keepingOpen(fs, nodes) {
|
|
|
9740
9958
|
nodes.renamed(a, b);
|
|
9741
9959
|
});
|
|
9742
9960
|
},
|
|
9743
|
-
writeFile: (path, content) => nodes.onEntry(fs.resolvePath("/", path), () => fs.writeFile(path, content)),
|
|
9744
|
-
createExclusive: async (path) => nodes.createExclusive(await nodes.entryKey(fs.resolvePath("/", path))),
|
|
9745
|
-
symlink: (target, path) => nodes.onEntry(fs.resolvePath("/", path), () => fs.symlink(target, path)),
|
|
9961
|
+
writeFile: (path, content, owner) => nodes.onEntry(fs.resolvePath("/", path), () => fs.writeFile(path, content, owner)),
|
|
9962
|
+
createExclusive: async (path, owner) => nodes.createExclusive(await nodes.entryKey(fs.resolvePath("/", path)), owner),
|
|
9963
|
+
symlink: (target, path, owner) => nodes.onEntry(fs.resolvePath("/", path), () => fs.symlink(target, path, owner)),
|
|
9746
9964
|
mkdir: (path, options) => nodes.onEntry(fs.resolvePath("/", path), () => fs.mkdir(path, options))
|
|
9747
9965
|
};
|
|
9748
9966
|
}
|
|
@@ -10013,9 +10231,9 @@ var WasmProcess = class {
|
|
|
10013
10231
|
return "deliver";
|
|
10014
10232
|
}
|
|
10015
10233
|
async spawn(req) {
|
|
10016
|
-
const { file, argv, env, cwd, stdio, inherit, exec } = req;
|
|
10234
|
+
const { file, argv, env, cwd, stdio, inherit: inherit2, exec } = req;
|
|
10017
10235
|
const spawned = { file, argv, env, cwd, ...exec ? { exec } : {} };
|
|
10018
|
-
const pid = await this.children.spawn(spawned, stdio,
|
|
10236
|
+
const pid = await this.children.spawn(spawned, stdio, inherit2);
|
|
10019
10237
|
if (!exec) return pid;
|
|
10020
10238
|
if (this.killed) void Promise.allSettled([this.options.kill?.(pid, SIG.KILL)]);
|
|
10021
10239
|
else this.adoptExec(pid);
|
|
@@ -10180,12 +10398,14 @@ var WasmProcess = class {
|
|
|
10180
10398
|
}
|
|
10181
10399
|
const open = { ...req, path };
|
|
10182
10400
|
if (req.exclusive) {
|
|
10183
|
-
await nodes.createExclusive(path);
|
|
10401
|
+
await nodes.createExclusive(path, this.newOwner());
|
|
10184
10402
|
this.fds.installAt(fd, this.openVfsFile(open));
|
|
10185
10403
|
} else if (req.create) {
|
|
10186
10404
|
await nodes.onEntry(path, async () => {
|
|
10405
|
+
const fresh = this.options.owners && !await present(this.options.fs, path, true);
|
|
10187
10406
|
this.fds.installAt(fd, this.openVfsFile(open));
|
|
10188
10407
|
await this.fds.get(fd).file.stat?.();
|
|
10408
|
+
if (fresh) await this.options.fs.chown?.(path, { ...this.newOwner(), kind: "new" });
|
|
10189
10409
|
});
|
|
10190
10410
|
} else {
|
|
10191
10411
|
this.fds.installAt(fd, this.openVfsFile(open));
|
|
@@ -10199,6 +10419,10 @@ var WasmProcess = class {
|
|
|
10199
10419
|
}
|
|
10200
10420
|
return fd;
|
|
10201
10421
|
}
|
|
10422
|
+
newOwner() {
|
|
10423
|
+
if (!this.options.owners) return void 0;
|
|
10424
|
+
return { uid: this.cred.euid, gid: this.cred.egid, mode: 438 & ~this.umask };
|
|
10425
|
+
}
|
|
10202
10426
|
async openProc(req, path) {
|
|
10203
10427
|
return this.fds.install(await this.procFile(req, path), 3);
|
|
10204
10428
|
}
|
|
@@ -10845,6 +11069,7 @@ function processInit(opts, sab, umask, cred, lane) {
|
|
|
10845
11069
|
sab,
|
|
10846
11070
|
umask,
|
|
10847
11071
|
cred,
|
|
11072
|
+
...opts.owners ? { owners: true } : {},
|
|
10848
11073
|
...opts.ppid !== void 0 ? { ppid: opts.ppid } : {}
|
|
10849
11074
|
};
|
|
10850
11075
|
if (opts.program.abi === "js") {
|
|
@@ -10868,8 +11093,9 @@ function inherited(opts) {
|
|
|
10868
11093
|
...opts.cred ? { cred: opts.cred } : {}
|
|
10869
11094
|
};
|
|
10870
11095
|
}
|
|
10871
|
-
function holdingToken(opts, holds) {
|
|
11096
|
+
function holdingToken(opts, holds, caller) {
|
|
10872
11097
|
return mintSyncFsToken({
|
|
11098
|
+
...opts.owners ? caller : {},
|
|
10873
11099
|
fs: opts.fs,
|
|
10874
11100
|
cwd: opts.cwd,
|
|
10875
11101
|
...opts.statfs ? { statfs: opts.statfs } : {},
|
|
@@ -10885,6 +11111,7 @@ function holdingToken(opts, holds) {
|
|
|
10885
11111
|
function processOptions(opts, header3, hooks) {
|
|
10886
11112
|
return {
|
|
10887
11113
|
...inherited(opts),
|
|
11114
|
+
...opts.owners ? { owners: true } : {},
|
|
10888
11115
|
...opts.identity ? { identity: opts.identity } : {},
|
|
10889
11116
|
...opts.onSyscall ? { onSyscall: opts.onSyscall } : {},
|
|
10890
11117
|
...opts.settling ? { settling: opts.settling } : {},
|
|
@@ -10929,7 +11156,10 @@ function spawnWasmProcess(opts) {
|
|
|
10929
11156
|
publishStops(process, header3);
|
|
10930
11157
|
const holds = new HeldPaths();
|
|
10931
11158
|
opts.held?.add(holds);
|
|
10932
|
-
const token = holdingToken(opts, holds
|
|
11159
|
+
const token = holdingToken(opts, holds, {
|
|
11160
|
+
cred: () => process.cred,
|
|
11161
|
+
umask: () => process.umask
|
|
11162
|
+
});
|
|
10933
11163
|
process.keptPath = (path) => holds.keptAt(path)?.hidden;
|
|
10934
11164
|
process.keptHandle = (handle2) => holds.keptFor(handle2)?.hidden;
|
|
10935
11165
|
const worker = opts.createWorker();
|
|
@@ -11290,26 +11520,26 @@ function replayingHops(inner, heldMs = HELD_MS) {
|
|
|
11290
11520
|
void entry.final.cancel().catch(() => void 0);
|
|
11291
11521
|
};
|
|
11292
11522
|
const keyOf2 = (owner, method, url) => `${owner} ${method} ${url}`;
|
|
11293
|
-
const hold = (key,
|
|
11523
|
+
const hold = (key, chain2) => {
|
|
11294
11524
|
drop(key);
|
|
11295
|
-
const mine = [...held.keys()].filter((k) => held.get(k)?.owner ===
|
|
11525
|
+
const mine = [...held.keys()].filter((k) => held.get(k)?.owner === chain2.owner);
|
|
11296
11526
|
if (mine.length >= HELD_PER_OWNER) drop(mine[0]);
|
|
11297
11527
|
if (held.size >= HELD_MAX) drop(held.keys().next().value);
|
|
11298
11528
|
const timer = setTimeout(() => drop(key), heldMs);
|
|
11299
11529
|
timer.unref?.();
|
|
11300
|
-
held.set(key, { ...
|
|
11530
|
+
held.set(key, { ...chain2, timer });
|
|
11301
11531
|
};
|
|
11302
|
-
const replay = (
|
|
11303
|
-
const [hop, ...rest2] =
|
|
11532
|
+
const replay = (chain2) => {
|
|
11533
|
+
const [hop, ...rest2] = chain2.hops;
|
|
11304
11534
|
const location = hop && header2(hop.headers, "location");
|
|
11305
|
-
if (!hop || location === void 0) return
|
|
11535
|
+
if (!hop || location === void 0) return chain2.final;
|
|
11306
11536
|
const target = new URL(location, hop.url);
|
|
11307
11537
|
target.hash = "";
|
|
11308
|
-
const method = followedWith(hop.status,
|
|
11538
|
+
const method = followedWith(hop.status, chain2.method);
|
|
11309
11539
|
const away = target.origin !== new URL(hop.url).origin;
|
|
11310
|
-
const print = away ? unauthorized(
|
|
11311
|
-
hold(keyOf2(
|
|
11312
|
-
...
|
|
11540
|
+
const print = away ? unauthorized(chain2.fingerprint) : chain2.fingerprint;
|
|
11541
|
+
hold(keyOf2(chain2.owner, method, target.href), {
|
|
11542
|
+
...chain2,
|
|
11313
11543
|
method,
|
|
11314
11544
|
fingerprint: print,
|
|
11315
11545
|
hops: rest2
|
|
@@ -12898,6 +13128,11 @@ var DECIDE_MS = 100;
|
|
|
12898
13128
|
var INIT_PID = 1;
|
|
12899
13129
|
var SHARED_DIRS = ["/tmp", "/home"];
|
|
12900
13130
|
var encoder3 = new TextEncoder();
|
|
13131
|
+
var USERS_MODES = ["off", "report", "enforce"];
|
|
13132
|
+
function usersMode(mode = "off") {
|
|
13133
|
+
if (USERS_MODES.includes(mode)) return mode;
|
|
13134
|
+
throw new Error(`users must be 'off', 'report' or 'enforce', not ${String(mode)}`);
|
|
13135
|
+
}
|
|
12901
13136
|
function baseName(path) {
|
|
12902
13137
|
return path.slice(path.lastIndexOf("/") + 1);
|
|
12903
13138
|
}
|
|
@@ -13025,10 +13260,13 @@ var Launcher = class {
|
|
|
13025
13260
|
processMounts;
|
|
13026
13261
|
booting = new AbortController();
|
|
13027
13262
|
fstab = Promise.resolve([]);
|
|
13263
|
+
usersMode;
|
|
13028
13264
|
nextPid = 1e3;
|
|
13029
13265
|
boot = Date.now();
|
|
13030
13266
|
terminals = 0;
|
|
13031
13267
|
constructor(options) {
|
|
13268
|
+
this.usersMode = usersMode(options.users);
|
|
13269
|
+
if (this.owners) options.fs.trackOwners?.();
|
|
13032
13270
|
this.mounts = new MountTable({
|
|
13033
13271
|
open: (type, spec) => this.driver(type, spec),
|
|
13034
13272
|
busy: (target) => [...this.openFiles].some((nodes) => nodes.holds(target)) || heldUnder(this.held, target),
|
|
@@ -13082,7 +13320,7 @@ var Launcher = class {
|
|
|
13082
13320
|
}
|
|
13083
13321
|
);
|
|
13084
13322
|
this.fs = this.unlinked.wrap(keepingOpen(fs, this.nodes));
|
|
13085
|
-
this.users = new UserDb(this.fs);
|
|
13323
|
+
this.users = new UserDb(this.fs, this.owners);
|
|
13086
13324
|
void this.unlinked.sweep("/");
|
|
13087
13325
|
this.watchers.watch(
|
|
13088
13326
|
[this.modulesDir, this.pnpmHome],
|
|
@@ -13094,6 +13332,9 @@ var Launcher = class {
|
|
|
13094
13332
|
this.resetCatalogs();
|
|
13095
13333
|
});
|
|
13096
13334
|
}
|
|
13335
|
+
get owners() {
|
|
13336
|
+
return this.usersMode !== "off";
|
|
13337
|
+
}
|
|
13097
13338
|
setRoutes(table) {
|
|
13098
13339
|
this.routes.set(table);
|
|
13099
13340
|
}
|
|
@@ -13352,6 +13593,7 @@ var Launcher = class {
|
|
|
13352
13593
|
...req.ignored ? { ignored: req.ignored } : {},
|
|
13353
13594
|
...req.umask !== void 0 ? { umask: req.umask } : {},
|
|
13354
13595
|
cred: req.cred,
|
|
13596
|
+
...this.owners ? { owners: true } : {},
|
|
13355
13597
|
program: req.program,
|
|
13356
13598
|
argv0: req.argv0,
|
|
13357
13599
|
args: req.args,
|
|
@@ -13930,6 +14172,12 @@ function usersOp(l, req) {
|
|
|
13930
14172
|
if (req.op === "users-remove") return l.users.remove(req.name, req.options);
|
|
13931
14173
|
return l.users.list();
|
|
13932
14174
|
}
|
|
14175
|
+
function hostOptions(req) {
|
|
14176
|
+
return {
|
|
14177
|
+
...req.hostname !== void 0 ? { hostname: req.hostname } : {},
|
|
14178
|
+
...req.users !== void 0 ? { users: req.users } : {}
|
|
14179
|
+
};
|
|
14180
|
+
}
|
|
13933
14181
|
function serveKernel(port, deps) {
|
|
13934
14182
|
let launcher;
|
|
13935
14183
|
let remote;
|
|
@@ -14004,7 +14252,7 @@ function serveKernel(port, deps) {
|
|
|
14004
14252
|
...deps.createDriverWorker ? { createDriverWorker: deps.createDriverWorker } : {},
|
|
14005
14253
|
...req.modules ? { modules: req.modules } : {},
|
|
14006
14254
|
...req.env ? { env: req.env } : {},
|
|
14007
|
-
...req
|
|
14255
|
+
...hostOptions(req),
|
|
14008
14256
|
...net,
|
|
14009
14257
|
...media ? { media } : {},
|
|
14010
14258
|
onMountPending: (medium) => port.postMessage({ medium }),
|