The root package becomes a virtual workspace: `crates/ecr` holds the
library (package name `ecr`) and `crates/ecr-cli` the command line
front-end, which keeps installing the `ecr` binary. No behavior change.
The library must not depend on CLI types, so mount::setup_mounts now
takes the `no_bind` flag instead of a `&Args`.
- hard links in the rootfs were written as zero-size entries with no
inode set (all zero), so the kernel could link them to the wrong file;
assign a synthetic inode per (device, inode) group.
- build the cpio archive by streaming entries to disk instead of holding
the whole archive in memory.
- the VM command was joined into a single string and shell-expanded in
the guest, mangling quotes and nested commands; pass the argv
base64-encoded (ECR_ARGV) and exec it verbatim.
- parse ecr parameters from /proc/cmdline in the init script, set the
hostname via procfs (arch has no hostname binary), and give the serial
console a moment to drain before poweroff.
- --kernel took an optional value greedily, swallowing the DISTRO
positional: 'ecr --kernel alpine' failed with a missing-argument error
and 'ecr --kernel alpine -- cmd' pulled a garbage OCI ref. require
=PATH syntax for the kernel path instead.
- setup_namespaces returns the child's exit code (or 128+signal) instead
of calling process::exit, so the extracted rootfs tempdir is cleaned
up before exiting instead of leaking into /tmp.
- warn that --bind/--bind-rw are ignored when booting with --kernel.
extract_kernel_from_apk fell through to an unconditional error after a
successful extraction, so every first --kernel run failed after
downloading the 45MB package; the second run worked from cache. Also
remove the downloaded APK even when extraction fails.
- Add tests for hostname format and uniqueness
- Add tests for chroot environment setup
- Add tests for environment isolation and PATH configuration
- Verify all 34 tests pass
- Create unified Arch enum in utils.rs with methods for all naming conventions
- Replace 5 duplicate architecture mapping functions with single source of truth
- Add memory string validation for QEMU
- Add KVM capability verification via ioctl
- Fix TOCTOU race in resolv.conf writing using O_EXCL
- Extract magic numbers to named constants
- Use constants for stack size, buffer sizes, hostname entropy
Add an init script to the initramfs that traps shell exit and triggers
poweroff via /proc/sysrq-trigger. This ensures QEMU terminates cleanly
when the user exits the shell, rather than hanging indefinitely.
Changes:
- Add /init script to initramfs that runs as PID 1
- Use -no-reboot QEMU flag to exit on guest poweroff
- Simplify kernel command line using environment variables
- Init script handles hostname, device creation, and poweroff on exit
- Move detect_shell() to new src/utils.rs for reuse
- Use detected shell in QEMU VM mode (bash when available)
- Update chroot.rs and qemu_vm.rs to use shared function
Generate hostname like "ecr-vm-<hex>" at boot time via kernel command
line, leaving initramfs cacheable. Set via echo to /etc/hostname and
hostname command before spawning shell.
Add --kernel <PATH> option to boot extracted rootfs in a QEMU virtual
machine instead of namespace/chroot mode. The rootfs is converted to an
ext4 disk image using mke2fs and booted with the provided kernel.