diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 5070f27d75..c7059857e4 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); diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 8227480810..acc2c11589 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -1164,15 +1164,15 @@ static GuestFilesystemInfo *build_guest_fsinfo(char *guid, Error **errp) fs->mountpoint = g_strdup("System Reserved"); } else { fs->mountpoint = g_strndup(mnt_point, len); - if (GetDiskFreeSpaceEx(fs->mountpoint, - (PULARGE_INTEGER) & i64FreeBytesToCaller, - (PULARGE_INTEGER) & i64TotalBytes, - (PULARGE_INTEGER) & i64FreeBytes)) { - fs->used_bytes = i64TotalBytes - i64FreeBytes; - fs->total_bytes = i64TotalBytes; - fs->has_total_bytes = true; - fs->has_used_bytes = true; - } + } + if (GetDiskFreeSpaceEx(fs->name, + (PULARGE_INTEGER) & i64FreeBytesToCaller, + (PULARGE_INTEGER) & i64TotalBytes, + (PULARGE_INTEGER) & i64FreeBytes)) { + fs->used_bytes = i64TotalBytes - i64FreeBytes; + fs->total_bytes = i64TotalBytes; + fs->has_total_bytes = true; + fs->has_used_bytes = true; } wcstombs(fs_name, wfs_name, sizeof(wfs_name)); fs->type = g_strdup(fs_name); diff --git a/scripts/qemu-guest-agent/fsfreeze-hook b/scripts/qemu-guest-agent/fsfreeze-hook index c1feb6f5ce..5b915af017 100755 --- a/scripts/qemu-guest-agent/fsfreeze-hook +++ b/scripts/qemu-guest-agent/fsfreeze-hook @@ -1,11 +1,12 @@ #!/bin/sh -# This script is executed when a guest agent receives fsfreeze-freeze and -# fsfreeze-thaw command, if it is specified in --fsfreeze-hook (-F) -# option of qemu-ga or placed in default path (/etc/qemu/fsfreeze-hook). -# When the agent receives fsfreeze-freeze request, this script is issued with -# "freeze" argument before the filesystem is frozen. And for fsfreeze-thaw -# request, it is issued with "thaw" argument after filesystem is thawed. +# This script is executed when the guest agent receives fsfreeze-freeze and +# fsfreeze-thaw commands, provided that the --fsfreeze-hook (-F) option of +# qemu-ga is specified and the script is placed in /etc/qemu/fsfreeze-hook or in +# the path specified together with -F. When the agent receives fsfreeze-freeze +# requests, this script is called with "freeze" as its argument before the +# filesystem is frozen. And for fsfreeze-thaw requests, it is called with "thaw" +# as its argument after the filesystem is thawed. LOGFILE=/var/log/qga-fsfreeze-hook.log FSFREEZE_D=$(dirname -- "$0")/fsfreeze-hook.d