@secure-exec/core 0.2.0-rc.2 → 0.2.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/dist/generated/isolate-runtime.d.ts +1 -1
- package/dist/generated/isolate-runtime.js +1 -1
- package/dist/index.d.ts +17 -4
- package/dist/index.js +10 -2
- package/dist/isolate-runtime/require-setup.js +145 -7
- package/dist/kernel/device-backend.d.ts +14 -0
- package/dist/kernel/device-backend.js +251 -0
- package/dist/kernel/device-layer.js +9 -0
- package/dist/kernel/index.d.ts +4 -4
- package/dist/kernel/index.js +3 -3
- package/dist/kernel/kernel.js +141 -119
- package/dist/kernel/mount-table.d.ts +75 -0
- package/dist/kernel/mount-table.js +353 -0
- package/dist/kernel/permissions.d.ts +9 -0
- package/dist/kernel/permissions.js +33 -1
- package/dist/kernel/proc-backend.d.ts +30 -0
- package/dist/kernel/proc-backend.js +428 -0
- package/dist/kernel/proc-layer.js +6 -0
- package/dist/kernel/process-table.d.ts +3 -1
- package/dist/kernel/process-table.js +23 -3
- package/dist/kernel/pty.d.ts +3 -2
- package/dist/kernel/pty.js +13 -2
- package/dist/kernel/types.d.ts +45 -4
- package/dist/kernel/types.js +9 -0
- package/dist/kernel/vfs.d.ts +30 -2
- package/dist/kernel/vfs.js +19 -2
- package/dist/shared/api-types.d.ts +6 -0
- package/dist/shared/console-formatter.js +8 -8
- package/dist/shared/in-memory-fs.d.ts +14 -62
- package/dist/shared/in-memory-fs.js +101 -636
- package/dist/shared/permissions.js +5 -0
- package/dist/test/block-store-conformance.d.ts +34 -0
- package/dist/test/block-store-conformance.js +251 -0
- package/dist/test/metadata-store-conformance.d.ts +37 -0
- package/dist/test/metadata-store-conformance.js +646 -0
- package/dist/test/vfs-conformance.d.ts +65 -0
- package/dist/test/vfs-conformance.js +842 -0
- package/dist/types.d.ts +1 -0
- package/dist/vfs/chunked-vfs.d.ts +66 -0
- package/dist/vfs/chunked-vfs.js +1290 -0
- package/dist/vfs/host-block-store.d.ts +19 -0
- package/dist/vfs/host-block-store.js +97 -0
- package/dist/vfs/memory-block-store.d.ts +16 -0
- package/dist/vfs/memory-block-store.js +45 -0
- package/dist/vfs/memory-metadata.d.ts +75 -0
- package/dist/vfs/memory-metadata.js +528 -0
- package/dist/vfs/sqlite-metadata.d.ts +91 -0
- package/dist/vfs/sqlite-metadata.js +582 -0
- package/dist/vfs/types.d.ts +210 -0
- package/dist/vfs/types.js +8 -0
- package/package.json +20 -1
- package/dist/kernel/inode-table.d.ts +0 -43
- package/dist/kernel/inode-table.js +0 -85
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
export { createKernel } from "./kernel/kernel.js";
|
|
2
|
-
export type { Kernel, KernelOptions, KernelInterface, ExecOptions as KernelExecOptions, ExecResult as KernelExecResult, SpawnOptions as KernelSpawnOptions, ManagedProcess, RuntimeDriver as KernelRuntimeDriver, ProcessContext, DriverProcess, ProcessEntry, ProcessInfo, FDStat, FileDescription, FDEntry, Pipe, PermissionDecision, PermissionCheck, FsAccessRequest, NetworkAccessRequest, ChildProcessAccessRequest, EnvAccessRequest, KernelErrorCode, Termios, TermiosCC, OpenShellOptions, ShellHandle, ConnectTerminalOptions, Permissions, } from "./kernel/types.js";
|
|
3
|
-
export { KernelError, defaultTermios } from "./kernel/types.js";
|
|
4
|
-
export type { VirtualFileSystem, VirtualDirEntry, VirtualStat, } from "./kernel/vfs.js";
|
|
2
|
+
export type { FsMount, Kernel, KernelOptions, KernelInterface, KernelLogger, ExecOptions as KernelExecOptions, ExecResult as KernelExecResult, SpawnOptions as KernelSpawnOptions, ManagedProcess, RuntimeDriver as KernelRuntimeDriver, ProcessContext, DriverProcess, ProcessEntry, ProcessInfo, FDStat, FileDescription, FDEntry, Pipe, PermissionDecision, PermissionCheck, FsAccessRequest, NetworkAccessRequest, ChildProcessAccessRequest, EnvAccessRequest, KernelErrorCode, Termios, TermiosCC, OpenShellOptions, ShellHandle, ConnectTerminalOptions, Permissions, } from "./kernel/types.js";
|
|
3
|
+
export { KernelError, defaultTermios, noopKernelLogger } from "./kernel/types.js";
|
|
4
|
+
export type { VirtualFileSystem, VirtualDirEntry, VirtualDirStatEntry, VirtualStat, } from "./kernel/vfs.js";
|
|
5
5
|
export { FDTableManager, ProcessFDTable } from "./kernel/fd-table.js";
|
|
6
6
|
export { ProcessTable } from "./kernel/process-table.js";
|
|
7
7
|
export { TimerTable } from "./kernel/timer-table.js";
|
|
8
8
|
export type { KernelTimer, TimerTableOptions } from "./kernel/timer-table.js";
|
|
9
|
+
export { createDeviceBackend } from "./kernel/device-backend.js";
|
|
9
10
|
export { createDeviceLayer } from "./kernel/device-layer.js";
|
|
11
|
+
export { MountTable } from "./kernel/mount-table.js";
|
|
12
|
+
export type { MountEntry, MountOptions } from "./kernel/mount-table.js";
|
|
10
13
|
export { createProcLayer, createProcessScopedFileSystem, resolveProcSelfPath, } from "./kernel/proc-layer.js";
|
|
14
|
+
export { createProcBackend } from "./kernel/proc-backend.js";
|
|
15
|
+
export type { ProcBackendOptions } from "./kernel/proc-backend.js";
|
|
11
16
|
export { PipeManager } from "./kernel/pipe-manager.js";
|
|
12
17
|
export { PtyManager } from "./kernel/pty.js";
|
|
13
18
|
export type { LineDisciplineConfig } from "./kernel/pty.js";
|
|
@@ -25,7 +30,7 @@ export type { CommandExecutor, NetworkAdapter, NetworkServerAddress, NetworkServ
|
|
|
25
30
|
export type { DriverRuntimeConfig, NodeRuntimeDriver, NodeRuntimeDriverFactory, PythonRuntimeDriver, PythonRuntimeDriverFactory, ResourceBudgets, RuntimeDriver, RuntimeDriverFactory, RuntimeDriverOptions, SharedRuntimeDriver, SystemDriver, } from "./runtime-driver.js";
|
|
26
31
|
export type { ExecOptions, ExecResult, ExecutionStatus, OSConfig, ProcessConfig, PythonRunOptions, PythonRunResult, RunResult, StdioChannel, StdioEvent, StdioHook, TimingMitigation, } from "./shared/api-types.js";
|
|
27
32
|
export { TIMEOUT_EXIT_CODE, TIMEOUT_ERROR_MESSAGE, } from "./shared/constants.js";
|
|
28
|
-
export { createInMemoryFileSystem
|
|
33
|
+
export { createInMemoryFileSystem } from "./shared/in-memory-fs.js";
|
|
29
34
|
export { allowAll, allowAllChildProcess, allowAllEnv, allowAllFs, allowAllNetwork, createCommandExecutorStub, createFsStub, createNetworkStub, envAccessAllowed, filterEnv, wrapCommandExecutor, wrapFileSystem, wrapNetworkAdapter, } from "./shared/permissions.js";
|
|
30
35
|
export type { SystemError } from "./shared/errors.js";
|
|
31
36
|
export { createEaccesError, createEnosysError, createSystemError, } from "./shared/errors.js";
|
|
@@ -40,6 +45,14 @@ export { exposeCustomGlobal, exposeGlobalBinding, exposeMutableRuntimeStateGloba
|
|
|
40
45
|
export type { IsolateRuntimeSourceId } from "./generated/isolate-runtime.js";
|
|
41
46
|
export { getIsolateRuntimeSource, ISOLATE_RUNTIME_SOURCES, } from "./generated/isolate-runtime.js";
|
|
42
47
|
export { POLYFILL_CODE_MAP } from "./generated/polyfills.js";
|
|
48
|
+
export type { InodeType, CreateInodeAttrs, InodeMeta, DentryInfo, DentryStatInfo, FsMetadataStore, FsBlockStore, FsMetadataStoreVersioning, VersionMeta, VersionInfo, RetentionPolicy, } from "./vfs/types.js";
|
|
49
|
+
export { InMemoryMetadataStore } from "./vfs/memory-metadata.js";
|
|
50
|
+
export { InMemoryBlockStore } from "./vfs/memory-block-store.js";
|
|
51
|
+
export { SqliteMetadataStore } from "./vfs/sqlite-metadata.js";
|
|
52
|
+
export type { SqliteMetadataStoreOptions } from "./vfs/sqlite-metadata.js";
|
|
53
|
+
export { createChunkedVfs } from "./vfs/chunked-vfs.js";
|
|
54
|
+
export type { ChunkedVfsOptions, ChunkedVfsVersioning } from "./vfs/chunked-vfs.js";
|
|
55
|
+
export { HostBlockStore } from "./vfs/host-block-store.js";
|
|
43
56
|
export type { DirEntry, StatInfo } from "./fs-helpers.js";
|
|
44
57
|
export { exists, stat, rename, readDirWithTypes, mkdir } from "./fs-helpers.js";
|
|
45
58
|
export { BUILTIN_NAMED_EXPORTS, normalizeBuiltinSpecifier, getPathDir, } from "./module-resolver.js";
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
// Kernel — VFS, process table, FD table, device layer, pipes, PTY, command registry, permissions.
|
|
2
2
|
export { createKernel } from "./kernel/kernel.js";
|
|
3
|
-
export { KernelError, defaultTermios } from "./kernel/types.js";
|
|
3
|
+
export { KernelError, defaultTermios, noopKernelLogger } from "./kernel/types.js";
|
|
4
4
|
// Kernel components.
|
|
5
5
|
export { FDTableManager, ProcessFDTable } from "./kernel/fd-table.js";
|
|
6
6
|
export { ProcessTable } from "./kernel/process-table.js";
|
|
7
7
|
export { TimerTable } from "./kernel/timer-table.js";
|
|
8
|
+
export { createDeviceBackend } from "./kernel/device-backend.js";
|
|
8
9
|
export { createDeviceLayer } from "./kernel/device-layer.js";
|
|
10
|
+
export { MountTable } from "./kernel/mount-table.js";
|
|
9
11
|
export { createProcLayer, createProcessScopedFileSystem, resolveProcSelfPath, } from "./kernel/proc-layer.js";
|
|
12
|
+
export { createProcBackend } from "./kernel/proc-backend.js";
|
|
10
13
|
export { PipeManager } from "./kernel/pipe-manager.js";
|
|
11
14
|
export { PtyManager } from "./kernel/pty.js";
|
|
12
15
|
export { CommandRegistry } from "./kernel/command-registry.js";
|
|
@@ -24,7 +27,7 @@ export { encodeExitStatus, encodeSignalStatus, WIFEXITED, WEXITSTATUS, WIFSIGNAL
|
|
|
24
27
|
// Shared constants.
|
|
25
28
|
export { TIMEOUT_EXIT_CODE, TIMEOUT_ERROR_MESSAGE, } from "./shared/constants.js";
|
|
26
29
|
// Shared utilities.
|
|
27
|
-
export { createInMemoryFileSystem
|
|
30
|
+
export { createInMemoryFileSystem } from "./shared/in-memory-fs.js";
|
|
28
31
|
export { allowAll, allowAllChildProcess, allowAllEnv, allowAllFs, allowAllNetwork, createCommandExecutorStub, createFsStub, createNetworkStub, envAccessAllowed, filterEnv, wrapCommandExecutor, wrapFileSystem, wrapNetworkAdapter, } from "./shared/permissions.js";
|
|
29
32
|
export { createEaccesError, createEnosysError, createSystemError, } from "./shared/errors.js";
|
|
30
33
|
export { extractCjsNamedExports, extractDynamicImportSpecifiers, isESM, transformDynamicImport, wrapCJSForESM, wrapCJSForESMWithModulePath, } from "./shared/esm-utils.js";
|
|
@@ -35,6 +38,11 @@ export { exposeCustomGlobal, exposeGlobalBinding, exposeMutableRuntimeStateGloba
|
|
|
35
38
|
export { getIsolateRuntimeSource, ISOLATE_RUNTIME_SOURCES, } from "./generated/isolate-runtime.js";
|
|
36
39
|
// Generated polyfills.
|
|
37
40
|
export { POLYFILL_CODE_MAP } from "./generated/polyfills.js";
|
|
41
|
+
export { InMemoryMetadataStore } from "./vfs/memory-metadata.js";
|
|
42
|
+
export { InMemoryBlockStore } from "./vfs/memory-block-store.js";
|
|
43
|
+
export { SqliteMetadataStore } from "./vfs/sqlite-metadata.js";
|
|
44
|
+
export { createChunkedVfs } from "./vfs/chunked-vfs.js";
|
|
45
|
+
export { HostBlockStore } from "./vfs/host-block-store.js";
|
|
38
46
|
export { exists, stat, rename, readDirWithTypes, mkdir } from "./fs-helpers.js";
|
|
39
47
|
// Module resolution.
|
|
40
48
|
export { BUILTIN_NAMED_EXPORTS, normalizeBuiltinSpecifier, getPathDir, } from "./module-resolver.js";
|
|
@@ -525,7 +525,7 @@
|
|
|
525
525
|
return "utf-8";
|
|
526
526
|
}
|
|
527
527
|
});
|
|
528
|
-
function
|
|
528
|
+
function TextDecoder2(label, options) {
|
|
529
529
|
var normalizedOptions = options == null ? {} : Object(options);
|
|
530
530
|
this._encoding = _normalizeEncodingLabel(label);
|
|
531
531
|
this._fatal = Boolean(normalizedOptions.fatal);
|
|
@@ -533,22 +533,22 @@
|
|
|
533
533
|
this._pendingBytes = [];
|
|
534
534
|
this._bomSeen = false;
|
|
535
535
|
}
|
|
536
|
-
Object.defineProperty(
|
|
536
|
+
Object.defineProperty(TextDecoder2.prototype, "encoding", {
|
|
537
537
|
get: function() {
|
|
538
538
|
return this._encoding;
|
|
539
539
|
}
|
|
540
540
|
});
|
|
541
|
-
Object.defineProperty(
|
|
541
|
+
Object.defineProperty(TextDecoder2.prototype, "fatal", {
|
|
542
542
|
get: function() {
|
|
543
543
|
return this._fatal;
|
|
544
544
|
}
|
|
545
545
|
});
|
|
546
|
-
Object.defineProperty(
|
|
546
|
+
Object.defineProperty(TextDecoder2.prototype, "ignoreBOM", {
|
|
547
547
|
get: function() {
|
|
548
548
|
return this._ignoreBOM;
|
|
549
549
|
}
|
|
550
550
|
});
|
|
551
|
-
|
|
551
|
+
TextDecoder2.prototype.decode = function decode(input, options) {
|
|
552
552
|
var normalizedOptions = options == null ? {} : Object(options);
|
|
553
553
|
var stream = Boolean(normalizedOptions.stream);
|
|
554
554
|
var incoming = _toUint8Array(input);
|
|
@@ -743,7 +743,7 @@
|
|
|
743
743
|
return !event.defaultPrevented;
|
|
744
744
|
};
|
|
745
745
|
globalThis.TextEncoder = TextEncoder;
|
|
746
|
-
globalThis.TextDecoder =
|
|
746
|
+
globalThis.TextDecoder = TextDecoder2;
|
|
747
747
|
globalThis.Event = Event;
|
|
748
748
|
globalThis.CustomEvent = CustomEvent;
|
|
749
749
|
globalThis.EventTarget = EventTarget;
|
|
@@ -3437,9 +3437,137 @@
|
|
|
3437
3437
|
MessageChannel: globalThis.MessageChannel,
|
|
3438
3438
|
MessageEvent: globalThis.MessageEvent
|
|
3439
3439
|
};
|
|
3440
|
+
const readlineCompat = {
|
|
3441
|
+
createInterface: function createInterface(opts) {
|
|
3442
|
+
const input = opts && opts.input ? opts.input : typeof process !== "undefined" ? process.stdin : null;
|
|
3443
|
+
const output = opts && opts.output ? opts.output : typeof process !== "undefined" ? process.stdout : null;
|
|
3444
|
+
const listeners = {};
|
|
3445
|
+
const rl = {
|
|
3446
|
+
input,
|
|
3447
|
+
output,
|
|
3448
|
+
terminal: false,
|
|
3449
|
+
closed: false,
|
|
3450
|
+
on: function(event, handler) {
|
|
3451
|
+
(listeners[event] = listeners[event] || []).push(handler);
|
|
3452
|
+
return rl;
|
|
3453
|
+
},
|
|
3454
|
+
once: function(event, handler) {
|
|
3455
|
+
const wrapper = function() {
|
|
3456
|
+
rl.off(event, wrapper);
|
|
3457
|
+
handler.apply(this, arguments);
|
|
3458
|
+
};
|
|
3459
|
+
return rl.on(event, wrapper);
|
|
3460
|
+
},
|
|
3461
|
+
off: function(event, handler) {
|
|
3462
|
+
if (listeners[event]) listeners[event] = listeners[event].filter(function(h) {
|
|
3463
|
+
return h !== handler;
|
|
3464
|
+
});
|
|
3465
|
+
return rl;
|
|
3466
|
+
},
|
|
3467
|
+
removeListener: function(event, handler) {
|
|
3468
|
+
return rl.off(event, handler);
|
|
3469
|
+
},
|
|
3470
|
+
emit: function(event) {
|
|
3471
|
+
const args = Array.prototype.slice.call(arguments, 1);
|
|
3472
|
+
(listeners[event] || []).forEach(function(h) {
|
|
3473
|
+
h.apply(null, args);
|
|
3474
|
+
});
|
|
3475
|
+
return rl;
|
|
3476
|
+
},
|
|
3477
|
+
close: function() {
|
|
3478
|
+
if (!rl.closed) {
|
|
3479
|
+
rl.closed = true;
|
|
3480
|
+
rl.emit("close");
|
|
3481
|
+
}
|
|
3482
|
+
},
|
|
3483
|
+
question: function(query, cb) {
|
|
3484
|
+
if (output && output.write) output.write(query);
|
|
3485
|
+
if (input && input.once) {
|
|
3486
|
+
var buf = "";
|
|
3487
|
+
var onData = function(chunk) {
|
|
3488
|
+
buf += typeof chunk === "string" ? chunk : new TextDecoder().decode(chunk);
|
|
3489
|
+
var idx = buf.indexOf("\n");
|
|
3490
|
+
if (idx !== -1) {
|
|
3491
|
+
input.removeListener("data", onData);
|
|
3492
|
+
cb(buf.slice(0, idx));
|
|
3493
|
+
}
|
|
3494
|
+
};
|
|
3495
|
+
input.on("data", onData);
|
|
3496
|
+
} else {
|
|
3497
|
+
cb("");
|
|
3498
|
+
}
|
|
3499
|
+
},
|
|
3500
|
+
prompt: function() {
|
|
3501
|
+
if (output && output.write) output.write("> ");
|
|
3502
|
+
},
|
|
3503
|
+
setPrompt: function() {
|
|
3504
|
+
},
|
|
3505
|
+
pause: function() {
|
|
3506
|
+
return rl;
|
|
3507
|
+
},
|
|
3508
|
+
resume: function() {
|
|
3509
|
+
return rl;
|
|
3510
|
+
},
|
|
3511
|
+
write: function() {
|
|
3512
|
+
},
|
|
3513
|
+
[Symbol.asyncIterator]: function() {
|
|
3514
|
+
return rl._iterState;
|
|
3515
|
+
}
|
|
3516
|
+
};
|
|
3517
|
+
var _lineBuf = "";
|
|
3518
|
+
var _iterLines = [];
|
|
3519
|
+
var _iterResolve = null;
|
|
3520
|
+
var _iterDone = false;
|
|
3521
|
+
rl._iterState = {
|
|
3522
|
+
next: function() {
|
|
3523
|
+
if (_iterLines.length > 0) return Promise.resolve({ value: _iterLines.shift(), done: false });
|
|
3524
|
+
if (_iterDone) return Promise.resolve({ value: void 0, done: true });
|
|
3525
|
+
return new Promise(function(r) {
|
|
3526
|
+
_iterResolve = r;
|
|
3527
|
+
}).then(function() {
|
|
3528
|
+
if (_iterLines.length > 0) return { value: _iterLines.shift(), done: false };
|
|
3529
|
+
return { value: void 0, done: true };
|
|
3530
|
+
});
|
|
3531
|
+
}
|
|
3532
|
+
};
|
|
3533
|
+
if (input && input.on) {
|
|
3534
|
+
input.on("data", function(chunk) {
|
|
3535
|
+
_lineBuf += typeof chunk === "string" ? chunk : new TextDecoder().decode(chunk);
|
|
3536
|
+
var idx;
|
|
3537
|
+
while ((idx = _lineBuf.indexOf("\n")) !== -1) {
|
|
3538
|
+
var line = _lineBuf.slice(0, idx);
|
|
3539
|
+
_lineBuf = _lineBuf.slice(idx + 1);
|
|
3540
|
+
rl.emit("line", line);
|
|
3541
|
+
_iterLines.push(line);
|
|
3542
|
+
if (_iterResolve) {
|
|
3543
|
+
_iterResolve();
|
|
3544
|
+
_iterResolve = null;
|
|
3545
|
+
}
|
|
3546
|
+
}
|
|
3547
|
+
});
|
|
3548
|
+
input.on("end", function() {
|
|
3549
|
+
rl.emit("close");
|
|
3550
|
+
_iterDone = true;
|
|
3551
|
+
if (_iterResolve) {
|
|
3552
|
+
_iterResolve();
|
|
3553
|
+
_iterResolve = null;
|
|
3554
|
+
}
|
|
3555
|
+
});
|
|
3556
|
+
if (input.resume) input.resume();
|
|
3557
|
+
}
|
|
3558
|
+
return rl;
|
|
3559
|
+
},
|
|
3560
|
+
promises: {
|
|
3561
|
+
createInterface: function createInterface(opts) {
|
|
3562
|
+
return readlineCompat.createInterface(opts);
|
|
3563
|
+
}
|
|
3564
|
+
}
|
|
3565
|
+
};
|
|
3440
3566
|
const moduleCompat = {
|
|
3441
3567
|
worker_threads: workerThreadsCompat,
|
|
3442
|
-
"node:worker_threads": workerThreadsCompat
|
|
3568
|
+
"node:worker_threads": workerThreadsCompat,
|
|
3569
|
+
readline: readlineCompat,
|
|
3570
|
+
"node:readline": readlineCompat
|
|
3443
3571
|
};
|
|
3444
3572
|
let stub = null;
|
|
3445
3573
|
stub = new Proxy({}, {
|
|
@@ -3861,6 +3989,16 @@
|
|
|
3861
3989
|
_debugRequire("loaded", name, "diagnostics-channel-special");
|
|
3862
3990
|
return dcModule;
|
|
3863
3991
|
}
|
|
3992
|
+
if (name === "path/win32") {
|
|
3993
|
+
var pathMod = _requireFrom("path", fromDir);
|
|
3994
|
+
__internalModuleCache[name] = pathMod.win32 || pathMod;
|
|
3995
|
+
return __internalModuleCache[name];
|
|
3996
|
+
}
|
|
3997
|
+
if (name === "path/posix") {
|
|
3998
|
+
var pathMod2 = _requireFrom("path", fromDir);
|
|
3999
|
+
__internalModuleCache[name] = pathMod2.posix || pathMod2;
|
|
4000
|
+
return __internalModuleCache[name];
|
|
4001
|
+
}
|
|
3864
4002
|
if (_deferredCoreModules.has(name)) {
|
|
3865
4003
|
if (__internalModuleCache[name]) return __internalModuleCache[name];
|
|
3866
4004
|
const deferredStub = _createDeferredModuleStub(name);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device backend.
|
|
3
|
+
*
|
|
4
|
+
* Standalone VirtualFileSystem that handles device nodes.
|
|
5
|
+
* Receives relative paths (e.g. "null" not "/dev/null").
|
|
6
|
+
* Designed to be mounted at /dev via MountTable.
|
|
7
|
+
*/
|
|
8
|
+
import type { VirtualFileSystem } from "./vfs.js";
|
|
9
|
+
/**
|
|
10
|
+
* Create a standalone device backend VFS.
|
|
11
|
+
* All paths are relative to /dev (e.g. "null", "zero", "pts/0").
|
|
12
|
+
* Mount at /dev via MountTable.
|
|
13
|
+
*/
|
|
14
|
+
export declare function createDeviceBackend(): VirtualFileSystem;
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device backend.
|
|
3
|
+
*
|
|
4
|
+
* Standalone VirtualFileSystem that handles device nodes.
|
|
5
|
+
* Receives relative paths (e.g. "null" not "/dev/null").
|
|
6
|
+
* Designed to be mounted at /dev via MountTable.
|
|
7
|
+
*/
|
|
8
|
+
import { KernelError } from "./types.js";
|
|
9
|
+
const DEVICE_NAMES = new Set([
|
|
10
|
+
"null",
|
|
11
|
+
"zero",
|
|
12
|
+
"stdin",
|
|
13
|
+
"stdout",
|
|
14
|
+
"stderr",
|
|
15
|
+
"urandom",
|
|
16
|
+
"random",
|
|
17
|
+
"tty",
|
|
18
|
+
"console",
|
|
19
|
+
"full",
|
|
20
|
+
"ptmx",
|
|
21
|
+
]);
|
|
22
|
+
const DEVICE_INO = {
|
|
23
|
+
null: 0xffff_0001,
|
|
24
|
+
zero: 0xffff_0002,
|
|
25
|
+
stdin: 0xffff_0003,
|
|
26
|
+
stdout: 0xffff_0004,
|
|
27
|
+
stderr: 0xffff_0005,
|
|
28
|
+
urandom: 0xffff_0006,
|
|
29
|
+
random: 0xffff_0007,
|
|
30
|
+
tty: 0xffff_0008,
|
|
31
|
+
console: 0xffff_0009,
|
|
32
|
+
full: 0xffff_000a,
|
|
33
|
+
ptmx: 0xffff_000b,
|
|
34
|
+
};
|
|
35
|
+
/** Device pseudo-directories that contain dynamic entries. */
|
|
36
|
+
const DEVICE_DIRS = new Set(["fd", "pts", "shm"]);
|
|
37
|
+
function isDeviceName(path) {
|
|
38
|
+
return (DEVICE_NAMES.has(path) || path.startsWith("fd/") || path.startsWith("pts/"));
|
|
39
|
+
}
|
|
40
|
+
function isDeviceDir(path) {
|
|
41
|
+
return path === "" || DEVICE_DIRS.has(path);
|
|
42
|
+
}
|
|
43
|
+
function deviceStat(path) {
|
|
44
|
+
const now = Date.now();
|
|
45
|
+
return {
|
|
46
|
+
mode: 0o666,
|
|
47
|
+
size: 0,
|
|
48
|
+
isDirectory: false,
|
|
49
|
+
isSymbolicLink: false,
|
|
50
|
+
atimeMs: now,
|
|
51
|
+
mtimeMs: now,
|
|
52
|
+
ctimeMs: now,
|
|
53
|
+
birthtimeMs: now,
|
|
54
|
+
ino: DEVICE_INO[path] ?? 0xffff_0000,
|
|
55
|
+
nlink: 1,
|
|
56
|
+
uid: 0,
|
|
57
|
+
gid: 0,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function dirStat(path) {
|
|
61
|
+
const now = Date.now();
|
|
62
|
+
return {
|
|
63
|
+
mode: 0o755,
|
|
64
|
+
size: 0,
|
|
65
|
+
isDirectory: true,
|
|
66
|
+
isSymbolicLink: false,
|
|
67
|
+
atimeMs: now,
|
|
68
|
+
mtimeMs: now,
|
|
69
|
+
ctimeMs: now,
|
|
70
|
+
birthtimeMs: now,
|
|
71
|
+
ino: DEVICE_INO[path] ?? 0xffff_0000,
|
|
72
|
+
nlink: 2,
|
|
73
|
+
uid: 0,
|
|
74
|
+
gid: 0,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
const DEV_DIR_ENTRIES = [
|
|
78
|
+
{ name: "null", isDirectory: false },
|
|
79
|
+
{ name: "zero", isDirectory: false },
|
|
80
|
+
{ name: "stdin", isDirectory: false },
|
|
81
|
+
{ name: "stdout", isDirectory: false },
|
|
82
|
+
{ name: "stderr", isDirectory: false },
|
|
83
|
+
{ name: "urandom", isDirectory: false },
|
|
84
|
+
{ name: "random", isDirectory: false },
|
|
85
|
+
{ name: "tty", isDirectory: false },
|
|
86
|
+
{ name: "console", isDirectory: false },
|
|
87
|
+
{ name: "full", isDirectory: false },
|
|
88
|
+
{ name: "ptmx", isDirectory: false },
|
|
89
|
+
{ name: "fd", isDirectory: true },
|
|
90
|
+
{ name: "pts", isDirectory: true },
|
|
91
|
+
{ name: "shm", isDirectory: true },
|
|
92
|
+
];
|
|
93
|
+
function randomBytes(length) {
|
|
94
|
+
const buf = new Uint8Array(length);
|
|
95
|
+
if (typeof globalThis.crypto?.getRandomValues === "function") {
|
|
96
|
+
globalThis.crypto.getRandomValues(buf);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
for (let i = 0; i < buf.length; i++) {
|
|
100
|
+
buf[i] = (Math.random() * 256) | 0;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return buf;
|
|
104
|
+
}
|
|
105
|
+
function notFound(path) {
|
|
106
|
+
throw new KernelError("ENOENT", `no such device: ${path}`);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Create a standalone device backend VFS.
|
|
110
|
+
* All paths are relative to /dev (e.g. "null", "zero", "pts/0").
|
|
111
|
+
* Mount at /dev via MountTable.
|
|
112
|
+
*/
|
|
113
|
+
export function createDeviceBackend() {
|
|
114
|
+
const backend = {
|
|
115
|
+
async readFile(path) {
|
|
116
|
+
if (path === "null" || path === "full")
|
|
117
|
+
return new Uint8Array(0);
|
|
118
|
+
if (path === "zero")
|
|
119
|
+
return new Uint8Array(4096);
|
|
120
|
+
if (path === "urandom" || path === "random")
|
|
121
|
+
return randomBytes(4096);
|
|
122
|
+
if (path === "tty" || path === "console" || path === "ptmx")
|
|
123
|
+
return new Uint8Array(0);
|
|
124
|
+
if (path === "stdin" || path === "stdout" || path === "stderr")
|
|
125
|
+
return new Uint8Array(0);
|
|
126
|
+
notFound(path);
|
|
127
|
+
},
|
|
128
|
+
async pread(path, _offset, length) {
|
|
129
|
+
if (path === "null" || path === "full")
|
|
130
|
+
return new Uint8Array(0);
|
|
131
|
+
if (path === "zero")
|
|
132
|
+
return new Uint8Array(length);
|
|
133
|
+
if (path === "urandom" || path === "random")
|
|
134
|
+
return randomBytes(length);
|
|
135
|
+
if (path === "tty" || path === "console" || path === "ptmx")
|
|
136
|
+
return new Uint8Array(0);
|
|
137
|
+
if (path === "stdin" || path === "stdout" || path === "stderr")
|
|
138
|
+
return new Uint8Array(0);
|
|
139
|
+
notFound(path);
|
|
140
|
+
},
|
|
141
|
+
async readTextFile(path) {
|
|
142
|
+
const bytes = await this.readFile(path);
|
|
143
|
+
return new TextDecoder().decode(bytes);
|
|
144
|
+
},
|
|
145
|
+
async readDir(path) {
|
|
146
|
+
if (path === "")
|
|
147
|
+
return DEV_DIR_ENTRIES.map((e) => e.name);
|
|
148
|
+
if (DEVICE_DIRS.has(path))
|
|
149
|
+
return [];
|
|
150
|
+
notFound(path);
|
|
151
|
+
},
|
|
152
|
+
async readDirWithTypes(path) {
|
|
153
|
+
if (path === "")
|
|
154
|
+
return DEV_DIR_ENTRIES;
|
|
155
|
+
if (DEVICE_DIRS.has(path))
|
|
156
|
+
return [];
|
|
157
|
+
notFound(path);
|
|
158
|
+
},
|
|
159
|
+
async writeFile(path, _content) {
|
|
160
|
+
if (path === "full")
|
|
161
|
+
throw new KernelError("ENOSPC", "No space left on device");
|
|
162
|
+
if (DEVICE_NAMES.has(path) ||
|
|
163
|
+
path.startsWith("fd/") ||
|
|
164
|
+
path.startsWith("pts/")) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
notFound(path);
|
|
168
|
+
},
|
|
169
|
+
async pwrite(path, _offset, _data) {
|
|
170
|
+
if (path === "full")
|
|
171
|
+
throw new KernelError("ENOSPC", "No space left on device");
|
|
172
|
+
if (DEVICE_NAMES.has(path) ||
|
|
173
|
+
path.startsWith("fd/") ||
|
|
174
|
+
path.startsWith("pts/")) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
notFound(path);
|
|
178
|
+
},
|
|
179
|
+
async createDir(path) {
|
|
180
|
+
if (isDeviceDir(path))
|
|
181
|
+
return;
|
|
182
|
+
throw new KernelError("EPERM", "cannot create directory in /dev");
|
|
183
|
+
},
|
|
184
|
+
async mkdir(path, _options) {
|
|
185
|
+
if (isDeviceDir(path))
|
|
186
|
+
return;
|
|
187
|
+
throw new KernelError("EPERM", "cannot create directory in /dev");
|
|
188
|
+
},
|
|
189
|
+
async exists(path) {
|
|
190
|
+
return isDeviceName(path) || isDeviceDir(path);
|
|
191
|
+
},
|
|
192
|
+
async stat(path) {
|
|
193
|
+
if (isDeviceName(path))
|
|
194
|
+
return deviceStat(path);
|
|
195
|
+
if (isDeviceDir(path))
|
|
196
|
+
return dirStat(path);
|
|
197
|
+
notFound(path);
|
|
198
|
+
},
|
|
199
|
+
async removeFile(path) {
|
|
200
|
+
if (isDeviceName(path))
|
|
201
|
+
throw new KernelError("EPERM", "cannot remove device");
|
|
202
|
+
notFound(path);
|
|
203
|
+
},
|
|
204
|
+
async removeDir(path) {
|
|
205
|
+
if (isDeviceDir(path))
|
|
206
|
+
throw new KernelError("EPERM", "cannot remove device directory");
|
|
207
|
+
notFound(path);
|
|
208
|
+
},
|
|
209
|
+
async rename(_oldPath, _newPath) {
|
|
210
|
+
throw new KernelError("EPERM", "cannot rename device");
|
|
211
|
+
},
|
|
212
|
+
async realpath(path) {
|
|
213
|
+
if (isDeviceName(path) || isDeviceDir(path))
|
|
214
|
+
return path;
|
|
215
|
+
notFound(path);
|
|
216
|
+
},
|
|
217
|
+
async symlink(_target, _linkPath) {
|
|
218
|
+
throw new KernelError("EPERM", "cannot create symlink in /dev");
|
|
219
|
+
},
|
|
220
|
+
async readlink(path) {
|
|
221
|
+
notFound(path);
|
|
222
|
+
},
|
|
223
|
+
async lstat(path) {
|
|
224
|
+
return this.stat(path);
|
|
225
|
+
},
|
|
226
|
+
async link(_oldPath, _newPath) {
|
|
227
|
+
throw new KernelError("EPERM", "cannot link device");
|
|
228
|
+
},
|
|
229
|
+
async chmod(path, _mode) {
|
|
230
|
+
if (isDeviceName(path) || isDeviceDir(path))
|
|
231
|
+
return;
|
|
232
|
+
notFound(path);
|
|
233
|
+
},
|
|
234
|
+
async chown(path, _uid, _gid) {
|
|
235
|
+
if (isDeviceName(path) || isDeviceDir(path))
|
|
236
|
+
return;
|
|
237
|
+
notFound(path);
|
|
238
|
+
},
|
|
239
|
+
async utimes(path, _atime, _mtime) {
|
|
240
|
+
if (isDeviceName(path) || isDeviceDir(path))
|
|
241
|
+
return;
|
|
242
|
+
notFound(path);
|
|
243
|
+
},
|
|
244
|
+
async truncate(path, _length) {
|
|
245
|
+
if (isDeviceName(path) || isDeviceDir(path))
|
|
246
|
+
return;
|
|
247
|
+
notFound(path);
|
|
248
|
+
},
|
|
249
|
+
};
|
|
250
|
+
return backend;
|
|
251
|
+
}
|
|
@@ -160,6 +160,15 @@ export function createDeviceLayer(vfs) {
|
|
|
160
160
|
return;
|
|
161
161
|
return vfs.writeFile(path, content);
|
|
162
162
|
},
|
|
163
|
+
async pwrite(path, offset, data) {
|
|
164
|
+
if (path === "/dev/full")
|
|
165
|
+
throw new KernelError("ENOSPC", "No space left on device");
|
|
166
|
+
if (path === "/dev/null" || path === "/dev/zero" || path === "/dev/urandom"
|
|
167
|
+
|| path === "/dev/random" || path === "/dev/tty" || path === "/dev/console"
|
|
168
|
+
|| path === "/dev/ptmx")
|
|
169
|
+
return;
|
|
170
|
+
return vfs.pwrite(path, offset, data);
|
|
171
|
+
},
|
|
163
172
|
async createDir(path) {
|
|
164
173
|
if (isDeviceDir(path))
|
|
165
174
|
return;
|
package/dist/kernel/index.d.ts
CHANGED
|
@@ -6,21 +6,21 @@
|
|
|
6
6
|
* same kernel instance.
|
|
7
7
|
*/
|
|
8
8
|
export { createKernel } from "./kernel.js";
|
|
9
|
-
export type { Kernel, KernelOptions, KernelInterface, ExecOptions, ExecResult, SpawnOptions, ManagedProcess, RuntimeDriver, ProcessContext, DriverProcess, ProcessEntry, ProcessInfo, FDStat, FileDescription, FDEntry, Pipe, Permissions, PermissionDecision, PermissionCheck, FsAccessRequest, NetworkAccessRequest, ChildProcessAccessRequest, EnvAccessRequest, KernelErrorCode, SignalDisposition, SignalHandler, ProcessSignalState, Termios, TermiosCC, OpenShellOptions, ShellHandle, ConnectTerminalOptions, } from "./types.js";
|
|
10
|
-
export { KernelError, defaultTermios } from "./types.js";
|
|
9
|
+
export type { FsMount, Kernel, KernelOptions, KernelInterface, KernelLogger, ExecOptions, ExecResult, SpawnOptions, ManagedProcess, RuntimeDriver, ProcessContext, DriverProcess, ProcessEntry, ProcessInfo, FDStat, FileDescription, FDEntry, Pipe, Permissions, PermissionDecision, PermissionCheck, FsAccessRequest, NetworkAccessRequest, ChildProcessAccessRequest, EnvAccessRequest, KernelErrorCode, SignalDisposition, SignalHandler, ProcessSignalState, Termios, TermiosCC, OpenShellOptions, ShellHandle, ConnectTerminalOptions, } from "./types.js";
|
|
10
|
+
export { KernelError, defaultTermios, noopKernelLogger } from "./types.js";
|
|
11
11
|
export type { VirtualFileSystem, VirtualDirEntry, VirtualStat, } from "./vfs.js";
|
|
12
12
|
export { FDTableManager, ProcessFDTable } from "./fd-table.js";
|
|
13
13
|
export { ProcessTable } from "./process-table.js";
|
|
14
14
|
export { createDeviceLayer } from "./device-layer.js";
|
|
15
15
|
export { createProcLayer, createProcessScopedFileSystem, resolveProcSelfPath, } from "./proc-layer.js";
|
|
16
|
+
export { createProcBackend } from "./proc-backend.js";
|
|
17
|
+
export type { ProcBackendOptions } from "./proc-backend.js";
|
|
16
18
|
export { PipeManager } from "./pipe-manager.js";
|
|
17
19
|
export { PtyManager } from "./pty.js";
|
|
18
20
|
export type { LineDisciplineConfig } from "./pty.js";
|
|
19
21
|
export { CommandRegistry } from "./command-registry.js";
|
|
20
22
|
export { FileLockManager, LOCK_SH, LOCK_EX, LOCK_UN, LOCK_NB } from "./file-lock.js";
|
|
21
23
|
export { WaitHandle, WaitQueue } from "./wait.js";
|
|
22
|
-
export { InodeTable } from "./inode-table.js";
|
|
23
|
-
export type { Inode } from "./inode-table.js";
|
|
24
24
|
export { TimerTable } from "./timer-table.js";
|
|
25
25
|
export type { KernelTimer, TimerTableOptions } from "./timer-table.js";
|
|
26
26
|
export { DnsCache } from "./dns-cache.js";
|
package/dist/kernel/index.js
CHANGED
|
@@ -7,19 +7,19 @@
|
|
|
7
7
|
*/
|
|
8
8
|
// Kernel factory
|
|
9
9
|
export { createKernel } from "./kernel.js";
|
|
10
|
-
// Structured kernel error and
|
|
11
|
-
export { KernelError, defaultTermios } from "./types.js";
|
|
10
|
+
// Structured kernel error, termios defaults, and no-op logger
|
|
11
|
+
export { KernelError, defaultTermios, noopKernelLogger } from "./types.js";
|
|
12
12
|
// Kernel components (for direct use / testing)
|
|
13
13
|
export { FDTableManager, ProcessFDTable } from "./fd-table.js";
|
|
14
14
|
export { ProcessTable } from "./process-table.js";
|
|
15
15
|
export { createDeviceLayer } from "./device-layer.js";
|
|
16
16
|
export { createProcLayer, createProcessScopedFileSystem, resolveProcSelfPath, } from "./proc-layer.js";
|
|
17
|
+
export { createProcBackend } from "./proc-backend.js";
|
|
17
18
|
export { PipeManager } from "./pipe-manager.js";
|
|
18
19
|
export { PtyManager } from "./pty.js";
|
|
19
20
|
export { CommandRegistry } from "./command-registry.js";
|
|
20
21
|
export { FileLockManager, LOCK_SH, LOCK_EX, LOCK_UN, LOCK_NB } from "./file-lock.js";
|
|
21
22
|
export { WaitHandle, WaitQueue } from "./wait.js";
|
|
22
|
-
export { InodeTable } from "./inode-table.js";
|
|
23
23
|
export { TimerTable } from "./timer-table.js";
|
|
24
24
|
export { DnsCache } from "./dns-cache.js";
|
|
25
25
|
export { UserManager } from "./user.js";
|