Reviewed-by: Kostiantyn Kostiuk <[email protected]>
Best Regards,
Kostiantyn Kostiuk.


On Sat, Sep 27, 2025 at 12:49 AM Rodrigo Dias Correa <[email protected]> wrote:

> On POSIX systems, the QEMU Guest Agent uses /sbin/shutdown to implement
> the command guest-shutdown. Systems based on BusyBox, such as Alpine
> Linux, don't have /sbin/shutdown. They have instead three separate
> commands: poweroff, reboot, and halt.
>
> Change the QEMU Guest Agent to, depending on the mode argument, use
> /sbin/{poweroff,halt,reboot} when they exist, falling back to
> /sbin/shutdown when they don't.
>
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2589
>
> Signed-off-by: Rodrigo Dias Correa <[email protected]>
> ---
>  qga/commands-posix.c | 29 +++++++++++++++++++++++++++++
>  1 file changed, 29 insertions(+)
>
> diff --git a/qga/commands-posix.c b/qga/commands-posix.c
> index 5070f27..c705985 100644
> --- a/qga/commands-posix.c
> +++ b/qga/commands-posix.c
> @@ -213,9 +213,20 @@ out:
>      return retcode;
>  }
>
> +static bool file_exists(const char *path)
> +{
> +    struct stat st;
> +    return stat(path, &st) == 0 && (S_ISREG(st.st_mode) ||
> S_ISLNK(st.st_mode));
> +}
> +
> +#define POWEROFF_CMD_PATH "/sbin/poweroff"
> +#define HALT_CMD_PATH "/sbin/halt"
> +#define REBOOT_CMD_PATH "/sbin/reboot"
> +
>  void qmp_guest_shutdown(const char *mode, Error **errp)
>  {
>      const char *shutdown_flag;
> +    const char *shutdown_cmd = NULL;
>      Error *local_err = NULL;
>
>  #ifdef CONFIG_SOLARIS
> @@ -234,10 +245,19 @@ void qmp_guest_shutdown(const char *mode, Error
> **errp)
>
>      slog("guest-shutdown called, mode: %s", mode);
>      if (!mode || strcmp(mode, "powerdown") == 0) {
> +        if (file_exists(POWEROFF_CMD_PATH)) {
> +            shutdown_cmd = POWEROFF_CMD_PATH;
> +        }
>          shutdown_flag = powerdown_flag;
>      } else if (strcmp(mode, "halt") == 0) {
> +        if (file_exists(HALT_CMD_PATH)) {
> +            shutdown_cmd = HALT_CMD_PATH;
> +        }
>          shutdown_flag = halt_flag;
>      } else if (strcmp(mode, "reboot") == 0) {
> +        if (file_exists(REBOOT_CMD_PATH)) {
> +            shutdown_cmd = REBOOT_CMD_PATH;
> +        }
>          shutdown_flag = reboot_flag;
>      } else {
>          error_setg(errp,
> @@ -255,6 +275,15 @@ void qmp_guest_shutdown(const char *mode, Error
> **errp)
>  #endif
>                            "hypervisor initiated shutdown", (char *) NULL};
>
> +    /*
> +     * If the specific command exists (poweroff, halt or reboot), use it
> instead
> +     * of /sbin/shutdown.
> +     */
> +    if (shutdown_cmd != NULL) {
> +        argv[0] = shutdown_cmd;
> +        argv[1] = NULL;
> +    }
> +
>      ga_run_command(argv, NULL, "shutdown", &local_err);
>      if (local_err) {
>          error_propagate(errp, local_err);
> --
> 2.47.3
>
>

Reply via email to