@ai-ecoverse/slicc-kernel 1.57.1 → 1.58.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 +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 +207 -28
- 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 +207 -28
- 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
|
},
|
|
@@ -4633,6 +4714,7 @@ function cachingBridge(bridge, now = () => performance.now(), shared) {
|
|
|
4633
4714
|
mkdir: (p) => mutating(() => bridge.mkdir(p), ...entry(p)),
|
|
4634
4715
|
rm: (p) => mutating(() => bridge.rm(p)),
|
|
4635
4716
|
rename: (from, to) => mutating(() => bridge.rename(from, to)),
|
|
4717
|
+
link: (from, to, follow2) => mutating(() => bridge.link(from, to, follow2)),
|
|
4636
4718
|
unlink: (p) => mutating(() => bridge.unlink(p)),
|
|
4637
4719
|
rmdir: (p) => mutating(() => bridge.rmdir(p)),
|
|
4638
4720
|
symlink: (target, link) => mutating(() => bridge.symlink(target, link), ...entry(link)),
|
|
@@ -5051,6 +5133,8 @@ var init_wasi_fds = __esm({
|
|
|
5051
5133
|
WasiFds = class {
|
|
5052
5134
|
table = /* @__PURE__ */ new Map();
|
|
5053
5135
|
buffers = /* @__PURE__ */ new Map();
|
|
5136
|
+
byId = /* @__PURE__ */ new Map();
|
|
5137
|
+
ids = /* @__PURE__ */ new Map();
|
|
5054
5138
|
kernel;
|
|
5055
5139
|
fs;
|
|
5056
5140
|
constructor(kernel, fs) {
|
|
@@ -5300,7 +5384,7 @@ var init_wasi_fds = __esm({
|
|
|
5300
5384
|
}
|
|
5301
5385
|
for (const file of promoted.keys()) {
|
|
5302
5386
|
if (--file.buffer.opens <= 0) {
|
|
5303
|
-
this.
|
|
5387
|
+
this.forget(file.buffer);
|
|
5304
5388
|
this.letGo(file.buffer);
|
|
5305
5389
|
}
|
|
5306
5390
|
}
|
|
@@ -5371,9 +5455,48 @@ var init_wasi_fds = __esm({
|
|
|
5371
5455
|
const { buffer } = e.file;
|
|
5372
5456
|
buffer.flush();
|
|
5373
5457
|
if (--buffer.opens > 0) return;
|
|
5374
|
-
|
|
5458
|
+
this.forget(buffer);
|
|
5375
5459
|
this.letGo(buffer);
|
|
5376
5460
|
}
|
|
5461
|
+
forget(buffer) {
|
|
5462
|
+
for (const [p, b] of [...this.buffers]) if (b === buffer) this.buffers.delete(p);
|
|
5463
|
+
const id = this.ids.get(buffer);
|
|
5464
|
+
if (id !== void 0 && this.byId.get(id) === buffer) this.byId.delete(id);
|
|
5465
|
+
this.ids.delete(buffer);
|
|
5466
|
+
}
|
|
5467
|
+
know(buffer, id) {
|
|
5468
|
+
if (this.ids.has(buffer)) return;
|
|
5469
|
+
this.ids.set(buffer, id);
|
|
5470
|
+
if (!this.byId.has(id)) this.byId.set(id, buffer);
|
|
5471
|
+
}
|
|
5472
|
+
identity(st) {
|
|
5473
|
+
if (!st || st.ino === void 0 || (st.nlink ?? 1) < 2) return void 0;
|
|
5474
|
+
return `${st.dev ?? 0}:${st.ino}`;
|
|
5475
|
+
}
|
|
5476
|
+
sharing(path, st) {
|
|
5477
|
+
if (st?.ino === void 0) return void 0;
|
|
5478
|
+
const id = `${st.dev ?? 0}:${st.ino}`;
|
|
5479
|
+
if (!this.byId.has(id) && this.identity(st) !== void 0) this.learn();
|
|
5480
|
+
const buffer = this.byId.get(id);
|
|
5481
|
+
if (!buffer) return void 0;
|
|
5482
|
+
this.buffers.set(path, buffer);
|
|
5483
|
+
return buffer;
|
|
5484
|
+
}
|
|
5485
|
+
learn() {
|
|
5486
|
+
for (const [p, buffer] of this.buffers) {
|
|
5487
|
+
if (this.ids.has(buffer) || buffer.isOrphan()) continue;
|
|
5488
|
+
const known = this.identity(this.statOrMissing(p));
|
|
5489
|
+
if (known !== void 0) this.know(buffer, known);
|
|
5490
|
+
}
|
|
5491
|
+
}
|
|
5492
|
+
linked(from, to) {
|
|
5493
|
+
const buffer = this.buffers.get(from);
|
|
5494
|
+
if (!buffer || buffer.isOrphan()) return;
|
|
5495
|
+
const id = this.identity(this.statOrMissing(to));
|
|
5496
|
+
if (id === void 0) return;
|
|
5497
|
+
this.know(buffer, id);
|
|
5498
|
+
if (!this.buffers.has(to)) this.buffers.set(to, buffer);
|
|
5499
|
+
}
|
|
5377
5500
|
letGo(buffer) {
|
|
5378
5501
|
this.fs.hold?.(buffer.path, false, true, buffer.handle);
|
|
5379
5502
|
}
|
|
@@ -5399,15 +5522,21 @@ var init_wasi_fds = __esm({
|
|
|
5399
5522
|
for (const [p, buffer] of this.buffers) if (within(p, path)) buffer.flush();
|
|
5400
5523
|
if (this.shared) this.kernel.call({ op: "fd-path-flush", path });
|
|
5401
5524
|
}
|
|
5402
|
-
|
|
5403
|
-
this.buffers.
|
|
5525
|
+
holdsUnder(path) {
|
|
5526
|
+
for (const p of this.buffers.keys()) if (within(p, path)) return true;
|
|
5527
|
+
return false;
|
|
5528
|
+
}
|
|
5529
|
+
unlinking(path, linked) {
|
|
5530
|
+
const buffer = this.buffers.get(path);
|
|
5531
|
+
if (buffer && this.survives(buffer, linked)) buffer.flush();
|
|
5532
|
+
else buffer?.keep();
|
|
5404
5533
|
if (this.shared) this.kernel.call({ op: "fd-path-unlinking", path });
|
|
5405
5534
|
}
|
|
5406
|
-
unlinked(path) {
|
|
5535
|
+
unlinked(path, linked) {
|
|
5407
5536
|
if (this.shared) this.kernel.call({ op: "fd-path-unlinked", path });
|
|
5408
5537
|
const buffer = this.buffers.get(path);
|
|
5409
5538
|
if (!buffer) return;
|
|
5410
|
-
|
|
5539
|
+
this.detach(buffer, linked);
|
|
5411
5540
|
this.buffers.delete(path);
|
|
5412
5541
|
}
|
|
5413
5542
|
inoOf(path) {
|
|
@@ -5417,7 +5546,19 @@ var init_wasi_fds = __esm({
|
|
|
5417
5546
|
return void 0;
|
|
5418
5547
|
}
|
|
5419
5548
|
}
|
|
5420
|
-
|
|
5549
|
+
survives(buffer, linked) {
|
|
5550
|
+
return linked !== void 0 && buffer.handle !== void 0;
|
|
5551
|
+
}
|
|
5552
|
+
detach(buffer, linked) {
|
|
5553
|
+
if (this.survives(buffer, linked)) {
|
|
5554
|
+
const id = this.identity(linked);
|
|
5555
|
+
if (id !== void 0) this.know(buffer, id);
|
|
5556
|
+
return;
|
|
5557
|
+
}
|
|
5558
|
+
buffer.orphan();
|
|
5559
|
+
this.forget(buffer);
|
|
5560
|
+
}
|
|
5561
|
+
renamed(from, to, replacedLinked) {
|
|
5421
5562
|
if (from === to) return;
|
|
5422
5563
|
if (this.shared) this.kernel.call({ op: "fd-path-renamed", from, to });
|
|
5423
5564
|
for (const e of this.table.values()) {
|
|
@@ -5429,14 +5570,15 @@ var init_wasi_fds = __esm({
|
|
|
5429
5570
|
for (const [p, buffer] of this.buffers) {
|
|
5430
5571
|
if (within(p, from)) moved.push([p, buffer]);
|
|
5431
5572
|
else if (within(p, to)) {
|
|
5432
|
-
|
|
5573
|
+
this.detach(buffer, replacedLinked);
|
|
5433
5574
|
this.buffers.delete(p);
|
|
5434
5575
|
}
|
|
5435
5576
|
}
|
|
5577
|
+
for (const [p] of moved) this.buffers.delete(p);
|
|
5436
5578
|
for (const [p, buffer] of moved) {
|
|
5437
|
-
|
|
5438
|
-
buffer.path
|
|
5439
|
-
this.buffers.set(
|
|
5579
|
+
const next2 = to + p.slice(from.length);
|
|
5580
|
+
if (buffer.path === p) buffer.path = next2;
|
|
5581
|
+
this.buffers.set(next2, buffer);
|
|
5440
5582
|
}
|
|
5441
5583
|
}
|
|
5442
5584
|
resolve(dirfd, path) {
|
|
@@ -5479,6 +5621,7 @@ var init_wasi_fds = __esm({
|
|
|
5479
5621
|
this.buffers.delete(path);
|
|
5480
5622
|
buffer = void 0;
|
|
5481
5623
|
}
|
|
5624
|
+
buffer ??= this.sharing(path, existing);
|
|
5482
5625
|
if (buffer) {
|
|
5483
5626
|
if (oflags & OFLAGS.TRUNC) buffer.truncate(0);
|
|
5484
5627
|
} else {
|
|
@@ -5492,6 +5635,8 @@ var init_wasi_fds = __esm({
|
|
|
5492
5635
|
buffer = new FileBuffer(io, path, empty, st.maxFile, ranged, st.version);
|
|
5493
5636
|
buffer.handle = handle;
|
|
5494
5637
|
this.buffers.set(path, buffer);
|
|
5638
|
+
const id = this.identity(st);
|
|
5639
|
+
if (id !== void 0) this.know(buffer, id);
|
|
5495
5640
|
}
|
|
5496
5641
|
buffer.opens++;
|
|
5497
5642
|
return new LocalFile(buffer, readable2, writable2, (fdflags & FDFLAGS.APPEND) !== 0);
|
|
@@ -5825,6 +5970,16 @@ var init_wasi_termios = __esm({
|
|
|
5825
5970
|
});
|
|
5826
5971
|
|
|
5827
5972
|
// src/process/wasi/wasi-host.ts
|
|
5973
|
+
function linkedOf(st) {
|
|
5974
|
+
return (st.nlink ?? 1) > 1 ? st : void 0;
|
|
5975
|
+
}
|
|
5976
|
+
function linkedElsewhere(fs, path) {
|
|
5977
|
+
try {
|
|
5978
|
+
return linkedOf(fs.lstat(path));
|
|
5979
|
+
} catch {
|
|
5980
|
+
return void 0;
|
|
5981
|
+
}
|
|
5982
|
+
}
|
|
5828
5983
|
function filetypeOf(s) {
|
|
5829
5984
|
if (!s) return FILETYPE.UNKNOWN;
|
|
5830
5985
|
if (s.isSymbolicLink) return FILETYPE.SYMBOLIC_LINK;
|
|
@@ -5836,6 +5991,7 @@ function filestatOf(path, s) {
|
|
|
5836
5991
|
filetype: filetypeOf(s),
|
|
5837
5992
|
size: BigInt(s.size),
|
|
5838
5993
|
ino: s.ino !== void 0 ? BigInt(s.ino) : pathInode(path),
|
|
5994
|
+
...s.nlink !== void 0 ? { nlink: BigInt(s.nlink) } : {},
|
|
5839
5995
|
mtimeNs: BigInt(Math.round(s.mtimeMs ?? 0)) * NS_PER_MS
|
|
5840
5996
|
};
|
|
5841
5997
|
}
|
|
@@ -5886,6 +6042,7 @@ var WasiExit, IDS, NS_PER_MS, AT_SYMLINK_NOFOLLOW2, S_IFIFO, DEFAULT_UMASK, MONO
|
|
|
5886
6042
|
var init_wasi_host = __esm({
|
|
5887
6043
|
"src/process/wasi/wasi-host.ts"() {
|
|
5888
6044
|
"use strict";
|
|
6045
|
+
init_physical_path();
|
|
5889
6046
|
init_cred();
|
|
5890
6047
|
init_wasi_abi();
|
|
5891
6048
|
init_wasi_fds();
|
|
@@ -6195,17 +6352,20 @@ var init_wasi_host = __esm({
|
|
|
6195
6352
|
path_remove_directory: (dirfd, p, l) => void o.fs.rmdir(at(dirfd, p, l)),
|
|
6196
6353
|
path_unlink_file: (dirfd, p, l) => {
|
|
6197
6354
|
const path = at(dirfd, p, l);
|
|
6198
|
-
|
|
6199
|
-
|
|
6355
|
+
const st = o.fs.lstat(path);
|
|
6356
|
+
if (st.isDirectory) throw new WasiError("EISDIR");
|
|
6357
|
+
const linked = linkedOf(st);
|
|
6358
|
+
fds.unlinking(path, linked);
|
|
6200
6359
|
o.fs.unlink(path);
|
|
6201
|
-
fds.unlinked(path);
|
|
6360
|
+
fds.unlinked(path, linked);
|
|
6202
6361
|
},
|
|
6203
6362
|
path_rename: (fd, p, l, fd2, p2, l2) => {
|
|
6204
6363
|
const from = at(fd, p, l);
|
|
6205
6364
|
const to = at(fd2, p2, l2);
|
|
6206
6365
|
fds.flushPath(from);
|
|
6366
|
+
const replaced = fds.holdsUnder(to) ? linkedElsewhere(o.fs, to) : void 0;
|
|
6207
6367
|
o.fs.rename(from, to);
|
|
6208
|
-
fds.renamed(from, to);
|
|
6368
|
+
fds.renamed(from, to, replaced);
|
|
6209
6369
|
},
|
|
6210
6370
|
path_symlink: (tp, tl, dirfd, p, l) => void o.fs.symlink(mem.string(tp, tl), at(dirfd, p, l)),
|
|
6211
6371
|
path_readlink: (dirfd, p, l, buf, len, used) => {
|
|
@@ -6214,7 +6374,17 @@ var init_wasi_host = __esm({
|
|
|
6214
6374
|
mem.bytes(buf, n).set(target.subarray(0, n));
|
|
6215
6375
|
mem.view().setUint32(used, n, true);
|
|
6216
6376
|
},
|
|
6217
|
-
path_link: () =>
|
|
6377
|
+
path_link: (fd, lookup, p, l, fd2, p2, l2) => {
|
|
6378
|
+
const from = at(fd, p, l);
|
|
6379
|
+
const to = at(fd2, p2, l2);
|
|
6380
|
+
const follow2 = (lookup & LOOKUP_SYMLINK_FOLLOW) !== 0;
|
|
6381
|
+
const source = follow2 ? physicalPath(o.fs, from) : from;
|
|
6382
|
+
fds.flushPath(from);
|
|
6383
|
+
if (source !== from) fds.flushPath(source);
|
|
6384
|
+
o.fs.link(from, to, follow2);
|
|
6385
|
+
fds.linked(from, to);
|
|
6386
|
+
if (source !== from) fds.linked(source, to);
|
|
6387
|
+
}
|
|
6218
6388
|
};
|
|
6219
6389
|
}
|
|
6220
6390
|
socket(fd) {
|
|
@@ -6418,7 +6588,7 @@ var init_wasi_host = __esm({
|
|
|
6418
6588
|
v.setBigUint64(ptr, 1n, true);
|
|
6419
6589
|
v.setBigUint64(ptr + 8, f.ino, true);
|
|
6420
6590
|
v.setUint8(ptr + 16, f.filetype);
|
|
6421
|
-
v.setBigUint64(ptr + 24, 1n, true);
|
|
6591
|
+
v.setBigUint64(ptr + 24, f.nlink ?? 1n, true);
|
|
6422
6592
|
v.setBigUint64(ptr + 32, f.size, true);
|
|
6423
6593
|
v.setBigUint64(ptr + 40, f.mtimeNs, true);
|
|
6424
6594
|
v.setBigUint64(ptr + 48, f.mtimeNs, true);
|
|
@@ -7222,6 +7392,13 @@ function procfsBridge(fs, tree) {
|
|
|
7222
7392
|
() => fs.rename(from, to)
|
|
7223
7393
|
),
|
|
7224
7394
|
symlink: (target, link) => readOnly([[link, false]], () => fs.symlink(target, link)),
|
|
7395
|
+
link: (from, to, follow2) => readOnly(
|
|
7396
|
+
[
|
|
7397
|
+
[from, follow2 === true],
|
|
7398
|
+
[to, false]
|
|
7399
|
+
],
|
|
7400
|
+
() => fs.link(from, to, follow2)
|
|
7401
|
+
),
|
|
7225
7402
|
hold: (p, held, open, handle) => {
|
|
7226
7403
|
if (handle !== void 0 && snapshots.delete(handle)) return void 0;
|
|
7227
7404
|
if (!held) return fs.hold?.(p, held, open, handle);
|
|
@@ -11019,6 +11196,7 @@ function syncPathOps(kernel, resolve, statOf, open) {
|
|
|
11019
11196
|
rm: (path) => void kernel.call({ op: "rm", path: resolve(path) }),
|
|
11020
11197
|
unlink: (path) => void kernel.call({ op: "unlink", path: resolve(path) }),
|
|
11021
11198
|
rename: (from, to) => void kernel.call({ op: "rename", path: resolve(from), arg2: resolve(to) }),
|
|
11199
|
+
link: (from, to) => void kernel.call({ op: "link", path: resolve(from), arg2: resolve(to) }),
|
|
11022
11200
|
symlink: (target, path) => void kernel.call({ op: "symlink", path: resolve(path), arg2: target }),
|
|
11023
11201
|
readlink: (path) => String(kernel.json({ op: "readlink", path: resolve(path) })),
|
|
11024
11202
|
readFile(path) {
|
|
@@ -11615,6 +11793,7 @@ function pathOps(kernel, resolve, statOf, open) {
|
|
|
11615
11793
|
rm: async (path) => void await kernel.call({ op: "rm", path: resolve(path) }),
|
|
11616
11794
|
unlink: async (path) => void await kernel.call({ op: "unlink", path: resolve(path) }),
|
|
11617
11795
|
rename: async (from, to) => void await kernel.call({ op: "rename", path: resolve(from), arg2: resolve(to) }),
|
|
11796
|
+
link: async (from, to) => void await kernel.call({ op: "link", path: resolve(from), arg2: resolve(to) }),
|
|
11618
11797
|
symlink: async (target, path) => void await kernel.call({ op: "symlink", path: resolve(path), arg2: target }),
|
|
11619
11798
|
readlink: async (path) => String(await kernel.json({ op: "readlink", path: resolve(path) })),
|
|
11620
11799
|
async readFile(path) {
|