@ai-ecoverse/slicc-kernel 1.91.0 → 1.93.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 +18 -12
- package/dist/driver-worker.js +9 -7
- package/dist/driver-worker.js.map +2 -2
- package/dist/index.js +40 -7
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +851 -199
- package/dist/kernel-worker.js.map +4 -4
- package/dist/meta.js.map +2 -2
- package/dist/node-driver-worker.js +150 -11
- package/dist/node-driver-worker.js.map +4 -4
- package/dist/node-process-worker.js +912 -238
- package/dist/node-process-worker.js.map +4 -4
- package/dist/node.js +939 -208
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +2168 -1506
- package/dist/process-worker.js.map +4 -4
- package/package.json +6 -6
package/dist/process-worker.js
CHANGED
|
@@ -44,17 +44,20 @@ function hide(target, names) {
|
|
|
44
44
|
}
|
|
45
45
|
function vacate(target, names) {
|
|
46
46
|
for (const name2 of names) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
const holders = chain(target);
|
|
48
|
+
for (const holder of holders) {
|
|
49
|
+
if (Object.getOwnPropertyDescriptor(holder, name2)?.configurable) {
|
|
50
|
+
Reflect.deleteProperty(holder, name2);
|
|
51
|
+
}
|
|
50
52
|
}
|
|
51
|
-
|
|
53
|
+
const kept = holders.slice(1).some((holder) => Object.hasOwn(holder, name2));
|
|
54
|
+
const opened2 = Reflect.defineProperty(target, name2, {
|
|
52
55
|
value: void 0,
|
|
53
56
|
writable: true,
|
|
54
57
|
enumerable: false,
|
|
55
58
|
configurable: true
|
|
56
59
|
});
|
|
57
|
-
if (Reflect.get(target, name2) !== void 0) {
|
|
60
|
+
if (kept || !opened2 || Reflect.get(target, name2) !== void 0) {
|
|
58
61
|
throw new Error(`slicc-kernel: cannot withhold ${name2} from a JS program`);
|
|
59
62
|
}
|
|
60
63
|
}
|
|
@@ -80,7 +83,6 @@ var init_lockdown = __esm({
|
|
|
80
83
|
"cookieStore",
|
|
81
84
|
"Worker",
|
|
82
85
|
"SharedWorker",
|
|
83
|
-
"BroadcastChannel",
|
|
84
86
|
"postMessage",
|
|
85
87
|
"close",
|
|
86
88
|
"webkitRequestFileSystem",
|
|
@@ -97,11 +99,18 @@ var init_lockdown = __esm({
|
|
|
97
99
|
"hid",
|
|
98
100
|
"serial"
|
|
99
101
|
];
|
|
100
|
-
OPEN_SLOTS = ["fetch", "WebSocket"];
|
|
102
|
+
OPEN_SLOTS = ["fetch", "WebSocket", "BroadcastChannel"];
|
|
101
103
|
}
|
|
102
104
|
});
|
|
103
105
|
|
|
104
106
|
// src/realm/sync-sab-wire.ts
|
|
107
|
+
function loadBlocked(header) {
|
|
108
|
+
return [Atomics.load(header, SAB_I_BLOCKED), Atomics.load(header, SAB_I_BLOCKED_HI)];
|
|
109
|
+
}
|
|
110
|
+
function storeBlocked(header, [low, high]) {
|
|
111
|
+
Atomics.store(header, SAB_I_BLOCKED_HI, high);
|
|
112
|
+
Atomics.store(header, SAB_I_BLOCKED, low);
|
|
113
|
+
}
|
|
105
114
|
function loadU53(header, lo, hi) {
|
|
106
115
|
return (Atomics.load(header, lo) >>> 0) + Atomics.load(header, hi) * U32;
|
|
107
116
|
}
|
|
@@ -144,7 +153,7 @@ function sabViews(sab) {
|
|
|
144
153
|
window: new Uint8Array(sab, SAB_HEADER_BYTES)
|
|
145
154
|
};
|
|
146
155
|
}
|
|
147
|
-
var SAB_HEADER_I32, SAB_CLOCK_OFFSET, SAB_CLOCK_I64, SAB_HEADER_BYTES, SAB_I_STATE, SAB_I_SEQ, SAB_I_STATUS, SAB_I_TOTAL, SAB_I_CHUNK, SAB_I_OFFSET, SAB_I_REQ, SAB_I_PUB, SAB_I_SIGNALS, SAB_I_TIMERS, SAB_I_MEMORY, SAB_I_TOTAL_HI, SAB_I_OFFSET_HI, SAB_I_KILLED, SAB_I_ASYNC, SAB_I_STOP, SAB_I_BLOCKED, U32, SAB_STATE_IDLE, SAB_STATE_PENDING, SAB_STATE_READY, SAB_STATUS_BYTES, SAB_STATUS_JSON, SAB_STATUS_VOID, SAB_STATUS_ERRNO, SAB_DEFAULT_WINDOW_BYTES, SAB_MIN_BYTES, SYNC_SAB_REQ_MSG, SYNC_SAB_NEXT_MSG, encoder, decoder;
|
|
156
|
+
var SAB_HEADER_I32, SAB_CLOCK_OFFSET, SAB_CLOCK_I64, SAB_HEADER_BYTES, SAB_I_STATE, SAB_I_SEQ, SAB_I_STATUS, SAB_I_TOTAL, SAB_I_CHUNK, SAB_I_OFFSET, SAB_I_REQ, SAB_I_PUB, SAB_I_SIGNALS, SAB_I_TIMERS, SAB_I_MEMORY, SAB_I_TOTAL_HI, SAB_I_OFFSET_HI, SAB_I_KILLED, SAB_I_ASYNC, SAB_I_STOP, SAB_I_BLOCKED, SAB_I_BLOCKED_HI, anyBlocked, U32, SAB_STATE_IDLE, SAB_STATE_PENDING, SAB_STATE_READY, SAB_STATUS_BYTES, SAB_STATUS_JSON, SAB_STATUS_VOID, SAB_STATUS_ERRNO, SAB_DEFAULT_WINDOW_BYTES, SAB_MIN_BYTES, SYNC_SAB_REQ_MSG, SYNC_SAB_NEXT_MSG, encoder, decoder;
|
|
148
157
|
var init_sync_sab_wire = __esm({
|
|
149
158
|
"src/realm/sync-sab-wire.ts"() {
|
|
150
159
|
"use strict";
|
|
@@ -169,6 +178,8 @@ var init_sync_sab_wire = __esm({
|
|
|
169
178
|
SAB_I_ASYNC = 14;
|
|
170
179
|
SAB_I_STOP = 15;
|
|
171
180
|
SAB_I_BLOCKED = 16;
|
|
181
|
+
SAB_I_BLOCKED_HI = 17;
|
|
182
|
+
anyBlocked = (mask) => mask !== void 0 && (mask[0] !== 0 || mask[1] !== 0);
|
|
172
183
|
U32 = 2 ** 32;
|
|
173
184
|
SAB_STATE_IDLE = 0;
|
|
174
185
|
SAB_STATE_PENDING = 1;
|
|
@@ -363,6 +374,73 @@ var init_signals = __esm({
|
|
|
363
374
|
}
|
|
364
375
|
});
|
|
365
376
|
|
|
377
|
+
// src/fs/types.ts
|
|
378
|
+
function normalizePath(path) {
|
|
379
|
+
const parts = [];
|
|
380
|
+
for (const part of path.split("/")) {
|
|
381
|
+
if (part === "" || part === ".") continue;
|
|
382
|
+
if (part === "..") parts.pop();
|
|
383
|
+
else parts.push(part);
|
|
384
|
+
}
|
|
385
|
+
return `/${parts.join("/")}`;
|
|
386
|
+
}
|
|
387
|
+
function inodeOf(path) {
|
|
388
|
+
let h1 = 3735928559;
|
|
389
|
+
let h2 = 1103547991;
|
|
390
|
+
for (let i = 0; i < path.length; i++) {
|
|
391
|
+
const c = path.charCodeAt(i);
|
|
392
|
+
h1 = Math.imul(h1 ^ c, 2654435761);
|
|
393
|
+
h2 = Math.imul(h2 ^ c, 1597334677);
|
|
394
|
+
}
|
|
395
|
+
h1 = Math.imul(h1 ^ h1 >>> 16, 2246822507) ^ Math.imul(h2 ^ h2 >>> 13, 3266489909);
|
|
396
|
+
h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507) ^ Math.imul(h1 ^ h1 >>> 13, 3266489909);
|
|
397
|
+
return 4294967296 * (2097151 & h2) + (h1 >>> 0) || 1;
|
|
398
|
+
}
|
|
399
|
+
var init_types = __esm({
|
|
400
|
+
"src/fs/types.ts"() {
|
|
401
|
+
"use strict";
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
// src/fs/owners.ts
|
|
406
|
+
function inGroup(cred, gid) {
|
|
407
|
+
return cred.egid === gid || cred.groups.includes(gid);
|
|
408
|
+
}
|
|
409
|
+
var ROOT_OWNER;
|
|
410
|
+
var init_owners = __esm({
|
|
411
|
+
"src/fs/owners.ts"() {
|
|
412
|
+
"use strict";
|
|
413
|
+
init_types();
|
|
414
|
+
ROOT_OWNER = Object.freeze({ uid: 0, gid: 0 });
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
// src/fs/walk.ts
|
|
419
|
+
var init_walk = __esm({
|
|
420
|
+
"src/fs/walk.ts"() {
|
|
421
|
+
"use strict";
|
|
422
|
+
init_types();
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
// src/fs/access.ts
|
|
427
|
+
function permits(cred, perm, want, directory = true) {
|
|
428
|
+
const mode = perm.mode ?? (directory ? 493 : 420);
|
|
429
|
+
if (cred.euid === 0) return (want & X_OK) === 0 || directory || (mode & 73) !== 0;
|
|
430
|
+
const shift = cred.euid === perm.uid ? 6 : inGroup(cred, perm.gid) ? 3 : 0;
|
|
431
|
+
return (mode >> shift & want) === want;
|
|
432
|
+
}
|
|
433
|
+
var X_OK;
|
|
434
|
+
var init_access = __esm({
|
|
435
|
+
"src/fs/access.ts"() {
|
|
436
|
+
"use strict";
|
|
437
|
+
init_owners();
|
|
438
|
+
init_types();
|
|
439
|
+
init_walk();
|
|
440
|
+
X_OK = 1;
|
|
441
|
+
}
|
|
442
|
+
});
|
|
443
|
+
|
|
366
444
|
// src/fs/pages.ts
|
|
367
445
|
var PAGE, READAHEAD, CLEAN_LIMIT, WRITEBACK, RUN, Pages;
|
|
368
446
|
var init_pages = __esm({
|
|
@@ -617,34 +695,6 @@ var init_ranged = __esm({
|
|
|
617
695
|
}
|
|
618
696
|
});
|
|
619
697
|
|
|
620
|
-
// src/fs/types.ts
|
|
621
|
-
function normalizePath(path) {
|
|
622
|
-
const parts = [];
|
|
623
|
-
for (const part of path.split("/")) {
|
|
624
|
-
if (part === "" || part === ".") continue;
|
|
625
|
-
if (part === "..") parts.pop();
|
|
626
|
-
else parts.push(part);
|
|
627
|
-
}
|
|
628
|
-
return `/${parts.join("/")}`;
|
|
629
|
-
}
|
|
630
|
-
function inodeOf(path) {
|
|
631
|
-
let h1 = 3735928559;
|
|
632
|
-
let h2 = 1103547991;
|
|
633
|
-
for (let i = 0; i < path.length; i++) {
|
|
634
|
-
const c = path.charCodeAt(i);
|
|
635
|
-
h1 = Math.imul(h1 ^ c, 2654435761);
|
|
636
|
-
h2 = Math.imul(h2 ^ c, 1597334677);
|
|
637
|
-
}
|
|
638
|
-
h1 = Math.imul(h1 ^ h1 >>> 16, 2246822507) ^ Math.imul(h2 ^ h2 >>> 13, 3266489909);
|
|
639
|
-
h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507) ^ Math.imul(h1 ^ h1 >>> 13, 3266489909);
|
|
640
|
-
return 4294967296 * (2097151 & h2) + (h1 >>> 0) || 1;
|
|
641
|
-
}
|
|
642
|
-
var init_types = __esm({
|
|
643
|
-
"src/fs/types.ts"() {
|
|
644
|
-
"use strict";
|
|
645
|
-
}
|
|
646
|
-
});
|
|
647
|
-
|
|
648
698
|
// src/process/wasi/wasi-abi.ts
|
|
649
699
|
function wasiErrnoOf(code2) {
|
|
650
700
|
if (!code2) return E.IO;
|
|
@@ -1069,12 +1119,21 @@ function createSyncFsSabBridge(transport, opts = {}) {
|
|
|
1069
1119
|
lutimes: (path, atimeMs, mtimeMs, now) => {
|
|
1070
1120
|
run({ op: "lutimes", path, atimeMs, mtimeMs, ...now ? { now } : {} }, path);
|
|
1071
1121
|
},
|
|
1072
|
-
create: (path, mode) => {
|
|
1073
|
-
|
|
1122
|
+
create: (path, mode, opening2) => {
|
|
1123
|
+
const flags = { ...mode !== void 0 ? { mode } : {}, ...opening2 ? { opening: opening2 } : {} };
|
|
1124
|
+
run({ op: "create", path, ...flags }, path);
|
|
1074
1125
|
},
|
|
1075
|
-
chown: (path, uid, gid, follow2) => {
|
|
1126
|
+
chown: (path, uid, gid, follow2, handle) => {
|
|
1076
1127
|
const ids = { ...uid !== void 0 ? { uid } : {}, ...gid !== void 0 ? { gid } : {} };
|
|
1077
|
-
changing(
|
|
1128
|
+
changing(
|
|
1129
|
+
{
|
|
1130
|
+
op: follow2 ? "chown" : "lchown",
|
|
1131
|
+
path,
|
|
1132
|
+
...ids,
|
|
1133
|
+
...handle !== void 0 ? { handle } : {}
|
|
1134
|
+
},
|
|
1135
|
+
path
|
|
1136
|
+
);
|
|
1078
1137
|
},
|
|
1079
1138
|
...opts.owners ? { owners: true } : {},
|
|
1080
1139
|
...opts.links ? { links: true } : {},
|
|
@@ -1135,6 +1194,7 @@ function toMs(v) {
|
|
|
1135
1194
|
return v instanceof Date ? v.getTime() : v;
|
|
1136
1195
|
}
|
|
1137
1196
|
function wantOf(flags) {
|
|
1197
|
+
if (flags & O_PATH) return 0;
|
|
1138
1198
|
const mode = flags & O_ACCMODE;
|
|
1139
1199
|
const read2 = mode === 1 ? 0 : HOLD_READ;
|
|
1140
1200
|
const write2 = mode !== 0 || (flags & O_TRUNC) !== 0 ? HOLD_WRITE : 0;
|
|
@@ -1150,15 +1210,36 @@ function refusal(err) {
|
|
|
1150
1210
|
function cachedStat(s, dir) {
|
|
1151
1211
|
return s.stat !== void 0 && (!dir || s.statAt === syncCallCount());
|
|
1152
1212
|
}
|
|
1213
|
+
function searchParents(Fs, node, bridge, call2) {
|
|
1214
|
+
const cred = Fs.sliccCred;
|
|
1215
|
+
if (!cred) return;
|
|
1216
|
+
let cur = node.parent;
|
|
1217
|
+
while (cur) {
|
|
1218
|
+
const st = cur.live.stat;
|
|
1219
|
+
if (st && st.uid !== void 0 && st.mode !== void 0) {
|
|
1220
|
+
const perm = { uid: st.uid, gid: st.gid ?? 0, mode: st.mode & 4095 };
|
|
1221
|
+
if (!permits(cred, perm, X_OK, true)) {
|
|
1222
|
+
call2(() => bridge.access?.(liveNodePath(cur), X_OK, "eaccess"));
|
|
1223
|
+
cur.live.stat = void 0;
|
|
1224
|
+
return;
|
|
1225
|
+
}
|
|
1226
|
+
} else {
|
|
1227
|
+
call2(() => bridge.access?.(liveNodePath(cur), X_OK, "eaccess"));
|
|
1228
|
+
return;
|
|
1229
|
+
}
|
|
1230
|
+
if (cur === cur.parent) break;
|
|
1231
|
+
cur = cur.parent;
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1153
1234
|
function linkedStates(bridgeOf) {
|
|
1154
1235
|
const opens = /* @__PURE__ */ new Map();
|
|
1155
1236
|
const byId = /* @__PURE__ */ new Map();
|
|
1156
|
-
const
|
|
1237
|
+
const idOf4 = (st) => st?.ino === void 0 || (st.nlink ?? 1) < 2 ? void 0 : `${st.dev}:${st.ino}`;
|
|
1157
1238
|
function know(s, id) {
|
|
1158
1239
|
s.id = id;
|
|
1159
1240
|
if (!byId.has(id)) byId.set(id, s);
|
|
1160
1241
|
}
|
|
1161
|
-
function
|
|
1242
|
+
function opening2(node, on) {
|
|
1162
1243
|
const s = node.live;
|
|
1163
1244
|
if (!on) {
|
|
1164
1245
|
opens.delete(s);
|
|
@@ -1167,14 +1248,14 @@ function linkedStates(bridgeOf) {
|
|
|
1167
1248
|
return;
|
|
1168
1249
|
}
|
|
1169
1250
|
opens.set(s, node);
|
|
1170
|
-
const id =
|
|
1251
|
+
const id = idOf4(s.stat);
|
|
1171
1252
|
if (id !== void 0) know(s, id);
|
|
1172
1253
|
}
|
|
1173
1254
|
function sharedWith(node) {
|
|
1174
1255
|
const st = node.live.stat;
|
|
1175
1256
|
if (st?.ino === void 0) return void 0;
|
|
1176
1257
|
const id = `${st.dev}:${st.ino}`;
|
|
1177
|
-
if (!byId.has(id) &&
|
|
1258
|
+
if (!byId.has(id) && idOf4(st) !== void 0) {
|
|
1178
1259
|
for (const [s2, other] of opens) {
|
|
1179
1260
|
if (s2.id !== void 0 || s2.orphan) continue;
|
|
1180
1261
|
let st2;
|
|
@@ -1182,7 +1263,7 @@ function linkedStates(bridgeOf) {
|
|
|
1182
1263
|
st2 = bridgeOf(other).lstat(liveNodePath(other));
|
|
1183
1264
|
} catch {
|
|
1184
1265
|
}
|
|
1185
|
-
const known =
|
|
1266
|
+
const known = idOf4(st2);
|
|
1186
1267
|
if (known !== void 0) know(s2, known);
|
|
1187
1268
|
}
|
|
1188
1269
|
}
|
|
@@ -1190,7 +1271,7 @@ function linkedStates(bridgeOf) {
|
|
|
1190
1271
|
return s && s !== node.live && !stale(s) ? s : void 0;
|
|
1191
1272
|
}
|
|
1192
1273
|
const holder = (node) => opens.get(node.live) ?? node;
|
|
1193
|
-
return { opening, sharedWith, know, idOf:
|
|
1274
|
+
return { opening: opening2, sharedWith, know, idOf: idOf4, holder };
|
|
1194
1275
|
}
|
|
1195
1276
|
function createHelpers(Fs, ops) {
|
|
1196
1277
|
const bridgeOf = (node) => node.mount.opts.bridge;
|
|
@@ -1412,7 +1493,9 @@ function createNodeOps(h) {
|
|
|
1412
1493
|
const owned = bridgeOf(node).owners === true;
|
|
1413
1494
|
if (owned && Fs.isLink(node.mode) && statOf(node).uid === void 0)
|
|
1414
1495
|
node.live.stat = void 0;
|
|
1496
|
+
const cached = owned && cachedStat(node.live, Fs.isDir(node.mode));
|
|
1415
1497
|
const st = statOf(node);
|
|
1498
|
+
if (cached) searchParents(Fs, node, bridgeOf(node), call2);
|
|
1416
1499
|
const s = node.live;
|
|
1417
1500
|
const size = Fs.isDir(node.mode) ? 4096 : s.ranged?.size() ?? (s.loaded ? s.len : st.size);
|
|
1418
1501
|
const mtime = new Date(st.mtimeMs ?? 0);
|
|
@@ -1475,7 +1558,7 @@ function createNodeOps(h) {
|
|
|
1475
1558
|
if (masked !== DEFAULT_DIR_PERM) metadataCall(() => bridge.chmod(path, masked));
|
|
1476
1559
|
} else if (Fs.isFile(mode)) {
|
|
1477
1560
|
call2(
|
|
1478
|
-
() => bridge.create ? bridge.create(path, perm) : bridge.writeFile(path, new Uint8Array(0))
|
|
1561
|
+
() => bridge.create ? bridge.create(path, perm, opening.get(h.Fs) > 0) : bridge.writeFile(path, new Uint8Array(0))
|
|
1479
1562
|
);
|
|
1480
1563
|
} else {
|
|
1481
1564
|
throw new Fs.ErrnoError(wasiErrno("EPERM"));
|
|
@@ -1721,10 +1804,24 @@ function createStreamOps(h) {
|
|
|
1721
1804
|
}
|
|
1722
1805
|
};
|
|
1723
1806
|
}
|
|
1807
|
+
function countOpens(Fs) {
|
|
1808
|
+
const { open } = Fs;
|
|
1809
|
+
if (typeof open !== "function" || opening.has(Fs)) return;
|
|
1810
|
+
opening.set(Fs, 0);
|
|
1811
|
+
Fs.open = function(...args) {
|
|
1812
|
+
opening.set(Fs, (opening.get(Fs) ?? 0) + 1);
|
|
1813
|
+
try {
|
|
1814
|
+
return open.apply(this, args);
|
|
1815
|
+
} finally {
|
|
1816
|
+
opening.set(Fs, (opening.get(Fs) ?? 1) - 1);
|
|
1817
|
+
}
|
|
1818
|
+
};
|
|
1819
|
+
}
|
|
1724
1820
|
function createLiveVfsPlugin(Fs) {
|
|
1725
1821
|
const mounts = /* @__PURE__ */ new Set();
|
|
1726
1822
|
const ops = {};
|
|
1727
1823
|
const h = createHelpers(Fs, ops);
|
|
1824
|
+
countOpens(Fs);
|
|
1728
1825
|
const nodeOps = createNodeOps(h);
|
|
1729
1826
|
const streamOps = createStreamOps(h);
|
|
1730
1827
|
ops.node = nodeOps;
|
|
@@ -1857,12 +1954,12 @@ function liveRoot(Fs, bridge) {
|
|
|
1857
1954
|
};
|
|
1858
1955
|
}
|
|
1859
1956
|
function crosses(Fs, from, to) {
|
|
1860
|
-
const
|
|
1957
|
+
const parentOf2 = (path) => Fs.lookupPath?.(path, { parent: true }).node;
|
|
1861
1958
|
const name2 = from.replace(/\/+$/, "").split("/").pop() ?? "";
|
|
1862
1959
|
try {
|
|
1863
|
-
const fromDir =
|
|
1960
|
+
const fromDir = parentOf2(from);
|
|
1864
1961
|
const node = fromDir && Fs.lookupNode?.(fromDir, name2);
|
|
1865
|
-
const dir =
|
|
1962
|
+
const dir = parentOf2(to);
|
|
1866
1963
|
return !!node && !!dir && !!node.live !== !!dir.live;
|
|
1867
1964
|
} catch {
|
|
1868
1965
|
return false;
|
|
@@ -1926,6 +2023,25 @@ function guardRenames(Fs) {
|
|
|
1926
2023
|
function idOf(value2) {
|
|
1927
2024
|
return value2 === -1 || value2 === 4294967295 ? void 0 : value2 >>> 0;
|
|
1928
2025
|
}
|
|
2026
|
+
function chownHeld(Fs, node, s, uid, gid) {
|
|
2027
|
+
const bridge = node.mount.opts.bridge;
|
|
2028
|
+
const handle = s.handle;
|
|
2029
|
+
try {
|
|
2030
|
+
bridge.chown?.(liveNodePath(node), idOf(uid), idOf(gid), false, handle);
|
|
2031
|
+
} catch (err) {
|
|
2032
|
+
throw toErrno(Fs, err);
|
|
2033
|
+
}
|
|
2034
|
+
if (node.parent?.live) node.parent.live.listed = void 0;
|
|
2035
|
+
if (!s.orphan) {
|
|
2036
|
+
s.stat = void 0;
|
|
2037
|
+
return;
|
|
2038
|
+
}
|
|
2039
|
+
try {
|
|
2040
|
+
const st = bridge.keptStat?.(handle);
|
|
2041
|
+
if (st && s.stat) s.stat = { ...s.stat, uid: st.uid, gid: st.gid, mode: st.mode };
|
|
2042
|
+
} catch {
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
1929
2045
|
function useLiveChown(Fs) {
|
|
1930
2046
|
const chown = Fs.chown?.bind(Fs);
|
|
1931
2047
|
if (!chown) return;
|
|
@@ -1944,8 +2060,10 @@ function useLiveChown(Fs) {
|
|
|
1944
2060
|
if (!Fs.fchown || !getStreamChecked) return;
|
|
1945
2061
|
Fs.fchown = (fd, uid, gid) => {
|
|
1946
2062
|
const stream = getStreamChecked.call(Fs, fd);
|
|
1947
|
-
const
|
|
1948
|
-
const
|
|
2063
|
+
const node = stream.node;
|
|
2064
|
+
const s = node.live;
|
|
2065
|
+
if (s?.handle !== void 0 && (!s.orphan || s.kept)) return chownHeld(Fs, node, s, uid, gid);
|
|
2066
|
+
const target = s !== void 0 || stream.path === void 0 ? stream.node : stream.path;
|
|
1949
2067
|
Fs.chown(target, uid, gid);
|
|
1950
2068
|
};
|
|
1951
2069
|
}
|
|
@@ -2006,10 +2124,11 @@ function readingLinks(Fs) {
|
|
|
2006
2124
|
}
|
|
2007
2125
|
};
|
|
2008
2126
|
}
|
|
2009
|
-
var S_IFDIR, S_IFREG, S_IFLNK, PERM_MASK, DEFAULT_DIR_PERM, UMASK, SEEK_CUR, SEEK_END, EARLY_WHOLE_FILE, O_ACCMODE, O_TRUNC, O_PATH, stale;
|
|
2127
|
+
var S_IFDIR, S_IFREG, S_IFLNK, PERM_MASK, DEFAULT_DIR_PERM, UMASK, SEEK_CUR, SEEK_END, EARLY_WHOLE_FILE, O_ACCMODE, O_TRUNC, O_PATH, stale, opening;
|
|
2010
2128
|
var init_live_vfs_fs = __esm({
|
|
2011
2129
|
"src/realm/live-vfs-fs.ts"() {
|
|
2012
2130
|
"use strict";
|
|
2131
|
+
init_access();
|
|
2013
2132
|
init_ranged();
|
|
2014
2133
|
init_types();
|
|
2015
2134
|
init_wasi_errno();
|
|
@@ -2028,6 +2147,7 @@ var init_live_vfs_fs = __esm({
|
|
|
2028
2147
|
O_TRUNC = 512;
|
|
2029
2148
|
O_PATH = 2097152;
|
|
2030
2149
|
stale = (s) => !!s.orphan && !s.kept;
|
|
2150
|
+
opening = /* @__PURE__ */ new WeakMap();
|
|
2031
2151
|
}
|
|
2032
2152
|
});
|
|
2033
2153
|
|
|
@@ -2051,6 +2171,22 @@ function topLevelDirs(bridge, warn) {
|
|
|
2051
2171
|
}
|
|
2052
2172
|
return dirs;
|
|
2053
2173
|
}
|
|
2174
|
+
function linuxRmdir(Fs) {
|
|
2175
|
+
const raw = Fs;
|
|
2176
|
+
const { mayDelete, lookupNode } = raw;
|
|
2177
|
+
if (!mayDelete || !lookupNode) return;
|
|
2178
|
+
raw.mayDelete = (dir, name2, isdir) => {
|
|
2179
|
+
const code2 = mayDelete.call(raw, dir, name2, isdir);
|
|
2180
|
+
if (code2 !== 10 || !isdir) return code2;
|
|
2181
|
+
try {
|
|
2182
|
+
const node = lookupNode.call(raw, dir, name2);
|
|
2183
|
+
if (node === node.parent) return 10;
|
|
2184
|
+
} catch {
|
|
2185
|
+
return code2;
|
|
2186
|
+
}
|
|
2187
|
+
return 0;
|
|
2188
|
+
};
|
|
2189
|
+
}
|
|
2054
2190
|
function mountVfsIntoEmscripten(Fs, deps) {
|
|
2055
2191
|
const { bridge, warn } = deps;
|
|
2056
2192
|
const dirs = topLevelDirs(bridge, warn);
|
|
@@ -2058,6 +2194,8 @@ function mountVfsIntoEmscripten(Fs, deps) {
|
|
|
2058
2194
|
if (dirs) liveRoot(Fs, bridge);
|
|
2059
2195
|
if (bridge.owners && Fs.lookupPath) useLiveChown(Fs);
|
|
2060
2196
|
if (bridge.links && Fs.lookupPath) readingLinks(Fs);
|
|
2197
|
+
linuxRmdir(Fs);
|
|
2198
|
+
if (deps.cred) Fs.sliccCred = deps.cred;
|
|
2061
2199
|
try {
|
|
2062
2200
|
Fs.chdir(deps.cwd);
|
|
2063
2201
|
} catch (err) {
|
|
@@ -2080,1406 +2218,1533 @@ var init_emscripten_vfs_hook = __esm({
|
|
|
2080
2218
|
}
|
|
2081
2219
|
});
|
|
2082
2220
|
|
|
2083
|
-
// src/
|
|
2084
|
-
function
|
|
2085
|
-
return
|
|
2221
|
+
// src/fs/dev-removal.ts
|
|
2222
|
+
function inDevTree(path) {
|
|
2223
|
+
return path === "/dev" || path.startsWith("/dev/");
|
|
2086
2224
|
}
|
|
2087
|
-
function
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
return
|
|
2091
|
-
dev: 22,
|
|
2092
|
-
ino: n === void 0 ? 2 : 3 + Number(n),
|
|
2093
|
-
mode: n === void 0 ? 8630 : 8592,
|
|
2094
|
-
nlink: 1,
|
|
2095
|
-
uid: 1e3,
|
|
2096
|
-
gid: 1e3,
|
|
2097
|
-
rdev: n === void 0 ? 5 << 8 | 2 : 136 << 8 | Number(n),
|
|
2098
|
-
size: 0,
|
|
2099
|
-
blksize: 4096,
|
|
2100
|
-
blocks: 0,
|
|
2101
|
-
atime: now,
|
|
2102
|
-
mtime: now,
|
|
2103
|
-
ctime: now
|
|
2104
|
-
};
|
|
2225
|
+
function devRemoval(path, cred) {
|
|
2226
|
+
if (!inDevTree(path)) return void 0;
|
|
2227
|
+
if (cred && cred.euid !== 0) return "EACCES";
|
|
2228
|
+
return path === "/dev" ? "EBUSY" : "EPERM";
|
|
2105
2229
|
}
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2230
|
+
var init_dev_removal = __esm({
|
|
2231
|
+
"src/fs/dev-removal.ts"() {
|
|
2232
|
+
"use strict";
|
|
2233
|
+
}
|
|
2234
|
+
});
|
|
2235
|
+
|
|
2236
|
+
// src/process/process-pty.ts
|
|
2237
|
+
function failed(e) {
|
|
2238
|
+
const code2 = e?.code;
|
|
2239
|
+
if (typeof code2 === "string") return -wasiErrno(code2);
|
|
2240
|
+
throw e;
|
|
2241
|
+
}
|
|
2242
|
+
function ptyIoctl(ioctl, deps) {
|
|
2243
|
+
return (fd, op, varargs) => {
|
|
2244
|
+
const request = op >>> 0;
|
|
2245
|
+
if (request !== TIOCGPTN && request !== TIOCSPTLCK && request !== TIOCSCTTY && request !== TIOCSWINSZ && request !== TIOCPKT) {
|
|
2246
|
+
return ioctl(fd, op, varargs);
|
|
2247
|
+
}
|
|
2248
|
+
const stream = deps.fs()?.getStream(fd);
|
|
2249
|
+
const kfd = stream?.sliccKernelFd;
|
|
2250
|
+
if (kfd === void 0) return ioctl(fd, op, varargs);
|
|
2251
|
+
const heap = deps.heap();
|
|
2252
|
+
if (!heap) return -wasiErrno("EFAULT");
|
|
2253
|
+
const argp = (heap[varargs >> 2] ?? 0) >>> 0;
|
|
2254
|
+
try {
|
|
2255
|
+
return answer(request, kfd, argp, heap, deps.kernel);
|
|
2256
|
+
} catch (e) {
|
|
2257
|
+
return failed(e);
|
|
2258
|
+
}
|
|
2122
2259
|
};
|
|
2123
2260
|
}
|
|
2124
|
-
function
|
|
2125
|
-
|
|
2261
|
+
function answer(request, kfd, argp, heap, kernel) {
|
|
2262
|
+
switch (request) {
|
|
2263
|
+
case TIOCGPTN:
|
|
2264
|
+
heap[argp >> 2] = kernel.ptyNumber(kfd);
|
|
2265
|
+
return 0;
|
|
2266
|
+
case TIOCSPTLCK:
|
|
2267
|
+
kernel.ptyLock(kfd, (heap[argp >> 2] ?? 0) !== 0);
|
|
2268
|
+
return 0;
|
|
2269
|
+
case TIOCSCTTY:
|
|
2270
|
+
kernel.setControllingTerminal(kfd);
|
|
2271
|
+
return 0;
|
|
2272
|
+
case TIOCPKT:
|
|
2273
|
+
kernel.setPacketMode(kfd, (heap[argp >> 2] ?? 0) !== 0);
|
|
2274
|
+
return 0;
|
|
2275
|
+
default: {
|
|
2276
|
+
const word = heap[argp >> 2] ?? 0;
|
|
2277
|
+
kernel.setWinsize(kfd, word & 65535, word >>> 16 & 65535);
|
|
2278
|
+
return 0;
|
|
2279
|
+
}
|
|
2280
|
+
}
|
|
2126
2281
|
}
|
|
2127
|
-
var
|
|
2128
|
-
var
|
|
2129
|
-
"src/process/
|
|
2282
|
+
var TIOCGPTN, TIOCSPTLCK, TIOCSCTTY, TIOCSWINSZ, TIOCPKT;
|
|
2283
|
+
var init_process_pty = __esm({
|
|
2284
|
+
"src/process/process-pty.ts"() {
|
|
2130
2285
|
"use strict";
|
|
2131
2286
|
init_wasi_errno();
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2287
|
+
TIOCGPTN = 2147767344;
|
|
2288
|
+
TIOCSPTLCK = 1074025521;
|
|
2289
|
+
TIOCSCTTY = 21518;
|
|
2290
|
+
TIOCSWINSZ = 21524;
|
|
2291
|
+
TIOCPKT = 21536;
|
|
2292
|
+
}
|
|
2293
|
+
});
|
|
2294
|
+
|
|
2295
|
+
// src/process/process-fds.ts
|
|
2296
|
+
function closesOnExec(stream) {
|
|
2297
|
+
return stream.sliccCloexec === true;
|
|
2298
|
+
}
|
|
2299
|
+
function setCloseOnExec(stream, on) {
|
|
2300
|
+
if (on) stream.sliccCloexec = true;
|
|
2301
|
+
else delete stream.sliccCloexec;
|
|
2302
|
+
}
|
|
2303
|
+
function trackCloseOnExec(Fs) {
|
|
2304
|
+
if (tracked.has(Fs)) return;
|
|
2305
|
+
tracked.add(Fs);
|
|
2306
|
+
if (typeof Fs.dupStream === "function") {
|
|
2307
|
+
const dupStream = Fs.dupStream.bind(Fs);
|
|
2308
|
+
Fs.dupStream = (stream, fd) => {
|
|
2309
|
+
const copy2 = dupStream(stream, fd);
|
|
2310
|
+
setCloseOnExec(copy2, false);
|
|
2311
|
+
return copy2;
|
|
2153
2312
|
};
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
constructor(status2) {
|
|
2163
|
-
super(`exit ${status2}`);
|
|
2164
|
-
this.status = status2;
|
|
2165
|
-
}
|
|
2313
|
+
}
|
|
2314
|
+
if (typeof Fs.open === "function") {
|
|
2315
|
+
const open = Fs.open.bind(Fs);
|
|
2316
|
+
Fs.open = (path, flags, mode) => {
|
|
2317
|
+
const cloexec = typeof flags === "number" && (flags & O_CLOEXEC) !== 0;
|
|
2318
|
+
const stream = open(path, cloexec ? flags & ~O_CLOEXEC : flags, mode);
|
|
2319
|
+
setCloseOnExec(stream, cloexec);
|
|
2320
|
+
return stream;
|
|
2166
2321
|
};
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2322
|
+
}
|
|
2323
|
+
}
|
|
2324
|
+
function marker(deps) {
|
|
2325
|
+
return (fd, on) => {
|
|
2326
|
+
const stream = deps.fs()?.getStream(fd);
|
|
2327
|
+
if (stream) setCloseOnExec(stream, on);
|
|
2328
|
+
};
|
|
2329
|
+
}
|
|
2330
|
+
function cloexecFcntl(fcntl, deps) {
|
|
2331
|
+
const mark = marker(deps);
|
|
2332
|
+
return (fd, cmd, varargs) => {
|
|
2333
|
+
if (cmd === F_DUPFD_CLOEXEC) {
|
|
2334
|
+
const copy2 = fcntl(fd, F_DUPFD, varargs);
|
|
2335
|
+
if (copy2 >= 0) mark(copy2, true);
|
|
2336
|
+
return copy2;
|
|
2337
|
+
}
|
|
2338
|
+
if (cmd === F_GETFL) {
|
|
2339
|
+
const flags = fcntl(fd, cmd, varargs);
|
|
2340
|
+
return flags < 0 ? flags : flags & ~O_CLOEXEC;
|
|
2341
|
+
}
|
|
2342
|
+
if (cmd !== F_GETFD && cmd !== F_SETFD) return fcntl(fd, cmd, varargs);
|
|
2343
|
+
const stream = deps.fs()?.getStream(fd);
|
|
2344
|
+
if (!stream) return -wasiErrno("EBADF");
|
|
2345
|
+
if (cmd === F_GETFD) return closesOnExec(stream) ? FD_CLOEXEC : 0;
|
|
2346
|
+
const arg = deps.heap()?.[varargs >> 2];
|
|
2347
|
+
if (arg === void 0) return -wasiErrno("EINVAL");
|
|
2348
|
+
setCloseOnExec(stream, (arg & FD_CLOEXEC) !== 0);
|
|
2349
|
+
return 0;
|
|
2350
|
+
};
|
|
2351
|
+
}
|
|
2352
|
+
function cloexecPipe2(pipe2, deps) {
|
|
2353
|
+
const mark = marker(deps);
|
|
2354
|
+
return (fdPtr, flags) => {
|
|
2355
|
+
const r = pipe2(fdPtr, flags & ~O_CLOEXEC);
|
|
2356
|
+
const heap = deps.heap();
|
|
2357
|
+
if (r === 0 && flags & O_CLOEXEC && heap) {
|
|
2358
|
+
mark(heap[fdPtr >> 2], true);
|
|
2359
|
+
mark(heap[(fdPtr >> 2) + 1], true);
|
|
2360
|
+
}
|
|
2361
|
+
return r;
|
|
2362
|
+
};
|
|
2363
|
+
}
|
|
2364
|
+
function quietTarget(dup3, deps) {
|
|
2365
|
+
return (fd = -1, newfd = -1, flags = 0, ...rest2) => {
|
|
2366
|
+
const Fs = deps.fs();
|
|
2367
|
+
const target = fd === newfd || flags !== 0 ? void 0 : Fs?.getStream(newfd);
|
|
2368
|
+
if (target && Fs?.getStream(fd)) {
|
|
2369
|
+
try {
|
|
2370
|
+
Fs.close?.(target);
|
|
2371
|
+
} catch {
|
|
2172
2372
|
}
|
|
2373
|
+
}
|
|
2374
|
+
return dup3(fd, newfd, flags, ...rest2);
|
|
2375
|
+
};
|
|
2376
|
+
}
|
|
2377
|
+
function cloexecByFlag(syscall, flagArg, deps) {
|
|
2378
|
+
const mark = marker(deps);
|
|
2379
|
+
return (...args) => {
|
|
2380
|
+
const cloexec = ((args[flagArg] ?? 0) & O_CLOEXEC) !== 0;
|
|
2381
|
+
if (cloexec) args[flagArg] = args[flagArg] & ~O_CLOEXEC;
|
|
2382
|
+
const fd = syscall(...args);
|
|
2383
|
+
if (fd >= 0) mark(fd, cloexec);
|
|
2384
|
+
return fd;
|
|
2385
|
+
};
|
|
2386
|
+
}
|
|
2387
|
+
function wrapperFactories(deps) {
|
|
2388
|
+
const { pty, timer } = deps;
|
|
2389
|
+
return {
|
|
2390
|
+
...timer ? { setitimer: (f) => kernelTimer(f, timer) } : {},
|
|
2391
|
+
fcntl: (f) => cloexecFcntl(f, deps),
|
|
2392
|
+
pipe2: (f) => cloexecPipe2(f, deps),
|
|
2393
|
+
dup3: (f) => cloexecByFlag(quietTarget(f, deps), 2, deps),
|
|
2394
|
+
socket: (f) => cloexecByFlag(f, 1, deps),
|
|
2395
|
+
accept4: (f) => cloexecByFlag(f, 3, deps),
|
|
2396
|
+
...pty ? { ioctl: (f) => ptyIoctl(f, { fs: deps.fs, heap: deps.heap, kernel: pty }) } : {}
|
|
2397
|
+
};
|
|
2398
|
+
}
|
|
2399
|
+
function kernelTimer(setitimer, timer) {
|
|
2400
|
+
return (which, ms) => {
|
|
2401
|
+
if (which !== 0) return setitimer(which, ms);
|
|
2402
|
+
timer.arm(ms ?? 0);
|
|
2403
|
+
return 0;
|
|
2404
|
+
};
|
|
2405
|
+
}
|
|
2406
|
+
function syscallOf(glue, name2, value2) {
|
|
2407
|
+
const names = Object.keys(IMPORT_NAMES);
|
|
2408
|
+
const own = names.find((key) => glue[key] !== void 0 && glue[key] === value2);
|
|
2409
|
+
if (own) return own;
|
|
2410
|
+
return typeof value2 === "function" ? names.find((key) => glue[key] !== void 0 && IMPORT_NAMES[key] === name2) : void 0;
|
|
2411
|
+
}
|
|
2412
|
+
function wrapCloexecSyscalls(imports, glue, deps) {
|
|
2413
|
+
if (!glue) return;
|
|
2414
|
+
const factories = wrapperFactories(deps);
|
|
2415
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2416
|
+
for (const namespace of Object.values(imports)) {
|
|
2417
|
+
if (!namespace || typeof namespace !== "object" || seen.has(namespace)) continue;
|
|
2418
|
+
seen.add(namespace);
|
|
2419
|
+
for (const [name2, value2] of Object.entries(namespace)) {
|
|
2420
|
+
const key = syscallOf(glue, name2, value2);
|
|
2421
|
+
const wrap2 = key && factories[key];
|
|
2422
|
+
if (wrap2) namespace[name2] = wrap2(value2);
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
function pathOpensLinks(Fs) {
|
|
2427
|
+
const fs = Fs;
|
|
2428
|
+
const { mayOpen, isLink } = fs;
|
|
2429
|
+
if (!mayOpen || !isLink) return;
|
|
2430
|
+
fs.mayOpen = (node, flags) => flags & O_PATH2 && isLink.call(fs, node.mode) ? 0 : mayOpen.call(fs, node, flags);
|
|
2431
|
+
}
|
|
2432
|
+
function importKey(namespace, name2, glue) {
|
|
2433
|
+
const own = glue?.[name2];
|
|
2434
|
+
if (typeof own === "function") {
|
|
2435
|
+
const found = Object.keys(namespace).find((k) => namespace[k] === own);
|
|
2436
|
+
if (found !== void 0) return found;
|
|
2437
|
+
}
|
|
2438
|
+
const literal = LITERALS[name2];
|
|
2439
|
+
return typeof namespace[literal] === "function" ? literal : void 0;
|
|
2440
|
+
}
|
|
2441
|
+
function wrapImport(imports, name2, glue, wrap2, optional = false) {
|
|
2442
|
+
let wrapped = false;
|
|
2443
|
+
for (const ns of namespaces(imports)) {
|
|
2444
|
+
const key = importKey(ns, name2, glue);
|
|
2445
|
+
if (key === void 0) continue;
|
|
2446
|
+
ns[key] = wrap2(ns[key]);
|
|
2447
|
+
wrapped = true;
|
|
2448
|
+
}
|
|
2449
|
+
if (!wrapped && !optional && typeof glue?.[name2] === "function") {
|
|
2450
|
+
throw new Error(`slicc-kernel cannot find the glue's ${LITERALS[name2]} among its imports`);
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2453
|
+
function kernelUmask(imports, deps) {
|
|
2454
|
+
let umask = deps.initial & 511;
|
|
2455
|
+
const { glue } = deps;
|
|
2456
|
+
wrapImport(imports, "openat", glue, (openat) => (dirfd, path, flags, varargs) => {
|
|
2457
|
+
const memory = deps.memory();
|
|
2458
|
+
if (flags & O_CREAT && varargs && memory) new Int32Array(memory.buffer)[varargs >> 2] &= ~umask;
|
|
2459
|
+
return openat(dirfd, path, flags, varargs);
|
|
2460
|
+
});
|
|
2461
|
+
wrapImport(
|
|
2462
|
+
imports,
|
|
2463
|
+
"mkdirat",
|
|
2464
|
+
glue,
|
|
2465
|
+
(mkdirat) => (dirfd, path, mode) => mkdirat(dirfd, path, mode & ~umask)
|
|
2466
|
+
);
|
|
2467
|
+
wrapImport(
|
|
2468
|
+
imports,
|
|
2469
|
+
"mknodat",
|
|
2470
|
+
glue,
|
|
2471
|
+
(mknodat) => (dirfd, path, mode, dev) => mknodat(dirfd, path, mode & ~umask, dev)
|
|
2472
|
+
);
|
|
2473
|
+
wrapImport(imports, "umask", glue, (own) => {
|
|
2474
|
+
own(umask);
|
|
2475
|
+
return (mask) => {
|
|
2476
|
+
const old = umask;
|
|
2477
|
+
umask = mask & 511;
|
|
2478
|
+
own(umask);
|
|
2479
|
+
deps.set(umask);
|
|
2480
|
+
return old;
|
|
2173
2481
|
};
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2482
|
+
});
|
|
2483
|
+
}
|
|
2484
|
+
function touching(times, memory) {
|
|
2485
|
+
if (times === 0) return true;
|
|
2486
|
+
if (!memory) return false;
|
|
2487
|
+
const heap = new Int32Array(memory.buffer);
|
|
2488
|
+
const nsec = [heap[times + 8 >> 2], heap[times + 24 >> 2]];
|
|
2489
|
+
return nsec.every((n) => n === UTIME_NOW || n === UTIME_OMIT);
|
|
2490
|
+
}
|
|
2491
|
+
function touch(Fs, on, run) {
|
|
2492
|
+
if (!Fs || !on) return run();
|
|
2493
|
+
Fs.sliccTouch = true;
|
|
2494
|
+
try {
|
|
2495
|
+
return run();
|
|
2496
|
+
} finally {
|
|
2497
|
+
Fs.sliccTouch = void 0;
|
|
2498
|
+
}
|
|
2499
|
+
}
|
|
2500
|
+
function noFollowUtimes(imports, fs, glue, memory = () => void 0) {
|
|
2501
|
+
wrapImport(
|
|
2502
|
+
imports,
|
|
2503
|
+
"utimensat",
|
|
2504
|
+
{ utimensat: glue },
|
|
2505
|
+
(utimensat) => (dirfd, path, times, flags) => {
|
|
2506
|
+
const Fs = fs();
|
|
2507
|
+
const on = touching(times, memory());
|
|
2508
|
+
const { utime, lookupPath, ErrnoError } = Fs ?? {};
|
|
2509
|
+
if (!Fs || !(flags & AT_SYMLINK_NOFOLLOW) || !utime || !lookupPath || !ErrnoError) {
|
|
2510
|
+
return touch(Fs, on, () => utimensat(dirfd, path, times, flags));
|
|
2198
2511
|
}
|
|
2199
|
-
|
|
2200
|
-
const
|
|
2201
|
-
if (!
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
const ino = ++this.sockets;
|
|
2209
|
-
const node = fs.createNode(this.socketRoot, `socket:${ino}`, SOCKET_MODE, 0);
|
|
2210
|
-
const now = /* @__PURE__ */ new Date();
|
|
2211
|
-
const stat = { dev: 0, ino, mode: SOCKET_MODE, nlink: 1, uid: 0, gid: 0, rdev: 0, size: 0 };
|
|
2212
|
-
const times = { atime: now, mtime: now, ctime: now, blksize: 4096, blocks: 0 };
|
|
2213
|
-
node.node_ops = { getattr: () => ({ ...stat, ...times }) };
|
|
2214
|
-
return fs.createStream({ node, flags, seekable: false, position: 0, stream_ops: {} });
|
|
2512
|
+
Fs.utime = (at, atime, mtime) => {
|
|
2513
|
+
const { node } = lookupPath.call(Fs, at, { follow: false });
|
|
2514
|
+
if (!node.node_ops.setattr) throw new ErrnoError(EMSCRIPTEN_EPERM);
|
|
2515
|
+
node.node_ops.setattr(node, { atime, mtime });
|
|
2516
|
+
};
|
|
2517
|
+
try {
|
|
2518
|
+
return touch(Fs, on, () => utimensat(dirfd, path, times, flags));
|
|
2519
|
+
} finally {
|
|
2520
|
+
Fs.utime = utime;
|
|
2215
2521
|
}
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
}
|
|
2256
|
-
openNode(stream, path, opener) {
|
|
2257
|
-
let kfd;
|
|
2258
|
-
try {
|
|
2259
|
-
kfd = this.call(() => opener.call(this.sys, stream.flags & 3));
|
|
2260
|
-
} catch (e) {
|
|
2261
|
-
this.Fs.closeStream(stream.fd);
|
|
2262
|
-
throw e;
|
|
2263
|
-
}
|
|
2264
|
-
this.attach(stream, kfd, false);
|
|
2265
|
-
this.nameStream(stream, path);
|
|
2266
|
-
if (path === CLIPBOARD_PATH) this.reportClose(kfd);
|
|
2267
|
-
}
|
|
2268
|
-
reporting = /* @__PURE__ */ new Set();
|
|
2269
|
-
reportClose(kfd) {
|
|
2270
|
-
this.reporting.add(kfd);
|
|
2271
|
-
}
|
|
2272
|
-
quitting = false;
|
|
2273
|
-
atExit = false;
|
|
2274
|
-
failedAtExit = false;
|
|
2275
|
-
committed = /* @__PURE__ */ new Set();
|
|
2276
|
-
exiting() {
|
|
2277
|
-
this.atExit = true;
|
|
2278
|
-
return () => {
|
|
2279
|
-
this.atExit = false;
|
|
2280
|
-
};
|
|
2281
|
-
}
|
|
2282
|
-
commitStdout() {
|
|
2283
|
-
const kfd = this.Fs.getStream(1)?.sliccKernelFd;
|
|
2284
|
-
if (kfd === void 0 || !this.reporting.delete(kfd)) return;
|
|
2285
|
-
this.committed.add(kfd);
|
|
2286
|
-
try {
|
|
2287
|
-
this.sys.close(kfd);
|
|
2288
|
-
} catch (e) {
|
|
2289
|
-
if (e instanceof SyscallError) this.stdoutFailed(e.code);
|
|
2290
|
-
}
|
|
2522
|
+
}
|
|
2523
|
+
);
|
|
2524
|
+
}
|
|
2525
|
+
function errnoOf(err) {
|
|
2526
|
+
const { errno: errno2, code: code2 } = err ?? {};
|
|
2527
|
+
if (typeof errno2 === "number") return errno2;
|
|
2528
|
+
if (typeof code2 === "string") return wasiErrno(code2);
|
|
2529
|
+
throw err;
|
|
2530
|
+
}
|
|
2531
|
+
function persistsItself(stream) {
|
|
2532
|
+
const type = stream.node.mount?.type;
|
|
2533
|
+
return typeof type?.syncfs === "function";
|
|
2534
|
+
}
|
|
2535
|
+
function namespaces(imports) {
|
|
2536
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2537
|
+
for (const namespace of Object.values(imports)) {
|
|
2538
|
+
if (namespace && typeof namespace === "object") seen.add(namespace);
|
|
2539
|
+
}
|
|
2540
|
+
return [...seen];
|
|
2541
|
+
}
|
|
2542
|
+
function keyOf(namespace, name2, glue) {
|
|
2543
|
+
const own = glue?.[name2];
|
|
2544
|
+
const found = typeof own === "function" ? Object.keys(namespace).find((k) => namespace[k] === own) : void 0;
|
|
2545
|
+
return found ?? (typeof namespace[name2] === "function" ? name2 : void 0);
|
|
2546
|
+
}
|
|
2547
|
+
function syncFsync(imports, fs, glue) {
|
|
2548
|
+
for (const namespace of namespaces(imports)) {
|
|
2549
|
+
const key = keyOf(namespace, "fd_sync", glue);
|
|
2550
|
+
const original = key === void 0 ? void 0 : namespace[key];
|
|
2551
|
+
if (key === void 0 || !original?.isAsync) continue;
|
|
2552
|
+
namespace[key] = (fd) => {
|
|
2553
|
+
const stream = fs()?.getStream(fd);
|
|
2554
|
+
if (!stream) return EBADF;
|
|
2555
|
+
if (persistsItself(stream)) return original(fd);
|
|
2556
|
+
try {
|
|
2557
|
+
const result = stream.stream_ops.fsync?.(stream);
|
|
2558
|
+
return typeof result === "number" ? result : 0;
|
|
2559
|
+
} catch (err) {
|
|
2560
|
+
return errnoOf(err);
|
|
2291
2561
|
}
|
|
2292
|
-
|
|
2293
|
-
|
|
2562
|
+
};
|
|
2563
|
+
}
|
|
2564
|
+
}
|
|
2565
|
+
function offsetOf(rest2) {
|
|
2566
|
+
const at = rest2.length >= 3 ? Number(rest2[1]) * 2 ** 32 + (Number(rest2[0]) >>> 0) : Number(BigInt.asIntN(64, BigInt(rest2[0])));
|
|
2567
|
+
return at >= 0 && Number.isSafeInteger(at) ? at : void 0;
|
|
2568
|
+
}
|
|
2569
|
+
function readInto(sys, kfd, target, at) {
|
|
2570
|
+
let done = 0;
|
|
2571
|
+
while (done < target.length) {
|
|
2572
|
+
const got = sys.pread?.(kfd, target.length - done, at + done) ?? new Uint8Array(0);
|
|
2573
|
+
if (got.length === 0) break;
|
|
2574
|
+
target.set(got, done);
|
|
2575
|
+
done += got.length;
|
|
2576
|
+
}
|
|
2577
|
+
return done;
|
|
2578
|
+
}
|
|
2579
|
+
function positioned(original, write2, deps) {
|
|
2580
|
+
return (fd, iov, iovcnt, ...rest2) => {
|
|
2581
|
+
const stream = deps.fs()?.getStream(Number(fd));
|
|
2582
|
+
const memory = deps.memory();
|
|
2583
|
+
const kfd = stream?.sliccKernelFile ? stream.sliccKernelFd : void 0;
|
|
2584
|
+
if (kfd === void 0 || !memory || !(write2 ? deps.sys.pwrite : deps.sys.pread)) {
|
|
2585
|
+
return original(fd, iov, iovcnt, ...rest2);
|
|
2586
|
+
}
|
|
2587
|
+
const at = offsetOf(rest2);
|
|
2588
|
+
if (at === void 0) return wasiErrno("EINVAL");
|
|
2589
|
+
const view = new DataView(memory.buffer);
|
|
2590
|
+
let done = 0;
|
|
2591
|
+
try {
|
|
2592
|
+
for (let i = 0; i < Number(iovcnt); i++) {
|
|
2593
|
+
const ptr = view.getUint32(Number(iov) + i * 8, true);
|
|
2594
|
+
const len = view.getUint32(Number(iov) + i * 8 + 4, true);
|
|
2595
|
+
const part = new Uint8Array(memory.buffer, ptr, len);
|
|
2596
|
+
const moved = write2 ? deps.sys.pwrite?.(kfd, part.slice(), at + done) ?? 0 : readInto(deps.sys, kfd, part, at + done);
|
|
2597
|
+
done += moved;
|
|
2598
|
+
if (moved < len) break;
|
|
2294
2599
|
}
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2600
|
+
} catch (err) {
|
|
2601
|
+
return errnoOf(err);
|
|
2602
|
+
}
|
|
2603
|
+
view.setUint32(Number(rest2[rest2.length - 1]), done, true);
|
|
2604
|
+
return 0;
|
|
2605
|
+
};
|
|
2606
|
+
}
|
|
2607
|
+
function positionalIo(imports, deps) {
|
|
2608
|
+
for (const namespace of namespaces(imports)) {
|
|
2609
|
+
for (const [name2, write2] of [
|
|
2610
|
+
["fd_pread", false],
|
|
2611
|
+
["fd_pwrite", true]
|
|
2612
|
+
]) {
|
|
2613
|
+
const key = keyOf(namespace, name2, deps.glue);
|
|
2614
|
+
if (key !== void 0) {
|
|
2615
|
+
namespace[key] = positioned(namespace[key], write2, deps);
|
|
2304
2616
|
}
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
2620
|
+
function staging(Fs, length) {
|
|
2621
|
+
try {
|
|
2622
|
+
return new Uint8Array(length);
|
|
2623
|
+
} catch {
|
|
2624
|
+
throw new Fs.ErrnoError(wasiErrno("ENOMEM"));
|
|
2625
|
+
}
|
|
2626
|
+
}
|
|
2627
|
+
function useFileMmap(Fs, deps) {
|
|
2628
|
+
const fs = Fs;
|
|
2629
|
+
const mmap = fs.mmap;
|
|
2630
|
+
if (typeof mmap !== "function") return;
|
|
2631
|
+
fs.mmap = (stream, length, position, prot, flags) => {
|
|
2632
|
+
const memalign = deps.memalign();
|
|
2633
|
+
const memory = deps.memory();
|
|
2634
|
+
const shared = (flags & MAP_TYPE) !== MAP_PRIVATE && (prot & PROT_WRITE) !== 0;
|
|
2635
|
+
const kfd = stream.sliccKernelFile ? stream.sliccKernelFd : void 0;
|
|
2636
|
+
if (shared && kfd !== void 0) throw new Fs.ErrnoError(wasiErrno("ENODEV"));
|
|
2637
|
+
if (stream.stream_ops.mmap && kfd === void 0 || !memalign || !memory || length <= 0 || shared || (stream.flags & O_ACCMODE2) === O_WRONLY || !Fs.isFile(stream.node.mode)) {
|
|
2638
|
+
return mmap.call(fs, stream, length, position, prot, flags);
|
|
2639
|
+
}
|
|
2640
|
+
const data = staging(Fs, length);
|
|
2641
|
+
let done = 0;
|
|
2642
|
+
try {
|
|
2643
|
+
if (kfd !== void 0) done = readInto(deps.sys, kfd, data, position);
|
|
2644
|
+
else {
|
|
2645
|
+
for (let got = 1; done < length && got > 0; done += got) {
|
|
2646
|
+
got = Fs.read(stream, data, done, length - done, position + done);
|
|
2314
2647
|
}
|
|
2315
2648
|
}
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
const fs = this.Fs;
|
|
2319
|
-
const { lookupNode, readdir, getPath, mkdev, makedev } = fs;
|
|
2320
|
-
const ttyNames = this.sys.ttyNames?.bind(this.sys);
|
|
2321
|
-
if (!lookupNode || !readdir || !getPath || !mkdev || !makedev || !ttyNames) return;
|
|
2322
|
-
fs.lookupNode = (parent, name2) => {
|
|
2323
|
-
try {
|
|
2324
|
-
return lookupNode.call(fs, parent, name2);
|
|
2325
|
-
} catch (e) {
|
|
2326
|
-
const path = `/dev/${name2}`;
|
|
2327
|
-
if (this.creatingTerminal || !TTY_NAME.test(name2) || getPath.call(fs, parent) !== "/dev")
|
|
2328
|
-
throw e;
|
|
2329
|
-
if (!ttyNames().includes(path)) throw e;
|
|
2330
|
-
this.creatingTerminal = true;
|
|
2331
|
-
try {
|
|
2332
|
-
mkdev.call(fs, path, makedev.call(fs, 6, 0));
|
|
2333
|
-
} finally {
|
|
2334
|
-
this.creatingTerminal = false;
|
|
2335
|
-
}
|
|
2336
|
-
return lookupNode.call(fs, parent, name2);
|
|
2337
|
-
}
|
|
2338
|
-
};
|
|
2339
|
-
fs.readdir = (path) => {
|
|
2340
|
-
const names = readdir.call(fs, path);
|
|
2341
|
-
if (path.replace(/\/+$/, "") !== "/dev") return names;
|
|
2342
|
-
const missing2 = ttyNames().map((tty) => tty.slice("/dev/".length)).filter((name2) => TTY_NAME.test(name2) && !names.includes(name2));
|
|
2343
|
-
return [...names, ...missing2];
|
|
2344
|
-
};
|
|
2345
|
-
}
|
|
2346
|
-
ttyNode(name2) {
|
|
2347
|
-
const { analyzePath, mkdev, makedev } = this.Fs;
|
|
2348
|
-
if (!TTY_PATH.test(name2) || !analyzePath || !mkdev || !makedev) return;
|
|
2349
|
-
if (!analyzePath.call(this.Fs, name2).exists)
|
|
2350
|
-
mkdev.call(this.Fs, name2, makedev.call(this.Fs, 6, 0));
|
|
2351
|
-
}
|
|
2352
|
-
ttyOps(kfd) {
|
|
2353
|
-
return {
|
|
2354
|
-
ops: {
|
|
2355
|
-
ioctl_tcgets: () => this.call(() => this.sys.tcgets?.(kfd)),
|
|
2356
|
-
ioctl_tcsets: (_tty, op, termios) => this.call(() => {
|
|
2357
|
-
this.sys.tcsets?.(kfd, termios, op === TCSETSF);
|
|
2358
|
-
return 0;
|
|
2359
|
-
}),
|
|
2360
|
-
ioctl_tiocgwinsz: () => this.call(() => this.sys.winsize?.(kfd) ?? [24, 80]),
|
|
2361
|
-
fsync: () => {
|
|
2362
|
-
}
|
|
2363
|
-
}
|
|
2364
|
-
};
|
|
2365
|
-
}
|
|
2366
|
-
attachFile(stream, kfd) {
|
|
2367
|
-
this.attach(stream, kfd, false);
|
|
2368
|
-
stream.sliccKernelFile = true;
|
|
2369
|
-
stream.stream_ops = {
|
|
2370
|
-
...stream.stream_ops,
|
|
2371
|
-
llseek: (_s, offset, whence) => this.call(() => this.sys.seek(kfd, offset, whence)),
|
|
2372
|
-
fsync: () => this.call(() => {
|
|
2373
|
-
this.sys.flush(kfd);
|
|
2374
|
-
return 0;
|
|
2375
|
-
})
|
|
2376
|
-
};
|
|
2377
|
-
}
|
|
2378
|
-
sizeFromKernel(stream, kfd) {
|
|
2379
|
-
const { size } = this.sys;
|
|
2380
|
-
if (!size) return;
|
|
2381
|
-
const node = stream.node;
|
|
2382
|
-
this.describe(stream, `${stream.path ?? ""}:${++this.described}`, () => ({
|
|
2383
|
-
...node.node_ops?.getattr?.(node),
|
|
2384
|
-
size: this.call(() => size.call(this.sys, kfd))
|
|
2385
|
-
}));
|
|
2386
|
-
}
|
|
2387
|
-
describe(stream, name2, getattr) {
|
|
2388
|
-
if (this.descriptions.size === 0) this.useDescriptions();
|
|
2389
|
-
this.descriptions.set(name2, getattr);
|
|
2390
|
-
stream.path = name2;
|
|
2391
|
-
stream.stream_ops = { ...stream.stream_ops, getattr };
|
|
2392
|
-
}
|
|
2393
|
-
useDescriptions() {
|
|
2394
|
-
const fs = this.Fs;
|
|
2395
|
-
for (const name2 of ["stat", "lstat"]) {
|
|
2396
|
-
const original = fs[name2];
|
|
2397
|
-
if (typeof original !== "function") continue;
|
|
2398
|
-
fs[name2] = (path, ...rest2) => {
|
|
2399
|
-
const getattr = this.descriptions.get(path);
|
|
2400
|
-
return getattr ? getattr() : original.call(fs, path, ...rest2);
|
|
2401
|
-
};
|
|
2402
|
-
}
|
|
2403
|
-
}
|
|
2404
|
-
useControllingTerminal() {
|
|
2405
|
-
if (typeof this.Fs.open !== "function") return;
|
|
2406
|
-
this.usePtyPaths();
|
|
2407
|
-
this.useTerminalNodes();
|
|
2408
|
-
this.listSealed();
|
|
2409
|
-
const open = this.Fs.open.bind(this.Fs);
|
|
2410
|
-
this.Fs.open = (path, flags, mode) => {
|
|
2411
|
-
const device2 = typeof path === "string" ? this.devicePath(path) : void 0;
|
|
2412
|
-
if (device2 !== void 0 && TTY_PATH.test(device2) && !this.terminalExists(device2)) {
|
|
2413
|
-
throw new this.Fs.ErrnoError(wasiErrno("ENOENT"));
|
|
2414
|
-
}
|
|
2415
|
-
const pty = this.openPty(open, path, flags, mode) ?? this.openSealed(open, path, flags, mode) ?? this.openClipboard(open, path, flags, mode);
|
|
2416
|
-
if (pty) return pty;
|
|
2417
|
-
this.refuseExclusiveLink(path, flags);
|
|
2418
|
-
const stream = this.openRacing(open, path, flags, mode);
|
|
2419
|
-
if (!stream.tty) return stream;
|
|
2420
|
-
if (stream.path === "/dev/tty" && this.sys.openTty) {
|
|
2421
|
-
let kfd;
|
|
2422
|
-
try {
|
|
2423
|
-
kfd = this.call(() => this.sys.openTty?.());
|
|
2424
|
-
} catch (e) {
|
|
2425
|
-
this.Fs.closeStream(stream.fd);
|
|
2426
|
-
throw e;
|
|
2427
|
-
}
|
|
2428
|
-
this.attach(stream, kfd, true);
|
|
2429
|
-
return stream;
|
|
2430
|
-
}
|
|
2431
|
-
let named;
|
|
2432
|
-
try {
|
|
2433
|
-
named = stream.path ? this.openNamedTerminal(stream.path) : void 0;
|
|
2434
|
-
} catch (e) {
|
|
2435
|
-
this.Fs.closeStream(stream.fd);
|
|
2436
|
-
throw e;
|
|
2437
|
-
}
|
|
2438
|
-
if (named !== void 0) {
|
|
2439
|
-
this.attach(stream, named, true);
|
|
2440
|
-
return stream;
|
|
2441
|
-
}
|
|
2442
|
-
const terminal = this.stdioTerminal();
|
|
2443
|
-
if (terminal !== void 0) this.attach(stream, terminal, true);
|
|
2444
|
-
return stream;
|
|
2445
|
-
};
|
|
2446
|
-
}
|
|
2447
|
-
openRacing(open, path, flags, mode) {
|
|
2448
|
-
try {
|
|
2449
|
-
return open(path, flags, mode);
|
|
2450
|
-
} catch (err) {
|
|
2451
|
-
const lost = err.errno === wasiErrno("EEXIST") && !(flags & O_EXCL);
|
|
2452
|
-
if (!lost) throw err;
|
|
2453
|
-
return open(path, flags, mode);
|
|
2454
|
-
}
|
|
2455
|
-
}
|
|
2456
|
-
refuseExclusiveLink(path, flags) {
|
|
2457
|
-
if ((flags & (O_CREAT | O_EXCL)) !== (O_CREAT | O_EXCL)) return;
|
|
2458
|
-
let mode = 0;
|
|
2459
|
-
try {
|
|
2460
|
-
mode = this.Fs.stat?.(path, true)?.mode ?? 0;
|
|
2461
|
-
} catch {
|
|
2462
|
-
}
|
|
2463
|
-
if ((mode & 61440) === 40960) throw new this.Fs.ErrnoError(wasiErrno("EEXIST"));
|
|
2464
|
-
}
|
|
2465
|
-
openPty(open, path, flags, mode) {
|
|
2466
|
-
const pts = /^\/dev\/pts\/(\d+)$/.exec(path);
|
|
2467
|
-
if (path !== "/dev/ptmx" && !pts) return void 0;
|
|
2468
|
-
const { openPty, openPts } = this.sys;
|
|
2469
|
-
if (!openPty || !openPts) return void 0;
|
|
2470
|
-
const kfd = this.call(
|
|
2471
|
-
() => pts ? openPts(Number(pts[1]), (flags & O_NOCTTY) !== 0) : openPty()
|
|
2472
|
-
);
|
|
2473
|
-
return this.vessel(open, kfd, { path, flags, mode }, true);
|
|
2474
|
-
}
|
|
2475
|
-
openSealed(open, path, flags, mode) {
|
|
2476
|
-
const { openSealed } = this.sys;
|
|
2477
|
-
if (path !== SEALED_PATH || !openSealed) return void 0;
|
|
2478
|
-
const kfd = this.call(() => openSealed.call(this.sys, flags & 3));
|
|
2479
|
-
return this.vessel(open, kfd, { path, flags, mode }, false);
|
|
2480
|
-
}
|
|
2481
|
-
openClipboard(open, path, flags, mode) {
|
|
2482
|
-
const { openClipboard } = this.sys;
|
|
2483
|
-
if (path !== CLIPBOARD_PATH || !openClipboard) return void 0;
|
|
2484
|
-
const kfd = this.call(() => openClipboard.call(this.sys, flags & 3));
|
|
2485
|
-
const stream = this.vessel(open, kfd, { path, flags, mode }, false);
|
|
2486
|
-
this.reportClose(kfd);
|
|
2487
|
-
return stream;
|
|
2488
|
-
}
|
|
2489
|
-
vessel(open, kfd, at, terminal) {
|
|
2490
|
-
let stream;
|
|
2491
|
-
try {
|
|
2492
|
-
stream = open("/dev/null", at.flags & ~(O_CREAT | O_EXCL | O_TRUNC2), at.mode);
|
|
2493
|
-
} catch (e) {
|
|
2494
|
-
this.sys.close(kfd);
|
|
2495
|
-
throw e;
|
|
2496
|
-
}
|
|
2497
|
-
this.attach(stream, kfd, terminal);
|
|
2498
|
-
this.nameStream(stream, at.path);
|
|
2499
|
-
return stream;
|
|
2500
|
-
}
|
|
2501
|
-
usePtyPaths() {
|
|
2502
|
-
const fs = this.Fs;
|
|
2503
|
-
for (const name2 of ["chown", "lchown", "chmod", "lchmod"]) {
|
|
2504
|
-
const original = fs[name2];
|
|
2505
|
-
if (typeof original !== "function") continue;
|
|
2506
|
-
fs[name2] = (path, ...rest2) => isPtyPath(path) ? this.existingPty(path) : original.call(fs, path, ...rest2);
|
|
2507
|
-
}
|
|
2508
|
-
for (const name2 of ["stat", "lstat"]) {
|
|
2509
|
-
const original = fs[name2];
|
|
2510
|
-
if (typeof original !== "function") continue;
|
|
2511
|
-
fs[name2] = (path, ...rest2) => {
|
|
2512
|
-
if (path === SEALED_PATH && this.sys.openSealed) return sealedStat();
|
|
2513
|
-
if (path === CLIPBOARD_PATH && this.sys.openClipboard) return sealedStat(251);
|
|
2514
|
-
const owned = this.ownedTty(path);
|
|
2515
|
-
if (owned && isPtyPath(path)) return this.owned(path, ptyStat(path));
|
|
2516
|
-
if (!isPtyPath(path)) {
|
|
2517
|
-
const st = original.call(fs, path, ...rest2);
|
|
2518
|
-
return owned && TTY_PATH.test(path) ? this.owned(path, st) : st;
|
|
2519
|
-
}
|
|
2520
|
-
this.existingPty(path);
|
|
2521
|
-
return ptyStat(path);
|
|
2522
|
-
};
|
|
2523
|
-
}
|
|
2524
|
-
}
|
|
2525
|
-
ownedTty(path) {
|
|
2526
|
-
return this.options.owners === true && this.sys.ttyOwner !== void 0 && path !== "/dev/ptmx";
|
|
2527
|
-
}
|
|
2528
|
-
owned(path, st) {
|
|
2529
|
-
const ask = this.sys.ttyOwner;
|
|
2530
|
-
const owner = this.call(() => ask.call(this.sys, path));
|
|
2531
|
-
if (!owner) return st;
|
|
2532
|
-
const mode = st.mode & ~4095 | (owner.mode ?? 400);
|
|
2533
|
-
return { ...st, uid: owner.uid, gid: owner.gid, mode };
|
|
2534
|
-
}
|
|
2535
|
-
existingPty(path) {
|
|
2536
|
-
const n = PTY_PATH.exec(path)?.[1];
|
|
2537
|
-
const exists = n === void 0 ? this.sys.openPty !== void 0 : this.sys.ptyNumbers?.().includes(Number(n)) ?? false;
|
|
2538
|
-
if (!exists) throw new this.Fs.ErrnoError(wasiErrno("ENOENT"));
|
|
2539
|
-
}
|
|
2540
|
-
devicePath(path) {
|
|
2541
|
-
const name2 = path.slice(path.lastIndexOf("/") + 1);
|
|
2542
|
-
if (!TTY_NAME.test(name2)) return void 0;
|
|
2543
|
-
const { lookupPath, cwd } = this.Fs;
|
|
2544
|
-
const absolute = path.startsWith("/") ? path : `${cwd?.call(this.Fs) ?? "/"}/${path}`;
|
|
2545
|
-
const dir = absolute.slice(0, absolute.lastIndexOf("/")) || "/";
|
|
2546
|
-
try {
|
|
2547
|
-
const real = lookupPath?.call(this.Fs, dir, { follow: true }).path ?? dir;
|
|
2548
|
-
return `${real === "/" ? "" : real}/${name2}`;
|
|
2549
|
-
} catch {
|
|
2550
|
-
return absolute;
|
|
2551
|
-
}
|
|
2552
|
-
}
|
|
2553
|
-
terminalExists(path) {
|
|
2554
|
-
const { analyzePath } = this.Fs;
|
|
2555
|
-
return analyzePath?.call(this.Fs, path).exists ?? true;
|
|
2556
|
-
}
|
|
2557
|
-
openNamedTerminal(path) {
|
|
2558
|
-
const { openTty } = this.sys;
|
|
2559
|
-
if (!openTty) return void 0;
|
|
2560
|
-
try {
|
|
2561
|
-
return openTty.call(this.sys, path);
|
|
2562
|
-
} catch (e) {
|
|
2563
|
-
if (e instanceof SyscallError && e.code === "ENXIO") return void 0;
|
|
2564
|
-
return this.call(() => {
|
|
2565
|
-
throw e;
|
|
2566
|
-
});
|
|
2567
|
-
}
|
|
2568
|
-
}
|
|
2569
|
-
stdioTerminal() {
|
|
2570
|
-
for (const fd of [0, 1, 2]) {
|
|
2571
|
-
const stream = this.Fs.getStream(fd);
|
|
2572
|
-
if (stream?.sliccKernelFd !== void 0 && stream.tty) return stream.sliccKernelFd;
|
|
2573
|
-
}
|
|
2574
|
-
return void 0;
|
|
2575
|
-
}
|
|
2576
|
-
usePipes(pipefs) {
|
|
2577
|
-
const createPipe = pipefs.createPipe.bind(pipefs);
|
|
2578
|
-
pipefs.createPipe = () => {
|
|
2579
|
-
const [read2, write2] = this.call(() => this.sys.pipe());
|
|
2580
|
-
let fds;
|
|
2581
|
-
try {
|
|
2582
|
-
fds = createPipe();
|
|
2583
|
-
} catch (e) {
|
|
2584
|
-
for (const kfd of [read2, write2]) {
|
|
2585
|
-
try {
|
|
2586
|
-
this.sys.close(kfd);
|
|
2587
|
-
} catch {
|
|
2588
|
-
}
|
|
2589
|
-
}
|
|
2590
|
-
throw e;
|
|
2591
|
-
}
|
|
2592
|
-
this.attach(this.Fs.getStream(fds.readable_fd), read2, false);
|
|
2593
|
-
this.attach(this.Fs.getStream(fds.writable_fd), write2, false);
|
|
2594
|
-
return fds;
|
|
2595
|
-
};
|
|
2596
|
-
}
|
|
2597
|
-
restarting(syscall) {
|
|
2598
|
-
for (; ; ) {
|
|
2599
|
-
try {
|
|
2600
|
-
return syscall();
|
|
2601
|
-
} catch (e) {
|
|
2602
|
-
if (!(e instanceof SyscallError && e.code === "EINTR" && this.options.restartable?.())) {
|
|
2603
|
-
throw e;
|
|
2604
|
-
}
|
|
2605
|
-
}
|
|
2606
|
-
}
|
|
2607
|
-
}
|
|
2608
|
-
call(syscall) {
|
|
2609
|
-
try {
|
|
2610
|
-
return syscall();
|
|
2611
|
-
} catch (e) {
|
|
2612
|
-
if (e instanceof SyscallError) throw new this.Fs.ErrnoError(wasiErrno(e.code));
|
|
2613
|
-
throw e;
|
|
2614
|
-
}
|
|
2615
|
-
}
|
|
2616
|
-
ops(kfd, base) {
|
|
2617
|
-
return {
|
|
2618
|
-
...base,
|
|
2619
|
-
llseek: () => this.call(() => {
|
|
2620
|
-
throw new SyscallError("ESPIPE");
|
|
2621
|
-
}),
|
|
2622
|
-
read: (s, buffer, offset, length) => this.call(() => {
|
|
2623
|
-
const bytes = this.restarting(() => this.sys.read(kfd, length, nonblocking(s)));
|
|
2624
|
-
buffer.set(bytes, offset);
|
|
2625
|
-
return bytes.length;
|
|
2626
|
-
}),
|
|
2627
|
-
write: (s, buffer, offset, length) => {
|
|
2628
|
-
try {
|
|
2629
|
-
const bytes = buffer.slice(offset, offset + length);
|
|
2630
|
-
return this.restarting(() => this.sys.write(kfd, bytes, nonblocking(s)));
|
|
2631
|
-
} catch (e) {
|
|
2632
|
-
if (e instanceof SyscallError && e.code === "EPIPE" && !this.options.sigpipe?.()) {
|
|
2633
|
-
throw new ProcessExit(KILLED_BY_SIGPIPE);
|
|
2634
|
-
}
|
|
2635
|
-
return this.call(() => {
|
|
2636
|
-
throw e;
|
|
2637
|
-
});
|
|
2638
|
-
}
|
|
2639
|
-
},
|
|
2640
|
-
fsync: () => 0,
|
|
2641
|
-
poll: () => {
|
|
2642
|
-
const state = this.call(() => this.sys.poll(kfd));
|
|
2643
|
-
let mask = 0;
|
|
2644
|
-
if (state.readable) mask |= POLLIN | POLLRDNORM;
|
|
2645
|
-
if (state.writable) mask |= POLLOUT | POLLWRNORM;
|
|
2646
|
-
if (state.hangup) mask |= state.readable ? POLLHUP : POLLERR;
|
|
2647
|
-
return mask;
|
|
2648
|
-
},
|
|
2649
|
-
dup: (stream) => {
|
|
2650
|
-
base.dup?.(stream);
|
|
2651
|
-
this.refs.set(kfd, (this.refs.get(kfd) ?? 0) + 1);
|
|
2652
|
-
},
|
|
2653
|
-
close: (stream) => {
|
|
2654
|
-
if (this.atExit && stream.fd === 2 && this.reporting.size > 0) this.commitStdout();
|
|
2655
|
-
try {
|
|
2656
|
-
base.close?.(stream);
|
|
2657
|
-
} catch {
|
|
2658
|
-
}
|
|
2659
|
-
const left = (this.refs.get(kfd) ?? 1) - 1;
|
|
2660
|
-
if (left > 0) {
|
|
2661
|
-
this.refs.set(kfd, left);
|
|
2662
|
-
return;
|
|
2663
|
-
}
|
|
2664
|
-
this.refs.delete(kfd);
|
|
2665
|
-
if (this.committed.size > 0 && this.committed.delete(kfd)) return;
|
|
2666
|
-
if (this.reporting.size > 0 && this.reporting.delete(kfd)) {
|
|
2667
|
-
this.reportedClose(stream, kfd);
|
|
2668
|
-
return;
|
|
2669
|
-
}
|
|
2670
|
-
try {
|
|
2671
|
-
this.sys.close(kfd);
|
|
2672
|
-
} catch {
|
|
2673
|
-
}
|
|
2674
|
-
}
|
|
2675
|
-
};
|
|
2676
|
-
}
|
|
2677
|
-
};
|
|
2678
|
-
}
|
|
2679
|
-
});
|
|
2680
|
-
|
|
2681
|
-
// src/process/process-pty.ts
|
|
2682
|
-
function failed(e) {
|
|
2683
|
-
const code2 = e?.code;
|
|
2684
|
-
if (typeof code2 === "string") return -wasiErrno(code2);
|
|
2685
|
-
throw e;
|
|
2686
|
-
}
|
|
2687
|
-
function ptyIoctl(ioctl, deps) {
|
|
2688
|
-
return (fd, op, varargs) => {
|
|
2689
|
-
const request = op >>> 0;
|
|
2690
|
-
if (request !== TIOCGPTN && request !== TIOCSPTLCK && request !== TIOCSCTTY && request !== TIOCSWINSZ && request !== TIOCPKT) {
|
|
2691
|
-
return ioctl(fd, op, varargs);
|
|
2692
|
-
}
|
|
2693
|
-
const stream = deps.fs()?.getStream(fd);
|
|
2694
|
-
const kfd = stream?.sliccKernelFd;
|
|
2695
|
-
if (kfd === void 0) return ioctl(fd, op, varargs);
|
|
2696
|
-
const heap = deps.heap();
|
|
2697
|
-
if (!heap) return -wasiErrno("EFAULT");
|
|
2698
|
-
const argp = (heap[varargs >> 2] ?? 0) >>> 0;
|
|
2699
|
-
try {
|
|
2700
|
-
return answer(request, kfd, argp, heap, deps.kernel);
|
|
2701
|
-
} catch (e) {
|
|
2702
|
-
return failed(e);
|
|
2703
|
-
}
|
|
2704
|
-
};
|
|
2705
|
-
}
|
|
2706
|
-
function answer(request, kfd, argp, heap, kernel) {
|
|
2707
|
-
switch (request) {
|
|
2708
|
-
case TIOCGPTN:
|
|
2709
|
-
heap[argp >> 2] = kernel.ptyNumber(kfd);
|
|
2710
|
-
return 0;
|
|
2711
|
-
case TIOCSPTLCK:
|
|
2712
|
-
kernel.ptyLock(kfd, (heap[argp >> 2] ?? 0) !== 0);
|
|
2713
|
-
return 0;
|
|
2714
|
-
case TIOCSCTTY:
|
|
2715
|
-
kernel.setControllingTerminal(kfd);
|
|
2716
|
-
return 0;
|
|
2717
|
-
case TIOCPKT:
|
|
2718
|
-
kernel.setPacketMode(kfd, (heap[argp >> 2] ?? 0) !== 0);
|
|
2719
|
-
return 0;
|
|
2720
|
-
default: {
|
|
2721
|
-
const word = heap[argp >> 2] ?? 0;
|
|
2722
|
-
kernel.setWinsize(kfd, word & 65535, word >>> 16 & 65535);
|
|
2723
|
-
return 0;
|
|
2724
|
-
}
|
|
2725
|
-
}
|
|
2726
|
-
}
|
|
2727
|
-
var TIOCGPTN, TIOCSPTLCK, TIOCSCTTY, TIOCSWINSZ, TIOCPKT;
|
|
2728
|
-
var init_process_pty = __esm({
|
|
2729
|
-
"src/process/process-pty.ts"() {
|
|
2730
|
-
"use strict";
|
|
2731
|
-
init_wasi_errno();
|
|
2732
|
-
TIOCGPTN = 2147767344;
|
|
2733
|
-
TIOCSPTLCK = 1074025521;
|
|
2734
|
-
TIOCSCTTY = 21518;
|
|
2735
|
-
TIOCSWINSZ = 21524;
|
|
2736
|
-
TIOCPKT = 21536;
|
|
2737
|
-
}
|
|
2738
|
-
});
|
|
2739
|
-
|
|
2740
|
-
// src/process/process-fds.ts
|
|
2741
|
-
function closesOnExec(stream) {
|
|
2742
|
-
return stream.sliccCloexec === true;
|
|
2743
|
-
}
|
|
2744
|
-
function setCloseOnExec(stream, on) {
|
|
2745
|
-
if (on) stream.sliccCloexec = true;
|
|
2746
|
-
else delete stream.sliccCloexec;
|
|
2747
|
-
}
|
|
2748
|
-
function trackCloseOnExec(Fs) {
|
|
2749
|
-
if (tracked.has(Fs)) return;
|
|
2750
|
-
tracked.add(Fs);
|
|
2751
|
-
if (typeof Fs.dupStream === "function") {
|
|
2752
|
-
const dupStream = Fs.dupStream.bind(Fs);
|
|
2753
|
-
Fs.dupStream = (stream, fd) => {
|
|
2754
|
-
const copy2 = dupStream(stream, fd);
|
|
2755
|
-
setCloseOnExec(copy2, false);
|
|
2756
|
-
return copy2;
|
|
2757
|
-
};
|
|
2758
|
-
}
|
|
2759
|
-
if (typeof Fs.open === "function") {
|
|
2760
|
-
const open = Fs.open.bind(Fs);
|
|
2761
|
-
Fs.open = (path, flags, mode) => {
|
|
2762
|
-
const cloexec = typeof flags === "number" && (flags & O_CLOEXEC) !== 0;
|
|
2763
|
-
const stream = open(path, cloexec ? flags & ~O_CLOEXEC : flags, mode);
|
|
2764
|
-
setCloseOnExec(stream, cloexec);
|
|
2765
|
-
return stream;
|
|
2766
|
-
};
|
|
2767
|
-
}
|
|
2768
|
-
}
|
|
2769
|
-
function marker(deps) {
|
|
2770
|
-
return (fd, on) => {
|
|
2771
|
-
const stream = deps.fs()?.getStream(fd);
|
|
2772
|
-
if (stream) setCloseOnExec(stream, on);
|
|
2773
|
-
};
|
|
2774
|
-
}
|
|
2775
|
-
function cloexecFcntl(fcntl, deps) {
|
|
2776
|
-
const mark = marker(deps);
|
|
2777
|
-
return (fd, cmd, varargs) => {
|
|
2778
|
-
if (cmd === F_DUPFD_CLOEXEC) {
|
|
2779
|
-
const copy2 = fcntl(fd, F_DUPFD, varargs);
|
|
2780
|
-
if (copy2 >= 0) mark(copy2, true);
|
|
2781
|
-
return copy2;
|
|
2782
|
-
}
|
|
2783
|
-
if (cmd === F_GETFL) {
|
|
2784
|
-
const flags = fcntl(fd, cmd, varargs);
|
|
2785
|
-
return flags < 0 ? flags : flags & ~O_CLOEXEC;
|
|
2649
|
+
} catch (err) {
|
|
2650
|
+
throw new Fs.ErrnoError(errnoOf(err));
|
|
2786
2651
|
}
|
|
2787
|
-
|
|
2788
|
-
const
|
|
2789
|
-
if (!
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
return 0;
|
|
2652
|
+
const size = Math.ceil(length / MAP_ALIGN) * MAP_ALIGN;
|
|
2653
|
+
const ptr = memalign(MAP_ALIGN, size);
|
|
2654
|
+
if (!ptr) throw new Fs.ErrnoError(wasiErrno("ENOMEM"));
|
|
2655
|
+
const target = new Uint8Array(memory.buffer, ptr, size);
|
|
2656
|
+
target.fill(0);
|
|
2657
|
+
target.set(data.subarray(0, done));
|
|
2658
|
+
return { ptr, allocated: true };
|
|
2795
2659
|
};
|
|
2796
2660
|
}
|
|
2797
|
-
function
|
|
2798
|
-
const
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
return r;
|
|
2807
|
-
};
|
|
2661
|
+
function wasmMemory(instance, imports) {
|
|
2662
|
+
const isMemory = (v) => v instanceof WebAssembly.Memory;
|
|
2663
|
+
const exported = Object.values(instance.exports).find(isMemory);
|
|
2664
|
+
if (exported) return exported;
|
|
2665
|
+
for (const namespace of Object.values(imports)) {
|
|
2666
|
+
const found = Object.values(namespace ?? {}).find(isMemory);
|
|
2667
|
+
if (found) return found;
|
|
2668
|
+
}
|
|
2669
|
+
return void 0;
|
|
2808
2670
|
}
|
|
2809
|
-
function
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
if (
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
}
|
|
2818
|
-
}
|
|
2819
|
-
return dup3(fd, newfd, flags, ...rest2);
|
|
2820
|
-
};
|
|
2671
|
+
function absoluteOf(path, cwd) {
|
|
2672
|
+
const parts = [];
|
|
2673
|
+
for (const part of `${path.startsWith("/") ? "" : cwd}/${path}`.split("/")) {
|
|
2674
|
+
if (part === "" || part === ".") continue;
|
|
2675
|
+
if (part === "..") parts.pop();
|
|
2676
|
+
else parts.push(part);
|
|
2677
|
+
}
|
|
2678
|
+
return `/${parts.join("/")}`;
|
|
2821
2679
|
}
|
|
2822
|
-
function
|
|
2823
|
-
const
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
if (fd >= 0) mark(fd, cloexec);
|
|
2829
|
-
return fd;
|
|
2830
|
-
};
|
|
2680
|
+
function fdOfPath(path, cwd) {
|
|
2681
|
+
const abs = absoluteOf(path, cwd);
|
|
2682
|
+
const std = ["/dev/stdin", "/dev/stdout", "/dev/stderr"].indexOf(abs);
|
|
2683
|
+
if (std >= 0) return std;
|
|
2684
|
+
const m = /^\/(?:dev|proc\/self)\/fd\/(\d+)$/.exec(abs);
|
|
2685
|
+
return m ? Number(m[1]) : void 0;
|
|
2831
2686
|
}
|
|
2832
|
-
function
|
|
2833
|
-
const
|
|
2687
|
+
function syntheticAttr(mode, ino) {
|
|
2688
|
+
const now = /* @__PURE__ */ new Date();
|
|
2834
2689
|
return {
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2690
|
+
dev: 1,
|
|
2691
|
+
ino,
|
|
2692
|
+
mode,
|
|
2693
|
+
nlink: 1,
|
|
2694
|
+
uid: 0,
|
|
2695
|
+
gid: 0,
|
|
2696
|
+
rdev: 0,
|
|
2697
|
+
size: 0,
|
|
2698
|
+
atime: now,
|
|
2699
|
+
mtime: now,
|
|
2700
|
+
ctime: now,
|
|
2701
|
+
blksize: 4096,
|
|
2702
|
+
blocks: 0
|
|
2842
2703
|
};
|
|
2843
2704
|
}
|
|
2844
|
-
function
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2705
|
+
function describeFdDir(Fs) {
|
|
2706
|
+
let dir;
|
|
2707
|
+
try {
|
|
2708
|
+
dir = Fs.lookupPath?.("/proc/self/fd", { follow: true })?.node;
|
|
2709
|
+
} catch {
|
|
2710
|
+
return;
|
|
2711
|
+
}
|
|
2712
|
+
const ops = dir?.node_ops;
|
|
2713
|
+
const lookup2 = ops?.lookup;
|
|
2714
|
+
if (!dir || !lookup2 || ops.getattr) return;
|
|
2715
|
+
dir.node_ops = {
|
|
2716
|
+
...ops,
|
|
2717
|
+
getattr: () => syntheticAttr(DIR_MODE, 1),
|
|
2718
|
+
lookup: (parent, name2) => {
|
|
2719
|
+
const entry = lookup2(parent, name2);
|
|
2720
|
+
entry.node_ops = {
|
|
2721
|
+
...entry.node_ops,
|
|
2722
|
+
getattr: () => syntheticAttr(LINK_MODE, entry.id ?? 0)
|
|
2723
|
+
};
|
|
2724
|
+
return entry;
|
|
2725
|
+
}
|
|
2849
2726
|
};
|
|
2850
2727
|
}
|
|
2851
|
-
function
|
|
2852
|
-
const
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2728
|
+
function useZeroDevices(Fs) {
|
|
2729
|
+
const { analyzePath, registerDevice, mkdev, makedev } = Fs;
|
|
2730
|
+
if (!analyzePath || !registerDevice || !mkdev || !makedev) return;
|
|
2731
|
+
const zeros = (_s, buffer, offset, length) => {
|
|
2732
|
+
buffer.fill(0, offset, offset + length);
|
|
2733
|
+
return length;
|
|
2734
|
+
};
|
|
2735
|
+
const devices = [
|
|
2736
|
+
["/dev/zero", 5, (_s, _b, _o, length) => length],
|
|
2737
|
+
[
|
|
2738
|
+
"/dev/full",
|
|
2739
|
+
7,
|
|
2740
|
+
(_s, _b, _o, length) => {
|
|
2741
|
+
if (length > 0) throw new Fs.ErrnoError(wasiErrno("ENOSPC"));
|
|
2742
|
+
return 0;
|
|
2743
|
+
}
|
|
2744
|
+
]
|
|
2745
|
+
];
|
|
2746
|
+
for (const [path, minor, write2] of devices) {
|
|
2747
|
+
if (analyzePath.call(Fs, path).exists) continue;
|
|
2748
|
+
const dev = makedev.call(Fs, 1, minor);
|
|
2749
|
+
registerDevice.call(Fs, dev, { read: zeros, write: write2, llseek: () => 0 });
|
|
2750
|
+
mkdev.call(Fs, path, CHAR_DEVICE, dev);
|
|
2751
|
+
}
|
|
2856
2752
|
}
|
|
2857
|
-
function
|
|
2858
|
-
|
|
2859
|
-
const
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2753
|
+
function useDevRemoval(Fs) {
|
|
2754
|
+
const fs = Fs;
|
|
2755
|
+
for (const name2 of ["unlink", "rmdir"]) {
|
|
2756
|
+
const remove = fs[name2];
|
|
2757
|
+
if (typeof remove !== "function") continue;
|
|
2758
|
+
fs[name2] = (path) => {
|
|
2759
|
+
const refused = devRemoval(absoluteOf(path, Fs.cwd()), fs.sliccCred);
|
|
2760
|
+
if (refused) throw new Fs.ErrnoError(wasiErrno(refused));
|
|
2761
|
+
remove.call(Fs, path);
|
|
2762
|
+
};
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
function linkStdio(Fs) {
|
|
2766
|
+
const { unlink, symlink } = Fs;
|
|
2767
|
+
if (!unlink || !symlink) return;
|
|
2768
|
+
for (const [fd, name2] of ["stdin", "stdout", "stderr"].entries()) {
|
|
2769
|
+
try {
|
|
2770
|
+
unlink.call(Fs, `/dev/${name2}`);
|
|
2771
|
+
} catch {
|
|
2772
|
+
}
|
|
2773
|
+
try {
|
|
2774
|
+
symlink.call(Fs, `/proc/self/fd/${fd}`, `/dev/${name2}`);
|
|
2775
|
+
} catch {
|
|
2868
2776
|
}
|
|
2869
2777
|
}
|
|
2870
2778
|
}
|
|
2871
|
-
function
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2779
|
+
function useDevFd(Fs) {
|
|
2780
|
+
if (typeof Fs.open !== "function") return;
|
|
2781
|
+
try {
|
|
2782
|
+
Fs.symlink?.("/proc/self/fd", "/dev/fd");
|
|
2783
|
+
} catch {
|
|
2784
|
+
}
|
|
2785
|
+
linkStdio(Fs);
|
|
2786
|
+
describeFdDir(Fs);
|
|
2787
|
+
const fdOf = (path) => typeof path === "string" ? fdOfPath(path, Fs.cwd()) : void 0;
|
|
2788
|
+
const target = (fd) => {
|
|
2789
|
+
const stream = Fs.getStream(fd);
|
|
2790
|
+
if (!stream) throw new Fs.ErrnoError(wasiErrno("EBADF"));
|
|
2791
|
+
return stream;
|
|
2792
|
+
};
|
|
2793
|
+
const open = Fs.open.bind(Fs);
|
|
2794
|
+
Fs.open = (path, flags, mode) => {
|
|
2795
|
+
const fd = fdOf(path);
|
|
2796
|
+
if (fd === void 0) return open(path, flags, mode);
|
|
2797
|
+
const copy2 = Fs.dupStream(target(fd), -1);
|
|
2798
|
+
setCloseOnExec(copy2, typeof flags === "number" && (flags & O_CLOEXEC) !== 0);
|
|
2799
|
+
return copy2;
|
|
2800
|
+
};
|
|
2801
|
+
const { stat, fstat } = Fs;
|
|
2802
|
+
if (typeof stat !== "function" || typeof fstat !== "function") return;
|
|
2803
|
+
Fs.stat = (path, dontFollow) => {
|
|
2804
|
+
const fd = dontFollow ? void 0 : fdOf(path);
|
|
2805
|
+
if (fd === void 0) return stat.call(Fs, path, dontFollow);
|
|
2806
|
+
target(fd);
|
|
2807
|
+
return fstat.call(Fs, fd);
|
|
2808
|
+
};
|
|
2876
2809
|
}
|
|
2877
|
-
function
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2810
|
+
function pinRootKind() {
|
|
2811
|
+
pinnedRoot = rootKind();
|
|
2812
|
+
}
|
|
2813
|
+
function mountTable(mounts = []) {
|
|
2814
|
+
const root = pinnedRoot ?? rootKind();
|
|
2815
|
+
const lines = [`${root} / ${root} rw 0 0`, "devfs /dev devfs rw 0 0", "proc /proc proc rw 0 0"];
|
|
2816
|
+
for (const m of mounts) {
|
|
2817
|
+
const options = Object.entries(m.options).map(([k, v]) => v === "" ? k : `${k}=${v}`);
|
|
2818
|
+
if (m.state !== "ok") options.push(m.state);
|
|
2819
|
+
const access = options.includes("ro") ? [] : ["rw"];
|
|
2820
|
+
lines.push(
|
|
2821
|
+
`${field(m.source)} ${field(m.target)} ${m.type} ${[...access, ...options].join(",")} 0 0`
|
|
2822
|
+
);
|
|
2882
2823
|
}
|
|
2883
|
-
|
|
2884
|
-
|
|
2824
|
+
return `${lines.join("\n")}
|
|
2825
|
+
`;
|
|
2885
2826
|
}
|
|
2886
|
-
function
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2827
|
+
function accounts(env = {}) {
|
|
2828
|
+
const user = env.USER ?? "web_user";
|
|
2829
|
+
const name2 = NAME.test(user) && user !== "root" ? user : "user";
|
|
2830
|
+
const home = env.HOME || "/home";
|
|
2831
|
+
return {
|
|
2832
|
+
passwd: `root:x:0:0:root:/root:/bin/sh
|
|
2833
|
+
${name2}:x:1000:1000:${name2}:${home}:/bin/bash
|
|
2834
|
+
`,
|
|
2835
|
+
group: `root:x:0:
|
|
2836
|
+
${name2}:x:1000:
|
|
2837
|
+
`
|
|
2838
|
+
};
|
|
2839
|
+
}
|
|
2840
|
+
function useMounts(Fs, env = {}, live = false) {
|
|
2841
|
+
const { writeFile, mkdirTree } = Fs;
|
|
2842
|
+
if (typeof Fs.open !== "function" || typeof writeFile !== "function") return;
|
|
2843
|
+
const { passwd, group } = accounts(env);
|
|
2844
|
+
const backing = { "/etc/mtab": "/proc/mounts" };
|
|
2845
|
+
try {
|
|
2846
|
+
if (!live) writeFile.call(Fs, "/proc/mounts", mountTable());
|
|
2847
|
+
} catch {
|
|
2848
|
+
return;
|
|
2893
2849
|
}
|
|
2894
|
-
|
|
2895
|
-
|
|
2850
|
+
try {
|
|
2851
|
+
mkdirTree.call(Fs, "/dev/.etc");
|
|
2852
|
+
writeFile.call(Fs, "/dev/.etc/passwd", passwd);
|
|
2853
|
+
writeFile.call(Fs, "/dev/.etc/group", group);
|
|
2854
|
+
writeFile.call(Fs, "/dev/.etc/hosts", hostsFile(hostnameOf(env)));
|
|
2855
|
+
writeFile.call(Fs, "/dev/.etc/hostname", `${hostnameOf(env)}
|
|
2856
|
+
`);
|
|
2857
|
+
backing["/etc/passwd"] = "/dev/.etc/passwd";
|
|
2858
|
+
backing["/etc/group"] = "/dev/.etc/group";
|
|
2859
|
+
backing["/etc/hosts"] = "/dev/.etc/hosts";
|
|
2860
|
+
backing["/etc/hostname"] = "/dev/.etc/hostname";
|
|
2861
|
+
} catch {
|
|
2896
2862
|
}
|
|
2863
|
+
const open = Fs.open.bind(Fs);
|
|
2864
|
+
Fs.open = (path, flags, mode) => {
|
|
2865
|
+
const instead = backing[path];
|
|
2866
|
+
if (!instead || (flags & (O_ACCMODE2 | O_CREAT)) !== 0) return open(path, flags, mode);
|
|
2867
|
+
try {
|
|
2868
|
+
return open(path, flags, mode);
|
|
2869
|
+
} catch (e) {
|
|
2870
|
+
if (e?.errno !== wasiErrno("ENOENT")) throw e;
|
|
2871
|
+
return open(instead, flags, mode);
|
|
2872
|
+
}
|
|
2873
|
+
};
|
|
2897
2874
|
}
|
|
2898
|
-
function
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
wrapImport(imports, "openat", glue, (openat) => (dirfd, path, flags, varargs) => {
|
|
2902
|
-
const memory = deps.memory();
|
|
2903
|
-
if (flags & O_CREAT2 && varargs && memory) new Int32Array(memory.buffer)[varargs >> 2] &= ~umask;
|
|
2904
|
-
return openat(dirfd, path, flags, varargs);
|
|
2905
|
-
});
|
|
2906
|
-
wrapImport(
|
|
2907
|
-
imports,
|
|
2908
|
-
"mkdirat",
|
|
2909
|
-
glue,
|
|
2910
|
-
(mkdirat) => (dirfd, path, mode) => mkdirat(dirfd, path, mode & ~umask)
|
|
2911
|
-
);
|
|
2912
|
-
wrapImport(
|
|
2913
|
-
imports,
|
|
2914
|
-
"mknodat",
|
|
2915
|
-
glue,
|
|
2916
|
-
(mknodat) => (dirfd, path, mode, dev) => mknodat(dirfd, path, mode & ~umask, dev)
|
|
2917
|
-
);
|
|
2918
|
-
wrapImport(imports, "umask", glue, (own) => {
|
|
2919
|
-
own(umask);
|
|
2920
|
-
return (mask) => {
|
|
2921
|
-
const old = umask;
|
|
2922
|
-
umask = mask & 511;
|
|
2923
|
-
own(umask);
|
|
2924
|
-
deps.set(umask);
|
|
2925
|
-
return old;
|
|
2926
|
-
};
|
|
2927
|
-
});
|
|
2875
|
+
function cString(memory, at) {
|
|
2876
|
+
const bytes = new Uint8Array(memory.buffer, at);
|
|
2877
|
+
return new TextDecoder().decode(bytes.subarray(0, bytes.indexOf(0)));
|
|
2928
2878
|
}
|
|
2929
|
-
function
|
|
2930
|
-
|
|
2931
|
-
if (!memory) return false;
|
|
2932
|
-
const heap = new Int32Array(memory.buffer);
|
|
2933
|
-
const nsec = [heap[times + 8 >> 2], heap[times + 24 >> 2]];
|
|
2934
|
-
return nsec.every((n) => n === UTIME_NOW || n === UTIME_OMIT);
|
|
2879
|
+
function baseOf(Fs, dirfd) {
|
|
2880
|
+
return dirfd === AT_FDCWD ? Fs.cwd?.() ?? "/" : Fs.getStream?.(dirfd)?.path ?? "/";
|
|
2935
2881
|
}
|
|
2936
|
-
function
|
|
2937
|
-
if (!
|
|
2938
|
-
Fs.sliccTouch = true;
|
|
2882
|
+
function readonlyRefusal(Fs, memory, call2) {
|
|
2883
|
+
if (!(call2.amode & W_ACCESS)) return 0;
|
|
2939
2884
|
try {
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2885
|
+
const name2 = cString(memory, call2.path);
|
|
2886
|
+
const abs = name2.startsWith("/") ? name2 : `${baseOf(Fs, call2.dirfd)}/${name2}`;
|
|
2887
|
+
const follow2 = (call2.flags & AT_SYMLINK_NOFOLLOW) === 0;
|
|
2888
|
+
const { node } = Fs.lookupPath.call(Fs, abs, {
|
|
2889
|
+
follow: follow2
|
|
2890
|
+
});
|
|
2891
|
+
const bridge = node.live ? node.mount.opts.bridge : void 0;
|
|
2892
|
+
const stats = bridge;
|
|
2893
|
+
const stat = follow2 ? stats?.stat : stats?.lstat;
|
|
2894
|
+
return stat?.call(stats, liveNodePath(node)).readonly ? -wasiErrno("EROFS") : 0;
|
|
2895
|
+
} catch {
|
|
2896
|
+
return 0;
|
|
2943
2897
|
}
|
|
2944
2898
|
}
|
|
2945
|
-
function
|
|
2899
|
+
function kernelChecks(Fs, memory, call2) {
|
|
2900
|
+
const name2 = cString(memory, call2.path);
|
|
2901
|
+
const abs = name2.startsWith("/") ? name2 : `${baseOf(Fs, call2.dirfd)}/${name2}`;
|
|
2902
|
+
const lookupPath = Fs.lookupPath;
|
|
2903
|
+
const { node } = lookupPath.call(Fs, abs, { follow: (call2.flags & AT_SYMLINK_NOFOLLOW) === 0 });
|
|
2904
|
+
const bridge = node.live ? node.mount.opts.bridge : void 0;
|
|
2905
|
+
if (!bridge?.owners || !bridge.access) return 0;
|
|
2906
|
+
const kind = call2.flags & AT_EACCESS ? "eaccess" : "access";
|
|
2907
|
+
bridge.access(liveNodePath(node), call2.amode, kind, (call2.flags & AT_SYMLINK_NOFOLLOW) !== 0);
|
|
2908
|
+
return 0;
|
|
2909
|
+
}
|
|
2910
|
+
function kernelAccess(imports, fs, memory, glue) {
|
|
2911
|
+
wrapImport(imports, "faccessat", glue, (own) => (dirfd, path, amode, flags) => {
|
|
2912
|
+
const Fs = fs();
|
|
2913
|
+
const heap = memory();
|
|
2914
|
+
const call2 = { dirfd, path, amode: amode & 7, flags };
|
|
2915
|
+
const refused = Fs?.lookupPath && heap ? readonlyRefusal(Fs, heap, call2) : 0;
|
|
2916
|
+
if (refused !== 0) return refused;
|
|
2917
|
+
const rc = own(dirfd, path, amode, flags);
|
|
2918
|
+
if (rc !== 0 || !Fs?.lookupPath || !heap) return rc;
|
|
2919
|
+
try {
|
|
2920
|
+
return kernelChecks(Fs, heap, { dirfd, path, amode: amode & 7, flags });
|
|
2921
|
+
} catch (err) {
|
|
2922
|
+
return -errnoOf(err);
|
|
2923
|
+
}
|
|
2924
|
+
});
|
|
2925
|
+
}
|
|
2926
|
+
function kernelLink(imports, fs, memory, glue) {
|
|
2946
2927
|
wrapImport(
|
|
2947
2928
|
imports,
|
|
2948
|
-
"
|
|
2949
|
-
|
|
2950
|
-
(
|
|
2929
|
+
"linkat",
|
|
2930
|
+
glue,
|
|
2931
|
+
(own) => (olddirfd, oldpath, newdirfd, newpath, flags) => {
|
|
2951
2932
|
const Fs = fs();
|
|
2952
|
-
const
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
Fs.utime = (at, atime, mtime) => {
|
|
2958
|
-
const { node } = lookupPath.call(Fs, at, { follow: false });
|
|
2959
|
-
if (!node.node_ops.setattr) throw new ErrnoError(EMSCRIPTEN_EPERM);
|
|
2960
|
-
node.node_ops.setattr(node, { atime, mtime });
|
|
2933
|
+
const heap = memory();
|
|
2934
|
+
if (!Fs?.lookupPath || !heap) return own(olddirfd, oldpath, newdirfd, newpath, flags);
|
|
2935
|
+
const at = (dirfd, ptr) => {
|
|
2936
|
+
const name2 = cString(heap, ptr);
|
|
2937
|
+
return name2.startsWith("/") ? name2 : `${baseOf(Fs, dirfd)}/${name2}`;
|
|
2961
2938
|
};
|
|
2962
2939
|
try {
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2940
|
+
const from = at(olddirfd, oldpath);
|
|
2941
|
+
const to = at(newdirfd, newpath);
|
|
2942
|
+
const follow2 = (flags & AT_SYMLINK_FOLLOW) !== 0;
|
|
2943
|
+
if (linkLive(Fs, from, to, follow2)) return 0;
|
|
2944
|
+
} catch (err) {
|
|
2945
|
+
return -errnoOf(err);
|
|
2966
2946
|
}
|
|
2967
|
-
|
|
2947
|
+
return own(olddirfd, oldpath, newdirfd, newpath, flags);
|
|
2948
|
+
},
|
|
2949
|
+
true
|
|
2968
2950
|
);
|
|
2969
2951
|
}
|
|
2970
|
-
function
|
|
2971
|
-
const {
|
|
2972
|
-
if (
|
|
2973
|
-
|
|
2974
|
-
|
|
2952
|
+
function kernelChdir(Fs) {
|
|
2953
|
+
const { chdir, lookupPath, ErrnoError } = Fs;
|
|
2954
|
+
if (!chdir || !lookupPath || !ErrnoError) return;
|
|
2955
|
+
Fs.chdir = (path) => {
|
|
2956
|
+
const { node } = lookupPath.call(Fs, path, { follow: true });
|
|
2957
|
+
const directory = Fs.isDir?.(node.mode) === true;
|
|
2958
|
+
const bridge = node.live && directory ? node.mount.opts.bridge : void 0;
|
|
2959
|
+
try {
|
|
2960
|
+
bridge?.access?.(liveNodePath(node), X_ACCESS, "eaccess", false);
|
|
2961
|
+
} catch (err) {
|
|
2962
|
+
throw new ErrnoError(errnoOf(err));
|
|
2963
|
+
}
|
|
2964
|
+
chdir.call(Fs, path);
|
|
2965
|
+
};
|
|
2966
|
+
}
|
|
2967
|
+
function linuxDevices(Fs) {
|
|
2968
|
+
Fs.ignorePermissions = true;
|
|
2969
|
+
kernelChdir(Fs);
|
|
2970
|
+
const { chmod } = Fs;
|
|
2971
|
+
if (!chmod) return;
|
|
2972
|
+
for (const [path, mode] of DEVICE_MODES) {
|
|
2973
|
+
try {
|
|
2974
|
+
chmod.call(Fs, path, mode);
|
|
2975
|
+
} catch {
|
|
2976
|
+
}
|
|
2977
|
+
}
|
|
2978
|
+
}
|
|
2979
|
+
var O_CLOEXEC, FD_CLOEXEC, F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_DUPFD_CLOEXEC, tracked, IMPORT_NAMES, EBADF, AT_SYMLINK_NOFOLLOW, EMSCRIPTEN_EPERM, O_PATH2, LITERALS, UTIME_NOW, UTIME_OMIT, PROT_WRITE, MAP_PRIVATE, MAP_TYPE, O_WRONLY, MAP_ALIGN, DIR_MODE, LINK_MODE, CHAR_DEVICE, O_ACCMODE2, O_CREAT, field, pinnedRoot, rootKind, NAME, AT_FDCWD, AT_EACCESS, W_ACCESS, X_ACCESS, AT_SYMLINK_FOLLOW, DEVICE_MODES;
|
|
2980
|
+
var init_process_fds = __esm({
|
|
2981
|
+
"src/process/process-fds.ts"() {
|
|
2982
|
+
"use strict";
|
|
2983
|
+
init_dev_removal();
|
|
2984
|
+
init_loopback_names();
|
|
2985
|
+
init_live_vfs_fs();
|
|
2986
|
+
init_process_pty();
|
|
2987
|
+
init_wasi_errno();
|
|
2988
|
+
O_CLOEXEC = 524288;
|
|
2989
|
+
FD_CLOEXEC = 1;
|
|
2990
|
+
F_DUPFD = 0;
|
|
2991
|
+
F_GETFD = 1;
|
|
2992
|
+
F_SETFD = 2;
|
|
2993
|
+
F_GETFL = 3;
|
|
2994
|
+
F_DUPFD_CLOEXEC = 1030;
|
|
2995
|
+
tracked = /* @__PURE__ */ new WeakSet();
|
|
2996
|
+
IMPORT_NAMES = {
|
|
2997
|
+
fcntl: "__syscall_fcntl64",
|
|
2998
|
+
pipe2: "__syscall_pipe2",
|
|
2999
|
+
dup3: "__syscall_dup3",
|
|
3000
|
+
socket: "__syscall_socket",
|
|
3001
|
+
accept4: "__syscall_accept4",
|
|
3002
|
+
ioctl: "__syscall_ioctl",
|
|
3003
|
+
setitimer: "_setitimer_js"
|
|
3004
|
+
};
|
|
3005
|
+
EBADF = 8;
|
|
3006
|
+
AT_SYMLINK_NOFOLLOW = 256;
|
|
3007
|
+
EMSCRIPTEN_EPERM = 63;
|
|
3008
|
+
O_PATH2 = 2097152;
|
|
3009
|
+
LITERALS = {
|
|
3010
|
+
openat: "__syscall_openat",
|
|
3011
|
+
mkdirat: "__syscall_mkdirat",
|
|
3012
|
+
mknodat: "__syscall_mknodat",
|
|
3013
|
+
umask: "__syscall_umask",
|
|
3014
|
+
faccessat: "__syscall_faccessat",
|
|
3015
|
+
linkat: "__syscall_linkat",
|
|
3016
|
+
utimensat: "__syscall_utimensat",
|
|
3017
|
+
getppid: "slicc_getppid_js",
|
|
3018
|
+
resizeHeap: "emscripten_resize_heap",
|
|
3019
|
+
fdWrite: "fd_write",
|
|
3020
|
+
fdRead: "fd_read",
|
|
3021
|
+
sleepMs: "slicc_sleep_ms"
|
|
3022
|
+
};
|
|
3023
|
+
UTIME_NOW = 1073741823;
|
|
3024
|
+
UTIME_OMIT = 1073741822;
|
|
3025
|
+
PROT_WRITE = 2;
|
|
3026
|
+
MAP_PRIVATE = 2;
|
|
3027
|
+
MAP_TYPE = 15;
|
|
3028
|
+
O_WRONLY = 1;
|
|
3029
|
+
MAP_ALIGN = 65536;
|
|
3030
|
+
DIR_MODE = 16749;
|
|
3031
|
+
LINK_MODE = 41408;
|
|
3032
|
+
CHAR_DEVICE = 8630;
|
|
3033
|
+
O_ACCMODE2 = 3;
|
|
3034
|
+
O_CREAT = 64;
|
|
3035
|
+
field = (text) => (text || "none").replace(/[\s\\]/g, (c) => `\\${c.charCodeAt(0).toString(8).padStart(3, "0")}`);
|
|
3036
|
+
rootKind = () => globalThis.navigator?.storage ? "opfs" : "memory";
|
|
3037
|
+
NAME = /^[a-z_][a-z0-9_-]*$/i;
|
|
3038
|
+
AT_FDCWD = -100;
|
|
3039
|
+
AT_EACCESS = 512;
|
|
3040
|
+
W_ACCESS = 2;
|
|
3041
|
+
X_ACCESS = 1;
|
|
3042
|
+
AT_SYMLINK_FOLLOW = 1024;
|
|
3043
|
+
DEVICE_MODES = [
|
|
3044
|
+
["/", 493],
|
|
3045
|
+
["/dev", 493],
|
|
3046
|
+
["/dev/null", 438],
|
|
3047
|
+
["/dev/zero", 438],
|
|
3048
|
+
["/dev/full", 438],
|
|
3049
|
+
["/dev/random", 438],
|
|
3050
|
+
["/dev/urandom", 438],
|
|
3051
|
+
["/dev/tty", 438],
|
|
3052
|
+
["/dev/shm", 1023]
|
|
3053
|
+
];
|
|
3054
|
+
}
|
|
3055
|
+
});
|
|
3056
|
+
|
|
3057
|
+
// src/process/fd-metadata.ts
|
|
3058
|
+
function idOf2(value2) {
|
|
3059
|
+
return value2 === -1 || value2 === 4294967295 ? void 0 : value2 >>> 0;
|
|
3060
|
+
}
|
|
3061
|
+
function timeOf(value2) {
|
|
3062
|
+
return typeof value2 === "number" && Number.isFinite(value2) ? value2 : null;
|
|
2975
3063
|
}
|
|
2976
|
-
function
|
|
2977
|
-
const
|
|
2978
|
-
|
|
3064
|
+
function useKernelFdMetadata(Fs, sys, call2) {
|
|
3065
|
+
const { fdChown, fdChmod, fdUtimes } = sys;
|
|
3066
|
+
const meta = Fs;
|
|
3067
|
+
const kernelFd = (stream) => stream?.sliccKernelFile ? stream.sliccKernelFd : void 0;
|
|
3068
|
+
const find = (match) => {
|
|
3069
|
+
for (const s of Fs.streams) {
|
|
3070
|
+
const kfd = s && match(s) ? kernelFd(s) : void 0;
|
|
3071
|
+
if (kfd !== void 0) return kfd;
|
|
3072
|
+
}
|
|
3073
|
+
return void 0;
|
|
3074
|
+
};
|
|
3075
|
+
const ofPath = (path, follow2) => {
|
|
3076
|
+
if (typeof path !== "string") return find((s) => s.node === path);
|
|
3077
|
+
const fd = follow2 ? fdOfPath(path, Fs.cwd()) : void 0;
|
|
3078
|
+
if (fd !== void 0) return kernelFd(Fs.getStream(fd));
|
|
3079
|
+
return find((s) => s.path === path);
|
|
3080
|
+
};
|
|
3081
|
+
const ofFd = (fd) => kernelFd(Fs.getStream(fd));
|
|
3082
|
+
const chownBy = (kfd, uid, gid) => call2(() => fdChown?.call(sys, kfd, idOf2(uid), idOf2(gid)));
|
|
3083
|
+
if (fdChown && meta.chown) {
|
|
3084
|
+
const chown = meta.chown.bind(Fs);
|
|
3085
|
+
meta.chown = (path, uid, gid, dontFollow) => {
|
|
3086
|
+
const kfd = ofPath(path, !dontFollow);
|
|
3087
|
+
if (kfd === void 0) return chown(path, uid, gid, dontFollow);
|
|
3088
|
+
chownBy(kfd, uid, gid);
|
|
3089
|
+
};
|
|
3090
|
+
}
|
|
3091
|
+
if (fdChown && meta.fchown) {
|
|
3092
|
+
const fchown = meta.fchown.bind(Fs);
|
|
3093
|
+
meta.fchown = (fd, uid, gid) => {
|
|
3094
|
+
const kfd = ofFd(fd);
|
|
3095
|
+
if (kfd === void 0) return fchown(fd, uid, gid);
|
|
3096
|
+
chownBy(kfd, uid, gid);
|
|
3097
|
+
};
|
|
3098
|
+
}
|
|
3099
|
+
if (fdChmod && meta.chmod) {
|
|
3100
|
+
const chmod = meta.chmod.bind(Fs);
|
|
3101
|
+
meta.chmod = (path, mode, dontFollow) => {
|
|
3102
|
+
const kfd = ofPath(path, !dontFollow);
|
|
3103
|
+
if (kfd === void 0) return chmod(path, mode, dontFollow);
|
|
3104
|
+
call2(() => fdChmod.call(sys, kfd, mode & 4095));
|
|
3105
|
+
};
|
|
3106
|
+
}
|
|
3107
|
+
if (fdChmod && meta.fchmod) {
|
|
3108
|
+
const fchmod = meta.fchmod.bind(Fs);
|
|
3109
|
+
meta.fchmod = (fd, mode) => {
|
|
3110
|
+
const kfd = ofFd(fd);
|
|
3111
|
+
if (kfd === void 0) return fchmod(fd, mode);
|
|
3112
|
+
call2(() => fdChmod.call(sys, kfd, mode & 4095));
|
|
3113
|
+
};
|
|
3114
|
+
}
|
|
3115
|
+
if (fdUtimes && meta.utime) {
|
|
3116
|
+
const utime = meta.utime.bind(Fs);
|
|
3117
|
+
meta.utime = (path, atime, mtime) => {
|
|
3118
|
+
const kfd = ofPath(path, true);
|
|
3119
|
+
if (kfd === void 0) return utime(path, atime, mtime);
|
|
3120
|
+
const now = meta.sliccTouch === true;
|
|
3121
|
+
call2(() => fdUtimes.call(sys, kfd, timeOf(atime), timeOf(mtime), now));
|
|
3122
|
+
};
|
|
3123
|
+
}
|
|
2979
3124
|
}
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
3125
|
+
var init_fd_metadata = __esm({
|
|
3126
|
+
"src/process/fd-metadata.ts"() {
|
|
3127
|
+
"use strict";
|
|
3128
|
+
init_process_fds();
|
|
2984
3129
|
}
|
|
2985
|
-
|
|
3130
|
+
});
|
|
3131
|
+
|
|
3132
|
+
// src/process/kernel-streams.ts
|
|
3133
|
+
function isPtyPath(path) {
|
|
3134
|
+
return PTY_PATH.test(path);
|
|
2986
3135
|
}
|
|
2987
|
-
function
|
|
2988
|
-
const
|
|
2989
|
-
const
|
|
2990
|
-
return
|
|
3136
|
+
function ptyStat(path) {
|
|
3137
|
+
const n = PTY_PATH.exec(path)?.[1];
|
|
3138
|
+
const now = /* @__PURE__ */ new Date();
|
|
3139
|
+
return {
|
|
3140
|
+
dev: 22,
|
|
3141
|
+
ino: n === void 0 ? 2 : 3 + Number(n),
|
|
3142
|
+
mode: n === void 0 ? 8630 : 8592,
|
|
3143
|
+
nlink: 1,
|
|
3144
|
+
uid: 1e3,
|
|
3145
|
+
gid: 1e3,
|
|
3146
|
+
rdev: n === void 0 ? 5 << 8 | 2 : 136 << 8 | Number(n),
|
|
3147
|
+
size: 0,
|
|
3148
|
+
blksize: 4096,
|
|
3149
|
+
blocks: 0,
|
|
3150
|
+
atime: now,
|
|
3151
|
+
mtime: now,
|
|
3152
|
+
ctime: now
|
|
3153
|
+
};
|
|
2991
3154
|
}
|
|
2992
|
-
function
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
}
|
|
3155
|
+
function sealedStat(minor = 250) {
|
|
3156
|
+
const now = /* @__PURE__ */ new Date();
|
|
3157
|
+
return {
|
|
3158
|
+
dev: 22,
|
|
3159
|
+
ino: minor === 251 ? 2 : 1,
|
|
3160
|
+
mode: 8630,
|
|
3161
|
+
nlink: 1,
|
|
3162
|
+
uid: 0,
|
|
3163
|
+
gid: 0,
|
|
3164
|
+
rdev: 10 << 8 | minor,
|
|
3165
|
+
size: 0,
|
|
3166
|
+
blksize: 4096,
|
|
3167
|
+
blocks: 0,
|
|
3168
|
+
atime: now,
|
|
3169
|
+
mtime: now,
|
|
3170
|
+
ctime: now
|
|
3171
|
+
};
|
|
3009
3172
|
}
|
|
3010
|
-
function
|
|
3011
|
-
|
|
3012
|
-
return at >= 0 && Number.isSafeInteger(at) ? at : void 0;
|
|
3173
|
+
function nonblocking(stream) {
|
|
3174
|
+
return (stream.flags & O_NONBLOCK) !== 0 ? { nonblock: true } : void 0;
|
|
3013
3175
|
}
|
|
3014
|
-
function
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
done += got.length;
|
|
3021
|
-
}
|
|
3022
|
-
return done;
|
|
3176
|
+
function datesOf(real) {
|
|
3177
|
+
const dates = {};
|
|
3178
|
+
for (const [key, value2] of Object.entries(real ?? {}))
|
|
3179
|
+
if (/^[amc]time$/.test(key) && (typeof value2 === "string" || typeof value2 === "number"))
|
|
3180
|
+
dates[key] = new Date(value2);
|
|
3181
|
+
return dates;
|
|
3023
3182
|
}
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3183
|
+
var POLLIN, POLLOUT, POLLERR, POLLHUP, POLLRDNORM, POLLWRNORM, TCSETSF, O_NONBLOCK, SOCKET_MODE, PTY_PATH, TTY_PATH, TTY_NAME, SEALED_PATH, STRERROR, CLIPBOARD_PATH, O_CREAT2, O_EXCL, O_NOCTTY, O_TRUNC2, O_DIRECTORY, KILLED_BY_SIGPIPE, ProcessExit, SyscallError, KernelStreams;
|
|
3184
|
+
var init_kernel_streams = __esm({
|
|
3185
|
+
"src/process/kernel-streams.ts"() {
|
|
3186
|
+
"use strict";
|
|
3187
|
+
init_fd_metadata();
|
|
3188
|
+
init_wasi_errno();
|
|
3189
|
+
POLLIN = 1;
|
|
3190
|
+
POLLOUT = 4;
|
|
3191
|
+
POLLERR = 8;
|
|
3192
|
+
POLLHUP = 16;
|
|
3193
|
+
POLLRDNORM = 64;
|
|
3194
|
+
POLLWRNORM = 256;
|
|
3195
|
+
TCSETSF = 21508;
|
|
3196
|
+
O_NONBLOCK = 2048;
|
|
3197
|
+
SOCKET_MODE = 49663;
|
|
3198
|
+
PTY_PATH = /^\/dev\/(?:ptmx|pts\/(\d+))$/;
|
|
3199
|
+
TTY_PATH = /^\/dev\/tty\d+$/;
|
|
3200
|
+
TTY_NAME = /^tty\d+$/;
|
|
3201
|
+
SEALED_PATH = "/dev/sealed";
|
|
3202
|
+
STRERROR = {
|
|
3203
|
+
EACCES: "Permission denied",
|
|
3204
|
+
EIO: "I/O error",
|
|
3205
|
+
ENOTSUP: "Not supported",
|
|
3206
|
+
EOPNOTSUPP: "Not supported",
|
|
3207
|
+
EFBIG: "File too large",
|
|
3208
|
+
EILSEQ: "Illegal byte sequence",
|
|
3209
|
+
EINTR: "Interrupted system call"
|
|
3210
|
+
};
|
|
3211
|
+
CLIPBOARD_PATH = "/dev/clipboard";
|
|
3212
|
+
O_CREAT2 = 64;
|
|
3213
|
+
O_EXCL = 128;
|
|
3214
|
+
O_NOCTTY = 256;
|
|
3215
|
+
O_TRUNC2 = 512;
|
|
3216
|
+
O_DIRECTORY = 65536;
|
|
3217
|
+
KILLED_BY_SIGPIPE = 128 + 13;
|
|
3218
|
+
ProcessExit = class extends Error {
|
|
3219
|
+
status;
|
|
3220
|
+
constructor(status2) {
|
|
3221
|
+
super(`exit ${status2}`);
|
|
3222
|
+
this.status = status2;
|
|
3223
|
+
}
|
|
3224
|
+
};
|
|
3225
|
+
SyscallError = class extends Error {
|
|
3226
|
+
code;
|
|
3227
|
+
constructor(code2) {
|
|
3228
|
+
super(code2);
|
|
3229
|
+
this.code = code2;
|
|
3230
|
+
}
|
|
3231
|
+
};
|
|
3232
|
+
KernelStreams = class {
|
|
3233
|
+
refs = /* @__PURE__ */ new Map();
|
|
3234
|
+
socketRoot;
|
|
3235
|
+
sockets = 0;
|
|
3236
|
+
descriptions = /* @__PURE__ */ new Map();
|
|
3237
|
+
described = 0;
|
|
3238
|
+
Fs;
|
|
3239
|
+
sys;
|
|
3240
|
+
options;
|
|
3241
|
+
constructor(Fs, sys, options = {}) {
|
|
3242
|
+
this.Fs = Fs;
|
|
3243
|
+
this.sys = sys;
|
|
3244
|
+
this.options = options;
|
|
3245
|
+
}
|
|
3246
|
+
attach(stream, kfd, terminal) {
|
|
3247
|
+
this.refs.set(kfd, (this.refs.get(kfd) ?? 0) + 1);
|
|
3248
|
+
stream.sliccKernelFd = kfd;
|
|
3249
|
+
stream.stream_ops = this.ops(kfd, stream.stream_ops);
|
|
3250
|
+
if (terminal ?? this.sys.isatty?.(kfd) ?? false) stream.tty = this.ttyOps(kfd);
|
|
3251
|
+
else delete stream.tty;
|
|
3252
|
+
}
|
|
3253
|
+
attachSocket(stream, kfd) {
|
|
3254
|
+
this.attach(stream, kfd, false);
|
|
3255
|
+
stream.sliccKernelSocket = true;
|
|
3256
|
+
}
|
|
3257
|
+
socketStream(flags) {
|
|
3258
|
+
const fs = this.Fs;
|
|
3259
|
+
if (!fs.mount || !fs.createNode || !fs.createStream) {
|
|
3260
|
+
const stream = this.Fs.open("/dev/null", 2);
|
|
3261
|
+
stream.flags = flags;
|
|
3262
|
+
return stream;
|
|
3263
|
+
}
|
|
3264
|
+
const createNode = fs.createNode;
|
|
3265
|
+
this.socketRoot ??= fs.mount({ mount: () => createNode(null, "/", 16895, 0) }, {}, null);
|
|
3266
|
+
const ino = ++this.sockets;
|
|
3267
|
+
const node = fs.createNode(this.socketRoot, `socket:${ino}`, SOCKET_MODE, 0);
|
|
3268
|
+
const now = /* @__PURE__ */ new Date();
|
|
3269
|
+
const stat = { dev: 0, ino, mode: SOCKET_MODE, nlink: 1, uid: 0, gid: 0, rdev: 0, size: 0 };
|
|
3270
|
+
const times = { atime: now, mtime: now, ctime: now, blksize: 4096, blocks: 0 };
|
|
3271
|
+
node.node_ops = { getattr: () => ({ ...stat, ...times }) };
|
|
3272
|
+
return fs.createStream({ node, flags, seekable: false, position: 0, stream_ops: {} });
|
|
3273
|
+
}
|
|
3274
|
+
nameTerminal(stream) {
|
|
3275
|
+
const kfd = stream.sliccKernelFd;
|
|
3276
|
+
if (!stream.tty || kfd === void 0) return;
|
|
3277
|
+
const name2 = this.sys.ttyName?.(kfd);
|
|
3278
|
+
if (name2) this.nameStream(stream, name2);
|
|
3279
|
+
}
|
|
3280
|
+
nameStream(stream, name2) {
|
|
3281
|
+
stream.path = name2;
|
|
3282
|
+
this.ttyNode(name2);
|
|
3283
|
+
if (typeof this.Fs.stat !== "function") return;
|
|
3284
|
+
stream.stream_ops = { ...stream.stream_ops, getattr: () => this.Fs.stat?.(name2) ?? {} };
|
|
3285
|
+
}
|
|
3286
|
+
nameDevice(stream, kind) {
|
|
3287
|
+
this.nameStream(stream, kind === "sealed" ? SEALED_PATH : CLIPBOARD_PATH);
|
|
3288
|
+
}
|
|
3289
|
+
listSealed() {
|
|
3290
|
+
const fs = this.Fs;
|
|
3291
|
+
const { analyzePath, mkdev, makedev, registerDevice } = fs;
|
|
3292
|
+
if (!analyzePath || !mkdev || !makedev) return;
|
|
3293
|
+
const nodes = [
|
|
3294
|
+
[SEALED_PATH, 250, this.sys.openSealed],
|
|
3295
|
+
[CLIPBOARD_PATH, 251, this.sys.openClipboard]
|
|
3296
|
+
];
|
|
3297
|
+
for (const [path, minor, opener] of nodes) {
|
|
3298
|
+
if (!opener) continue;
|
|
3299
|
+
const dev = makedev.call(fs, 10, minor);
|
|
3300
|
+
registerDevice?.call(fs, dev, {
|
|
3301
|
+
open: (stream) => this.openNode(stream, path, opener)
|
|
3302
|
+
});
|
|
3303
|
+
if (analyzePath.call(fs, path).exists) continue;
|
|
3304
|
+
try {
|
|
3305
|
+
const node = mkdev.call(fs, path, dev);
|
|
3306
|
+
if (typeof node === "object" && node !== null) {
|
|
3307
|
+
const made = node;
|
|
3308
|
+
made.node_ops = { ...made.node_ops, getattr: () => sealedStat(minor) };
|
|
3309
|
+
}
|
|
3310
|
+
} catch {
|
|
3311
|
+
}
|
|
3312
|
+
}
|
|
3044
3313
|
}
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
["fd_pwrite", true]
|
|
3057
|
-
]) {
|
|
3058
|
-
const key = keyOf(namespace, name2, deps.glue);
|
|
3059
|
-
if (key !== void 0) {
|
|
3060
|
-
namespace[key] = positioned(namespace[key], write2, deps);
|
|
3314
|
+
openNode(stream, path, opener) {
|
|
3315
|
+
let kfd;
|
|
3316
|
+
try {
|
|
3317
|
+
kfd = this.call(() => opener.call(this.sys, stream.flags & 3));
|
|
3318
|
+
} catch (e) {
|
|
3319
|
+
this.Fs.closeStream(stream.fd);
|
|
3320
|
+
throw e;
|
|
3321
|
+
}
|
|
3322
|
+
this.attach(stream, kfd, false);
|
|
3323
|
+
this.nameStream(stream, path);
|
|
3324
|
+
if (path === CLIPBOARD_PATH) this.reportClose(kfd);
|
|
3061
3325
|
}
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
}
|
|
3085
|
-
const data = staging(Fs, length);
|
|
3086
|
-
let done = 0;
|
|
3087
|
-
try {
|
|
3088
|
-
if (kfd !== void 0) done = readInto(deps.sys, kfd, data, position);
|
|
3089
|
-
else {
|
|
3090
|
-
for (let got = 1; done < length && got > 0; done += got) {
|
|
3091
|
-
got = Fs.read(stream, data, done, length - done, position + done);
|
|
3326
|
+
reporting = /* @__PURE__ */ new Set();
|
|
3327
|
+
reportClose(kfd) {
|
|
3328
|
+
this.reporting.add(kfd);
|
|
3329
|
+
}
|
|
3330
|
+
quitting = false;
|
|
3331
|
+
atExit = false;
|
|
3332
|
+
failedAtExit = false;
|
|
3333
|
+
committed = /* @__PURE__ */ new Set();
|
|
3334
|
+
exiting() {
|
|
3335
|
+
this.atExit = true;
|
|
3336
|
+
return () => {
|
|
3337
|
+
this.atExit = false;
|
|
3338
|
+
};
|
|
3339
|
+
}
|
|
3340
|
+
commitStdout() {
|
|
3341
|
+
const kfd = this.Fs.getStream(1)?.sliccKernelFd;
|
|
3342
|
+
if (kfd === void 0 || !this.reporting.delete(kfd)) return;
|
|
3343
|
+
this.committed.add(kfd);
|
|
3344
|
+
try {
|
|
3345
|
+
this.sys.close(kfd);
|
|
3346
|
+
} catch (e) {
|
|
3347
|
+
if (e instanceof SyscallError) this.stdoutFailed(e.code);
|
|
3092
3348
|
}
|
|
3093
3349
|
}
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
}
|
|
3097
|
-
const size = Math.ceil(length / MAP_ALIGN) * MAP_ALIGN;
|
|
3098
|
-
const ptr = memalign(MAP_ALIGN, size);
|
|
3099
|
-
if (!ptr) throw new Fs.ErrnoError(wasiErrno("ENOMEM"));
|
|
3100
|
-
const target = new Uint8Array(memory.buffer, ptr, size);
|
|
3101
|
-
target.fill(0);
|
|
3102
|
-
target.set(data.subarray(0, done));
|
|
3103
|
-
return { ptr, allocated: true };
|
|
3104
|
-
};
|
|
3105
|
-
}
|
|
3106
|
-
function wasmMemory(instance, imports) {
|
|
3107
|
-
const isMemory = (v) => v instanceof WebAssembly.Memory;
|
|
3108
|
-
const exported = Object.values(instance.exports).find(isMemory);
|
|
3109
|
-
if (exported) return exported;
|
|
3110
|
-
for (const namespace of Object.values(imports)) {
|
|
3111
|
-
const found = Object.values(namespace ?? {}).find(isMemory);
|
|
3112
|
-
if (found) return found;
|
|
3113
|
-
}
|
|
3114
|
-
return void 0;
|
|
3115
|
-
}
|
|
3116
|
-
function fdOfPath(path, cwd) {
|
|
3117
|
-
const parts = [];
|
|
3118
|
-
for (const part of `${path.startsWith("/") ? "" : cwd}/${path}`.split("/")) {
|
|
3119
|
-
if (part === "" || part === ".") continue;
|
|
3120
|
-
if (part === "..") parts.pop();
|
|
3121
|
-
else parts.push(part);
|
|
3122
|
-
}
|
|
3123
|
-
const abs = `/${parts.join("/")}`;
|
|
3124
|
-
const std = ["/dev/stdin", "/dev/stdout", "/dev/stderr"].indexOf(abs);
|
|
3125
|
-
if (std >= 0) return std;
|
|
3126
|
-
const m = /^\/(?:dev|proc\/self)\/fd\/(\d+)$/.exec(abs);
|
|
3127
|
-
return m ? Number(m[1]) : void 0;
|
|
3128
|
-
}
|
|
3129
|
-
function syntheticAttr(mode, ino) {
|
|
3130
|
-
const now = /* @__PURE__ */ new Date();
|
|
3131
|
-
return {
|
|
3132
|
-
dev: 1,
|
|
3133
|
-
ino,
|
|
3134
|
-
mode,
|
|
3135
|
-
nlink: 1,
|
|
3136
|
-
uid: 0,
|
|
3137
|
-
gid: 0,
|
|
3138
|
-
rdev: 0,
|
|
3139
|
-
size: 0,
|
|
3140
|
-
atime: now,
|
|
3141
|
-
mtime: now,
|
|
3142
|
-
ctime: now,
|
|
3143
|
-
blksize: 4096,
|
|
3144
|
-
blocks: 0
|
|
3145
|
-
};
|
|
3146
|
-
}
|
|
3147
|
-
function describeFdDir(Fs) {
|
|
3148
|
-
let dir;
|
|
3149
|
-
try {
|
|
3150
|
-
dir = Fs.lookupPath?.("/proc/self/fd", { follow: true })?.node;
|
|
3151
|
-
} catch {
|
|
3152
|
-
return;
|
|
3153
|
-
}
|
|
3154
|
-
const ops = dir?.node_ops;
|
|
3155
|
-
const lookup2 = ops?.lookup;
|
|
3156
|
-
if (!dir || !lookup2 || ops.getattr) return;
|
|
3157
|
-
dir.node_ops = {
|
|
3158
|
-
...ops,
|
|
3159
|
-
getattr: () => syntheticAttr(DIR_MODE, 1),
|
|
3160
|
-
lookup: (parent, name2) => {
|
|
3161
|
-
const entry = lookup2(parent, name2);
|
|
3162
|
-
entry.node_ops = {
|
|
3163
|
-
...entry.node_ops,
|
|
3164
|
-
getattr: () => syntheticAttr(LINK_MODE, entry.id ?? 0)
|
|
3165
|
-
};
|
|
3166
|
-
return entry;
|
|
3167
|
-
}
|
|
3168
|
-
};
|
|
3169
|
-
}
|
|
3170
|
-
function useZeroDevices(Fs) {
|
|
3171
|
-
const { analyzePath, registerDevice, mkdev, makedev } = Fs;
|
|
3172
|
-
if (!analyzePath || !registerDevice || !mkdev || !makedev) return;
|
|
3173
|
-
const zeros = (_s, buffer, offset, length) => {
|
|
3174
|
-
buffer.fill(0, offset, offset + length);
|
|
3175
|
-
return length;
|
|
3176
|
-
};
|
|
3177
|
-
const devices = [
|
|
3178
|
-
["/dev/zero", 5, (_s, _b, _o, length) => length],
|
|
3179
|
-
[
|
|
3180
|
-
"/dev/full",
|
|
3181
|
-
7,
|
|
3182
|
-
(_s, _b, _o, length) => {
|
|
3183
|
-
if (length > 0) throw new Fs.ErrnoError(wasiErrno("ENOSPC"));
|
|
3184
|
-
return 0;
|
|
3350
|
+
exitStatus(status2) {
|
|
3351
|
+
return this.failedAtExit && status2 === 0 ? 1 : status2;
|
|
3185
3352
|
}
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
}
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
} catch {
|
|
3202
|
-
}
|
|
3203
|
-
try {
|
|
3204
|
-
symlink.call(Fs, `/proc/self/fd/${fd}`, `/dev/${name2}`);
|
|
3205
|
-
} catch {
|
|
3206
|
-
}
|
|
3207
|
-
}
|
|
3208
|
-
}
|
|
3209
|
-
function useDevFd(Fs) {
|
|
3210
|
-
if (typeof Fs.open !== "function") return;
|
|
3211
|
-
try {
|
|
3212
|
-
Fs.symlink?.("/proc/self/fd", "/dev/fd");
|
|
3213
|
-
} catch {
|
|
3214
|
-
}
|
|
3215
|
-
linkStdio(Fs);
|
|
3216
|
-
describeFdDir(Fs);
|
|
3217
|
-
const fdOf = (path) => typeof path === "string" ? fdOfPath(path, Fs.cwd()) : void 0;
|
|
3218
|
-
const target = (fd) => {
|
|
3219
|
-
const stream = Fs.getStream(fd);
|
|
3220
|
-
if (!stream) throw new Fs.ErrnoError(wasiErrno("EBADF"));
|
|
3221
|
-
return stream;
|
|
3222
|
-
};
|
|
3223
|
-
const open = Fs.open.bind(Fs);
|
|
3224
|
-
Fs.open = (path, flags, mode) => {
|
|
3225
|
-
const fd = fdOf(path);
|
|
3226
|
-
if (fd === void 0) return open(path, flags, mode);
|
|
3227
|
-
const copy2 = Fs.dupStream(target(fd), -1);
|
|
3228
|
-
setCloseOnExec(copy2, typeof flags === "number" && (flags & O_CLOEXEC) !== 0);
|
|
3229
|
-
return copy2;
|
|
3230
|
-
};
|
|
3231
|
-
const { stat, fstat } = Fs;
|
|
3232
|
-
if (typeof stat !== "function" || typeof fstat !== "function") return;
|
|
3233
|
-
Fs.stat = (path, dontFollow) => {
|
|
3234
|
-
const fd = dontFollow ? void 0 : fdOf(path);
|
|
3235
|
-
if (fd === void 0) return stat.call(Fs, path, dontFollow);
|
|
3236
|
-
target(fd);
|
|
3237
|
-
return fstat.call(Fs, fd);
|
|
3238
|
-
};
|
|
3239
|
-
}
|
|
3240
|
-
function pinRootKind() {
|
|
3241
|
-
pinnedRoot = rootKind();
|
|
3242
|
-
}
|
|
3243
|
-
function mountTable(mounts = []) {
|
|
3244
|
-
const root = pinnedRoot ?? rootKind();
|
|
3245
|
-
const lines = [`${root} / ${root} rw 0 0`, "devfs /dev devfs rw 0 0", "proc /proc proc rw 0 0"];
|
|
3246
|
-
for (const m of mounts) {
|
|
3247
|
-
const options = Object.entries(m.options).map(([k, v]) => v === "" ? k : `${k}=${v}`);
|
|
3248
|
-
if (m.state !== "ok") options.push(m.state);
|
|
3249
|
-
const access = options.includes("ro") ? [] : ["rw"];
|
|
3250
|
-
lines.push(
|
|
3251
|
-
`${field(m.source)} ${field(m.target)} ${m.type} ${[...access, ...options].join(",")} 0 0`
|
|
3252
|
-
);
|
|
3253
|
-
}
|
|
3254
|
-
return `${lines.join("\n")}
|
|
3353
|
+
reportedClose(stream, kfd) {
|
|
3354
|
+
try {
|
|
3355
|
+
this.sys.close(kfd);
|
|
3356
|
+
} catch (e) {
|
|
3357
|
+
if (this.quitting && stream.fd === 1 && e instanceof SyscallError) this.stdoutFailed(e.code);
|
|
3358
|
+
this.call(() => {
|
|
3359
|
+
throw e;
|
|
3360
|
+
});
|
|
3361
|
+
}
|
|
3362
|
+
}
|
|
3363
|
+
stdoutFailed(code2) {
|
|
3364
|
+
this.failedAtExit = true;
|
|
3365
|
+
const stderr = this.Fs.getStream(2)?.sliccKernelFd;
|
|
3366
|
+
if (stderr === void 0) return;
|
|
3367
|
+
const line = `${this.options.program ?? "program"}: write error: ${STRERROR[code2] ?? code2}
|
|
3255
3368
|
`;
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
}
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
}
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
}
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3369
|
+
try {
|
|
3370
|
+
this.sys.write(stderr, new TextEncoder().encode(line));
|
|
3371
|
+
} catch {
|
|
3372
|
+
}
|
|
3373
|
+
}
|
|
3374
|
+
creatingTerminal = false;
|
|
3375
|
+
useTerminalNodes() {
|
|
3376
|
+
const fs = this.Fs;
|
|
3377
|
+
const { lookupNode, readdir, getPath, mkdev, makedev } = fs;
|
|
3378
|
+
const ttyNames = this.sys.ttyNames?.bind(this.sys);
|
|
3379
|
+
if (!lookupNode || !readdir || !getPath || !mkdev || !makedev || !ttyNames) return;
|
|
3380
|
+
fs.lookupNode = (parent, name2) => {
|
|
3381
|
+
try {
|
|
3382
|
+
return lookupNode.call(fs, parent, name2);
|
|
3383
|
+
} catch (e) {
|
|
3384
|
+
const path = `/dev/${name2}`;
|
|
3385
|
+
if (this.creatingTerminal || !TTY_NAME.test(name2) || getPath.call(fs, parent) !== "/dev")
|
|
3386
|
+
throw e;
|
|
3387
|
+
if (!ttyNames().includes(path)) throw e;
|
|
3388
|
+
this.creatingTerminal = true;
|
|
3389
|
+
try {
|
|
3390
|
+
mkdev.call(fs, path, makedev.call(fs, 6, 0));
|
|
3391
|
+
} finally {
|
|
3392
|
+
this.creatingTerminal = false;
|
|
3393
|
+
}
|
|
3394
|
+
return lookupNode.call(fs, parent, name2);
|
|
3395
|
+
}
|
|
3396
|
+
};
|
|
3397
|
+
fs.readdir = (path) => {
|
|
3398
|
+
const names = readdir.call(fs, path);
|
|
3399
|
+
if (path.replace(/\/+$/, "") !== "/dev") return names;
|
|
3400
|
+
const missing2 = ttyNames().map((tty) => tty.slice("/dev/".length)).filter((name2) => TTY_NAME.test(name2) && !names.includes(name2));
|
|
3401
|
+
return [...names, ...missing2];
|
|
3402
|
+
};
|
|
3403
|
+
}
|
|
3404
|
+
ttyNode(name2) {
|
|
3405
|
+
const { analyzePath, mkdev, makedev } = this.Fs;
|
|
3406
|
+
if (!TTY_PATH.test(name2) || !analyzePath || !mkdev || !makedev) return;
|
|
3407
|
+
if (!analyzePath.call(this.Fs, name2).exists)
|
|
3408
|
+
mkdev.call(this.Fs, name2, makedev.call(this.Fs, 6, 0));
|
|
3409
|
+
}
|
|
3410
|
+
ttyOps(kfd) {
|
|
3411
|
+
return {
|
|
3412
|
+
ops: {
|
|
3413
|
+
ioctl_tcgets: () => this.call(() => this.sys.tcgets?.(kfd)),
|
|
3414
|
+
ioctl_tcsets: (_tty, op, termios) => this.call(() => {
|
|
3415
|
+
this.sys.tcsets?.(kfd, termios, op === TCSETSF);
|
|
3416
|
+
return 0;
|
|
3417
|
+
}),
|
|
3418
|
+
ioctl_tiocgwinsz: () => this.call(() => this.sys.winsize?.(kfd) ?? [24, 80]),
|
|
3419
|
+
fsync: () => {
|
|
3420
|
+
}
|
|
3421
|
+
}
|
|
3422
|
+
};
|
|
3423
|
+
}
|
|
3424
|
+
attachFile(stream, kfd) {
|
|
3425
|
+
this.attach(stream, kfd, false);
|
|
3426
|
+
stream.sliccKernelFile = true;
|
|
3427
|
+
stream.stream_ops = {
|
|
3428
|
+
...stream.stream_ops,
|
|
3429
|
+
llseek: (_s, offset, whence) => this.call(() => this.sys.seek(kfd, offset, whence)),
|
|
3430
|
+
fsync: () => this.call(() => {
|
|
3431
|
+
this.sys.flush(kfd);
|
|
3432
|
+
return 0;
|
|
3433
|
+
})
|
|
3434
|
+
};
|
|
3435
|
+
}
|
|
3436
|
+
sizeFromKernel(stream, kfd) {
|
|
3437
|
+
const { size, fdStat: fdStat2 } = this.sys;
|
|
3438
|
+
if (!size) return;
|
|
3439
|
+
const node = stream.node;
|
|
3440
|
+
this.describe(stream, `${stream.path ?? ""}:${++this.described}`, () => {
|
|
3441
|
+
const base = node.node_ops?.getattr?.(node);
|
|
3442
|
+
const live = this.call(() => size.call(this.sys, kfd));
|
|
3443
|
+
const real = fdStat2 && this.call(() => fdStat2.call(this.sys, kfd));
|
|
3444
|
+
return { ...base, ...real, ...datesOf(real), size: live };
|
|
3445
|
+
});
|
|
3446
|
+
}
|
|
3447
|
+
describe(stream, name2, getattr) {
|
|
3448
|
+
if (this.descriptions.size === 0) this.useDescriptions();
|
|
3449
|
+
this.descriptions.set(name2, getattr);
|
|
3450
|
+
stream.path = name2;
|
|
3451
|
+
stream.stream_ops = { ...stream.stream_ops, getattr };
|
|
3452
|
+
}
|
|
3453
|
+
useDescriptions() {
|
|
3454
|
+
const fs = this.Fs;
|
|
3455
|
+
for (const name2 of ["stat", "lstat"]) {
|
|
3456
|
+
const original = fs[name2];
|
|
3457
|
+
if (typeof original !== "function") continue;
|
|
3458
|
+
fs[name2] = (path, ...rest2) => {
|
|
3459
|
+
const getattr = this.descriptions.get(path);
|
|
3460
|
+
return getattr ? getattr() : original.call(fs, path, ...rest2);
|
|
3461
|
+
};
|
|
3462
|
+
}
|
|
3463
|
+
}
|
|
3464
|
+
useKernelFdMetadata() {
|
|
3465
|
+
useKernelFdMetadata(this.Fs, this.sys, this.call.bind(this));
|
|
3466
|
+
}
|
|
3467
|
+
useControllingTerminal() {
|
|
3468
|
+
if (typeof this.Fs.open !== "function") return;
|
|
3469
|
+
this.usePtyPaths();
|
|
3470
|
+
this.useTerminalNodes();
|
|
3471
|
+
this.listSealed();
|
|
3472
|
+
const open = this.Fs.open.bind(this.Fs);
|
|
3473
|
+
this.Fs.open = (path, flags, mode) => {
|
|
3474
|
+
const device2 = typeof path === "string" ? this.devicePath(path) : void 0;
|
|
3475
|
+
if (device2 !== void 0 && TTY_PATH.test(device2) && !this.terminalExists(device2)) {
|
|
3476
|
+
throw new this.Fs.ErrnoError(wasiErrno("ENOENT"));
|
|
3477
|
+
}
|
|
3478
|
+
const pty = this.openPty(open, path, flags, mode) ?? this.openSealed(open, path, flags, mode) ?? this.openClipboard(open, path, flags, mode);
|
|
3479
|
+
if (pty) return pty;
|
|
3480
|
+
this.refuseExclusiveLink(path, flags);
|
|
3481
|
+
const stream = this.openRacing(open, path, flags, mode);
|
|
3482
|
+
if (!stream.tty) return stream;
|
|
3483
|
+
if (stream.path === "/dev/tty" && this.sys.openTty) {
|
|
3484
|
+
let kfd;
|
|
3485
|
+
try {
|
|
3486
|
+
kfd = this.call(() => this.sys.openTty?.());
|
|
3487
|
+
} catch (e) {
|
|
3488
|
+
this.Fs.closeStream(stream.fd);
|
|
3489
|
+
throw e;
|
|
3490
|
+
}
|
|
3491
|
+
this.attach(stream, kfd, true);
|
|
3492
|
+
return stream;
|
|
3493
|
+
}
|
|
3494
|
+
let named;
|
|
3495
|
+
try {
|
|
3496
|
+
named = stream.path ? this.openNamedTerminal(stream.path) : void 0;
|
|
3497
|
+
} catch (e) {
|
|
3498
|
+
this.Fs.closeStream(stream.fd);
|
|
3499
|
+
throw e;
|
|
3500
|
+
}
|
|
3501
|
+
if (named !== void 0) {
|
|
3502
|
+
this.attach(stream, named, true);
|
|
3503
|
+
return stream;
|
|
3504
|
+
}
|
|
3505
|
+
const terminal = this.stdioTerminal();
|
|
3506
|
+
if (terminal !== void 0) this.attach(stream, terminal, true);
|
|
3507
|
+
return stream;
|
|
3508
|
+
};
|
|
3509
|
+
}
|
|
3510
|
+
openRacing(open, path, flags, mode) {
|
|
3511
|
+
try {
|
|
3512
|
+
return open(path, flags, mode);
|
|
3513
|
+
} catch (err) {
|
|
3514
|
+
const lost = err.errno === wasiErrno("EEXIST") && !(flags & O_EXCL);
|
|
3515
|
+
if (!lost) throw err;
|
|
3516
|
+
return open(path, flags, mode);
|
|
3517
|
+
}
|
|
3518
|
+
}
|
|
3519
|
+
refuseExclusiveLink(path, flags) {
|
|
3520
|
+
if ((flags & (O_CREAT2 | O_EXCL)) !== (O_CREAT2 | O_EXCL)) return;
|
|
3521
|
+
let mode = 0;
|
|
3522
|
+
try {
|
|
3523
|
+
mode = this.Fs.stat?.(path, true)?.mode ?? 0;
|
|
3524
|
+
} catch {
|
|
3525
|
+
}
|
|
3526
|
+
if ((mode & 61440) === 40960) throw new this.Fs.ErrnoError(wasiErrno("EEXIST"));
|
|
3527
|
+
}
|
|
3528
|
+
openPty(open, path, flags, mode) {
|
|
3529
|
+
const pts = /^\/dev\/pts\/(\d+)$/.exec(path);
|
|
3530
|
+
if (path !== "/dev/ptmx" && !pts) return void 0;
|
|
3531
|
+
const { openPty, openPts } = this.sys;
|
|
3532
|
+
if (!openPty || !openPts) return void 0;
|
|
3533
|
+
const kfd = this.call(
|
|
3534
|
+
() => pts ? openPts(Number(pts[1]), (flags & O_NOCTTY) !== 0) : openPty()
|
|
3535
|
+
);
|
|
3536
|
+
return this.vessel(open, kfd, { path, flags, mode }, true);
|
|
3537
|
+
}
|
|
3538
|
+
openSealed(open, path, flags, mode) {
|
|
3539
|
+
const { openSealed } = this.sys;
|
|
3540
|
+
if (path !== SEALED_PATH || !openSealed) return void 0;
|
|
3541
|
+
const kfd = this.call(() => openSealed.call(this.sys, flags & 3));
|
|
3542
|
+
return this.vessel(open, kfd, { path, flags, mode }, false);
|
|
3543
|
+
}
|
|
3544
|
+
openClipboard(open, path, flags, mode) {
|
|
3545
|
+
const { openClipboard } = this.sys;
|
|
3546
|
+
if (path !== CLIPBOARD_PATH || !openClipboard) return void 0;
|
|
3547
|
+
if (flags & O_DIRECTORY) throw new this.Fs.ErrnoError(wasiErrno("ENOTDIR"));
|
|
3548
|
+
const kfd = this.call(() => openClipboard.call(this.sys, flags & 3));
|
|
3549
|
+
try {
|
|
3550
|
+
const stream = this.vessel(open, kfd, { path, flags, mode }, false);
|
|
3551
|
+
this.reportClose(kfd);
|
|
3552
|
+
return stream;
|
|
3553
|
+
} catch (e) {
|
|
3554
|
+
this.sys.clipboardAbort?.(kfd);
|
|
3555
|
+
this.sys.close(kfd);
|
|
3556
|
+
throw e;
|
|
3557
|
+
}
|
|
3558
|
+
}
|
|
3559
|
+
vessel(open, kfd, at, terminal) {
|
|
3560
|
+
let stream;
|
|
3561
|
+
try {
|
|
3562
|
+
stream = open("/dev/null", at.flags & ~(O_CREAT2 | O_EXCL | O_TRUNC2), at.mode);
|
|
3563
|
+
} catch (e) {
|
|
3564
|
+
this.sys.close(kfd);
|
|
3565
|
+
throw e;
|
|
3566
|
+
}
|
|
3567
|
+
this.attach(stream, kfd, terminal);
|
|
3568
|
+
this.nameStream(stream, at.path);
|
|
3569
|
+
return stream;
|
|
3570
|
+
}
|
|
3571
|
+
usePtyPaths() {
|
|
3572
|
+
const fs = this.Fs;
|
|
3573
|
+
for (const name2 of ["chown", "lchown", "chmod", "lchmod"]) {
|
|
3574
|
+
const original = fs[name2];
|
|
3575
|
+
if (typeof original !== "function") continue;
|
|
3576
|
+
fs[name2] = (path, ...rest2) => isPtyPath(path) ? this.existingPty(path) : original.call(fs, path, ...rest2);
|
|
3577
|
+
}
|
|
3578
|
+
for (const name2 of ["stat", "lstat"]) {
|
|
3579
|
+
const original = fs[name2];
|
|
3580
|
+
if (typeof original !== "function") continue;
|
|
3581
|
+
fs[name2] = (path, ...rest2) => {
|
|
3582
|
+
if (path === SEALED_PATH && this.sys.openSealed) return sealedStat();
|
|
3583
|
+
if (path === CLIPBOARD_PATH && this.sys.openClipboard) return sealedStat(251);
|
|
3584
|
+
const owned = this.ownedTty(path);
|
|
3585
|
+
if (owned && isPtyPath(path)) return this.owned(path, ptyStat(path));
|
|
3586
|
+
if (!isPtyPath(path)) {
|
|
3587
|
+
const st = original.call(fs, path, ...rest2);
|
|
3588
|
+
return owned && TTY_PATH.test(path) ? this.owned(path, st) : st;
|
|
3589
|
+
}
|
|
3590
|
+
this.existingPty(path);
|
|
3591
|
+
return ptyStat(path);
|
|
3592
|
+
};
|
|
3593
|
+
}
|
|
3594
|
+
}
|
|
3595
|
+
ownedTty(path) {
|
|
3596
|
+
return this.options.owners === true && this.sys.ttyOwner !== void 0 && path !== "/dev/ptmx";
|
|
3597
|
+
}
|
|
3598
|
+
owned(path, st) {
|
|
3599
|
+
const ask = this.sys.ttyOwner;
|
|
3600
|
+
const owner = this.call(() => ask.call(this.sys, path));
|
|
3601
|
+
if (!owner) return st;
|
|
3602
|
+
const mode = st.mode & ~4095 | (owner.mode ?? 400);
|
|
3603
|
+
return { ...st, uid: owner.uid, gid: owner.gid, mode };
|
|
3604
|
+
}
|
|
3605
|
+
existingPty(path) {
|
|
3606
|
+
const n = PTY_PATH.exec(path)?.[1];
|
|
3607
|
+
const exists = n === void 0 ? this.sys.openPty !== void 0 : this.sys.ptyNumbers?.().includes(Number(n)) ?? false;
|
|
3608
|
+
if (!exists) throw new this.Fs.ErrnoError(wasiErrno("ENOENT"));
|
|
3609
|
+
}
|
|
3610
|
+
devicePath(path) {
|
|
3611
|
+
const name2 = path.slice(path.lastIndexOf("/") + 1);
|
|
3612
|
+
if (!TTY_NAME.test(name2)) return void 0;
|
|
3613
|
+
const { lookupPath, cwd } = this.Fs;
|
|
3614
|
+
const absolute = path.startsWith("/") ? path : `${cwd?.call(this.Fs) ?? "/"}/${path}`;
|
|
3615
|
+
const dir = absolute.slice(0, absolute.lastIndexOf("/")) || "/";
|
|
3616
|
+
try {
|
|
3617
|
+
const real = lookupPath?.call(this.Fs, dir, { follow: true }).path ?? dir;
|
|
3618
|
+
return `${real === "/" ? "" : real}/${name2}`;
|
|
3619
|
+
} catch {
|
|
3620
|
+
return absolute;
|
|
3621
|
+
}
|
|
3622
|
+
}
|
|
3623
|
+
terminalExists(path) {
|
|
3624
|
+
const { analyzePath } = this.Fs;
|
|
3625
|
+
return analyzePath?.call(this.Fs, path).exists ?? true;
|
|
3626
|
+
}
|
|
3627
|
+
openNamedTerminal(path) {
|
|
3628
|
+
const { openTty } = this.sys;
|
|
3629
|
+
if (!openTty) return void 0;
|
|
3630
|
+
try {
|
|
3631
|
+
return openTty.call(this.sys, path);
|
|
3632
|
+
} catch (e) {
|
|
3633
|
+
if (e instanceof SyscallError && e.code === "ENXIO") return void 0;
|
|
3634
|
+
return this.call(() => {
|
|
3635
|
+
throw e;
|
|
3636
|
+
});
|
|
3637
|
+
}
|
|
3638
|
+
}
|
|
3639
|
+
stdioTerminal() {
|
|
3640
|
+
for (const fd of [0, 1, 2]) {
|
|
3641
|
+
const stream = this.Fs.getStream(fd);
|
|
3642
|
+
if (stream?.sliccKernelFd !== void 0 && stream.tty) return stream.sliccKernelFd;
|
|
3643
|
+
}
|
|
3644
|
+
return void 0;
|
|
3645
|
+
}
|
|
3646
|
+
usePipes(pipefs) {
|
|
3647
|
+
const createPipe = pipefs.createPipe.bind(pipefs);
|
|
3648
|
+
pipefs.createPipe = () => {
|
|
3649
|
+
const [read2, write2] = this.call(() => this.sys.pipe());
|
|
3650
|
+
let fds;
|
|
3651
|
+
try {
|
|
3652
|
+
fds = createPipe();
|
|
3653
|
+
} catch (e) {
|
|
3654
|
+
for (const kfd of [read2, write2]) {
|
|
3655
|
+
try {
|
|
3656
|
+
this.sys.close(kfd);
|
|
3657
|
+
} catch {
|
|
3658
|
+
}
|
|
3659
|
+
}
|
|
3660
|
+
throw e;
|
|
3661
|
+
}
|
|
3662
|
+
this.attach(this.Fs.getStream(fds.readable_fd), read2, false);
|
|
3663
|
+
this.attach(this.Fs.getStream(fds.writable_fd), write2, false);
|
|
3664
|
+
return fds;
|
|
3665
|
+
};
|
|
3666
|
+
}
|
|
3667
|
+
restarting(syscall) {
|
|
3668
|
+
for (; ; ) {
|
|
3669
|
+
try {
|
|
3670
|
+
return syscall();
|
|
3671
|
+
} catch (e) {
|
|
3672
|
+
if (!(e instanceof SyscallError && e.code === "EINTR" && this.options.restartable?.())) {
|
|
3673
|
+
throw e;
|
|
3674
|
+
}
|
|
3675
|
+
}
|
|
3676
|
+
}
|
|
3677
|
+
}
|
|
3678
|
+
call(syscall) {
|
|
3679
|
+
try {
|
|
3680
|
+
return syscall();
|
|
3681
|
+
} catch (e) {
|
|
3682
|
+
if (e instanceof SyscallError) throw new this.Fs.ErrnoError(wasiErrno(e.code));
|
|
3683
|
+
throw e;
|
|
3684
|
+
}
|
|
3685
|
+
}
|
|
3686
|
+
ops(kfd, base) {
|
|
3687
|
+
return {
|
|
3688
|
+
...base,
|
|
3689
|
+
llseek: () => this.call(() => {
|
|
3690
|
+
throw new SyscallError("ESPIPE");
|
|
3691
|
+
}),
|
|
3692
|
+
read: (s, buffer, offset, length) => this.call(() => {
|
|
3693
|
+
const bytes = this.restarting(() => this.sys.read(kfd, length, nonblocking(s)));
|
|
3694
|
+
buffer.set(bytes, offset);
|
|
3695
|
+
return bytes.length;
|
|
3696
|
+
}),
|
|
3697
|
+
write: (s, buffer, offset, length) => {
|
|
3698
|
+
try {
|
|
3699
|
+
const bytes = buffer.slice(offset, offset + length);
|
|
3700
|
+
return this.restarting(() => this.sys.write(kfd, bytes, nonblocking(s)));
|
|
3701
|
+
} catch (e) {
|
|
3702
|
+
if (e instanceof SyscallError && e.code === "EPIPE" && !this.options.sigpipe?.()) {
|
|
3703
|
+
throw new ProcessExit(KILLED_BY_SIGPIPE);
|
|
3704
|
+
}
|
|
3705
|
+
return this.call(() => {
|
|
3706
|
+
throw e;
|
|
3707
|
+
});
|
|
3708
|
+
}
|
|
3709
|
+
},
|
|
3710
|
+
fsync: () => 0,
|
|
3711
|
+
poll: () => {
|
|
3712
|
+
const state = this.call(() => this.sys.poll(kfd));
|
|
3713
|
+
let mask = 0;
|
|
3714
|
+
if (state.readable) mask |= POLLIN | POLLRDNORM;
|
|
3715
|
+
if (state.writable) mask |= POLLOUT | POLLWRNORM;
|
|
3716
|
+
if (state.hangup) mask |= state.readable ? POLLHUP : POLLERR;
|
|
3717
|
+
return mask;
|
|
3718
|
+
},
|
|
3719
|
+
dup: (stream) => {
|
|
3720
|
+
base.dup?.(stream);
|
|
3721
|
+
this.refs.set(kfd, (this.refs.get(kfd) ?? 0) + 1);
|
|
3722
|
+
},
|
|
3723
|
+
close: (stream) => {
|
|
3724
|
+
if (this.atExit && stream.fd === 2 && this.reporting.size > 0) this.commitStdout();
|
|
3725
|
+
try {
|
|
3726
|
+
base.close?.(stream);
|
|
3727
|
+
} catch {
|
|
3728
|
+
}
|
|
3729
|
+
const left = (this.refs.get(kfd) ?? 1) - 1;
|
|
3730
|
+
if (left > 0) {
|
|
3731
|
+
this.refs.set(kfd, left);
|
|
3732
|
+
return;
|
|
3733
|
+
}
|
|
3734
|
+
this.refs.delete(kfd);
|
|
3735
|
+
if (this.committed.size > 0 && this.committed.delete(kfd)) return;
|
|
3736
|
+
if (this.reporting.size > 0 && this.reporting.delete(kfd)) {
|
|
3737
|
+
this.reportedClose(stream, kfd);
|
|
3738
|
+
return;
|
|
3739
|
+
}
|
|
3740
|
+
try {
|
|
3741
|
+
this.sys.close(kfd);
|
|
3742
|
+
} catch {
|
|
3743
|
+
}
|
|
3744
|
+
}
|
|
3745
|
+
};
|
|
3376
3746
|
}
|
|
3377
|
-
return own(olddirfd, oldpath, newdirfd, newpath, flags);
|
|
3378
|
-
},
|
|
3379
|
-
true
|
|
3380
|
-
);
|
|
3381
|
-
}
|
|
3382
|
-
function kernelChdir(Fs) {
|
|
3383
|
-
const { chdir, lookupPath, ErrnoError } = Fs;
|
|
3384
|
-
if (!chdir || !lookupPath || !ErrnoError) return;
|
|
3385
|
-
Fs.chdir = (path) => {
|
|
3386
|
-
const { node } = lookupPath.call(Fs, path, { follow: true });
|
|
3387
|
-
const directory = Fs.isDir?.(node.mode) === true;
|
|
3388
|
-
const bridge = node.live && directory ? node.mount.opts.bridge : void 0;
|
|
3389
|
-
try {
|
|
3390
|
-
bridge?.access?.(liveNodePath(node), X_ACCESS, "eaccess", false);
|
|
3391
|
-
} catch (err) {
|
|
3392
|
-
throw new ErrnoError(errnoOf(err));
|
|
3393
|
-
}
|
|
3394
|
-
chdir.call(Fs, path);
|
|
3395
|
-
};
|
|
3396
|
-
}
|
|
3397
|
-
function linuxDevices(Fs) {
|
|
3398
|
-
Fs.ignorePermissions = true;
|
|
3399
|
-
kernelChdir(Fs);
|
|
3400
|
-
const { chmod } = Fs;
|
|
3401
|
-
if (!chmod) return;
|
|
3402
|
-
for (const [path, mode] of DEVICE_MODES) {
|
|
3403
|
-
try {
|
|
3404
|
-
chmod.call(Fs, path, mode);
|
|
3405
|
-
} catch {
|
|
3406
|
-
}
|
|
3407
|
-
}
|
|
3408
|
-
}
|
|
3409
|
-
var O_CLOEXEC, FD_CLOEXEC, F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_DUPFD_CLOEXEC, tracked, IMPORT_NAMES, EBADF, AT_SYMLINK_NOFOLLOW, EMSCRIPTEN_EPERM, O_PATH2, LITERALS, UTIME_NOW, UTIME_OMIT, PROT_WRITE, MAP_PRIVATE, MAP_TYPE, O_WRONLY, MAP_ALIGN, DIR_MODE, LINK_MODE, CHAR_DEVICE, O_ACCMODE2, O_CREAT2, field, pinnedRoot, rootKind, NAME, AT_FDCWD, AT_EACCESS, W_ACCESS, X_ACCESS, AT_SYMLINK_FOLLOW, DEVICE_MODES;
|
|
3410
|
-
var init_process_fds = __esm({
|
|
3411
|
-
"src/process/process-fds.ts"() {
|
|
3412
|
-
"use strict";
|
|
3413
|
-
init_loopback_names();
|
|
3414
|
-
init_live_vfs_fs();
|
|
3415
|
-
init_process_pty();
|
|
3416
|
-
init_wasi_errno();
|
|
3417
|
-
O_CLOEXEC = 524288;
|
|
3418
|
-
FD_CLOEXEC = 1;
|
|
3419
|
-
F_DUPFD = 0;
|
|
3420
|
-
F_GETFD = 1;
|
|
3421
|
-
F_SETFD = 2;
|
|
3422
|
-
F_GETFL = 3;
|
|
3423
|
-
F_DUPFD_CLOEXEC = 1030;
|
|
3424
|
-
tracked = /* @__PURE__ */ new WeakSet();
|
|
3425
|
-
IMPORT_NAMES = {
|
|
3426
|
-
fcntl: "__syscall_fcntl64",
|
|
3427
|
-
pipe2: "__syscall_pipe2",
|
|
3428
|
-
dup3: "__syscall_dup3",
|
|
3429
|
-
socket: "__syscall_socket",
|
|
3430
|
-
accept4: "__syscall_accept4",
|
|
3431
|
-
ioctl: "__syscall_ioctl",
|
|
3432
|
-
setitimer: "_setitimer_js"
|
|
3433
|
-
};
|
|
3434
|
-
EBADF = 8;
|
|
3435
|
-
AT_SYMLINK_NOFOLLOW = 256;
|
|
3436
|
-
EMSCRIPTEN_EPERM = 63;
|
|
3437
|
-
O_PATH2 = 2097152;
|
|
3438
|
-
LITERALS = {
|
|
3439
|
-
openat: "__syscall_openat",
|
|
3440
|
-
mkdirat: "__syscall_mkdirat",
|
|
3441
|
-
mknodat: "__syscall_mknodat",
|
|
3442
|
-
umask: "__syscall_umask",
|
|
3443
|
-
faccessat: "__syscall_faccessat",
|
|
3444
|
-
linkat: "__syscall_linkat",
|
|
3445
|
-
utimensat: "__syscall_utimensat",
|
|
3446
|
-
getppid: "slicc_getppid_js",
|
|
3447
|
-
resizeHeap: "emscripten_resize_heap",
|
|
3448
|
-
fdWrite: "fd_write",
|
|
3449
|
-
fdRead: "fd_read",
|
|
3450
|
-
sleepMs: "slicc_sleep_ms"
|
|
3451
3747
|
};
|
|
3452
|
-
UTIME_NOW = 1073741823;
|
|
3453
|
-
UTIME_OMIT = 1073741822;
|
|
3454
|
-
PROT_WRITE = 2;
|
|
3455
|
-
MAP_PRIVATE = 2;
|
|
3456
|
-
MAP_TYPE = 15;
|
|
3457
|
-
O_WRONLY = 1;
|
|
3458
|
-
MAP_ALIGN = 65536;
|
|
3459
|
-
DIR_MODE = 16749;
|
|
3460
|
-
LINK_MODE = 41408;
|
|
3461
|
-
CHAR_DEVICE = 8630;
|
|
3462
|
-
O_ACCMODE2 = 3;
|
|
3463
|
-
O_CREAT2 = 64;
|
|
3464
|
-
field = (text) => (text || "none").replace(/[\s\\]/g, (c) => `\\${c.charCodeAt(0).toString(8).padStart(3, "0")}`);
|
|
3465
|
-
rootKind = () => globalThis.navigator?.storage ? "opfs" : "memory";
|
|
3466
|
-
NAME = /^[a-z_][a-z0-9_-]*$/i;
|
|
3467
|
-
AT_FDCWD = -100;
|
|
3468
|
-
AT_EACCESS = 512;
|
|
3469
|
-
W_ACCESS = 2;
|
|
3470
|
-
X_ACCESS = 1;
|
|
3471
|
-
AT_SYMLINK_FOLLOW = 1024;
|
|
3472
|
-
DEVICE_MODES = [
|
|
3473
|
-
["/", 493],
|
|
3474
|
-
["/dev", 493],
|
|
3475
|
-
["/dev/null", 438],
|
|
3476
|
-
["/dev/zero", 438],
|
|
3477
|
-
["/dev/full", 438],
|
|
3478
|
-
["/dev/random", 438],
|
|
3479
|
-
["/dev/urandom", 438],
|
|
3480
|
-
["/dev/tty", 438],
|
|
3481
|
-
["/dev/shm", 1023]
|
|
3482
|
-
];
|
|
3483
3748
|
}
|
|
3484
3749
|
});
|
|
3485
3750
|
|
|
@@ -3539,7 +3804,8 @@ function kernelEntry(stream, kernel) {
|
|
|
3539
3804
|
}
|
|
3540
3805
|
const device2 = stream.path === void 0 ? void 0 : NAMED_DEVICES[stream.path];
|
|
3541
3806
|
const kind = stream.sliccKernelFile ? "file" : stream.tty ? "tty" : device2 ?? "stream";
|
|
3542
|
-
|
|
3807
|
+
const access = kind === "tty" ? O_RDWR : (stream.flags ?? O_RDWR) & O_ACCMODE3;
|
|
3808
|
+
return { fd: stream.fd, kernel, kind, flags: access, ...cloexec };
|
|
3543
3809
|
}
|
|
3544
3810
|
function describeInherited(Fs, sys, streams, livePath, actions = []) {
|
|
3545
3811
|
const table = /* @__PURE__ */ new Map();
|
|
@@ -3586,12 +3852,13 @@ function place(Fs, stream, fd) {
|
|
|
3586
3852
|
return moved;
|
|
3587
3853
|
}
|
|
3588
3854
|
function placeholder(Fs, streams, entry) {
|
|
3589
|
-
|
|
3855
|
+
const access = entry.flags ?? O_RDWR;
|
|
3856
|
+
if (entry.kind === "socket") return streams.socketStream(access);
|
|
3590
3857
|
if (entry.kind === "tty") return Fs.open("/dev/tty", O_RDWR);
|
|
3591
3858
|
if (entry.kind === "stream" || entry.kind === "clipboard" || entry.kind === "sealed")
|
|
3592
|
-
return Fs.open("/dev/null",
|
|
3859
|
+
return Fs.open("/dev/null", access);
|
|
3593
3860
|
Fs.mkdirTree(PLACEHOLDER_DIR);
|
|
3594
|
-
return Fs.open(`${PLACEHOLDER_DIR}/${entry.fd}`,
|
|
3861
|
+
return Fs.open(`${PLACEHOLDER_DIR}/${entry.fd}`, access | O_CREAT3);
|
|
3595
3862
|
}
|
|
3596
3863
|
function asFifo(stream, streams, identity) {
|
|
3597
3864
|
const inos = streamInos.get(streams) ?? /* @__PURE__ */ new Map();
|
|
@@ -4292,7 +4559,7 @@ var KERNEL_VERSION, OS_RELEASE;
|
|
|
4292
4559
|
var init_version = __esm({
|
|
4293
4560
|
"src/version.ts"() {
|
|
4294
4561
|
"use strict";
|
|
4295
|
-
KERNEL_VERSION = true ? "1.
|
|
4562
|
+
KERNEL_VERSION = true ? "1.93.0" : "0.0.0-dev";
|
|
4296
4563
|
OS_RELEASE = "6.0.0-slicc";
|
|
4297
4564
|
}
|
|
4298
4565
|
});
|
|
@@ -4793,6 +5060,20 @@ function kernelSys(transport) {
|
|
|
4793
5060
|
size(fd) {
|
|
4794
5061
|
return json2(call2({ op: "fd-vfs-stat", fd }, `fd-vfs-stat ${fd}`)).size;
|
|
4795
5062
|
},
|
|
5063
|
+
fdStat(fd) {
|
|
5064
|
+
const r = json2(call2({ op: "fd-vfs-stat", fd, full: true }, `fd-vfs-stat ${fd}`));
|
|
5065
|
+
return r?.stat;
|
|
5066
|
+
},
|
|
5067
|
+
fdChmod(fd, mode) {
|
|
5068
|
+
call2({ op: "fd-chmod", fd, mode }, `fd-chmod ${fd}`);
|
|
5069
|
+
},
|
|
5070
|
+
fdChown(fd, uid, gid) {
|
|
5071
|
+
const ids = { ...uid !== void 0 ? { uid } : {}, ...gid !== void 0 ? { gid } : {} };
|
|
5072
|
+
call2({ op: "fd-chown", fd, ...ids }, `fd-chown ${fd}`);
|
|
5073
|
+
},
|
|
5074
|
+
fdUtimes(fd, atimeMs, mtimeMs, now) {
|
|
5075
|
+
call2({ op: "fd-utimes", fd, atimeMs, mtimeMs, now }, `fd-utimes ${fd}`);
|
|
5076
|
+
},
|
|
4796
5077
|
ttyNames() {
|
|
4797
5078
|
return json2(call2({ op: "fd-tty-names" }, "fd-tty-names"));
|
|
4798
5079
|
},
|
|
@@ -4824,6 +5105,9 @@ function kernelSys(transport) {
|
|
|
4824
5105
|
openClipboard(flags) {
|
|
4825
5106
|
return json2(call2({ op: "fd-open-clipboard", flags }, "fd-open-clipboard"));
|
|
4826
5107
|
},
|
|
5108
|
+
clipboardAbort(fd) {
|
|
5109
|
+
call2({ op: "fd-clipboard-abort", fd }, "fd-clipboard-abort");
|
|
5110
|
+
},
|
|
4827
5111
|
ptyNumbers() {
|
|
4828
5112
|
return json2(call2({ op: "pty-list" }, "pty-list"));
|
|
4829
5113
|
},
|
|
@@ -4862,7 +5146,7 @@ function openDevice(Fs, fd, meta) {
|
|
|
4862
5146
|
return openAt(Fs, fd, `/dev/${meta.device}`, accessMode(meta.access));
|
|
4863
5147
|
}
|
|
4864
5148
|
function openHeld(Fs, fd, meta) {
|
|
4865
|
-
return "dir" in meta ? openAt(Fs, fd, meta.dir, O_RDONLY |
|
|
5149
|
+
return "dir" in meta ? openAt(Fs, fd, meta.dir, O_RDONLY | O_DIRECTORY2) : openDevice(Fs, fd, meta);
|
|
4866
5150
|
}
|
|
4867
5151
|
function openAt(Fs, fd, path, flags) {
|
|
4868
5152
|
let stream;
|
|
@@ -4974,6 +5258,17 @@ function kernelWrappers(imports, module, deps) {
|
|
|
4974
5258
|
function bridgeFlags(init) {
|
|
4975
5259
|
return { ...init.owners ? { owners: true } : {}, ...init.links ? { links: true } : {} };
|
|
4976
5260
|
}
|
|
5261
|
+
function credSyncTransport(gated, early, cred) {
|
|
5262
|
+
return {
|
|
5263
|
+
call: (req, timeoutMs, label) => {
|
|
5264
|
+
if (!FS_OPS.has(req.op)) early();
|
|
5265
|
+
const r = gated.call(req, timeoutMs, label);
|
|
5266
|
+
if (cred && req.op === "proc-setcred" && r.ok && r.kind === "json")
|
|
5267
|
+
Object.assign(cred, r.json);
|
|
5268
|
+
return r;
|
|
5269
|
+
}
|
|
5270
|
+
};
|
|
5271
|
+
}
|
|
4977
5272
|
async function runWasmProcess(init, port2, deps = {}) {
|
|
4978
5273
|
const signals = new SignalGate(
|
|
4979
5274
|
createSyncSabTransport(init.sab, port2, {
|
|
@@ -4992,12 +5287,7 @@ async function runWasmProcess(init, port2, deps = {}) {
|
|
|
4992
5287
|
const gated = signals.transport();
|
|
4993
5288
|
let early = () => {
|
|
4994
5289
|
};
|
|
4995
|
-
const transport =
|
|
4996
|
-
call: (req, timeoutMs, label) => {
|
|
4997
|
-
if (!FS_OPS.has(req.op)) early();
|
|
4998
|
-
return gated.call(req, timeoutMs, label);
|
|
4999
|
-
}
|
|
5000
|
-
};
|
|
5290
|
+
const transport = credSyncTransport(gated, () => early(), init.cred);
|
|
5001
5291
|
const sys = kernelSys(transport);
|
|
5002
5292
|
const encoder5 = new TextEncoder();
|
|
5003
5293
|
const say = (fd) => (text) => sys.write(fd, encoder5.encode(`${text}
|
|
@@ -5080,7 +5370,8 @@ async function runWasmProcess(init, port2, deps = {}) {
|
|
|
5080
5370
|
const vfs = mountVfsIntoEmscripten(running.FS, {
|
|
5081
5371
|
bridge: createSyncFsSabBridge(transport, bridgeFlags(init)),
|
|
5082
5372
|
cwd: init.cwd,
|
|
5083
|
-
warn: deps.warn ?? say(2)
|
|
5373
|
+
warn: deps.warn ?? say(2),
|
|
5374
|
+
cred: init.owners ? init.cred : void 0
|
|
5084
5375
|
});
|
|
5085
5376
|
early = () => signals.quiet(() => vfs.flushDirty());
|
|
5086
5377
|
const sigpipe = () => running.sliccSigpipe?.() === 1;
|
|
@@ -5099,6 +5390,7 @@ async function runWasmProcess(init, port2, deps = {}) {
|
|
|
5099
5390
|
atExit = () => streams.exiting();
|
|
5100
5391
|
useMounts(running.FS, init.env, true);
|
|
5101
5392
|
useZeroDevices(running.FS);
|
|
5393
|
+
useDevRemoval(running.FS);
|
|
5102
5394
|
useProcfs(running.FS, sys, init.pid);
|
|
5103
5395
|
if (init.fork) restoreForkedStreams(running.FS, streams, init.fork.streams ?? []);
|
|
5104
5396
|
else {
|
|
@@ -5108,6 +5400,7 @@ async function runWasmProcess(init, port2, deps = {}) {
|
|
|
5108
5400
|
const pipefs = ownValue(running, "PIPEFS");
|
|
5109
5401
|
if (pipefs) streams.usePipes(pipefs);
|
|
5110
5402
|
streams.useControllingTerminal();
|
|
5403
|
+
streams.useKernelFdMetadata();
|
|
5111
5404
|
useDevFd(running.FS);
|
|
5112
5405
|
useFileMmap(running.FS, {
|
|
5113
5406
|
sys,
|
|
@@ -5119,9 +5412,9 @@ async function runWasmProcess(init, port2, deps = {}) {
|
|
|
5119
5412
|
transport,
|
|
5120
5413
|
Fs: running.FS,
|
|
5121
5414
|
env: init.env,
|
|
5415
|
+
pid: init.pid,
|
|
5122
5416
|
beforeSpawn: () => vfs.flush(),
|
|
5123
5417
|
afterChild: () => vfs.invalidate(),
|
|
5124
|
-
pid: init.pid,
|
|
5125
5418
|
raise: (sig) => running.sliccRaise?.(sig),
|
|
5126
5419
|
restartable,
|
|
5127
5420
|
memory: () => memory,
|
|
@@ -5141,6 +5434,9 @@ async function runWasmProcess(init, port2, deps = {}) {
|
|
|
5141
5434
|
sigpipe,
|
|
5142
5435
|
restartable
|
|
5143
5436
|
});
|
|
5437
|
+
return runWithFlush(running, init, streams, vfs);
|
|
5438
|
+
}
|
|
5439
|
+
function runWithFlush(running, init, streams, vfs) {
|
|
5144
5440
|
try {
|
|
5145
5441
|
return streams.exitStatus(runMain(running, init));
|
|
5146
5442
|
} finally {
|
|
@@ -5205,7 +5501,7 @@ function runMain(running, init) {
|
|
|
5205
5501
|
return status2;
|
|
5206
5502
|
}
|
|
5207
5503
|
}
|
|
5208
|
-
var FS_OPS, O_RDONLY, O_WRONLY3, O_RDWR3, O_ACCMODE4,
|
|
5504
|
+
var FS_OPS, O_RDONLY, O_WRONLY3, O_RDWR3, O_ACCMODE4, O_DIRECTORY2, accessMode, PLACED, GLUE_TRAILER, evaluateGlue, EVAL_BLOCKED;
|
|
5209
5505
|
var init_process_runtime = __esm({
|
|
5210
5506
|
"src/process/process-runtime.ts"() {
|
|
5211
5507
|
"use strict";
|
|
@@ -5231,7 +5527,7 @@ var init_process_runtime = __esm({
|
|
|
5231
5527
|
O_WRONLY3 = 1;
|
|
5232
5528
|
O_RDWR3 = 2;
|
|
5233
5529
|
O_ACCMODE4 = 3;
|
|
5234
|
-
|
|
5530
|
+
O_DIRECTORY2 = 65536;
|
|
5235
5531
|
accessMode = (access) => access === "read" ? O_RDONLY : access === "write" ? O_WRONLY3 : O_RDWR3;
|
|
5236
5532
|
PLACED = /* @__PURE__ */ new Set(["stream", "file", "socket", "clipboard", "sealed"]);
|
|
5237
5533
|
GLUE_TRAILER = [
|
|
@@ -5357,6 +5653,21 @@ function physicalPath(fs, path) {
|
|
|
5357
5653
|
}
|
|
5358
5654
|
return `/${walk.done.join("/")}`;
|
|
5359
5655
|
}
|
|
5656
|
+
async function physicalPathAsync(fs, path) {
|
|
5657
|
+
const walk = start(path);
|
|
5658
|
+
for (let part = next(walk); part !== void 0; part = next(walk)) {
|
|
5659
|
+
const at = `/${[...walk.done, part].join("/")}`;
|
|
5660
|
+
let target;
|
|
5661
|
+
try {
|
|
5662
|
+
target = (await fs.lstat(at)).isSymbolicLink ? await fs.readlink(at) : void 0;
|
|
5663
|
+
} catch {
|
|
5664
|
+
return rest(walk, part);
|
|
5665
|
+
}
|
|
5666
|
+
if (target === void 0) walk.done.push(part);
|
|
5667
|
+
else if (!follow(walk, target)) return lexical(path);
|
|
5668
|
+
}
|
|
5669
|
+
return `/${walk.done.join("/")}`;
|
|
5670
|
+
}
|
|
5360
5671
|
var MAX_HOPS;
|
|
5361
5672
|
var init_physical_path = __esm({
|
|
5362
5673
|
"src/fs/physical-path.ts"() {
|
|
@@ -5581,9 +5892,11 @@ function cachingBridge(bridge, now = () => performance.now(), shared) {
|
|
|
5581
5892
|
...bridge.kept ? { kept: bridge.kept.bind(bridge) } : {},
|
|
5582
5893
|
...bridge.keptStat ? { keptStat: bridge.keptStat.bind(bridge) } : {},
|
|
5583
5894
|
...bridge.pinned ? { pinned: (handle) => pinnedIo2(bridge, handle, rewriting) } : {},
|
|
5584
|
-
...bridge.create ? {
|
|
5895
|
+
...bridge.create ? {
|
|
5896
|
+
create: (p, mode, opening2) => mutating(() => bridge.create?.(p, mode, opening2), ...entry(p))
|
|
5897
|
+
} : {},
|
|
5585
5898
|
...chown ? {
|
|
5586
|
-
chown: (p,
|
|
5899
|
+
chown: (p, ...rest2) => rewriting(p, () => chown.call(bridge, p, ...rest2))
|
|
5587
5900
|
} : {},
|
|
5588
5901
|
...bridge.pread && bridge.pwrite && bridge.truncate ? {
|
|
5589
5902
|
pread: bridge.pread.bind(bridge),
|
|
@@ -6353,6 +6666,7 @@ var init_wasi_fds = __esm({
|
|
|
6353
6666
|
const { buffer } = e.file;
|
|
6354
6667
|
try {
|
|
6355
6668
|
buffer.flush();
|
|
6669
|
+
this.reported.delete(buffer);
|
|
6356
6670
|
} catch (err) {
|
|
6357
6671
|
this.reported.add(buffer);
|
|
6358
6672
|
this.drop(buffer);
|
|
@@ -6418,6 +6732,7 @@ var init_wasi_fds = __esm({
|
|
|
6418
6732
|
for (const buffer of this.buffers.values()) {
|
|
6419
6733
|
try {
|
|
6420
6734
|
buffer.flush();
|
|
6735
|
+
this.reported.delete(buffer);
|
|
6421
6736
|
} catch (err) {
|
|
6422
6737
|
if (!this.reported.has(buffer)) throw err;
|
|
6423
6738
|
}
|
|
@@ -6640,7 +6955,7 @@ var init_wasi_fds = __esm({
|
|
|
6640
6955
|
return true;
|
|
6641
6956
|
}
|
|
6642
6957
|
try {
|
|
6643
|
-
this.fs.create(path);
|
|
6958
|
+
this.fs.create(path, void 0, true);
|
|
6644
6959
|
return true;
|
|
6645
6960
|
} catch (err) {
|
|
6646
6961
|
if (oflags & OFLAGS.EXCL || err.code !== "EEXIST") throw err;
|
|
@@ -6954,7 +7269,7 @@ var init_wasi_termios = __esm({
|
|
|
6954
7269
|
});
|
|
6955
7270
|
|
|
6956
7271
|
// src/process/wasi/wasi-host.ts
|
|
6957
|
-
function
|
|
7272
|
+
function idOf3(value2) {
|
|
6958
7273
|
return value2 >>> 0 === 4294967295 ? void 0 : value2 >>> 0;
|
|
6959
7274
|
}
|
|
6960
7275
|
function linkedOf(st) {
|
|
@@ -7031,6 +7346,7 @@ var WasiExit, IDS, NS_PER_MS, AT_SYMLINK_NOFOLLOW2, AT_EACCESS2, ROOT_IDS, GONE,
|
|
|
7031
7346
|
var init_wasi_host = __esm({
|
|
7032
7347
|
"src/process/wasi/wasi-host.ts"() {
|
|
7033
7348
|
"use strict";
|
|
7349
|
+
init_dev_removal();
|
|
7034
7350
|
init_physical_path();
|
|
7035
7351
|
init_cpu_clock();
|
|
7036
7352
|
init_cred();
|
|
@@ -7128,10 +7444,10 @@ var init_wasi_host = __esm({
|
|
|
7128
7444
|
return path;
|
|
7129
7445
|
};
|
|
7130
7446
|
const modeOf2 = (st) => (st.mode ?? 0) & 4095;
|
|
7131
|
-
const chown = (path, uid, gid, follow2) => {
|
|
7447
|
+
const chown = (path, uid, gid, follow2, handle) => {
|
|
7132
7448
|
const { chown: own } = this.o.fs;
|
|
7133
7449
|
if (!own) throw new WasiError("ENOSYS");
|
|
7134
|
-
own.call(this.o.fs, path,
|
|
7450
|
+
own.call(this.o.fs, path, idOf3(uid), idOf3(gid), follow2, handle);
|
|
7135
7451
|
};
|
|
7136
7452
|
const caller = () => {
|
|
7137
7453
|
const cred = this.o.kernel.call({ op: "proc-cred" });
|
|
@@ -7162,7 +7478,11 @@ var init_wasi_host = __esm({
|
|
|
7162
7478
|
return follow2 ? this.o.fs.stat(path) : this.o.fs.lstat(path);
|
|
7163
7479
|
};
|
|
7164
7480
|
return wrap({
|
|
7165
|
-
fd_chown: (fd, uid, gid) =>
|
|
7481
|
+
fd_chown: (fd, uid, gid) => {
|
|
7482
|
+
const e = fds.get(fd);
|
|
7483
|
+
const handle = e.type === "file" ? e.file.buffer.handle : void 0;
|
|
7484
|
+
void chown(pathOf(fd), uid, gid, true, handle);
|
|
7485
|
+
},
|
|
7166
7486
|
path_chown: (dirfd, p, l, uid, gid, flags) => void chown(at(dirfd, p, l), uid, gid, (flags & AT_SYMLINK_NOFOLLOW2) === 0),
|
|
7167
7487
|
fd_owner: (fd, out) => {
|
|
7168
7488
|
if (!this.o.fs.owners) throw new WasiError("ENOTSUP");
|
|
@@ -7174,14 +7494,14 @@ var init_wasi_host = __esm({
|
|
|
7174
7494
|
owner(fdOwned(fd), out);
|
|
7175
7495
|
},
|
|
7176
7496
|
path_filestat_owner: (dirfd, lookup2, p, l, statOut, out) => {
|
|
7177
|
-
if (!this.o.fs.owners) throw new WasiError("ENOTSUP");
|
|
7178
7497
|
const path = at(dirfd, p, l);
|
|
7498
|
+
if (!this.o.fs.owners) throw new WasiError("ENOTSUP");
|
|
7179
7499
|
this.writeFilestat(statOut, this.pathFilestat(path, lookup2));
|
|
7180
7500
|
owner(pathOwned(path, (lookup2 & LOOKUP_SYMLINK_FOLLOW) !== 0), out);
|
|
7181
7501
|
},
|
|
7182
7502
|
path_owner: (dirfd, p, l, flags, out) => {
|
|
7183
|
-
if (!this.o.fs.owners) throw new WasiError("ENOTSUP");
|
|
7184
7503
|
const path = at(dirfd, p, l);
|
|
7504
|
+
if (!this.o.fs.owners) throw new WasiError("ENOTSUP");
|
|
7185
7505
|
owner(pathOwned(path, (flags & AT_SYMLINK_NOFOLLOW2) === 0), out);
|
|
7186
7506
|
},
|
|
7187
7507
|
path_access: (dirfd, p, l, amode, flags) => {
|
|
@@ -7438,14 +7758,35 @@ var init_wasi_host = __esm({
|
|
|
7438
7758
|
const { mem, fds, o } = this;
|
|
7439
7759
|
const at = (dirfd, p, l) => fds.resolve(dirfd, mem.string(p, l));
|
|
7440
7760
|
return {
|
|
7441
|
-
path_open: (dirfd,
|
|
7442
|
-
const
|
|
7443
|
-
|
|
7444
|
-
|
|
7445
|
-
|
|
7446
|
-
|
|
7761
|
+
path_open: (dirfd, lookup2, p, l, oflags, rights, _inheriting, fdflags, out) => {
|
|
7762
|
+
const follow2 = (lookup2 & LOOKUP_SYMLINK_FOLLOW) !== 0;
|
|
7763
|
+
try {
|
|
7764
|
+
const path = at(dirfd, p, l);
|
|
7765
|
+
if (deviceOf(path)) this.interrupted?.();
|
|
7766
|
+
const fresh = (oflags & OFLAGS.CREAT) !== 0 && !this.synthetic(path) && !o.fs.exists(path);
|
|
7767
|
+
mem.view().setUint32(out, fds.open(path, oflags, rights, fdflags), true);
|
|
7768
|
+
if (fresh) this.created(path, 438);
|
|
7769
|
+
} catch (err) {
|
|
7770
|
+
if (err.code !== "ENOENT") throw err;
|
|
7771
|
+
const raw = mem.string(p, l);
|
|
7772
|
+
const joined2 = raw.startsWith("/") ? raw : `${fds.dir(dirfd).path}/${raw}`;
|
|
7773
|
+
const resolved2 = this.resolveForDev(joined2, follow2);
|
|
7774
|
+
if (!resolved2) throw err;
|
|
7775
|
+
mem.view().setUint32(out, fds.open(resolved2, oflags, rights, fdflags), true);
|
|
7776
|
+
}
|
|
7777
|
+
},
|
|
7778
|
+
path_filestat_get: (dirfd, lookup2, p, l, out) => {
|
|
7779
|
+
try {
|
|
7780
|
+
this.writeFilestat(out, this.pathFilestat(at(dirfd, p, l), lookup2));
|
|
7781
|
+
} catch (err) {
|
|
7782
|
+
if (err.code !== "ENOENT") throw err;
|
|
7783
|
+
const raw = mem.string(p, l);
|
|
7784
|
+
const joined2 = raw.startsWith("/") ? raw : `${fds.dir(dirfd).path}/${raw}`;
|
|
7785
|
+
const resolved2 = this.resolveForDev(joined2, (lookup2 & LOOKUP_SYMLINK_FOLLOW) !== 0);
|
|
7786
|
+
if (!resolved2) throw err;
|
|
7787
|
+
this.writeFilestat(out, this.pathFilestat(resolved2, lookup2));
|
|
7788
|
+
}
|
|
7447
7789
|
},
|
|
7448
|
-
path_filestat_get: (dirfd, lookup2, p, l, out) => void this.writeFilestat(out, this.pathFilestat(at(dirfd, p, l), lookup2)),
|
|
7449
7790
|
path_filestat_set_times: (dirfd, lookup2, p, l, atim, mtim, flags) => {
|
|
7450
7791
|
const path = at(dirfd, p, l);
|
|
7451
7792
|
fds.flushPath(path);
|
|
@@ -7460,6 +7801,7 @@ var init_wasi_host = __esm({
|
|
|
7460
7801
|
path_remove_directory: (dirfd, p, l) => void o.fs.rmdir(at(dirfd, p, l)),
|
|
7461
7802
|
path_unlink_file: (dirfd, p, l) => {
|
|
7462
7803
|
const path = at(dirfd, p, l);
|
|
7804
|
+
if (inDevTree(path)) return void o.fs.unlink(path);
|
|
7463
7805
|
const st = o.fs.lstat(path);
|
|
7464
7806
|
if (st.isDirectory) throw new WasiError("EISDIR");
|
|
7465
7807
|
const linked = linkedOf(st);
|
|
@@ -7691,7 +8033,12 @@ var init_wasi_host = __esm({
|
|
|
7691
8033
|
const v = this.mem.view();
|
|
7692
8034
|
v.setUint8(out, filetype);
|
|
7693
8035
|
v.setUint16(out + 2, flags, true);
|
|
7694
|
-
|
|
8036
|
+
let rights = seeks ? RIGHTS.ALL : RIGHTS.ALL & ~(RIGHTS.FD_SEEK | RIGHTS.FD_TELL);
|
|
8037
|
+
if (e.type === "kernel") {
|
|
8038
|
+
const access = this.o.kernel.sys.access?.(fd);
|
|
8039
|
+
if (access === "read") rights &= ~RIGHTS.FD_WRITE;
|
|
8040
|
+
else if (access === "write") rights &= ~RIGHTS.FD_READ;
|
|
8041
|
+
}
|
|
7695
8042
|
v.setBigUint64(out + 8, rights, true);
|
|
7696
8043
|
v.setBigUint64(out + 16, RIGHTS.ALL, true);
|
|
7697
8044
|
}
|
|
@@ -7757,6 +8104,21 @@ var init_wasi_host = __esm({
|
|
|
7757
8104
|
synthetic(path) {
|
|
7758
8105
|
return deviceOf(path) !== void 0 || path === SEALED_PATH2 && !!this.o.kernel.sys.openSealed || path === CLIPBOARD_PATH2 && !!this.o.kernel.sys.openClipboard;
|
|
7759
8106
|
}
|
|
8107
|
+
resolveForDev(path, follow2 = true) {
|
|
8108
|
+
try {
|
|
8109
|
+
if (!follow2) {
|
|
8110
|
+
const slash = path.lastIndexOf("/");
|
|
8111
|
+
if (slash <= 0) return void 0;
|
|
8112
|
+
const parent = physicalPath(this.o.fs, path.slice(0, slash));
|
|
8113
|
+
const resolved3 = `${parent}/${path.slice(slash + 1)}`;
|
|
8114
|
+
return resolved3 !== path && this.synthetic(resolved3) ? resolved3 : void 0;
|
|
8115
|
+
}
|
|
8116
|
+
const resolved2 = physicalPath(this.o.fs, path);
|
|
8117
|
+
return resolved2 !== path && this.synthetic(resolved2) ? resolved2 : void 0;
|
|
8118
|
+
} catch {
|
|
8119
|
+
return void 0;
|
|
8120
|
+
}
|
|
8121
|
+
}
|
|
7760
8122
|
pathFilestat(path, lookup2) {
|
|
7761
8123
|
if (this.synthetic(path)) {
|
|
7762
8124
|
return this.local({
|
|
@@ -7768,7 +8130,19 @@ var init_wasi_host = __esm({
|
|
|
7768
8130
|
}
|
|
7769
8131
|
this.fds.flushPath(path);
|
|
7770
8132
|
const follow2 = (lookup2 & LOOKUP_SYMLINK_FOLLOW) !== 0;
|
|
7771
|
-
|
|
8133
|
+
try {
|
|
8134
|
+
return filestatOf(path, follow2 ? this.o.fs.stat(path) : this.o.fs.lstat(path));
|
|
8135
|
+
} catch (err) {
|
|
8136
|
+
if (err.code !== "ENOENT") throw err;
|
|
8137
|
+
const resolved2 = this.resolveForDev(path, follow2);
|
|
8138
|
+
if (!resolved2) throw err;
|
|
8139
|
+
return this.local({
|
|
8140
|
+
filetype: FILETYPE.CHARACTER_DEVICE,
|
|
8141
|
+
size: 0n,
|
|
8142
|
+
ino: pathInode(resolved2),
|
|
8143
|
+
mtimeNs: 0n
|
|
8144
|
+
});
|
|
8145
|
+
}
|
|
7772
8146
|
}
|
|
7773
8147
|
setTimes(path, atim, mtim, flags, follow2 = true) {
|
|
7774
8148
|
const asked = FSTFLAGS.ATIM | FSTFLAGS.ATIM_NOW | FSTFLAGS.MTIM | FSTFLAGS.MTIM_NOW;
|
|
@@ -7840,6 +8214,7 @@ var init_wasi_threads = __esm({
|
|
|
7840
8214
|
"src/process/wasi/wasi-threads.ts"() {
|
|
7841
8215
|
"use strict";
|
|
7842
8216
|
init_protocol();
|
|
8217
|
+
init_sync_sab_wire();
|
|
7843
8218
|
init_wasi_files();
|
|
7844
8219
|
LAST_TID = 0;
|
|
7845
8220
|
RUNNING = 1;
|
|
@@ -7875,7 +8250,7 @@ var init_wasi_threads = __esm({
|
|
|
7875
8250
|
this.beforeSpawn?.();
|
|
7876
8251
|
const tid = Atomics.add(this.ids, LAST_TID, 1) + 1;
|
|
7877
8252
|
const modules = this.modules?.();
|
|
7878
|
-
const blocked = this.blocked?.()
|
|
8253
|
+
const blocked = this.blocked?.();
|
|
7879
8254
|
this.port.postMessage({
|
|
7880
8255
|
type: WASM_THREAD_SPAWN,
|
|
7881
8256
|
thread: {
|
|
@@ -7884,7 +8259,7 @@ var init_wasi_threads = __esm({
|
|
|
7884
8259
|
memory: this.memory,
|
|
7885
8260
|
ids: this.ids.buffer,
|
|
7886
8261
|
...modules ? { modules } : {},
|
|
7887
|
-
...blocked ? { blocked } : {}
|
|
8262
|
+
...anyBlocked(blocked) ? { blocked } : {}
|
|
7888
8263
|
}
|
|
7889
8264
|
});
|
|
7890
8265
|
return tid;
|
|
@@ -8105,7 +8480,8 @@ var init_wasix_process = __esm({
|
|
|
8105
8480
|
cwd: this.host.cwd,
|
|
8106
8481
|
...fds.isShared ? { shared: true } : {},
|
|
8107
8482
|
setjmps: this.driver.setjmps(),
|
|
8108
|
-
...this.host.signals ? { signals: this.host.signals.snapshot() } : {}
|
|
8483
|
+
...this.host.signals ? { signals: this.host.signals.snapshot() } : {},
|
|
8484
|
+
...this.host.sigmask ? { blocked: this.host.sigmask.inherited() } : {}
|
|
8109
8485
|
};
|
|
8110
8486
|
return this.call({
|
|
8111
8487
|
op: "proc-fork",
|
|
@@ -8235,6 +8611,7 @@ function importsContext({
|
|
|
8235
8611
|
fs,
|
|
8236
8612
|
fds,
|
|
8237
8613
|
syscall: call2,
|
|
8614
|
+
net: network(raw, call2),
|
|
8238
8615
|
...processes(host, call2, tid !== MAIN_TID),
|
|
8239
8616
|
async: {
|
|
8240
8617
|
submit: (req) => call2({ op: "async-submit", req }),
|
|
@@ -8270,6 +8647,30 @@ function importsContext({
|
|
|
8270
8647
|
gid: { get: () => live().gid, enumerable: true }
|
|
8271
8648
|
});
|
|
8272
8649
|
}
|
|
8650
|
+
function loopbackHost(host) {
|
|
8651
|
+
if (host === "localhost") return "127.0.0.1";
|
|
8652
|
+
if (typeof host === "string" && LOOPBACK.test(host)) return host;
|
|
8653
|
+
throw new WasiError("EINVAL");
|
|
8654
|
+
}
|
|
8655
|
+
function network(raw, call2) {
|
|
8656
|
+
return {
|
|
8657
|
+
connect({ host, port: port2, nonblock = false }) {
|
|
8658
|
+
const to = loopbackHost(host);
|
|
8659
|
+
if (!Number.isInteger(port2) || port2 < 1 || port2 > 65535) throw new WasiError("EINVAL");
|
|
8660
|
+
const fd = call2({ op: "sock-open", domain: "inet" });
|
|
8661
|
+
const addr = { family: "inet", host: to, port: port2 };
|
|
8662
|
+
const r = raw({ op: "sock-connect", fd, addr, ...nonblock ? { nonblock: true } : {} });
|
|
8663
|
+
if (r.ok || nonblock && r.errno === "EINPROGRESS") return fd;
|
|
8664
|
+
raw({ op: "fd-close", fd });
|
|
8665
|
+
throw new WasiError(r.errno);
|
|
8666
|
+
},
|
|
8667
|
+
ready(fd) {
|
|
8668
|
+
const sel = call2({ op: "fd-select", read: [], write: [fd], timeoutMs: 0 });
|
|
8669
|
+
if (!sel.write.includes(fd)) return E.INPROGRESS;
|
|
8670
|
+
return call2({ op: "sock-getopt", fd, level: SOL_SOCKET, name: SO_ERROR });
|
|
8671
|
+
}
|
|
8672
|
+
};
|
|
8673
|
+
}
|
|
8273
8674
|
function processes(host, call2, inThread) {
|
|
8274
8675
|
const close = (fd) => void call2({ op: "fd-close", fd });
|
|
8275
8676
|
const slot2 = (n, how, mine, theirs) => {
|
|
@@ -8327,7 +8728,7 @@ function processes(host, call2, inThread) {
|
|
|
8327
8728
|
}
|
|
8328
8729
|
};
|
|
8329
8730
|
}
|
|
8330
|
-
var UID2, STDIO;
|
|
8731
|
+
var UID2, LOOPBACK, SOL_SOCKET, SO_ERROR, STDIO;
|
|
8331
8732
|
var init_wasi_imports = __esm({
|
|
8332
8733
|
"src/process/wasi/wasi-imports.ts"() {
|
|
8333
8734
|
"use strict";
|
|
@@ -8336,6 +8737,9 @@ var init_wasi_imports = __esm({
|
|
|
8336
8737
|
init_wasi_threads();
|
|
8337
8738
|
init_wasix_process();
|
|
8338
8739
|
UID2 = 1e3;
|
|
8740
|
+
LOOPBACK = /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
|
|
8741
|
+
SOL_SOCKET = 1;
|
|
8742
|
+
SO_ERROR = 4;
|
|
8339
8743
|
STDIO = ["stdin", "stdout", "stderr"];
|
|
8340
8744
|
}
|
|
8341
8745
|
});
|
|
@@ -8583,7 +8987,7 @@ function procfsBridge(fs, tree) {
|
|
|
8583
8987
|
}
|
|
8584
8988
|
const { chown } = fs;
|
|
8585
8989
|
if (chown) {
|
|
8586
|
-
over.chown = (p,
|
|
8990
|
+
over.chown = (p, ...rest2) => readOnly2([[p, rest2[2] === true]], () => chown.call(fs, p, ...rest2));
|
|
8587
8991
|
}
|
|
8588
8992
|
return new Proxy(fs, {
|
|
8589
8993
|
get: (target, key, receiver) => key in over ? over[key] : Reflect.get(target, key, receiver)
|
|
@@ -8741,7 +9145,7 @@ var init_wasi_sigmask = __esm({
|
|
|
8741
9145
|
};
|
|
8742
9146
|
WasiSigmask = class {
|
|
8743
9147
|
lo;
|
|
8744
|
-
hi
|
|
9148
|
+
hi;
|
|
8745
9149
|
header;
|
|
8746
9150
|
deliver;
|
|
8747
9151
|
process;
|
|
@@ -8750,9 +9154,10 @@ var init_wasi_sigmask = __esm({
|
|
|
8750
9154
|
this.deliver = deliver;
|
|
8751
9155
|
this.process = process;
|
|
8752
9156
|
this.lo = libcBits(Atomics.load(header, SAB_I_BLOCKED));
|
|
9157
|
+
this.hi = Atomics.load(header, SAB_I_BLOCKED_HI);
|
|
8753
9158
|
}
|
|
8754
9159
|
static unsupported(header) {
|
|
8755
|
-
|
|
9160
|
+
storeBlocked(header, [0, 0]);
|
|
8756
9161
|
}
|
|
8757
9162
|
set(how, setLo, setHi, old) {
|
|
8758
9163
|
if (how !== SIG_BLOCK && how !== SIG_UNBLOCK && how !== SIG_SETMASK) return E.INVAL;
|
|
@@ -8760,7 +9165,7 @@ var init_wasi_sigmask = __esm({
|
|
|
8760
9165
|
this.lo = apply(how, this.lo, setLo | 0) & ~LIBC_UNBLOCKABLE;
|
|
8761
9166
|
this.hi = apply(how, this.hi, setHi | 0);
|
|
8762
9167
|
const now = kernelBits(this.lo);
|
|
8763
|
-
|
|
9168
|
+
storeBlocked(this.header, [now, this.hi]);
|
|
8764
9169
|
if ((Atomics.load(this.header, SAB_I_SIGNALS) & ~now) !== 0) this.deliver();
|
|
8765
9170
|
return E.SUCCESS;
|
|
8766
9171
|
}
|
|
@@ -8768,7 +9173,7 @@ var init_wasi_sigmask = __esm({
|
|
|
8768
9173
|
const old = [this.lo, this.hi];
|
|
8769
9174
|
this.lo = setLo & ~LIBC_UNBLOCKABLE;
|
|
8770
9175
|
this.hi = setHi | 0;
|
|
8771
|
-
|
|
9176
|
+
storeBlocked(this.header, [kernelBits(this.lo), this.hi]);
|
|
8772
9177
|
return old;
|
|
8773
9178
|
}
|
|
8774
9179
|
deliverUnblocked() {
|
|
@@ -8781,6 +9186,9 @@ var init_wasi_sigmask = __esm({
|
|
|
8781
9186
|
this.set(SIG_SETMASK, lo, hi, () => {
|
|
8782
9187
|
});
|
|
8783
9188
|
}
|
|
9189
|
+
inherited() {
|
|
9190
|
+
return [kernelBits(this.lo), this.hi];
|
|
9191
|
+
}
|
|
8784
9192
|
discard(sig) {
|
|
8785
9193
|
Atomics.and(this.header, SAB_I_SIGNALS, ~sigbit(sig));
|
|
8786
9194
|
if (this.process) Atomics.and(this.process, SAB_I_SIGNALS, ~sigbit(sig));
|
|
@@ -10060,7 +10468,7 @@ function readAddr(view, ptr) {
|
|
|
10060
10468
|
function ipv6Host(bytes) {
|
|
10061
10469
|
const zeros = (n) => bytes.subarray(0, n).every((b) => b === 0);
|
|
10062
10470
|
if (zeros(16)) return "0.0.0.0";
|
|
10063
|
-
if (zeros(15) && bytes[15] === 1) return
|
|
10471
|
+
if (zeros(15) && bytes[15] === 1) return LOOPBACK2;
|
|
10064
10472
|
if (zeros(10) && bytes[10] === 255 && bytes[11] === 255) return bytes.subarray(12).join(".");
|
|
10065
10473
|
const groups = [0, 2, 4, 6, 8, 10, 12, 14].map(
|
|
10066
10474
|
(i) => (bytes[i] << 8 | bytes[i + 1]).toString(16)
|
|
@@ -10217,7 +10625,7 @@ function wasixSocketImports(host, preview1) {
|
|
|
10217
10625
|
}
|
|
10218
10626
|
};
|
|
10219
10627
|
}
|
|
10220
|
-
var INET4, INET6, UNIX, STREAM, ADDR_IP_SIZE,
|
|
10628
|
+
var INET4, INET6, UNIX, STREAM, ADDR_IP_SIZE, LOOPBACK2, OPTIONS;
|
|
10221
10629
|
var init_wasix_sockets = __esm({
|
|
10222
10630
|
"src/process/wasi/wasix-sockets.ts"() {
|
|
10223
10631
|
"use strict";
|
|
@@ -10229,7 +10637,7 @@ var init_wasix_sockets = __esm({
|
|
|
10229
10637
|
UNIX = 3;
|
|
10230
10638
|
STREAM = 1;
|
|
10231
10639
|
ADDR_IP_SIZE = 18;
|
|
10232
|
-
|
|
10640
|
+
LOOPBACK2 = "127.0.0.1";
|
|
10233
10641
|
OPTIONS = {
|
|
10234
10642
|
1: [1, 15],
|
|
10235
10643
|
2: [1, 2],
|
|
@@ -10758,6 +11166,7 @@ __export(wasi_runtime_exports, {
|
|
|
10758
11166
|
runWasiProcess: () => runWasiProcess,
|
|
10759
11167
|
runWasiThread: () => runWasiThread,
|
|
10760
11168
|
sigmaskOf: () => sigmaskOf,
|
|
11169
|
+
takeThreadDefault: () => takeThreadDefault,
|
|
10761
11170
|
trapMessage: () => trapMessage,
|
|
10762
11171
|
unsupportedImport: () => unsupportedImport,
|
|
10763
11172
|
wireSignals: () => wireSignals
|
|
@@ -10801,7 +11210,7 @@ function sigmaskOf(module, sab, gate, threads, process) {
|
|
|
10801
11210
|
WasiSigmask.unsupported(header);
|
|
10802
11211
|
return void 0;
|
|
10803
11212
|
}
|
|
10804
|
-
if (threads) threads.blocked = () =>
|
|
11213
|
+
if (threads) threads.blocked = () => loadBlocked(header);
|
|
10805
11214
|
const shared = process && new Int32Array(process, 0, SAB_HEADER_I32);
|
|
10806
11215
|
return new WasiSigmask(header, () => gate.deliver(), shared);
|
|
10807
11216
|
}
|
|
@@ -11195,7 +11604,7 @@ async function runWasiThread(init, port2) {
|
|
|
11195
11604
|
masks: () => null,
|
|
11196
11605
|
raise: (sig) => signals.raise(sig)
|
|
11197
11606
|
});
|
|
11198
|
-
const signals = new WasiSignals(
|
|
11607
|
+
const signals = new WasiSignals(takeThreadDefault(call2, init.pid));
|
|
11199
11608
|
const threads = new WasiThreads(port2, thread.memory, threadCap(init.env), thread.tid, thread.ids);
|
|
11200
11609
|
threads.received = thread.modules;
|
|
11201
11610
|
const id = identify(transport, init);
|
|
@@ -11249,7 +11658,7 @@ async function runWasiThread(init, port2) {
|
|
|
11249
11658
|
throw e;
|
|
11250
11659
|
}
|
|
11251
11660
|
}
|
|
11252
|
-
var TRAPPED, PREVIEW1, WASIX, SLICC, SIGNAL_CALLBACK, takeDefault, SLICC_FS, SLICC_TTY, RESERVED2, UNDELIVERED, DELIVERED, importsSlicc, importsSigactionHook, noErrno, FALLBACK_MAXIMUM_PAGES, LinkSync, DL_GEN, BACKTRACE_FRAMES;
|
|
11661
|
+
var TRAPPED, PREVIEW1, WASIX, SLICC, SIGNAL_CALLBACK, takeDefault, takeThreadDefault, SLICC_FS, SLICC_TTY, RESERVED2, UNDELIVERED, DELIVERED, importsSlicc, importsSigactionHook, noErrno, FALLBACK_MAXIMUM_PAGES, LinkSync, DL_GEN, BACKTRACE_FRAMES;
|
|
11253
11662
|
var init_wasi_runtime = __esm({
|
|
11254
11663
|
"src/process/wasi/wasi-runtime.ts"() {
|
|
11255
11664
|
"use strict";
|
|
@@ -11284,6 +11693,17 @@ var init_wasi_runtime = __esm({
|
|
|
11284
11693
|
call2({ op: "proc-kill", pid, sig });
|
|
11285
11694
|
if (defaultAction(sig) === "terminate") throw new WasiExit(128 + sig);
|
|
11286
11695
|
};
|
|
11696
|
+
takeThreadDefault = (call2, pid) => (sig) => {
|
|
11697
|
+
if (defaultAction(sig) !== "terminate") {
|
|
11698
|
+
call2({ op: "proc-kill", pid, sig });
|
|
11699
|
+
return;
|
|
11700
|
+
}
|
|
11701
|
+
try {
|
|
11702
|
+
call2({ op: "proc-kill-self", sig });
|
|
11703
|
+
} catch {
|
|
11704
|
+
}
|
|
11705
|
+
throw new WasiExit(128 + sig);
|
|
11706
|
+
};
|
|
11287
11707
|
SLICC_FS = "slicc_fs";
|
|
11288
11708
|
SLICC_TTY = "slicc_tty";
|
|
11289
11709
|
RESERVED2 = RESERVED_NAMESPACES;
|
|
@@ -11453,6 +11873,13 @@ var init_async_sab = __esm({
|
|
|
11453
11873
|
});
|
|
11454
11874
|
|
|
11455
11875
|
// src/process/js/js-kernel.ts
|
|
11876
|
+
function umaskRequest(mask) {
|
|
11877
|
+
if (mask === void 0) return { op: "proc-umask" };
|
|
11878
|
+
if (!Number.isInteger(mask) || mask < 0 || mask > 511) {
|
|
11879
|
+
throw new JsCallError("EINVAL", "umask");
|
|
11880
|
+
}
|
|
11881
|
+
return { op: "proc-umask", mask };
|
|
11882
|
+
}
|
|
11456
11883
|
function modeOf(mode) {
|
|
11457
11884
|
if (!Number.isInteger(mode) || mode < 0 || mode > 4095) {
|
|
11458
11885
|
throw new JsCallError("EINVAL", "chmod");
|
|
@@ -11677,6 +12104,8 @@ var init_js_kernel = __esm({
|
|
|
11677
12104
|
|
|
11678
12105
|
// src/process/js/js-children.ts
|
|
11679
12106
|
function exitedOf(status2) {
|
|
12107
|
+
if ((status2 & 255) === 127)
|
|
12108
|
+
return { status: 128 + (status2 >> 8 & 255), signal: status2 >> 8 & 255, stopped: true };
|
|
11680
12109
|
const signal = status2 & 127;
|
|
11681
12110
|
return signal ? { status: 128 + signal, signal } : { status: status2 >> 8 & 255 };
|
|
11682
12111
|
}
|
|
@@ -11713,8 +12142,10 @@ function writable(io, fd) {
|
|
|
11713
12142
|
});
|
|
11714
12143
|
}
|
|
11715
12144
|
function childOps(kernel, io, defaults, sync) {
|
|
11716
|
-
const wait2 = async (pid) => {
|
|
11717
|
-
|
|
12145
|
+
const wait2 = async (pid, options = {}) => {
|
|
12146
|
+
if (typeof options !== "object" || options === null) throw new JsCallError("EINVAL", "wait");
|
|
12147
|
+
const untraced = options.untraced === true ? { untraced: true } : {};
|
|
12148
|
+
const r = await kernel.blocking({ op: "proc-wait", pid, nohang: false, ...untraced });
|
|
11718
12149
|
const [, status2] = r.ok && r.kind === "json" ? r.json : [0, 0];
|
|
11719
12150
|
return exitedOf(status2);
|
|
11720
12151
|
};
|
|
@@ -11728,7 +12159,7 @@ function childOps(kernel, io, defaults, sync) {
|
|
|
11728
12159
|
...stdin !== void 0 ? { stdin: writable(io, stdin) } : {},
|
|
11729
12160
|
...stdout !== void 0 ? { stdout: readable(io, stdout) } : {},
|
|
11730
12161
|
...stderr !== void 0 ? { stderr: readable(io, stderr) } : {},
|
|
11731
|
-
wait: () => wait2(pid),
|
|
12162
|
+
wait: (options) => wait2(pid, options),
|
|
11732
12163
|
kill: (signal) => kill(pid, signal)
|
|
11733
12164
|
};
|
|
11734
12165
|
};
|
|
@@ -11934,7 +12365,8 @@ function openRequest(abs, o) {
|
|
|
11934
12365
|
flags: flagsOf(o),
|
|
11935
12366
|
position: 0,
|
|
11936
12367
|
...isExclusive(o) ? { exclusive: true } : o.create ? { create: true } : { existing: true },
|
|
11937
|
-
...o.truncate ? { truncate: true } : {}
|
|
12368
|
+
...o.truncate ? { truncate: true } : {},
|
|
12369
|
+
...o.create || isExclusive(o) ? { mode: o.mode === void 0 ? 438 : modeOf(o.mode) } : {}
|
|
11938
12370
|
};
|
|
11939
12371
|
}
|
|
11940
12372
|
function index2(n, what) {
|
|
@@ -11993,6 +12425,7 @@ function* lookup(abs) {
|
|
|
11993
12425
|
const names = yield { op: "fd-tty-names" };
|
|
11994
12426
|
if (names.includes(abs)) return { kind: "terminal", name: abs };
|
|
11995
12427
|
}
|
|
12428
|
+
if (name2 === "pts") return { kind: "dir", mode: DIR | 365 };
|
|
11996
12429
|
const pts = /^pts\/(\d+)$/.exec(name2)?.[1];
|
|
11997
12430
|
if (pts !== void 0) {
|
|
11998
12431
|
const open = yield { op: "pty-list" };
|
|
@@ -12024,7 +12457,8 @@ function* fdStat(fd, path) {
|
|
|
12024
12457
|
if (info.kind === "file") {
|
|
12025
12458
|
const file = yield { op: "fd-vfs-stat", fd };
|
|
12026
12459
|
if (file.orphan) return { ...nodeStat(33152, file.size), isFile: true };
|
|
12027
|
-
|
|
12460
|
+
const st = yield* pathStat(file.path);
|
|
12461
|
+
return { ...st, size: file.size };
|
|
12028
12462
|
}
|
|
12029
12463
|
if (info.terminal) return yield* terminalStat(info.terminal);
|
|
12030
12464
|
if (CHAR_KINDS.has(info.kind)) return nodeStat(CHAR | 438);
|
|
@@ -12077,16 +12511,26 @@ function* devReadlink(abs) {
|
|
|
12077
12511
|
if (node.kind === "fd") return yield* fdTarget(node.fd, abs);
|
|
12078
12512
|
throw new JsCallError("EINVAL", abs);
|
|
12079
12513
|
}
|
|
12514
|
+
function* devResolveTarget(abs) {
|
|
12515
|
+
const node = yield* lookup(abs);
|
|
12516
|
+
if (node.kind === "fd") return yield* fdTarget(node.fd, abs);
|
|
12517
|
+
if (node.kind === "link" && node.fd !== void 0) return yield* fdTarget(node.fd, abs);
|
|
12518
|
+
return void 0;
|
|
12519
|
+
}
|
|
12080
12520
|
function* devReaddir(abs) {
|
|
12081
12521
|
if (abs === "/dev/fd") {
|
|
12082
12522
|
const fds = yield { op: "fd-list" };
|
|
12083
12523
|
return fds.map(({ fd }) => String(fd));
|
|
12084
12524
|
}
|
|
12525
|
+
if (abs === "/dev/pts") {
|
|
12526
|
+
const open = yield { op: "pty-list" };
|
|
12527
|
+
return open.map(String).sort();
|
|
12528
|
+
}
|
|
12085
12529
|
const node = yield* lookup(abs);
|
|
12086
12530
|
if (node.kind !== "dir") throw new JsCallError("ENOTDIR", abs);
|
|
12087
12531
|
const names = yield { op: "fd-tty-names" };
|
|
12088
12532
|
const ttys = names.filter((n) => /^\/dev\/tty\d+$/.test(n)).map((n) => n.slice(5));
|
|
12089
|
-
return [...DEVICES2, "clipboard", "sealed", "tty", "fd", ...STDIO3, ...ttys].sort();
|
|
12533
|
+
return [...DEVICES2, "clipboard", "sealed", "tty", "fd", "pts", ...STDIO3, ...ttys].sort();
|
|
12090
12534
|
}
|
|
12091
12535
|
function* aliasOf(fd, abs, o) {
|
|
12092
12536
|
const info = yield* fdInfo(fd, abs);
|
|
@@ -12095,6 +12539,9 @@ function* aliasOf(fd, abs, o) {
|
|
|
12095
12539
|
const at = yield { op: "fd-vfs-stat", fd };
|
|
12096
12540
|
if (!at.orphan)
|
|
12097
12541
|
return { fd: yield openRequest(at.path, { ...o, create: false }), file };
|
|
12542
|
+
const wantWrite = o.write === true || o.append === true || o.truncate === true;
|
|
12543
|
+
if (wantWrite && info.access === "read") throw new JsCallError("EBADF", abs);
|
|
12544
|
+
if (!wantWrite && info.access === "write") throw new JsCallError("EBADF", abs);
|
|
12098
12545
|
}
|
|
12099
12546
|
const copy2 = yield { op: "fd-dup", fd, min: 3 };
|
|
12100
12547
|
if (file && o.truncate) {
|
|
@@ -12400,11 +12847,18 @@ function plain(status2, text) {
|
|
|
12400
12847
|
function local2(url) {
|
|
12401
12848
|
return isKernelLoopbackHost(new URL(url).hostname);
|
|
12402
12849
|
}
|
|
12850
|
+
function badPort(url) {
|
|
12851
|
+
const port2 = url.port ? Number(url.port) : 0;
|
|
12852
|
+
return port2 !== 0 && BAD_PORTS.has(port2);
|
|
12853
|
+
}
|
|
12403
12854
|
function rewrite(hop, status2, location) {
|
|
12404
12855
|
const next2 = new URL(location, hop.url);
|
|
12405
12856
|
if (next2.protocol !== "http:" && next2.protocol !== "https:") {
|
|
12406
12857
|
throw failed3(new JsCallError("EPROTONOSUPPORT", next2.protocol));
|
|
12407
12858
|
}
|
|
12859
|
+
if (badPort(next2)) {
|
|
12860
|
+
throw failed3(new JsCallError("EACCES", `bad port: ${next2.href}`));
|
|
12861
|
+
}
|
|
12408
12862
|
if (local2(next2.href) && !local2(hop.url)) {
|
|
12409
12863
|
const from = new URL(hop.url).origin;
|
|
12410
12864
|
throw failed3(
|
|
@@ -12690,6 +13144,9 @@ function fetchOp(kernel) {
|
|
|
12690
13144
|
if (protocol !== "http:" && protocol !== "https:") {
|
|
12691
13145
|
throw failed3(new JsCallError("EPROTONOSUPPORT", protocol));
|
|
12692
13146
|
}
|
|
13147
|
+
if (badPort(new URL(request.url))) {
|
|
13148
|
+
throw failed3(new JsCallError("EACCES", `bad port: ${request.url}`));
|
|
13149
|
+
}
|
|
12693
13150
|
let known = await traitsAt(request.url);
|
|
12694
13151
|
if (!known.manualRedirects && request.redirect !== "follow") {
|
|
12695
13152
|
throw failed3(new JsCallError("ENOTSUP", `redirect: ${request.redirect}`));
|
|
@@ -12720,7 +13177,7 @@ function fetchOp(kernel) {
|
|
|
12720
13177
|
}
|
|
12721
13178
|
};
|
|
12722
13179
|
}
|
|
12723
|
-
var CHUNK2, MAX_REDIRECTS, NULL_BODY, REDIRECTS, BODY_HEADERS, DECODED, CREDENTIALS, OVER, TOKEN, QUOTABLE, SPACE, BASE64, SLICE;
|
|
13180
|
+
var CHUNK2, MAX_REDIRECTS, NULL_BODY, REDIRECTS, BODY_HEADERS, DECODED, CREDENTIALS, BAD_PORTS, OVER, TOKEN, QUOTABLE, SPACE, BASE64, SLICE;
|
|
12724
13181
|
var init_js_fetch = __esm({
|
|
12725
13182
|
"src/process/js/js-fetch.ts"() {
|
|
12726
13183
|
"use strict";
|
|
@@ -12739,6 +13196,89 @@ var init_js_fetch = __esm({
|
|
|
12739
13196
|
]);
|
|
12740
13197
|
DECODED = /* @__PURE__ */ new Set(["gzip", "x-gzip", "deflate"]);
|
|
12741
13198
|
CREDENTIALS = /* @__PURE__ */ new Set(["authorization", "proxy-authorization", "cookie", "cookie2"]);
|
|
13199
|
+
BAD_PORTS = /* @__PURE__ */ new Set([
|
|
13200
|
+
1,
|
|
13201
|
+
7,
|
|
13202
|
+
9,
|
|
13203
|
+
11,
|
|
13204
|
+
13,
|
|
13205
|
+
15,
|
|
13206
|
+
17,
|
|
13207
|
+
19,
|
|
13208
|
+
20,
|
|
13209
|
+
21,
|
|
13210
|
+
22,
|
|
13211
|
+
23,
|
|
13212
|
+
25,
|
|
13213
|
+
37,
|
|
13214
|
+
42,
|
|
13215
|
+
43,
|
|
13216
|
+
53,
|
|
13217
|
+
69,
|
|
13218
|
+
77,
|
|
13219
|
+
79,
|
|
13220
|
+
87,
|
|
13221
|
+
95,
|
|
13222
|
+
101,
|
|
13223
|
+
102,
|
|
13224
|
+
103,
|
|
13225
|
+
104,
|
|
13226
|
+
109,
|
|
13227
|
+
110,
|
|
13228
|
+
111,
|
|
13229
|
+
113,
|
|
13230
|
+
115,
|
|
13231
|
+
117,
|
|
13232
|
+
119,
|
|
13233
|
+
123,
|
|
13234
|
+
135,
|
|
13235
|
+
137,
|
|
13236
|
+
139,
|
|
13237
|
+
143,
|
|
13238
|
+
161,
|
|
13239
|
+
179,
|
|
13240
|
+
389,
|
|
13241
|
+
427,
|
|
13242
|
+
465,
|
|
13243
|
+
512,
|
|
13244
|
+
513,
|
|
13245
|
+
514,
|
|
13246
|
+
515,
|
|
13247
|
+
526,
|
|
13248
|
+
530,
|
|
13249
|
+
531,
|
|
13250
|
+
532,
|
|
13251
|
+
540,
|
|
13252
|
+
548,
|
|
13253
|
+
554,
|
|
13254
|
+
556,
|
|
13255
|
+
563,
|
|
13256
|
+
587,
|
|
13257
|
+
601,
|
|
13258
|
+
636,
|
|
13259
|
+
989,
|
|
13260
|
+
990,
|
|
13261
|
+
993,
|
|
13262
|
+
995,
|
|
13263
|
+
1719,
|
|
13264
|
+
1720,
|
|
13265
|
+
1723,
|
|
13266
|
+
2049,
|
|
13267
|
+
3659,
|
|
13268
|
+
4045,
|
|
13269
|
+
4190,
|
|
13270
|
+
5060,
|
|
13271
|
+
5061,
|
|
13272
|
+
6e3,
|
|
13273
|
+
6566,
|
|
13274
|
+
6665,
|
|
13275
|
+
6666,
|
|
13276
|
+
6667,
|
|
13277
|
+
6668,
|
|
13278
|
+
6669,
|
|
13279
|
+
6697,
|
|
13280
|
+
10080
|
|
13281
|
+
]);
|
|
12742
13282
|
OVER = /* @__PURE__ */ Symbol("over");
|
|
12743
13283
|
TOKEN = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
12744
13284
|
QUOTABLE = /^[\t\x20-\x7e\x80-\xff]*$/;
|
|
@@ -12865,8 +13405,8 @@ function netOps(kernel, io) {
|
|
|
12865
13405
|
const failed5 = await kernel.json({
|
|
12866
13406
|
op: "sock-getopt",
|
|
12867
13407
|
fd,
|
|
12868
|
-
level:
|
|
12869
|
-
name:
|
|
13408
|
+
level: SOL_SOCKET2,
|
|
13409
|
+
name: SO_ERROR2
|
|
12870
13410
|
});
|
|
12871
13411
|
if (failed5 !== 0) throw new JsCallError(errnoName(failed5), "connect");
|
|
12872
13412
|
return connection(fd);
|
|
@@ -12874,7 +13414,7 @@ function netOps(kernel, io) {
|
|
|
12874
13414
|
}
|
|
12875
13415
|
};
|
|
12876
13416
|
}
|
|
12877
|
-
var SHUT_RD, SHUT_WR, IPV4, NEVER,
|
|
13417
|
+
var SHUT_RD, SHUT_WR, IPV4, NEVER, SOL_SOCKET2, SO_ERROR2;
|
|
12878
13418
|
var init_js_net = __esm({
|
|
12879
13419
|
"src/process/js/js-net.ts"() {
|
|
12880
13420
|
"use strict";
|
|
@@ -12884,8 +13424,8 @@ var init_js_net = __esm({
|
|
|
12884
13424
|
SHUT_WR = 1;
|
|
12885
13425
|
IPV4 = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
|
|
12886
13426
|
NEVER = new AbortController().signal;
|
|
12887
|
-
|
|
12888
|
-
|
|
13427
|
+
SOL_SOCKET2 = 1;
|
|
13428
|
+
SO_ERROR2 = 4;
|
|
12889
13429
|
}
|
|
12890
13430
|
});
|
|
12891
13431
|
|
|
@@ -13114,6 +13654,24 @@ function laneOf(lane) {
|
|
|
13114
13654
|
}
|
|
13115
13655
|
function syncOps(kernel, shared) {
|
|
13116
13656
|
const { infos, handles, resolve } = shared;
|
|
13657
|
+
const tryDevSync = (abs) => {
|
|
13658
|
+
try {
|
|
13659
|
+
const resolved2 = physicalPath(
|
|
13660
|
+
{
|
|
13661
|
+
lstat(p) {
|
|
13662
|
+
return parseSyncFsStat(kernel.json({ op: "lstat", path: p })) ?? {};
|
|
13663
|
+
},
|
|
13664
|
+
readlink(p) {
|
|
13665
|
+
return String(kernel.json({ op: "readlink", path: p }));
|
|
13666
|
+
}
|
|
13667
|
+
},
|
|
13668
|
+
abs
|
|
13669
|
+
);
|
|
13670
|
+
return resolved2 !== abs && inDev(resolved2) ? resolved2 : void 0;
|
|
13671
|
+
} catch {
|
|
13672
|
+
return void 0;
|
|
13673
|
+
}
|
|
13674
|
+
};
|
|
13117
13675
|
const info = (fd) => {
|
|
13118
13676
|
const known = infos.get(fd);
|
|
13119
13677
|
if (known) return known;
|
|
@@ -13146,10 +13704,17 @@ function syncOps(kernel, shared) {
|
|
|
13146
13704
|
const statOf = (op, path) => {
|
|
13147
13705
|
const abs = resolve(path);
|
|
13148
13706
|
if (inDev(abs)) return devSync(kernel, devStat(abs, op === "stat"));
|
|
13149
|
-
|
|
13150
|
-
|
|
13151
|
-
|
|
13152
|
-
|
|
13707
|
+
try {
|
|
13708
|
+
kernel.call({ op: "fd-path-flush", path: abs });
|
|
13709
|
+
const s = parseSyncFsStat(kernel.json({ op, path: abs }));
|
|
13710
|
+
if (!s) throw new JsCallError("EIO", op);
|
|
13711
|
+
return s;
|
|
13712
|
+
} catch (err) {
|
|
13713
|
+
if (!(err instanceof JsCallError) || err.code !== "ENOENT") throw err;
|
|
13714
|
+
const devPath = tryDevSync(abs);
|
|
13715
|
+
if (!devPath) throw err;
|
|
13716
|
+
return devSync(kernel, devStat(devPath, op === "stat"));
|
|
13717
|
+
}
|
|
13153
13718
|
};
|
|
13154
13719
|
const openDev2 = (abs, options) => {
|
|
13155
13720
|
const { fd, file, ...access } = devSync(kernel, devOpen(abs, options));
|
|
@@ -13169,27 +13734,34 @@ function syncOps(kernel, shared) {
|
|
|
13169
13734
|
const open = (path, options = {}) => {
|
|
13170
13735
|
const abs = resolve(path);
|
|
13171
13736
|
if (inDev(abs)) return openDev2(abs, options);
|
|
13172
|
-
let existing;
|
|
13173
13737
|
try {
|
|
13174
|
-
existing
|
|
13175
|
-
|
|
13176
|
-
|
|
13177
|
-
|
|
13178
|
-
|
|
13179
|
-
|
|
13180
|
-
|
|
13181
|
-
kernel.
|
|
13738
|
+
let existing;
|
|
13739
|
+
try {
|
|
13740
|
+
existing = statOf(isExclusive(options) ? "lstat" : "stat", abs);
|
|
13741
|
+
} catch (err) {
|
|
13742
|
+
existing = absent(err);
|
|
13743
|
+
}
|
|
13744
|
+
checkOpen(abs, options, existing);
|
|
13745
|
+
const fd = kernel.json(openRequest(abs, options));
|
|
13746
|
+
try {
|
|
13747
|
+
kernel.call({ op: "fd-vfs-stat", fd });
|
|
13748
|
+
} catch (err) {
|
|
13749
|
+
kernel.raw({ op: "fd-close", fd });
|
|
13750
|
+
throw err;
|
|
13751
|
+
}
|
|
13752
|
+
infos.set(fd, { kind: "file" });
|
|
13753
|
+
const handle = syncFile(kernel, fd, abs, options.append === true, () => {
|
|
13754
|
+
infos.delete(fd);
|
|
13755
|
+
handles.delete(fd);
|
|
13756
|
+
});
|
|
13757
|
+
handles.set(fd, handle.invalidate);
|
|
13758
|
+
return handle.file;
|
|
13182
13759
|
} catch (err) {
|
|
13183
|
-
|
|
13184
|
-
|
|
13760
|
+
if (!(err instanceof JsCallError) || err.code !== "ENOENT") throw err;
|
|
13761
|
+
const devPath = tryDevSync(abs);
|
|
13762
|
+
if (!devPath) throw err;
|
|
13763
|
+
return openDev2(devPath, options);
|
|
13185
13764
|
}
|
|
13186
|
-
infos.set(fd, { kind: "file" });
|
|
13187
|
-
const handle = syncFile(kernel, fd, abs, options.append === true, () => {
|
|
13188
|
-
infos.delete(fd);
|
|
13189
|
-
handles.delete(fd);
|
|
13190
|
-
});
|
|
13191
|
-
handles.set(fd, handle.invalidate);
|
|
13192
|
-
return handle.file;
|
|
13193
13765
|
};
|
|
13194
13766
|
return {
|
|
13195
13767
|
read: read2,
|
|
@@ -13201,7 +13773,7 @@ function syncOps(kernel, shared) {
|
|
|
13201
13773
|
kernel.call({ op: "fd-close", fd });
|
|
13202
13774
|
},
|
|
13203
13775
|
open: procOpenSync(open, kernel, { resolve, pid: shared.pid }),
|
|
13204
|
-
fs: procFsSync(syncPathOps(kernel, resolve, statOf, open), kernel, {
|
|
13776
|
+
fs: procFsSync(syncPathOps(kernel, resolve, statOf, open, tryDevSync), kernel, {
|
|
13205
13777
|
resolve,
|
|
13206
13778
|
pid: shared.pid
|
|
13207
13779
|
})
|
|
@@ -13271,14 +13843,16 @@ function syncFile(kernel, fd, path, append, forget) {
|
|
|
13271
13843
|
}
|
|
13272
13844
|
};
|
|
13273
13845
|
}
|
|
13274
|
-
function syncPathOps(kernel, resolve, statOf, open) {
|
|
13846
|
+
function syncPathOps(kernel, resolve, statOf, open, tryDev) {
|
|
13275
13847
|
return {
|
|
13276
13848
|
stat: (path) => statOf("stat", path),
|
|
13277
13849
|
lstat: (path) => statOf("lstat", path),
|
|
13278
13850
|
exists(path) {
|
|
13279
13851
|
const abs = resolve(path);
|
|
13280
13852
|
if (inDev(abs)) return devSync(kernel, devExists(abs));
|
|
13281
|
-
|
|
13853
|
+
if (kernel.json({ op: "exists", path: abs }) === true) return true;
|
|
13854
|
+
const devPath = tryDev(abs);
|
|
13855
|
+
return devPath ? devSync(kernel, devExists(devPath)) : false;
|
|
13282
13856
|
},
|
|
13283
13857
|
readdir(path) {
|
|
13284
13858
|
const abs = resolve(path);
|
|
@@ -13288,7 +13862,8 @@ function syncPathOps(kernel, resolve, statOf, open) {
|
|
|
13288
13862
|
mkdir: (path, options) => void kernel.call({
|
|
13289
13863
|
op: "mkdir",
|
|
13290
13864
|
path: resolve(path),
|
|
13291
|
-
...options?.recursive === false ? { exclusive: true } : {}
|
|
13865
|
+
...options?.recursive === false ? { exclusive: true } : {},
|
|
13866
|
+
mode: options?.mode === void 0 ? 511 : modeOf(options.mode)
|
|
13292
13867
|
}),
|
|
13293
13868
|
rm: (path) => void kernel.call({ op: "rm", path: resolve(path) }),
|
|
13294
13869
|
unlink: (path) => void kernel.call({ op: "unlink", path: resolve(path) }),
|
|
@@ -13302,18 +13877,38 @@ function syncPathOps(kernel, resolve, statOf, open) {
|
|
|
13302
13877
|
return String(kernel.json({ op: "readlink", path: abs }));
|
|
13303
13878
|
},
|
|
13304
13879
|
statfs(path) {
|
|
13305
|
-
|
|
13880
|
+
let abs = resolve(path);
|
|
13881
|
+
if (inDev(abs)) {
|
|
13882
|
+
try {
|
|
13883
|
+
const target = devSync(kernel, devResolveTarget(abs));
|
|
13884
|
+
if (target?.startsWith("/")) abs = target;
|
|
13885
|
+
} catch {
|
|
13886
|
+
}
|
|
13887
|
+
}
|
|
13306
13888
|
statOf("stat", abs);
|
|
13307
13889
|
return statFsOf(kernel.json({ op: "statfs", path: abs }));
|
|
13308
13890
|
},
|
|
13309
13891
|
readFile(path) {
|
|
13310
13892
|
const abs = resolve(path);
|
|
13311
13893
|
if (inDev(abs)) return readWholeSync(open(abs));
|
|
13312
|
-
|
|
13313
|
-
|
|
13314
|
-
|
|
13315
|
-
|
|
13316
|
-
|
|
13894
|
+
try {
|
|
13895
|
+
kernel.call({ op: "fd-path-flush", path: abs });
|
|
13896
|
+
return kernel.bytes({ op: "read", path: abs });
|
|
13897
|
+
} catch (err) {
|
|
13898
|
+
if (!(err instanceof JsCallError) || err.code !== "ENOENT") throw err;
|
|
13899
|
+
const devPath = tryDev(abs);
|
|
13900
|
+
if (!devPath) throw err;
|
|
13901
|
+
return readWholeSync(open(devPath));
|
|
13902
|
+
}
|
|
13903
|
+
},
|
|
13904
|
+
writeFile(path, data, options) {
|
|
13905
|
+
const mode = options?.mode;
|
|
13906
|
+
const file = open(path, {
|
|
13907
|
+
write: true,
|
|
13908
|
+
create: true,
|
|
13909
|
+
truncate: true,
|
|
13910
|
+
...mode !== void 0 ? { mode } : {}
|
|
13911
|
+
});
|
|
13317
13912
|
try {
|
|
13318
13913
|
file.write(0, typeof data === "string" ? encoder3.encode(data) : data);
|
|
13319
13914
|
} finally {
|
|
@@ -13326,6 +13921,7 @@ var encoder3, noLane, JsSyncKernel;
|
|
|
13326
13921
|
var init_js_sync = __esm({
|
|
13327
13922
|
"src/process/js/js-sync.ts"() {
|
|
13328
13923
|
"use strict";
|
|
13924
|
+
init_physical_path();
|
|
13329
13925
|
init_signals();
|
|
13330
13926
|
init_sync_fs_wire();
|
|
13331
13927
|
init_sync_sab_bridge();
|
|
@@ -13722,6 +14318,55 @@ function readable2(read2) {
|
|
|
13722
14318
|
{ highWaterMark: 0 }
|
|
13723
14319
|
);
|
|
13724
14320
|
}
|
|
14321
|
+
async function resolveDevAsync(kernel, abs) {
|
|
14322
|
+
try {
|
|
14323
|
+
const resolved2 = await physicalPathAsync(
|
|
14324
|
+
{
|
|
14325
|
+
async lstat(p) {
|
|
14326
|
+
return parseSyncFsStat(await kernel.json({ op: "lstat", path: p })) ?? {};
|
|
14327
|
+
},
|
|
14328
|
+
async readlink(p) {
|
|
14329
|
+
return String(await kernel.json({ op: "readlink", path: p }));
|
|
14330
|
+
}
|
|
14331
|
+
},
|
|
14332
|
+
abs
|
|
14333
|
+
);
|
|
14334
|
+
return resolved2 !== abs && inDev(resolved2) ? resolved2 : void 0;
|
|
14335
|
+
} catch {
|
|
14336
|
+
return void 0;
|
|
14337
|
+
}
|
|
14338
|
+
}
|
|
14339
|
+
async function vfsStat(kernel, abs, op, tryDev) {
|
|
14340
|
+
try {
|
|
14341
|
+
await kernel.call({ op: "fd-path-flush", path: abs });
|
|
14342
|
+
const s = parseSyncFsStat(await kernel.json({ op, path: abs }));
|
|
14343
|
+
if (!s) throw new JsCallError("EIO", op);
|
|
14344
|
+
return s;
|
|
14345
|
+
} catch (err) {
|
|
14346
|
+
if (!(err instanceof JsCallError) || err.code !== "ENOENT") throw err;
|
|
14347
|
+
const devPath = await tryDev(abs);
|
|
14348
|
+
if (!devPath) throw err;
|
|
14349
|
+
return devAsync(kernel, devStat(devPath, op === "stat"));
|
|
14350
|
+
}
|
|
14351
|
+
}
|
|
14352
|
+
async function vfsOpen(kernel, abs, options, statOf, infos, handles) {
|
|
14353
|
+
const existing = await statOf(isExclusive(options) ? "lstat" : "stat", abs).catch(absent);
|
|
14354
|
+
checkOpen(abs, options, existing);
|
|
14355
|
+
const fd = await kernel.json(openRequest(abs, options));
|
|
14356
|
+
try {
|
|
14357
|
+
await kernel.call({ op: "fd-vfs-stat", fd });
|
|
14358
|
+
} catch (err) {
|
|
14359
|
+
await kernel.raw({ op: "fd-close", fd });
|
|
14360
|
+
throw err;
|
|
14361
|
+
}
|
|
14362
|
+
infos.set(fd, { kind: "file" });
|
|
14363
|
+
const handle = fileHandle(kernel, fd, abs, options.append === true, () => {
|
|
14364
|
+
infos.delete(fd);
|
|
14365
|
+
handles.delete(fd);
|
|
14366
|
+
});
|
|
14367
|
+
handles.set(fd, handle.invalidate);
|
|
14368
|
+
return handle.file;
|
|
14369
|
+
}
|
|
13725
14370
|
function createContext(o) {
|
|
13726
14371
|
const { kernel } = o;
|
|
13727
14372
|
const infos = /* @__PURE__ */ new Map();
|
|
@@ -13729,6 +14374,7 @@ function createContext(o) {
|
|
|
13729
14374
|
const pending = /* @__PURE__ */ new Set();
|
|
13730
14375
|
const random = o.random ?? ((bytes) => void crypto.getRandomValues(bytes));
|
|
13731
14376
|
const resolve = (path) => resolvePath(o.cwd, path);
|
|
14377
|
+
const tryDev = (abs) => resolveDevAsync(kernel, abs);
|
|
13732
14378
|
let exiting;
|
|
13733
14379
|
const exit = (code2 = 0) => {
|
|
13734
14380
|
exiting ??= code2;
|
|
@@ -13771,32 +14417,25 @@ function createContext(o) {
|
|
|
13771
14417
|
const statOf = async (op, path) => {
|
|
13772
14418
|
const abs = resolve(path);
|
|
13773
14419
|
if (inDev(abs)) return devAsync(kernel, devStat(abs, op === "stat"));
|
|
13774
|
-
|
|
13775
|
-
const s = parseSyncFsStat(await kernel.json({ op, path: abs }));
|
|
13776
|
-
if (!s) throw new JsCallError("EIO", op);
|
|
13777
|
-
return s;
|
|
14420
|
+
return vfsStat(kernel, abs, op, tryDev);
|
|
13778
14421
|
};
|
|
14422
|
+
const devIo = { infos, handles, read: read2, write: writeAll };
|
|
13779
14423
|
const open = async (path, options = {}) => {
|
|
13780
14424
|
const abs = resolve(path);
|
|
13781
|
-
if (inDev(abs)) return openDev(kernel, abs, options,
|
|
13782
|
-
const existing = await statOf(isExclusive(options) ? "lstat" : "stat", abs).catch(absent);
|
|
13783
|
-
checkOpen(abs, options, existing);
|
|
13784
|
-
const fd = await kernel.json(openRequest(abs, options));
|
|
14425
|
+
if (inDev(abs)) return openDev(kernel, abs, options, devIo);
|
|
13785
14426
|
try {
|
|
13786
|
-
await kernel
|
|
14427
|
+
return await vfsOpen(kernel, abs, options, statOf, infos, handles);
|
|
13787
14428
|
} catch (err) {
|
|
13788
|
-
|
|
13789
|
-
|
|
14429
|
+
if (!(err instanceof JsCallError) || err.code !== "ENOENT") throw err;
|
|
14430
|
+
const devPath = await tryDev(abs);
|
|
14431
|
+
if (!devPath) throw err;
|
|
14432
|
+
return openDev(kernel, devPath, options, devIo);
|
|
13790
14433
|
}
|
|
13791
|
-
infos.set(fd, { kind: "file" });
|
|
13792
|
-
const handle = fileHandle(kernel, fd, abs, options.append === true, () => {
|
|
13793
|
-
infos.delete(fd);
|
|
13794
|
-
handles.delete(fd);
|
|
13795
|
-
});
|
|
13796
|
-
handles.set(fd, handle.invalidate);
|
|
13797
|
-
return handle.file;
|
|
13798
14434
|
};
|
|
13799
|
-
const fs = procFsAsync(pathOps(kernel, resolve, statOf, open), kernel, {
|
|
14435
|
+
const fs = procFsAsync(pathOps(kernel, resolve, statOf, open, tryDev), kernel, {
|
|
14436
|
+
resolve,
|
|
14437
|
+
pid: o.pid
|
|
14438
|
+
});
|
|
13800
14439
|
const lane = o.lane ?? laneOf(void 0);
|
|
13801
14440
|
if (o.lane && o.lane !== noLane) kernel.syncLane = o.lane;
|
|
13802
14441
|
const syncKernel = new JsSyncKernel(lane, kernel, unwind);
|
|
@@ -13812,6 +14451,7 @@ function createContext(o) {
|
|
|
13812
14451
|
},
|
|
13813
14452
|
kill: killer({ self: o.pid, kernel, syncKernel, lane, writes, modes: terminal.modes }),
|
|
13814
14453
|
cred: () => syncKernel.json({ op: "proc-cred" }),
|
|
14454
|
+
umask: (mask) => syncKernel.json(umaskRequest(mask)),
|
|
13815
14455
|
setcred(change) {
|
|
13816
14456
|
if (typeof change !== "object" || change === null || Array.isArray(change)) {
|
|
13817
14457
|
throw new JsCallError("EINVAL", "setcred");
|
|
@@ -13858,6 +14498,7 @@ function createContext(o) {
|
|
|
13858
14498
|
},
|
|
13859
14499
|
sync,
|
|
13860
14500
|
fetch: fetchOp(kernel),
|
|
14501
|
+
umask: async (mask) => await kernel.json(umaskRequest(mask)),
|
|
13861
14502
|
sudo: async (args) => await kernel.json({
|
|
13862
14503
|
op: "proc-sudo",
|
|
13863
14504
|
args: [...args],
|
|
@@ -13990,14 +14631,16 @@ async function sendSome(kernel, fd, body, signal) {
|
|
|
13990
14631
|
await kernel.blocking({ op: "fd-select", read: [], write: [fd], timeoutMs: -1 }, signal);
|
|
13991
14632
|
}
|
|
13992
14633
|
}
|
|
13993
|
-
function pathOps(kernel, resolve, statOf, open) {
|
|
14634
|
+
function pathOps(kernel, resolve, statOf, open, tryDev) {
|
|
13994
14635
|
return {
|
|
13995
14636
|
stat: (path) => statOf("stat", path),
|
|
13996
14637
|
lstat: (path) => statOf("lstat", path),
|
|
13997
14638
|
async exists(path) {
|
|
13998
14639
|
const abs = resolve(path);
|
|
13999
14640
|
if (inDev(abs)) return devAsync(kernel, devExists(abs));
|
|
14000
|
-
|
|
14641
|
+
if (await kernel.json({ op: "exists", path: abs }) === true) return true;
|
|
14642
|
+
const devPath = await tryDev(abs);
|
|
14643
|
+
return devPath ? devAsync(kernel, devExists(devPath)) : false;
|
|
14001
14644
|
},
|
|
14002
14645
|
async readdir(path) {
|
|
14003
14646
|
const abs = resolve(path);
|
|
@@ -14007,7 +14650,8 @@ function pathOps(kernel, resolve, statOf, open) {
|
|
|
14007
14650
|
mkdir: async (path, options) => void await kernel.call({
|
|
14008
14651
|
op: "mkdir",
|
|
14009
14652
|
path: resolve(path),
|
|
14010
|
-
...options?.recursive === false ? { exclusive: true } : {}
|
|
14653
|
+
...options?.recursive === false ? { exclusive: true } : {},
|
|
14654
|
+
mode: options?.mode === void 0 ? 511 : modeOf(options.mode)
|
|
14011
14655
|
}),
|
|
14012
14656
|
rm: async (path) => void await kernel.call({ op: "rm", path: resolve(path) }),
|
|
14013
14657
|
unlink: async (path) => void await kernel.call({ op: "unlink", path: resolve(path) }),
|
|
@@ -14021,18 +14665,35 @@ function pathOps(kernel, resolve, statOf, open) {
|
|
|
14021
14665
|
return String(await kernel.json({ op: "readlink", path: abs }));
|
|
14022
14666
|
},
|
|
14023
14667
|
async statfs(path) {
|
|
14024
|
-
|
|
14668
|
+
let abs = resolve(path);
|
|
14669
|
+
if (inDev(abs)) {
|
|
14670
|
+
const target = await devAsync(kernel, devResolveTarget(abs)).catch(() => void 0);
|
|
14671
|
+
if (target?.startsWith("/")) abs = target;
|
|
14672
|
+
}
|
|
14025
14673
|
await statOf("stat", abs);
|
|
14026
14674
|
return statFsOf(await kernel.json({ op: "statfs", path: abs }));
|
|
14027
14675
|
},
|
|
14028
14676
|
async readFile(path) {
|
|
14029
14677
|
const abs = resolve(path);
|
|
14030
14678
|
if (inDev(abs)) return readWhole(await open(abs));
|
|
14031
|
-
|
|
14032
|
-
|
|
14033
|
-
|
|
14034
|
-
|
|
14035
|
-
|
|
14679
|
+
try {
|
|
14680
|
+
await kernel.call({ op: "fd-path-flush", path: abs });
|
|
14681
|
+
return await kernel.bytes({ op: "read", path: abs });
|
|
14682
|
+
} catch (err) {
|
|
14683
|
+
if (!(err instanceof JsCallError) || err.code !== "ENOENT") throw err;
|
|
14684
|
+
const devPath = await tryDev(abs);
|
|
14685
|
+
if (!devPath) throw err;
|
|
14686
|
+
return readWhole(await open(devPath));
|
|
14687
|
+
}
|
|
14688
|
+
},
|
|
14689
|
+
async writeFile(path, data, options) {
|
|
14690
|
+
const mode = options?.mode;
|
|
14691
|
+
const file = await open(path, {
|
|
14692
|
+
write: true,
|
|
14693
|
+
create: true,
|
|
14694
|
+
truncate: true,
|
|
14695
|
+
...mode !== void 0 ? { mode } : {}
|
|
14696
|
+
});
|
|
14036
14697
|
try {
|
|
14037
14698
|
await file.write(0, typeof data === "string" ? encoder4.encode(data) : data);
|
|
14038
14699
|
} finally {
|
|
@@ -14045,6 +14706,7 @@ var KERNEL_INFO, JsExit, encoder4;
|
|
|
14045
14706
|
var init_js_context = __esm({
|
|
14046
14707
|
"src/process/js/js-context.ts"() {
|
|
14047
14708
|
"use strict";
|
|
14709
|
+
init_physical_path();
|
|
14048
14710
|
init_signals();
|
|
14049
14711
|
init_sync_fs_wire();
|
|
14050
14712
|
init_version();
|