@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
package/dist/process-worker.js
CHANGED
|
@@ -600,11 +600,54 @@ function toMs(v) {
|
|
|
600
600
|
if (v === void 0 || v === null) return void 0;
|
|
601
601
|
return v instanceof Date ? v.getTime() : v;
|
|
602
602
|
}
|
|
603
|
+
function linkedStates(bridgeOf) {
|
|
604
|
+
const opens = /* @__PURE__ */ new Map();
|
|
605
|
+
const byId = /* @__PURE__ */ new Map();
|
|
606
|
+
const idOf2 = (st) => st?.ino === void 0 || (st.nlink ?? 1) < 2 ? void 0 : `${st.dev}:${st.ino}`;
|
|
607
|
+
function know(s, id) {
|
|
608
|
+
s.id = id;
|
|
609
|
+
if (!byId.has(id)) byId.set(id, s);
|
|
610
|
+
}
|
|
611
|
+
function opening(node, on) {
|
|
612
|
+
const s = node.live;
|
|
613
|
+
if (!on) {
|
|
614
|
+
opens.delete(s);
|
|
615
|
+
if (s.id !== void 0 && byId.get(s.id) === s) byId.delete(s.id);
|
|
616
|
+
s.id = void 0;
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
opens.set(s, node);
|
|
620
|
+
const id = idOf2(s.stat);
|
|
621
|
+
if (id !== void 0) know(s, id);
|
|
622
|
+
}
|
|
623
|
+
function sharedWith(node) {
|
|
624
|
+
const st = node.live.stat;
|
|
625
|
+
if (st?.ino === void 0) return void 0;
|
|
626
|
+
const id = `${st.dev}:${st.ino}`;
|
|
627
|
+
if (!byId.has(id) && idOf2(st) !== void 0) {
|
|
628
|
+
for (const [s2, other] of opens) {
|
|
629
|
+
if (s2.id !== void 0 || s2.orphan) continue;
|
|
630
|
+
let st2;
|
|
631
|
+
try {
|
|
632
|
+
st2 = bridgeOf(other).lstat(liveNodePath(other));
|
|
633
|
+
} catch {
|
|
634
|
+
}
|
|
635
|
+
const known = idOf2(st2);
|
|
636
|
+
if (known !== void 0) know(s2, known);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
const s = byId.get(id);
|
|
640
|
+
return s && s !== node.live && !stale(s) ? s : void 0;
|
|
641
|
+
}
|
|
642
|
+
const holder = (node) => opens.get(node.live) ?? node;
|
|
643
|
+
return { opening, sharedWith, know, idOf: idOf2, holder };
|
|
644
|
+
}
|
|
603
645
|
function createHelpers(Fs, ops) {
|
|
604
646
|
const bridgeOf = (node) => node.mount.opts.bridge;
|
|
605
647
|
const fileIo = (node) => pinnedIo(bridgeOf(node), node.live.handle);
|
|
606
648
|
const dirty = /* @__PURE__ */ new Set();
|
|
607
649
|
const handled = /* @__PURE__ */ new Set();
|
|
650
|
+
const linked = linkedStates(bridgeOf);
|
|
608
651
|
function markDirty(node) {
|
|
609
652
|
node.live.dirty = true;
|
|
610
653
|
dirty.add(node);
|
|
@@ -612,7 +655,7 @@ function createHelpers(Fs, ops) {
|
|
|
612
655
|
function flushDirty() {
|
|
613
656
|
for (const node of [...dirty]) {
|
|
614
657
|
const s = node.live;
|
|
615
|
-
if (!s.dirty || s
|
|
658
|
+
if (!s.dirty || stale(s)) {
|
|
616
659
|
dirty.delete(node);
|
|
617
660
|
continue;
|
|
618
661
|
}
|
|
@@ -654,7 +697,7 @@ function createHelpers(Fs, ops) {
|
|
|
654
697
|
return { ...node.live.stat, size };
|
|
655
698
|
}
|
|
656
699
|
if (!node.live.stat) {
|
|
657
|
-
const st = call2(() => bridgeOf(node).lstat(liveNodePath(node)));
|
|
700
|
+
const st = call2(() => bridgeOf(node).lstat(liveNodePath(linked.holder(node))));
|
|
658
701
|
node.live.stat = st;
|
|
659
702
|
node.mode = modeFromStat(st);
|
|
660
703
|
}
|
|
@@ -667,7 +710,7 @@ function createHelpers(Fs, ops) {
|
|
|
667
710
|
function ensureLoaded(node) {
|
|
668
711
|
const s = node.live;
|
|
669
712
|
if (s.loaded) return;
|
|
670
|
-
const bytes = call2(() => fileIo(node).readFile(liveNodePath(node)));
|
|
713
|
+
const bytes = call2(() => fileIo(node).readFile(liveNodePath(linked.holder(node))));
|
|
671
714
|
s.data = bytes;
|
|
672
715
|
s.len = bytes.length;
|
|
673
716
|
s.loaded = true;
|
|
@@ -676,7 +719,7 @@ function createHelpers(Fs, ops) {
|
|
|
676
719
|
const s = node.live;
|
|
677
720
|
if (s.ranged || !s.ranges) return s.ranged;
|
|
678
721
|
const bridge = bridgeOf(node);
|
|
679
|
-
const path = () => liveNodePath(node);
|
|
722
|
+
const path = () => liveNodePath(linked.holder(node));
|
|
680
723
|
const file = () => fileIo(node);
|
|
681
724
|
const io = {
|
|
682
725
|
pread: (_, at, n, version) => file().pread(path(), at, n, version),
|
|
@@ -698,11 +741,11 @@ function createHelpers(Fs, ops) {
|
|
|
698
741
|
}
|
|
699
742
|
function flushNode(node) {
|
|
700
743
|
const s = node.live;
|
|
701
|
-
if (!s.dirty || s
|
|
744
|
+
if (!s.dirty || stale(s) || !(s.data || s.ranged)) return;
|
|
702
745
|
if (s.ranged) call2(() => s.ranged?.flush());
|
|
703
746
|
else {
|
|
704
747
|
const bytes = s.data.slice(0, s.len);
|
|
705
|
-
call2(() => fileIo(node).writeFile(liveNodePath(node), bytes, true));
|
|
748
|
+
call2(() => fileIo(node).writeFile(liveNodePath(linked.holder(node)), bytes, true));
|
|
706
749
|
}
|
|
707
750
|
s.dirty = false;
|
|
708
751
|
s.stat = void 0;
|
|
@@ -750,6 +793,7 @@ function createHelpers(Fs, ops) {
|
|
|
750
793
|
Fs,
|
|
751
794
|
bridgeOf,
|
|
752
795
|
handled,
|
|
796
|
+
linked,
|
|
753
797
|
call: call2,
|
|
754
798
|
metadataCall,
|
|
755
799
|
makeNode,
|
|
@@ -764,6 +808,33 @@ function createHelpers(Fs, ops) {
|
|
|
764
808
|
truncate
|
|
765
809
|
};
|
|
766
810
|
}
|
|
811
|
+
function freshStat(h, node) {
|
|
812
|
+
const { statOf } = h;
|
|
813
|
+
const st = statOf(node);
|
|
814
|
+
if (!st.linkable) return st;
|
|
815
|
+
node.live.stat = void 0;
|
|
816
|
+
return statOf(node);
|
|
817
|
+
}
|
|
818
|
+
function orphaned(h, node, st) {
|
|
819
|
+
const { bridgeOf } = h;
|
|
820
|
+
const s = node.live;
|
|
821
|
+
const nlink = st.nlink ?? 1;
|
|
822
|
+
let kept = false;
|
|
823
|
+
try {
|
|
824
|
+
kept = nlink > 1 && s.handle !== void 0 && bridgeOf(node).kept?.(s.handle) === true;
|
|
825
|
+
} catch {
|
|
826
|
+
}
|
|
827
|
+
if (nlink > 1 && !kept && h.linked.holder(node) !== node) {
|
|
828
|
+
s.stat = void 0;
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
s.orphan = true;
|
|
832
|
+
if (!kept) return;
|
|
833
|
+
s.kept = true;
|
|
834
|
+
s.stat = { ...st, nlink: nlink - 1 };
|
|
835
|
+
const id = h.linked.idOf(st);
|
|
836
|
+
if (id !== void 0) h.linked.know(s, id);
|
|
837
|
+
}
|
|
767
838
|
function createNodeOps(h) {
|
|
768
839
|
const { Fs, bridgeOf, call: call2, metadataCall, makeNode, statOf, childPath, flushNode, truncate } = h;
|
|
769
840
|
const { ensureLoaded } = h;
|
|
@@ -794,7 +865,7 @@ function createNodeOps(h) {
|
|
|
794
865
|
dev: st.dev ?? 1,
|
|
795
866
|
ino: st.ino ?? inodeOf(liveNodePath(node)),
|
|
796
867
|
mode: node.mode,
|
|
797
|
-
nlink: 1,
|
|
868
|
+
nlink: st.nlink ?? 1,
|
|
798
869
|
uid: owned ? st.uid ?? 0 : 0,
|
|
799
870
|
gid: owned ? st.gid ?? 0 : 0,
|
|
800
871
|
rdev: 0,
|
|
@@ -889,14 +960,14 @@ function createNodeOps(h) {
|
|
|
889
960
|
if (node && node.live?.openCount > 0 && Fs.isFile(node.mode)) open = node;
|
|
890
961
|
} catch {
|
|
891
962
|
}
|
|
963
|
+
const st = open && freshStat(h, open);
|
|
892
964
|
if (open) {
|
|
893
|
-
statOf(open);
|
|
894
965
|
const ranged = h.rangedOf(open);
|
|
895
966
|
if (ranged) ranged.pin();
|
|
896
967
|
else ensureLoaded(open);
|
|
897
968
|
}
|
|
898
969
|
call2(() => bridgeOf(parent).unlink(childPath(parent, name2)));
|
|
899
|
-
if (open) open
|
|
970
|
+
if (open && st) orphaned(h, open, st);
|
|
900
971
|
},
|
|
901
972
|
rmdir(parent, name2) {
|
|
902
973
|
parent.live.listed = void 0;
|
|
@@ -944,6 +1015,7 @@ function createStreamOps(h) {
|
|
|
944
1015
|
try {
|
|
945
1016
|
const handle = bridgeOf(node).hold?.(liveNodePath(node), on, true, s.handle);
|
|
946
1017
|
s.handle = on ? handle : void 0;
|
|
1018
|
+
h.linked.opening(node, on);
|
|
947
1019
|
if (s.handle === void 0) h.handled.delete(node);
|
|
948
1020
|
else h.handled.add(node);
|
|
949
1021
|
} catch {
|
|
@@ -956,7 +1028,9 @@ function createStreamOps(h) {
|
|
|
956
1028
|
if (s.openCount === 0 && !s.orphan) {
|
|
957
1029
|
const bridge = bridgeOf(stream.node);
|
|
958
1030
|
s.ranges = !!(bridge.pread && bridge.pwrite && bridge.truncate && statOf(stream.node).ranged);
|
|
959
|
-
|
|
1031
|
+
const shared = h.linked.sharedWith(stream.node);
|
|
1032
|
+
if (shared) stream.node.live = shared;
|
|
1033
|
+
else rangedOf(stream.node);
|
|
960
1034
|
}
|
|
961
1035
|
if ((stream.flags & 3) !== 0) {
|
|
962
1036
|
try {
|
|
@@ -1278,7 +1352,7 @@ function useLiveChown(Fs) {
|
|
|
1278
1352
|
Fs.chown(target, uid, gid);
|
|
1279
1353
|
};
|
|
1280
1354
|
}
|
|
1281
|
-
var S_IFDIR, S_IFREG, S_IFLNK, PERM_MASK, DEFAULT_DIR_PERM, UMASK, SEEK_CUR, SEEK_END, EARLY_WHOLE_FILE;
|
|
1355
|
+
var S_IFDIR, S_IFREG, S_IFLNK, PERM_MASK, DEFAULT_DIR_PERM, UMASK, SEEK_CUR, SEEK_END, EARLY_WHOLE_FILE, stale;
|
|
1282
1356
|
var init_live_vfs_fs = __esm({
|
|
1283
1357
|
"src/realm/live-vfs-fs.ts"() {
|
|
1284
1358
|
"use strict";
|
|
@@ -1294,6 +1368,7 @@ var init_live_vfs_fs = __esm({
|
|
|
1294
1368
|
SEEK_CUR = 1;
|
|
1295
1369
|
SEEK_END = 2;
|
|
1296
1370
|
EARLY_WHOLE_FILE = 64 * 1024;
|
|
1371
|
+
stale = (s) => !!s.orphan && !s.kept;
|
|
1297
1372
|
}
|
|
1298
1373
|
});
|
|
1299
1374
|
|
|
@@ -1369,10 +1444,12 @@ function parseSyncFsStat(json) {
|
|
|
1369
1444
|
...typeof s.atimeMs === "number" ? { atimeMs: s.atimeMs } : {},
|
|
1370
1445
|
...typeof s.ctimeMs === "number" ? { ctimeMs: s.ctimeMs } : {},
|
|
1371
1446
|
...typeof s.ino === "number" ? { ino: s.ino } : {},
|
|
1447
|
+
...typeof s.nlink === "number" ? { nlink: s.nlink } : {},
|
|
1372
1448
|
...typeof s.dev === "number" ? { dev: s.dev } : {},
|
|
1373
1449
|
...s.readonly === true ? { readonly: true } : {},
|
|
1374
1450
|
...typeof s.maxFile === "number" ? { maxFile: s.maxFile } : {},
|
|
1375
1451
|
...s.ranged === true ? { ranged: true } : {},
|
|
1452
|
+
...s.linkable === true ? { linkable: true } : {},
|
|
1376
1453
|
...typeof s.version === "string" ? { version: s.version } : {},
|
|
1377
1454
|
...typeof s.uid === "number" ? { uid: s.uid } : {},
|
|
1378
1455
|
...typeof s.gid === "number" ? { gid: s.gid } : {}
|
|
@@ -1393,6 +1470,7 @@ var init_sync_fs_wire = __esm({
|
|
|
1393
1470
|
"mkdir",
|
|
1394
1471
|
"rm",
|
|
1395
1472
|
"rename",
|
|
1473
|
+
"link",
|
|
1396
1474
|
"unlink",
|
|
1397
1475
|
"rmdir",
|
|
1398
1476
|
"symlink",
|
|
@@ -1639,6 +1717,9 @@ function createSyncFsSabBridge(transport, opts = {}) {
|
|
|
1639
1717
|
rename: (from, to) => {
|
|
1640
1718
|
run({ op: "rename", path: from, arg2: to }, from);
|
|
1641
1719
|
},
|
|
1720
|
+
link: (from, to, follow2) => {
|
|
1721
|
+
run({ op: "link", path: from, arg2: to, ...follow2 ? { mode: 1 } : {} }, from);
|
|
1722
|
+
},
|
|
1642
1723
|
unlink: (path) => {
|
|
1643
1724
|
run({ op: "unlink", path }, path);
|
|
1644
1725
|
},
|
|
@@ -3769,7 +3850,7 @@ function useProcfs(Fs, sys, pid, memory = memorySource()) {
|
|
|
3769
3850
|
const pidContent = (target, name2, own = false) => () => {
|
|
3770
3851
|
const listing = procList();
|
|
3771
3852
|
const info = find(listing.processes, target, own);
|
|
3772
|
-
if (!info) throw error(
|
|
3853
|
+
if (!info) throw error();
|
|
3773
3854
|
return pidFile(name2, info, listing.boot);
|
|
3774
3855
|
};
|
|
3775
3856
|
const pidNames = (names) => [.../* @__PURE__ */ new Set([...names, ...PID_FILES])];
|
|
@@ -3782,14 +3863,29 @@ function useProcfs(Fs, sys, pid, memory = memorySource()) {
|
|
|
3782
3863
|
dir.node_ops.readdir = () => [".", "..", ...PID_FILES];
|
|
3783
3864
|
return dir;
|
|
3784
3865
|
};
|
|
3866
|
+
const scans = /* @__PURE__ */ new Map();
|
|
3867
|
+
const listed = (target) => {
|
|
3868
|
+
let found = false;
|
|
3869
|
+
for (const [stream, pids] of scans) {
|
|
3870
|
+
if (Fs.streams && Fs.streams[stream.fd ?? -1] !== stream) scans.delete(stream);
|
|
3871
|
+
else found ||= pids.has(target);
|
|
3872
|
+
}
|
|
3873
|
+
return found;
|
|
3874
|
+
};
|
|
3785
3875
|
const procOps = proc.node_ops;
|
|
3786
3876
|
const lookup = procOps.lookup?.bind(procOps);
|
|
3787
3877
|
const readdir = procOps.readdir?.bind(procOps);
|
|
3878
|
+
const listAll = (node) => {
|
|
3879
|
+
const names = new Set(readdir ? readdir(node) : [".", ".."]);
|
|
3880
|
+
for (const name2 of [...SYSTEM_FILES, "mounts"]) names.add(name2);
|
|
3881
|
+
for (const p of procList().processes) names.add(String(p.pid));
|
|
3882
|
+
return [...names];
|
|
3883
|
+
};
|
|
3788
3884
|
proc.node_ops = {
|
|
3789
3885
|
...procOps,
|
|
3790
3886
|
lookup: (parent, name2) => {
|
|
3791
3887
|
if (/^[1-9]\d*$/.test(name2)) {
|
|
3792
|
-
if (!infoOf(Number(name2))) throw error();
|
|
3888
|
+
if (!infoOf(Number(name2)) && !listed(Number(name2))) throw error();
|
|
3793
3889
|
return pidDir(name2, Number(name2));
|
|
3794
3890
|
}
|
|
3795
3891
|
if (name2 === "mounts") return file(parent, name2, () => mountTable(sys.mountList?.() ?? []));
|
|
@@ -3803,11 +3899,36 @@ function useProcfs(Fs, sys, pid, memory = memorySource()) {
|
|
|
3803
3899
|
if (!lookup) throw error();
|
|
3804
3900
|
return lookup(parent, name2);
|
|
3805
3901
|
},
|
|
3806
|
-
readdir: (node) =>
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3902
|
+
readdir: (node) => listAll(node)
|
|
3903
|
+
};
|
|
3904
|
+
const track = (stream, names) => {
|
|
3905
|
+
let current = names;
|
|
3906
|
+
const remember = (list) => scans.set(stream, new Set(list.filter((n) => /^[1-9]\d*$/.test(n)).map(Number)));
|
|
3907
|
+
remember(current ?? []);
|
|
3908
|
+
Object.defineProperty(stream, "getdents", {
|
|
3909
|
+
configurable: true,
|
|
3910
|
+
enumerable: true,
|
|
3911
|
+
get: () => current,
|
|
3912
|
+
set: (next2) => {
|
|
3913
|
+
current = next2;
|
|
3914
|
+
if (next2) remember(next2);
|
|
3915
|
+
}
|
|
3916
|
+
});
|
|
3917
|
+
};
|
|
3918
|
+
const dirOps = proc.stream_ops ?? {};
|
|
3919
|
+
proc.stream_ops = {
|
|
3920
|
+
...dirOps,
|
|
3921
|
+
open: (stream) => {
|
|
3922
|
+
dirOps.open?.(stream);
|
|
3923
|
+
track(stream, listAll(proc));
|
|
3924
|
+
},
|
|
3925
|
+
dup: (stream) => {
|
|
3926
|
+
dirOps.dup?.(stream);
|
|
3927
|
+
track(stream, stream.getdents);
|
|
3928
|
+
},
|
|
3929
|
+
close: (stream) => {
|
|
3930
|
+
scans.delete(stream);
|
|
3931
|
+
dirOps.close?.(stream);
|
|
3811
3932
|
}
|
|
3812
3933
|
};
|
|
3813
3934
|
hashRemoveNode.call(Fs, self);
|
|
@@ -3831,7 +3952,7 @@ function useProcfs(Fs, sys, pid, memory = memorySource()) {
|
|
|
3831
3952
|
readdir: (node) => pidNames(selfReaddir ? selfReaddir(node) : [".", ".."])
|
|
3832
3953
|
};
|
|
3833
3954
|
}
|
|
3834
|
-
var HZ, DIR_MODE2, FILE_MODE, LINK_MODE2, ENOENT,
|
|
3955
|
+
var HZ, DIR_MODE2, FILE_MODE, LINK_MODE2, ENOENT, EINVAL, UID, KIB, FALLBACK_MEMORY, PID_FILES, SYSTEM_FILES, sigMask;
|
|
3835
3956
|
var init_procfs = __esm({
|
|
3836
3957
|
"src/process/procfs.ts"() {
|
|
3837
3958
|
"use strict";
|
|
@@ -3842,7 +3963,6 @@ var init_procfs = __esm({
|
|
|
3842
3963
|
FILE_MODE = 33060;
|
|
3843
3964
|
LINK_MODE2 = 41471;
|
|
3844
3965
|
ENOENT = 44;
|
|
3845
|
-
ESRCH = 71;
|
|
3846
3966
|
EINVAL = 28;
|
|
3847
3967
|
UID = 1e3;
|
|
3848
3968
|
KIB = 1024;
|
|
@@ -4633,6 +4753,7 @@ function cachingBridge(bridge, now = () => performance.now(), shared) {
|
|
|
4633
4753
|
mkdir: (p) => mutating(() => bridge.mkdir(p), ...entry(p)),
|
|
4634
4754
|
rm: (p) => mutating(() => bridge.rm(p)),
|
|
4635
4755
|
rename: (from, to) => mutating(() => bridge.rename(from, to)),
|
|
4756
|
+
link: (from, to, follow2) => mutating(() => bridge.link(from, to, follow2)),
|
|
4636
4757
|
unlink: (p) => mutating(() => bridge.unlink(p)),
|
|
4637
4758
|
rmdir: (p) => mutating(() => bridge.rmdir(p)),
|
|
4638
4759
|
symlink: (target, link) => mutating(() => bridge.symlink(target, link), ...entry(link)),
|
|
@@ -5051,6 +5172,8 @@ var init_wasi_fds = __esm({
|
|
|
5051
5172
|
WasiFds = class {
|
|
5052
5173
|
table = /* @__PURE__ */ new Map();
|
|
5053
5174
|
buffers = /* @__PURE__ */ new Map();
|
|
5175
|
+
byId = /* @__PURE__ */ new Map();
|
|
5176
|
+
ids = /* @__PURE__ */ new Map();
|
|
5054
5177
|
kernel;
|
|
5055
5178
|
fs;
|
|
5056
5179
|
constructor(kernel, fs) {
|
|
@@ -5300,7 +5423,7 @@ var init_wasi_fds = __esm({
|
|
|
5300
5423
|
}
|
|
5301
5424
|
for (const file of promoted.keys()) {
|
|
5302
5425
|
if (--file.buffer.opens <= 0) {
|
|
5303
|
-
this.
|
|
5426
|
+
this.forget(file.buffer);
|
|
5304
5427
|
this.letGo(file.buffer);
|
|
5305
5428
|
}
|
|
5306
5429
|
}
|
|
@@ -5371,9 +5494,48 @@ var init_wasi_fds = __esm({
|
|
|
5371
5494
|
const { buffer } = e.file;
|
|
5372
5495
|
buffer.flush();
|
|
5373
5496
|
if (--buffer.opens > 0) return;
|
|
5374
|
-
|
|
5497
|
+
this.forget(buffer);
|
|
5375
5498
|
this.letGo(buffer);
|
|
5376
5499
|
}
|
|
5500
|
+
forget(buffer) {
|
|
5501
|
+
for (const [p, b] of [...this.buffers]) if (b === buffer) this.buffers.delete(p);
|
|
5502
|
+
const id = this.ids.get(buffer);
|
|
5503
|
+
if (id !== void 0 && this.byId.get(id) === buffer) this.byId.delete(id);
|
|
5504
|
+
this.ids.delete(buffer);
|
|
5505
|
+
}
|
|
5506
|
+
know(buffer, id) {
|
|
5507
|
+
if (this.ids.has(buffer)) return;
|
|
5508
|
+
this.ids.set(buffer, id);
|
|
5509
|
+
if (!this.byId.has(id)) this.byId.set(id, buffer);
|
|
5510
|
+
}
|
|
5511
|
+
identity(st) {
|
|
5512
|
+
if (!st || st.ino === void 0 || (st.nlink ?? 1) < 2) return void 0;
|
|
5513
|
+
return `${st.dev ?? 0}:${st.ino}`;
|
|
5514
|
+
}
|
|
5515
|
+
sharing(path, st) {
|
|
5516
|
+
if (st?.ino === void 0) return void 0;
|
|
5517
|
+
const id = `${st.dev ?? 0}:${st.ino}`;
|
|
5518
|
+
if (!this.byId.has(id) && this.identity(st) !== void 0) this.learn();
|
|
5519
|
+
const buffer = this.byId.get(id);
|
|
5520
|
+
if (!buffer) return void 0;
|
|
5521
|
+
this.buffers.set(path, buffer);
|
|
5522
|
+
return buffer;
|
|
5523
|
+
}
|
|
5524
|
+
learn() {
|
|
5525
|
+
for (const [p, buffer] of this.buffers) {
|
|
5526
|
+
if (this.ids.has(buffer) || buffer.isOrphan()) continue;
|
|
5527
|
+
const known = this.identity(this.statOrMissing(p));
|
|
5528
|
+
if (known !== void 0) this.know(buffer, known);
|
|
5529
|
+
}
|
|
5530
|
+
}
|
|
5531
|
+
linked(from, to) {
|
|
5532
|
+
const buffer = this.buffers.get(from);
|
|
5533
|
+
if (!buffer || buffer.isOrphan()) return;
|
|
5534
|
+
const id = this.identity(this.statOrMissing(to));
|
|
5535
|
+
if (id === void 0) return;
|
|
5536
|
+
this.know(buffer, id);
|
|
5537
|
+
if (!this.buffers.has(to)) this.buffers.set(to, buffer);
|
|
5538
|
+
}
|
|
5377
5539
|
letGo(buffer) {
|
|
5378
5540
|
this.fs.hold?.(buffer.path, false, true, buffer.handle);
|
|
5379
5541
|
}
|
|
@@ -5399,15 +5561,21 @@ var init_wasi_fds = __esm({
|
|
|
5399
5561
|
for (const [p, buffer] of this.buffers) if (within(p, path)) buffer.flush();
|
|
5400
5562
|
if (this.shared) this.kernel.call({ op: "fd-path-flush", path });
|
|
5401
5563
|
}
|
|
5402
|
-
|
|
5403
|
-
this.buffers.
|
|
5564
|
+
holdsUnder(path) {
|
|
5565
|
+
for (const p of this.buffers.keys()) if (within(p, path)) return true;
|
|
5566
|
+
return false;
|
|
5567
|
+
}
|
|
5568
|
+
unlinking(path, linked) {
|
|
5569
|
+
const buffer = this.buffers.get(path);
|
|
5570
|
+
if (buffer && this.survives(buffer, linked)) buffer.flush();
|
|
5571
|
+
else buffer?.keep();
|
|
5404
5572
|
if (this.shared) this.kernel.call({ op: "fd-path-unlinking", path });
|
|
5405
5573
|
}
|
|
5406
|
-
unlinked(path) {
|
|
5574
|
+
unlinked(path, linked) {
|
|
5407
5575
|
if (this.shared) this.kernel.call({ op: "fd-path-unlinked", path });
|
|
5408
5576
|
const buffer = this.buffers.get(path);
|
|
5409
5577
|
if (!buffer) return;
|
|
5410
|
-
|
|
5578
|
+
this.detach(buffer, linked);
|
|
5411
5579
|
this.buffers.delete(path);
|
|
5412
5580
|
}
|
|
5413
5581
|
inoOf(path) {
|
|
@@ -5417,7 +5585,19 @@ var init_wasi_fds = __esm({
|
|
|
5417
5585
|
return void 0;
|
|
5418
5586
|
}
|
|
5419
5587
|
}
|
|
5420
|
-
|
|
5588
|
+
survives(buffer, linked) {
|
|
5589
|
+
return linked !== void 0 && buffer.handle !== void 0;
|
|
5590
|
+
}
|
|
5591
|
+
detach(buffer, linked) {
|
|
5592
|
+
if (this.survives(buffer, linked)) {
|
|
5593
|
+
const id = this.identity(linked);
|
|
5594
|
+
if (id !== void 0) this.know(buffer, id);
|
|
5595
|
+
return;
|
|
5596
|
+
}
|
|
5597
|
+
buffer.orphan();
|
|
5598
|
+
this.forget(buffer);
|
|
5599
|
+
}
|
|
5600
|
+
renamed(from, to, replacedLinked) {
|
|
5421
5601
|
if (from === to) return;
|
|
5422
5602
|
if (this.shared) this.kernel.call({ op: "fd-path-renamed", from, to });
|
|
5423
5603
|
for (const e of this.table.values()) {
|
|
@@ -5429,14 +5609,15 @@ var init_wasi_fds = __esm({
|
|
|
5429
5609
|
for (const [p, buffer] of this.buffers) {
|
|
5430
5610
|
if (within(p, from)) moved.push([p, buffer]);
|
|
5431
5611
|
else if (within(p, to)) {
|
|
5432
|
-
|
|
5612
|
+
this.detach(buffer, replacedLinked);
|
|
5433
5613
|
this.buffers.delete(p);
|
|
5434
5614
|
}
|
|
5435
5615
|
}
|
|
5616
|
+
for (const [p] of moved) this.buffers.delete(p);
|
|
5436
5617
|
for (const [p, buffer] of moved) {
|
|
5437
|
-
|
|
5438
|
-
buffer.path
|
|
5439
|
-
this.buffers.set(
|
|
5618
|
+
const next2 = to + p.slice(from.length);
|
|
5619
|
+
if (buffer.path === p) buffer.path = next2;
|
|
5620
|
+
this.buffers.set(next2, buffer);
|
|
5440
5621
|
}
|
|
5441
5622
|
}
|
|
5442
5623
|
resolve(dirfd, path) {
|
|
@@ -5479,6 +5660,7 @@ var init_wasi_fds = __esm({
|
|
|
5479
5660
|
this.buffers.delete(path);
|
|
5480
5661
|
buffer = void 0;
|
|
5481
5662
|
}
|
|
5663
|
+
buffer ??= this.sharing(path, existing);
|
|
5482
5664
|
if (buffer) {
|
|
5483
5665
|
if (oflags & OFLAGS.TRUNC) buffer.truncate(0);
|
|
5484
5666
|
} else {
|
|
@@ -5492,6 +5674,8 @@ var init_wasi_fds = __esm({
|
|
|
5492
5674
|
buffer = new FileBuffer(io, path, empty, st.maxFile, ranged, st.version);
|
|
5493
5675
|
buffer.handle = handle;
|
|
5494
5676
|
this.buffers.set(path, buffer);
|
|
5677
|
+
const id = this.identity(st);
|
|
5678
|
+
if (id !== void 0) this.know(buffer, id);
|
|
5495
5679
|
}
|
|
5496
5680
|
buffer.opens++;
|
|
5497
5681
|
return new LocalFile(buffer, readable2, writable2, (fdflags & FDFLAGS.APPEND) !== 0);
|
|
@@ -5825,6 +6009,16 @@ var init_wasi_termios = __esm({
|
|
|
5825
6009
|
});
|
|
5826
6010
|
|
|
5827
6011
|
// src/process/wasi/wasi-host.ts
|
|
6012
|
+
function linkedOf(st) {
|
|
6013
|
+
return (st.nlink ?? 1) > 1 ? st : void 0;
|
|
6014
|
+
}
|
|
6015
|
+
function linkedElsewhere(fs, path) {
|
|
6016
|
+
try {
|
|
6017
|
+
return linkedOf(fs.lstat(path));
|
|
6018
|
+
} catch {
|
|
6019
|
+
return void 0;
|
|
6020
|
+
}
|
|
6021
|
+
}
|
|
5828
6022
|
function filetypeOf(s) {
|
|
5829
6023
|
if (!s) return FILETYPE.UNKNOWN;
|
|
5830
6024
|
if (s.isSymbolicLink) return FILETYPE.SYMBOLIC_LINK;
|
|
@@ -5836,6 +6030,7 @@ function filestatOf(path, s) {
|
|
|
5836
6030
|
filetype: filetypeOf(s),
|
|
5837
6031
|
size: BigInt(s.size),
|
|
5838
6032
|
ino: s.ino !== void 0 ? BigInt(s.ino) : pathInode(path),
|
|
6033
|
+
...s.nlink !== void 0 ? { nlink: BigInt(s.nlink) } : {},
|
|
5839
6034
|
mtimeNs: BigInt(Math.round(s.mtimeMs ?? 0)) * NS_PER_MS
|
|
5840
6035
|
};
|
|
5841
6036
|
}
|
|
@@ -5886,6 +6081,7 @@ var WasiExit, IDS, NS_PER_MS, AT_SYMLINK_NOFOLLOW2, S_IFIFO, DEFAULT_UMASK, MONO
|
|
|
5886
6081
|
var init_wasi_host = __esm({
|
|
5887
6082
|
"src/process/wasi/wasi-host.ts"() {
|
|
5888
6083
|
"use strict";
|
|
6084
|
+
init_physical_path();
|
|
5889
6085
|
init_cred();
|
|
5890
6086
|
init_wasi_abi();
|
|
5891
6087
|
init_wasi_fds();
|
|
@@ -6195,17 +6391,20 @@ var init_wasi_host = __esm({
|
|
|
6195
6391
|
path_remove_directory: (dirfd, p, l) => void o.fs.rmdir(at(dirfd, p, l)),
|
|
6196
6392
|
path_unlink_file: (dirfd, p, l) => {
|
|
6197
6393
|
const path = at(dirfd, p, l);
|
|
6198
|
-
|
|
6199
|
-
|
|
6394
|
+
const st = o.fs.lstat(path);
|
|
6395
|
+
if (st.isDirectory) throw new WasiError("EISDIR");
|
|
6396
|
+
const linked = linkedOf(st);
|
|
6397
|
+
fds.unlinking(path, linked);
|
|
6200
6398
|
o.fs.unlink(path);
|
|
6201
|
-
fds.unlinked(path);
|
|
6399
|
+
fds.unlinked(path, linked);
|
|
6202
6400
|
},
|
|
6203
6401
|
path_rename: (fd, p, l, fd2, p2, l2) => {
|
|
6204
6402
|
const from = at(fd, p, l);
|
|
6205
6403
|
const to = at(fd2, p2, l2);
|
|
6206
6404
|
fds.flushPath(from);
|
|
6405
|
+
const replaced = fds.holdsUnder(to) ? linkedElsewhere(o.fs, to) : void 0;
|
|
6207
6406
|
o.fs.rename(from, to);
|
|
6208
|
-
fds.renamed(from, to);
|
|
6407
|
+
fds.renamed(from, to, replaced);
|
|
6209
6408
|
},
|
|
6210
6409
|
path_symlink: (tp, tl, dirfd, p, l) => void o.fs.symlink(mem.string(tp, tl), at(dirfd, p, l)),
|
|
6211
6410
|
path_readlink: (dirfd, p, l, buf, len, used) => {
|
|
@@ -6214,7 +6413,17 @@ var init_wasi_host = __esm({
|
|
|
6214
6413
|
mem.bytes(buf, n).set(target.subarray(0, n));
|
|
6215
6414
|
mem.view().setUint32(used, n, true);
|
|
6216
6415
|
},
|
|
6217
|
-
path_link: () =>
|
|
6416
|
+
path_link: (fd, lookup, p, l, fd2, p2, l2) => {
|
|
6417
|
+
const from = at(fd, p, l);
|
|
6418
|
+
const to = at(fd2, p2, l2);
|
|
6419
|
+
const follow2 = (lookup & LOOKUP_SYMLINK_FOLLOW) !== 0;
|
|
6420
|
+
const source = follow2 ? physicalPath(o.fs, from) : from;
|
|
6421
|
+
fds.flushPath(from);
|
|
6422
|
+
if (source !== from) fds.flushPath(source);
|
|
6423
|
+
o.fs.link(from, to, follow2);
|
|
6424
|
+
fds.linked(from, to);
|
|
6425
|
+
if (source !== from) fds.linked(source, to);
|
|
6426
|
+
}
|
|
6218
6427
|
};
|
|
6219
6428
|
}
|
|
6220
6429
|
socket(fd) {
|
|
@@ -6418,7 +6627,7 @@ var init_wasi_host = __esm({
|
|
|
6418
6627
|
v.setBigUint64(ptr, 1n, true);
|
|
6419
6628
|
v.setBigUint64(ptr + 8, f.ino, true);
|
|
6420
6629
|
v.setUint8(ptr + 16, f.filetype);
|
|
6421
|
-
v.setBigUint64(ptr + 24, 1n, true);
|
|
6630
|
+
v.setBigUint64(ptr + 24, f.nlink ?? 1n, true);
|
|
6422
6631
|
v.setBigUint64(ptr + 32, f.size, true);
|
|
6423
6632
|
v.setBigUint64(ptr + 40, f.mtimeNs, true);
|
|
6424
6633
|
v.setBigUint64(ptr + 48, f.mtimeNs, true);
|
|
@@ -7222,6 +7431,13 @@ function procfsBridge(fs, tree) {
|
|
|
7222
7431
|
() => fs.rename(from, to)
|
|
7223
7432
|
),
|
|
7224
7433
|
symlink: (target, link) => readOnly([[link, false]], () => fs.symlink(target, link)),
|
|
7434
|
+
link: (from, to, follow2) => readOnly(
|
|
7435
|
+
[
|
|
7436
|
+
[from, follow2 === true],
|
|
7437
|
+
[to, false]
|
|
7438
|
+
],
|
|
7439
|
+
() => fs.link(from, to, follow2)
|
|
7440
|
+
),
|
|
7225
7441
|
hold: (p, held, open, handle) => {
|
|
7226
7442
|
if (handle !== void 0 && snapshots.delete(handle)) return void 0;
|
|
7227
7443
|
if (!held) return fs.hold?.(p, held, open, handle);
|
|
@@ -11019,6 +11235,7 @@ function syncPathOps(kernel, resolve, statOf, open) {
|
|
|
11019
11235
|
rm: (path) => void kernel.call({ op: "rm", path: resolve(path) }),
|
|
11020
11236
|
unlink: (path) => void kernel.call({ op: "unlink", path: resolve(path) }),
|
|
11021
11237
|
rename: (from, to) => void kernel.call({ op: "rename", path: resolve(from), arg2: resolve(to) }),
|
|
11238
|
+
link: (from, to) => void kernel.call({ op: "link", path: resolve(from), arg2: resolve(to) }),
|
|
11022
11239
|
symlink: (target, path) => void kernel.call({ op: "symlink", path: resolve(path), arg2: target }),
|
|
11023
11240
|
readlink: (path) => String(kernel.json({ op: "readlink", path: resolve(path) })),
|
|
11024
11241
|
readFile(path) {
|
|
@@ -11615,6 +11832,7 @@ function pathOps(kernel, resolve, statOf, open) {
|
|
|
11615
11832
|
rm: async (path) => void await kernel.call({ op: "rm", path: resolve(path) }),
|
|
11616
11833
|
unlink: async (path) => void await kernel.call({ op: "unlink", path: resolve(path) }),
|
|
11617
11834
|
rename: async (from, to) => void await kernel.call({ op: "rename", path: resolve(from), arg2: resolve(to) }),
|
|
11835
|
+
link: async (from, to) => void await kernel.call({ op: "link", path: resolve(from), arg2: resolve(to) }),
|
|
11618
11836
|
symlink: async (target, path) => void await kernel.call({ op: "symlink", path: resolve(path), arg2: target }),
|
|
11619
11837
|
readlink: async (path) => String(await kernel.json({ op: "readlink", path: resolve(path) })),
|
|
11620
11838
|
async readFile(path) {
|