@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/node.js
CHANGED
|
@@ -1753,12 +1753,30 @@ function userEnv(account, system) {
|
|
|
1753
1753
|
PATH: `${pnpm}/bin:/usr/local/bin:/usr/bin:/bin`
|
|
1754
1754
|
};
|
|
1755
1755
|
}
|
|
1756
|
+
function homeGroupOf(groups, name2) {
|
|
1757
|
+
if (name2 === void 0) return void 0;
|
|
1758
|
+
const found = groups.find((g) => g.name === name2);
|
|
1759
|
+
if (!found) throw fsError("ENOENT", `no group ${name2}`);
|
|
1760
|
+
return found;
|
|
1761
|
+
}
|
|
1756
1762
|
var UserDb = class {
|
|
1757
1763
|
fs;
|
|
1764
|
+
owners;
|
|
1758
1765
|
umasks = /* @__PURE__ */ new Map();
|
|
1759
1766
|
writing = Promise.resolve();
|
|
1760
|
-
constructor(fs) {
|
|
1767
|
+
constructor(fs, owners = false) {
|
|
1761
1768
|
this.fs = fs;
|
|
1769
|
+
this.owners = owners;
|
|
1770
|
+
}
|
|
1771
|
+
async stampHome(row, shared) {
|
|
1772
|
+
const home = this.fs.resolvePath("/", row.home);
|
|
1773
|
+
if (!this.owners || !this.fs.chown || !HOME_DIR.test(home)) return;
|
|
1774
|
+
if (await this.fs.realpath?.(home, false).catch(() => void 0) !== home) return;
|
|
1775
|
+
if (!(await this.fs.lstat(home)).isDirectory) return;
|
|
1776
|
+
const gid = shared?.gid ?? row.gid;
|
|
1777
|
+
await this.fs.chown(home, { uid: row.uid, gid, follow: false, kind: "adopt" });
|
|
1778
|
+
const mode = shared ? 1512 : row.name.startsWith("scoop-") ? 488 : 448;
|
|
1779
|
+
await this.fs.chmod(home, mode);
|
|
1762
1780
|
}
|
|
1763
1781
|
async read(path, fallback) {
|
|
1764
1782
|
try {
|
|
@@ -1858,8 +1876,12 @@ var UserDb = class {
|
|
|
1858
1876
|
const users = parsed(passwd);
|
|
1859
1877
|
const groups = parsed(group);
|
|
1860
1878
|
const found = users.find((r) => r.name === name2);
|
|
1879
|
+
const shared = homeGroupOf(groups, options.homeGroup);
|
|
1861
1880
|
if (found) {
|
|
1862
|
-
if (found.uid >= FIRST_UID && found.uid <= LAST_UID)
|
|
1881
|
+
if (found.uid >= FIRST_UID && found.uid <= LAST_UID) {
|
|
1882
|
+
await this.provision(found);
|
|
1883
|
+
await this.stampHome(found, shared);
|
|
1884
|
+
}
|
|
1863
1885
|
remember();
|
|
1864
1886
|
return this.account(found, groups);
|
|
1865
1887
|
}
|
|
@@ -1879,6 +1901,7 @@ var UserDb = class {
|
|
|
1879
1901
|
await this.fs.mkdir(home, { recursive: true });
|
|
1880
1902
|
try {
|
|
1881
1903
|
await this.provision(row);
|
|
1904
|
+
await this.stampHome(row, shared);
|
|
1882
1905
|
await this.fs.mkdir("/etc", { recursive: true });
|
|
1883
1906
|
await this.commit(formatPasswd(passwd), formatGroup(group));
|
|
1884
1907
|
} catch (err) {
|
|
@@ -1974,7 +1997,7 @@ async function realpath(fs, path) {
|
|
|
1974
1997
|
}
|
|
1975
1998
|
return resolved || "/";
|
|
1976
1999
|
}
|
|
1977
|
-
async function fsCall(fs, method, args) {
|
|
2000
|
+
async function fsCall(fs, method, args, owner) {
|
|
1978
2001
|
const path = (i) => fs.resolvePath("/", String(args[i]));
|
|
1979
2002
|
switch (method) {
|
|
1980
2003
|
case "readFile": {
|
|
@@ -1982,7 +2005,7 @@ async function fsCall(fs, method, args) {
|
|
|
1982
2005
|
return { result: bytes, transfer: [bytes.buffer] };
|
|
1983
2006
|
}
|
|
1984
2007
|
case "writeFile":
|
|
1985
|
-
await fs.writeFile(path(0), args[1]);
|
|
2008
|
+
await fs.writeFile(path(0), args[1], owner);
|
|
1986
2009
|
return { result: true };
|
|
1987
2010
|
case "stat":
|
|
1988
2011
|
return { result: await fs.stat(path(0)) };
|
|
@@ -1991,7 +2014,7 @@ async function fsCall(fs, method, args) {
|
|
|
1991
2014
|
case "readdir":
|
|
1992
2015
|
return { result: await fs.readdir(path(0)) };
|
|
1993
2016
|
case "mkdir":
|
|
1994
|
-
await fs.mkdir(path(0), { recursive: true });
|
|
2017
|
+
await fs.mkdir(path(0), owner ? { recursive: true, owner } : { recursive: true });
|
|
1995
2018
|
return { result: true };
|
|
1996
2019
|
case "rm":
|
|
1997
2020
|
await fs.rm(path(0), { recursive: true, force: args[1] === true });
|
|
@@ -2002,7 +2025,7 @@ async function fsCall(fs, method, args) {
|
|
|
2002
2025
|
case "realpath":
|
|
2003
2026
|
return { result: await realpath(fs, String(args[0])) };
|
|
2004
2027
|
case "symlink":
|
|
2005
|
-
await fs.symlink(String(args[0]), path(1));
|
|
2028
|
+
await fs.symlink(String(args[0]), path(1), owner);
|
|
2006
2029
|
return { result: true };
|
|
2007
2030
|
case "readlink":
|
|
2008
2031
|
return { result: await fs.readlink(path(0)) };
|
|
@@ -2024,6 +2047,9 @@ function dialFor(l, req, open) {
|
|
|
2024
2047
|
);
|
|
2025
2048
|
return { result: port2, transfer: [port2] };
|
|
2026
2049
|
}
|
|
2050
|
+
function ownerFor(l, self) {
|
|
2051
|
+
return l.owners && self ? { uid: self.uid, gid: self.gid } : void 0;
|
|
2052
|
+
}
|
|
2027
2053
|
async function accountOf(l, user) {
|
|
2028
2054
|
const found = await l.users.lookup(user);
|
|
2029
2055
|
if (!found) throw fsError("ENOENT", `no user ${String(user)}`);
|
|
@@ -2151,6 +2177,7 @@ function serveClient(port, host) {
|
|
|
2151
2177
|
hello: {
|
|
2152
2178
|
protocol: PROTOCOL,
|
|
2153
2179
|
traits: transport.traits,
|
|
2180
|
+
...launcher.usersMode ? { users: launcher.usersMode } : {},
|
|
2154
2181
|
...host.lock ? { lock: host.lock } : {}
|
|
2155
2182
|
}
|
|
2156
2183
|
});
|
|
@@ -2216,7 +2243,7 @@ function serveClient(port, host) {
|
|
|
2216
2243
|
if (!FS_METHODS.includes(req.method)) {
|
|
2217
2244
|
throw new Error(`unknown file system call ${req.method}`);
|
|
2218
2245
|
}
|
|
2219
|
-
return fsCall(l.fs, req.method, req.args);
|
|
2246
|
+
return fsCall(l.fs, req.method, req.args, ownerFor(l, self));
|
|
2220
2247
|
case "watch":
|
|
2221
2248
|
case "unwatch":
|
|
2222
2249
|
return watchOp(l, req, watches, send);
|
|
@@ -2324,11 +2351,69 @@ var MemoryMeta = class {
|
|
|
2324
2351
|
}
|
|
2325
2352
|
};
|
|
2326
2353
|
|
|
2354
|
+
// src/fs/owners.ts
|
|
2355
|
+
var ROOT_OWNER = Object.freeze({ uid: 0, gid: 0 });
|
|
2356
|
+
var S_ISUID = 2048;
|
|
2357
|
+
var S_ISGID = 1024;
|
|
2358
|
+
var S_IXGRP = 8;
|
|
2359
|
+
function ownOf(entry) {
|
|
2360
|
+
if (entry?.uid === void 0 || entry.gid === void 0) return void 0;
|
|
2361
|
+
return { uid: entry.uid, gid: entry.gid };
|
|
2362
|
+
}
|
|
2363
|
+
function handedBy(entry) {
|
|
2364
|
+
return entry?.heir ? { uid: entry.heir[0], gid: entry.heir[1] } : ownOf(entry);
|
|
2365
|
+
}
|
|
2366
|
+
function inherit(entries) {
|
|
2367
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
2368
|
+
const found = handedBy(entries[i]);
|
|
2369
|
+
if (found) return found;
|
|
2370
|
+
}
|
|
2371
|
+
return { ...ROOT_OWNER };
|
|
2372
|
+
}
|
|
2373
|
+
function chain(path) {
|
|
2374
|
+
const parts = path.split("/").filter(Boolean);
|
|
2375
|
+
return ["/", ...parts.map((_, i) => `/${parts.slice(0, i + 1).join("/")}`)];
|
|
2376
|
+
}
|
|
2377
|
+
function sameOwner(a, b) {
|
|
2378
|
+
return a.uid === b.uid && a.gid === b.gid;
|
|
2379
|
+
}
|
|
2380
|
+
function ownerOf(cred, mode) {
|
|
2381
|
+
return { uid: cred.euid, gid: cred.egid, ...mode !== void 0 ? { mode } : {} };
|
|
2382
|
+
}
|
|
2383
|
+
function inGroup(cred, gid) {
|
|
2384
|
+
return cred.egid === gid || cred.groups.includes(gid);
|
|
2385
|
+
}
|
|
2386
|
+
function mayChown(cred, current, uid, gid) {
|
|
2387
|
+
if (cred.euid === 0) return true;
|
|
2388
|
+
const owner = cred.euid === current.uid;
|
|
2389
|
+
if (uid !== void 0 && !(owner && uid === current.uid)) return false;
|
|
2390
|
+
if (gid !== void 0 && !(owner && (gid === current.gid || inGroup(cred, gid)))) return false;
|
|
2391
|
+
return true;
|
|
2392
|
+
}
|
|
2393
|
+
function clearedSetId(mode) {
|
|
2394
|
+
const bits2 = S_ISUID | (mode & S_IXGRP ? S_ISGID : 0);
|
|
2395
|
+
return mode & 4095 & ~bits2;
|
|
2396
|
+
}
|
|
2397
|
+
async function chownAs(fs, cred, path, change) {
|
|
2398
|
+
const { uid, gid, follow: follow2 } = change;
|
|
2399
|
+
const st = follow2 ? await fs.stat(path) : await fs.lstat(path);
|
|
2400
|
+
const current = { uid: st.uid ?? 0, gid: st.gid ?? 0 };
|
|
2401
|
+
if (!fs.chown || !mayChown(cred, current, uid, gid)) throw fsError("EPERM", path);
|
|
2402
|
+
const clear = st.isFile && (uid !== void 0 || gid !== void 0) ? clearedSetId(st.mode) : void 0;
|
|
2403
|
+
await fs.chown(path, {
|
|
2404
|
+
...uid !== void 0 ? { uid } : {},
|
|
2405
|
+
...gid !== void 0 ? { gid } : {},
|
|
2406
|
+
follow: follow2,
|
|
2407
|
+
...clear !== void 0 && clear !== (st.mode & 4095) ? { mode: clear } : {}
|
|
2408
|
+
});
|
|
2409
|
+
}
|
|
2410
|
+
|
|
2327
2411
|
// src/fs/opfs.ts
|
|
2328
2412
|
var S_IFDIR = 16384;
|
|
2329
2413
|
var S_IFREG = 32768;
|
|
2330
2414
|
var S_IFLNK = 40960;
|
|
2331
2415
|
var PERM_MASK = 4095;
|
|
2416
|
+
var S_ISGID2 = 1024;
|
|
2332
2417
|
var READ_ATTEMPTS = 3;
|
|
2333
2418
|
var MAX_LINKS2 = 40;
|
|
2334
2419
|
var CHECK_MS = 1e3;
|
|
@@ -2426,6 +2511,7 @@ var OpfsFs = class {
|
|
|
2426
2511
|
checked = /* @__PURE__ */ new WeakMap();
|
|
2427
2512
|
channel;
|
|
2428
2513
|
ranged;
|
|
2514
|
+
owners = false;
|
|
2429
2515
|
constructor(root, meta = new MemoryMeta(), channel, options = {}) {
|
|
2430
2516
|
this.root = root;
|
|
2431
2517
|
this.meta = meta;
|
|
@@ -2445,6 +2531,73 @@ var OpfsFs = class {
|
|
|
2445
2531
|
resolvePath(base, path) {
|
|
2446
2532
|
return resolvePath(base, path);
|
|
2447
2533
|
}
|
|
2534
|
+
trackOwners() {
|
|
2535
|
+
this.owners = true;
|
|
2536
|
+
}
|
|
2537
|
+
async handedTo(dir) {
|
|
2538
|
+
return inherit(await this.meta.get(chain(dir)));
|
|
2539
|
+
}
|
|
2540
|
+
async ownerAt(path, entry) {
|
|
2541
|
+
const own = ownOf(entry);
|
|
2542
|
+
if (own) return own;
|
|
2543
|
+
return path === "/" ? { ...ROOT_OWNER } : this.handedTo(parentOf2(path));
|
|
2544
|
+
}
|
|
2545
|
+
async owned(stat, path, entry) {
|
|
2546
|
+
return this.owners ? { ...stat, ...await this.ownerAt(path, entry) } : stat;
|
|
2547
|
+
}
|
|
2548
|
+
async newFields(path, owner, directory) {
|
|
2549
|
+
if (!this.owners || !owner) return void 0;
|
|
2550
|
+
const entries = await this.meta.get(chain(path));
|
|
2551
|
+
const self = entries.pop();
|
|
2552
|
+
const parent = entries.at(-1);
|
|
2553
|
+
const setgid = ((parent?.mode ?? 0) & S_ISGID2) !== 0;
|
|
2554
|
+
const parentGid = (ownOf(parent) ?? inherit(entries.slice(0, -1))).gid;
|
|
2555
|
+
const want = { uid: owner.uid, gid: setgid ? parentGid : owner.gid };
|
|
2556
|
+
let mode = owner.mode === void 0 ? void 0 : owner.mode & PERM_MASK;
|
|
2557
|
+
if (directory && setgid) mode = (mode ?? 493) | S_ISGID2;
|
|
2558
|
+
const fields = {};
|
|
2559
|
+
if (mode !== void 0 && mode !== (this.mode(path, directory, void 0) & PERM_MASK)) {
|
|
2560
|
+
fields.mode = mode;
|
|
2561
|
+
}
|
|
2562
|
+
if (self) fields.heir = void 0;
|
|
2563
|
+
if (ownOf(self) || !sameOwner(want, inherit(entries))) Object.assign(fields, want);
|
|
2564
|
+
return Object.keys(fields).length > 0 ? fields : void 0;
|
|
2565
|
+
}
|
|
2566
|
+
async stampNew(path, owner, directory) {
|
|
2567
|
+
const fields = await this.newFields(path, owner, directory);
|
|
2568
|
+
if (fields) await this.meta.update(path, (entry) => ({ ...entry, path, ...fields }));
|
|
2569
|
+
}
|
|
2570
|
+
async chown(path, change) {
|
|
2571
|
+
if (!this.owners) return;
|
|
2572
|
+
if (change.kind === "new") {
|
|
2573
|
+
const at = resolvePath((await this.locate(parentOf2(path), true)).path, baseOf(path));
|
|
2574
|
+
const { uid = 0, gid = 0, mode } = change;
|
|
2575
|
+
return this.stampNew(at, { uid, gid, ...mode !== void 0 ? { mode } : {} }, false);
|
|
2576
|
+
}
|
|
2577
|
+
const found = await this.locate(path, change.follow !== false);
|
|
2578
|
+
const [stored] = found.link ? [found.link] : await this.meta.get([found.path]);
|
|
2579
|
+
const current = await this.ownerAt(found.path, stored);
|
|
2580
|
+
const next2 = { uid: change.uid ?? current.uid, gid: change.gid ?? current.gid };
|
|
2581
|
+
const handing = found.handle?.kind === "directory" && !sameOwner(next2, current);
|
|
2582
|
+
const heir = change.kind === "adopt" ? void 0 : stored?.heir ?? (handing ? [current.uid, current.gid] : void 0);
|
|
2583
|
+
const ctimeMs = Date.now();
|
|
2584
|
+
await this.meta.update(found.path, (entry) => {
|
|
2585
|
+
const { heir: _, ...rest2 } = entry ?? found.link ?? { path: found.path };
|
|
2586
|
+
return {
|
|
2587
|
+
...rest2,
|
|
2588
|
+
path: found.path,
|
|
2589
|
+
...next2,
|
|
2590
|
+
...heir ? { heir } : {},
|
|
2591
|
+
...change.mode !== void 0 ? { mode: change.mode & PERM_MASK } : {},
|
|
2592
|
+
ctimeMs
|
|
2593
|
+
};
|
|
2594
|
+
});
|
|
2595
|
+
}
|
|
2596
|
+
async movedOwner(source) {
|
|
2597
|
+
if (!this.owners) return void 0;
|
|
2598
|
+
const [stored] = source.link ? [source.link] : await this.meta.get([source.path]);
|
|
2599
|
+
return ownOf(stored) ? void 0 : this.ownerAt(source.path, stored);
|
|
2600
|
+
}
|
|
2448
2601
|
async walk(parts, from, start2) {
|
|
2449
2602
|
let dir = start2;
|
|
2450
2603
|
for (let at = from; at < parts.length; at++) {
|
|
@@ -2637,9 +2790,15 @@ var OpfsFs = class {
|
|
|
2637
2790
|
};
|
|
2638
2791
|
}
|
|
2639
2792
|
async describe(found) {
|
|
2640
|
-
if (found.link) return this.linkStat(found.link);
|
|
2641
|
-
|
|
2642
|
-
|
|
2793
|
+
if (found.link) return this.owned(this.linkStat(found.link), found.path, found.link);
|
|
2794
|
+
if (!this.owners) {
|
|
2795
|
+
const [meta2] = await this.meta.get([found.path]);
|
|
2796
|
+
return this.statOf(found.path, found.handle, meta2);
|
|
2797
|
+
}
|
|
2798
|
+
const entries = await this.meta.get(chain(found.path));
|
|
2799
|
+
const meta = entries.pop();
|
|
2800
|
+
const stat = await this.statOf(found.path, found.handle, meta);
|
|
2801
|
+
return { ...stat, ...ownOf(meta) ?? inherit(entries) };
|
|
2643
2802
|
}
|
|
2644
2803
|
async stat(path) {
|
|
2645
2804
|
return this.describe(await this.locate(path, true));
|
|
@@ -2729,14 +2888,15 @@ var OpfsFs = class {
|
|
|
2729
2888
|
(parent) => parent.getFileHandle(name2, { create: true })
|
|
2730
2889
|
);
|
|
2731
2890
|
if (!existed) this.touch(parentOf2(target));
|
|
2732
|
-
return [handle, existed];
|
|
2891
|
+
return [handle, existed, target];
|
|
2733
2892
|
} catch (err) {
|
|
2734
2893
|
const code = err?.name === "TypeMismatchError" ? "EISDIR" : null;
|
|
2735
2894
|
throw code ? fsError(code, path) : translate(err, path);
|
|
2736
2895
|
}
|
|
2737
2896
|
}
|
|
2738
|
-
async writeFile(path, content) {
|
|
2739
|
-
const [file, existed] = await this.fileFor(path);
|
|
2897
|
+
async writeFile(path, content, owner) {
|
|
2898
|
+
const [file, existed, target] = await this.fileFor(path);
|
|
2899
|
+
if (!existed) await this.stampNew(target, owner, false);
|
|
2740
2900
|
if (!existed && content.length === 0) return;
|
|
2741
2901
|
const writable = await file.createWritable();
|
|
2742
2902
|
await writable.write(content);
|
|
@@ -2761,11 +2921,13 @@ var OpfsFs = class {
|
|
|
2761
2921
|
const [dir, children2] = await this.listing(path);
|
|
2762
2922
|
const base = dir === "/" ? "" : dir;
|
|
2763
2923
|
const metas = await this.meta.get(children2.map(([name2]) => `${base}/${name2}`));
|
|
2924
|
+
const handed2 = this.owners ? await this.handedTo(dir) : void 0;
|
|
2925
|
+
const owned = (stat, entry) => handed2 ? { ...stat, ...ownOf(entry) ?? handed2 } : stat;
|
|
2764
2926
|
return Promise.all(
|
|
2765
2927
|
children2.map(async ([name2, child], i) => {
|
|
2766
|
-
if (!isHandle(child)) return [name2, this.linkStat(child)];
|
|
2928
|
+
if (!isHandle(child)) return [name2, owned(this.linkStat(child), child)];
|
|
2767
2929
|
const stat = await this.statOf(`${base}/${name2}`, child, metas[i]).catch(() => null);
|
|
2768
|
-
return [name2, stat];
|
|
2930
|
+
return [name2, stat && owned(stat, metas[i])];
|
|
2769
2931
|
})
|
|
2770
2932
|
);
|
|
2771
2933
|
}
|
|
@@ -2783,11 +2945,22 @@ var OpfsFs = class {
|
|
|
2783
2945
|
}
|
|
2784
2946
|
const [entry] = await this.meta.get([path]);
|
|
2785
2947
|
if (entry?.link !== void 0) throw fsError("EEXIST", path);
|
|
2786
|
-
|
|
2948
|
+
const { owner } = options;
|
|
2949
|
+
if (options.recursive) {
|
|
2950
|
+
const mode = owner?.parents;
|
|
2951
|
+
const above = owner && {
|
|
2952
|
+
uid: owner.uid,
|
|
2953
|
+
gid: owner.gid,
|
|
2954
|
+
...mode ? { mode, parents: mode } : {}
|
|
2955
|
+
};
|
|
2956
|
+
await this.mkdir(parentOf2(path), { recursive: true, ...above ? { owner: above } : {} });
|
|
2957
|
+
}
|
|
2787
2958
|
const parent = await this.locate(parentOf2(path), true);
|
|
2788
2959
|
if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
|
|
2789
2960
|
await parent.handle.getDirectoryHandle(baseOf(path), { create: true });
|
|
2790
|
-
|
|
2961
|
+
const made = `${parent.path === "/" ? "" : parent.path}/${baseOf(path)}`;
|
|
2962
|
+
await this.stampNew(made, owner, true);
|
|
2963
|
+
this.touch(parent.path, made);
|
|
2791
2964
|
}
|
|
2792
2965
|
async rm(path, options = {}) {
|
|
2793
2966
|
let found;
|
|
@@ -2834,9 +3007,11 @@ var OpfsFs = class {
|
|
|
2834
3007
|
throw fsError("ENOTEMPTY", to);
|
|
2835
3008
|
}
|
|
2836
3009
|
const now = Date.now();
|
|
3010
|
+
const moving = await this.movedOwner(source);
|
|
2837
3011
|
const carry = (entry) => ({
|
|
2838
3012
|
ino: inodeOf(source.path),
|
|
2839
3013
|
...entry,
|
|
3014
|
+
...moving,
|
|
2840
3015
|
path: destination,
|
|
2841
3016
|
ctimeMs: now
|
|
2842
3017
|
});
|
|
@@ -2910,7 +3085,7 @@ var OpfsFs = class {
|
|
|
2910
3085
|
const target = await dir.getDirectoryHandle(name2, { create: true });
|
|
2911
3086
|
for await (const child of handle.values()) await this.copy(child, target, child.name);
|
|
2912
3087
|
}
|
|
2913
|
-
async symlink(target, path) {
|
|
3088
|
+
async symlink(target, path, owner) {
|
|
2914
3089
|
const parent = await this.locate(parentOf2(path), true);
|
|
2915
3090
|
if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
|
|
2916
3091
|
const at = resolvePath(parent.path, baseOf(path));
|
|
@@ -2921,13 +3096,15 @@ var OpfsFs = class {
|
|
|
2921
3096
|
throw fsError("EEXIST", path);
|
|
2922
3097
|
}
|
|
2923
3098
|
const now = Date.now();
|
|
3099
|
+
const fields = await this.newFields(at, owner && { uid: owner.uid, gid: owner.gid }, false);
|
|
2924
3100
|
await this.meta.update(at, () => ({
|
|
2925
3101
|
path: at,
|
|
2926
3102
|
link: target,
|
|
2927
3103
|
dir: parent.path,
|
|
2928
3104
|
ino: inodeOf(at),
|
|
2929
3105
|
mtimeMs: now,
|
|
2930
|
-
ctimeMs: now
|
|
3106
|
+
ctimeMs: now,
|
|
3107
|
+
...fields
|
|
2931
3108
|
}));
|
|
2932
3109
|
this.touch(parent.path);
|
|
2933
3110
|
}
|
|
@@ -4234,7 +4411,7 @@ function withCommandDirs(fs, names, userDir = async () => void 0) {
|
|
|
4234
4411
|
throw err;
|
|
4235
4412
|
}
|
|
4236
4413
|
},
|
|
4237
|
-
writeFile: (path, content) => fs.writeFile(path, content),
|
|
4414
|
+
writeFile: (path, content, owner) => fs.writeFile(path, content, owner),
|
|
4238
4415
|
async exists(path) {
|
|
4239
4416
|
return await fs.exists(path) || await linked(path) !== void 0;
|
|
4240
4417
|
},
|
|
@@ -4272,9 +4449,10 @@ function withCommandDirs(fs, names, userDir = async () => void 0) {
|
|
|
4272
4449
|
mkdir: (path, options) => fs.mkdir(path, options),
|
|
4273
4450
|
rm: (path, options) => fs.rm(path, options),
|
|
4274
4451
|
rename: (from, to) => fs.rename(from, to),
|
|
4275
|
-
symlink: (target, path) => fs.symlink(target, path),
|
|
4452
|
+
symlink: (target, path, owner) => fs.symlink(target, path, owner),
|
|
4276
4453
|
readlink: (path) => fs.readlink(path),
|
|
4277
4454
|
...fs.realpath ? { realpath: fs.realpath.bind(fs) } : {},
|
|
4455
|
+
...fs.chown ? { chown: fs.chown.bind(fs) } : {},
|
|
4278
4456
|
chmod: (path, mode) => fs.chmod(path, mode),
|
|
4279
4457
|
utimes: (path, atime, mtime) => fs.utimes(path, atime, mtime),
|
|
4280
4458
|
lutimes: (path, atime, mtime) => lutimesOf(fs, path, atime, mtime),
|
|
@@ -4400,6 +4578,7 @@ var FsWatchers = class {
|
|
|
4400
4578
|
rename: after(fs.rename.bind(fs), (from, to) => [from, to]),
|
|
4401
4579
|
symlink: after(fs.symlink.bind(fs), (_target, path) => [path]),
|
|
4402
4580
|
chmod: after(fs.chmod.bind(fs), (path) => [path]),
|
|
4581
|
+
...fs.chown ? { chown: after(fs.chown.bind(fs), (path) => [path]) } : {},
|
|
4403
4582
|
utimes: after(fs.utimes.bind(fs), (path) => [path]),
|
|
4404
4583
|
lutimes: after(
|
|
4405
4584
|
(path, atime, mtime) => lutimesOf(fs, path, atime, mtime),
|
|
@@ -4471,13 +4650,13 @@ var ChildTable = class {
|
|
|
4471
4650
|
if (!this.forker) throw new SpawnError("ENOSYS");
|
|
4472
4651
|
return this.track(state, this.parentFds.fork(), /* @__PURE__ */ new Map(), this.forker);
|
|
4473
4652
|
}
|
|
4474
|
-
async spawn(req, stdio,
|
|
4653
|
+
async spawn(req, stdio, inherit2 = []) {
|
|
4475
4654
|
if (!this.spawner) throw new SpawnError("ENOSYS");
|
|
4476
4655
|
const fds = new FdTable();
|
|
4477
4656
|
const captured = /* @__PURE__ */ new Map();
|
|
4478
4657
|
try {
|
|
4479
4658
|
for (const [n, slot] of stdio.entries()) fds.installAt(n, this.openSlot(slot, n, captured));
|
|
4480
|
-
for (const slot of
|
|
4659
|
+
for (const slot of inherit2) {
|
|
4481
4660
|
if (slot.fd <= 2) continue;
|
|
4482
4661
|
if ("device" in slot) {
|
|
4483
4662
|
fds.installAt(slot.fd, deviceFile(slot.device, slot.access));
|
|
@@ -4558,8 +4737,8 @@ var ChildTable = class {
|
|
|
4558
4737
|
candidates(pid, flags) {
|
|
4559
4738
|
const all = [...this.children];
|
|
4560
4739
|
if (pid > 0) return all.filter(([p]) => p === pid);
|
|
4561
|
-
const
|
|
4562
|
-
return pid === -1 || !
|
|
4740
|
+
const inGroup2 = flags.inGroup;
|
|
4741
|
+
return pid === -1 || !inGroup2 ? all : all.filter(([p]) => inGroup2(p));
|
|
4563
4742
|
}
|
|
4564
4743
|
async nextChange(candidates, flags, interrupt) {
|
|
4565
4744
|
let wake;
|
|
@@ -5280,10 +5459,10 @@ var MountFs = class {
|
|
|
5280
5459
|
}
|
|
5281
5460
|
return concat3(chunks2, total);
|
|
5282
5461
|
}
|
|
5283
|
-
async writeFile(path, content) {
|
|
5462
|
+
async writeFile(path, content, owner) {
|
|
5284
5463
|
const real = await this.follow(path, 0, true);
|
|
5285
5464
|
const found = this.at(real);
|
|
5286
|
-
if (!found) return this.base.writeFile(real, content);
|
|
5465
|
+
if (!found) return this.base.writeFile(real, content, owner);
|
|
5287
5466
|
const { mount, rel: rel2 } = found;
|
|
5288
5467
|
this.writable(mount, real);
|
|
5289
5468
|
const bytes = typeof content === "string" ? new TextEncoder().encode(content) : content;
|
|
@@ -5550,9 +5729,9 @@ var MountFs = class {
|
|
|
5550
5729
|
this.table.forget(a.mount, normalizePath(to));
|
|
5551
5730
|
}
|
|
5552
5731
|
}
|
|
5553
|
-
async symlink(target, path) {
|
|
5732
|
+
async symlink(target, path, owner) {
|
|
5554
5733
|
const found = this.at(path);
|
|
5555
|
-
if (!found) return this.base.symlink(target, path);
|
|
5734
|
+
if (!found) return this.base.symlink(target, path, owner);
|
|
5556
5735
|
this.writable(found.mount, normalizePath(path));
|
|
5557
5736
|
if (!found.mount.caps.symlinks)
|
|
5558
5737
|
throw errnoError("EPERM", `${path}: this file system has no symlinks`);
|
|
@@ -5570,6 +5749,15 @@ var MountFs = class {
|
|
|
5570
5749
|
if (!found) return this.base.readlink(path);
|
|
5571
5750
|
return await found.mount.conn.call({ op: "readlink", path: found.rel });
|
|
5572
5751
|
}
|
|
5752
|
+
async chown(path, change) {
|
|
5753
|
+
const real = change.follow === false || change.kind === "new" ? path : await this.follow(path);
|
|
5754
|
+
if (this.at(real)) {
|
|
5755
|
+
if (change.kind === "new") return;
|
|
5756
|
+
throw errnoError("EPERM", `${path}: this file system keeps no owners`);
|
|
5757
|
+
}
|
|
5758
|
+
if (!this.base.chown) throw errnoError("EPERM", path);
|
|
5759
|
+
return this.base.chown(real, change);
|
|
5760
|
+
}
|
|
5573
5761
|
async chmod(path, mode) {
|
|
5574
5762
|
const found = this.at(path);
|
|
5575
5763
|
if (!found) return this.base.chmod(path, mode);
|
|
@@ -5644,7 +5832,9 @@ function statJson(s) {
|
|
|
5644
5832
|
...s.readonly ? { readonly: true } : {},
|
|
5645
5833
|
...s.maxFile ? { maxFile: s.maxFile } : {},
|
|
5646
5834
|
...s.ranged ? { ranged: true } : {},
|
|
5647
|
-
...s.version !== void 0 ? { version: s.version } : {}
|
|
5835
|
+
...s.version !== void 0 ? { version: s.version } : {},
|
|
5836
|
+
...s.uid !== void 0 ? { uid: s.uid } : {},
|
|
5837
|
+
...s.gid !== void 0 ? { gid: s.gid } : {}
|
|
5648
5838
|
};
|
|
5649
5839
|
}
|
|
5650
5840
|
async function readdirStat(fs, dir) {
|
|
@@ -5659,13 +5849,34 @@ var done = { ok: true, kind: "void" };
|
|
|
5659
5849
|
function json2(value) {
|
|
5660
5850
|
return { ok: true, kind: "json", json: value };
|
|
5661
5851
|
}
|
|
5852
|
+
function ownerFor2(entry, mode) {
|
|
5853
|
+
const cred = entry.cred?.();
|
|
5854
|
+
if (!cred) return void 0;
|
|
5855
|
+
return ownerOf(cred, mode === void 0 ? void 0 : mode & ~(entry.umask?.() ?? 18));
|
|
5856
|
+
}
|
|
5857
|
+
function mkdirOptions(entry, mode = 511) {
|
|
5858
|
+
const owner = ownerFor2(entry, mode);
|
|
5859
|
+
if (!owner) return { recursive: true };
|
|
5860
|
+
const parents = 511 & ~(entry.umask?.() ?? 18) | 192;
|
|
5861
|
+
return { recursive: true, owner: { ...owner, parents } };
|
|
5862
|
+
}
|
|
5863
|
+
async function chown(entry, path, req) {
|
|
5864
|
+
const cred = entry.cred?.();
|
|
5865
|
+
if (!cred) return done;
|
|
5866
|
+
await chownAs(entry.fs, cred, path, {
|
|
5867
|
+
...req.uid !== void 0 ? { uid: req.uid } : {},
|
|
5868
|
+
...req.gid !== void 0 ? { gid: req.gid } : {},
|
|
5869
|
+
follow: req.op === "chown"
|
|
5870
|
+
});
|
|
5871
|
+
return done;
|
|
5872
|
+
}
|
|
5662
5873
|
async function run(entry, path, req) {
|
|
5663
5874
|
const { fs, cwd } = entry;
|
|
5664
5875
|
switch (req.op) {
|
|
5665
5876
|
case "read":
|
|
5666
5877
|
return { ok: true, kind: "bytes", bytes: await fs.readFileBuffer(path) };
|
|
5667
5878
|
case "write":
|
|
5668
|
-
await fs.writeFile(path, req.body ?? new Uint8Array(0));
|
|
5879
|
+
await fs.writeFile(path, req.body ?? new Uint8Array(0), ownerFor2(entry, 438));
|
|
5669
5880
|
return done;
|
|
5670
5881
|
case "exists":
|
|
5671
5882
|
return json2(await fs.exists(path));
|
|
@@ -5678,7 +5889,7 @@ async function run(entry, path, req) {
|
|
|
5678
5889
|
case "readdir-stat":
|
|
5679
5890
|
return json2(await readdirStat(fs, path));
|
|
5680
5891
|
case "mkdir":
|
|
5681
|
-
await fs.mkdir(path,
|
|
5892
|
+
await fs.mkdir(path, mkdirOptions(entry, req.mode));
|
|
5682
5893
|
return done;
|
|
5683
5894
|
case "rm":
|
|
5684
5895
|
await fs.rm(path, { recursive: true });
|
|
@@ -5699,10 +5910,10 @@ async function run(entry, path, req) {
|
|
|
5699
5910
|
await fs.rm(path, { recursive: true });
|
|
5700
5911
|
return done;
|
|
5701
5912
|
case "symlink":
|
|
5702
|
-
await fs.symlink(req.arg2 ?? "", path);
|
|
5913
|
+
await fs.symlink(req.arg2 ?? "", path, ownerFor2(entry));
|
|
5703
5914
|
return done;
|
|
5704
5915
|
case "create":
|
|
5705
|
-
await createExclusive(fs, path);
|
|
5916
|
+
await createExclusive(fs, path, ownerFor2(entry, req.mode ?? 438));
|
|
5706
5917
|
return done;
|
|
5707
5918
|
case "readlink":
|
|
5708
5919
|
return json2(await fs.readlink(path));
|
|
@@ -5715,6 +5926,9 @@ async function run(entry, path, req) {
|
|
|
5715
5926
|
case "lutimes":
|
|
5716
5927
|
await lutimesOf(fs, path, new Date(req.atimeMs ?? 0), new Date(req.mtimeMs ?? 0));
|
|
5717
5928
|
return done;
|
|
5929
|
+
case "chown":
|
|
5930
|
+
case "lchown":
|
|
5931
|
+
return chown(entry, path, req);
|
|
5718
5932
|
case "pread":
|
|
5719
5933
|
case "pwrite":
|
|
5720
5934
|
case "truncate":
|
|
@@ -5723,14 +5937,14 @@ async function run(entry, path, req) {
|
|
|
5723
5937
|
return { ok: false, errno: "EINVAL", message: `sync-fs: unknown op '${req.op}'` };
|
|
5724
5938
|
}
|
|
5725
5939
|
}
|
|
5726
|
-
async function createExclusive(fs, path) {
|
|
5727
|
-
if (fs.createExclusive) return fs.createExclusive(path);
|
|
5940
|
+
async function createExclusive(fs, path, owner) {
|
|
5941
|
+
if (fs.createExclusive) return fs.createExclusive(path, owner);
|
|
5728
5942
|
if (await fs.lstat(path).then(
|
|
5729
5943
|
() => true,
|
|
5730
5944
|
() => false
|
|
5731
5945
|
))
|
|
5732
5946
|
throw syncError("EEXIST", path);
|
|
5733
|
-
await fs.writeFile(path, new Uint8Array(0));
|
|
5947
|
+
await fs.writeFile(path, new Uint8Array(0), owner);
|
|
5734
5948
|
}
|
|
5735
5949
|
async function ranged(fs, path, req) {
|
|
5736
5950
|
const ops = rangedOps(fs);
|
|
@@ -6379,6 +6593,10 @@ function normalize(path) {
|
|
|
6379
6593
|
}
|
|
6380
6594
|
return `/${out.join("/")}`;
|
|
6381
6595
|
}
|
|
6596
|
+
var RING = 8;
|
|
6597
|
+
var RING_SIZE = 64;
|
|
6598
|
+
var SLOT = 3;
|
|
6599
|
+
var SHARED_IDS_BYTES = (RING + RING_SIZE * SLOT) * 4;
|
|
6382
6600
|
|
|
6383
6601
|
// src/process/wasi/wasi-procfs.ts
|
|
6384
6602
|
var DIR_MODE = 16749;
|
|
@@ -7220,10 +7438,10 @@ var RealmProxy = class {
|
|
|
7220
7438
|
}
|
|
7221
7439
|
async bridge(ctx, socket, hangup) {
|
|
7222
7440
|
const stop = this.stop.signal;
|
|
7223
|
-
let
|
|
7441
|
+
let chain2 = Promise.resolve();
|
|
7224
7442
|
const toGuest = (bytes) => {
|
|
7225
|
-
|
|
7226
|
-
return
|
|
7443
|
+
chain2 = chain2.then(() => ctx.sink.write(bytes, stop));
|
|
7444
|
+
return chain2;
|
|
7227
7445
|
};
|
|
7228
7446
|
const done4 = new AbortController();
|
|
7229
7447
|
const reading = AbortSignal.any([stop, done4.signal, hangup]);
|
|
@@ -9273,12 +9491,12 @@ var VfsNodes = class {
|
|
|
9273
9491
|
}
|
|
9274
9492
|
return walk();
|
|
9275
9493
|
}
|
|
9276
|
-
createExclusive(path) {
|
|
9494
|
+
createExclusive(path, owner) {
|
|
9277
9495
|
return this.onEntry(path, async () => {
|
|
9278
9496
|
const node = this.byPath.get(path);
|
|
9279
9497
|
const held = node ? await node.serial(async () => node.holds()) : false;
|
|
9280
9498
|
if (held || await present(this.fs, path)) throw fsError("EEXIST", path);
|
|
9281
|
-
await this.fs.writeFile(path, new Uint8Array(0));
|
|
9499
|
+
await this.fs.writeFile(path, new Uint8Array(0), owner);
|
|
9282
9500
|
});
|
|
9283
9501
|
}
|
|
9284
9502
|
open(path, pin, writable = false) {
|
|
@@ -9495,9 +9713,9 @@ function keepingOpen(fs, nodes) {
|
|
|
9495
9713
|
nodes.renamed(a, b);
|
|
9496
9714
|
});
|
|
9497
9715
|
},
|
|
9498
|
-
writeFile: (path, content) => nodes.onEntry(fs.resolvePath("/", path), () => fs.writeFile(path, content)),
|
|
9499
|
-
createExclusive: async (path) => nodes.createExclusive(await nodes.entryKey(fs.resolvePath("/", path))),
|
|
9500
|
-
symlink: (target, path) => nodes.onEntry(fs.resolvePath("/", path), () => fs.symlink(target, path)),
|
|
9716
|
+
writeFile: (path, content, owner) => nodes.onEntry(fs.resolvePath("/", path), () => fs.writeFile(path, content, owner)),
|
|
9717
|
+
createExclusive: async (path, owner) => nodes.createExclusive(await nodes.entryKey(fs.resolvePath("/", path)), owner),
|
|
9718
|
+
symlink: (target, path, owner) => nodes.onEntry(fs.resolvePath("/", path), () => fs.symlink(target, path, owner)),
|
|
9501
9719
|
mkdir: (path, options) => nodes.onEntry(fs.resolvePath("/", path), () => fs.mkdir(path, options))
|
|
9502
9720
|
};
|
|
9503
9721
|
}
|
|
@@ -9768,9 +9986,9 @@ var WasmProcess = class {
|
|
|
9768
9986
|
return "deliver";
|
|
9769
9987
|
}
|
|
9770
9988
|
async spawn(req) {
|
|
9771
|
-
const { file, argv, env, cwd, stdio, inherit, exec } = req;
|
|
9989
|
+
const { file, argv, env, cwd, stdio, inherit: inherit2, exec } = req;
|
|
9772
9990
|
const spawned = { file, argv, env, cwd, ...exec ? { exec } : {} };
|
|
9773
|
-
const pid = await this.children.spawn(spawned, stdio,
|
|
9991
|
+
const pid = await this.children.spawn(spawned, stdio, inherit2);
|
|
9774
9992
|
if (!exec) return pid;
|
|
9775
9993
|
if (this.killed) void Promise.allSettled([this.options.kill?.(pid, SIG.KILL)]);
|
|
9776
9994
|
else this.adoptExec(pid);
|
|
@@ -9935,12 +10153,14 @@ var WasmProcess = class {
|
|
|
9935
10153
|
}
|
|
9936
10154
|
const open = { ...req, path };
|
|
9937
10155
|
if (req.exclusive) {
|
|
9938
|
-
await nodes.createExclusive(path);
|
|
10156
|
+
await nodes.createExclusive(path, this.newOwner());
|
|
9939
10157
|
this.fds.installAt(fd, this.openVfsFile(open));
|
|
9940
10158
|
} else if (req.create) {
|
|
9941
10159
|
await nodes.onEntry(path, async () => {
|
|
10160
|
+
const fresh = this.options.owners && !await present(this.options.fs, path, true);
|
|
9942
10161
|
this.fds.installAt(fd, this.openVfsFile(open));
|
|
9943
10162
|
await this.fds.get(fd).file.stat?.();
|
|
10163
|
+
if (fresh) await this.options.fs.chown?.(path, { ...this.newOwner(), kind: "new" });
|
|
9944
10164
|
});
|
|
9945
10165
|
} else {
|
|
9946
10166
|
this.fds.installAt(fd, this.openVfsFile(open));
|
|
@@ -9954,6 +10174,10 @@ var WasmProcess = class {
|
|
|
9954
10174
|
}
|
|
9955
10175
|
return fd;
|
|
9956
10176
|
}
|
|
10177
|
+
newOwner() {
|
|
10178
|
+
if (!this.options.owners) return void 0;
|
|
10179
|
+
return { uid: this.cred.euid, gid: this.cred.egid, mode: 438 & ~this.umask };
|
|
10180
|
+
}
|
|
9957
10181
|
async openProc(req, path) {
|
|
9958
10182
|
return this.fds.install(await this.procFile(req, path), 3);
|
|
9959
10183
|
}
|
|
@@ -10600,6 +10824,7 @@ function processInit(opts, sab, umask, cred, lane) {
|
|
|
10600
10824
|
sab,
|
|
10601
10825
|
umask,
|
|
10602
10826
|
cred,
|
|
10827
|
+
...opts.owners ? { owners: true } : {},
|
|
10603
10828
|
...opts.ppid !== void 0 ? { ppid: opts.ppid } : {}
|
|
10604
10829
|
};
|
|
10605
10830
|
if (opts.program.abi === "js") {
|
|
@@ -10623,8 +10848,9 @@ function inherited(opts) {
|
|
|
10623
10848
|
...opts.cred ? { cred: opts.cred } : {}
|
|
10624
10849
|
};
|
|
10625
10850
|
}
|
|
10626
|
-
function holdingToken(opts, holds) {
|
|
10851
|
+
function holdingToken(opts, holds, caller) {
|
|
10627
10852
|
return mintSyncFsToken({
|
|
10853
|
+
...opts.owners ? caller : {},
|
|
10628
10854
|
fs: opts.fs,
|
|
10629
10855
|
cwd: opts.cwd,
|
|
10630
10856
|
...opts.statfs ? { statfs: opts.statfs } : {},
|
|
@@ -10640,6 +10866,7 @@ function holdingToken(opts, holds) {
|
|
|
10640
10866
|
function processOptions(opts, header4, hooks) {
|
|
10641
10867
|
return {
|
|
10642
10868
|
...inherited(opts),
|
|
10869
|
+
...opts.owners ? { owners: true } : {},
|
|
10643
10870
|
...opts.identity ? { identity: opts.identity } : {},
|
|
10644
10871
|
...opts.onSyscall ? { onSyscall: opts.onSyscall } : {},
|
|
10645
10872
|
...opts.settling ? { settling: opts.settling } : {},
|
|
@@ -10684,7 +10911,10 @@ function spawnWasmProcess(opts) {
|
|
|
10684
10911
|
publishStops(process2, header4);
|
|
10685
10912
|
const holds = new HeldPaths();
|
|
10686
10913
|
opts.held?.add(holds);
|
|
10687
|
-
const token = holdingToken(opts, holds
|
|
10914
|
+
const token = holdingToken(opts, holds, {
|
|
10915
|
+
cred: () => process2.cred,
|
|
10916
|
+
umask: () => process2.umask
|
|
10917
|
+
});
|
|
10688
10918
|
process2.keptPath = (path) => holds.keptAt(path)?.hidden;
|
|
10689
10919
|
process2.keptHandle = (handle2) => holds.keptFor(handle2)?.hidden;
|
|
10690
10920
|
const worker = opts.createWorker();
|
|
@@ -11045,26 +11275,26 @@ function replayingHops(inner, heldMs = HELD_MS) {
|
|
|
11045
11275
|
void entry.final.cancel().catch(() => void 0);
|
|
11046
11276
|
};
|
|
11047
11277
|
const keyOf2 = (owner, method, url) => `${owner} ${method} ${url}`;
|
|
11048
|
-
const hold = (key,
|
|
11278
|
+
const hold = (key, chain2) => {
|
|
11049
11279
|
drop(key);
|
|
11050
|
-
const mine = [...held.keys()].filter((k) => held.get(k)?.owner ===
|
|
11280
|
+
const mine = [...held.keys()].filter((k) => held.get(k)?.owner === chain2.owner);
|
|
11051
11281
|
if (mine.length >= HELD_PER_OWNER) drop(mine[0]);
|
|
11052
11282
|
if (held.size >= HELD_MAX) drop(held.keys().next().value);
|
|
11053
11283
|
const timer = setTimeout(() => drop(key), heldMs);
|
|
11054
11284
|
timer.unref?.();
|
|
11055
|
-
held.set(key, { ...
|
|
11285
|
+
held.set(key, { ...chain2, timer });
|
|
11056
11286
|
};
|
|
11057
|
-
const replay = (
|
|
11058
|
-
const [hop, ...rest2] =
|
|
11287
|
+
const replay = (chain2) => {
|
|
11288
|
+
const [hop, ...rest2] = chain2.hops;
|
|
11059
11289
|
const location = hop && header2(hop.headers, "location");
|
|
11060
|
-
if (!hop || location === void 0) return
|
|
11290
|
+
if (!hop || location === void 0) return chain2.final;
|
|
11061
11291
|
const target = new URL(location, hop.url);
|
|
11062
11292
|
target.hash = "";
|
|
11063
|
-
const method = followedWith(hop.status,
|
|
11293
|
+
const method = followedWith(hop.status, chain2.method);
|
|
11064
11294
|
const away = target.origin !== new URL(hop.url).origin;
|
|
11065
|
-
const print = away ? unauthorized(
|
|
11066
|
-
hold(keyOf2(
|
|
11067
|
-
...
|
|
11295
|
+
const print = away ? unauthorized(chain2.fingerprint) : chain2.fingerprint;
|
|
11296
|
+
hold(keyOf2(chain2.owner, method, target.href), {
|
|
11297
|
+
...chain2,
|
|
11068
11298
|
method,
|
|
11069
11299
|
fingerprint: print,
|
|
11070
11300
|
hops: rest2
|
|
@@ -12756,6 +12986,11 @@ var DECIDE_MS = 100;
|
|
|
12756
12986
|
var INIT_PID = 1;
|
|
12757
12987
|
var SHARED_DIRS = ["/tmp", "/home"];
|
|
12758
12988
|
var encoder3 = new TextEncoder();
|
|
12989
|
+
var USERS_MODES = ["off", "report", "enforce"];
|
|
12990
|
+
function usersMode(mode = "off") {
|
|
12991
|
+
if (USERS_MODES.includes(mode)) return mode;
|
|
12992
|
+
throw new Error(`users must be 'off', 'report' or 'enforce', not ${String(mode)}`);
|
|
12993
|
+
}
|
|
12759
12994
|
function baseName(path) {
|
|
12760
12995
|
return path.slice(path.lastIndexOf("/") + 1);
|
|
12761
12996
|
}
|
|
@@ -12883,10 +13118,13 @@ var Launcher = class {
|
|
|
12883
13118
|
processMounts;
|
|
12884
13119
|
booting = new AbortController();
|
|
12885
13120
|
fstab = Promise.resolve([]);
|
|
13121
|
+
usersMode;
|
|
12886
13122
|
nextPid = 1e3;
|
|
12887
13123
|
boot = Date.now();
|
|
12888
13124
|
terminals = 0;
|
|
12889
13125
|
constructor(options) {
|
|
13126
|
+
this.usersMode = usersMode(options.users);
|
|
13127
|
+
if (this.owners) options.fs.trackOwners?.();
|
|
12890
13128
|
this.mounts = new MountTable({
|
|
12891
13129
|
open: (type, spec) => this.driver(type, spec),
|
|
12892
13130
|
busy: (target) => [...this.openFiles].some((nodes) => nodes.holds(target)) || heldUnder(this.held, target),
|
|
@@ -12940,7 +13178,7 @@ var Launcher = class {
|
|
|
12940
13178
|
}
|
|
12941
13179
|
);
|
|
12942
13180
|
this.fs = this.unlinked.wrap(keepingOpen(fs, this.nodes));
|
|
12943
|
-
this.users = new UserDb(this.fs);
|
|
13181
|
+
this.users = new UserDb(this.fs, this.owners);
|
|
12944
13182
|
void this.unlinked.sweep("/");
|
|
12945
13183
|
this.watchers.watch(
|
|
12946
13184
|
[this.modulesDir, this.pnpmHome],
|
|
@@ -12952,6 +13190,9 @@ var Launcher = class {
|
|
|
12952
13190
|
this.resetCatalogs();
|
|
12953
13191
|
});
|
|
12954
13192
|
}
|
|
13193
|
+
get owners() {
|
|
13194
|
+
return this.usersMode !== "off";
|
|
13195
|
+
}
|
|
12955
13196
|
setRoutes(table) {
|
|
12956
13197
|
this.routes.set(table);
|
|
12957
13198
|
}
|
|
@@ -13210,6 +13451,7 @@ var Launcher = class {
|
|
|
13210
13451
|
...req.ignored ? { ignored: req.ignored } : {},
|
|
13211
13452
|
...req.umask !== void 0 ? { umask: req.umask } : {},
|
|
13212
13453
|
cred: req.cred,
|
|
13454
|
+
...this.owners ? { owners: true } : {},
|
|
13213
13455
|
program: req.program,
|
|
13214
13456
|
argv0: req.argv0,
|
|
13215
13457
|
args: req.args,
|
|
@@ -14671,6 +14913,7 @@ async function attachKernel(port, options = {}) {
|
|
|
14671
14913
|
return {
|
|
14672
14914
|
protocol: hello.protocol,
|
|
14673
14915
|
transport,
|
|
14916
|
+
users: hello.users ?? "off",
|
|
14674
14917
|
closed: channel.ended.promise,
|
|
14675
14918
|
spawn: (argv, opts = {}) => spawnOn(channel, argv, opts),
|
|
14676
14919
|
run: (argv, opts = {}) => runOn(channel, argv, opts),
|
|
@@ -14798,7 +15041,8 @@ async function createNodeKernel(options = {}) {
|
|
|
14798
15041
|
...options.hostfs ? { hostfs: options.hostfs } : {},
|
|
14799
15042
|
...hostfsFetchOf(options),
|
|
14800
15043
|
...options.cdp ? { cdp: options.cdp } : {},
|
|
14801
|
-
...options.hostname !== void 0 ? { hostname: options.hostname } : {}
|
|
15044
|
+
...options.hostname !== void 0 ? { hostname: options.hostname } : {},
|
|
15045
|
+
...options.users !== void 0 ? { users: options.users } : {}
|
|
14802
15046
|
});
|
|
14803
15047
|
await launcher.prepare();
|
|
14804
15048
|
const guard = (work) => new Promise((resolve, reject) => {
|
|
@@ -14864,6 +15108,7 @@ async function createNodeKernel(options = {}) {
|
|
|
14864
15108
|
mounts: async () => launcher.mounts.list(),
|
|
14865
15109
|
setRoutes: (routes) => guard(async () => launcher.setRoutes(routes)),
|
|
14866
15110
|
users: {
|
|
15111
|
+
mode: launcher.usersMode,
|
|
14867
15112
|
add: (user) => guard(() => launcher.users.add(user)),
|
|
14868
15113
|
remove: (name2, options2) => guard(() => launcher.users.remove(name2, options2)),
|
|
14869
15114
|
list: () => guard(() => launcher.users.list())
|