Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package virtme for openSUSE:Factory checked in at 2025-10-06 18:08:08 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/virtme (Old) and /work/SRC/openSUSE:Factory/.virtme.new.11973 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "virtme" Mon Oct 6 18:08:08 2025 rev:27 rq:1309142 version:1.38 Changes: -------- --- /work/SRC/openSUSE:Factory/virtme/virtme.changes 2025-08-11 13:54:10.997291865 +0200 +++ /work/SRC/openSUSE:Factory/.virtme.new.11973/virtme.changes 2025-10-06 18:08:36.708489659 +0200 @@ -1,0 +2,10 @@ +Mon Sep 29 05:51:22 UTC 2025 - Michael Vetter <[email protected]> + +- Update to 1.38: + * Fix the infamous Stale file handle (ESTALE) errors with virtiofsd + * Fix for systemctl daemon-reload when systemd support is enabled + * Fix for a kernel symlink issue affecting openSUSE/SLE + * README/docs improvements + * Various coding style cleanups + +------------------------------------------------------------------- Old: ---- virtme-ng-1.37.tar.xz New: ---- virtme-ng-1.38.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ virtme.spec ++++++ --- /var/tmp/diff_new_pack.Z6MEeA/_old 2025-10-06 18:08:37.432520060 +0200 +++ /var/tmp/diff_new_pack.Z6MEeA/_new 2025-10-06 18:08:37.440520395 +0200 @@ -22,7 +22,7 @@ %global pythons python311 %endif Name: virtme -Version: 1.37 +Version: 1.38 Release: 0 Summary: Tools for virtualize the running distro or a rootfs License: GPL-2.0-only ++++++ _service ++++++ --- /var/tmp/diff_new_pack.Z6MEeA/_old 2025-10-06 18:08:37.484522243 +0200 +++ /var/tmp/diff_new_pack.Z6MEeA/_new 2025-10-06 18:08:37.488522411 +0200 @@ -3,7 +3,7 @@ <param name="url">https://github.com/arighi/virtme-ng.git</param> <param name="scm">git</param> <param name="submodules">enable</param> - <param name="revision">v1.37</param> + <param name="revision">v1.38</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="versionrewrite-replacement">\1</param> ++++++ virtme-ng-1.37.tar.xz -> virtme-ng-1.38.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/virtme-ng-1.37/.github/workflows/rust.yml new/virtme-ng-1.38/.github/workflows/rust.yml --- old/virtme-ng-1.37/.github/workflows/rust.yml 2025-08-08 09:40:53.000000000 +0200 +++ new/virtme-ng-1.38/.github/workflows/rust.yml 2025-09-26 17:23:55.000000000 +0200 @@ -20,8 +20,11 @@ steps: - uses: actions/checkout@v3 - - name: Coding style - run: cargo fmt -- --check + - uses: actions/setup-python@v3 + - uses: pre-commit/[email protected] + with: + # To be adapted if the structure changes, e.g. new subdirs. + extra_args: --files virtme_ng_init/*/*.rs - name: Build run: cargo build --verbose - name: Run tests diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/virtme-ng-1.37/.pre-commit-config.yaml new/virtme-ng-1.38/.pre-commit-config.yaml --- old/virtme-ng-1.37/.pre-commit-config.yaml 2025-08-08 09:40:53.000000000 +0200 +++ new/virtme-ng-1.38/.pre-commit-config.yaml 2025-09-26 17:23:55.000000000 +0200 @@ -1,7 +1,10 @@ --- +ci: + skip: [cargo-clippy-fix, cargo-clippy, cargo-check, cargo-fmt] + repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: end-of-file-fixer exclude: 'DCO-1\.1\.txt' @@ -10,17 +13,59 @@ - id: mixed-line-ending - id: check-executables-have-shebangs - id: check-shebang-scripts-are-executable + - id: check-yaml + - id: check-json + - id: check-toml - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.7 + rev: v0.13.1 hooks: - - id: ruff + - id: ruff-check args: [--fix] - id: ruff-format - repo: https://github.com/shellcheck-py/shellcheck-py - rev: v0.10.0.1 + rev: v0.11.0.1 hooks: - id: shellcheck - repo: https://github.com/scop/pre-commit-shfmt rev: v3.12.0-2 hooks: - id: shfmt + - repo: local + hooks: + - id: cargo-clippy-fix + description: Run cargo clippy fix + entry: env + args: [--chdir=virtme_ng_init, --, cargo, clippy, --fix, --allow-dirty, --allow-staged, --all-targets, --all-features, --] + language: system + name: cargo clippy --fix + pass_filenames: false + require_serial: true + types: [rust] + - id: cargo-clippy + description: Run cargo clippy + entry: env + # Fail if any warnings are found in the code + args: [--chdir=virtme_ng_init, --, cargo, clippy, --all-targets, --all-features, --, --deny, warnings] + language: system + name: cargo clippy --deny warnings + pass_filenames: false + require_serial: true + types: [rust] + - id: cargo-check + description: Run cargo check + entry: env + args: [--chdir=virtme_ng_init, --, cargo, check, --all-targets, --all-features, --] + language: system + name: cargo check + pass_filenames: false + require_serial: true + types: [rust] + - id: cargo-fmt + description: Run cargo fmt + entry: env + args: [--chdir=virtme_ng_init, --, cargo, fmt, --all, --] + language: system + name: cargo fmt + pass_filenames: false + require_serial: true + types: [rust] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/virtme-ng-1.37/README.md new/virtme-ng-1.38/README.md --- old/virtme-ng-1.37/README.md 2025-08-08 09:40:53.000000000 +0200 +++ new/virtme-ng-1.38/README.md 2025-09-26 17:23:55.000000000 +0200 @@ -6,7 +6,7 @@ virtme-ng is a tool that allows to easily and quickly recompile and test a Linux kernel, starting from the source code. -It allows to recompile the kernel in few minutes (rather than hours), then the +It allows recompiling the kernel in few minutes (rather than hours), then the kernel is automatically started in a virtualized environment that is an exact copy-on-write copy of your live system, which means that any changes made to the virtualized environment do not affect the host system. @@ -29,7 +29,7 @@ Quick start =========== -``` +```shell $ uname -r 5.19.0-23-generic $ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git @@ -57,70 +57,54 @@ Installation ============ -* Debian / Ubuntu +* virtme-ng is packaged in most major distributions: -You can install the latest stable version of virtme-ng via: -``` - $ sudo apt install virtme-ng -``` + [](https://repology.org/project/virtme-ng/versions) -* Ubuntu ppa + Note: it might not be the latest stable version containing new features and + bug-fixes. Do not hesitate to help with the packaging! -If you're using Ubuntu, you can install the latest experimental version of -virtme-ng from ppa:arighi/virtme-ng: -``` - $ sudo add-apt-repository ppa:arighi/virtme-ng - $ sudo apt install --yes virtme-ng -``` +* The latest stable version is also published on + [pypi](https://pypi.org/project/virtme-ng/): -* Install from source + ```shell + $ pip install virtme-ng + ``` -To install virtme-ng from source you can clone this git repository and build a -standalone virtme-ng running the following commands: -``` - $ git clone --recurse-submodules https://github.com/arighi/virtme-ng.git - $ BUILD_VIRTME_NG_INIT=1 pip3 install . -``` + You will need to install the dependences manually, see the + [Requirements](#requirements) section. -If you are in Debian/Ubuntu you may need to install the following packages to -build virtme-ng from source properly: -``` - $ sudo apt install python3-pip flake8 pylint cargo rustc qemu-system-x86 -``` +* Install from source -If you'd prefer to use `uv`: -``` - $ BUILD_VIRTME_NG_INIT=1 uv tool install . -``` + To install virtme-ng from source, you can clone this git repository and build + a standalone virtme-ng running the following commands: + ```shell + $ git clone https://github.com/arighi/virtme-ng.git + $ cd virtme-ng + $ BUILD_VIRTME_NG_INIT=1 pip3 install . + ``` + + There are some extra dependences on top of the ones mentioned in the + [Requirements](#requirements) section. If you are on Debian/Ubuntu, you may + need to install the following packages to build virtme-ng from source properly: + ```shell + $ sudo apt install python3-pip flake8 pylint cargo rustc qemu-system-x86 + ``` + + If you'd prefer to use `uv`: + ```shell + $ BUILD_VIRTME_NG_INIT=1 uv tool install . + ``` * Run from source -You can also run virtme-ng directly from source, make sure you have all the -requirements installed (optionally you can build `virtme-ng-init` for a faster -boot, by running `make`), then from the source directory simply run any -virtme-ng command, such as: -``` - $ ./vng --help -``` - -Configuration -============= - -* You may customize the default configuration by providing one of the - following, by order of preference: `$HOME/.config/virtme-ng/virtme-ng.conf`, - `$HOME/.virtme-ng.conf` or `/etc/virtme-ng.conf`. As a fallback for any - missing values, the default ones will be used. - -* The format of the file is JSON. Default values: -``` -{ - "default_opts": {}, - "systemd": { - "masks": ["getty@"] - } -} -``` - + You can also run virtme-ng directly from source, make sure you have all the + requirements installed (optionally you can build `virtme-ng-init` for a faster + boot, by running `make`), then from the source directory simply run any + virtme-ng command, such as: + ```shell + $ ./vng --help + ``` Requirements ============ @@ -155,114 +139,143 @@ * Optionally, you may need `sshd` installed for the `--ssh` and `--ssh-client` options. + * Optionally, if the shell completion is not available (e.g. when installed + from pip or from source), you can install `shtab` and run: + ```shell + # Bash + $ mkdir -p ~/.local/share/bash-completion/completions/ + $ shtab --shell=bash -u virtme_ng.run.make_parser > ~/.local/share/bash-completion/completions/vng + + # ZSH + $ shtab --shell=zsh -u virtme_ng.run.make_parser | sudo tee /usr/local/share/zsh/site-functions/_vng >/dev/null + ``` + +Configuration +============= + +* You may customize the default configuration by providing one of the + following, by order of preference: `$HOME/.config/virtme-ng/virtme-ng.conf`, + `$HOME/.virtme-ng.conf` or `/etc/virtme-ng.conf`. As a fallback for any + missing values, the default ones will be used. + +* The format of the file is JSON. Default values: + ```json + { + "default_opts": {}, + "systemd": { + "masks": ["getty@"] + } + } + ``` + Examples ======== - - Build a kernel from a clean local kernel source directory (if a .config is - not available virtme-ng will automatically create a minimum .config with + - Build a kernel from a clean local kernel source directory (if a `.config` is + not available virtme-ng will automatically create a minimum `.config` with all the required feature to boot the instance): -``` + ```shell $ vng -b -``` + ``` - Build tag v6.1-rc3 from a local kernel git repository: -``` + ```shell $ vng -b -c v6.1-rc3 -``` + ``` - - Generate a minimal kernel .config in the current kernel build directory: -``` + - Generate a minimal kernel `.config` in the current kernel build directory: + ```shell $ vng --kconfig -``` + ``` - Run a kernel previously compiled from a local git repository in the current working directory: -``` + ```shell $ vng -``` + ``` - Run an interactive virtme-ng session using the same kernel as the host: -``` + ```shell $ vng -r -``` + ``` - Test installed kernel 6.2.0-21-generic kernel (NOTE: /boot/vmlinuz-6.2.0-21-generic needs to be accessible): -``` + ```shell $ vng -r 6.2.0-21-generic -``` + ``` - Run a pre-compiled vanilla v6.6 kernel fetched from the Ubuntu mainline builds repository (useful to test a specific kernel version directly and save a lot of build time): -``` + ```shell $ vng -r v6.6 -``` + ``` - Download and test kernel 6.2.0-1003-lowlatency from deb packages: -``` + ```shell $ mkdir test $ cd test $ apt download linux-image-6.2.0-1003-lowlatency linux-modules-6.2.0-1003-lowlatency $ for d in *.deb; do dpkg -x $d .; done $ vng -r ./boot/vmlinuz-6.2.0-1003-lowlatency -``` + ``` - Build the tip of the latest kernel on a remote build host called "builder", running make inside a specific build chroot (managed remotely by schroot): -``` + ```shell $ vng --build --build-host builder \ --build-host-exec-prefix "schroot -c chroot:kinetic-amd64 -- " -``` + ``` - Run the previously compiled kernel from the current working directory and enable networking: -``` + ```shell $ vng --net user -``` + ``` - Run the previously compiled kernel adding an additional virtio-scsi device: -``` + ```shell $ qemu-img create -f qcow2 /tmp/disk.img 8G $ vng --disk /tmp/disk.img -``` + ``` - Recompile the kernel passing some env variables to enable Rust support (using specific versions of the Rust toolchain binaries): -``` + ```shell $ vng --build RUSTC=rustc-1.62 BINDGEN=bindgen-0.56 RUSTFMT=rustfmt-1.62 -``` + ``` - Build the arm64 kernel (using a separate chroot in /opt/chroot/arm64 as the main filesystem): -``` + ```shell $ vng --build --arch arm64 --root /opt/chroot/arm64/ -``` + ``` - Build the kernel using a separate build directory, and run it, in verbose: -``` + ```shell $ export KBUILD_OUTPUT=.virtme/build $ vng --build --verbose $ vng --verbose -``` + ``` - Same example, but using `O=`: -``` + ```shell $ vng --build --verbose -- O=.virtme/build $ vng --verbose -- O=.virtme/build -``` + ``` - Accelerate the kernel rebuilds using CCache (if installed): -``` + ```shell $ PATH="/usr/lib/ccache:${PATH}" \ KBUILD_BUILD_TIMESTAMP=0 \ vng --build # or export the two variables before, see 'man ccache' for more details -``` + ``` - Execute `uname -r` inside a kernel recompiled in the current directory and send the output to cowsay on the host: -``` + ```shell $ vng -- uname -r | cowsay __________________ < 6.1.0-rc6-virtme > @@ -272,13 +285,13 @@ (__)\ )\/\ ||----w | || || -``` + ``` - Run a bunch of parallel virtme-ng instances in a pipeline, with different kernels installed in the system, passing each other their stdout/stdin and return all the generated output back to the host (also measure the total elapsed time): -``` + ```shell $ time true | \ > vng -r 5.19.0-38-generic -e "cat && uname -r" | \ > vng -r 6.2.0-19-generic -e "cat && uname -r" | \ @@ -300,10 +313,10 @@ real 0m2.737s user 0m8.425s sys 0m8.806s -``` + ``` - Run the vanilla v6.7-rc5 kernel with an Ubuntu 22.04 rootfs: -``` + ```shell $ vng -r v6.7-rc5 --user root --root ./rootfs/22.04 --root-release jammy -- cat /etc/lsb-release /proc/version ... DISTRIB_ID=Ubuntu @@ -311,10 +324,10 @@ DISTRIB_CODENAME=jammy DISTRIB_DESCRIPTION="Ubuntu 22.04.3 LTS" Linux version 6.7.0-060700rc5-generic (kernel@kathleen) (x86_64-linux-gnu-gcc-13 (Ubuntu 13.2.0-7ubuntu1) 13.2.0, GNU ld (GNU Binutils for Ubuntu) 2.41) #202312102332 SMP PREEMPT_DYNAMIC Sun Dec 10 23:41:31 UTC 2023 -``` + ``` - Run with systemd as init: -``` + ```shell $ sudo vng -r --systemd --exec "systemctl status | head" ● virtme-ng State: starting @@ -326,10 +339,10 @@ Tainted: unmerged-bin CGroup: / ├─init.scope -``` + ``` - Run with systemd as init in an external rootfs: -``` + ```shell $ vng -r --systemd --user root --root ./rootfs/sid --exec "systemctl status | head" ● virtme-ng State: degraded @@ -341,11 +354,11 @@ Tainted: unmerged-bin CGroup: / ├─init.scope -``` + ``` - Run the current kernel creating a 1GB NUMA node with CPUs 0,1,3 assigned and a 3GB NUMA node with CPUs 2,4,5,6,7 assigned: -``` + ```shell $ vng -r -m 4G --numa 1G,cpus=0-1,cpus=3 --numa 3G,cpus=2,cpus=4-7 -- numactl -H available: 2 nodes (0-1) node 0 cpus: 0 1 3 @@ -358,12 +371,12 @@ node 0 1 0: 10 20 1: 20 10 -``` + ``` - Run the current kernel creating 4 NUMA nodes of 1GB each and assign different distance costs between the NUMA nodes to simulate non-uniform memory access: -``` + ```shell $ vng -r --cpu 8 -m 4G \ > --numa 1G,cpus=0-1 --numa 1G,cpus=2-3 \ > --numa 1G,cpus=4-5 --numa 1G,cpus=6-7 \ @@ -389,34 +402,34 @@ 1: 51 10 21 61 2: 31 21 10 11 3: 41 61 11 10 -``` + ``` - Run `glxgears` inside a kernel recompiled in the current directory: -``` + ```shell $ vng -g -- glxgears (virtme-ng is started in graphical mode) -``` + ``` - Execute an `awesome` window manager session with kernel 6.2.0-1003-lowlatency (installed in the system): -``` + ```shell $ vng -r 6.2.0-1003-lowlatency -g -- awesome (virtme-ng is started in graphical mode) -``` + ``` - Run the `steam` snap (tested in Ubuntu) inside a virtme-ng instance using the 6.2.0-1003-lowlatency kernel: -``` + ```shell $ vng -r 6.2.0-1003-lowlatency --snaps --net user -g -- /snap/bin/steam (virtme-ng is started in graphical mode) -``` + ``` - Generate a memory dump of a running instance and read 'jiffies' from the - memory dump using the drgn debugger: -``` + memory dump using the `drgn` debugger: + ```shell # Start the vng instance in debug mode $ vng --debug @@ -432,10 +445,10 @@ >>> from drgn.helpers.common import * >>> from drgn.helpers.linux import * >>> (volatile unsigned long)4294675464 -``` + ``` - - Attach a gdb session to a running instance started with `--debug`: -``` + - Attach a GDB session to a running instance started with `--debug`: + ```shell # Start the vng instance in debug mode $ vng --debug @@ -451,29 +464,28 @@ # NOTE: a vmlinux must be present in the current working directory in order # to resolve symbols, otherwise vng # will automatically search for a # vmlinux available in the system. -``` + ``` - Connect to a simple remote shell (`socat` is required, VSOCK will be used): -``` + ```shell # Start the vng instance with server support: $ vng --console # In a separate terminal run the following command to connect to a remote shell: $ vng --console-client -``` + ``` - - Enable ssh in the vng guest: -``` + - Enable SSH in the vng guest: + ```shell # Start the vng instance with ssh server support: $ vng --ssh # Connect to the vng guest from the host via ssh: $ vng --ssh-client -``` - + ``` - Generate some results inside the vng guest and copy them back to the - host using scp: -``` + host using SCP: + ```shell # Start the vng instance with SSH server support: arighi@host~> vng --ssh ... @@ -489,10 +501,10 @@ # With systemd >= 256, it is possible to use the 'vsock/<CID>' hostname directly: arighi@host~> ssh vsock/2222 arighi@virtme-ng~> -``` + ``` - Run virtme-ng inside a docker container: -``` + ```shell $ docker run -it --privileged ubuntu:23.10 /bin/bash # apt update # echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections @@ -501,12 +513,12 @@ # git clone --recursive https://github.com/arighi/virtme-ng.git # ./virtme-ng/vng -r v6.6 -- uname -r 6.6.0-060600-generic -``` + ``` See also: `.github/workflows/run.yml` as a practical example on how to use virtme-ng inside docker. - - Run virtme-ng with gpu passthrough: -``` + - Run virtme-ng with GPU passthrough: + ```shell # Confirm host kernel has VFIO and IOMMU support # Check if NVIDIA module is installed on the host $ modinfo nvidia @@ -523,7 +535,7 @@ $ sudo modprobe vfio-pci # Pass PCI address to virtme-ng $ sudo vng --nvgpu "01:00.0" -r linux -``` + ``` Implementation details ====================== @@ -534,12 +546,12 @@ A minimal custom `.config` is automatically generated if not already present when `--build` is specified. -It is possible to specify a set of custom configs (.config chunk) in -`~/.config/virtme-ng/kernel.config`, or using --config chunk-file's -or --configitem CONFIG_FOO=bar's. These user-specific settings will +It is possible to specify a set of custom configs (`.config` chunk) in +`~/.config/virtme-ng/kernel.config`, or using `--config` chunk-file's +or `--configitem CONFIG_FOO=bar`'s. These user-specific settings will successively override the default settings. The final overrides are the mandatory config items that are required to boot and test the -kernel inside qemu, using `virtme-run`. +kernel inside QEmu, using `virtme-run`. Then the kernel is compiled either locally or on an external build host (if the `--build-host` option is used); once the build is done only the required files @@ -572,10 +584,10 @@ them in your configuration file (refer to the [Configuration](#configuration) section) under `default_opts` and then simply run `vng --build`. -Example (always use an external build server called 'kathleen' and run make +Example (always use an external build server called `kathleen` and run make inside a build chroot called `chroot:lunar-amd64`). To do so, add the `default_opts` section in your configuration file as following: -``` +```json { "default_opts": { "build_host": "kathleen", @@ -591,51 +603,57 @@ Troubleshooting =============== + - If you experience poor performance, check the [Requirements](#requirements) + section, maybe some optional tools or services are not available, e.g. KVM + support and virtiofsd. Please note that some Linux distributions are + currently not shipping `virtme-ng-init` tool, which runs faster than the Bash + init script, used as fallback. + - If you get permission denied when starting qemu, make sure that your username is assigned to the group `kvm` or `libvirt`: -``` - $ groups | grep "kvm\|libvirt" -``` + ```shell + $ groups | grep "kvm\|libvirt" + ``` - When using `--network bridge` to create a bridged network in the guest you may get the following error: -``` - ... - failed to create tun device: Operation not permitted -``` + ``` + ... + failed to create tun device: Operation not permitted + ``` This is because `qemu-bridge-helper` requires `CAP_NET_ADMIN` permissions. To fix this you need to add `allow all` to `/etc/qemu/bridge.conf` and set the `CAP_NET_ADMIN` capability to `qemu-bridge-helper`, as following: -``` - $ sudo filecap /usr/lib/qemu/qemu-bridge-helper net_admin -``` + ```shell + $ sudo filecap /usr/lib/qemu/qemu-bridge-helper net_admin + ``` - If the guest fails to start because the host doesn't have enough memory available you can specify a different amount of memory using `--memory MB`, (this option is passed directly to qemu via `-m`, default is 1G). - - If you're testing a kernel for an architecture different than the host, keep + - If you're testing a kernel for an architecture different from the host, keep in mind that you need to use also `--root DIR` to use a specific chroot with the binaries compatible with the architecture that you're testing. If the chroot doesn't exist in your system virtme-ng will automatically create it using the latest daily build Ubuntu cloud image: -``` - $ vng --build --arch riscv64 --root ./tmproot -``` + ```shell + $ vng --build --arch riscv64 --root ./tmproot + ``` - If the build on a remote build host is failing unexpectedly you may want to try cleaning up the remote git repository, running: -``` - $ vng --clean --build-host HOSTNAME -``` + ```shell + $ vng --clean --build-host HOSTNAME + ``` - Snap support is still experimental and something may not work as expected - (keep in mind that, by default, virtme-ng will try to run snapd in a bare + (keep in mind that, by default, virtme-ng will try to run `snapd` in a bare minimum system environment without systemd), if some snaps are not running - try to disable apparmor, adding `--append="apparmor=0"` to the virtme-ng + try to disable `apparmor`, adding `--append="apparmor=0"` to the virtme-ng command line. - Systemd support (`--systemd`) is still experimental. If something does not @@ -649,28 +667,50 @@ especially with stdin/stdout/stderr redirections, make sure that you have `udev` installed in your docker image and run the following command before using `vng`: -``` - $ udevadm trigger --subsystem-match --action=change -``` + ```shell + $ udevadm trigger --subsystem-match --action=change + ``` - - To mount the legacy cgroup filesystem (v1) layout, add + - To mount the legacy CGroup filesystem (v1) layout, add `SYSTEMD_CGROUP_ENABLE_LEGACY_FORCE=1` to the kernel boot options: -``` -$ vng -r --append "SYSTEMD_CGROUP_ENABLE_LEGACY_FORCE=1" -- 'df -T /sys/fs/cgroup/*' -Filesystem Type 1K-blocks Used Available Use% Mounted on -blkio cgroup 0 0 0 - /sys/fs/cgroup/blkio -cpu cgroup 0 0 0 - /sys/fs/cgroup/cpu -cpuacct cgroup 0 0 0 - /sys/fs/cgroup/cpuacct -devices cgroup 0 0 0 - /sys/fs/cgroup/devices -memory cgroup 0 0 0 - /sys/fs/cgroup/memory -pids cgroup 0 0 0 - /sys/fs/cgroup/pids -``` + ```shell + $ vng -r --append "SYSTEMD_CGROUP_ENABLE_LEGACY_FORCE=1" -- 'df -T /sys/fs/cgroup/*' + Filesystem Type 1K-blocks Used Available Use% Mounted on + blkio cgroup 0 0 0 - /sys/fs/cgroup/blkio + cpu cgroup 0 0 0 - /sys/fs/cgroup/cpu + cpuacct cgroup 0 0 0 - /sys/fs/cgroup/cpuacct + devices cgroup 0 0 0 - /sys/fs/cgroup/devices + memory cgroup 0 0 0 - /sys/fs/cgroup/memory + pids cgroup 0 0 0 - /sys/fs/cgroup/pids + ``` + + - If you experience stale file handle errors (ESTALE) in the guest, this + may be due to an inode revalidation issue with VirtioFS. + + Applying [#340](https://github.com/arighi/virtme-ng/pull/340) prevents + these errors, but host-side file changes may not be immediately visible + in the guest. If you observe out-of-sync filesystem issues, you can + simply force a resync by invalidating the page cache in the guest: + ```shell + # echo 3 > /proc/sys/vm/drop_caches + ``` Contributing ============ Please see DCO-1.1.txt. +virtme-ng uses [pre-commit](https://pre-commit.com/) to perform some checks, +e.g. code formatting and linting. Therefore it is recommended to set up +pre-commit for development: + +```shell +$ cd "$VIRTME_NG" +$ # Activate pre-commit hooks for virtme-ng +$ pre-commit install +pre-commit installed at .git/hooks/pre-commit +``` + Additional resources ==================== @@ -689,5 +729,3 @@ [korg-web]: https://git.kernel.org/cgit/utils/kernel/virtme/virtme.git "virtme on kernel.org" [korg-git]: git://git.kernel.org/pub/scm/utils/kernel/virtme/virtme.git "git address" -[virtme]: https://github.com/amluto/virtme "virtme" -[virtme-ng-ppa]: https://launchpad.net/~arighi/+archive/ubuntu/virtme-ng "virtme-ng ppa" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/virtme-ng-1.37/setup.py new/virtme-ng-1.38/setup.py --- old/virtme-ng-1.37/setup.py 2025-08-08 09:40:53.000000000 +0200 +++ new/virtme-ng-1.38/setup.py 2025-09-26 17:23:55.000000000 +0200 @@ -3,7 +3,6 @@ import os import platform import subprocess -import sys import sysconfig from argcomplete import shell_integration @@ -32,13 +31,6 @@ # Global variables to store custom build options (as env variables) build_virtme_ng_init = int(os.environ.get("BUILD_VIRTME_NG_INIT", 0)) -# Make sure virtme-ng-init submodule has been cloned -if build_virtme_ng_init and not os.path.exists("virtme_ng_init/Cargo.toml"): - sys.stderr.write( - "WARNING: virtme-ng-init submodule not available, trying to clone it\n" - ) - subprocess.check_call("git submodule update --init --recursive", shell=True) - # Always include standard site-packages to PYTHONPATH os.environ["PYTHONPATH"] = sysconfig.get_paths()["purelib"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/virtme-ng-1.37/virtme/commands/run.py new/virtme-ng-1.38/virtme/commands/run.py --- old/virtme-ng-1.37/virtme/commands/run.py 2025-08-08 09:40:53.000000000 +0200 +++ new/virtme-ng-1.38/virtme/commands/run.py 2025-09-26 17:23:55.000000000 +0200 @@ -20,6 +20,7 @@ import tempfile import termios from base64 import b64encode +from pathlib import Path from shutil import which from time import sleep from typing import Any, Dict, List, NoReturn, Optional, Tuple @@ -451,7 +452,10 @@ return os.path.abspath(path) -def get_kernel_version(path, img_name: Optional[str] = None): +def get_kernel_version(orig_path, img_name: Optional[str] = None): + # Resolve symlinks first + path = Path(orig_path).resolve() + if not os.path.exists(path): arg_fail(f"kernel file {path} does not exist, try --build to build the kernel") if not os.access(path, os.R_OK): @@ -746,7 +750,7 @@ stderr = "" os.system( f"{virtiofsd_path} --syslog --no-announce-submounts " - + f"--socket-path {self.sock} --shared-dir {path} --sandbox none {stderr} &" + + f"--socket-path {self.sock} --shared-dir {path} --sandbox none {stderr} -o cache=always &" ) max_attempts = 5 check_duration = 0.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/virtme-ng-1.37/virtme/guest/virtme-init new/virtme-ng-1.38/virtme/guest/virtme-init --- old/virtme-ng-1.37/virtme/guest/virtme-init 2025-08-08 09:40:53.000000000 +0200 +++ new/virtme-ng-1.38/virtme/guest/virtme-init 2025-09-26 17:23:55.000000000 +0200 @@ -136,6 +136,14 @@ mkdir /run/tmp/lvm mount --bind /run/tmp/lvm /etc/lvm +# Create a default lvm configuration is lvmconfig is available when systemd is enabled +if [[ $$ -ne 1 ]]; then + if command -v lvmconfig &> /dev/null; then + log "Creating a default lvm.conf file" + lvmconfig --type default > /etc/lvm/lvm.conf + fi +fi + for tag in "${!virtme_initmount@}"; do if [[ ! -d ${!tag} ]]; then mkdir -p "${!tag}" @@ -349,7 +357,7 @@ log 'starting script' if [[ -n ${virtme_user} ]]; then chmod +x /run/tmp/.virtme-script - setsid su - "${virtme_user}" -c /run/tmp/.virtme-script < /dev/virtio-ports/virtme.stdin > /dev/virtio-ports/virtme.stdout 2> /dev/virtio-ports/virtme.stderr + setsid su -c /run/tmp/.virtme-script -- "${virtme_user}" < /dev/virtio-ports/virtme.stdin > /dev/virtio-ports/virtme.stdout 2> /dev/virtio-ports/virtme.stderr else setsid bash /run/tmp/.virtme-script < /dev/virtio-ports/virtme.stdin > /dev/virtio-ports/virtme.stdout 2> /dev/virtio-ports/virtme.stderr fi @@ -472,14 +480,14 @@ # Try to fix permissions on the virtual consoles, we are starting X # directly here so we may need extra permissions on the tty devices. chown -- "${virtme_user}" /dev/char/* - setsid bash -c "su - ${virtme_user} -c 'xinit ${xinit_rc}'" 0<> "/dev/$consdev" 1>&0 2>&0 + setsid bash -c "su -c 'xinit ${xinit_rc}' -- ${virtme_user}" 0<> "/dev/$consdev" 1>&0 2>&0 else setsid bash -c "xinit ${xinit_rc}" 0<> "/dev/$consdev" 1>&0 2>&0 fi # Drop to console if the graphical app failed. fi if [[ -n ${virtme_user} ]]; then - setsid bash -c "su - ${virtme_user}" 0<> "/dev/$consdev" 1>&0 2>&0 + setsid bash -c "su -- ${virtme_user}" 0<> "/dev/$consdev" 1>&0 2>&0 else setsid bash 0<> "/dev/$consdev" 1>&0 2>&0 fi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/virtme-ng-1.37/virtme_ng/version.py new/virtme-ng-1.38/virtme_ng/version.py --- old/virtme-ng-1.37/virtme_ng/version.py 2025-08-08 09:40:53.000000000 +0200 +++ new/virtme-ng-1.38/virtme_ng/version.py 2025-09-26 17:23:55.000000000 +0200 @@ -7,7 +7,7 @@ from importlib.metadata import PackageNotFoundError, version from subprocess import DEVNULL, CalledProcessError, check_output -PKG_VERSION = "1.37" +PKG_VERSION = "1.38" def get_package_version(): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/virtme-ng-1.37/virtme_ng_init/Cargo.toml new/virtme-ng-1.38/virtme_ng_init/Cargo.toml --- old/virtme-ng-1.37/virtme_ng_init/Cargo.toml 2025-08-08 09:40:53.000000000 +0200 +++ new/virtme-ng-1.38/virtme_ng_init/Cargo.toml 2025-09-26 17:23:55.000000000 +0200 @@ -2,6 +2,18 @@ name = "virtme-ng-init" version = "0.1.0" edition = "2021" +rust-version = "1.75.0" + +[lints.rust] +missing_docs = { level = "deny", priority = 1 } +missing_debug_implementations = "warn" +non_ascii_idents = "warn" +nonstandard-style = "warn" +trivial_numeric_casts = "warn" +unstable_features = "warn" +unused = "warn" +unused_import_braces = "warn" +unused_qualifications = "warn" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/virtme-ng-1.37/virtme_ng_init/src/main.rs new/virtme-ng-1.38/virtme_ng_init/src/main.rs --- old/virtme-ng-1.37/virtme_ng_init/src/main.rs 2025-08-08 09:40:53.000000000 +0200 +++ new/virtme-ng-1.38/virtme_ng_init/src/main.rs 2025-09-26 17:23:55.000000000 +0200 @@ -217,7 +217,7 @@ let release = utsname.release().to_string_lossy(); if show_machine { let machine = utsname.machine().to_string_lossy(); - format!("{} {}", release, machine) + format!("{release} {machine}") } else { release.into_owned() } @@ -229,11 +229,10 @@ Ok(file) => { let reader = BufReader::new(file); - // .flatten() ignores lines with reading errors - for line in reader.lines().flatten() { + for line in reader.lines().map_while(Result::ok) { if line.chars().nth(27) == Some('C') { let console = line.split(' ').next()?; - return Some(format!("/dev/{}", console)); + return Some(format!("/dev/{console}")); } } None @@ -247,7 +246,7 @@ fn get_active_console() -> Option<String> { if let Ok(console) = env::var("virtme_console") { - Some(format!("/dev/{}", console)) + Some(format!("/dev/{console}")) } else { get_legacy_active_console() } @@ -308,7 +307,7 @@ for line in reader.lines() { if let Some((username, _)) = line?.split_once(':') { - writeln!(writer, "{}:!:::::::", username)?; + writeln!(writer, "{username}:!:::::::")?; } } utils::do_mount( @@ -327,10 +326,10 @@ let mut content = "Defaults secure_path=\"/usr/sbin:/usr/bin:/sbin:/bin\"\n".to_string(); content += "root ALL = (ALL) NOPASSWD: ALL\n"; if let Ok(user) = env::var("virtme_user") { - content += &format!("{} ALL = (ALL) NOPASSWD: ALL\n", user); + content += &format!("{user} ALL = (ALL) NOPASSWD: ALL\n"); } if !Path::new("/etc/sudoers").exists() { - utils::create_file("/etc/sudoers", 0o0440, "").unwrap_or_else(|_| {}); + utils::create_file("/etc/sudoers", 0o0440, "").unwrap_or(()); } utils::create_file(fname, 0o0440, &content).ok(); utils::do_mount(fname, "/etc/sudoers", "", libc::MS_BIND as usize, ""); @@ -342,17 +341,21 @@ fn generate_lvm() -> io::Result<()> { utils::do_mkdir("/run/tmp/lvm"); utils::do_mount("/run/tmp/lvm", "/etc/lvm/", "", libc::MS_BIND as usize, ""); + + // Create a default lvm.conf file if --systemd was specified + if id() != 1 { + let args: &[&str] = &["--type", "default", "--file", "/etc/lvm/lvm.conf"]; + utils::run_cmd("lvmconfig", args); + } + Ok(()) } fn generate_hosts() -> io::Result<()> { if let Ok(hostname) = env::var("virtme_hostname") { std::fs::copy("/etc/hosts", "/run/tmp/hosts")?; - let mut h = OpenOptions::new() - .write(true) - .append(true) - .open("/run/tmp/hosts")?; - writeln!(h, "\n127.0.0.1 {}\n::1 {}", hostname, hostname)?; + let mut h = OpenOptions::new().append(true).open("/run/tmp/hosts")?; + writeln!(h, "\n127.0.0.1 {hostname}\n::1 {hostname}")?; utils::do_mount( "/run/tmp/hosts", "/etc/hosts", @@ -389,8 +392,8 @@ ]; // Install /proc/self/fd symlinks into /dev if not already present. - for (src, dst) in fd_links.iter() { - if !std::path::Path::new(dst).exists() { + for (src, dst) in &fd_links { + if !Path::new(dst).exists() { utils::do_symlink(src, dst); } } @@ -423,7 +426,7 @@ mount_info.fs_type, mount_info.flags, mount_info.fsdata, - ) + ); } } @@ -435,7 +438,7 @@ utils::do_mount("cgroup", "/sys/fs/cgroup", "tmpfs", 0, ""); let subsystems = vec!["cpu", "cpuacct", "blkio", "memory", "devices", "pids"]; for subsys in &subsystems { - let target = format!("/sys/fs/cgroup/{}", subsys); + let target = format!("/sys/fs/cgroup/{subsys}"); utils::do_mkdir(&target); // Don't treat failure as critical here, since the kernel may not // support all the legacy cgroups. @@ -450,23 +453,18 @@ utils::do_mkdir("/run/tmp/"); for (key, path) in env::vars() { if key.starts_with("virtme_rw_overlay") { - let dir = &format!("/run/tmp/{}", key); - let upperdir = &format!("{}/upper", dir); - let workdir = &format!("{}/work", dir); - let mnt_opts = &format!( - "xino=off,lowerdir={},upperdir={},workdir={}", - path, upperdir, workdir - ); + let dir = &format!("/run/tmp/{key}"); + let upperdir = &format!("{dir}/upper"); + let workdir = &format!("{dir}/work"); + let mnt_opts = + &format!("xino=off,lowerdir={path},upperdir={upperdir},workdir={workdir}"); utils::do_mkdir(dir); utils::do_mkdir(upperdir); utils::do_mkdir(workdir); let result = utils::do_mount_check(&key, &path, "overlay", 0, mnt_opts); if result.is_err() { // Old kernels don't support xino=on|off, re-try without this option. - let mnt_opts = &format!( - "lowerdir={},upperdir={},workdir={}", - path, upperdir, workdir - ); + let mnt_opts = &format!("lowerdir={path},upperdir={upperdir},workdir={workdir}"); utils::do_mount(&key, &path, "overlay", 0, mnt_opts); } } @@ -490,7 +488,7 @@ fn mount_kernel_modules() { let kver = get_kernel_version(false); - let mod_dir = format!("/lib/modules/{}", kver); + let mod_dir = format!("/lib/modules/{kver}"); // Make sure to always have /lib/modules, otherwise we won't be able to configure kmod support // properly (this can happen in some container environments, such as docker). @@ -521,7 +519,7 @@ mount_info.fs_type, mount_info.flags, mount_info.fsdata, - ) + ); } } @@ -542,7 +540,7 @@ if fname.is_empty() { continue; } - let src_file = format!("/run/tmp/{}", fname); + let src_file = format!("/run/tmp/{fname}"); utils::create_file(&src_file, 0o0640, "").ok(); utils::do_mount(&src_file, path, "", libc::MS_BIND as usize, ""); } @@ -657,7 +655,7 @@ ) -> Option<thread::JoinHandle<()>> { let network_dev_str = network_dev.unwrap(); log!("setting up network device {}", network_dev_str); - return Some(thread::spawn(move || { + Some(thread::spawn(move || { let args = [ "udhcpc", "-i", @@ -669,13 +667,13 @@ &format!("{}/virtme-udhcpc-script", guest_tools_dir.unwrap()), ]; utils::run_cmd("busybox", &args); - })); + })) } fn setup_network_lo() -> Option<thread::JoinHandle<()>> { - return Some(thread::spawn(move || { + Some(thread::spawn(move || { utils::run_cmd("ip", &["link", "set", "dev", "lo", "up"]); - })); + })) } fn setup_network() -> Vec<Option<thread::JoinHandle<()>>> { @@ -693,12 +691,12 @@ } if let Some(guest_tools_dir) = get_guest_tools_dir() { - get_network_devices().into_iter().for_each(|network_dev| { + for network_dev in get_network_devices() { vec.push(get_network_handle( network_dev, - Some(guest_tools_dir.to_owned()), + Some(guest_tools_dir.clone()), )); - }); + } } } vec @@ -714,11 +712,11 @@ } fn run_user_script(uid: u32) { - if !std::path::Path::new("/dev/virtio-ports/virtme.stdin").exists() - || !std::path::Path::new("/dev/virtio-ports/virtme.stdout").exists() - || !std::path::Path::new("/dev/virtio-ports/virtme.stderr").exists() - || !std::path::Path::new("/dev/virtio-ports/virtme.dev_stdout").exists() - || !std::path::Path::new("/dev/virtio-ports/virtme.dev_stderr").exists() + if !Path::new("/dev/virtio-ports/virtme.stdin").exists() + || !Path::new("/dev/virtio-ports/virtme.stdout").exists() + || !Path::new("/dev/virtio-ports/virtme.stderr").exists() + || !Path::new("/dev/virtio-ports/virtme.dev_stdout").exists() + || !Path::new("/dev/virtio-ports/virtme.dev_stderr").exists() { log!("virtme-init: cannot find script I/O ports; make sure virtio-serial is available",); } else { @@ -729,11 +727,11 @@ ("/dev/virtio-ports/virtme.dev_stdout", "/dev/stdout"), ("/dev/virtio-ports/virtme.dev_stderr", "/dev/stderr"), ]; - for (src, dst) in io_files.iter() { - if !std::path::Path::new(src).exists() { + for (src, dst) in &io_files { + if !Path::new(src).exists() { continue; } - if std::path::Path::new(dst).exists() { + if Path::new(dst).exists() { utils::do_unlink(dst); } utils::do_chown(src, uid, None).ok(); @@ -749,23 +747,23 @@ // Determine if we need to switch to a different user, or if we can run the script as root. let user = env::var("virtme_user").unwrap_or_else(|_| String::new()); - let (cmd, args) = if !user.is_empty() { - ("su", vec![user.as_str(), "-c", USER_SCRIPT]) - } else { + let (cmd, args) = if user.is_empty() { ("/bin/sh", vec![USER_SCRIPT]) + } else { + ("su", vec!["-c", USER_SCRIPT, "--", user.as_str()]) }; clear_virtme_envs(); unsafe { let ret = Command::new(cmd) .args(&args) .pre_exec(move || { - nix::libc::setsid(); + libc::setsid(); libc::close(libc::STDIN_FILENO); libc::close(libc::STDOUT_FILENO); libc::close(libc::STDERR_FILENO); // Make stdin a controlling tty. let stdin_fd = libc::dup2(tty_in, libc::STDIN_FILENO); - nix::libc::ioctl(stdin_fd, libc::TIOCSCTTY, 1); + libc::ioctl(stdin_fd, libc::TIOCSCTTY, 1); libc::dup2(tty_out, libc::STDOUT_FILENO); libc::dup2(tty_err, libc::STDERR_FILENO); Ok(()) @@ -840,12 +838,12 @@ let fd = file.into_raw_fd(); - let stdout = std::io::stdout(); + let stdout = io::stdout(); let handle = stdout.lock(); let stdout_fd = handle.as_raw_fd(); redirect_fd(fd, stdout_fd); - let stderr = std::io::stderr(); + let stderr = io::stderr(); let handle = stderr.lock(); let stderr_fd = handle.as_raw_fd(); redirect_fd(fd, stderr_fd); @@ -853,15 +851,15 @@ fn configure_terminal(consdev: &str, uid: u32) { // Set proper user ownership on the default console device - utils::do_chown(&consdev, uid, None).ok(); + utils::do_chown(consdev, uid, None).ok(); // Redirect stdout/stderr to the new console device. - redirect_console(&consdev); + redirect_console(consdev); if let Ok(params) = env::var("virtme_stty_con") { let output = Command::new("stty") .args(params.split_whitespace()) - .stdin(std::fs::File::open(consdev).unwrap()) + .stdin(File::open(consdev).unwrap()) .stdout(Stdio::inherit()) .stderr(Stdio::inherit()) // Replace the current init process with a shell session. @@ -873,12 +871,12 @@ fn detach_from_terminal(tty_fd: libc::c_int) { // Detach the process from the controlling terminal unsafe { - nix::libc::setsid(); + libc::setsid(); libc::close(libc::STDIN_FILENO); libc::close(libc::STDOUT_FILENO); libc::close(libc::STDERR_FILENO); let stdin_fd = libc::dup2(tty_fd, libc::STDIN_FILENO); - nix::libc::ioctl(stdin_fd, libc::TIOCSCTTY, 1); + libc::ioctl(stdin_fd, libc::TIOCSCTTY, 1); libc::dup2(tty_fd, libc::STDOUT_FILENO); libc::dup2(tty_fd, libc::STDERR_FILENO); } @@ -906,14 +904,14 @@ if let Ok(cmdline) = std::fs::read_to_string("/proc/cmdline") { if cmdline.contains("virtme.sound") { if let Some(guest_tools_dir) = get_guest_tools_dir() { - pre_exec_cmd = format!("{}/virtme-sound-script", guest_tools_dir); + pre_exec_cmd = format!("{guest_tools_dir}/virtme-sound-script"); } } } if let Err(err) = utils::create_file( xinitrc, 0o0644, - &format!("{}\n/bin/bash {}", pre_exec_cmd, USER_SCRIPT), + &format!("{pre_exec_cmd}\n/bin/bash {USER_SCRIPT}"), ) { log!("failed to generate {}: {}", xinitrc, err); return; @@ -925,13 +923,13 @@ if let Ok(user) = env::var("virtme_user") { // Try to fix permissions on the virtual consoles, we are starting X // directly here so we may need extra permissions on the tty devices. - utils::run_cmd("bash", &["-c", &format!("chown {} /dev/char/*", user)]); + utils::run_cmd("bash", &["-c", &format!("chown {user} /dev/char/*")]); // Clean up any previous X11 state. - utils::run_cmd("bash", &["-c", &"rm -f /tmp/.X11*/* /tmp/.X11-lock"]); + utils::run_cmd("bash", &["-c", "rm -f /tmp/.X11*/* /tmp/.X11-lock"]); // Start xinit directly. - storage = format!("su {} -c 'xinit /run/tmp/.xinitrc'", user); + storage = format!("su -c 'xinit /run/tmp/.xinitrc' -- {user}"); args.push(&storage); } else { args.push("xinit /run/tmp/.xinitrc"); @@ -942,7 +940,7 @@ fn init_xdg_runtime_dir(uid: u32) { // $XDG_RUNTIME_DIR defines the base directory relative to which user-specific non-essential // runtime files and other file objects (such as sockets, named pipes, ...) should be stored. - let dir = format!("/run/user/{}", uid); + let dir = format!("/run/user/{uid}"); utils::do_mkdir(&dir); utils::do_chown(&dir, uid, None).ok(); env::set_var("XDG_RUNTIME_DIR", dir); @@ -953,7 +951,7 @@ let storage; if let Ok(user) = env::var("virtme_user") { args.push("-c"); - storage = format!("su {}", user); + storage = format!("su -- {user}"); args.push(&storage); } print_logo(); @@ -980,14 +978,13 @@ .and_then(|user| utils::get_user_id(&user)) .unwrap_or(0); - let consdev = match get_active_console() { - Some(console) => console, - None => { - log!("failed to determine console"); - let err = Command::new("bash").arg("-l").exec(); - log!("failed to exec bash: {}", err); - return; - } + let consdev = if let Some(console) = get_active_console() { + console + } else { + log!("failed to determine console"); + let err = Command::new("bash").arg("-l").exec(); + log!("failed to exec bash: {}", err); + return; }; configure_terminal(consdev.as_str(), uid); init_xdg_runtime_dir(uid); @@ -1002,7 +999,7 @@ if let Ok(cmdline) = std::fs::read_to_string("/proc/cmdline") { if cmdline.contains("virtme.ssh") { if let Some(guest_tools_dir) = get_guest_tools_dir() { - utils::run_cmd(format!("{}/virtme-sshd-script", guest_tools_dir), &[]); + utils::run_cmd(format!("{guest_tools_dir}/virtme-sshd-script"), &[]); } } } @@ -1021,7 +1018,7 @@ return; } if let Some(guest_tools_dir) = get_guest_tools_dir() { - utils::run_cmd(format!("{}/virtme-snapd-script", guest_tools_dir), &[]); + utils::run_cmd(format!("{guest_tools_dir}/virtme-snapd-script"), &[]); } Command::new(snapd_bin) .stdin(Stdio::null()) @@ -1058,7 +1055,7 @@ thread::spawn(move || { log!("setting up vsock proxy executing {}", exec); let key = "virtme_vsockmount"; - if let Ok(path) = env::var(&key) { + if let Ok(path) = env::var(key) { utils::do_mkdir(&path); utils::do_mount( &key.replace('_', "."), @@ -1070,7 +1067,7 @@ } let from = "VSOCK-LISTEN:1024,reuseaddr,fork"; - let to = format!("EXEC:\"{}\",pty,stderr,setsid,sigint,sane,echo=0", exec); + let to = format!("EXEC:\"{exec}\",pty,stderr,setsid,sigint,sane,echo=0"); let args = vec![from, &to]; utils::run_cmd("socat", &args); }); @@ -1090,13 +1087,13 @@ } fn print_logo() { - let logo = r#" + let logo = r" _ _ __ _(_)_ __| |_ _ __ ___ ___ _ __ __ _ \ \ / / | __| __| _ _ \ / _ \_____| _ \ / _ | \ V /| | | | |_| | | | | | __/_____| | | | (_| | \_/ |_|_| \__|_| |_| |_|\___| |_| |_|\__ | - |___/"#; + |___/"; println!("{}", logo.trim_start_matches('\n')); println!(" kernel version: {}", get_kernel_version(true)); println!(" (CTRL+d to exit)\n"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/virtme-ng-1.37/virtme_ng_init/src/utils.rs new/virtme-ng-1.38/virtme_ng_init/src/utils.rs --- old/virtme-ng-1.37/virtme_ng_init/src/utils.rs 2025-08-08 09:40:53.000000000 +0200 +++ new/virtme-ng-1.38/virtme_ng_init/src/utils.rs 2025-09-26 17:23:55.000000000 +0200 @@ -26,7 +26,7 @@ static PREFIX: &str = "<6>virtme-ng-init: "; static LOG_LEVEL: &str = "<6>"; - let mut msg = format!("{}{}", PREFIX, msg); + let mut msg = format!("{PREFIX}{msg}"); // Remove all trailing \n while msg.ends_with('\n') { @@ -57,11 +57,10 @@ Some(get_user_by_name(username)?.uid()) } -pub fn do_chown(path: &str, uid: u32, gid: Option<u32>) -> std::io::Result<()> { - let gid_option = gid.map(|gid| Gid::from_raw(gid)); +pub fn do_chown(path: &str, uid: u32, gid: Option<u32>) -> io::Result<()> { + let gid_option = gid.map(Gid::from_raw); - chown(path, Some(Uid::from_raw(uid)), gid_option) - .map_err(|err| io::Error::new(std::io::ErrorKind::Other, err))?; + chown(path, Some(Uid::from_raw(uid)), gid_option).map_err(io::Error::other)?; Ok(()) } @@ -73,7 +72,7 @@ pub fn do_unlink(path: &str) { match std::fs::remove_file(path) { - Ok(_) => (), + Ok(()) => (), Err(err) => { log!("failed to unlink file {}: {}", path, err); } @@ -81,7 +80,7 @@ } fn do_touch(path: &str, mode: u32) { - fn _do_touch(path: &str, mode: u32) -> std::io::Result<()> { + fn _do_touch(path: &str, mode: u32) -> io::Result<()> { let file = File::create(path)?; let permissions = std::fs::Permissions::from_mode(mode); file.set_permissions(permissions)?; @@ -105,7 +104,7 @@ pub fn do_symlink(src: &str, dst: &str) { match fs::symlink(src, dst) { - Ok(_) => (), + Ok(()) => (), Err(err) => { log!("failed to create symlink {} -> {}: {}", src, dst, err); } @@ -160,11 +159,12 @@ ); } } - Err(_) => { + Err(e) => { log!( - "WARNING: failed to run: {:?} {}", + "WARNING: failed to run: {:?} {} (error: {})", cmd.as_ref(), - args.join(" ") + args.join(" "), + e ); } }
