@ai-ecoverse/slicc-kernel 1.58.1 → 1.59.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 -11
- package/dist/driver-worker.js +30 -11
- package/dist/driver-worker.js.map +2 -2
- package/dist/driver.js +30 -11
- package/dist/driver.js.map +2 -2
- package/dist/index.js +25 -7
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +271 -111
- package/dist/kernel-worker.js.map +3 -3
- package/dist/node-driver-worker.js +30 -11
- package/dist/node-driver-worker.js.map +2 -2
- package/dist/node-process-worker.js +87 -13
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +367 -133
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +85 -11
- package/dist/process-worker.js.map +3 -3
- package/package.json +2 -2
package/dist/kernel-worker.js
CHANGED
|
@@ -794,12 +794,12 @@ var OpfsFs = class {
|
|
|
794
794
|
const base = dir === "/" ? "" : dir;
|
|
795
795
|
const metas = await this.meta.get(children2.map(([name2]) => `${base}/${name2}`));
|
|
796
796
|
const handed2 = this.owners ? await this.handedTo(dir) : void 0;
|
|
797
|
-
const
|
|
797
|
+
const owned3 = (stat, entry) => handed2 ? { ...stat, ...ownOf(entry) ?? handed2 } : stat;
|
|
798
798
|
return Promise.all(
|
|
799
799
|
children2.map(async ([name2, child], i) => {
|
|
800
|
-
if (!isHandle(child)) return [name2,
|
|
800
|
+
if (!isHandle(child)) return [name2, owned3(this.linkStat(child), child)];
|
|
801
801
|
const stat = await this.statOf(`${base}/${name2}`, child, metas[i]).catch(() => null);
|
|
802
|
-
return [name2, stat &&
|
|
802
|
+
return [name2, stat && owned3(stat, metas[i])];
|
|
803
803
|
})
|
|
804
804
|
);
|
|
805
805
|
}
|
|
@@ -830,9 +830,9 @@ var OpfsFs = class {
|
|
|
830
830
|
const parent = await this.locate(parentOf2(path), true);
|
|
831
831
|
if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
|
|
832
832
|
await parent.handle.getDirectoryHandle(baseOf(path), { create: true });
|
|
833
|
-
const
|
|
834
|
-
await this.stampNew(
|
|
835
|
-
this.touch(parent.path,
|
|
833
|
+
const made2 = `${parent.path === "/" ? "" : parent.path}/${baseOf(path)}`;
|
|
834
|
+
await this.stampNew(made2, owner, true);
|
|
835
|
+
this.touch(parent.path, made2);
|
|
836
836
|
}
|
|
837
837
|
async rm(path, options = {}) {
|
|
838
838
|
let found;
|
|
@@ -2644,12 +2644,22 @@ var UserDb = class {
|
|
|
2644
2644
|
async stampHome(row, shared) {
|
|
2645
2645
|
const home = this.fs.resolvePath("/", row.home);
|
|
2646
2646
|
if (!this.owners || !this.fs.chown || !HOME_DIR.test(home)) return;
|
|
2647
|
-
if (await this.
|
|
2648
|
-
if (!(await this.fs.lstat(home)).isDirectory) return;
|
|
2647
|
+
if (!await this.realDir(home)) return;
|
|
2649
2648
|
const gid = shared?.gid ?? row.gid;
|
|
2650
2649
|
await this.fs.chown(home, { uid: row.uid, gid, follow: false, kind: "adopt" });
|
|
2651
|
-
const
|
|
2652
|
-
await this.fs.chmod(home,
|
|
2650
|
+
const scoop = row.name.startsWith("scoop-");
|
|
2651
|
+
await this.fs.chmod(home, shared ? 1512 : scoop ? 488 : 448);
|
|
2652
|
+
const pnpm = `${home}/.local/share/pnpm`;
|
|
2653
|
+
if (await this.realDir(pnpm)) await this.fs.chmod(pnpm, scoop ? 488 : 448);
|
|
2654
|
+
}
|
|
2655
|
+
async realDir(path) {
|
|
2656
|
+
const parts = path.split("/").filter(Boolean);
|
|
2657
|
+
for (let n = 1; n <= parts.length; n++) {
|
|
2658
|
+
const at = `/${parts.slice(0, n).join("/")}`;
|
|
2659
|
+
const st = await this.fs.lstat(at).catch(() => void 0);
|
|
2660
|
+
if (!st?.isDirectory) return false;
|
|
2661
|
+
}
|
|
2662
|
+
return true;
|
|
2653
2663
|
}
|
|
2654
2664
|
async read(path, fallback) {
|
|
2655
2665
|
try {
|
|
@@ -2666,15 +2676,17 @@ var UserDb = class {
|
|
|
2666
2676
|
};
|
|
2667
2677
|
}
|
|
2668
2678
|
async provision(row) {
|
|
2679
|
+
const owner = this.owners ? { uid: row.uid, gid: row.gid } : void 0;
|
|
2680
|
+
const made2 = owner ? { recursive: true, owner } : { recursive: true };
|
|
2669
2681
|
const pnpm = `${row.home}/.local/share/pnpm`;
|
|
2670
2682
|
if (!await this.fs.exists(pnpm)) {
|
|
2671
|
-
await this.fs.mkdir(pnpm,
|
|
2683
|
+
await this.fs.mkdir(pnpm, made2);
|
|
2672
2684
|
await this.fs.chmod(pnpm, row.name.startsWith("scoop-") ? 488 : 448);
|
|
2673
2685
|
}
|
|
2674
2686
|
const config = `${row.home}/.config/pnpm/config.yaml`;
|
|
2675
2687
|
if (!await this.fs.exists(config)) {
|
|
2676
|
-
await this.fs.mkdir(`${row.home}/.config/pnpm`,
|
|
2677
|
-
await this.fs.writeFile(config, PNPM_CONFIG);
|
|
2688
|
+
await this.fs.mkdir(`${row.home}/.config/pnpm`, made2);
|
|
2689
|
+
await this.fs.writeFile(config, PNPM_CONFIG, owner);
|
|
2678
2690
|
}
|
|
2679
2691
|
}
|
|
2680
2692
|
async commit(passwd, group, then) {
|
|
@@ -2851,7 +2863,7 @@ async function fsCall(fs, method, args, owner) {
|
|
|
2851
2863
|
return { result: bytes, transfer: [bytes.buffer] };
|
|
2852
2864
|
}
|
|
2853
2865
|
case "writeFile":
|
|
2854
|
-
await fs.writeFile(path(0), args[1], owner);
|
|
2866
|
+
await fs.writeFile(path(0), args[1], created(owner, 438));
|
|
2855
2867
|
return { result: true };
|
|
2856
2868
|
case "stat":
|
|
2857
2869
|
return { result: await fs.stat(path(0)) };
|
|
@@ -2860,7 +2872,10 @@ async function fsCall(fs, method, args, owner) {
|
|
|
2860
2872
|
case "readdir":
|
|
2861
2873
|
return { result: await fs.readdir(path(0)) };
|
|
2862
2874
|
case "mkdir":
|
|
2863
|
-
await fs.mkdir(
|
|
2875
|
+
await fs.mkdir(
|
|
2876
|
+
path(0),
|
|
2877
|
+
owner ? { recursive: true, owner: made(owner) } : { recursive: true }
|
|
2878
|
+
);
|
|
2864
2879
|
return { result: true };
|
|
2865
2880
|
case "rm":
|
|
2866
2881
|
await fs.rm(path(0), { recursive: true, force: args[1] === true });
|
|
@@ -2871,7 +2886,7 @@ async function fsCall(fs, method, args, owner) {
|
|
|
2871
2886
|
case "realpath":
|
|
2872
2887
|
return { result: await realpath(fs, String(args[0])) };
|
|
2873
2888
|
case "symlink":
|
|
2874
|
-
await fs.symlink(String(args[0]), path(1), owner);
|
|
2889
|
+
await fs.symlink(String(args[0]), path(1), owner && { uid: owner.uid, gid: owner.gid });
|
|
2875
2890
|
return { result: true };
|
|
2876
2891
|
case "readlink":
|
|
2877
2892
|
return { result: await fs.readlink(path(0)) };
|
|
@@ -2893,8 +2908,16 @@ function dialFor(l, req, open) {
|
|
|
2893
2908
|
);
|
|
2894
2909
|
return { result: port2, transfer: [port2] };
|
|
2895
2910
|
}
|
|
2911
|
+
function created(owner, mode) {
|
|
2912
|
+
return owner && { uid: owner.uid, gid: owner.gid, mode: mode & ~owner.umask };
|
|
2913
|
+
}
|
|
2914
|
+
function made(owner) {
|
|
2915
|
+
const mode = 511 & ~owner.umask;
|
|
2916
|
+
return { uid: owner.uid, gid: owner.gid, mode, parents: mode | 192 };
|
|
2917
|
+
}
|
|
2896
2918
|
function ownerFor(l, self) {
|
|
2897
|
-
|
|
2919
|
+
if (!l.owners || !self) return void 0;
|
|
2920
|
+
return { uid: self.uid, gid: self.gid, umask: self.umask ?? 18 };
|
|
2898
2921
|
}
|
|
2899
2922
|
async function accountOf(l, user) {
|
|
2900
2923
|
const found = await l.users.lookup(user);
|
|
@@ -5782,7 +5805,17 @@ async function followLinks(fs, path) {
|
|
|
5782
5805
|
}
|
|
5783
5806
|
return current;
|
|
5784
5807
|
}
|
|
5785
|
-
function withCommandDirs(fs, names, userDir = async () => void 0) {
|
|
5808
|
+
function withCommandDirs(fs, names, userDir = async () => void 0, owners = false) {
|
|
5809
|
+
async function nearest(path) {
|
|
5810
|
+
const st = await fs.stat(path).catch(() => void 0);
|
|
5811
|
+
if (st || path === "/") return st ?? {};
|
|
5812
|
+
return nearest(path.slice(0, path.lastIndexOf("/")) || "/");
|
|
5813
|
+
}
|
|
5814
|
+
async function owned3(stat2, dir) {
|
|
5815
|
+
if (!owners) return stat2;
|
|
5816
|
+
const { uid = 0, gid = 0 } = dir === void 0 ? {} : await nearest(dir);
|
|
5817
|
+
return { ...stat2, uid, gid };
|
|
5818
|
+
}
|
|
5786
5819
|
async function children2(path) {
|
|
5787
5820
|
if (path === "/") return ["bin", "usr"];
|
|
5788
5821
|
if (path === "/usr") return ["bin"];
|
|
@@ -5791,13 +5824,18 @@ function withCommandDirs(fs, names, userDir = async () => void 0) {
|
|
|
5791
5824
|
return own?.size ? [...own] : void 0;
|
|
5792
5825
|
}
|
|
5793
5826
|
async function virtual(path) {
|
|
5794
|
-
if (path === "/usr" || path === "/bin" || path === "/usr/bin")
|
|
5827
|
+
if (path === "/usr" || path === "/bin" || path === "/usr/bin") {
|
|
5828
|
+
return owned3(synthetic(true, path));
|
|
5829
|
+
}
|
|
5795
5830
|
const name2 = COMMAND.exec(path)?.[1];
|
|
5796
|
-
if (name2 !== void 0)
|
|
5797
|
-
|
|
5831
|
+
if (name2 !== void 0) {
|
|
5832
|
+
return (await names()).has(name2) ? owned3(synthetic(false, path)) : void 0;
|
|
5833
|
+
}
|
|
5834
|
+
if ((await userDir(path))?.size) return owned3(synthetic(true, path), path);
|
|
5798
5835
|
const slash = path.lastIndexOf("/");
|
|
5799
|
-
const
|
|
5800
|
-
|
|
5836
|
+
const dir = path.slice(0, slash);
|
|
5837
|
+
const own = await userDir(dir);
|
|
5838
|
+
return own?.has(path.slice(slash + 1)) ? owned3(synthetic(false, path), dir) : void 0;
|
|
5801
5839
|
}
|
|
5802
5840
|
async function linked(path) {
|
|
5803
5841
|
return await virtual(path) ?? virtual(await followLinks(fs, path));
|
|
@@ -6192,18 +6230,18 @@ var FsWatchers = class {
|
|
|
6192
6230
|
const overrides = {
|
|
6193
6231
|
writeFile: after(fs.writeFile.bind(fs), (path) => [path]),
|
|
6194
6232
|
mkdir: async (path, options) => {
|
|
6195
|
-
const
|
|
6233
|
+
const created3 = [];
|
|
6196
6234
|
if (options?.recursive) {
|
|
6197
6235
|
const parts = normalizePath(path).split("/").filter(Boolean);
|
|
6198
6236
|
for (let at = 1; at < parts.length; at++) {
|
|
6199
6237
|
const ancestor = `/${parts.slice(0, at).join("/")}`;
|
|
6200
|
-
if (
|
|
6238
|
+
if (created3.length > 0 || !await fs.exists(ancestor)) created3.push(ancestor);
|
|
6201
6239
|
}
|
|
6202
6240
|
}
|
|
6203
6241
|
try {
|
|
6204
6242
|
await fs.mkdir(path, options);
|
|
6205
6243
|
} finally {
|
|
6206
|
-
this.changed(...
|
|
6244
|
+
this.changed(...created3, path);
|
|
6207
6245
|
}
|
|
6208
6246
|
},
|
|
6209
6247
|
rm: after(fs.rm.bind(fs), (path) => [path]),
|
|
@@ -6482,7 +6520,7 @@ async function realTarget(fs, path) {
|
|
|
6482
6520
|
}
|
|
6483
6521
|
|
|
6484
6522
|
// src/mount/protocol.ts
|
|
6485
|
-
var DRIVER_PROTOCOL = [1,
|
|
6523
|
+
var DRIVER_PROTOCOL = [1, 2];
|
|
6486
6524
|
function driverVersionError(theirs) {
|
|
6487
6525
|
const major = Array.isArray(theirs) ? theirs[0] : void 0;
|
|
6488
6526
|
if (major === DRIVER_PROTOCOL[0]) return void 0;
|
|
@@ -6584,6 +6622,19 @@ var DriverConnection = class _DriverConnection {
|
|
|
6584
6622
|
};
|
|
6585
6623
|
|
|
6586
6624
|
// src/mount/mount-fs.ts
|
|
6625
|
+
var S_ISGID3 = 1024;
|
|
6626
|
+
var ID = /^\d{1,10}$/;
|
|
6627
|
+
var MAX_ID2 = 4294967294;
|
|
6628
|
+
function idOption(value) {
|
|
6629
|
+
return value === void 0 ? 0 : Number(value);
|
|
6630
|
+
}
|
|
6631
|
+
function checkIds(options) {
|
|
6632
|
+
for (const key of ["uid", "gid"]) {
|
|
6633
|
+
const value = options[key];
|
|
6634
|
+
if (value === void 0) continue;
|
|
6635
|
+
if (!ID.test(value) || Number(value) > MAX_ID2) throw errnoError("EINVAL", `${key}=${value}`);
|
|
6636
|
+
}
|
|
6637
|
+
}
|
|
6587
6638
|
var MAX_LINKS5 = 40;
|
|
6588
6639
|
var STALE_RETRIES = 3;
|
|
6589
6640
|
var SETTLE_ROUNDS = 4;
|
|
@@ -6750,31 +6801,35 @@ var HeldPaths = class extends Map {
|
|
|
6750
6801
|
};
|
|
6751
6802
|
var parentOf6 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
6752
6803
|
var readonly = (mount) => mount.caps.readonly === true || mount.options.ro !== void 0;
|
|
6753
|
-
function inodeless(mount,
|
|
6754
|
-
if (
|
|
6804
|
+
function inodeless(mount, attr2) {
|
|
6805
|
+
if (attr2.ino !== void 0) return false;
|
|
6755
6806
|
if (mount.caps.links) mount.caps = { ...mount.caps, links: false };
|
|
6756
6807
|
return true;
|
|
6757
6808
|
}
|
|
6758
|
-
function statOf(
|
|
6759
|
-
const mtime = new Date(
|
|
6760
|
-
const fallback =
|
|
6809
|
+
function statOf(attr2, path, mount) {
|
|
6810
|
+
const mtime = new Date(attr2.mtime);
|
|
6811
|
+
const fallback = attr2.kind === "directory" ? 16877 : attr2.kind === "symlink" ? 41471 : 33188;
|
|
6761
6812
|
return {
|
|
6762
|
-
isFile:
|
|
6763
|
-
isDirectory:
|
|
6764
|
-
isSymbolicLink:
|
|
6765
|
-
size:
|
|
6766
|
-
mode:
|
|
6813
|
+
isFile: attr2.kind === "file",
|
|
6814
|
+
isDirectory: attr2.kind === "directory",
|
|
6815
|
+
isSymbolicLink: attr2.kind === "symlink",
|
|
6816
|
+
size: attr2.size,
|
|
6817
|
+
mode: attr2.mode ?? fallback,
|
|
6767
6818
|
mtime,
|
|
6768
6819
|
atime: mtime,
|
|
6769
6820
|
ctime: mtime,
|
|
6770
|
-
ino:
|
|
6771
|
-
...!inodeless(mount,
|
|
6821
|
+
ino: attr2.ino ?? inodeOf(path),
|
|
6822
|
+
...!inodeless(mount, attr2) && attr2.nlink !== void 0 ? { nlink: attr2.nlink } : {},
|
|
6772
6823
|
dev: mount.dev,
|
|
6773
6824
|
...readonly(mount) ? { readonly: true } : {},
|
|
6774
6825
|
...mount.maxFile > 0 ? { maxFile: mount.maxFile } : {},
|
|
6775
6826
|
...mount.caps.ranges ? { ranged: true } : {},
|
|
6776
6827
|
...mount.caps.links ? { linkable: true } : {},
|
|
6777
|
-
...
|
|
6828
|
+
...attr2.etag !== void 0 ? { version: attr2.etag } : {},
|
|
6829
|
+
...mount.owners ? {
|
|
6830
|
+
uid: (mount.caps.owners ? attr2.uid : void 0) ?? idOption(mount.options.uid),
|
|
6831
|
+
gid: (mount.caps.owners ? attr2.gid : void 0) ?? idOption(mount.options.gid)
|
|
6832
|
+
} : {}
|
|
6778
6833
|
};
|
|
6779
6834
|
}
|
|
6780
6835
|
function concat4(chunks, total) {
|
|
@@ -6867,6 +6922,7 @@ var MountTable = class {
|
|
|
6867
6922
|
const st = await fs.stat(target);
|
|
6868
6923
|
if (!st.isDirectory) throw errnoError("ENOTDIR", target);
|
|
6869
6924
|
const options = { ...spec.options };
|
|
6925
|
+
if (this.deps.owners) checkIds(options);
|
|
6870
6926
|
const maxFile = options.maxfile !== void 0 ? parseSize(options.maxfile) : void 0;
|
|
6871
6927
|
const opened2 = await this.deps.open(spec.type, { ...spec, target, options });
|
|
6872
6928
|
let mounted;
|
|
@@ -6912,6 +6968,7 @@ var MountTable = class {
|
|
|
6912
6968
|
attrs: /* @__PURE__ */ new Map(),
|
|
6913
6969
|
lists: /* @__PURE__ */ new Map(),
|
|
6914
6970
|
epoch: 0,
|
|
6971
|
+
owners: this.deps.owners === true,
|
|
6915
6972
|
dispose: () => opened2.dispose(),
|
|
6916
6973
|
...opened2.present ? { present: opened2.present } : {}
|
|
6917
6974
|
};
|
|
@@ -7033,15 +7090,15 @@ var MountTable = class {
|
|
|
7033
7090
|
if (cached && cached.expires > Date.now()) return cached.value;
|
|
7034
7091
|
const seen = mount.epoch;
|
|
7035
7092
|
const session = this.sessions.get(path);
|
|
7036
|
-
const
|
|
7093
|
+
const attr2 = await mount.conn.call({ op: "getattr", path: rel2 });
|
|
7037
7094
|
if (mount.epoch !== seen) {
|
|
7038
7095
|
const moved2 = this.sessions.get(path) !== session || this.committing.has(path);
|
|
7039
7096
|
if (settled && moved2 && round < SETTLE_ROUNDS) continue;
|
|
7040
|
-
return
|
|
7097
|
+
return attr2;
|
|
7041
7098
|
}
|
|
7042
7099
|
const ttl = mount.caps.attrTtl ?? 1e3;
|
|
7043
|
-
if (ttl > 0) mount.attrs.set(path, { value:
|
|
7044
|
-
return
|
|
7100
|
+
if (ttl > 0) mount.attrs.set(path, { value: attr2, expires: Date.now() + ttl });
|
|
7101
|
+
return attr2;
|
|
7045
7102
|
}
|
|
7046
7103
|
}
|
|
7047
7104
|
async readdir(mount, path, rel2) {
|
|
@@ -7088,28 +7145,43 @@ var MountFs = class {
|
|
|
7088
7145
|
const found = this.at(path);
|
|
7089
7146
|
if (!found) return path;
|
|
7090
7147
|
const real = normalizePath(path);
|
|
7091
|
-
let
|
|
7148
|
+
let attr2;
|
|
7092
7149
|
try {
|
|
7093
|
-
|
|
7150
|
+
attr2 = await this.table.getattr(found.mount, real, found.rel);
|
|
7094
7151
|
} catch (err) {
|
|
7095
7152
|
if (create && err.code === "ENOENT") return real;
|
|
7096
7153
|
throw err;
|
|
7097
7154
|
}
|
|
7098
|
-
if (
|
|
7155
|
+
if (attr2.kind !== "symlink") return real;
|
|
7099
7156
|
if (hops >= MAX_LINKS5) throw errnoError("ELOOP", path);
|
|
7100
7157
|
const target = await found.mount.conn.call({ op: "readlink", path: found.rel });
|
|
7101
7158
|
return this.follow(this.base.resolvePath(parentOf6(real), target), hops + 1, create);
|
|
7102
7159
|
}
|
|
7103
|
-
async open(mount, rel2, write) {
|
|
7160
|
+
async open(mount, rel2, write, owner) {
|
|
7104
7161
|
return await mount.conn.call({
|
|
7105
7162
|
op: "open",
|
|
7106
7163
|
path: rel2,
|
|
7107
7164
|
write,
|
|
7108
7165
|
create: write,
|
|
7109
7166
|
truncate: write,
|
|
7110
|
-
exclusive: false
|
|
7167
|
+
exclusive: false,
|
|
7168
|
+
...owner
|
|
7111
7169
|
});
|
|
7112
7170
|
}
|
|
7171
|
+
async driverOwner(found, real, owner, directory) {
|
|
7172
|
+
const { mount, rel: rel2 } = found;
|
|
7173
|
+
if (!owner || !mount.owners || !mount.caps.owners) return void 0;
|
|
7174
|
+
const dir = parentOf6(real);
|
|
7175
|
+
const above = statOf(await this.table.getattr(mount, dir, parentOf6(rel2)), dir, mount);
|
|
7176
|
+
const setgid = (above.mode & S_ISGID3) !== 0;
|
|
7177
|
+
let mode = owner.mode;
|
|
7178
|
+
if (directory && setgid) mode = (mode ?? 493) | S_ISGID3;
|
|
7179
|
+
return {
|
|
7180
|
+
uid: owner.uid,
|
|
7181
|
+
gid: setgid ? above.gid : owner.gid,
|
|
7182
|
+
...mode !== void 0 ? { mode } : {}
|
|
7183
|
+
};
|
|
7184
|
+
}
|
|
7113
7185
|
resolvePath(base, path) {
|
|
7114
7186
|
return this.base.resolvePath(base, path);
|
|
7115
7187
|
}
|
|
@@ -7131,9 +7203,9 @@ var MountFs = class {
|
|
|
7131
7203
|
}
|
|
7132
7204
|
async readWhole(mount, real, rel2) {
|
|
7133
7205
|
await this.table.commit(real);
|
|
7134
|
-
const
|
|
7135
|
-
if (
|
|
7136
|
-
if (mount.maxFile > 0 &&
|
|
7206
|
+
const attr2 = await this.table.getattr(mount, real, rel2);
|
|
7207
|
+
if (attr2.kind === "directory") throw errnoError("EISDIR", real);
|
|
7208
|
+
if (mount.maxFile > 0 && attr2.size > mount.maxFile) {
|
|
7137
7209
|
throw errnoError("EFBIG", `${real} is larger than this mount's maxfile (${mount.maxFile})`);
|
|
7138
7210
|
}
|
|
7139
7211
|
const fh = await this.open(mount, rel2, false);
|
|
@@ -7151,7 +7223,7 @@ var MountFs = class {
|
|
|
7151
7223
|
if (bytes.length === 0) break;
|
|
7152
7224
|
chunks.push(bytes);
|
|
7153
7225
|
total += bytes.length;
|
|
7154
|
-
if (bytes.length < chunk2 && total >=
|
|
7226
|
+
if (bytes.length < chunk2 && total >= attr2.size) break;
|
|
7155
7227
|
}
|
|
7156
7228
|
} finally {
|
|
7157
7229
|
await mount.conn.call({ op: "release", fh });
|
|
@@ -7171,18 +7243,19 @@ var MountFs = class {
|
|
|
7171
7243
|
`${real} would be larger than this mount's maxfile (${mount.maxFile})`
|
|
7172
7244
|
);
|
|
7173
7245
|
}
|
|
7246
|
+
const made2 = await this.driverOwner(found, real, owner, false);
|
|
7174
7247
|
for (let attempt = 1; ; attempt++) {
|
|
7175
7248
|
try {
|
|
7176
|
-
return await this.writeWhole(mount, real, rel2, bytes);
|
|
7249
|
+
return await this.writeWhole(mount, real, rel2, bytes, made2);
|
|
7177
7250
|
} catch (err) {
|
|
7178
7251
|
if (err.code !== "ESTALE" || attempt >= STALE_RETRIES) throw err;
|
|
7179
7252
|
}
|
|
7180
7253
|
}
|
|
7181
7254
|
}
|
|
7182
|
-
async writeWhole(mount, real, rel2, bytes) {
|
|
7255
|
+
async writeWhole(mount, real, rel2, bytes, owner) {
|
|
7183
7256
|
await this.table.commit(real);
|
|
7184
7257
|
this.table.forget(mount, real);
|
|
7185
|
-
const fh = await this.open(mount, rel2, true);
|
|
7258
|
+
const fh = await this.open(mount, rel2, true, owner);
|
|
7186
7259
|
const chunk2 = mount.caps.maxIo ?? DEFAULT_IO;
|
|
7187
7260
|
try {
|
|
7188
7261
|
for (let offset = 0; offset < bytes.length; offset += chunk2) {
|
|
@@ -7328,9 +7401,9 @@ var MountFs = class {
|
|
|
7328
7401
|
found.mount
|
|
7329
7402
|
);
|
|
7330
7403
|
}
|
|
7331
|
-
statWriting(
|
|
7404
|
+
statWriting(attr2, real, mount) {
|
|
7332
7405
|
const ends = (this.table.writing(real)?.extents ?? []).map(([, end]) => end);
|
|
7333
|
-
return statOf({ ...
|
|
7406
|
+
return statOf({ ...attr2, size: Math.max(attr2.size, ...ends) }, real, mount);
|
|
7334
7407
|
}
|
|
7335
7408
|
async stat(path) {
|
|
7336
7409
|
const real = await this.follow(path);
|
|
@@ -7369,10 +7442,12 @@ var MountFs = class {
|
|
|
7369
7442
|
const { mount, rel: rel2 } = found;
|
|
7370
7443
|
const real = normalizePath(path);
|
|
7371
7444
|
this.writable(mount, real);
|
|
7445
|
+
const { owner } = options;
|
|
7372
7446
|
if (!options.recursive) {
|
|
7373
7447
|
if (rel2 === "/") throw errnoError("EEXIST", real);
|
|
7448
|
+
const made2 = await this.driverOwner(found, real, owner, true);
|
|
7374
7449
|
this.table.forget(mount, real);
|
|
7375
|
-
await mount.conn.call({ op: "mkdir", path: rel2 });
|
|
7450
|
+
await mount.conn.call({ op: "mkdir", path: rel2, ...made2 });
|
|
7376
7451
|
return;
|
|
7377
7452
|
}
|
|
7378
7453
|
const parts = rel2.split("/").filter(Boolean);
|
|
@@ -7382,8 +7457,10 @@ var MountFs = class {
|
|
|
7382
7457
|
const exists = await this.table.getattr(mount, full, sub).catch(() => void 0);
|
|
7383
7458
|
if (exists?.kind === "directory") continue;
|
|
7384
7459
|
if (exists) throw errnoError("ENOTDIR", full);
|
|
7460
|
+
const own = n === parts.length ? owner : owner && { ...owner, mode: owner.parents };
|
|
7461
|
+
const made2 = await this.driverOwner({ mount, rel: sub }, full, own, true);
|
|
7385
7462
|
this.table.forget(mount, full);
|
|
7386
|
-
await mount.conn.call({ op: "mkdir", path: sub });
|
|
7463
|
+
await mount.conn.call({ op: "mkdir", path: sub, ...made2 });
|
|
7387
7464
|
}
|
|
7388
7465
|
}
|
|
7389
7466
|
async rm(path, options = {}) {
|
|
@@ -7394,21 +7471,21 @@ var MountFs = class {
|
|
|
7394
7471
|
if (rel2 === "/") throw errnoError("EBUSY", `${real} is a mount point`);
|
|
7395
7472
|
this.writable(mount, real);
|
|
7396
7473
|
await this.table.commitUnder(real);
|
|
7397
|
-
let
|
|
7474
|
+
let attr2;
|
|
7398
7475
|
try {
|
|
7399
|
-
|
|
7476
|
+
attr2 = await this.table.getattr(mount, real, rel2);
|
|
7400
7477
|
} catch (err) {
|
|
7401
7478
|
if (options.force && err.code === "ENOENT") return;
|
|
7402
7479
|
throw err;
|
|
7403
7480
|
}
|
|
7404
7481
|
this.table.forget(mount, real);
|
|
7405
|
-
if (
|
|
7482
|
+
if (attr2.kind === "directory" && options.recursive) {
|
|
7406
7483
|
for (const entry of await this.table.readdir(mount, real, rel2)) {
|
|
7407
7484
|
await this.rm(`${real}/${entry.name}`, { recursive: true, force: options.force ?? false });
|
|
7408
7485
|
}
|
|
7409
7486
|
this.table.forget(mount, real);
|
|
7410
7487
|
}
|
|
7411
|
-
await mount.conn.call({ op:
|
|
7488
|
+
await mount.conn.call({ op: attr2.kind === "directory" ? "rmdir" : "unlink", path: rel2 });
|
|
7412
7489
|
this.table.forget(mount, real);
|
|
7413
7490
|
}
|
|
7414
7491
|
async rename(from, to) {
|
|
@@ -7462,8 +7539,10 @@ var MountFs = class {
|
|
|
7462
7539
|
this.writable(found.mount, normalizePath(path));
|
|
7463
7540
|
if (!found.mount.caps.symlinks)
|
|
7464
7541
|
throw errnoError("EPERM", `${path}: this file system has no symlinks`);
|
|
7542
|
+
const link2 = owner && { uid: owner.uid, gid: owner.gid };
|
|
7543
|
+
const made2 = await this.driverOwner(found, normalizePath(path), link2, false);
|
|
7465
7544
|
this.table.forget(found.mount, normalizePath(path));
|
|
7466
|
-
await found.mount.conn.call({ op: "symlink", target, path: found.rel });
|
|
7545
|
+
await found.mount.conn.call({ op: "symlink", target, path: found.rel, ...made2 });
|
|
7467
7546
|
}
|
|
7468
7547
|
async realpath(path, follow2) {
|
|
7469
7548
|
if (this.at(path) || !this.base.realpath) throw errnoError("ENOSYS", path);
|
|
@@ -7478,13 +7557,29 @@ var MountFs = class {
|
|
|
7478
7557
|
}
|
|
7479
7558
|
async chown(path, change) {
|
|
7480
7559
|
const real = change.follow === false || change.kind === "new" ? path : await this.follow(path);
|
|
7481
|
-
|
|
7482
|
-
|
|
7483
|
-
throw errnoError("EPERM", `${path}: this file system keeps no owners`);
|
|
7484
|
-
}
|
|
7560
|
+
const found = this.at(real);
|
|
7561
|
+
if (found) return this.chownMounted(found, normalizePath(real), change);
|
|
7485
7562
|
if (!this.base.chown) throw errnoError("EPERM", path);
|
|
7486
7563
|
return this.base.chown(real, change);
|
|
7487
7564
|
}
|
|
7565
|
+
async chownMounted(found, real, change) {
|
|
7566
|
+
const { mount, rel: rel2 } = found;
|
|
7567
|
+
if (!mount.owners || !mount.caps.owners) {
|
|
7568
|
+
if (change.kind === "new") return;
|
|
7569
|
+
throw errnoError("EPERM", `${real}: this file system keeps no owners`);
|
|
7570
|
+
}
|
|
7571
|
+
this.writable(mount, real);
|
|
7572
|
+
const { uid, gid, mode } = change;
|
|
7573
|
+
const fresh = change.kind === "new" && { uid, gid, mode };
|
|
7574
|
+
const set2 = fresh ? await this.driverOwner(found, real, fresh, false) : change;
|
|
7575
|
+
this.table.forget(mount, real);
|
|
7576
|
+
const attrs = Object.entries({ uid: set2.uid, gid: set2.gid, mode: set2.mode });
|
|
7577
|
+
await mount.conn.call({
|
|
7578
|
+
op: "setattr",
|
|
7579
|
+
path: rel2,
|
|
7580
|
+
...Object.fromEntries(attrs.filter(([, value]) => value !== void 0))
|
|
7581
|
+
});
|
|
7582
|
+
}
|
|
7488
7583
|
async chmod(path, mode) {
|
|
7489
7584
|
const found = this.at(path);
|
|
7490
7585
|
if (!found) return this.base.chmod(path, mode);
|
|
@@ -7591,7 +7686,10 @@ function mkdirOptions(entry, mode = 511) {
|
|
|
7591
7686
|
}
|
|
7592
7687
|
async function chown(entry, path, req) {
|
|
7593
7688
|
const cred = entry.cred?.();
|
|
7594
|
-
if (!cred)
|
|
7689
|
+
if (!cred) {
|
|
7690
|
+
await (req.op === "chown" ? entry.fs.stat(path) : entry.fs.lstat(path));
|
|
7691
|
+
return done;
|
|
7692
|
+
}
|
|
7595
7693
|
await chownAs(entry.fs, cred, path, {
|
|
7596
7694
|
...req.uid !== void 0 ? { uid: req.uid } : {},
|
|
7597
7695
|
...req.gid !== void 0 ? { gid: req.gid } : {},
|
|
@@ -8681,6 +8779,11 @@ var TOKEN3 = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
|
8681
8779
|
function message(e) {
|
|
8682
8780
|
return e instanceof Error ? e.message : String(e);
|
|
8683
8781
|
}
|
|
8782
|
+
var ERRNO = /^E[A-Z]+$|^EAI_[A-Z]+$/;
|
|
8783
|
+
function errnoOf(e) {
|
|
8784
|
+
const code = e?.code;
|
|
8785
|
+
return typeof code === "string" && ERRNO.test(code) ? code : "ECONNREFUSED";
|
|
8786
|
+
}
|
|
8684
8787
|
function fail(errno, text) {
|
|
8685
8788
|
return { ok: false, errno, message: text };
|
|
8686
8789
|
}
|
|
@@ -8724,13 +8827,13 @@ var WsHandles = class {
|
|
|
8724
8827
|
let socket;
|
|
8725
8828
|
try {
|
|
8726
8829
|
socket = await transport.websocket({
|
|
8727
|
-
url: req.url,
|
|
8830
|
+
url: toHostLoopback(req.url),
|
|
8728
8831
|
protocols: req.protocols,
|
|
8729
8832
|
headers: req.headers,
|
|
8730
8833
|
signal: entry.abort.signal
|
|
8731
8834
|
});
|
|
8732
8835
|
} catch (e) {
|
|
8733
|
-
return fail(
|
|
8836
|
+
return fail(errnoOf(e), message(e));
|
|
8734
8837
|
}
|
|
8735
8838
|
if (!this.open.has(handle)) {
|
|
8736
8839
|
socket.close(1001, "the program went away");
|
|
@@ -11415,6 +11518,7 @@ function spawnWasmProcess(opts) {
|
|
|
11415
11518
|
cwd: opts.cwd,
|
|
11416
11519
|
sab: tsab,
|
|
11417
11520
|
cred: copyCred(process.cred),
|
|
11521
|
+
owners: opts.owners === true,
|
|
11418
11522
|
...opts.ppid !== void 0 ? { ppid: opts.ppid } : {},
|
|
11419
11523
|
thread
|
|
11420
11524
|
};
|
|
@@ -11808,6 +11912,17 @@ var SettlingChildren = class {
|
|
|
11808
11912
|
};
|
|
11809
11913
|
|
|
11810
11914
|
// src/mount/driver.ts
|
|
11915
|
+
function ownerOf2(req) {
|
|
11916
|
+
const owner = {
|
|
11917
|
+
...req.uid !== void 0 ? { uid: req.uid } : {},
|
|
11918
|
+
...req.gid !== void 0 ? { gid: req.gid } : {},
|
|
11919
|
+
...req.mode !== void 0 ? { mode: req.mode } : {}
|
|
11920
|
+
};
|
|
11921
|
+
return Object.keys(owner).length > 0 ? owner : void 0;
|
|
11922
|
+
}
|
|
11923
|
+
function withOwner(base, owner) {
|
|
11924
|
+
return owner ? { ...base, owner } : base;
|
|
11925
|
+
}
|
|
11811
11926
|
function fsError2(code, message3 = code) {
|
|
11812
11927
|
return Object.assign(new Error(message3), { code });
|
|
11813
11928
|
}
|
|
@@ -11818,13 +11933,19 @@ async function dispatch(h, req) {
|
|
|
11818
11933
|
case "readdir":
|
|
11819
11934
|
return h.readdir(req.path);
|
|
11820
11935
|
case "open":
|
|
11821
|
-
return h.open(
|
|
11822
|
-
|
|
11823
|
-
|
|
11824
|
-
|
|
11825
|
-
|
|
11826
|
-
|
|
11827
|
-
|
|
11936
|
+
return h.open(
|
|
11937
|
+
req.path,
|
|
11938
|
+
withOwner(
|
|
11939
|
+
{
|
|
11940
|
+
write: req.write,
|
|
11941
|
+
create: req.create,
|
|
11942
|
+
truncate: req.truncate,
|
|
11943
|
+
exclusive: req.exclusive,
|
|
11944
|
+
...req.ifMatch !== void 0 ? { ifMatch: req.ifMatch } : {}
|
|
11945
|
+
},
|
|
11946
|
+
ownerOf2(req)
|
|
11947
|
+
)
|
|
11948
|
+
);
|
|
11828
11949
|
case "read":
|
|
11829
11950
|
return h.read(req.fh, req.offset, req.size);
|
|
11830
11951
|
case "write":
|
|
@@ -11832,7 +11953,7 @@ async function dispatch(h, req) {
|
|
|
11832
11953
|
case "release":
|
|
11833
11954
|
return h.release(req.fh);
|
|
11834
11955
|
case "mkdir":
|
|
11835
|
-
return h.mkdir(req.path);
|
|
11956
|
+
return ownerOf2(req) ? h.mkdir(req.path, ownerOf2(req)) : h.mkdir(req.path);
|
|
11836
11957
|
case "rmdir":
|
|
11837
11958
|
return h.rmdir(req.path);
|
|
11838
11959
|
case "unlink":
|
|
@@ -11844,7 +11965,7 @@ async function dispatch(h, req) {
|
|
|
11844
11965
|
return h.link(req.from, req.to);
|
|
11845
11966
|
case "symlink":
|
|
11846
11967
|
if (!h.symlink) throw fsError2("EPERM", "this file system has no symlinks");
|
|
11847
|
-
return h.symlink(req.target, req.path);
|
|
11968
|
+
return ownerOf2(req) ? h.symlink(req.target, req.path, ownerOf2(req)) : h.symlink(req.target, req.path);
|
|
11848
11969
|
case "readlink":
|
|
11849
11970
|
if (!h.readlink) throw fsError2("EINVAL", `${req.path} is not a symlink`);
|
|
11850
11971
|
return h.readlink(req.path);
|
|
@@ -11852,7 +11973,9 @@ async function dispatch(h, req) {
|
|
|
11852
11973
|
return h.setattr?.(req.path, {
|
|
11853
11974
|
...req.mode !== void 0 ? { mode: req.mode } : {},
|
|
11854
11975
|
...req.mtime !== void 0 ? { mtime: req.mtime } : {},
|
|
11855
|
-
...req.size !== void 0 ? { size: req.size } : {}
|
|
11976
|
+
...req.size !== void 0 ? { size: req.size } : {},
|
|
11977
|
+
...req.uid !== void 0 ? { uid: req.uid } : {},
|
|
11978
|
+
...req.gid !== void 0 ? { gid: req.gid } : {}
|
|
11856
11979
|
});
|
|
11857
11980
|
case "statfs":
|
|
11858
11981
|
return h.statfs?.() ?? null;
|
|
@@ -12003,8 +12126,8 @@ function kernelFsHandlers(fs) {
|
|
|
12003
12126
|
getattr: async (path) => attrOf(await fs.lstat(path)),
|
|
12004
12127
|
readdir: async (path) => (await fs.readdirStat(path)).flatMap(([name2, st]) => {
|
|
12005
12128
|
if (!st) return [];
|
|
12006
|
-
const
|
|
12007
|
-
return [{ name: name2, kind:
|
|
12129
|
+
const attr2 = attrOf(st);
|
|
12130
|
+
return [{ name: name2, kind: attr2.kind, attr: attr2 }];
|
|
12008
12131
|
}),
|
|
12009
12132
|
async open(path, flags) {
|
|
12010
12133
|
const st = await existing(path);
|
|
@@ -12434,7 +12557,7 @@ function hostfsHandlers(current, againMs = RESTORE_AGAIN_MS) {
|
|
|
12434
12557
|
"list",
|
|
12435
12558
|
{ path: rel(path) }
|
|
12436
12559
|
);
|
|
12437
|
-
return entries.map(({ name: name2, attr }) => ({ name: name2, kind:
|
|
12560
|
+
return entries.map(({ name: name2, attr: attr2 }) => ({ name: name2, kind: attr2.kind, attr: attr2 }));
|
|
12438
12561
|
},
|
|
12439
12562
|
async open(path, flags) {
|
|
12440
12563
|
const client = current();
|
|
@@ -12924,8 +13047,8 @@ var ChunkedBytes = class {
|
|
|
12924
13047
|
}
|
|
12925
13048
|
return out;
|
|
12926
13049
|
}
|
|
12927
|
-
write(offset, bytes,
|
|
12928
|
-
const whole =
|
|
13050
|
+
write(offset, bytes, owned3 = false) {
|
|
13051
|
+
const whole = owned3 && bytes.byteOffset === 0 && bytes.byteLength === bytes.buffer.byteLength;
|
|
12929
13052
|
for (let done4 = 0; done4 < bytes.length; ) {
|
|
12930
13053
|
const at = offset + done4;
|
|
12931
13054
|
const index = Math.floor(at / CHUNK3);
|
|
@@ -12958,18 +13081,42 @@ var ChunkedBytes = class {
|
|
|
12958
13081
|
};
|
|
12959
13082
|
|
|
12960
13083
|
// src/mount/tmpfs.ts
|
|
12961
|
-
function
|
|
12962
|
-
|
|
12963
|
-
|
|
13084
|
+
function idOption2(value) {
|
|
13085
|
+
return value !== void 0 && /^\d+$/.test(value) ? Number(value) : 0;
|
|
13086
|
+
}
|
|
13087
|
+
function created2(ino, kind, mode, from, owner) {
|
|
13088
|
+
return {
|
|
12964
13089
|
kind,
|
|
12965
|
-
ino
|
|
12966
|
-
mode,
|
|
13090
|
+
ino,
|
|
13091
|
+
mode: owner?.mode === void 0 ? mode : mode & ~4095 | owner.mode & 4095,
|
|
12967
13092
|
mtime: Date.now(),
|
|
12968
13093
|
data: new ChunkedBytes(),
|
|
12969
13094
|
target: "",
|
|
12970
13095
|
children: /* @__PURE__ */ new Map(),
|
|
12971
|
-
links: 1
|
|
12972
|
-
|
|
13096
|
+
links: 1,
|
|
13097
|
+
uid: owner?.uid ?? from?.uid ?? 0,
|
|
13098
|
+
gid: owner?.gid ?? from?.gid ?? 0
|
|
13099
|
+
};
|
|
13100
|
+
}
|
|
13101
|
+
function owned2(node, change) {
|
|
13102
|
+
if (change.uid !== void 0) node.uid = change.uid;
|
|
13103
|
+
if (change.gid !== void 0) node.gid = change.gid;
|
|
13104
|
+
}
|
|
13105
|
+
function attr(node) {
|
|
13106
|
+
return {
|
|
13107
|
+
kind: node.kind,
|
|
13108
|
+
size: node.kind === "file" ? node.data.size : node.kind === "symlink" ? node.target.length : 4096,
|
|
13109
|
+
mtime: node.mtime,
|
|
13110
|
+
mode: node.mode,
|
|
13111
|
+
ino: node.ino,
|
|
13112
|
+
...node.kind === "directory" ? {} : { nlink: node.links },
|
|
13113
|
+
uid: node.uid,
|
|
13114
|
+
gid: node.gid
|
|
13115
|
+
};
|
|
13116
|
+
}
|
|
13117
|
+
function tmpfs() {
|
|
13118
|
+
let inodes = 0;
|
|
13119
|
+
const make = (kind, mode, from, owner) => created2(++inodes, kind, mode, from, owner);
|
|
12973
13120
|
const root = make("directory", 16877);
|
|
12974
13121
|
const handles = /* @__PURE__ */ new Map();
|
|
12975
13122
|
let nextFh = 0;
|
|
@@ -12996,14 +13143,6 @@ function tmpfs() {
|
|
|
12996
13143
|
if (dir.kind !== "directory") throw fsError2("ENOTDIR", path);
|
|
12997
13144
|
return { dir, name: name2 };
|
|
12998
13145
|
}
|
|
12999
|
-
const attr = (node) => ({
|
|
13000
|
-
kind: node.kind,
|
|
13001
|
-
size: node.kind === "file" ? node.data.size : node.kind === "symlink" ? node.target.length : 4096,
|
|
13002
|
-
mtime: node.mtime,
|
|
13003
|
-
mode: node.mode,
|
|
13004
|
-
ino: node.ino,
|
|
13005
|
-
...node.kind === "directory" ? {} : { nlink: node.links }
|
|
13006
|
-
});
|
|
13007
13146
|
const handle = (fh) => {
|
|
13008
13147
|
const found = handles.get(fh);
|
|
13009
13148
|
if (!found) throw fsError2("EBADF", `handle ${fh}`);
|
|
@@ -13016,11 +13155,16 @@ function tmpfs() {
|
|
|
13016
13155
|
if (existing?.kind === "directory" && flags.write) throw fsError2("EISDIR", path);
|
|
13017
13156
|
if (existing) return existing;
|
|
13018
13157
|
if (!flags.create) throw fsError2("ENOENT", path);
|
|
13019
|
-
const node = make("file", 33188);
|
|
13158
|
+
const node = make("file", 33188, dir, flags.owner);
|
|
13020
13159
|
place(dir, name2, node);
|
|
13021
13160
|
return node;
|
|
13022
13161
|
}
|
|
13023
13162
|
return {
|
|
13163
|
+
mount(info) {
|
|
13164
|
+
root.uid = idOption2(info.options.uid);
|
|
13165
|
+
root.gid = idOption2(info.options.gid);
|
|
13166
|
+
return void 0;
|
|
13167
|
+
},
|
|
13024
13168
|
async getattr(path) {
|
|
13025
13169
|
return attr(find(path));
|
|
13026
13170
|
},
|
|
@@ -13053,10 +13197,10 @@ function tmpfs() {
|
|
|
13053
13197
|
handle(fh);
|
|
13054
13198
|
handles.delete(fh);
|
|
13055
13199
|
},
|
|
13056
|
-
async mkdir(path) {
|
|
13200
|
+
async mkdir(path, owner) {
|
|
13057
13201
|
const { dir, name: name2 } = parent(path);
|
|
13058
13202
|
if (dir.children.has(name2)) throw fsError2("EEXIST", path);
|
|
13059
|
-
place(dir, name2, make("directory", 16877));
|
|
13203
|
+
place(dir, name2, make("directory", 16877, dir, owner));
|
|
13060
13204
|
},
|
|
13061
13205
|
async rmdir(path) {
|
|
13062
13206
|
const { dir, name: name2 } = parent(path);
|
|
@@ -13103,10 +13247,10 @@ function tmpfs() {
|
|
|
13103
13247
|
place(dir, name2, node);
|
|
13104
13248
|
node.links++;
|
|
13105
13249
|
},
|
|
13106
|
-
async symlink(target, path) {
|
|
13250
|
+
async symlink(target, path, owner) {
|
|
13107
13251
|
const { dir, name: name2 } = parent(path);
|
|
13108
13252
|
if (dir.children.has(name2)) throw fsError2("EEXIST", path);
|
|
13109
|
-
const node = make("symlink", 41471);
|
|
13253
|
+
const node = make("symlink", 41471, dir, owner && { ...owner, mode: 511 });
|
|
13110
13254
|
node.target = target;
|
|
13111
13255
|
place(dir, name2, node);
|
|
13112
13256
|
},
|
|
@@ -13125,6 +13269,7 @@ function tmpfs() {
|
|
|
13125
13269
|
node.mtime = Date.now();
|
|
13126
13270
|
}
|
|
13127
13271
|
if (change.mtime !== void 0) node.mtime = change.mtime;
|
|
13272
|
+
owned2(node, change);
|
|
13128
13273
|
},
|
|
13129
13274
|
async statfs() {
|
|
13130
13275
|
return { bsize: 4096, blocks: 262144, bfree: 262144 };
|
|
@@ -13445,7 +13590,8 @@ var Launcher = class {
|
|
|
13445
13590
|
this.mounts = new MountTable({
|
|
13446
13591
|
open: (type, spec) => this.driver(type, spec),
|
|
13447
13592
|
busy: (target) => [...this.openFiles].some((nodes) => nodes.holds(target)) || heldUnder(this.held, target),
|
|
13448
|
-
changed: this.watchers.changed.bind(this.watchers)
|
|
13593
|
+
changed: this.watchers.changed.bind(this.watchers),
|
|
13594
|
+
owners: this.owners
|
|
13449
13595
|
});
|
|
13450
13596
|
this.base = this.watchers.wrap(this.mounts.wrap(options.fs));
|
|
13451
13597
|
this.createWorker = options.createWorker;
|
|
@@ -13478,7 +13624,8 @@ var Launcher = class {
|
|
|
13478
13624
|
const fs = withCommandDirs(
|
|
13479
13625
|
this.base,
|
|
13480
13626
|
async () => new Set((await this.commands()).keys()),
|
|
13481
|
-
(dir) => this.userCommandDir(dir)
|
|
13627
|
+
(dir) => this.userCommandDir(dir),
|
|
13628
|
+
this.owners
|
|
13482
13629
|
);
|
|
13483
13630
|
this.nodes = new VfsNodes(fs, (path) => this.released(path));
|
|
13484
13631
|
this.nodes.keepsOnDisk = true;
|
|
@@ -14008,7 +14155,15 @@ var Launcher = class {
|
|
|
14008
14155
|
serveFilesystem(
|
|
14009
14156
|
port2,
|
|
14010
14157
|
tmpfs(),
|
|
14011
|
-
{
|
|
14158
|
+
{
|
|
14159
|
+
symlinks: true,
|
|
14160
|
+
links: true,
|
|
14161
|
+
chmod: true,
|
|
14162
|
+
owners: true,
|
|
14163
|
+
linkTimes: true,
|
|
14164
|
+
ranges: true,
|
|
14165
|
+
attrTtl: 0
|
|
14166
|
+
},
|
|
14012
14167
|
{ owned: true }
|
|
14013
14168
|
);
|
|
14014
14169
|
return {
|
|
@@ -14081,6 +14236,11 @@ var Launcher = class {
|
|
|
14081
14236
|
void this.unlinked.sweep(entry.target);
|
|
14082
14237
|
return entry;
|
|
14083
14238
|
}
|
|
14239
|
+
mountedBy(spec, cred) {
|
|
14240
|
+
if (!this.owners || cred.euid === 0 && cred.egid === 0) return spec;
|
|
14241
|
+
const ids = { uid: String(cred.euid), gid: String(cred.egid) };
|
|
14242
|
+
return { ...spec, options: { ...ids, ...spec.options } };
|
|
14243
|
+
}
|
|
14084
14244
|
mountRoot(path) {
|
|
14085
14245
|
let root = "/";
|
|
14086
14246
|
for (const { target } of this.mounts.list()) {
|
|
@@ -14124,7 +14284,7 @@ var Launcher = class {
|
|
|
14124
14284
|
async processMount(pid, call, signal) {
|
|
14125
14285
|
const spec = mountCall(call);
|
|
14126
14286
|
await this.permit({ op: "mount", pid, ...spec, options: { ...spec.options } });
|
|
14127
|
-
const entry = await this.mount(spec);
|
|
14287
|
+
const entry = await this.mount(this.mountedBy(spec, this.credOf(pid)));
|
|
14128
14288
|
if (signal.aborted) this.umount(entry.target, true);
|
|
14129
14289
|
}
|
|
14130
14290
|
async processUmount(pid, target, flags) {
|