feat: add TCP staging path for FreeDOS
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
@echo off
|
||||
rem Pull a host-built TCP staging bundle into the authoritative C:\FEC tree.
|
||||
rem QEMU user networking exposes the host as 10.0.2.2. HTGET and UNZIP are
|
||||
rem supplied by the installed FreeDOS network tools.
|
||||
if "%1"=="" goto usage
|
||||
if exist C:\FEC\STAGE.ZIP del C:\FEC\STAGE.ZIP
|
||||
htget -o C:\FEC\STAGE.ZIP %1
|
||||
if errorlevel 1 goto fail
|
||||
unzip -o C:\FEC\STAGE.ZIP -d C:\FEC
|
||||
if errorlevel 1 goto fail
|
||||
if exist C:\FEC\TCPSTG.OK del C:\FEC\TCPSTG.OK
|
||||
echo OK>C:\FEC\TCPSTG.OK
|
||||
goto done
|
||||
:usage
|
||||
echo usage: TCP-STAGE.BAT http://10.0.2.2:8000/STAGE.ZIP
|
||||
goto done
|
||||
:fail
|
||||
echo FAIL>C:\FEC\TCPSTG.FAIL
|
||||
:done
|
||||
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Build and serve a FreeDOS TCP staging bundle.
|
||||
|
||||
The guest pulls STAGE.ZIP with its existing HTGET client from QEMU user-net's
|
||||
host address (10.0.2.2), then extracts it into C:\\FEC. This avoids changing
|
||||
the live vvfat exchange disk and keeps serial for bootstrap/recovery only.
|
||||
"""
|
||||
import argparse
|
||||
import http.server
|
||||
import os
|
||||
import shutil
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
DEFAULT_STAGE = ROOT / ".tcp-stage"
|
||||
|
||||
|
||||
def bundle(stage: Path, files: list[str]) -> Path:
|
||||
if stage.exists():
|
||||
shutil.rmtree(stage)
|
||||
stage.mkdir(parents=True)
|
||||
archive = stage / "STAGE.ZIP"
|
||||
with zipfile.ZipFile(archive, "w", zipfile.ZIP_DEFLATED) as zf:
|
||||
for item in files:
|
||||
source = (ROOT / item).resolve()
|
||||
try:
|
||||
relative = source.relative_to(ROOT / "fec")
|
||||
except ValueError as exc:
|
||||
raise SystemExit("only files below fec/ may be staged: " + item) from exc
|
||||
if not source.is_file():
|
||||
raise SystemExit("not a file: " + item)
|
||||
zf.write(source, relative.as_posix())
|
||||
print("created %s (%d bytes)" % (archive, archive.stat().st_size))
|
||||
return archive
|
||||
|
||||
|
||||
def serve(stage: Path, port: int) -> None:
|
||||
if not (stage / "STAGE.ZIP").is_file():
|
||||
raise SystemExit("missing STAGE.ZIP; run bundle first")
|
||||
handler = lambda *args, **kwargs: http.server.SimpleHTTPRequestHandler(
|
||||
*args, directory=str(stage), **kwargs)
|
||||
server = http.server.ThreadingHTTPServer(("0.0.0.0", port), handler)
|
||||
print("serving %s at http://10.0.2.2:%d/STAGE.ZIP" % (stage, port))
|
||||
try:
|
||||
server.serve_forever()
|
||||
finally:
|
||||
server.server_close()
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--stage-dir", type=Path, default=DEFAULT_STAGE)
|
||||
commands = parser.add_subparsers(dest="command", required=True)
|
||||
make = commands.add_parser("bundle")
|
||||
make.add_argument("files", nargs="+")
|
||||
web = commands.add_parser("serve")
|
||||
web.add_argument("--port", type=int, default=8000)
|
||||
args = parser.parse_args()
|
||||
if args.command == "bundle":
|
||||
bundle(args.stage_dir, args.files)
|
||||
else:
|
||||
serve(args.stage_dir, args.port)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user