@ai-ecoverse/slicc-kernel 1.8.11 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -1
- package/dist/index.js +391 -2
- package/dist/index.js.map +4 -4
- package/dist/kernel-worker.js +486 -66
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +382 -28
- package/dist/node-process-worker.js.map +4 -4
- package/dist/node.js +945 -179
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +382 -28
- package/dist/process-worker.js.map +4 -4
- package/package.json +2 -2
package/dist/process-worker.js
CHANGED
|
@@ -265,31 +265,31 @@ function createNodeOps(h) {
|
|
|
265
265
|
mtime,
|
|
266
266
|
ctime: new Date(st.ctimeMs ?? mtime.getTime()),
|
|
267
267
|
blksize: 4096,
|
|
268
|
-
blocks: Math.ceil(size / 4096)
|
|
268
|
+
blocks: Math.ceil(size / 4096) * 8
|
|
269
269
|
};
|
|
270
270
|
},
|
|
271
|
-
setattr(node,
|
|
271
|
+
setattr(node, attr2) {
|
|
272
272
|
if (node.live.orphan) {
|
|
273
|
-
if (
|
|
274
|
-
node.mode = node.mode & ~PERM_MASK |
|
|
273
|
+
if (attr2.mode !== void 0 && attr2.mode !== null) {
|
|
274
|
+
node.mode = node.mode & ~PERM_MASK | attr2.mode & PERM_MASK;
|
|
275
275
|
}
|
|
276
|
-
if (
|
|
276
|
+
if (attr2.size !== void 0 && attr2.size !== null) truncate(node, attr2.size);
|
|
277
277
|
return;
|
|
278
278
|
}
|
|
279
279
|
const path = liveNodePath(node);
|
|
280
|
-
if (
|
|
281
|
-
const perm =
|
|
280
|
+
if (attr2.mode !== void 0 && attr2.mode !== null) {
|
|
281
|
+
const perm = attr2.mode & PERM_MASK;
|
|
282
282
|
if (perm !== (node.mode & PERM_MASK)) {
|
|
283
283
|
metadataCall(() => bridgeOf(node).chmod(path, perm));
|
|
284
284
|
node.mode = node.mode & ~PERM_MASK | perm;
|
|
285
285
|
}
|
|
286
286
|
}
|
|
287
|
-
if (
|
|
288
|
-
truncate(node,
|
|
287
|
+
if (attr2.size !== void 0 && attr2.size !== null && Fs.isFile(node.mode)) {
|
|
288
|
+
truncate(node, attr2.size);
|
|
289
289
|
}
|
|
290
|
-
const mtime = toMs(
|
|
290
|
+
const mtime = toMs(attr2.mtime) ?? attr2.timestamp;
|
|
291
291
|
if (mtime !== void 0) {
|
|
292
|
-
const atime = toMs(
|
|
292
|
+
const atime = toMs(attr2.atime) ?? mtime;
|
|
293
293
|
flushNode(node);
|
|
294
294
|
metadataCall(() => bridgeOf(node).utimes(path, atime, mtime));
|
|
295
295
|
}
|
|
@@ -524,6 +524,7 @@ function mountLiveVfsDirs(Fs, bridge, dirs, warn) {
|
|
|
524
524
|
}
|
|
525
525
|
const plugin = Fs.filesystems.SLICC_LIVE_FS ?? createLiveVfsPlugin(Fs);
|
|
526
526
|
Fs.filesystems.SLICC_LIVE_FS = plugin;
|
|
527
|
+
guardStatfs(Fs);
|
|
527
528
|
const mounted = [];
|
|
528
529
|
for (const dir of outermostDirs(dirs)) {
|
|
529
530
|
if (dir === "/") continue;
|
|
@@ -546,6 +547,7 @@ function liveRoot(Fs, bridge) {
|
|
|
546
547
|
plugin.mounts.add(root.mount);
|
|
547
548
|
invalidateLiveVfs(Fs, plugin);
|
|
548
549
|
guardRenames(Fs);
|
|
550
|
+
guardStatfs(Fs);
|
|
549
551
|
const memfs = root.memfs ?? root.node_ops;
|
|
550
552
|
const live = plugin.node_ops;
|
|
551
553
|
root.memfs = memfs;
|
|
@@ -577,6 +579,30 @@ function crosses(Fs, from, to) {
|
|
|
577
579
|
return false;
|
|
578
580
|
}
|
|
579
581
|
}
|
|
582
|
+
function guardStatfs(Fs) {
|
|
583
|
+
const statfsNode = Fs.statfsNode?.bind(Fs);
|
|
584
|
+
if (!statfsNode || Fs.sliccStatfs) return;
|
|
585
|
+
Fs.sliccStatfs = true;
|
|
586
|
+
Fs.statfsNode = (node) => {
|
|
587
|
+
const defaults = statfsNode(node);
|
|
588
|
+
let usage;
|
|
589
|
+
try {
|
|
590
|
+
usage = node.live ? node.mount?.opts?.bridge?.statfs?.() : void 0;
|
|
591
|
+
} catch {
|
|
592
|
+
return defaults;
|
|
593
|
+
}
|
|
594
|
+
if (!usage) return defaults;
|
|
595
|
+
const free = Math.max(0, Math.floor((usage.quota - usage.usage) / 4096));
|
|
596
|
+
return {
|
|
597
|
+
...defaults,
|
|
598
|
+
bsize: 4096,
|
|
599
|
+
frsize: 4096,
|
|
600
|
+
blocks: Math.ceil(usage.quota / 4096),
|
|
601
|
+
bfree: free,
|
|
602
|
+
bavail: free
|
|
603
|
+
};
|
|
604
|
+
};
|
|
605
|
+
}
|
|
580
606
|
function guardRenames(Fs) {
|
|
581
607
|
const rename = Fs.rename?.bind(Fs);
|
|
582
608
|
if (!rename || Fs.sliccRename) return;
|
|
@@ -670,6 +696,11 @@ var init_emscripten_vfs_hook = __esm({
|
|
|
670
696
|
});
|
|
671
697
|
|
|
672
698
|
// src/realm/sync-fs-wire.ts
|
|
699
|
+
function parseSyncFsUsage(json) {
|
|
700
|
+
const u = json;
|
|
701
|
+
if (!u || typeof u.quota !== "number" || typeof u.usage !== "number") return null;
|
|
702
|
+
return { quota: u.quota, usage: u.usage };
|
|
703
|
+
}
|
|
673
704
|
function syncError(code2, label) {
|
|
674
705
|
return Object.assign(new Error(`${code2}: ${label}`), { code: code2 });
|
|
675
706
|
}
|
|
@@ -911,7 +942,8 @@ function createSyncFsSabBridge(transport, opts = {}) {
|
|
|
911
942
|
},
|
|
912
943
|
utimes: (path, atimeMs, mtimeMs) => {
|
|
913
944
|
run({ op: "utimes", path, atimeMs, mtimeMs }, path);
|
|
914
|
-
}
|
|
945
|
+
},
|
|
946
|
+
statfs: () => parseSyncFsUsage(json({ op: "statfs", path: "/" }, "/"))
|
|
915
947
|
};
|
|
916
948
|
}
|
|
917
949
|
var init_sync_sab_bridge = __esm({
|
|
@@ -1878,7 +1910,34 @@ function useDevFd(Fs) {
|
|
|
1878
1910
|
return fstat.call(Fs, fd);
|
|
1879
1911
|
};
|
|
1880
1912
|
}
|
|
1881
|
-
|
|
1913
|
+
function mountTable() {
|
|
1914
|
+
const root = globalThis.navigator?.storage ? "opfs" : "memory";
|
|
1915
|
+
return [`${root} / ${root} rw 0 0`, "devfs /dev devfs rw 0 0", "proc /proc proc rw 0 0", ""].join(
|
|
1916
|
+
"\n"
|
|
1917
|
+
);
|
|
1918
|
+
}
|
|
1919
|
+
function useMounts(Fs) {
|
|
1920
|
+
const { writeFile } = Fs;
|
|
1921
|
+
if (typeof Fs.open !== "function" || typeof writeFile !== "function") return;
|
|
1922
|
+
try {
|
|
1923
|
+
writeFile.call(Fs, "/proc/mounts", mountTable());
|
|
1924
|
+
} catch {
|
|
1925
|
+
return;
|
|
1926
|
+
}
|
|
1927
|
+
const open = Fs.open.bind(Fs);
|
|
1928
|
+
Fs.open = (path, flags, mode) => {
|
|
1929
|
+
if (path !== "/etc/mtab" || (flags & (O_ACCMODE | O_CREAT2)) !== 0) {
|
|
1930
|
+
return open(path, flags, mode);
|
|
1931
|
+
}
|
|
1932
|
+
try {
|
|
1933
|
+
return open(path, flags, mode);
|
|
1934
|
+
} catch (e) {
|
|
1935
|
+
if (e?.errno !== wasiErrno("ENOENT")) throw e;
|
|
1936
|
+
return open("/proc/mounts", flags, mode);
|
|
1937
|
+
}
|
|
1938
|
+
};
|
|
1939
|
+
}
|
|
1940
|
+
var O_CLOEXEC, FD_CLOEXEC, F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_DUPFD_CLOEXEC, tracked, IMPORT_NAMES, EBADF, DIR_MODE, LINK_MODE, O_ACCMODE, O_CREAT2;
|
|
1882
1941
|
var init_process_fds = __esm({
|
|
1883
1942
|
"src/process/process-fds.ts"() {
|
|
1884
1943
|
"use strict";
|
|
@@ -1904,6 +1963,8 @@ var init_process_fds = __esm({
|
|
|
1904
1963
|
EBADF = 8;
|
|
1905
1964
|
DIR_MODE = 16749;
|
|
1906
1965
|
LINK_MODE = 41408;
|
|
1966
|
+
O_ACCMODE = 3;
|
|
1967
|
+
O_CREAT2 = 64;
|
|
1907
1968
|
}
|
|
1908
1969
|
});
|
|
1909
1970
|
|
|
@@ -1986,7 +2047,7 @@ function inheritedSlot(fd, stream) {
|
|
|
1986
2047
|
if (stream.sliccKernelFd === void 0) {
|
|
1987
2048
|
const device = stream.path === void 0 ? void 0 : DEVICES[stream.path];
|
|
1988
2049
|
if (!device) return void 0;
|
|
1989
|
-
const access = ACCESS[stream.flags &
|
|
2050
|
+
const access = ACCESS[stream.flags & O_ACCMODE2];
|
|
1990
2051
|
return { fd, device, ...access ? { access } : {} };
|
|
1991
2052
|
}
|
|
1992
2053
|
const flags = stream.sliccKernelSocket ? { flags: stream.flags } : {};
|
|
@@ -2003,7 +2064,7 @@ function placeholder(Fs, streams, entry) {
|
|
|
2003
2064
|
if (entry.kind === "tty") return Fs.open("/dev/tty", O_RDWR);
|
|
2004
2065
|
if (entry.kind === "stream") return Fs.open("/dev/null", O_RDWR);
|
|
2005
2066
|
Fs.mkdirTree(PLACEHOLDER_DIR);
|
|
2006
|
-
return Fs.open(`${PLACEHOLDER_DIR}/${entry.fd}`, O_RDWR |
|
|
2067
|
+
return Fs.open(`${PLACEHOLDER_DIR}/${entry.fd}`, O_RDWR | O_CREAT3);
|
|
2007
2068
|
}
|
|
2008
2069
|
function asFifo(stream, streams, identity) {
|
|
2009
2070
|
const inos = streamInos.get(streams) ?? /* @__PURE__ */ new Map();
|
|
@@ -2037,7 +2098,7 @@ function restoreForkedStreams(Fs, streams, table) {
|
|
|
2037
2098
|
} else {
|
|
2038
2099
|
const placed = place(
|
|
2039
2100
|
Fs,
|
|
2040
|
-
Fs.open(entry.path, entry.flags & ~(
|
|
2101
|
+
Fs.open(entry.path, entry.flags & ~(O_CREAT3 | O_EXCL2 | O_TRUNC2)),
|
|
2041
2102
|
entry.fd
|
|
2042
2103
|
);
|
|
2043
2104
|
setCloseOnExec(placed, (entry.flags & O_CLOEXEC) !== 0);
|
|
@@ -2046,14 +2107,14 @@ function restoreForkedStreams(Fs, streams, table) {
|
|
|
2046
2107
|
}
|
|
2047
2108
|
}
|
|
2048
2109
|
}
|
|
2049
|
-
var O_RDWR,
|
|
2110
|
+
var O_RDWR, O_ACCMODE2, O_CREAT3, O_EXCL2, O_TRUNC2, PLACEHOLDER_DIR, ACCESS, DEVICES, FIFO_MODE, nextStreamIno, streamInos;
|
|
2050
2111
|
var init_process_fork = __esm({
|
|
2051
2112
|
"src/process/process-fork.ts"() {
|
|
2052
2113
|
"use strict";
|
|
2053
2114
|
init_process_fds();
|
|
2054
2115
|
O_RDWR = 2;
|
|
2055
|
-
|
|
2056
|
-
|
|
2116
|
+
O_ACCMODE2 = 3;
|
|
2117
|
+
O_CREAT3 = 64;
|
|
2057
2118
|
O_EXCL2 = 128;
|
|
2058
2119
|
O_TRUNC2 = 512;
|
|
2059
2120
|
PLACEHOLDER_DIR = "/dev/slicc-fd";
|
|
@@ -2197,7 +2258,7 @@ function socketNode(Fs, addr) {
|
|
|
2197
2258
|
const fs = Fs;
|
|
2198
2259
|
let stream;
|
|
2199
2260
|
try {
|
|
2200
|
-
stream = Fs.open(addr.path, O_WRONLY |
|
|
2261
|
+
stream = Fs.open(addr.path, O_WRONLY | O_CREAT4 | O_EXCL3, 493);
|
|
2201
2262
|
} catch (e) {
|
|
2202
2263
|
if (e?.errno === wasiErrno("EEXIST")) {
|
|
2203
2264
|
throw new SyscallError("EADDRINUSE");
|
|
@@ -2328,7 +2389,7 @@ function createSocketKernel(deps) {
|
|
|
2328
2389
|
})
|
|
2329
2390
|
};
|
|
2330
2391
|
}
|
|
2331
|
-
var O_RDWR2, KILLED_BY_SIGPIPE2, O_WRONLY,
|
|
2392
|
+
var O_RDWR2, KILLED_BY_SIGPIPE2, O_WRONLY, O_CREAT4, O_EXCL3;
|
|
2332
2393
|
var init_process_sockets = __esm({
|
|
2333
2394
|
"src/process/process-sockets.ts"() {
|
|
2334
2395
|
"use strict";
|
|
@@ -2339,15 +2400,302 @@ var init_process_sockets = __esm({
|
|
|
2339
2400
|
O_RDWR2 = 2;
|
|
2340
2401
|
KILLED_BY_SIGPIPE2 = 128 + 13;
|
|
2341
2402
|
O_WRONLY = 1;
|
|
2342
|
-
|
|
2403
|
+
O_CREAT4 = 64;
|
|
2343
2404
|
O_EXCL3 = 128;
|
|
2344
2405
|
}
|
|
2345
2406
|
});
|
|
2346
2407
|
|
|
2408
|
+
// src/process/procfs.ts
|
|
2409
|
+
function commOf(info) {
|
|
2410
|
+
const name = info.argv[0] ?? "";
|
|
2411
|
+
return name.slice(name.lastIndexOf("/") + 1).slice(0, 15);
|
|
2412
|
+
}
|
|
2413
|
+
function ttyNumber(tty) {
|
|
2414
|
+
const pts = tty && /^\/dev\/pts\/(\d+)$/.exec(tty);
|
|
2415
|
+
if (pts) return 136 << 8 | Number(pts[1]);
|
|
2416
|
+
const vt = tty && /^\/dev\/tty(\d+)$/.exec(tty);
|
|
2417
|
+
return vt ? 4 << 8 | Number(vt[1]) : 0;
|
|
2418
|
+
}
|
|
2419
|
+
function ticks(ms) {
|
|
2420
|
+
return Math.max(0, Math.floor(ms * HZ / 1e3));
|
|
2421
|
+
}
|
|
2422
|
+
function pidStat(info, boot) {
|
|
2423
|
+
const fields = [
|
|
2424
|
+
info.pid,
|
|
2425
|
+
`(${commOf(info)})`,
|
|
2426
|
+
info.state,
|
|
2427
|
+
info.ppid,
|
|
2428
|
+
info.pgid,
|
|
2429
|
+
info.sid,
|
|
2430
|
+
ttyNumber(info.tty),
|
|
2431
|
+
info.tty ? info.pgid : -1,
|
|
2432
|
+
4194304,
|
|
2433
|
+
0,
|
|
2434
|
+
0,
|
|
2435
|
+
0,
|
|
2436
|
+
0,
|
|
2437
|
+
0,
|
|
2438
|
+
0,
|
|
2439
|
+
0,
|
|
2440
|
+
0,
|
|
2441
|
+
20,
|
|
2442
|
+
0,
|
|
2443
|
+
1,
|
|
2444
|
+
0,
|
|
2445
|
+
ticks(info.started - boot),
|
|
2446
|
+
0,
|
|
2447
|
+
0,
|
|
2448
|
+
"18446744073709551615",
|
|
2449
|
+
...Array(12).fill(0),
|
|
2450
|
+
17,
|
|
2451
|
+
0,
|
|
2452
|
+
0,
|
|
2453
|
+
0,
|
|
2454
|
+
0,
|
|
2455
|
+
0,
|
|
2456
|
+
0,
|
|
2457
|
+
...Array(7).fill(0),
|
|
2458
|
+
0
|
|
2459
|
+
];
|
|
2460
|
+
return `${fields.join(" ")}
|
|
2461
|
+
`;
|
|
2462
|
+
}
|
|
2463
|
+
function pidStatus(info) {
|
|
2464
|
+
const state = info.state === "Z" ? "Z (zombie)" : "S (sleeping)";
|
|
2465
|
+
const ids = `${UID} ${UID} ${UID} ${UID}`;
|
|
2466
|
+
return [
|
|
2467
|
+
`Name: ${commOf(info)}`,
|
|
2468
|
+
"Umask: 0022",
|
|
2469
|
+
`State: ${state}`,
|
|
2470
|
+
`Tgid: ${info.pid}`,
|
|
2471
|
+
"Ngid: 0",
|
|
2472
|
+
`Pid: ${info.pid}`,
|
|
2473
|
+
`PPid: ${info.ppid}`,
|
|
2474
|
+
"TracerPid: 0",
|
|
2475
|
+
`Uid: ${ids}`,
|
|
2476
|
+
`Gid: ${ids}`,
|
|
2477
|
+
"FDSize: 64",
|
|
2478
|
+
"Groups: ",
|
|
2479
|
+
`NSpid: ${info.pid}`,
|
|
2480
|
+
`NSpgid: ${info.pgid}`,
|
|
2481
|
+
`NSsid: ${info.sid}`,
|
|
2482
|
+
"Threads: 1",
|
|
2483
|
+
"SigQ: 0/0",
|
|
2484
|
+
"SigPnd: 0000000000000000",
|
|
2485
|
+
"ShdPnd: 0000000000000000",
|
|
2486
|
+
"SigBlk: 0000000000000000",
|
|
2487
|
+
"SigIgn: 0000000000000000",
|
|
2488
|
+
"SigCgt: 0000000000000000",
|
|
2489
|
+
""
|
|
2490
|
+
].join("\n");
|
|
2491
|
+
}
|
|
2492
|
+
function pidFile(name, info, boot) {
|
|
2493
|
+
if (name === "cmdline") return info.state === "Z" ? "" : `${info.argv.join("\0")}\0`;
|
|
2494
|
+
if (name === "comm") return `${commOf(info)}
|
|
2495
|
+
`;
|
|
2496
|
+
if (name === "stat") return pidStat(info, boot);
|
|
2497
|
+
if (name === "statm") return "0 0 0 0 0 0 0\n";
|
|
2498
|
+
return pidStatus(info);
|
|
2499
|
+
}
|
|
2500
|
+
function memoryInfo(source) {
|
|
2501
|
+
const total = source.deviceMemory ? source.deviceMemory * KIB * KIB * KIB : FALLBACK_MEMORY;
|
|
2502
|
+
const free = Math.max(0, total - (source.usedHeap ?? 0));
|
|
2503
|
+
const kb = (bytes) => `${Math.floor(bytes / KIB)} kB`;
|
|
2504
|
+
return [
|
|
2505
|
+
["MemTotal", kb(total)],
|
|
2506
|
+
["MemFree", kb(free)],
|
|
2507
|
+
["MemAvailable", kb(free)],
|
|
2508
|
+
["Buffers", kb(0)],
|
|
2509
|
+
["Cached", kb(0)],
|
|
2510
|
+
["SwapCached", kb(0)],
|
|
2511
|
+
["Shmem", kb(0)],
|
|
2512
|
+
["SReclaimable", kb(0)],
|
|
2513
|
+
["SwapTotal", kb(0)],
|
|
2514
|
+
["SwapFree", kb(0)]
|
|
2515
|
+
].map(([key, value2]) => `${`${key}:`.padEnd(16)}${value2.padStart(12)}`).concat("").join("\n");
|
|
2516
|
+
}
|
|
2517
|
+
function systemFile(name, listing, now, memory) {
|
|
2518
|
+
const up = Math.max(0, now - listing.boot) / 1e3;
|
|
2519
|
+
if (name === "uptime") return `${up.toFixed(2)} ${up.toFixed(2)}
|
|
2520
|
+
`;
|
|
2521
|
+
if (name === "meminfo") return memoryInfo(memory);
|
|
2522
|
+
const live = listing.processes.filter((p) => p.state !== "Z");
|
|
2523
|
+
if (name === "loadavg") {
|
|
2524
|
+
const last = Math.max(0, ...listing.processes.map((p) => p.pid));
|
|
2525
|
+
return `0.00 0.00 0.00 1/${live.length} ${last}
|
|
2526
|
+
`;
|
|
2527
|
+
}
|
|
2528
|
+
const idle = ticks(now - listing.boot);
|
|
2529
|
+
return [
|
|
2530
|
+
`cpu 0 0 0 ${idle} 0 0 0 0 0 0`,
|
|
2531
|
+
`cpu0 0 0 0 ${idle} 0 0 0 0 0 0`,
|
|
2532
|
+
"intr 0",
|
|
2533
|
+
"ctxt 0",
|
|
2534
|
+
`btime ${Math.floor(listing.boot / 1e3)}`,
|
|
2535
|
+
`processes ${listing.processes.length}`,
|
|
2536
|
+
"procs_running 1",
|
|
2537
|
+
"procs_blocked 0",
|
|
2538
|
+
""
|
|
2539
|
+
].join("\n");
|
|
2540
|
+
}
|
|
2541
|
+
function memorySource(scope2 = globalThis) {
|
|
2542
|
+
const nav = scope2.navigator;
|
|
2543
|
+
const perf = scope2.performance;
|
|
2544
|
+
const deviceMemory = nav?.deviceMemory;
|
|
2545
|
+
const used = perf?.memory?.usedJSHeapSize;
|
|
2546
|
+
return {
|
|
2547
|
+
...typeof deviceMemory === "number" && deviceMemory > 0 ? { deviceMemory } : {},
|
|
2548
|
+
...typeof used === "number" ? { usedHeap: used } : {}
|
|
2549
|
+
};
|
|
2550
|
+
}
|
|
2551
|
+
function attr(node) {
|
|
2552
|
+
const now = /* @__PURE__ */ new Date();
|
|
2553
|
+
return {
|
|
2554
|
+
dev: 3,
|
|
2555
|
+
ino: node.id,
|
|
2556
|
+
mode: node.mode,
|
|
2557
|
+
nlink: 1,
|
|
2558
|
+
uid: UID,
|
|
2559
|
+
gid: UID,
|
|
2560
|
+
rdev: 0,
|
|
2561
|
+
size: 0,
|
|
2562
|
+
atime: now,
|
|
2563
|
+
mtime: now,
|
|
2564
|
+
ctime: now,
|
|
2565
|
+
blksize: 4096,
|
|
2566
|
+
blocks: 0
|
|
2567
|
+
};
|
|
2568
|
+
}
|
|
2569
|
+
function useProcfs(Fs, sys, pid, memory = memorySource()) {
|
|
2570
|
+
const { lookupPath, createNode, hashRemoveNode } = Fs;
|
|
2571
|
+
const procList = sys.procList?.bind(sys);
|
|
2572
|
+
if (!lookupPath || !createNode || !hashRemoveNode || !procList) return;
|
|
2573
|
+
let proc;
|
|
2574
|
+
let self;
|
|
2575
|
+
try {
|
|
2576
|
+
proc = lookupPath.call(Fs, "/proc", { follow: true }).node;
|
|
2577
|
+
self = lookupPath.call(Fs, "/proc/self", { follow: true }).node;
|
|
2578
|
+
} catch {
|
|
2579
|
+
return;
|
|
2580
|
+
}
|
|
2581
|
+
const error = (errno2 = ENOENT) => new Fs.ErrnoError(errno2);
|
|
2582
|
+
const fresh = (parent, name, mode) => {
|
|
2583
|
+
const node = createNode.call(Fs, parent, name, mode, 0);
|
|
2584
|
+
hashRemoveNode.call(Fs, node);
|
|
2585
|
+
node.node_ops = { getattr: attr, setattr: () => {
|
|
2586
|
+
} };
|
|
2587
|
+
node.stream_ops = {
|
|
2588
|
+
llseek: (stream, offset, whence) => {
|
|
2589
|
+
const at = (whence === 1 ? stream.position : 0) + offset;
|
|
2590
|
+
if (at < 0) throw error(EINVAL);
|
|
2591
|
+
return at;
|
|
2592
|
+
}
|
|
2593
|
+
};
|
|
2594
|
+
return node;
|
|
2595
|
+
};
|
|
2596
|
+
const file = (parent, name, content) => {
|
|
2597
|
+
const node = fresh(parent, name, FILE_MODE);
|
|
2598
|
+
node.stream_ops = {
|
|
2599
|
+
open: (stream) => {
|
|
2600
|
+
stream.sliccProc = new TextEncoder().encode(content());
|
|
2601
|
+
},
|
|
2602
|
+
read: (stream, buffer, offset, length, at) => {
|
|
2603
|
+
const data = stream.sliccProc ?? new Uint8Array(0);
|
|
2604
|
+
const chunk = data.subarray(at, at + length);
|
|
2605
|
+
buffer.set(chunk, offset);
|
|
2606
|
+
return chunk.length;
|
|
2607
|
+
},
|
|
2608
|
+
llseek: (stream, offset, whence) => {
|
|
2609
|
+
const end = stream.sliccProc?.length ?? 0;
|
|
2610
|
+
const at = (whence === 1 ? stream.position : whence === 2 ? end : 0) + offset;
|
|
2611
|
+
if (at < 0) throw error(EINVAL);
|
|
2612
|
+
return at;
|
|
2613
|
+
}
|
|
2614
|
+
};
|
|
2615
|
+
return node;
|
|
2616
|
+
};
|
|
2617
|
+
const find = (processes2, target, own) => processes2.find((p) => own ? p.tid === target : p.pid === target || p.tid === target);
|
|
2618
|
+
const infoOf = (target) => find(procList().processes, target, false);
|
|
2619
|
+
const pidContent = (target, name, own = false) => () => {
|
|
2620
|
+
const listing = procList();
|
|
2621
|
+
const info = find(listing.processes, target, own);
|
|
2622
|
+
if (!info) throw error(ESRCH);
|
|
2623
|
+
return pidFile(name, info, listing.boot);
|
|
2624
|
+
};
|
|
2625
|
+
const pidNames = (names) => [.../* @__PURE__ */ new Set([...names, ...PID_FILES])];
|
|
2626
|
+
const pidDir = (name, target) => {
|
|
2627
|
+
const dir = fresh(proc, name, DIR_MODE2);
|
|
2628
|
+
dir.node_ops.lookup = (parent, child) => {
|
|
2629
|
+
if (!PID_FILES.includes(child)) throw error();
|
|
2630
|
+
return file(parent, child, pidContent(target, child));
|
|
2631
|
+
};
|
|
2632
|
+
dir.node_ops.readdir = () => [".", "..", ...PID_FILES];
|
|
2633
|
+
return dir;
|
|
2634
|
+
};
|
|
2635
|
+
const procOps = proc.node_ops;
|
|
2636
|
+
const lookup = procOps.lookup?.bind(procOps);
|
|
2637
|
+
const readdir = procOps.readdir?.bind(procOps);
|
|
2638
|
+
proc.node_ops = {
|
|
2639
|
+
...procOps,
|
|
2640
|
+
lookup: (parent, name) => {
|
|
2641
|
+
if (/^[1-9]\d*$/.test(name)) {
|
|
2642
|
+
if (!infoOf(Number(name))) throw error();
|
|
2643
|
+
return pidDir(name, Number(name));
|
|
2644
|
+
}
|
|
2645
|
+
if (SYSTEM_FILES.includes(name)) {
|
|
2646
|
+
return file(
|
|
2647
|
+
parent,
|
|
2648
|
+
name,
|
|
2649
|
+
() => systemFile(name, procList(), Date.now(), memory)
|
|
2650
|
+
);
|
|
2651
|
+
}
|
|
2652
|
+
if (!lookup) throw error();
|
|
2653
|
+
return lookup(parent, name);
|
|
2654
|
+
},
|
|
2655
|
+
readdir: (node) => {
|
|
2656
|
+
const names = new Set(readdir ? readdir(node) : [".", ".."]);
|
|
2657
|
+
for (const name of SYSTEM_FILES) names.add(name);
|
|
2658
|
+
for (const p of procList().processes) names.add(String(p.pid));
|
|
2659
|
+
return [...names];
|
|
2660
|
+
}
|
|
2661
|
+
};
|
|
2662
|
+
const selfOps = self.node_ops;
|
|
2663
|
+
const selfLookup = selfOps.lookup?.bind(selfOps);
|
|
2664
|
+
const selfReaddir = selfOps.readdir?.bind(selfOps);
|
|
2665
|
+
self.node_ops = {
|
|
2666
|
+
...selfOps,
|
|
2667
|
+
lookup: (parent, name) => {
|
|
2668
|
+
if (PID_FILES.includes(name)) {
|
|
2669
|
+
return file(parent, name, pidContent(pid, name, true));
|
|
2670
|
+
}
|
|
2671
|
+
if (!selfLookup) throw error();
|
|
2672
|
+
return selfLookup(parent, name);
|
|
2673
|
+
},
|
|
2674
|
+
readdir: (node) => pidNames(selfReaddir ? selfReaddir(node) : [".", ".."])
|
|
2675
|
+
};
|
|
2676
|
+
}
|
|
2677
|
+
var HZ, DIR_MODE2, FILE_MODE, ENOENT, ESRCH, EINVAL, UID, KIB, FALLBACK_MEMORY, PID_FILES, SYSTEM_FILES;
|
|
2678
|
+
var init_procfs = __esm({
|
|
2679
|
+
"src/process/procfs.ts"() {
|
|
2680
|
+
"use strict";
|
|
2681
|
+
HZ = 100;
|
|
2682
|
+
DIR_MODE2 = 16749;
|
|
2683
|
+
FILE_MODE = 33060;
|
|
2684
|
+
ENOENT = 44;
|
|
2685
|
+
ESRCH = 71;
|
|
2686
|
+
EINVAL = 28;
|
|
2687
|
+
UID = 1e3;
|
|
2688
|
+
KIB = 1024;
|
|
2689
|
+
FALLBACK_MEMORY = 4 * KIB * KIB * KIB;
|
|
2690
|
+
PID_FILES = ["cmdline", "comm", "stat", "statm", "status"];
|
|
2691
|
+
SYSTEM_FILES = ["loadavg", "meminfo", "stat", "uptime"];
|
|
2692
|
+
}
|
|
2693
|
+
});
|
|
2694
|
+
|
|
2347
2695
|
// src/process/realm-user.ts
|
|
2348
2696
|
function ownByRealmUser(Fs) {
|
|
2349
2697
|
const { stat, fstat } = Fs;
|
|
2350
|
-
const owned = (
|
|
2698
|
+
const owned = (attr2) => ({ ...attr2, uid: REALM_UID, gid: REALM_GID });
|
|
2351
2699
|
if (typeof stat === "function") {
|
|
2352
2700
|
Fs.stat = (path, dontFollow) => owned(stat.call(Fs, path, dontFollow));
|
|
2353
2701
|
}
|
|
@@ -2458,6 +2806,9 @@ function kernelSys(transport) {
|
|
|
2458
2806
|
ptyNumbers() {
|
|
2459
2807
|
return json(call2({ op: "pty-list" }, "pty-list"));
|
|
2460
2808
|
},
|
|
2809
|
+
procList() {
|
|
2810
|
+
return json(call2({ op: "proc-list" }, "proc-list"));
|
|
2811
|
+
},
|
|
2461
2812
|
ptyNumber(fd) {
|
|
2462
2813
|
return json(call2({ op: "pty-number", fd }, `pty-number ${fd}`));
|
|
2463
2814
|
},
|
|
@@ -2618,6 +2969,8 @@ async function runWasmProcess(init, port, deps = {}) {
|
|
|
2618
2969
|
if (pipefs) streams.usePipes(pipefs);
|
|
2619
2970
|
streams.useControllingTerminal();
|
|
2620
2971
|
useDevFd(running.FS);
|
|
2972
|
+
useMounts(running.FS);
|
|
2973
|
+
useProcfs(running.FS, sys, init.pid);
|
|
2621
2974
|
ownByRealmUser(running.FS);
|
|
2622
2975
|
const livePath = (s) => liveNodePath(s.node);
|
|
2623
2976
|
running.sliccKernel = createProcessKernel({
|
|
@@ -2684,6 +3037,7 @@ var init_process_runtime = __esm({
|
|
|
2684
3037
|
init_process_http();
|
|
2685
3038
|
init_process_signals();
|
|
2686
3039
|
init_process_sockets();
|
|
3040
|
+
init_procfs();
|
|
2687
3041
|
init_realm_user();
|
|
2688
3042
|
init_kernel_streams();
|
|
2689
3043
|
O_RDONLY = 0;
|
|
@@ -4391,7 +4745,7 @@ function importsContext({
|
|
|
4391
4745
|
const path = pathOf(fd);
|
|
4392
4746
|
if (path === void 0) {
|
|
4393
4747
|
const kind = e.type === "device" ? "device" : "stream";
|
|
4394
|
-
return { kind, mode: kind === "device" ? 8630 : 4480, uid:
|
|
4748
|
+
return { kind, mode: kind === "device" ? 8630 : 4480, uid: UID2, gid: UID2, size: 0 };
|
|
4395
4749
|
}
|
|
4396
4750
|
host.fds.flushPath(path);
|
|
4397
4751
|
const s = fs.stat(path);
|
|
@@ -4399,8 +4753,8 @@ function importsContext({
|
|
|
4399
4753
|
kind: s.isDirectory ? "dir" : "file",
|
|
4400
4754
|
path,
|
|
4401
4755
|
mode: s.mode ?? (s.isDirectory ? 16877 : 33188),
|
|
4402
|
-
uid:
|
|
4403
|
-
gid:
|
|
4756
|
+
uid: UID2,
|
|
4757
|
+
gid: UID2,
|
|
4404
4758
|
size: s.size,
|
|
4405
4759
|
...s.ino !== void 0 ? { ino: s.ino } : {},
|
|
4406
4760
|
...s.mtimeMs !== void 0 ? { mtimeMs: s.mtimeMs } : {}
|
|
@@ -4518,13 +4872,13 @@ function processes(host, call2) {
|
|
|
4518
4872
|
}
|
|
4519
4873
|
};
|
|
4520
4874
|
}
|
|
4521
|
-
var
|
|
4875
|
+
var UID2, STDIO;
|
|
4522
4876
|
var init_wasi_imports = __esm({
|
|
4523
4877
|
"src/process/wasi/wasi-imports.ts"() {
|
|
4524
4878
|
"use strict";
|
|
4525
4879
|
init_wasi_abi();
|
|
4526
4880
|
init_wasi_files();
|
|
4527
|
-
|
|
4881
|
+
UID2 = 1e3;
|
|
4528
4882
|
STDIO = ["stdin", "stdout", "stderr"];
|
|
4529
4883
|
}
|
|
4530
4884
|
});
|