@ai-ecoverse/slicc-kernel 1.57.1 → 1.58.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 +3 -2
- package/dist/driver-worker.js +3 -0
- package/dist/driver-worker.js.map +2 -2
- package/dist/driver.js +3 -0
- package/dist/driver.js.map +2 -2
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +286 -111
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-driver-worker.js +3 -0
- package/dist/node-driver-worker.js.map +2 -2
- package/dist/node-process-worker.js +255 -37
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +286 -111
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +255 -37
- package/dist/process-worker.js.map +3 -3
- package/package.json +1 -1
|
@@ -611,6 +611,7 @@ function cachingBridge(bridge, now = () => performance.now(), shared) {
|
|
|
611
611
|
mkdir: (p) => mutating(() => bridge.mkdir(p), ...entry(p)),
|
|
612
612
|
rm: (p) => mutating(() => bridge.rm(p)),
|
|
613
613
|
rename: (from, to) => mutating(() => bridge.rename(from, to)),
|
|
614
|
+
link: (from, to, follow2) => mutating(() => bridge.link(from, to, follow2)),
|
|
614
615
|
unlink: (p) => mutating(() => bridge.unlink(p)),
|
|
615
616
|
rmdir: (p) => mutating(() => bridge.rmdir(p)),
|
|
616
617
|
symlink: (target, link) => mutating(() => bridge.symlink(target, link), ...entry(link)),
|
|
@@ -1218,6 +1219,8 @@ var init_wasi_fds = __esm({
|
|
|
1218
1219
|
WasiFds = class {
|
|
1219
1220
|
table = /* @__PURE__ */ new Map();
|
|
1220
1221
|
buffers = /* @__PURE__ */ new Map();
|
|
1222
|
+
byId = /* @__PURE__ */ new Map();
|
|
1223
|
+
ids = /* @__PURE__ */ new Map();
|
|
1221
1224
|
kernel;
|
|
1222
1225
|
fs;
|
|
1223
1226
|
constructor(kernel, fs) {
|
|
@@ -1467,7 +1470,7 @@ var init_wasi_fds = __esm({
|
|
|
1467
1470
|
}
|
|
1468
1471
|
for (const file of promoted.keys()) {
|
|
1469
1472
|
if (--file.buffer.opens <= 0) {
|
|
1470
|
-
this.
|
|
1473
|
+
this.forget(file.buffer);
|
|
1471
1474
|
this.letGo(file.buffer);
|
|
1472
1475
|
}
|
|
1473
1476
|
}
|
|
@@ -1538,9 +1541,48 @@ var init_wasi_fds = __esm({
|
|
|
1538
1541
|
const { buffer } = e.file;
|
|
1539
1542
|
buffer.flush();
|
|
1540
1543
|
if (--buffer.opens > 0) return;
|
|
1541
|
-
|
|
1544
|
+
this.forget(buffer);
|
|
1542
1545
|
this.letGo(buffer);
|
|
1543
1546
|
}
|
|
1547
|
+
forget(buffer) {
|
|
1548
|
+
for (const [p, b] of [...this.buffers]) if (b === buffer) this.buffers.delete(p);
|
|
1549
|
+
const id = this.ids.get(buffer);
|
|
1550
|
+
if (id !== void 0 && this.byId.get(id) === buffer) this.byId.delete(id);
|
|
1551
|
+
this.ids.delete(buffer);
|
|
1552
|
+
}
|
|
1553
|
+
know(buffer, id) {
|
|
1554
|
+
if (this.ids.has(buffer)) return;
|
|
1555
|
+
this.ids.set(buffer, id);
|
|
1556
|
+
if (!this.byId.has(id)) this.byId.set(id, buffer);
|
|
1557
|
+
}
|
|
1558
|
+
identity(st) {
|
|
1559
|
+
if (!st || st.ino === void 0 || (st.nlink ?? 1) < 2) return void 0;
|
|
1560
|
+
return `${st.dev ?? 0}:${st.ino}`;
|
|
1561
|
+
}
|
|
1562
|
+
sharing(path, st) {
|
|
1563
|
+
if (st?.ino === void 0) return void 0;
|
|
1564
|
+
const id = `${st.dev ?? 0}:${st.ino}`;
|
|
1565
|
+
if (!this.byId.has(id) && this.identity(st) !== void 0) this.learn();
|
|
1566
|
+
const buffer = this.byId.get(id);
|
|
1567
|
+
if (!buffer) return void 0;
|
|
1568
|
+
this.buffers.set(path, buffer);
|
|
1569
|
+
return buffer;
|
|
1570
|
+
}
|
|
1571
|
+
learn() {
|
|
1572
|
+
for (const [p, buffer] of this.buffers) {
|
|
1573
|
+
if (this.ids.has(buffer) || buffer.isOrphan()) continue;
|
|
1574
|
+
const known = this.identity(this.statOrMissing(p));
|
|
1575
|
+
if (known !== void 0) this.know(buffer, known);
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
linked(from, to) {
|
|
1579
|
+
const buffer = this.buffers.get(from);
|
|
1580
|
+
if (!buffer || buffer.isOrphan()) return;
|
|
1581
|
+
const id = this.identity(this.statOrMissing(to));
|
|
1582
|
+
if (id === void 0) return;
|
|
1583
|
+
this.know(buffer, id);
|
|
1584
|
+
if (!this.buffers.has(to)) this.buffers.set(to, buffer);
|
|
1585
|
+
}
|
|
1544
1586
|
letGo(buffer) {
|
|
1545
1587
|
this.fs.hold?.(buffer.path, false, true, buffer.handle);
|
|
1546
1588
|
}
|
|
@@ -1566,15 +1608,21 @@ var init_wasi_fds = __esm({
|
|
|
1566
1608
|
for (const [p, buffer] of this.buffers) if (within(p, path)) buffer.flush();
|
|
1567
1609
|
if (this.shared) this.kernel.call({ op: "fd-path-flush", path });
|
|
1568
1610
|
}
|
|
1569
|
-
|
|
1570
|
-
this.buffers.
|
|
1611
|
+
holdsUnder(path) {
|
|
1612
|
+
for (const p of this.buffers.keys()) if (within(p, path)) return true;
|
|
1613
|
+
return false;
|
|
1614
|
+
}
|
|
1615
|
+
unlinking(path, linked) {
|
|
1616
|
+
const buffer = this.buffers.get(path);
|
|
1617
|
+
if (buffer && this.survives(buffer, linked)) buffer.flush();
|
|
1618
|
+
else buffer?.keep();
|
|
1571
1619
|
if (this.shared) this.kernel.call({ op: "fd-path-unlinking", path });
|
|
1572
1620
|
}
|
|
1573
|
-
unlinked(path) {
|
|
1621
|
+
unlinked(path, linked) {
|
|
1574
1622
|
if (this.shared) this.kernel.call({ op: "fd-path-unlinked", path });
|
|
1575
1623
|
const buffer = this.buffers.get(path);
|
|
1576
1624
|
if (!buffer) return;
|
|
1577
|
-
|
|
1625
|
+
this.detach(buffer, linked);
|
|
1578
1626
|
this.buffers.delete(path);
|
|
1579
1627
|
}
|
|
1580
1628
|
inoOf(path) {
|
|
@@ -1584,7 +1632,19 @@ var init_wasi_fds = __esm({
|
|
|
1584
1632
|
return void 0;
|
|
1585
1633
|
}
|
|
1586
1634
|
}
|
|
1587
|
-
|
|
1635
|
+
survives(buffer, linked) {
|
|
1636
|
+
return linked !== void 0 && buffer.handle !== void 0;
|
|
1637
|
+
}
|
|
1638
|
+
detach(buffer, linked) {
|
|
1639
|
+
if (this.survives(buffer, linked)) {
|
|
1640
|
+
const id = this.identity(linked);
|
|
1641
|
+
if (id !== void 0) this.know(buffer, id);
|
|
1642
|
+
return;
|
|
1643
|
+
}
|
|
1644
|
+
buffer.orphan();
|
|
1645
|
+
this.forget(buffer);
|
|
1646
|
+
}
|
|
1647
|
+
renamed(from, to, replacedLinked) {
|
|
1588
1648
|
if (from === to) return;
|
|
1589
1649
|
if (this.shared) this.kernel.call({ op: "fd-path-renamed", from, to });
|
|
1590
1650
|
for (const e of this.table.values()) {
|
|
@@ -1596,14 +1656,15 @@ var init_wasi_fds = __esm({
|
|
|
1596
1656
|
for (const [p, buffer] of this.buffers) {
|
|
1597
1657
|
if (within(p, from)) moved.push([p, buffer]);
|
|
1598
1658
|
else if (within(p, to)) {
|
|
1599
|
-
|
|
1659
|
+
this.detach(buffer, replacedLinked);
|
|
1600
1660
|
this.buffers.delete(p);
|
|
1601
1661
|
}
|
|
1602
1662
|
}
|
|
1663
|
+
for (const [p] of moved) this.buffers.delete(p);
|
|
1603
1664
|
for (const [p, buffer] of moved) {
|
|
1604
|
-
|
|
1605
|
-
buffer.path
|
|
1606
|
-
this.buffers.set(
|
|
1665
|
+
const next2 = to + p.slice(from.length);
|
|
1666
|
+
if (buffer.path === p) buffer.path = next2;
|
|
1667
|
+
this.buffers.set(next2, buffer);
|
|
1607
1668
|
}
|
|
1608
1669
|
}
|
|
1609
1670
|
resolve(dirfd, path) {
|
|
@@ -1646,6 +1707,7 @@ var init_wasi_fds = __esm({
|
|
|
1646
1707
|
this.buffers.delete(path);
|
|
1647
1708
|
buffer = void 0;
|
|
1648
1709
|
}
|
|
1710
|
+
buffer ??= this.sharing(path, existing);
|
|
1649
1711
|
if (buffer) {
|
|
1650
1712
|
if (oflags & OFLAGS.TRUNC) buffer.truncate(0);
|
|
1651
1713
|
} else {
|
|
@@ -1659,6 +1721,8 @@ var init_wasi_fds = __esm({
|
|
|
1659
1721
|
buffer = new FileBuffer(io, path, empty, st.maxFile, ranged, st.version);
|
|
1660
1722
|
buffer.handle = handle;
|
|
1661
1723
|
this.buffers.set(path, buffer);
|
|
1724
|
+
const id = this.identity(st);
|
|
1725
|
+
if (id !== void 0) this.know(buffer, id);
|
|
1662
1726
|
}
|
|
1663
1727
|
buffer.opens++;
|
|
1664
1728
|
return new LocalFile(buffer, readable2, writable2, (fdflags & FDFLAGS.APPEND) !== 0);
|
|
@@ -1992,6 +2056,16 @@ var init_wasi_termios = __esm({
|
|
|
1992
2056
|
});
|
|
1993
2057
|
|
|
1994
2058
|
// src/process/wasi/wasi-host.ts
|
|
2059
|
+
function linkedOf(st) {
|
|
2060
|
+
return (st.nlink ?? 1) > 1 ? st : void 0;
|
|
2061
|
+
}
|
|
2062
|
+
function linkedElsewhere(fs, path) {
|
|
2063
|
+
try {
|
|
2064
|
+
return linkedOf(fs.lstat(path));
|
|
2065
|
+
} catch {
|
|
2066
|
+
return void 0;
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
1995
2069
|
function filetypeOf(s) {
|
|
1996
2070
|
if (!s) return FILETYPE.UNKNOWN;
|
|
1997
2071
|
if (s.isSymbolicLink) return FILETYPE.SYMBOLIC_LINK;
|
|
@@ -2003,6 +2077,7 @@ function filestatOf(path, s) {
|
|
|
2003
2077
|
filetype: filetypeOf(s),
|
|
2004
2078
|
size: BigInt(s.size),
|
|
2005
2079
|
ino: s.ino !== void 0 ? BigInt(s.ino) : pathInode(path),
|
|
2080
|
+
...s.nlink !== void 0 ? { nlink: BigInt(s.nlink) } : {},
|
|
2006
2081
|
mtimeNs: BigInt(Math.round(s.mtimeMs ?? 0)) * NS_PER_MS
|
|
2007
2082
|
};
|
|
2008
2083
|
}
|
|
@@ -2053,6 +2128,7 @@ var WasiExit, IDS, NS_PER_MS, AT_SYMLINK_NOFOLLOW, S_IFIFO, DEFAULT_UMASK, MONOT
|
|
|
2053
2128
|
var init_wasi_host = __esm({
|
|
2054
2129
|
"src/process/wasi/wasi-host.ts"() {
|
|
2055
2130
|
"use strict";
|
|
2131
|
+
init_physical_path();
|
|
2056
2132
|
init_cred();
|
|
2057
2133
|
init_wasi_abi();
|
|
2058
2134
|
init_wasi_fds();
|
|
@@ -2362,17 +2438,20 @@ var init_wasi_host = __esm({
|
|
|
2362
2438
|
path_remove_directory: (dirfd, p, l) => void o.fs.rmdir(at(dirfd, p, l)),
|
|
2363
2439
|
path_unlink_file: (dirfd, p, l) => {
|
|
2364
2440
|
const path = at(dirfd, p, l);
|
|
2365
|
-
|
|
2366
|
-
|
|
2441
|
+
const st = o.fs.lstat(path);
|
|
2442
|
+
if (st.isDirectory) throw new WasiError("EISDIR");
|
|
2443
|
+
const linked = linkedOf(st);
|
|
2444
|
+
fds.unlinking(path, linked);
|
|
2367
2445
|
o.fs.unlink(path);
|
|
2368
|
-
fds.unlinked(path);
|
|
2446
|
+
fds.unlinked(path, linked);
|
|
2369
2447
|
},
|
|
2370
2448
|
path_rename: (fd, p, l, fd2, p2, l2) => {
|
|
2371
2449
|
const from = at(fd, p, l);
|
|
2372
2450
|
const to = at(fd2, p2, l2);
|
|
2373
2451
|
fds.flushPath(from);
|
|
2452
|
+
const replaced = fds.holdsUnder(to) ? linkedElsewhere(o.fs, to) : void 0;
|
|
2374
2453
|
o.fs.rename(from, to);
|
|
2375
|
-
fds.renamed(from, to);
|
|
2454
|
+
fds.renamed(from, to, replaced);
|
|
2376
2455
|
},
|
|
2377
2456
|
path_symlink: (tp, tl, dirfd, p, l) => void o.fs.symlink(mem.string(tp, tl), at(dirfd, p, l)),
|
|
2378
2457
|
path_readlink: (dirfd, p, l, buf, len, used) => {
|
|
@@ -2381,7 +2460,17 @@ var init_wasi_host = __esm({
|
|
|
2381
2460
|
mem.bytes(buf, n).set(target.subarray(0, n));
|
|
2382
2461
|
mem.view().setUint32(used, n, true);
|
|
2383
2462
|
},
|
|
2384
|
-
path_link: () =>
|
|
2463
|
+
path_link: (fd, lookup, p, l, fd2, p2, l2) => {
|
|
2464
|
+
const from = at(fd, p, l);
|
|
2465
|
+
const to = at(fd2, p2, l2);
|
|
2466
|
+
const follow2 = (lookup & LOOKUP_SYMLINK_FOLLOW) !== 0;
|
|
2467
|
+
const source = follow2 ? physicalPath(o.fs, from) : from;
|
|
2468
|
+
fds.flushPath(from);
|
|
2469
|
+
if (source !== from) fds.flushPath(source);
|
|
2470
|
+
o.fs.link(from, to, follow2);
|
|
2471
|
+
fds.linked(from, to);
|
|
2472
|
+
if (source !== from) fds.linked(source, to);
|
|
2473
|
+
}
|
|
2385
2474
|
};
|
|
2386
2475
|
}
|
|
2387
2476
|
socket(fd) {
|
|
@@ -2585,7 +2674,7 @@ var init_wasi_host = __esm({
|
|
|
2585
2674
|
v.setBigUint64(ptr, 1n, true);
|
|
2586
2675
|
v.setBigUint64(ptr + 8, f.ino, true);
|
|
2587
2676
|
v.setUint8(ptr + 16, f.filetype);
|
|
2588
|
-
v.setBigUint64(ptr + 24, 1n, true);
|
|
2677
|
+
v.setBigUint64(ptr + 24, f.nlink ?? 1n, true);
|
|
2589
2678
|
v.setBigUint64(ptr + 32, f.size, true);
|
|
2590
2679
|
v.setBigUint64(ptr + 40, f.mtimeNs, true);
|
|
2591
2680
|
v.setBigUint64(ptr + 48, f.mtimeNs, true);
|
|
@@ -3350,10 +3439,12 @@ function parseSyncFsStat(json) {
|
|
|
3350
3439
|
...typeof s.atimeMs === "number" ? { atimeMs: s.atimeMs } : {},
|
|
3351
3440
|
...typeof s.ctimeMs === "number" ? { ctimeMs: s.ctimeMs } : {},
|
|
3352
3441
|
...typeof s.ino === "number" ? { ino: s.ino } : {},
|
|
3442
|
+
...typeof s.nlink === "number" ? { nlink: s.nlink } : {},
|
|
3353
3443
|
...typeof s.dev === "number" ? { dev: s.dev } : {},
|
|
3354
3444
|
...s.readonly === true ? { readonly: true } : {},
|
|
3355
3445
|
...typeof s.maxFile === "number" ? { maxFile: s.maxFile } : {},
|
|
3356
3446
|
...s.ranged === true ? { ranged: true } : {},
|
|
3447
|
+
...s.linkable === true ? { linkable: true } : {},
|
|
3357
3448
|
...typeof s.version === "string" ? { version: s.version } : {},
|
|
3358
3449
|
...typeof s.uid === "number" ? { uid: s.uid } : {},
|
|
3359
3450
|
...typeof s.gid === "number" ? { gid: s.gid } : {}
|
|
@@ -3374,6 +3465,7 @@ var init_sync_fs_wire = __esm({
|
|
|
3374
3465
|
"mkdir",
|
|
3375
3466
|
"rm",
|
|
3376
3467
|
"rename",
|
|
3468
|
+
"link",
|
|
3377
3469
|
"unlink",
|
|
3378
3470
|
"rmdir",
|
|
3379
3471
|
"symlink",
|
|
@@ -4390,6 +4482,9 @@ function createSyncFsSabBridge(transport, opts = {}) {
|
|
|
4390
4482
|
rename: (from, to) => {
|
|
4391
4483
|
run({ op: "rename", path: from, arg2: to }, from);
|
|
4392
4484
|
},
|
|
4485
|
+
link: (from, to, follow2) => {
|
|
4486
|
+
run({ op: "link", path: from, arg2: to, ...follow2 ? { mode: 1 } : {} }, from);
|
|
4487
|
+
},
|
|
4393
4488
|
unlink: (path) => {
|
|
4394
4489
|
run({ op: "unlink", path }, path);
|
|
4395
4490
|
},
|
|
@@ -4593,6 +4688,7 @@ function syncPathOps(kernel, resolve, statOf, open) {
|
|
|
4593
4688
|
rm: (path) => void kernel.call({ op: "rm", path: resolve(path) }),
|
|
4594
4689
|
unlink: (path) => void kernel.call({ op: "unlink", path: resolve(path) }),
|
|
4595
4690
|
rename: (from, to) => void kernel.call({ op: "rename", path: resolve(from), arg2: resolve(to) }),
|
|
4691
|
+
link: (from, to) => void kernel.call({ op: "link", path: resolve(from), arg2: resolve(to) }),
|
|
4596
4692
|
symlink: (target, path) => void kernel.call({ op: "symlink", path: resolve(path), arg2: target }),
|
|
4597
4693
|
readlink: (path) => String(kernel.json({ op: "readlink", path: resolve(path) })),
|
|
4598
4694
|
readFile(path) {
|
|
@@ -5189,6 +5285,7 @@ function pathOps(kernel, resolve, statOf, open) {
|
|
|
5189
5285
|
rm: async (path) => void await kernel.call({ op: "rm", path: resolve(path) }),
|
|
5190
5286
|
unlink: async (path) => void await kernel.call({ op: "unlink", path: resolve(path) }),
|
|
5191
5287
|
rename: async (from, to) => void await kernel.call({ op: "rename", path: resolve(from), arg2: resolve(to) }),
|
|
5288
|
+
link: async (from, to) => void await kernel.call({ op: "link", path: resolve(from), arg2: resolve(to) }),
|
|
5192
5289
|
symlink: async (target, path) => void await kernel.call({ op: "symlink", path: resolve(path), arg2: target }),
|
|
5193
5290
|
readlink: async (path) => String(await kernel.json({ op: "readlink", path: resolve(path) })),
|
|
5194
5291
|
async readFile(path) {
|
|
@@ -5440,11 +5537,54 @@ function toMs(v) {
|
|
|
5440
5537
|
if (v === void 0 || v === null) return void 0;
|
|
5441
5538
|
return v instanceof Date ? v.getTime() : v;
|
|
5442
5539
|
}
|
|
5540
|
+
function linkedStates(bridgeOf) {
|
|
5541
|
+
const opens = /* @__PURE__ */ new Map();
|
|
5542
|
+
const byId = /* @__PURE__ */ new Map();
|
|
5543
|
+
const idOf2 = (st) => st?.ino === void 0 || (st.nlink ?? 1) < 2 ? void 0 : `${st.dev}:${st.ino}`;
|
|
5544
|
+
function know(s, id) {
|
|
5545
|
+
s.id = id;
|
|
5546
|
+
if (!byId.has(id)) byId.set(id, s);
|
|
5547
|
+
}
|
|
5548
|
+
function opening(node, on) {
|
|
5549
|
+
const s = node.live;
|
|
5550
|
+
if (!on) {
|
|
5551
|
+
opens.delete(s);
|
|
5552
|
+
if (s.id !== void 0 && byId.get(s.id) === s) byId.delete(s.id);
|
|
5553
|
+
s.id = void 0;
|
|
5554
|
+
return;
|
|
5555
|
+
}
|
|
5556
|
+
opens.set(s, node);
|
|
5557
|
+
const id = idOf2(s.stat);
|
|
5558
|
+
if (id !== void 0) know(s, id);
|
|
5559
|
+
}
|
|
5560
|
+
function sharedWith(node) {
|
|
5561
|
+
const st = node.live.stat;
|
|
5562
|
+
if (st?.ino === void 0) return void 0;
|
|
5563
|
+
const id = `${st.dev}:${st.ino}`;
|
|
5564
|
+
if (!byId.has(id) && idOf2(st) !== void 0) {
|
|
5565
|
+
for (const [s2, other] of opens) {
|
|
5566
|
+
if (s2.id !== void 0 || s2.orphan) continue;
|
|
5567
|
+
let st2;
|
|
5568
|
+
try {
|
|
5569
|
+
st2 = bridgeOf(other).lstat(liveNodePath(other));
|
|
5570
|
+
} catch {
|
|
5571
|
+
}
|
|
5572
|
+
const known = idOf2(st2);
|
|
5573
|
+
if (known !== void 0) know(s2, known);
|
|
5574
|
+
}
|
|
5575
|
+
}
|
|
5576
|
+
const s = byId.get(id);
|
|
5577
|
+
return s && s !== node.live && !stale(s) ? s : void 0;
|
|
5578
|
+
}
|
|
5579
|
+
const holder = (node) => opens.get(node.live) ?? node;
|
|
5580
|
+
return { opening, sharedWith, know, idOf: idOf2, holder };
|
|
5581
|
+
}
|
|
5443
5582
|
function createHelpers(Fs, ops) {
|
|
5444
5583
|
const bridgeOf = (node) => node.mount.opts.bridge;
|
|
5445
5584
|
const fileIo = (node) => pinnedIo2(bridgeOf(node), node.live.handle);
|
|
5446
5585
|
const dirty = /* @__PURE__ */ new Set();
|
|
5447
5586
|
const handled = /* @__PURE__ */ new Set();
|
|
5587
|
+
const linked = linkedStates(bridgeOf);
|
|
5448
5588
|
function markDirty(node) {
|
|
5449
5589
|
node.live.dirty = true;
|
|
5450
5590
|
dirty.add(node);
|
|
@@ -5452,7 +5592,7 @@ function createHelpers(Fs, ops) {
|
|
|
5452
5592
|
function flushDirty() {
|
|
5453
5593
|
for (const node of [...dirty]) {
|
|
5454
5594
|
const s = node.live;
|
|
5455
|
-
if (!s.dirty || s
|
|
5595
|
+
if (!s.dirty || stale(s)) {
|
|
5456
5596
|
dirty.delete(node);
|
|
5457
5597
|
continue;
|
|
5458
5598
|
}
|
|
@@ -5494,7 +5634,7 @@ function createHelpers(Fs, ops) {
|
|
|
5494
5634
|
return { ...node.live.stat, size };
|
|
5495
5635
|
}
|
|
5496
5636
|
if (!node.live.stat) {
|
|
5497
|
-
const st = call2(() => bridgeOf(node).lstat(liveNodePath(node)));
|
|
5637
|
+
const st = call2(() => bridgeOf(node).lstat(liveNodePath(linked.holder(node))));
|
|
5498
5638
|
node.live.stat = st;
|
|
5499
5639
|
node.mode = modeFromStat(st);
|
|
5500
5640
|
}
|
|
@@ -5507,7 +5647,7 @@ function createHelpers(Fs, ops) {
|
|
|
5507
5647
|
function ensureLoaded(node) {
|
|
5508
5648
|
const s = node.live;
|
|
5509
5649
|
if (s.loaded) return;
|
|
5510
|
-
const bytes = call2(() => fileIo(node).readFile(liveNodePath(node)));
|
|
5650
|
+
const bytes = call2(() => fileIo(node).readFile(liveNodePath(linked.holder(node))));
|
|
5511
5651
|
s.data = bytes;
|
|
5512
5652
|
s.len = bytes.length;
|
|
5513
5653
|
s.loaded = true;
|
|
@@ -5516,7 +5656,7 @@ function createHelpers(Fs, ops) {
|
|
|
5516
5656
|
const s = node.live;
|
|
5517
5657
|
if (s.ranged || !s.ranges) return s.ranged;
|
|
5518
5658
|
const bridge = bridgeOf(node);
|
|
5519
|
-
const path = () => liveNodePath(node);
|
|
5659
|
+
const path = () => liveNodePath(linked.holder(node));
|
|
5520
5660
|
const file = () => fileIo(node);
|
|
5521
5661
|
const io = {
|
|
5522
5662
|
pread: (_, at, n, version) => file().pread(path(), at, n, version),
|
|
@@ -5538,11 +5678,11 @@ function createHelpers(Fs, ops) {
|
|
|
5538
5678
|
}
|
|
5539
5679
|
function flushNode(node) {
|
|
5540
5680
|
const s = node.live;
|
|
5541
|
-
if (!s.dirty || s
|
|
5681
|
+
if (!s.dirty || stale(s) || !(s.data || s.ranged)) return;
|
|
5542
5682
|
if (s.ranged) call2(() => s.ranged?.flush());
|
|
5543
5683
|
else {
|
|
5544
5684
|
const bytes = s.data.slice(0, s.len);
|
|
5545
|
-
call2(() => fileIo(node).writeFile(liveNodePath(node), bytes, true));
|
|
5685
|
+
call2(() => fileIo(node).writeFile(liveNodePath(linked.holder(node)), bytes, true));
|
|
5546
5686
|
}
|
|
5547
5687
|
s.dirty = false;
|
|
5548
5688
|
s.stat = void 0;
|
|
@@ -5590,6 +5730,7 @@ function createHelpers(Fs, ops) {
|
|
|
5590
5730
|
Fs,
|
|
5591
5731
|
bridgeOf,
|
|
5592
5732
|
handled,
|
|
5733
|
+
linked,
|
|
5593
5734
|
call: call2,
|
|
5594
5735
|
metadataCall,
|
|
5595
5736
|
makeNode,
|
|
@@ -5604,6 +5745,33 @@ function createHelpers(Fs, ops) {
|
|
|
5604
5745
|
truncate
|
|
5605
5746
|
};
|
|
5606
5747
|
}
|
|
5748
|
+
function freshStat(h, node) {
|
|
5749
|
+
const { statOf } = h;
|
|
5750
|
+
const st = statOf(node);
|
|
5751
|
+
if (!st.linkable) return st;
|
|
5752
|
+
node.live.stat = void 0;
|
|
5753
|
+
return statOf(node);
|
|
5754
|
+
}
|
|
5755
|
+
function orphaned(h, node, st) {
|
|
5756
|
+
const { bridgeOf } = h;
|
|
5757
|
+
const s = node.live;
|
|
5758
|
+
const nlink = st.nlink ?? 1;
|
|
5759
|
+
let kept = false;
|
|
5760
|
+
try {
|
|
5761
|
+
kept = nlink > 1 && s.handle !== void 0 && bridgeOf(node).kept?.(s.handle) === true;
|
|
5762
|
+
} catch {
|
|
5763
|
+
}
|
|
5764
|
+
if (nlink > 1 && !kept && h.linked.holder(node) !== node) {
|
|
5765
|
+
s.stat = void 0;
|
|
5766
|
+
return;
|
|
5767
|
+
}
|
|
5768
|
+
s.orphan = true;
|
|
5769
|
+
if (!kept) return;
|
|
5770
|
+
s.kept = true;
|
|
5771
|
+
s.stat = { ...st, nlink: nlink - 1 };
|
|
5772
|
+
const id = h.linked.idOf(st);
|
|
5773
|
+
if (id !== void 0) h.linked.know(s, id);
|
|
5774
|
+
}
|
|
5607
5775
|
function createNodeOps(h) {
|
|
5608
5776
|
const { Fs, bridgeOf, call: call2, metadataCall, makeNode, statOf, childPath, flushNode, truncate } = h;
|
|
5609
5777
|
const { ensureLoaded } = h;
|
|
@@ -5634,7 +5802,7 @@ function createNodeOps(h) {
|
|
|
5634
5802
|
dev: st.dev ?? 1,
|
|
5635
5803
|
ino: st.ino ?? inodeOf(liveNodePath(node)),
|
|
5636
5804
|
mode: node.mode,
|
|
5637
|
-
nlink: 1,
|
|
5805
|
+
nlink: st.nlink ?? 1,
|
|
5638
5806
|
uid: owned ? st.uid ?? 0 : 0,
|
|
5639
5807
|
gid: owned ? st.gid ?? 0 : 0,
|
|
5640
5808
|
rdev: 0,
|
|
@@ -5729,14 +5897,14 @@ function createNodeOps(h) {
|
|
|
5729
5897
|
if (node && node.live?.openCount > 0 && Fs.isFile(node.mode)) open = node;
|
|
5730
5898
|
} catch {
|
|
5731
5899
|
}
|
|
5900
|
+
const st = open && freshStat(h, open);
|
|
5732
5901
|
if (open) {
|
|
5733
|
-
statOf(open);
|
|
5734
5902
|
const ranged = h.rangedOf(open);
|
|
5735
5903
|
if (ranged) ranged.pin();
|
|
5736
5904
|
else ensureLoaded(open);
|
|
5737
5905
|
}
|
|
5738
5906
|
call2(() => bridgeOf(parent).unlink(childPath(parent, name2)));
|
|
5739
|
-
if (open) open
|
|
5907
|
+
if (open && st) orphaned(h, open, st);
|
|
5740
5908
|
},
|
|
5741
5909
|
rmdir(parent, name2) {
|
|
5742
5910
|
parent.live.listed = void 0;
|
|
@@ -5784,6 +5952,7 @@ function createStreamOps(h) {
|
|
|
5784
5952
|
try {
|
|
5785
5953
|
const handle = bridgeOf(node).hold?.(liveNodePath(node), on, true, s.handle);
|
|
5786
5954
|
s.handle = on ? handle : void 0;
|
|
5955
|
+
h.linked.opening(node, on);
|
|
5787
5956
|
if (s.handle === void 0) h.handled.delete(node);
|
|
5788
5957
|
else h.handled.add(node);
|
|
5789
5958
|
} catch {
|
|
@@ -5796,7 +5965,9 @@ function createStreamOps(h) {
|
|
|
5796
5965
|
if (s.openCount === 0 && !s.orphan) {
|
|
5797
5966
|
const bridge = bridgeOf(stream.node);
|
|
5798
5967
|
s.ranges = !!(bridge.pread && bridge.pwrite && bridge.truncate && statOf(stream.node).ranged);
|
|
5799
|
-
|
|
5968
|
+
const shared = h.linked.sharedWith(stream.node);
|
|
5969
|
+
if (shared) stream.node.live = shared;
|
|
5970
|
+
else rangedOf(stream.node);
|
|
5800
5971
|
}
|
|
5801
5972
|
if ((stream.flags & 3) !== 0) {
|
|
5802
5973
|
try {
|
|
@@ -6118,7 +6289,7 @@ function useLiveChown(Fs) {
|
|
|
6118
6289
|
Fs.chown(target, uid, gid);
|
|
6119
6290
|
};
|
|
6120
6291
|
}
|
|
6121
|
-
var S_IFDIR, S_IFREG, S_IFLNK, PERM_MASK, DEFAULT_DIR_PERM, UMASK, SEEK_CUR, SEEK_END, EARLY_WHOLE_FILE;
|
|
6292
|
+
var S_IFDIR, S_IFREG, S_IFLNK, PERM_MASK, DEFAULT_DIR_PERM, UMASK, SEEK_CUR, SEEK_END, EARLY_WHOLE_FILE, stale;
|
|
6122
6293
|
var init_live_vfs_fs = __esm({
|
|
6123
6294
|
"src/realm/live-vfs-fs.ts"() {
|
|
6124
6295
|
"use strict";
|
|
@@ -6134,6 +6305,7 @@ var init_live_vfs_fs = __esm({
|
|
|
6134
6305
|
SEEK_CUR = 1;
|
|
6135
6306
|
SEEK_END = 2;
|
|
6136
6307
|
EARLY_WHOLE_FILE = 64 * 1024;
|
|
6308
|
+
stale = (s) => !!s.orphan && !s.kept;
|
|
6137
6309
|
}
|
|
6138
6310
|
});
|
|
6139
6311
|
|
|
@@ -8248,7 +8420,7 @@ function useProcfs(Fs, sys, pid, memory = memorySource()) {
|
|
|
8248
8420
|
const pidContent = (target, name2, own = false) => () => {
|
|
8249
8421
|
const listing = procList();
|
|
8250
8422
|
const info = find(listing.processes, target, own);
|
|
8251
|
-
if (!info) throw error(
|
|
8423
|
+
if (!info) throw error();
|
|
8252
8424
|
return pidFile(name2, info, listing.boot);
|
|
8253
8425
|
};
|
|
8254
8426
|
const pidNames = (names) => [.../* @__PURE__ */ new Set([...names, ...PID_FILES])];
|
|
@@ -8261,14 +8433,29 @@ function useProcfs(Fs, sys, pid, memory = memorySource()) {
|
|
|
8261
8433
|
dir.node_ops.readdir = () => [".", "..", ...PID_FILES];
|
|
8262
8434
|
return dir;
|
|
8263
8435
|
};
|
|
8436
|
+
const scans = /* @__PURE__ */ new Map();
|
|
8437
|
+
const listed = (target) => {
|
|
8438
|
+
let found = false;
|
|
8439
|
+
for (const [stream, pids] of scans) {
|
|
8440
|
+
if (Fs.streams && Fs.streams[stream.fd ?? -1] !== stream) scans.delete(stream);
|
|
8441
|
+
else found ||= pids.has(target);
|
|
8442
|
+
}
|
|
8443
|
+
return found;
|
|
8444
|
+
};
|
|
8264
8445
|
const procOps = proc.node_ops;
|
|
8265
8446
|
const lookup = procOps.lookup?.bind(procOps);
|
|
8266
8447
|
const readdir = procOps.readdir?.bind(procOps);
|
|
8448
|
+
const listAll = (node) => {
|
|
8449
|
+
const names = new Set(readdir ? readdir(node) : [".", ".."]);
|
|
8450
|
+
for (const name2 of [...SYSTEM_FILES, "mounts"]) names.add(name2);
|
|
8451
|
+
for (const p of procList().processes) names.add(String(p.pid));
|
|
8452
|
+
return [...names];
|
|
8453
|
+
};
|
|
8267
8454
|
proc.node_ops = {
|
|
8268
8455
|
...procOps,
|
|
8269
8456
|
lookup: (parent, name2) => {
|
|
8270
8457
|
if (/^[1-9]\d*$/.test(name2)) {
|
|
8271
|
-
if (!infoOf(Number(name2))) throw error();
|
|
8458
|
+
if (!infoOf(Number(name2)) && !listed(Number(name2))) throw error();
|
|
8272
8459
|
return pidDir(name2, Number(name2));
|
|
8273
8460
|
}
|
|
8274
8461
|
if (name2 === "mounts") return file(parent, name2, () => mountTable(sys.mountList?.() ?? []));
|
|
@@ -8282,11 +8469,36 @@ function useProcfs(Fs, sys, pid, memory = memorySource()) {
|
|
|
8282
8469
|
if (!lookup) throw error();
|
|
8283
8470
|
return lookup(parent, name2);
|
|
8284
8471
|
},
|
|
8285
|
-
readdir: (node) =>
|
|
8286
|
-
|
|
8287
|
-
|
|
8288
|
-
|
|
8289
|
-
|
|
8472
|
+
readdir: (node) => listAll(node)
|
|
8473
|
+
};
|
|
8474
|
+
const track = (stream, names) => {
|
|
8475
|
+
let current = names;
|
|
8476
|
+
const remember = (list) => scans.set(stream, new Set(list.filter((n) => /^[1-9]\d*$/.test(n)).map(Number)));
|
|
8477
|
+
remember(current ?? []);
|
|
8478
|
+
Object.defineProperty(stream, "getdents", {
|
|
8479
|
+
configurable: true,
|
|
8480
|
+
enumerable: true,
|
|
8481
|
+
get: () => current,
|
|
8482
|
+
set: (next2) => {
|
|
8483
|
+
current = next2;
|
|
8484
|
+
if (next2) remember(next2);
|
|
8485
|
+
}
|
|
8486
|
+
});
|
|
8487
|
+
};
|
|
8488
|
+
const dirOps = proc.stream_ops ?? {};
|
|
8489
|
+
proc.stream_ops = {
|
|
8490
|
+
...dirOps,
|
|
8491
|
+
open: (stream) => {
|
|
8492
|
+
dirOps.open?.(stream);
|
|
8493
|
+
track(stream, listAll(proc));
|
|
8494
|
+
},
|
|
8495
|
+
dup: (stream) => {
|
|
8496
|
+
dirOps.dup?.(stream);
|
|
8497
|
+
track(stream, stream.getdents);
|
|
8498
|
+
},
|
|
8499
|
+
close: (stream) => {
|
|
8500
|
+
scans.delete(stream);
|
|
8501
|
+
dirOps.close?.(stream);
|
|
8290
8502
|
}
|
|
8291
8503
|
};
|
|
8292
8504
|
hashRemoveNode.call(Fs, self);
|
|
@@ -8310,7 +8522,7 @@ function useProcfs(Fs, sys, pid, memory = memorySource()) {
|
|
|
8310
8522
|
readdir: (node) => pidNames(selfReaddir ? selfReaddir(node) : [".", ".."])
|
|
8311
8523
|
};
|
|
8312
8524
|
}
|
|
8313
|
-
var HZ, DIR_MODE2, FILE_MODE, LINK_MODE2, ENOENT,
|
|
8525
|
+
var HZ, DIR_MODE2, FILE_MODE, LINK_MODE2, ENOENT, EINVAL, UID2, KIB, FALLBACK_MEMORY, PID_FILES, SYSTEM_FILES, sigMask;
|
|
8314
8526
|
var init_procfs = __esm({
|
|
8315
8527
|
"src/process/procfs.ts"() {
|
|
8316
8528
|
"use strict";
|
|
@@ -8321,7 +8533,6 @@ var init_procfs = __esm({
|
|
|
8321
8533
|
FILE_MODE = 33060;
|
|
8322
8534
|
LINK_MODE2 = 41471;
|
|
8323
8535
|
ENOENT = 44;
|
|
8324
|
-
ESRCH = 71;
|
|
8325
8536
|
EINVAL = 28;
|
|
8326
8537
|
UID2 = 1e3;
|
|
8327
8538
|
KIB = 1024;
|
|
@@ -9135,6 +9346,13 @@ function procfsBridge(fs, tree) {
|
|
|
9135
9346
|
() => fs.rename(from, to)
|
|
9136
9347
|
),
|
|
9137
9348
|
symlink: (target, link) => readOnly([[link, false]], () => fs.symlink(target, link)),
|
|
9349
|
+
link: (from, to, follow2) => readOnly(
|
|
9350
|
+
[
|
|
9351
|
+
[from, follow2 === true],
|
|
9352
|
+
[to, false]
|
|
9353
|
+
],
|
|
9354
|
+
() => fs.link(from, to, follow2)
|
|
9355
|
+
),
|
|
9138
9356
|
hold: (p, held, open, handle) => {
|
|
9139
9357
|
if (handle !== void 0 && snapshots.delete(handle)) return void 0;
|
|
9140
9358
|
if (!held) return fs.hold?.(p, held, open, handle);
|