@ai-ecoverse/slicc-kernel 1.20.1 → 1.21.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 +14 -0
- package/dist/kernel-worker.js +176 -95
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node.js +176 -95
- package/dist/node.js.map +4 -4
- package/package.json +1 -1
package/dist/node.js
CHANGED
|
@@ -498,7 +498,7 @@ var KernelSocket = class _KernelSocket {
|
|
|
498
498
|
const own = this.changes.wait(signal);
|
|
499
499
|
if (this.state !== "connected" || !this.link) return own;
|
|
500
500
|
const waits = [own, this.link.rx.changed(signal), this.link.tx.changed(signal)];
|
|
501
|
-
for (const
|
|
501
|
+
for (const wait2 of waits) wait2.catch(() => void 0);
|
|
502
502
|
return pipeCall(() => Promise.race(waits));
|
|
503
503
|
}
|
|
504
504
|
bind(addr) {
|
|
@@ -6952,10 +6952,164 @@ function removableMedium(onLost, open = (handle) => new OpfsFs(handle)) {
|
|
|
6952
6952
|
};
|
|
6953
6953
|
}
|
|
6954
6954
|
|
|
6955
|
+
// src/mount/syscall.ts
|
|
6956
|
+
var MS_RDONLY = 1;
|
|
6957
|
+
var MS_MGC_MSK = 4294901760;
|
|
6958
|
+
var MS_MGC_VAL = 3236757504;
|
|
6959
|
+
var IGNORED_FLAGS = 2 | 4 | 8 | 16 | 128 | 1024 | 2048 | 32768 | 1 << 21 | 1 << 24 | 1 << 25;
|
|
6960
|
+
var MNT_FORCE = 1;
|
|
6961
|
+
var MNT_DETACH = 2;
|
|
6962
|
+
var UMOUNT_NOFOLLOW = 8;
|
|
6963
|
+
var GENERIC = /* @__PURE__ */ new Set([
|
|
6964
|
+
"defaults",
|
|
6965
|
+
"async",
|
|
6966
|
+
"sync",
|
|
6967
|
+
"dirsync",
|
|
6968
|
+
"atime",
|
|
6969
|
+
"noatime",
|
|
6970
|
+
"diratime",
|
|
6971
|
+
"nodiratime",
|
|
6972
|
+
"relatime",
|
|
6973
|
+
"norelatime",
|
|
6974
|
+
"strictatime",
|
|
6975
|
+
"nostrictatime",
|
|
6976
|
+
"lazytime",
|
|
6977
|
+
"nolazytime",
|
|
6978
|
+
"suid",
|
|
6979
|
+
"nosuid",
|
|
6980
|
+
"dev",
|
|
6981
|
+
"nodev",
|
|
6982
|
+
"exec",
|
|
6983
|
+
"noexec",
|
|
6984
|
+
"auto",
|
|
6985
|
+
"noauto",
|
|
6986
|
+
"user",
|
|
6987
|
+
"nouser",
|
|
6988
|
+
"users",
|
|
6989
|
+
"nofail",
|
|
6990
|
+
"_netdev",
|
|
6991
|
+
"silent",
|
|
6992
|
+
"loud"
|
|
6993
|
+
]);
|
|
6994
|
+
function parseMountOptions(data) {
|
|
6995
|
+
const options = {};
|
|
6996
|
+
for (const raw of data.split(",")) {
|
|
6997
|
+
const item = raw.trim();
|
|
6998
|
+
if (!item || GENERIC.has(item)) continue;
|
|
6999
|
+
if (item === "rw") {
|
|
7000
|
+
delete options.ro;
|
|
7001
|
+
continue;
|
|
7002
|
+
}
|
|
7003
|
+
const eq = item.indexOf("=");
|
|
7004
|
+
if (eq === 0) throw errnoError("EINVAL", `bad mount option ${item}`);
|
|
7005
|
+
if (eq < 0) options[item] = "";
|
|
7006
|
+
else options[item.slice(0, eq)] = item.slice(eq + 1);
|
|
7007
|
+
}
|
|
7008
|
+
if (options.maxfile !== void 0) parseSize(options.maxfile);
|
|
7009
|
+
return options;
|
|
7010
|
+
}
|
|
7011
|
+
function refusedTarget(target) {
|
|
7012
|
+
const at = normalizePath(target);
|
|
7013
|
+
const kernel = at === "/" || [`/proc`, `/dev`].some((k) => at === k || at.startsWith(`${k}/`));
|
|
7014
|
+
if (kernel) throw errnoError("EBUSY", `${at} belongs to the kernel`);
|
|
7015
|
+
}
|
|
7016
|
+
function absolute(target) {
|
|
7017
|
+
if (!target) throw errnoError("ENOENT", "no mount point");
|
|
7018
|
+
if (!target.startsWith("/")) throw errnoError("EINVAL", `not an absolute path: ${target}`);
|
|
7019
|
+
return normalizePath(target);
|
|
7020
|
+
}
|
|
7021
|
+
function mountCall(call) {
|
|
7022
|
+
let flags = call.flags >>> 0;
|
|
7023
|
+
if ((flags & MS_MGC_MSK) >>> 0 === MS_MGC_VAL) flags &= ~MS_MGC_MSK;
|
|
7024
|
+
if (flags & ~(MS_RDONLY | IGNORED_FLAGS)) {
|
|
7025
|
+
throw errnoError("EINVAL", `unsupported mount flags ${flags.toString(16)}`);
|
|
7026
|
+
}
|
|
7027
|
+
if (!call.type) throw errnoError("EINVAL", "no file system type");
|
|
7028
|
+
const target = absolute(call.target);
|
|
7029
|
+
refusedTarget(target);
|
|
7030
|
+
const options = parseMountOptions(call.data);
|
|
7031
|
+
if (flags & MS_RDONLY) options.ro = "";
|
|
7032
|
+
return { type: call.type, source: call.source || "none", target, options };
|
|
7033
|
+
}
|
|
7034
|
+
function umountCall(target, flags) {
|
|
7035
|
+
const known = MNT_FORCE | MNT_DETACH | UMOUNT_NOFOLLOW;
|
|
7036
|
+
if (flags >>> 0 & ~known) throw errnoError("EINVAL", `unsupported umount flags ${flags}`);
|
|
7037
|
+
const at = absolute(target);
|
|
7038
|
+
refusedTarget(at);
|
|
7039
|
+
return { target: at, detach: (flags & (MNT_FORCE | MNT_DETACH)) !== 0 };
|
|
7040
|
+
}
|
|
7041
|
+
|
|
7042
|
+
// src/mount/fstab.ts
|
|
7043
|
+
var FSTAB_PATH = "/etc/fstab";
|
|
7044
|
+
var FSTAB_RETRIES = [1e3, 4e3, 16e3];
|
|
7045
|
+
var FINAL = /* @__PURE__ */ new Set(["EINVAL", "EBUSY", "EPERM", "EACCES"]);
|
|
7046
|
+
function unescape(field) {
|
|
7047
|
+
return field.replace(
|
|
7048
|
+
/\\([0-7]{3})/g,
|
|
7049
|
+
(_, octal) => String.fromCharCode(Number.parseInt(octal, 8))
|
|
7050
|
+
);
|
|
7051
|
+
}
|
|
7052
|
+
function parseFstab(text) {
|
|
7053
|
+
const lines = [];
|
|
7054
|
+
text.split("\n").forEach((raw, index) => {
|
|
7055
|
+
const content = raw.replace(/#.*$/, "").trim();
|
|
7056
|
+
if (!content) return;
|
|
7057
|
+
const [source, target, type, options = "defaults"] = content.split(/\s+/).map(unescape);
|
|
7058
|
+
if (source === void 0 || target === void 0 || type === void 0) return;
|
|
7059
|
+
if (options.split(",").includes("noauto")) return;
|
|
7060
|
+
const spec = { source, target, type, options: {} };
|
|
7061
|
+
try {
|
|
7062
|
+
lines.push({ line: index + 1, spec: { ...spec, options: parseMountOptions(options) } });
|
|
7063
|
+
} catch (err) {
|
|
7064
|
+
lines.push({ line: index + 1, spec, invalid: err });
|
|
7065
|
+
}
|
|
7066
|
+
});
|
|
7067
|
+
return lines;
|
|
7068
|
+
}
|
|
7069
|
+
function codeOf3(err) {
|
|
7070
|
+
const code = err?.code;
|
|
7071
|
+
return typeof code === "string" ? code : "EIO";
|
|
7072
|
+
}
|
|
7073
|
+
function wait(ms, signal) {
|
|
7074
|
+
if (signal.aborted) return Promise.resolve();
|
|
7075
|
+
return new Promise((resolve) => {
|
|
7076
|
+
const done4 = () => {
|
|
7077
|
+
clearTimeout(timer);
|
|
7078
|
+
signal.removeEventListener("abort", done4);
|
|
7079
|
+
resolve();
|
|
7080
|
+
};
|
|
7081
|
+
const timer = setTimeout(done4, ms);
|
|
7082
|
+
signal.addEventListener("abort", done4, { once: true });
|
|
7083
|
+
});
|
|
7084
|
+
}
|
|
7085
|
+
async function mountFstab(lines, mount, signal, retries = FSTAB_RETRIES, discard = () => {
|
|
7086
|
+
}) {
|
|
7087
|
+
return Promise.all(
|
|
7088
|
+
lines.map(async ({ line, spec, invalid }) => {
|
|
7089
|
+
let failed = invalid;
|
|
7090
|
+
for (let attempt = 0; !invalid && attempt <= retries.length && !signal.aborted; attempt++) {
|
|
7091
|
+
try {
|
|
7092
|
+
const entry = await mount(spec);
|
|
7093
|
+
if (!signal.aborted) return { line, target: spec.target, entry };
|
|
7094
|
+
discard(entry);
|
|
7095
|
+
failed = Object.assign(new Error("the kernel stopped"), { code: "ECANCELED" });
|
|
7096
|
+
break;
|
|
7097
|
+
} catch (err) {
|
|
7098
|
+
failed = err;
|
|
7099
|
+
if (FINAL.has(codeOf3(err)) || attempt === retries.length) break;
|
|
7100
|
+
await wait(retries[attempt], signal);
|
|
7101
|
+
}
|
|
7102
|
+
}
|
|
7103
|
+
const code = codeOf3(failed);
|
|
7104
|
+
return { line, target: spec.target, code, error: String(failed?.message ?? code) };
|
|
7105
|
+
})
|
|
7106
|
+
);
|
|
7107
|
+
}
|
|
7108
|
+
|
|
6955
7109
|
// src/mount/hostfs.ts
|
|
6956
7110
|
var HOSTFS_IO = 16 * 1024 * 1024;
|
|
6957
|
-
var
|
|
6958
|
-
var unreachable = (err) =>
|
|
7111
|
+
var codeOf4 = (err) => err?.code;
|
|
7112
|
+
var unreachable = (err) => codeOf4(err) === "ENOTCONN";
|
|
6959
7113
|
function rel(path) {
|
|
6960
7114
|
return path.replace(/^\/+/, "");
|
|
6961
7115
|
}
|
|
@@ -7090,7 +7244,7 @@ function hostfsHandlers(current) {
|
|
|
7090
7244
|
try {
|
|
7091
7245
|
return { opened: await opening(), restore: void 0 };
|
|
7092
7246
|
} catch (err) {
|
|
7093
|
-
if (!flags.write ||
|
|
7247
|
+
if (!flags.write || codeOf4(err) !== "EACCES") throw err;
|
|
7094
7248
|
const mode = (await client.call("stat", { path: rel(path) })).mode ?? 0;
|
|
7095
7249
|
if (mode & 128) throw err;
|
|
7096
7250
|
const restore = { path: rel(path), mode };
|
|
@@ -7179,7 +7333,7 @@ function keepWatching(loop, signal) {
|
|
|
7179
7333
|
const uncap = () => clearTimeout(capped);
|
|
7180
7334
|
void ready2.promise.then(uncap);
|
|
7181
7335
|
signal.addEventListener("abort", uncap, { once: true });
|
|
7182
|
-
let
|
|
7336
|
+
let wait2 = first;
|
|
7183
7337
|
let up = false;
|
|
7184
7338
|
let current;
|
|
7185
7339
|
async function session() {
|
|
@@ -7224,7 +7378,7 @@ function keepWatching(loop, signal) {
|
|
|
7224
7378
|
const opened2 = await session();
|
|
7225
7379
|
if (signal.aborted) return;
|
|
7226
7380
|
if (opened2 && Date.now() - began >= first) {
|
|
7227
|
-
|
|
7381
|
+
wait2 = first;
|
|
7228
7382
|
continue;
|
|
7229
7383
|
}
|
|
7230
7384
|
if (!opened2 && up) {
|
|
@@ -7232,8 +7386,8 @@ function keepWatching(loop, signal) {
|
|
|
7232
7386
|
loop.down();
|
|
7233
7387
|
}
|
|
7234
7388
|
ready2.resolve();
|
|
7235
|
-
await sleep(
|
|
7236
|
-
|
|
7389
|
+
await sleep(wait2, signal);
|
|
7390
|
+
wait2 = Math.min(wait2 * 2, most);
|
|
7237
7391
|
}
|
|
7238
7392
|
})();
|
|
7239
7393
|
return { ready: ready2.promise, kick: () => current?.abort() };
|
|
@@ -7297,93 +7451,6 @@ function memoryMedia() {
|
|
|
7297
7451
|
};
|
|
7298
7452
|
}
|
|
7299
7453
|
|
|
7300
|
-
// src/mount/syscall.ts
|
|
7301
|
-
var MS_RDONLY = 1;
|
|
7302
|
-
var MS_MGC_MSK = 4294901760;
|
|
7303
|
-
var MS_MGC_VAL = 3236757504;
|
|
7304
|
-
var IGNORED_FLAGS = 2 | 4 | 8 | 16 | 128 | 1024 | 2048 | 32768 | 1 << 21 | 1 << 24 | 1 << 25;
|
|
7305
|
-
var MNT_FORCE = 1;
|
|
7306
|
-
var MNT_DETACH = 2;
|
|
7307
|
-
var UMOUNT_NOFOLLOW = 8;
|
|
7308
|
-
var GENERIC = /* @__PURE__ */ new Set([
|
|
7309
|
-
"defaults",
|
|
7310
|
-
"async",
|
|
7311
|
-
"sync",
|
|
7312
|
-
"dirsync",
|
|
7313
|
-
"atime",
|
|
7314
|
-
"noatime",
|
|
7315
|
-
"diratime",
|
|
7316
|
-
"nodiratime",
|
|
7317
|
-
"relatime",
|
|
7318
|
-
"norelatime",
|
|
7319
|
-
"strictatime",
|
|
7320
|
-
"nostrictatime",
|
|
7321
|
-
"lazytime",
|
|
7322
|
-
"nolazytime",
|
|
7323
|
-
"suid",
|
|
7324
|
-
"nosuid",
|
|
7325
|
-
"dev",
|
|
7326
|
-
"nodev",
|
|
7327
|
-
"exec",
|
|
7328
|
-
"noexec",
|
|
7329
|
-
"auto",
|
|
7330
|
-
"noauto",
|
|
7331
|
-
"user",
|
|
7332
|
-
"nouser",
|
|
7333
|
-
"users",
|
|
7334
|
-
"nofail",
|
|
7335
|
-
"_netdev",
|
|
7336
|
-
"silent",
|
|
7337
|
-
"loud"
|
|
7338
|
-
]);
|
|
7339
|
-
function parseMountOptions(data) {
|
|
7340
|
-
const options = {};
|
|
7341
|
-
for (const raw of data.split(",")) {
|
|
7342
|
-
const item = raw.trim();
|
|
7343
|
-
if (!item || GENERIC.has(item)) continue;
|
|
7344
|
-
if (item === "rw") {
|
|
7345
|
-
delete options.ro;
|
|
7346
|
-
continue;
|
|
7347
|
-
}
|
|
7348
|
-
const eq = item.indexOf("=");
|
|
7349
|
-
if (eq === 0) throw errnoError("EINVAL", `bad mount option ${item}`);
|
|
7350
|
-
if (eq < 0) options[item] = "";
|
|
7351
|
-
else options[item.slice(0, eq)] = item.slice(eq + 1);
|
|
7352
|
-
}
|
|
7353
|
-
if (options.maxfile !== void 0) parseSize(options.maxfile);
|
|
7354
|
-
return options;
|
|
7355
|
-
}
|
|
7356
|
-
function refusedTarget(target) {
|
|
7357
|
-
const at = normalizePath(target);
|
|
7358
|
-
const kernel = at === "/" || [`/proc`, `/dev`].some((k) => at === k || at.startsWith(`${k}/`));
|
|
7359
|
-
if (kernel) throw errnoError("EBUSY", `${at} belongs to the kernel`);
|
|
7360
|
-
}
|
|
7361
|
-
function absolute(target) {
|
|
7362
|
-
if (!target) throw errnoError("ENOENT", "no mount point");
|
|
7363
|
-
if (!target.startsWith("/")) throw errnoError("EINVAL", `not an absolute path: ${target}`);
|
|
7364
|
-
return normalizePath(target);
|
|
7365
|
-
}
|
|
7366
|
-
function mountCall(call) {
|
|
7367
|
-
let flags = call.flags >>> 0;
|
|
7368
|
-
if ((flags & MS_MGC_MSK) >>> 0 === MS_MGC_VAL) flags &= ~MS_MGC_MSK;
|
|
7369
|
-
if (flags & ~(MS_RDONLY | IGNORED_FLAGS)) {
|
|
7370
|
-
throw errnoError("EINVAL", `unsupported mount flags ${flags.toString(16)}`);
|
|
7371
|
-
}
|
|
7372
|
-
if (!call.type) throw errnoError("EINVAL", "no file system type");
|
|
7373
|
-
const target = absolute(call.target);
|
|
7374
|
-
refusedTarget(target);
|
|
7375
|
-
const options = parseMountOptions(call.data);
|
|
7376
|
-
if (flags & MS_RDONLY) options.ro = "";
|
|
7377
|
-
return { type: call.type, source: call.source || "none", target, options };
|
|
7378
|
-
}
|
|
7379
|
-
function umountCall(target, flags) {
|
|
7380
|
-
const known = MNT_FORCE | MNT_DETACH | UMOUNT_NOFOLLOW;
|
|
7381
|
-
if (flags >>> 0 & ~known) throw errnoError("EINVAL", `unsupported umount flags ${flags}`);
|
|
7382
|
-
const at = absolute(target);
|
|
7383
|
-
refusedTarget(at);
|
|
7384
|
-
return { target: at, detach: (flags & (MNT_FORCE | MNT_DETACH)) !== 0 };
|
|
7385
|
-
}
|
|
7386
|
-
|
|
7387
7454
|
// src/mount/tmpfs.ts
|
|
7388
7455
|
function tmpfs() {
|
|
7389
7456
|
let inodes = 0;
|
|
@@ -7802,6 +7869,8 @@ var Launcher = class {
|
|
|
7802
7869
|
openFiles = /* @__PURE__ */ new Set();
|
|
7803
7870
|
held = /* @__PURE__ */ new Set();
|
|
7804
7871
|
processMounts;
|
|
7872
|
+
booting = new AbortController();
|
|
7873
|
+
fstab = Promise.resolve([]);
|
|
7805
7874
|
nextPid = 1e3;
|
|
7806
7875
|
boot = Date.now();
|
|
7807
7876
|
terminals = 0;
|
|
@@ -8209,6 +8278,7 @@ var Launcher = class {
|
|
|
8209
8278
|
for (const holds of this.held) holds.revoke(at);
|
|
8210
8279
|
}
|
|
8211
8280
|
unmountAll() {
|
|
8281
|
+
this.booting.abort();
|
|
8212
8282
|
const targets = this.mounts.list().map((m) => m.target);
|
|
8213
8283
|
for (const target of targets.sort((a, b) => b.length - a.length)) this.umount(target, true);
|
|
8214
8284
|
}
|
|
@@ -8240,6 +8310,17 @@ var Launcher = class {
|
|
|
8240
8310
|
async prepare() {
|
|
8241
8311
|
for (const dir of SHARED_DIRS) await this.base.mkdir(dir, { recursive: true });
|
|
8242
8312
|
await writeCaFile(this.base, this.ca).catch(() => void 0);
|
|
8313
|
+
this.fstab = this.mountFstab();
|
|
8314
|
+
}
|
|
8315
|
+
async mountFstab() {
|
|
8316
|
+
const text = await this.base.readFile(FSTAB_PATH).catch(() => "");
|
|
8317
|
+
return mountFstab(
|
|
8318
|
+
parseFstab(text),
|
|
8319
|
+
(spec) => this.mount(spec),
|
|
8320
|
+
this.booting.signal,
|
|
8321
|
+
FSTAB_RETRIES,
|
|
8322
|
+
(entry) => this.umount(entry.target, true)
|
|
8323
|
+
);
|
|
8243
8324
|
}
|
|
8244
8325
|
environment(cwd, extra) {
|
|
8245
8326
|
return {
|