typescript-virtual-container 1.4.3 → 1.4.4
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/.vscode/settings.json +2 -1
- package/README.md +137 -19
- package/benchmark-results.txt +21 -21
- package/builds/self-standalone.js +200 -193
- package/builds/self-standalone.js.map +4 -4
- package/builds/standalone-wo-sftp.js +166 -159
- package/builds/standalone-wo-sftp.js.map +4 -4
- package/builds/standalone.js +168 -161
- package/builds/standalone.js.map +4 -4
- package/builds/web-full-api.min.js +5 -5
- package/builds/web-full-api.min.js.map +3 -3
- package/builds/web.min.js +5 -5
- package/builds/web.min.js.map +3 -3
- package/bun.lock +4 -6
- package/examples/web.min.js +5 -5
- package/package.json +4 -3
- package/src/Honeypot/index.d.ts.map +1 -0
- package/src/SSHClient/index.d.ts.map +1 -0
- package/src/SSHMimic/exec.d.ts.map +1 -0
- package/src/SSHMimic/executor.d.ts.map +1 -0
- package/src/SSHMimic/hostKey.d.ts.map +1 -0
- package/src/SSHMimic/index.d.ts.map +1 -0
- package/src/SSHMimic/loginBanner.d.ts.map +1 -0
- package/src/SSHMimic/loginFormat.d.ts.map +1 -0
- package/src/SSHMimic/prompt.d.ts.map +1 -0
- package/src/SSHMimic/sftp.d.ts.map +1 -0
- package/src/VirtualFileSystem/binaryPack.d.ts.map +1 -0
- package/src/VirtualFileSystem/index.d.ts.map +1 -0
- package/src/VirtualFileSystem/index.ts +11 -9
- package/src/VirtualFileSystem/internalTypes.d.ts.map +1 -0
- package/src/VirtualFileSystem/path.d.ts.map +1 -0
- package/src/VirtualPackageManager/index.d.ts.map +1 -0
- package/src/VirtualShell/index.d.ts.map +1 -0
- package/src/VirtualShell/shell.d.ts.map +1 -0
- package/src/VirtualShell/shellParser.d.ts.map +1 -0
- package/{dist → src}/VirtualShell/shellParser.js +2 -1
- package/src/VirtualShell/shellParser.ts +3 -2
- package/src/VirtualUserManager/index.d.ts.map +1 -0
- package/src/bun.d.ts +1 -0
- package/src/commands/adduser.d.ts.map +1 -0
- package/src/commands/alias.d.ts.map +1 -0
- package/src/commands/apt.d.ts.map +1 -0
- package/src/commands/awk.d.ts.map +1 -0
- package/{dist → src}/commands/awk.js +1 -2
- package/src/commands/awk.ts +1 -2
- package/src/commands/base64.d.ts.map +1 -0
- package/src/commands/cat.d.ts.map +1 -0
- package/src/commands/cd.d.ts.map +1 -0
- package/{dist → src}/commands/cd.js +2 -2
- package/src/commands/cd.ts +2 -2
- package/src/commands/chmod.d.ts.map +1 -0
- package/src/commands/clear.d.ts.map +1 -0
- package/src/commands/command-helpers.d.ts.map +1 -0
- package/src/commands/cp.d.ts.map +1 -0
- package/src/commands/curl.d.ts.map +1 -0
- package/src/commands/cut.d.ts.map +1 -0
- package/src/commands/date.d.ts.map +1 -0
- package/src/commands/declare.d.ts.map +1 -0
- package/src/commands/deluser.d.ts.map +1 -0
- package/src/commands/df.d.ts.map +1 -0
- package/src/commands/diff.d.ts.map +1 -0
- package/src/commands/dpkg.d.ts.map +1 -0
- package/src/commands/du.d.ts.map +1 -0
- package/src/commands/echo.d.ts.map +1 -0
- package/src/commands/env.d.ts.map +1 -0
- package/src/commands/exit.d.ts.map +1 -0
- package/src/commands/export.d.ts.map +1 -0
- package/src/commands/find.d.ts.map +1 -0
- package/src/commands/free.d.ts.map +1 -0
- package/src/commands/grep.d.ts.map +1 -0
- package/src/commands/groups.d.ts.map +1 -0
- package/src/commands/gzip.d.ts.map +1 -0
- package/src/commands/head.d.ts.map +1 -0
- package/src/commands/help.d.ts.map +1 -0
- package/src/commands/helpers.d.ts.map +1 -0
- package/{dist → src}/commands/helpers.js +3 -0
- package/src/commands/helpers.ts +3 -0
- package/src/commands/history.d.ts.map +1 -0
- package/src/commands/hostname.d.ts.map +1 -0
- package/src/commands/htop.d.ts.map +1 -0
- package/src/commands/id.d.ts.map +1 -0
- package/src/commands/index.d.ts.map +1 -0
- package/src/commands/kill.d.ts.map +1 -0
- package/src/commands/ln.d.ts.map +1 -0
- package/src/commands/ls.d.ts.map +1 -0
- package/src/commands/ls.js +200 -0
- package/src/commands/ls.ts +210 -41
- package/src/commands/lsb-release.d.ts.map +1 -0
- package/src/commands/man.d.ts.map +1 -0
- package/src/commands/mkdir.d.ts.map +1 -0
- package/src/commands/mv.d.ts.map +1 -0
- package/src/commands/nano.d.ts.map +1 -0
- package/src/commands/neofetch.d.ts.map +1 -0
- package/src/commands/node.d.ts.map +1 -0
- package/src/commands/npm.d.ts.map +1 -0
- package/src/commands/passwd.d.ts.map +1 -0
- package/src/commands/ping.d.ts.map +1 -0
- package/src/commands/printf.d.ts.map +1 -0
- package/src/commands/ps.d.ts.map +1 -0
- package/src/commands/pwd.d.ts.map +1 -0
- package/src/commands/python.d.ts.map +1 -0
- package/src/commands/read.d.ts.map +1 -0
- package/src/commands/registry.d.ts.map +1 -0
- package/src/commands/rm.d.ts.map +1 -0
- package/src/commands/runtime.d.ts.map +1 -0
- package/{dist → src}/commands/runtime.js +36 -0
- package/src/commands/runtime.ts +56 -3
- package/src/commands/sed.d.ts.map +1 -0
- package/src/commands/seq.d.ts.map +1 -0
- package/src/commands/set.d.ts.map +1 -0
- package/src/commands/sh.d.ts.map +1 -0
- package/{dist → src}/commands/sh.js +8 -4
- package/src/commands/sh.ts +7 -4
- package/src/commands/shift.d.ts.map +1 -0
- package/src/commands/sleep.d.ts.map +1 -0
- package/src/commands/sort.d.ts.map +1 -0
- package/src/commands/source.d.ts.map +1 -0
- package/src/commands/stat.d.ts.map +1 -0
- package/src/commands/su.d.ts.map +1 -0
- package/src/commands/sudo.d.ts.map +1 -0
- package/src/commands/tail.d.ts.map +1 -0
- package/src/commands/tar.d.ts.map +1 -0
- package/src/commands/tee.d.ts.map +1 -0
- package/src/commands/test.d.ts.map +1 -0
- package/src/commands/test.ts +4 -2
- package/src/commands/touch.d.ts.map +1 -0
- package/src/commands/tr.d.ts.map +1 -0
- package/src/commands/tree.d.ts.map +1 -0
- package/src/commands/true.d.ts.map +1 -0
- package/src/commands/type.d.ts.map +1 -0
- package/src/commands/uname.d.ts.map +1 -0
- package/src/commands/uniq.d.ts.map +1 -0
- package/src/commands/unset.d.ts.map +1 -0
- package/src/commands/uptime.d.ts.map +1 -0
- package/src/commands/wc.d.ts.map +1 -0
- package/{dist → src}/commands/wc.js +1 -1
- package/src/commands/wc.ts +1 -1
- package/src/commands/wget.d.ts.map +1 -0
- package/src/commands/which.d.ts.map +1 -0
- package/src/commands/who.d.ts.map +1 -0
- package/src/commands/whoami.d.ts.map +1 -0
- package/src/commands/xargs.d.ts.map +1 -0
- package/src/index.d.ts.map +1 -0
- package/src/modules/linuxRootfs.d.ts +59 -0
- package/src/modules/linuxRootfs.d.ts.map +1 -0
- package/src/modules/linuxRootfs.js +619 -0
- package/src/modules/linuxRootfs.ts +420 -231
- package/src/modules/neofetch.d.ts.map +1 -0
- package/src/modules/shellInteractive.d.ts.map +1 -0
- package/src/modules/shellRuntime.d.ts.map +1 -0
- package/{dist → src}/self-standalone.d.ts.map +1 -1
- package/src/standalone-wo-sftp.d.ts.map +1 -0
- package/{dist → src}/standalone.d.ts.map +1 -1
- package/{dist → src}/types/commands.d.ts +1 -1
- package/src/types/commands.d.ts.map +1 -0
- package/src/types/commands.ts +1 -1
- package/src/types/pipeline.d.ts.map +1 -0
- package/src/types/streams.d.ts.map +1 -0
- package/src/types/vfs.d.ts.map +1 -0
- package/{dist → src}/utils/expand.d.ts +2 -2
- package/src/utils/expand.d.ts.map +1 -0
- package/src/utils/expand.js +476 -0
- package/src/utils/expand.ts +256 -76
- package/src/utils/perfLogger.d.ts.map +1 -0
- package/src/utils/tokenize.d.ts.map +1 -0
- package/src/utils/vfsDiff.d.ts.map +1 -0
- package/src/web-api.d.ts.map +1 -0
- package/src/web-full.d.ts.map +1 -0
- package/src/web.d.ts.map +1 -0
- package/tests/command-helpers.test.d.ts +2 -0
- package/tests/command-helpers.test.d.ts.map +1 -0
- package/tests/command-helpers.test.js +92 -0
- package/tests/command-helpers.test.ts +80 -0
- package/tests/commands-admin-net.test.d.ts +2 -0
- package/tests/commands-admin-net.test.d.ts.map +1 -0
- package/tests/commands-admin-net.test.js +353 -0
- package/tests/commands-admin-net.test.ts +441 -0
- package/tests/commands-advanced.test.d.ts +2 -0
- package/tests/commands-advanced.test.d.ts.map +1 -0
- package/tests/commands-advanced.test.js +378 -0
- package/tests/commands-advanced.test.ts +456 -0
- package/tests/commands-core.test.d.ts +2 -0
- package/tests/commands-core.test.d.ts.map +1 -0
- package/tests/commands-core.test.js +477 -0
- package/tests/commands-core.test.ts +562 -0
- package/tests/commands-missing.test.d.ts +2 -0
- package/tests/commands-missing.test.d.ts.map +1 -0
- package/tests/commands-missing.test.js +470 -0
- package/tests/commands-missing.test.ts +570 -0
- package/tests/commands-specific-units.test.d.ts +2 -0
- package/tests/commands-specific-units.test.d.ts.map +1 -0
- package/tests/commands-specific-units.test.js +264 -0
- package/tests/commands-specific-units.test.ts +327 -0
- package/tests/commands-text-sys.test.d.ts +2 -0
- package/tests/commands-text-sys.test.d.ts.map +1 -0
- package/tests/commands-text-sys.test.js +366 -0
- package/tests/commands-text-sys.test.ts +445 -0
- package/tests/expand.test.d.ts +2 -0
- package/tests/expand.test.d.ts.map +1 -0
- package/tests/expand.test.js +138 -0
- package/tests/expand.test.ts +170 -0
- package/tests/helpers.test.d.ts +2 -0
- package/tests/helpers.test.d.ts.map +1 -0
- package/tests/helpers.test.js +52 -0
- package/tests/helpers.test.ts +75 -0
- package/tests/new-features.test.d.ts +2 -0
- package/tests/new-features.test.d.ts.map +1 -0
- package/tests/new-features.test.js +850 -0
- package/tests/parser-executor.test.d.ts +2 -0
- package/tests/parser-executor.test.d.ts.map +1 -0
- package/tests/parser-executor.test.js +25 -0
- package/tests/sftp.test.d.ts +2 -0
- package/tests/sftp.test.d.ts.map +1 -0
- package/tests/sftp.test.js +246 -0
- package/tests/ssh-exec.test.d.ts +2 -0
- package/tests/ssh-exec.test.d.ts.map +1 -0
- package/tests/ssh-exec.test.js +39 -0
- package/tests/test-helper.d.ts +56 -0
- package/tests/test-helper.d.ts.map +1 -0
- package/tests/test-helper.js +71 -0
- package/tests/test-helper.ts +79 -0
- package/tests/users.test.d.ts +2 -0
- package/tests/users.test.d.ts.map +1 -0
- package/tests/users.test.js +71 -0
- package/tests/web.test.d.ts +2 -0
- package/tests/web.test.d.ts.map +1 -0
- package/tests/web.test.js +149 -0
- package/tsconfig.json +2 -4
- package/dist/Honeypot/index.d.ts.map +0 -1
- package/dist/SSHClient/index.d.ts.map +0 -1
- package/dist/SSHMimic/exec.d.ts.map +0 -1
- package/dist/SSHMimic/executor.d.ts.map +0 -1
- package/dist/SSHMimic/hostKey.d.ts.map +0 -1
- package/dist/SSHMimic/index.d.ts.map +0 -1
- package/dist/SSHMimic/loginBanner.d.ts.map +0 -1
- package/dist/SSHMimic/loginFormat.d.ts.map +0 -1
- package/dist/SSHMimic/prompt.d.ts.map +0 -1
- package/dist/SSHMimic/sftp.d.ts.map +0 -1
- package/dist/VirtualFileSystem/binaryPack.d.ts.map +0 -1
- package/dist/VirtualFileSystem/index.d.ts.map +0 -1
- package/dist/VirtualFileSystem/internalTypes.d.ts.map +0 -1
- package/dist/VirtualFileSystem/path.d.ts.map +0 -1
- package/dist/VirtualPackageManager/index.d.ts.map +0 -1
- package/dist/VirtualShell/index.d.ts.map +0 -1
- package/dist/VirtualShell/shell.d.ts.map +0 -1
- package/dist/VirtualShell/shellParser.d.ts.map +0 -1
- package/dist/VirtualUserManager/index.d.ts.map +0 -1
- package/dist/commands/adduser.d.ts.map +0 -1
- package/dist/commands/alias.d.ts.map +0 -1
- package/dist/commands/apt.d.ts.map +0 -1
- package/dist/commands/awk.d.ts.map +0 -1
- package/dist/commands/base64.d.ts.map +0 -1
- package/dist/commands/cat.d.ts.map +0 -1
- package/dist/commands/cd.d.ts.map +0 -1
- package/dist/commands/chmod.d.ts.map +0 -1
- package/dist/commands/clear.d.ts.map +0 -1
- package/dist/commands/command-helpers.d.ts.map +0 -1
- package/dist/commands/cp.d.ts.map +0 -1
- package/dist/commands/curl.d.ts.map +0 -1
- package/dist/commands/cut.d.ts.map +0 -1
- package/dist/commands/date.d.ts.map +0 -1
- package/dist/commands/declare.d.ts.map +0 -1
- package/dist/commands/deluser.d.ts.map +0 -1
- package/dist/commands/df.d.ts.map +0 -1
- package/dist/commands/diff.d.ts.map +0 -1
- package/dist/commands/dpkg.d.ts.map +0 -1
- package/dist/commands/du.d.ts.map +0 -1
- package/dist/commands/echo.d.ts.map +0 -1
- package/dist/commands/env.d.ts.map +0 -1
- package/dist/commands/exit.d.ts.map +0 -1
- package/dist/commands/export.d.ts.map +0 -1
- package/dist/commands/find.d.ts.map +0 -1
- package/dist/commands/free.d.ts.map +0 -1
- package/dist/commands/grep.d.ts.map +0 -1
- package/dist/commands/groups.d.ts.map +0 -1
- package/dist/commands/gzip.d.ts.map +0 -1
- package/dist/commands/head.d.ts.map +0 -1
- package/dist/commands/help.d.ts.map +0 -1
- package/dist/commands/helpers.d.ts.map +0 -1
- package/dist/commands/history.d.ts.map +0 -1
- package/dist/commands/hostname.d.ts.map +0 -1
- package/dist/commands/htop.d.ts.map +0 -1
- package/dist/commands/id.d.ts.map +0 -1
- package/dist/commands/index.d.ts.map +0 -1
- package/dist/commands/kill.d.ts.map +0 -1
- package/dist/commands/ln.d.ts.map +0 -1
- package/dist/commands/ls.d.ts.map +0 -1
- package/dist/commands/ls.js +0 -67
- package/dist/commands/lsb-release.d.ts.map +0 -1
- package/dist/commands/man.d.ts.map +0 -1
- package/dist/commands/mkdir.d.ts.map +0 -1
- package/dist/commands/mv.d.ts.map +0 -1
- package/dist/commands/nano.d.ts.map +0 -1
- package/dist/commands/neofetch.d.ts.map +0 -1
- package/dist/commands/node.d.ts.map +0 -1
- package/dist/commands/npm.d.ts.map +0 -1
- package/dist/commands/passwd.d.ts.map +0 -1
- package/dist/commands/ping.d.ts.map +0 -1
- package/dist/commands/printf.d.ts.map +0 -1
- package/dist/commands/ps.d.ts.map +0 -1
- package/dist/commands/pwd.d.ts.map +0 -1
- package/dist/commands/python.d.ts.map +0 -1
- package/dist/commands/read.d.ts.map +0 -1
- package/dist/commands/registry.d.ts.map +0 -1
- package/dist/commands/rm.d.ts.map +0 -1
- package/dist/commands/runtime.d.ts.map +0 -1
- package/dist/commands/sed.d.ts.map +0 -1
- package/dist/commands/seq.d.ts.map +0 -1
- package/dist/commands/set.d.ts.map +0 -1
- package/dist/commands/sh.d.ts.map +0 -1
- package/dist/commands/shift.d.ts.map +0 -1
- package/dist/commands/sleep.d.ts.map +0 -1
- package/dist/commands/sort.d.ts.map +0 -1
- package/dist/commands/source.d.ts.map +0 -1
- package/dist/commands/stat.d.ts.map +0 -1
- package/dist/commands/su.d.ts.map +0 -1
- package/dist/commands/sudo.d.ts.map +0 -1
- package/dist/commands/tail.d.ts.map +0 -1
- package/dist/commands/tar.d.ts.map +0 -1
- package/dist/commands/tee.d.ts.map +0 -1
- package/dist/commands/test.d.ts.map +0 -1
- package/dist/commands/touch.d.ts.map +0 -1
- package/dist/commands/tr.d.ts.map +0 -1
- package/dist/commands/tree.d.ts.map +0 -1
- package/dist/commands/true.d.ts.map +0 -1
- package/dist/commands/type.d.ts.map +0 -1
- package/dist/commands/uname.d.ts.map +0 -1
- package/dist/commands/uniq.d.ts.map +0 -1
- package/dist/commands/unset.d.ts.map +0 -1
- package/dist/commands/uptime.d.ts.map +0 -1
- package/dist/commands/wc.d.ts.map +0 -1
- package/dist/commands/wget.d.ts.map +0 -1
- package/dist/commands/which.d.ts.map +0 -1
- package/dist/commands/who.d.ts.map +0 -1
- package/dist/commands/whoami.d.ts.map +0 -1
- package/dist/commands/xargs.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/modules/linuxRootfs.d.ts +0 -41
- package/dist/modules/linuxRootfs.d.ts.map +0 -1
- package/dist/modules/linuxRootfs.js +0 -440
- package/dist/modules/neofetch.d.ts.map +0 -1
- package/dist/modules/shellInteractive.d.ts.map +0 -1
- package/dist/modules/shellRuntime.d.ts.map +0 -1
- package/dist/standalone-wo-sftp.d.ts.map +0 -1
- package/dist/types/commands.d.ts.map +0 -1
- package/dist/types/pipeline.d.ts.map +0 -1
- package/dist/types/streams.d.ts.map +0 -1
- package/dist/types/vfs.d.ts.map +0 -1
- package/dist/utils/expand.d.ts.map +0 -1
- package/dist/utils/expand.js +0 -265
- package/dist/utils/perfLogger.d.ts.map +0 -1
- package/dist/utils/tokenize.d.ts.map +0 -1
- package/dist/utils/vfsDiff.d.ts.map +0 -1
- package/dist/web-api.d.ts.map +0 -1
- package/dist/web-full.d.ts.map +0 -1
- package/dist/web.d.ts.map +0 -1
- package/tests/bun-test-shim.ts +0 -9
- /package/{dist → src}/Honeypot/index.d.ts +0 -0
- /package/{dist → src}/Honeypot/index.js +0 -0
- /package/{dist → src}/SSHClient/index.d.ts +0 -0
- /package/{dist → src}/SSHClient/index.js +0 -0
- /package/{dist → src}/SSHMimic/exec.d.ts +0 -0
- /package/{dist → src}/SSHMimic/exec.js +0 -0
- /package/{dist → src}/SSHMimic/executor.d.ts +0 -0
- /package/{dist → src}/SSHMimic/executor.js +0 -0
- /package/{dist → src}/SSHMimic/hostKey.d.ts +0 -0
- /package/{dist → src}/SSHMimic/hostKey.js +0 -0
- /package/{dist → src}/SSHMimic/index.d.ts +0 -0
- /package/{dist → src}/SSHMimic/index.js +0 -0
- /package/{dist → src}/SSHMimic/loginBanner.d.ts +0 -0
- /package/{dist → src}/SSHMimic/loginBanner.js +0 -0
- /package/{dist → src}/SSHMimic/loginFormat.d.ts +0 -0
- /package/{dist → src}/SSHMimic/loginFormat.js +0 -0
- /package/{dist → src}/SSHMimic/prompt.d.ts +0 -0
- /package/{dist → src}/SSHMimic/prompt.js +0 -0
- /package/{dist → src}/SSHMimic/sftp.d.ts +0 -0
- /package/{dist → src}/SSHMimic/sftp.js +0 -0
- /package/{dist → src}/VirtualFileSystem/binaryPack.d.ts +0 -0
- /package/{dist → src}/VirtualFileSystem/binaryPack.js +0 -0
- /package/{dist → src}/VirtualFileSystem/index.d.ts +0 -0
- /package/{dist → src}/VirtualFileSystem/index.js +0 -0
- /package/{dist → src}/VirtualFileSystem/internalTypes.d.ts +0 -0
- /package/{dist → src}/VirtualFileSystem/internalTypes.js +0 -0
- /package/{dist → src}/VirtualFileSystem/path.d.ts +0 -0
- /package/{dist → src}/VirtualFileSystem/path.js +0 -0
- /package/{dist → src}/VirtualPackageManager/index.d.ts +0 -0
- /package/{dist → src}/VirtualPackageManager/index.js +0 -0
- /package/{dist → src}/VirtualShell/index.d.ts +0 -0
- /package/{dist → src}/VirtualShell/index.js +0 -0
- /package/{dist → src}/VirtualShell/shell.d.ts +0 -0
- /package/{dist → src}/VirtualShell/shell.js +0 -0
- /package/{dist → src}/VirtualShell/shellParser.d.ts +0 -0
- /package/{dist → src}/VirtualUserManager/index.d.ts +0 -0
- /package/{dist → src}/VirtualUserManager/index.js +0 -0
- /package/{dist → src}/commands/adduser.d.ts +0 -0
- /package/{dist → src}/commands/adduser.js +0 -0
- /package/{dist → src}/commands/alias.d.ts +0 -0
- /package/{dist → src}/commands/alias.js +0 -0
- /package/{dist → src}/commands/apt.d.ts +0 -0
- /package/{dist → src}/commands/apt.js +0 -0
- /package/{dist → src}/commands/awk.d.ts +0 -0
- /package/{dist → src}/commands/base64.d.ts +0 -0
- /package/{dist → src}/commands/base64.js +0 -0
- /package/{dist → src}/commands/cat.d.ts +0 -0
- /package/{dist → src}/commands/cat.js +0 -0
- /package/{dist → src}/commands/cd.d.ts +0 -0
- /package/{dist → src}/commands/chmod.d.ts +0 -0
- /package/{dist → src}/commands/chmod.js +0 -0
- /package/{dist → src}/commands/clear.d.ts +0 -0
- /package/{dist → src}/commands/clear.js +0 -0
- /package/{dist → src}/commands/command-helpers.d.ts +0 -0
- /package/{dist → src}/commands/command-helpers.js +0 -0
- /package/{dist → src}/commands/cp.d.ts +0 -0
- /package/{dist → src}/commands/cp.js +0 -0
- /package/{dist → src}/commands/curl.d.ts +0 -0
- /package/{dist → src}/commands/curl.js +0 -0
- /package/{dist → src}/commands/cut.d.ts +0 -0
- /package/{dist → src}/commands/cut.js +0 -0
- /package/{dist → src}/commands/date.d.ts +0 -0
- /package/{dist → src}/commands/date.js +0 -0
- /package/{dist → src}/commands/declare.d.ts +0 -0
- /package/{dist → src}/commands/declare.js +0 -0
- /package/{dist → src}/commands/deluser.d.ts +0 -0
- /package/{dist → src}/commands/deluser.js +0 -0
- /package/{dist → src}/commands/df.d.ts +0 -0
- /package/{dist → src}/commands/df.js +0 -0
- /package/{dist → src}/commands/diff.d.ts +0 -0
- /package/{dist → src}/commands/diff.js +0 -0
- /package/{dist → src}/commands/dpkg.d.ts +0 -0
- /package/{dist → src}/commands/dpkg.js +0 -0
- /package/{dist → src}/commands/du.d.ts +0 -0
- /package/{dist → src}/commands/du.js +0 -0
- /package/{dist → src}/commands/echo.d.ts +0 -0
- /package/{dist → src}/commands/echo.js +0 -0
- /package/{dist → src}/commands/env.d.ts +0 -0
- /package/{dist → src}/commands/env.js +0 -0
- /package/{dist → src}/commands/exit.d.ts +0 -0
- /package/{dist → src}/commands/exit.js +0 -0
- /package/{dist → src}/commands/export.d.ts +0 -0
- /package/{dist → src}/commands/export.js +0 -0
- /package/{dist → src}/commands/find.d.ts +0 -0
- /package/{dist → src}/commands/find.js +0 -0
- /package/{dist → src}/commands/free.d.ts +0 -0
- /package/{dist → src}/commands/free.js +0 -0
- /package/{dist → src}/commands/grep.d.ts +0 -0
- /package/{dist → src}/commands/grep.js +0 -0
- /package/{dist → src}/commands/groups.d.ts +0 -0
- /package/{dist → src}/commands/groups.js +0 -0
- /package/{dist → src}/commands/gzip.d.ts +0 -0
- /package/{dist → src}/commands/gzip.js +0 -0
- /package/{dist → src}/commands/head.d.ts +0 -0
- /package/{dist → src}/commands/head.js +0 -0
- /package/{dist → src}/commands/help.d.ts +0 -0
- /package/{dist → src}/commands/help.js +0 -0
- /package/{dist → src}/commands/helpers.d.ts +0 -0
- /package/{dist → src}/commands/history.d.ts +0 -0
- /package/{dist → src}/commands/history.js +0 -0
- /package/{dist → src}/commands/hostname.d.ts +0 -0
- /package/{dist → src}/commands/hostname.js +0 -0
- /package/{dist → src}/commands/htop.d.ts +0 -0
- /package/{dist → src}/commands/htop.js +0 -0
- /package/{dist → src}/commands/id.d.ts +0 -0
- /package/{dist → src}/commands/id.js +0 -0
- /package/{dist → src}/commands/index.d.ts +0 -0
- /package/{dist → src}/commands/index.js +0 -0
- /package/{dist → src}/commands/kill.d.ts +0 -0
- /package/{dist → src}/commands/kill.js +0 -0
- /package/{dist → src}/commands/ln.d.ts +0 -0
- /package/{dist → src}/commands/ln.js +0 -0
- /package/{dist → src}/commands/ls.d.ts +0 -0
- /package/{dist → src}/commands/lsb-release.d.ts +0 -0
- /package/{dist → src}/commands/lsb-release.js +0 -0
- /package/{dist → src}/commands/man.d.ts +0 -0
- /package/{dist → src}/commands/man.js +0 -0
- /package/{dist → src}/commands/mkdir.d.ts +0 -0
- /package/{dist → src}/commands/mkdir.js +0 -0
- /package/{dist → src}/commands/mv.d.ts +0 -0
- /package/{dist → src}/commands/mv.js +0 -0
- /package/{dist → src}/commands/nano.d.ts +0 -0
- /package/{dist → src}/commands/nano.js +0 -0
- /package/{dist → src}/commands/neofetch.d.ts +0 -0
- /package/{dist → src}/commands/neofetch.js +0 -0
- /package/{dist → src}/commands/node.d.ts +0 -0
- /package/{dist → src}/commands/node.js +0 -0
- /package/{dist → src}/commands/npm.d.ts +0 -0
- /package/{dist → src}/commands/npm.js +0 -0
- /package/{dist → src}/commands/passwd.d.ts +0 -0
- /package/{dist → src}/commands/passwd.js +0 -0
- /package/{dist → src}/commands/ping.d.ts +0 -0
- /package/{dist → src}/commands/ping.js +0 -0
- /package/{dist → src}/commands/printf.d.ts +0 -0
- /package/{dist → src}/commands/printf.js +0 -0
- /package/{dist → src}/commands/ps.d.ts +0 -0
- /package/{dist → src}/commands/ps.js +0 -0
- /package/{dist → src}/commands/pwd.d.ts +0 -0
- /package/{dist → src}/commands/pwd.js +0 -0
- /package/{dist → src}/commands/python.d.ts +0 -0
- /package/{dist → src}/commands/python.js +0 -0
- /package/{dist → src}/commands/read.d.ts +0 -0
- /package/{dist → src}/commands/read.js +0 -0
- /package/{dist → src}/commands/registry.d.ts +0 -0
- /package/{dist → src}/commands/registry.js +0 -0
- /package/{dist → src}/commands/rm.d.ts +0 -0
- /package/{dist → src}/commands/rm.js +0 -0
- /package/{dist → src}/commands/runtime.d.ts +0 -0
- /package/{dist → src}/commands/sed.d.ts +0 -0
- /package/{dist → src}/commands/sed.js +0 -0
- /package/{dist → src}/commands/seq.d.ts +0 -0
- /package/{dist → src}/commands/seq.js +0 -0
- /package/{dist → src}/commands/set.d.ts +0 -0
- /package/{dist → src}/commands/set.js +0 -0
- /package/{dist → src}/commands/sh.d.ts +0 -0
- /package/{dist → src}/commands/shift.d.ts +0 -0
- /package/{dist → src}/commands/shift.js +0 -0
- /package/{dist → src}/commands/sleep.d.ts +0 -0
- /package/{dist → src}/commands/sleep.js +0 -0
- /package/{dist → src}/commands/sort.d.ts +0 -0
- /package/{dist → src}/commands/sort.js +0 -0
- /package/{dist → src}/commands/source.d.ts +0 -0
- /package/{dist → src}/commands/source.js +0 -0
- /package/{dist → src}/commands/stat.d.ts +0 -0
- /package/{dist → src}/commands/stat.js +0 -0
- /package/{dist → src}/commands/su.d.ts +0 -0
- /package/{dist → src}/commands/su.js +0 -0
- /package/{dist → src}/commands/sudo.d.ts +0 -0
- /package/{dist → src}/commands/sudo.js +0 -0
- /package/{dist → src}/commands/tail.d.ts +0 -0
- /package/{dist → src}/commands/tail.js +0 -0
- /package/{dist → src}/commands/tar.d.ts +0 -0
- /package/{dist → src}/commands/tar.js +0 -0
- /package/{dist → src}/commands/tee.d.ts +0 -0
- /package/{dist → src}/commands/tee.js +0 -0
- /package/{dist → src}/commands/test.d.ts +0 -0
- /package/{dist → src}/commands/test.js +0 -0
- /package/{dist → src}/commands/touch.d.ts +0 -0
- /package/{dist → src}/commands/touch.js +0 -0
- /package/{dist → src}/commands/tr.d.ts +0 -0
- /package/{dist → src}/commands/tr.js +0 -0
- /package/{dist → src}/commands/tree.d.ts +0 -0
- /package/{dist → src}/commands/tree.js +0 -0
- /package/{dist → src}/commands/true.d.ts +0 -0
- /package/{dist → src}/commands/true.js +0 -0
- /package/{dist → src}/commands/type.d.ts +0 -0
- /package/{dist → src}/commands/type.js +0 -0
- /package/{dist → src}/commands/uname.d.ts +0 -0
- /package/{dist → src}/commands/uname.js +0 -0
- /package/{dist → src}/commands/uniq.d.ts +0 -0
- /package/{dist → src}/commands/uniq.js +0 -0
- /package/{dist → src}/commands/unset.d.ts +0 -0
- /package/{dist → src}/commands/unset.js +0 -0
- /package/{dist → src}/commands/uptime.d.ts +0 -0
- /package/{dist → src}/commands/uptime.js +0 -0
- /package/{dist → src}/commands/wc.d.ts +0 -0
- /package/{dist → src}/commands/wget.d.ts +0 -0
- /package/{dist → src}/commands/wget.js +0 -0
- /package/{dist → src}/commands/which.d.ts +0 -0
- /package/{dist → src}/commands/which.js +0 -0
- /package/{dist → src}/commands/who.d.ts +0 -0
- /package/{dist → src}/commands/who.js +0 -0
- /package/{dist → src}/commands/whoami.d.ts +0 -0
- /package/{dist → src}/commands/whoami.js +0 -0
- /package/{dist → src}/commands/xargs.d.ts +0 -0
- /package/{dist → src}/commands/xargs.js +0 -0
- /package/{dist → src}/index.d.ts +0 -0
- /package/{dist → src}/index.js +0 -0
- /package/{dist → src}/modules/neofetch.d.ts +0 -0
- /package/{dist → src}/modules/neofetch.js +0 -0
- /package/{dist → src}/modules/shellInteractive.d.ts +0 -0
- /package/{dist → src}/modules/shellInteractive.js +0 -0
- /package/{dist → src}/modules/shellRuntime.d.ts +0 -0
- /package/{dist → src}/modules/shellRuntime.js +0 -0
- /package/{dist → src}/self-standalone.d.ts +0 -0
- /package/{dist → src}/self-standalone.js +0 -0
- /package/{dist → src}/standalone-wo-sftp.d.ts +0 -0
- /package/{dist → src}/standalone-wo-sftp.js +0 -0
- /package/{dist → src}/standalone.d.ts +0 -0
- /package/{dist → src}/standalone.js +0 -0
- /package/{dist → src}/types/commands.js +0 -0
- /package/{dist → src}/types/pipeline.d.ts +0 -0
- /package/{dist → src}/types/pipeline.js +0 -0
- /package/{dist → src}/types/streams.d.ts +0 -0
- /package/{dist → src}/types/streams.js +0 -0
- /package/{dist → src}/types/vfs.d.ts +0 -0
- /package/{dist → src}/types/vfs.js +0 -0
- /package/{dist → src}/utils/perfLogger.d.ts +0 -0
- /package/{dist → src}/utils/perfLogger.js +0 -0
- /package/{dist → src}/utils/tokenize.d.ts +0 -0
- /package/{dist → src}/utils/tokenize.js +0 -0
- /package/{dist → src}/utils/vfsDiff.d.ts +0 -0
- /package/{dist → src}/utils/vfsDiff.js +0 -0
- /package/{dist → src}/web-api.d.ts +0 -0
- /package/{dist → src}/web-api.js +0 -0
- /package/{dist → src}/web-full.d.ts +0 -0
- /package/{dist → src}/web-full.js +0 -0
- /package/{dist → src}/web.d.ts +0 -0
- /package/{dist → src}/web.js +0 -0
|
@@ -1,16 +1,23 @@
|
|
|
1
|
-
/** biome-ignore-all lint/style/useNamingConvention: ENV VAR KEYS */
|
|
1
|
+
/** biome-ignore-all lint/style/useNamingConvention: ENV VAR KEYS + system names */
|
|
2
2
|
/**
|
|
3
3
|
* linuxRootfs.ts
|
|
4
4
|
*
|
|
5
5
|
* Bootstraps a realistic Linux directory hierarchy in the VFS.
|
|
6
6
|
* Called once during VirtualShell initialization. Idempotent — skips
|
|
7
7
|
* paths that already exist so FS-mode snapshots survive restarts.
|
|
8
|
+
*
|
|
9
|
+
* Public API:
|
|
10
|
+
* - bootstrapLinuxRootfs() one-shot boot (VirtualShell calls this)
|
|
11
|
+
* - refreshProc() refresh /proc/* (call on session changes)
|
|
12
|
+
* - syncEtcPasswd() sync /etc/passwd|group|shadow from UserManager
|
|
13
|
+
* - createLinuxRootfsEngine() returns engine with .boot() + .tick() for
|
|
14
|
+
* runtimes that want a live refresh loop
|
|
8
15
|
*/
|
|
9
16
|
|
|
10
17
|
import * as os from "node:os";
|
|
11
18
|
import type VirtualFileSystem from "../VirtualFileSystem";
|
|
12
19
|
import type { ShellProperties } from "../VirtualShell";
|
|
13
|
-
import type { VirtualUserManager } from "../VirtualUserManager";
|
|
20
|
+
import type { VirtualActiveSession, VirtualUserManager } from "../VirtualUserManager";
|
|
14
21
|
|
|
15
22
|
// ─── helpers ────────────────────────────────────────────────────────────────
|
|
16
23
|
|
|
@@ -27,6 +34,20 @@ function ensureFile(
|
|
|
27
34
|
if (!vfs.exists(path)) vfs.writeFile(path, content, { mode });
|
|
28
35
|
}
|
|
29
36
|
|
|
37
|
+
function write(vfs: VirtualFileSystem, path: string, content: string): void {
|
|
38
|
+
vfs.writeFile(path, content);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** FNV-1a 32-bit — deterministic seed from any string */
|
|
42
|
+
function fnv1a(str: string): number {
|
|
43
|
+
let h = 2166136261;
|
|
44
|
+
for (let i = 0; i < str.length; i++) {
|
|
45
|
+
h ^= str.charCodeAt(i);
|
|
46
|
+
h = Math.imul(h, 16777619);
|
|
47
|
+
}
|
|
48
|
+
return h >>> 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
30
51
|
// ─── /etc ────────────────────────────────────────────────────────────────────
|
|
31
52
|
|
|
32
53
|
function bootstrapEtc(
|
|
@@ -63,8 +84,7 @@ function bootstrapEtc(
|
|
|
63
84
|
].join("\n")}\n`,
|
|
64
85
|
);
|
|
65
86
|
|
|
66
|
-
ensureFile(vfs, "/etc/issue",
|
|
67
|
-
|
|
87
|
+
ensureFile(vfs, "/etc/issue", "Fortune GNU/Linux 1.0 \\n \\l\n");
|
|
68
88
|
ensureFile(
|
|
69
89
|
vfs,
|
|
70
90
|
"/etc/motd",
|
|
@@ -84,7 +104,7 @@ function bootstrapEtc(
|
|
|
84
104
|
].join("\n")}\n`,
|
|
85
105
|
);
|
|
86
106
|
|
|
87
|
-
// network
|
|
107
|
+
// network
|
|
88
108
|
ensureDir(vfs, "/etc/network");
|
|
89
109
|
ensureFile(
|
|
90
110
|
vfs,
|
|
@@ -98,11 +118,7 @@ function bootstrapEtc(
|
|
|
98
118
|
].join("\n")}\n`,
|
|
99
119
|
);
|
|
100
120
|
|
|
101
|
-
ensureFile(
|
|
102
|
-
vfs,
|
|
103
|
-
"/etc/resolv.conf",
|
|
104
|
-
"nameserver 1.1.1.1\nnameserver 8.8.8.8\n",
|
|
105
|
-
);
|
|
121
|
+
ensureFile(vfs, "/etc/resolv.conf", "nameserver 1.1.1.1\nnameserver 8.8.8.8\n");
|
|
106
122
|
|
|
107
123
|
ensureFile(
|
|
108
124
|
vfs,
|
|
@@ -118,6 +134,69 @@ function bootstrapEtc(
|
|
|
118
134
|
ensureDir(vfs, "/etc/init.d");
|
|
119
135
|
ensureDir(vfs, "/etc/systemd");
|
|
120
136
|
ensureDir(vfs, "/etc/systemd/system");
|
|
137
|
+
|
|
138
|
+
// fstab
|
|
139
|
+
ensureFile(
|
|
140
|
+
vfs,
|
|
141
|
+
"/etc/fstab",
|
|
142
|
+
`${[
|
|
143
|
+
"# <file system> <mount point> <type> <options> <dump> <pass>",
|
|
144
|
+
"UUID=00000000-0000-0000-0000-000000000001 / ext4 errors=remount-ro 0 1",
|
|
145
|
+
"UUID=00000000-0000-0000-0000-000000000002 /boot ext4 defaults 0 2",
|
|
146
|
+
"UUID=00000000-0000-0000-0000-000000000003 none swap sw 0 0",
|
|
147
|
+
"tmpfs /tmp tmpfs defaults,noatime 0 0",
|
|
148
|
+
"tmpfs /run tmpfs defaults,noatime 0 0",
|
|
149
|
+
].join("\n")}\n`,
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
// login.defs — useradd/passwd defaults
|
|
153
|
+
ensureFile(
|
|
154
|
+
vfs,
|
|
155
|
+
"/etc/login.defs",
|
|
156
|
+
`${[
|
|
157
|
+
"MAIL_DIR /var/mail",
|
|
158
|
+
"PASS_MAX_DAYS 99999",
|
|
159
|
+
"PASS_MIN_DAYS 0",
|
|
160
|
+
"PASS_WARN_AGE 7",
|
|
161
|
+
"UID_MIN 1000",
|
|
162
|
+
"UID_MAX 60000",
|
|
163
|
+
"GID_MIN 1000",
|
|
164
|
+
"GID_MAX 60000",
|
|
165
|
+
"CREATE_HOME yes",
|
|
166
|
+
"UMASK 022",
|
|
167
|
+
"USERGROUPS_ENAB yes",
|
|
168
|
+
"ENCRYPT_METHOD SHA512",
|
|
169
|
+
].join("\n")}\n`,
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
// security + pam
|
|
173
|
+
ensureDir(vfs, "/etc/security");
|
|
174
|
+
ensureFile(vfs, "/etc/security/limits.conf", "# /etc/security/limits.conf\n");
|
|
175
|
+
ensureFile(vfs, "/etc/security/access.conf", "# /etc/security/access.conf\n");
|
|
176
|
+
|
|
177
|
+
ensureDir(vfs, "/etc/pam.d");
|
|
178
|
+
ensureFile(vfs, "/etc/pam.d/common-auth", "auth required pam_unix.so\n");
|
|
179
|
+
ensureFile(vfs, "/etc/pam.d/common-account", "account required pam_unix.so\n");
|
|
180
|
+
ensureFile(vfs, "/etc/pam.d/common-password",
|
|
181
|
+
"password required pam_unix.so obscure sha512\n");
|
|
182
|
+
ensureFile(vfs, "/etc/pam.d/common-session", "session required pam_unix.so\n");
|
|
183
|
+
ensureFile(vfs, "/etc/pam.d/sshd",
|
|
184
|
+
"@include common-auth\n@include common-account\n@include common-session\n");
|
|
185
|
+
|
|
186
|
+
// sudo config
|
|
187
|
+
ensureDir(vfs, "/etc/sudoers.d");
|
|
188
|
+
ensureFile(vfs, "/etc/sudoers",
|
|
189
|
+
"root ALL=(ALL:ALL) ALL\n%sudo ALL=(ALL:ALL) ALL\n", 0o440);
|
|
190
|
+
|
|
191
|
+
// ld
|
|
192
|
+
ensureFile(vfs, "/etc/ld.so.conf", "include /etc/ld.so.conf.d/*.conf\n");
|
|
193
|
+
ensureDir(vfs, "/etc/ld.so.conf.d");
|
|
194
|
+
ensureFile(vfs, "/etc/ld.so.conf.d/x86_64-linux-gnu.conf", "/lib/x86_64-linux-gnu\n/usr/lib/x86_64-linux-gnu\n");
|
|
195
|
+
|
|
196
|
+
// locale + timezone
|
|
197
|
+
ensureFile(vfs, "/etc/locale.conf", "LANG=en_US.UTF-8\n");
|
|
198
|
+
ensureFile(vfs, "/etc/timezone", "UTC\n");
|
|
199
|
+
ensureFile(vfs, "/etc/localtime", "UTC\n");
|
|
121
200
|
}
|
|
122
201
|
|
|
123
202
|
// ─── /etc/passwd + /etc/group + /etc/shadow ─────────────────────────────────
|
|
@@ -125,8 +204,6 @@ function bootstrapEtc(
|
|
|
125
204
|
/**
|
|
126
205
|
* Sync `/etc/passwd`, `/etc/group`, and `/etc/shadow` from the
|
|
127
206
|
* VirtualUserManager's current user list into the VFS.
|
|
128
|
-
* @param vfs VirtualFileSystem instance to write files into
|
|
129
|
-
* @param users VirtualUserManager to source users from
|
|
130
207
|
*/
|
|
131
208
|
export function syncEtcPasswd(
|
|
132
209
|
vfs: VirtualFileSystem,
|
|
@@ -159,7 +236,7 @@ export function syncEtcPasswd(
|
|
|
159
236
|
];
|
|
160
237
|
vfs.writeFile("/etc/group", `${groupLines.join("\n")}\n`);
|
|
161
238
|
|
|
162
|
-
// shadow — fake hashes, never real
|
|
239
|
+
// shadow — fake hashes, never real credentials
|
|
163
240
|
const shadowLines = [
|
|
164
241
|
"root:*:19000:0:99999:7:::",
|
|
165
242
|
"daemon:*:19000:0:99999:7:::",
|
|
@@ -171,9 +248,9 @@ export function syncEtcPasswd(
|
|
|
171
248
|
vfs.writeFile("/etc/shadow", `${shadowLines.join("\n")}\n`, { mode: 0o640 });
|
|
172
249
|
}
|
|
173
250
|
|
|
174
|
-
// ─── /proc
|
|
251
|
+
// ─── /proc helpers ───────────────────────────────────────────────────────────
|
|
175
252
|
|
|
176
|
-
/** Derive a stable virtual PID from a tty string
|
|
253
|
+
/** Derive a stable virtual PID from a tty string e.g. "pts/0" → 1000 */
|
|
177
254
|
function ttyToPid(tty: string): number {
|
|
178
255
|
const match = tty.match(/(\d+)$/);
|
|
179
256
|
return 1000 + (match?.[1] ? parseInt(match[1], 10) : 0);
|
|
@@ -194,16 +271,16 @@ function writeProcPid(
|
|
|
194
271
|
ensureDir(vfs, `${dir}/fd`);
|
|
195
272
|
ensureDir(vfs, `${dir}/fdinfo`);
|
|
196
273
|
|
|
197
|
-
const uptimeSec = Math.floor(
|
|
198
|
-
|
|
199
|
-
);
|
|
274
|
+
const uptimeSec = Math.floor((Date.now() - new Date(startedAt).getTime()) / 1000);
|
|
275
|
+
const comm = cmdline.split(/\s+/)[0] ?? "bash";
|
|
200
276
|
|
|
201
|
-
vfs
|
|
202
|
-
vfs
|
|
203
|
-
|
|
277
|
+
write(vfs, `${dir}/cmdline`, `${cmdline.replace(/\s+/g, "\0")}\0`);
|
|
278
|
+
write(vfs, `${dir}/comm`, comm);
|
|
279
|
+
write(
|
|
280
|
+
vfs,
|
|
204
281
|
`${dir}/status`,
|
|
205
282
|
`${[
|
|
206
|
-
`Name: ${
|
|
283
|
+
`Name: ${comm}`,
|
|
207
284
|
`State: S (sleeping)`,
|
|
208
285
|
`Pid: ${pid}`,
|
|
209
286
|
`PPid: 1`,
|
|
@@ -214,54 +291,71 @@ function writeProcPid(
|
|
|
214
291
|
`Threads: 1`,
|
|
215
292
|
].join("\n")}\n`,
|
|
216
293
|
);
|
|
217
|
-
|
|
294
|
+
write(
|
|
295
|
+
vfs,
|
|
218
296
|
`${dir}/stat`,
|
|
219
|
-
`${pid} (${
|
|
297
|
+
`${pid} (${comm}) S 1 ${pid} ${pid} 0 -1 4194304 0 0 0 0 ${uptimeSec} 0 0 0 20 0 1 0 0 16384 4096 0\n`,
|
|
220
298
|
);
|
|
221
|
-
|
|
299
|
+
write(
|
|
300
|
+
vfs,
|
|
222
301
|
`${dir}/environ`,
|
|
223
|
-
`${Object.entries(env)
|
|
224
|
-
.map(([k, v]) => `${k}=${v}`)
|
|
225
|
-
.join("\0")}\0`,
|
|
302
|
+
`${Object.entries(env).map(([k, v]) => `${k}=${v}`).join("\0")}\0`,
|
|
226
303
|
);
|
|
227
|
-
vfs
|
|
228
|
-
vfs
|
|
304
|
+
write(vfs, `${dir}/cwd`, `/home/${username}\0`);
|
|
305
|
+
write(vfs, `${dir}/exe`, "/bin/bash\0");
|
|
229
306
|
|
|
230
|
-
// Standard fd
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
307
|
+
// Standard fd stubs (stdin/stdout/stderr)
|
|
308
|
+
for (const fd of ["0", "1", "2"]) {
|
|
309
|
+
ensureFile(vfs, `${dir}/fd/${fd}`, "");
|
|
310
|
+
}
|
|
234
311
|
}
|
|
235
312
|
|
|
313
|
+
// ─── /proc boot log ──────────────────────────────────────────────────────────
|
|
314
|
+
|
|
315
|
+
function bootProcLog(vfs: VirtualFileSystem, props: ShellProperties): void {
|
|
316
|
+
ensureDir(vfs, "/proc/boot");
|
|
317
|
+
ensureFile(
|
|
318
|
+
vfs,
|
|
319
|
+
"/proc/boot/log",
|
|
320
|
+
`${[
|
|
321
|
+
"[ 0.000000] Linux virtual kernel booting...",
|
|
322
|
+
"[ 0.000120] init memory subsystem",
|
|
323
|
+
"[ 0.000240] mount /proc /sys /dev",
|
|
324
|
+
"[ 0.000420] start init",
|
|
325
|
+
"[ 0.000680] system ready",
|
|
326
|
+
].join("\n")}\n`,
|
|
327
|
+
);
|
|
328
|
+
ensureFile(vfs, "/proc/boot/version", `Linux ${props.kernel} (virtual)\n`);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// ─── /proc refresh ───────────────────────────────────────────────────────────
|
|
332
|
+
|
|
236
333
|
/**
|
|
237
334
|
* Populate and refresh `/proc` virtual entries based on host stats and
|
|
238
|
-
* provided active sessions. Rewrites
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
* @param hostname Hostname to write into /proc/hostname
|
|
243
|
-
* @param shellStartTime Start time used to compute uptime
|
|
244
|
-
* @param sessions Optional active sessions list to populate per-pid entries
|
|
335
|
+
* provided active sessions. Rewrites uptime, meminfo, cpuinfo, loadavg,
|
|
336
|
+
* per-pid entries, and /proc/self.
|
|
337
|
+
*
|
|
338
|
+
* Safe to call repeatedly — acts as a live kernel state snapshot.
|
|
245
339
|
*/
|
|
246
340
|
export function refreshProc(
|
|
247
341
|
vfs: VirtualFileSystem,
|
|
248
342
|
props: ShellProperties,
|
|
249
343
|
hostname: string,
|
|
250
344
|
shellStartTime: number,
|
|
251
|
-
sessions
|
|
345
|
+
sessions: VirtualActiveSession[] = [],
|
|
252
346
|
): void {
|
|
253
347
|
ensureDir(vfs, "/proc");
|
|
254
348
|
|
|
255
349
|
const uptimeSec = Math.floor((Date.now() - shellStartTime) / 1000);
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
`${uptimeSec}.00 ${Math.floor(uptimeSec * 0.9)}.00\n`,
|
|
259
|
-
);
|
|
350
|
+
const idleSec = Math.floor(uptimeSec * 0.9);
|
|
351
|
+
write(vfs, "/proc/uptime", `${uptimeSec}.00 ${idleSec}.00\n`);
|
|
260
352
|
|
|
353
|
+
// meminfo — real host values, Linux-compatible format
|
|
261
354
|
const totalMemKb = Math.floor(os.totalmem() / 1024);
|
|
262
355
|
const freeMemKb = Math.floor(os.freemem() / 1024);
|
|
263
356
|
const availMemKb = Math.floor(freeMemKb * 0.95);
|
|
264
|
-
|
|
357
|
+
write(
|
|
358
|
+
vfs,
|
|
265
359
|
"/proc/meminfo",
|
|
266
360
|
`${[
|
|
267
361
|
`MemTotal: ${String(totalMemKb).padStart(10)} kB`,
|
|
@@ -274,36 +368,33 @@ export function refreshProc(
|
|
|
274
368
|
].join("\n")}\n`,
|
|
275
369
|
);
|
|
276
370
|
|
|
371
|
+
// cpuinfo — real host CPU passthrough
|
|
277
372
|
const cpus = os.cpus();
|
|
278
373
|
const cpuLines: string[] = [];
|
|
279
374
|
for (let i = 0; i < cpus.length; i++) {
|
|
280
375
|
const c = cpus[i];
|
|
281
376
|
if (!c) continue;
|
|
282
|
-
const mhz = c.speed.toFixed(3);
|
|
283
377
|
cpuLines.push(
|
|
284
378
|
`processor\t: ${i}`,
|
|
285
379
|
`model name\t: ${c.model}`,
|
|
286
|
-
`cpu MHz\t\t: ${
|
|
380
|
+
`cpu MHz\t\t: ${c.speed.toFixed(3)}`,
|
|
287
381
|
`cache size\t: 8192 KB`,
|
|
288
382
|
"",
|
|
289
383
|
);
|
|
290
384
|
}
|
|
291
|
-
vfs
|
|
385
|
+
write(vfs, "/proc/cpuinfo", `${cpuLines.join("\n")}\n`);
|
|
292
386
|
|
|
293
|
-
|
|
387
|
+
write(
|
|
388
|
+
vfs,
|
|
294
389
|
"/proc/version",
|
|
295
390
|
`Linux version ${props.kernel} (fortune@build) (gcc version 12.2.0) #1 SMP\n`,
|
|
296
391
|
);
|
|
392
|
+
write(vfs, "/proc/hostname", `${hostname}\n`);
|
|
297
393
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
// /proc/loadavg
|
|
394
|
+
// loadavg — slightly random but bounded
|
|
301
395
|
const load = (Math.random() * 0.5).toFixed(2);
|
|
302
|
-
const numProcs = 1 +
|
|
303
|
-
vfs
|
|
304
|
-
"/proc/loadavg",
|
|
305
|
-
`${load} ${load} ${load} ${numProcs}/${numProcs} 1\n`,
|
|
306
|
-
);
|
|
396
|
+
const numProcs = 1 + sessions.length;
|
|
397
|
+
write(vfs, "/proc/loadavg", `${load} ${load} ${load} ${numProcs}/${numProcs} 1\n`);
|
|
307
398
|
|
|
308
399
|
// /proc/net stubs
|
|
309
400
|
ensureDir(vfs, "/proc/net");
|
|
@@ -317,113 +408,159 @@ export function refreshProc(
|
|
|
317
408
|
" eth0: 131072 1024 0 0 0 0 0 0 65536 512 0 0 0 0 0 0",
|
|
318
409
|
].join("\n")}\n`,
|
|
319
410
|
);
|
|
411
|
+
ensureFile(vfs, "/proc/net/if_inet6", "");
|
|
412
|
+
ensureFile(vfs, "/proc/net/tcp", " sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode\n");
|
|
413
|
+
ensureFile(vfs, "/proc/net/tcp6", " sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode\n");
|
|
414
|
+
|
|
415
|
+
// /proc/cmdline — kernel boot args
|
|
416
|
+
write(vfs, "/proc/cmdline", `BOOT_IMAGE=/boot/vmlinuz-${props.kernel} root=/dev/sda2 ro quiet splash\n`);
|
|
417
|
+
|
|
418
|
+
// /proc/filesystems
|
|
419
|
+
ensureFile(
|
|
420
|
+
vfs,
|
|
421
|
+
"/proc/filesystems",
|
|
422
|
+
`${["nodev\tsysfs", "nodev\ttmpfs", "nodev\tproc", "nodev\tdevtmpfs", "\text4", "\tvfat", "nodev\tsquashfs", "nodev\toverlay"].join("\n")}\n`,
|
|
423
|
+
);
|
|
424
|
+
|
|
425
|
+
// /proc/mounts (= /proc/self/mounts)
|
|
426
|
+
const mountsContent = `${[
|
|
427
|
+
"sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0",
|
|
428
|
+
"proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0",
|
|
429
|
+
"devtmpfs /dev devtmpfs rw,nosuid,size=8192k,nr_inodes=4096,mode=755 0 0",
|
|
430
|
+
"tmpfs /run tmpfs rw,nosuid,nodev,noexec,relatime,size=204800k,mode=755 0 0",
|
|
431
|
+
"tmpfs /tmp tmpfs rw,nosuid,nodev,noatime 0 0",
|
|
432
|
+
"/dev/sda2 / ext4 rw,relatime,errors=remount-ro 0 0",
|
|
433
|
+
"/dev/sda1 /boot ext4 rw,relatime 0 0",
|
|
434
|
+
"tmpfs /dev/shm tmpfs rw,nosuid,nodev 0 0",
|
|
435
|
+
"devpts /dev/pts devpts rw,nosuid,noexec,relatime,mode=620,ptmxmode=000 0 0",
|
|
436
|
+
"squashfs /snap/core squashfs ro,nodev,relatime 0 0",
|
|
437
|
+
].join("\n")}\n`;
|
|
438
|
+
write(vfs, "/proc/mounts", mountsContent);
|
|
439
|
+
ensureDir(vfs, "/proc/self");
|
|
440
|
+
write(vfs, "/proc/self/mounts", mountsContent);
|
|
441
|
+
|
|
442
|
+
// /proc/partitions
|
|
443
|
+
write(
|
|
444
|
+
vfs,
|
|
445
|
+
"/proc/partitions",
|
|
446
|
+
`${[
|
|
447
|
+
"major minor #blocks name",
|
|
448
|
+
"",
|
|
449
|
+
" 8 0 41943040 sda",
|
|
450
|
+
" 8 1 524288 sda1",
|
|
451
|
+
" 8 2 41417216 sda2",
|
|
452
|
+
" 7 0 10485760 loop0",
|
|
453
|
+
].join("\n")}\n`,
|
|
454
|
+
);
|
|
320
455
|
|
|
321
|
-
//
|
|
322
|
-
|
|
456
|
+
// /proc/swaps
|
|
457
|
+
write(
|
|
323
458
|
vfs,
|
|
324
|
-
|
|
325
|
-
"
|
|
326
|
-
|
|
327
|
-
"/sbin/init",
|
|
328
|
-
new Date(shellStartTime).toISOString(),
|
|
329
|
-
{},
|
|
459
|
+
"/proc/swaps",
|
|
460
|
+
"Filename\t\t\t\tType\t\tSize\t\tUsed\t\tPriority\n" +
|
|
461
|
+
`/dev/sda3\t\t\t\tpartition\t${Math.floor(os.totalmem() / 2048)}\t\t0\t\t-2\n`,
|
|
330
462
|
);
|
|
331
463
|
|
|
332
|
-
//
|
|
333
|
-
|
|
334
|
-
|
|
464
|
+
// /proc/sys — sysctl virtual tree
|
|
465
|
+
ensureDir(vfs, "/proc/sys");
|
|
466
|
+
ensureDir(vfs, "/proc/sys/kernel");
|
|
467
|
+
ensureDir(vfs, "/proc/sys/net");
|
|
468
|
+
ensureDir(vfs, "/proc/sys/vm");
|
|
469
|
+
ensureFile(vfs, "/proc/sys/kernel/hostname", `${hostname}\n`);
|
|
470
|
+
ensureFile(vfs, "/proc/sys/kernel/ostype", "Linux\n");
|
|
471
|
+
ensureFile(vfs, "/proc/sys/kernel/osrelease", `${props.kernel}\n`);
|
|
472
|
+
ensureFile(vfs, "/proc/sys/kernel/pid_max", "32768\n");
|
|
473
|
+
ensureFile(vfs, "/proc/sys/kernel/threads-max", "65536\n");
|
|
474
|
+
ensureFile(vfs, "/proc/sys/kernel/randomize_va_space", "2\n");
|
|
475
|
+
ensureFile(vfs, "/proc/sys/kernel/dmesg_restrict", "0\n");
|
|
476
|
+
ensureFile(vfs, "/proc/sys/net/ipv4/ip_forward", "0\n");
|
|
477
|
+
ensureFile(vfs, "/proc/sys/vm/swappiness", "60\n");
|
|
478
|
+
ensureFile(vfs, "/proc/sys/vm/overcommit_memory", "0\n");
|
|
479
|
+
|
|
480
|
+
// init process (PID 1)
|
|
481
|
+
writeProcPid(vfs, 1, "root", "pts/0", "/sbin/init", new Date(shellStartTime).toISOString(), {});
|
|
482
|
+
|
|
483
|
+
// per-session processes
|
|
484
|
+
for (const session of sessions) {
|
|
335
485
|
const pid = ttyToPid(session.tty);
|
|
336
|
-
writeProcPid(
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
session.startedAt,
|
|
343
|
-
{
|
|
344
|
-
USER: session.username,
|
|
345
|
-
HOME: `/home/${session.username}`,
|
|
346
|
-
TERM: "xterm-256color",
|
|
347
|
-
SHELL: "/bin/bash",
|
|
348
|
-
},
|
|
349
|
-
);
|
|
486
|
+
writeProcPid(vfs, pid, session.username, session.tty, "bash", session.startedAt, {
|
|
487
|
+
USER: session.username,
|
|
488
|
+
HOME: `/home/${session.username}`,
|
|
489
|
+
TERM: "xterm-256color",
|
|
490
|
+
SHELL: "/bin/bash",
|
|
491
|
+
});
|
|
350
492
|
}
|
|
351
493
|
|
|
352
|
-
//
|
|
353
|
-
|
|
354
|
-
// so /proc/self is a directory that mirrors the most recent session,
|
|
355
|
-
// or init if no sessions. Commands that read /proc/self get consistent data.
|
|
356
|
-
const selfPid =
|
|
357
|
-
activeSessions.length > 0
|
|
358
|
-
? ttyToPid(activeSessions[activeSessions.length - 1]!.tty)
|
|
359
|
-
: 1;
|
|
494
|
+
// /proc/self — mirror of most recent session, or init
|
|
495
|
+
const selfPid = sessions.length > 0 ? ttyToPid(sessions[sessions.length - 1]!.tty) : 1;
|
|
360
496
|
|
|
361
|
-
// Remove existing /proc/self and recreate as content copy
|
|
362
497
|
if (vfs.exists("/proc/self")) {
|
|
363
|
-
try {
|
|
364
|
-
vfs.remove("/proc/self");
|
|
365
|
-
} catch {}
|
|
498
|
+
try { vfs.remove("/proc/self"); } catch { /* ignore */ }
|
|
366
499
|
}
|
|
367
|
-
|
|
500
|
+
|
|
368
501
|
const selfSrc = `/proc/${selfPid}`;
|
|
502
|
+
ensureDir(vfs, "/proc/self");
|
|
503
|
+
ensureDir(vfs, "/proc/self/fd");
|
|
504
|
+
|
|
369
505
|
if (vfs.exists(selfSrc)) {
|
|
370
|
-
ensureDir(vfs, "/proc/self");
|
|
371
|
-
ensureDir(vfs, "/proc/self/fd");
|
|
372
506
|
for (const entry of vfs.list(selfSrc)) {
|
|
373
507
|
const srcPath = `${selfSrc}/${entry}`;
|
|
374
508
|
const dstPath = `/proc/self/${entry}`;
|
|
375
509
|
try {
|
|
376
510
|
const st = vfs.stat(srcPath);
|
|
377
|
-
if (st.type === "file")
|
|
378
|
-
|
|
379
|
-
}
|
|
380
|
-
} catch {}
|
|
511
|
+
if (st.type === "file") write(vfs, dstPath, vfs.readFile(srcPath));
|
|
512
|
+
} catch { /* skip unreadable entries */ }
|
|
381
513
|
}
|
|
382
|
-
vfs.writeFile(
|
|
383
|
-
"/proc/self/status",
|
|
384
|
-
vfs.exists(`${selfSrc}/status`) ? vfs.readFile(`${selfSrc}/status`) : "",
|
|
385
|
-
);
|
|
386
514
|
} else {
|
|
387
|
-
//
|
|
388
|
-
|
|
389
|
-
vfs
|
|
390
|
-
vfs
|
|
391
|
-
vfs
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
);
|
|
395
|
-
vfs.writeFile("/proc/self/environ", "");
|
|
396
|
-
vfs.writeFile("/proc/self/cwd", "/root\0");
|
|
397
|
-
vfs.writeFile("/proc/self/exe", "/bin/bash\0");
|
|
515
|
+
// Minimal fallback
|
|
516
|
+
write(vfs, "/proc/self/cmdline", "bash\0");
|
|
517
|
+
write(vfs, "/proc/self/comm", "bash");
|
|
518
|
+
write(vfs, "/proc/self/status", "Name:\tbash\nState:\tS (sleeping)\nPid:\t1\nPPid:\t0\n");
|
|
519
|
+
write(vfs, "/proc/self/environ", "");
|
|
520
|
+
write(vfs, "/proc/self/cwd", "/root\0");
|
|
521
|
+
write(vfs, "/proc/self/exe", "/bin/bash\0");
|
|
398
522
|
}
|
|
399
523
|
}
|
|
400
524
|
|
|
401
525
|
// ─── /sys ─────────────────────────────────────────────────────────────────────
|
|
402
526
|
|
|
403
|
-
function bootstrapSys(vfs: VirtualFileSystem, props: ShellProperties): void {
|
|
527
|
+
function bootstrapSys(vfs: VirtualFileSystem, hostname: string, props: ShellProperties): void {
|
|
404
528
|
ensureDir(vfs, "/sys");
|
|
405
529
|
ensureDir(vfs, "/sys/devices");
|
|
406
530
|
ensureDir(vfs, "/sys/devices/virtual");
|
|
407
531
|
ensureDir(vfs, "/sys/devices/virtual/dmi");
|
|
408
532
|
ensureDir(vfs, "/sys/devices/virtual/dmi/id");
|
|
409
533
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
"/
|
|
418
|
-
"
|
|
419
|
-
|
|
420
|
-
|
|
534
|
+
const seed = fnv1a(hostname);
|
|
535
|
+
const product = `VirtualNode-${(seed % 10000).toString().padStart(4, "0")}`;
|
|
536
|
+
|
|
537
|
+
// Full DMI table — deterministic, seeded from hostname
|
|
538
|
+
const dmi: Record<string, string> = {
|
|
539
|
+
bios_vendor: "Virtual BIOS",
|
|
540
|
+
bios_version: "1.0",
|
|
541
|
+
bios_date: "01/01/2025",
|
|
542
|
+
sys_vendor: "Fortune Systems",
|
|
543
|
+
product_name: product,
|
|
544
|
+
product_family: "VirtualContainer",
|
|
545
|
+
product_version: "v1",
|
|
546
|
+
product_uuid: `${seed.toString(16).padStart(8, "0")}-0000-0000-0000-000000000000`,
|
|
547
|
+
product_serial: `SN-${seed}`,
|
|
548
|
+
chassis_type: "3",
|
|
549
|
+
chassis_vendor: "Virtual",
|
|
550
|
+
chassis_version: "v1",
|
|
551
|
+
board_name: "fortune-board",
|
|
552
|
+
modalias: `dmi:bvnVirtual:bvr1.0:svnFortune:pn${product}`,
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
for (const [k, v] of Object.entries(dmi)) {
|
|
556
|
+
ensureFile(vfs, `/sys/devices/virtual/dmi/id/${k}`, `${v}\n`);
|
|
557
|
+
}
|
|
421
558
|
|
|
422
559
|
ensureDir(vfs, "/sys/class");
|
|
423
560
|
ensureDir(vfs, "/sys/class/net");
|
|
424
|
-
|
|
425
561
|
ensureDir(vfs, "/sys/kernel");
|
|
426
|
-
|
|
562
|
+
|
|
563
|
+
ensureFile(vfs, "/sys/kernel/hostname", `${hostname}\n`);
|
|
427
564
|
ensureFile(vfs, "/sys/kernel/osrelease", `${props.kernel}\n`);
|
|
428
565
|
ensureFile(vfs, "/sys/kernel/ostype", "Linux\n");
|
|
429
566
|
}
|
|
@@ -432,12 +569,39 @@ function bootstrapSys(vfs: VirtualFileSystem, props: ShellProperties): void {
|
|
|
432
569
|
|
|
433
570
|
function bootstrapDev(vfs: VirtualFileSystem): void {
|
|
434
571
|
ensureDir(vfs, "/dev");
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
ensureFile(vfs, "/dev/
|
|
572
|
+
|
|
573
|
+
// character devices
|
|
574
|
+
ensureFile(vfs, "/dev/null", "", 0o666);
|
|
575
|
+
ensureFile(vfs, "/dev/zero", "", 0o666);
|
|
576
|
+
ensureFile(vfs, "/dev/full", "", 0o666);
|
|
577
|
+
ensureFile(vfs, "/dev/random", "", 0o444);
|
|
438
578
|
ensureFile(vfs, "/dev/urandom", "", 0o444);
|
|
579
|
+
ensureFile(vfs, "/dev/mem", "", 0o640);
|
|
580
|
+
|
|
581
|
+
// terminal devices
|
|
582
|
+
ensureFile(vfs, "/dev/console", "", 0o600);
|
|
583
|
+
ensureFile(vfs, "/dev/tty", "", 0o666);
|
|
584
|
+
ensureFile(vfs, "/dev/tty0", "", 0o620);
|
|
585
|
+
ensureFile(vfs, "/dev/tty1", "", 0o620);
|
|
586
|
+
ensureFile(vfs, "/dev/ttyS0", "", 0o660);
|
|
587
|
+
|
|
588
|
+
// loop devices
|
|
589
|
+
for (let i = 0; i < 8; i++) {
|
|
590
|
+
ensureFile(vfs, `/dev/loop${i}`, "", 0o660);
|
|
591
|
+
}
|
|
592
|
+
ensureDir(vfs, "/dev/loop-control");
|
|
593
|
+
|
|
594
|
+
// block device stubs (sda + partitions)
|
|
595
|
+
ensureFile(vfs, "/dev/sda", "", 0o660);
|
|
596
|
+
ensureFile(vfs, "/dev/sda1", "", 0o660);
|
|
597
|
+
ensureFile(vfs, "/dev/sda2", "", 0o660);
|
|
598
|
+
|
|
599
|
+
// misc
|
|
439
600
|
ensureDir(vfs, "/dev/pts");
|
|
440
601
|
ensureDir(vfs, "/dev/shm");
|
|
602
|
+
ensureFile(vfs, "/dev/stdin", "", 0o666);
|
|
603
|
+
ensureFile(vfs, "/dev/stdout", "", 0o666);
|
|
604
|
+
ensureFile(vfs, "/dev/stderr", "", 0o666);
|
|
441
605
|
}
|
|
442
606
|
|
|
443
607
|
// ─── /usr ─────────────────────────────────────────────────────────────────────
|
|
@@ -456,70 +620,21 @@ function bootstrapUsr(vfs: VirtualFileSystem): void {
|
|
|
456
620
|
ensureDir(vfs, "/usr/share/man/man1");
|
|
457
621
|
ensureDir(vfs, "/usr/lib");
|
|
458
622
|
|
|
459
|
-
//
|
|
623
|
+
// Stubs so `which` can resolve built-in commands
|
|
460
624
|
const builtins = [
|
|
461
|
-
"sh",
|
|
462
|
-
"
|
|
463
|
-
"
|
|
464
|
-
"
|
|
465
|
-
"
|
|
466
|
-
"
|
|
467
|
-
"find",
|
|
468
|
-
"sort",
|
|
469
|
-
"head",
|
|
470
|
-
"tail",
|
|
471
|
-
"cut",
|
|
472
|
-
"tr",
|
|
473
|
-
"sed",
|
|
474
|
-
"awk",
|
|
475
|
-
"wc",
|
|
476
|
-
"tee",
|
|
477
|
-
"tar",
|
|
478
|
-
"gzip",
|
|
479
|
-
"gunzip",
|
|
480
|
-
"touch",
|
|
481
|
-
"mkdir",
|
|
482
|
-
"rm",
|
|
483
|
-
"mv",
|
|
484
|
-
"cp",
|
|
485
|
-
"chmod",
|
|
486
|
-
"ln",
|
|
487
|
-
"pwd",
|
|
488
|
-
"env",
|
|
489
|
-
"date",
|
|
490
|
-
"sleep",
|
|
491
|
-
"id",
|
|
492
|
-
"whoami",
|
|
493
|
-
"hostname",
|
|
494
|
-
"uname",
|
|
495
|
-
"ps",
|
|
496
|
-
"kill",
|
|
497
|
-
"df",
|
|
498
|
-
"du",
|
|
499
|
-
"curl",
|
|
500
|
-
"wget",
|
|
501
|
-
"nano",
|
|
502
|
-
"diff",
|
|
503
|
-
"uniq",
|
|
504
|
-
"xargs",
|
|
505
|
-
"base64",
|
|
625
|
+
"sh", "bash", "ls", "cat", "echo", "grep", "find", "sort",
|
|
626
|
+
"head", "tail", "cut", "tr", "sed", "awk", "wc", "tee",
|
|
627
|
+
"tar", "gzip", "gunzip", "touch", "mkdir", "rm", "mv", "cp",
|
|
628
|
+
"chmod", "ln", "pwd", "env", "date", "sleep", "id", "whoami",
|
|
629
|
+
"hostname", "uname", "ps", "kill", "df", "du", "curl", "wget",
|
|
630
|
+
"nano", "diff", "uniq", "xargs", "base64",
|
|
506
631
|
];
|
|
632
|
+
|
|
507
633
|
for (const bin of builtins) {
|
|
508
|
-
ensureFile(
|
|
509
|
-
vfs,
|
|
510
|
-
`/usr/bin/${bin}`,
|
|
511
|
-
`#!/bin/sh\nexec builtin ${bin} "$@"\n`,
|
|
512
|
-
0o755,
|
|
513
|
-
);
|
|
634
|
+
ensureFile(vfs, `/usr/bin/${bin}`, `#!/bin/sh\nexec builtin ${bin} "$@"\n`, 0o755);
|
|
514
635
|
}
|
|
515
636
|
|
|
516
|
-
|
|
517
|
-
ensureFile(
|
|
518
|
-
vfs,
|
|
519
|
-
"/usr/bin/lsb_release",
|
|
520
|
-
'#!/bin/sh\nexec lsb_release "$@"\n',
|
|
521
|
-
0o755,
|
|
522
|
-
);
|
|
637
|
+
ensureFile(vfs, "/usr/bin/lsb_release", '#!/bin/sh\nexec lsb_release "$@"\n', 0o755);
|
|
523
638
|
}
|
|
524
639
|
|
|
525
640
|
// ─── /var ─────────────────────────────────────────────────────────────────────
|
|
@@ -527,8 +642,8 @@ function bootstrapUsr(vfs: VirtualFileSystem): void {
|
|
|
527
642
|
function bootstrapVar(vfs: VirtualFileSystem): void {
|
|
528
643
|
ensureDir(vfs, "/var");
|
|
529
644
|
ensureDir(vfs, "/var/log");
|
|
645
|
+
ensureDir(vfs, "/var/log/apt");
|
|
530
646
|
ensureDir(vfs, "/var/tmp");
|
|
531
|
-
ensureDir(vfs, "/var/run");
|
|
532
647
|
ensureDir(vfs, "/var/cache");
|
|
533
648
|
ensureDir(vfs, "/var/cache/apt");
|
|
534
649
|
ensureDir(vfs, "/var/cache/apt/archives");
|
|
@@ -537,39 +652,46 @@ function bootstrapVar(vfs: VirtualFileSystem): void {
|
|
|
537
652
|
ensureDir(vfs, "/var/lib/apt/lists");
|
|
538
653
|
ensureDir(vfs, "/var/lib/dpkg");
|
|
539
654
|
ensureDir(vfs, "/var/lib/dpkg/info");
|
|
655
|
+
ensureDir(vfs, "/var/lib/misc");
|
|
656
|
+
ensureDir(vfs, "/var/spool");
|
|
657
|
+
ensureDir(vfs, "/var/spool/cron");
|
|
658
|
+
ensureDir(vfs, "/var/mail");
|
|
540
659
|
|
|
541
|
-
// dpkg status — starts empty,
|
|
660
|
+
// dpkg status — starts empty, VirtualPackageManager populates it
|
|
542
661
|
ensureFile(vfs, "/var/lib/dpkg/status", "");
|
|
543
662
|
ensureFile(vfs, "/var/lib/dpkg/available", "");
|
|
544
663
|
|
|
545
|
-
// syslog
|
|
546
|
-
ensureFile(
|
|
547
|
-
vfs,
|
|
548
|
-
"/var/log/syslog",
|
|
549
|
-
`${new Date().toUTCString()} fortune kernel: Virtual container started\n`,
|
|
550
|
-
);
|
|
664
|
+
// syslog stubs
|
|
665
|
+
ensureFile(vfs, "/var/log/syslog", `${new Date().toUTCString()} fortune kernel: Virtual container started\n`);
|
|
551
666
|
ensureFile(vfs, "/var/log/auth.log", "");
|
|
667
|
+
ensureFile(vfs, "/var/log/kern.log", "");
|
|
552
668
|
ensureFile(vfs, "/var/log/dpkg.log", "");
|
|
553
669
|
ensureFile(vfs, "/var/log/apt/history.log", "");
|
|
554
670
|
ensureFile(vfs, "/var/log/apt/term.log", "");
|
|
671
|
+
|
|
672
|
+
// /run — systemd tmpfs runtime dir (canonical on modern Debian)
|
|
673
|
+
// /var/run is a legacy symlink to /run
|
|
674
|
+
ensureDir(vfs, "/run");
|
|
675
|
+
ensureDir(vfs, "/run/lock");
|
|
676
|
+
ensureDir(vfs, "/run/systemd");
|
|
677
|
+
ensureDir(vfs, "/run/user");
|
|
678
|
+
ensureFile(vfs, "/run/utmp", "");
|
|
555
679
|
}
|
|
556
680
|
|
|
557
681
|
// ─── /bin + /sbin symlinks ────────────────────────────────────────────────────
|
|
558
682
|
|
|
559
683
|
function bootstrapBin(vfs: VirtualFileSystem): void {
|
|
560
|
-
//
|
|
561
|
-
if (!vfs.exists("/bin"))
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
ensureDir(vfs, "/lib64");
|
|
572
|
-
}
|
|
684
|
+
// Modern Debian: /bin and /sbin are symlinks to /usr/bin and /usr/sbin
|
|
685
|
+
if (!vfs.exists("/bin")) vfs.symlink("/usr/bin", "/bin");
|
|
686
|
+
if (!vfs.exists("/sbin")) vfs.symlink("/usr/sbin", "/sbin");
|
|
687
|
+
|
|
688
|
+
// /var/run → /run (systemd compat)
|
|
689
|
+
if (!vfs.exists("/var/run")) vfs.symlink("/run", "/var/run");
|
|
690
|
+
|
|
691
|
+
ensureDir(vfs, "/lib");
|
|
692
|
+
ensureDir(vfs, "/lib64");
|
|
693
|
+
ensureDir(vfs, "/lib/x86_64-linux-gnu");
|
|
694
|
+
ensureDir(vfs, "/lib/modules");
|
|
573
695
|
}
|
|
574
696
|
|
|
575
697
|
// ─── /tmp ─────────────────────────────────────────────────────────────────────
|
|
@@ -578,13 +700,13 @@ function bootstrapTmp(vfs: VirtualFileSystem): void {
|
|
|
578
700
|
ensureDir(vfs, "/tmp", 0o1777);
|
|
579
701
|
}
|
|
580
702
|
|
|
581
|
-
// ─── /root
|
|
703
|
+
// ─── /root home ───────────────────────────────────────────────────────────────
|
|
582
704
|
|
|
583
705
|
function bootstrapRoot(vfs: VirtualFileSystem): void {
|
|
584
706
|
ensureDir(vfs, "/root", 0o700);
|
|
585
707
|
ensureFile(
|
|
586
708
|
vfs,
|
|
587
|
-
"/
|
|
709
|
+
"/root/.bashrc",
|
|
588
710
|
`${[
|
|
589
711
|
"# root .bashrc",
|
|
590
712
|
"export PS1='\\[\\033[0;31m\\]\\u@\\h\\[\\033[0m\\]:\\[\\033[0;34m\\]\\w\\[\\033[0m\\]# '",
|
|
@@ -593,20 +715,55 @@ function bootstrapRoot(vfs: VirtualFileSystem): void {
|
|
|
593
715
|
"alias la='ls -A'",
|
|
594
716
|
].join("\n")}\n`,
|
|
595
717
|
);
|
|
596
|
-
ensureFile(vfs, "/
|
|
597
|
-
// Fix: /home/root should map to /root for root user
|
|
598
|
-
// if (!vfs.exists("/home/root")) {
|
|
599
|
-
// vfs.symlink("/root", "/home/root");
|
|
600
|
-
// }
|
|
718
|
+
ensureFile(vfs, "/root/.profile", "[ -f ~/.bashrc ] && . ~/.bashrc\n");
|
|
601
719
|
}
|
|
602
720
|
|
|
603
|
-
// ─── /opt
|
|
721
|
+
// ─── /opt /srv /mnt /media /home ─────────────────────────────────────────────
|
|
604
722
|
|
|
605
|
-
function bootstrapMisc(vfs: VirtualFileSystem): void {
|
|
723
|
+
function bootstrapMisc(vfs: VirtualFileSystem, props: ShellProperties): void {
|
|
606
724
|
ensureDir(vfs, "/opt");
|
|
607
725
|
ensureDir(vfs, "/srv");
|
|
608
726
|
ensureDir(vfs, "/mnt");
|
|
609
727
|
ensureDir(vfs, "/media");
|
|
728
|
+
ensureDir(vfs, "/home");
|
|
729
|
+
|
|
730
|
+
// /boot — grub + kernel images
|
|
731
|
+
ensureDir(vfs, "/boot");
|
|
732
|
+
ensureDir(vfs, "/boot/grub");
|
|
733
|
+
ensureDir(vfs, "/boot/grub/grub.cfg.d");
|
|
734
|
+
ensureFile(
|
|
735
|
+
vfs,
|
|
736
|
+
"/boot/grub/grub.cfg",
|
|
737
|
+
`${[
|
|
738
|
+
"# GRUB configuration (virtual)",
|
|
739
|
+
"set default=0",
|
|
740
|
+
"set timeout=5",
|
|
741
|
+
"",
|
|
742
|
+
`menuentry "Fortune GNU/Linux" {`,
|
|
743
|
+
` linux /vmlinuz root=/dev/sda2 ro quiet splash`,
|
|
744
|
+
` initrd /initrd.img`,
|
|
745
|
+
`}`,
|
|
746
|
+
].join("\n")}\n`,
|
|
747
|
+
);
|
|
748
|
+
// kernel + initrd stubs in /boot
|
|
749
|
+
const kver = props.kernel;
|
|
750
|
+
ensureFile(vfs, `/boot/vmlinuz-${kver}`, "", 0o644);
|
|
751
|
+
ensureFile(vfs, `/boot/initrd.img-${kver}`, "", 0o644);
|
|
752
|
+
ensureFile(vfs, `/boot/System.map-${kver}`, `${kver} virtual\n`, 0o644);
|
|
753
|
+
ensureFile(vfs, `/boot/config-${kver}`, `# Linux kernel config ${kver}\n`, 0o644);
|
|
754
|
+
|
|
755
|
+
// root-level symlinks (Debian convention)
|
|
756
|
+
if (!vfs.exists("/vmlinuz")) vfs.symlink(`/boot/vmlinuz-${kver}`, "/vmlinuz");
|
|
757
|
+
if (!vfs.exists("/vmlinuz.old")) vfs.symlink(`/boot/vmlinuz-${kver}`, "/vmlinuz.old");
|
|
758
|
+
if (!vfs.exists("/initrd.img")) vfs.symlink(`/boot/initrd.img-${kver}`, "/initrd.img");
|
|
759
|
+
if (!vfs.exists("/initrd.img.old")) vfs.symlink(`/boot/initrd.img-${kver}`, "/initrd.img.old");
|
|
760
|
+
|
|
761
|
+
// /snap — snapd mount namespace root
|
|
762
|
+
ensureDir(vfs, "/snap");
|
|
763
|
+
ensureDir(vfs, "/snap/bin");
|
|
764
|
+
|
|
765
|
+
// /lost+found — ext4 fsck recovery dir (mode 0o700, root only)
|
|
766
|
+
ensureDir(vfs, "/lost+found", 0o700);
|
|
610
767
|
}
|
|
611
768
|
|
|
612
769
|
// ─── main entry point ─────────────────────────────────────────────────────────
|
|
@@ -615,11 +772,12 @@ function bootstrapMisc(vfs: VirtualFileSystem): void {
|
|
|
615
772
|
* Bootstraps the full Linux rootfs hierarchy in the VFS.
|
|
616
773
|
* Safe to call multiple times — idempotent.
|
|
617
774
|
*
|
|
618
|
-
* @param vfs
|
|
619
|
-
* @param users
|
|
620
|
-
* @param hostname
|
|
621
|
-
* @param props
|
|
775
|
+
* @param vfs Target virtual filesystem.
|
|
776
|
+
* @param users User manager (for /etc/passwd sync).
|
|
777
|
+
* @param hostname Virtual hostname.
|
|
778
|
+
* @param props Shell properties (kernel, os, arch).
|
|
622
779
|
* @param shellStartTime Unix ms of shell creation (for uptime).
|
|
780
|
+
* @param sessions Active sessions (for /proc/<pid> population).
|
|
623
781
|
*/
|
|
624
782
|
export function bootstrapLinuxRootfs(
|
|
625
783
|
vfs: VirtualFileSystem,
|
|
@@ -627,16 +785,47 @@ export function bootstrapLinuxRootfs(
|
|
|
627
785
|
hostname: string,
|
|
628
786
|
props: ShellProperties,
|
|
629
787
|
shellStartTime: number,
|
|
788
|
+
sessions: VirtualActiveSession[] = [],
|
|
630
789
|
): void {
|
|
631
790
|
bootstrapEtc(vfs, hostname, props);
|
|
632
|
-
bootstrapSys(vfs, props);
|
|
791
|
+
bootstrapSys(vfs, hostname, props);
|
|
633
792
|
bootstrapDev(vfs);
|
|
634
793
|
bootstrapUsr(vfs);
|
|
635
794
|
bootstrapVar(vfs);
|
|
636
795
|
bootstrapBin(vfs);
|
|
637
796
|
bootstrapTmp(vfs);
|
|
638
797
|
bootstrapRoot(vfs);
|
|
639
|
-
bootstrapMisc(vfs);
|
|
640
|
-
|
|
798
|
+
bootstrapMisc(vfs, props);
|
|
799
|
+
bootProcLog(vfs, props);
|
|
800
|
+
refreshProc(vfs, props, hostname, shellStartTime, sessions);
|
|
641
801
|
syncEtcPasswd(vfs, users);
|
|
642
802
|
}
|
|
803
|
+
|
|
804
|
+
// ─── optional live engine ─────────────────────────────────────────────────────
|
|
805
|
+
|
|
806
|
+
/**
|
|
807
|
+
* Engine for runtimes that want periodic /proc refresh (e.g. web shell
|
|
808
|
+
* with live `top`/`ps` output). Call `.boot()` once, then `.tick()` on
|
|
809
|
+
* each session change or on a timer.
|
|
810
|
+
*
|
|
811
|
+
* ```ts
|
|
812
|
+
* const engine = createLinuxRootfsEngine(vfs, props, hostname, Date.now());
|
|
813
|
+
* engine.boot(users, sessions);
|
|
814
|
+
* setInterval(() => engine.tick(shell.listActiveSessions()), 5000);
|
|
815
|
+
* ```
|
|
816
|
+
*/
|
|
817
|
+
export function createLinuxRootfsEngine(
|
|
818
|
+
vfs: VirtualFileSystem,
|
|
819
|
+
props: ShellProperties,
|
|
820
|
+
hostname: string,
|
|
821
|
+
startTime: number,
|
|
822
|
+
) {
|
|
823
|
+
return {
|
|
824
|
+
boot(users: VirtualUserManager, sessions: VirtualActiveSession[] = []) {
|
|
825
|
+
bootstrapLinuxRootfs(vfs, users, hostname, props, startTime, sessions);
|
|
826
|
+
},
|
|
827
|
+
tick(sessions: VirtualActiveSession[] = []) {
|
|
828
|
+
refreshProc(vfs, props, hostname, startTime, sessions);
|
|
829
|
+
},
|
|
830
|
+
};
|
|
831
|
+
}
|