From: "Daniel P. Berrange" <berrange@redhat.com>
To: Luiz Capitulino <lcapitulino@redhat.com>
Cc: jcody@redhat.com, eblake@redhat.com, qemu-devel@nongnu.org,
mdroth@linux.vnet.ibm.com
Subject: Re: [Qemu-devel] [PATCH 2/2] qemu-ga: Add the guest-suspend command
Date: Mon, 16 Jan 2012 21:06:27 +0000 [thread overview]
Message-ID: <20120116210627.GD12789@redhat.com> (raw)
In-Reply-To: <1326744592-27650-3-git-send-email-lcapitulino@redhat.com>
On Mon, Jan 16, 2012 at 06:09:52PM -0200, Luiz Capitulino wrote:
> +/* Try to find executable file 'file'. If it's found, its absolute path is
> + returned in 'abs_path' and the function returns true. If it's not found,
> + the function will return false and 'abs_path' will contain zeros */
> +static bool find_executable_file(const char *file, char *abs_path, size_t len)
> +{
> + char *path, *saveptr;
> + const char *token, *delim = ":";
> +
> + if (!getenv("PATH")) {
> + return false;
> + }
> +
> + path = g_strdup(getenv("PATH"));
> + if (!path) {
> + return false;
> + }
> +
> + for (token = strtok_r(path, delim, &saveptr); token;
> + token = strtok_r(NULL, delim, &saveptr)) {
> + snprintf(abs_path, len, "%s/%s", token, file);
> + if (access(abs_path, X_OK) == 0) {
> + g_free(path);
> + return true;
> + }
> + }
> +
> + g_free(path);
> + memset(abs_path, 0, len);
> +
> + return false;
> +}
I hope you don't hate me for now pointing out...
g_find_program_in_path()
http://developer.gnome.org/glib/stable/glib-Miscellaneous-Utility-Functions.html#g-find-program-in-path
> +
> int64_t qmp_guest_sync(int64_t id, Error **errp)
> {
> return id;
> @@ -574,6 +623,220 @@ int64_t qmp_guest_fsfreeze_thaw(Error **err)
> }
> #endif
>
> +#define LINUX_SYS_STATE_FILE "/sys/power/state"
> +#define SUS_MODE_SUPPORTED 0
> +#define SUS_MODE_NOT_SUPPORTED 1
> +
> +/**
> + * This function forks twice and the information about the mode support
> + * status is passed to the qemu-ga process via a pipe.
> + *
> + * This approach allows us to keep the way we reap terminated children
> + * in qemu-ga quite simple.
> + */
> +static bool bios_supports_mode(const char *mode, Error **err)
> +{
> + pid_t pid;
> + ssize_t ret;
> + bool has_pmutils;
> + int status, pipefds[2];
> + char pmutils_path[PATH_MAX];
> + const char *pmutils_bin = "pm-is-supported";
> +
> + if (pipe(pipefds) < 0) {
> + error_set(err, QERR_UNDEFINED_ERROR);
> + return false;
> + }
> +
> + has_pmutils = find_executable_file(pmutils_bin, pmutils_path,
> + sizeof(pmutils_path));
> +
> + pid = fork();
> + if (!pid) {
> + struct sigaction act;
> +
> + memset(&act, 0, sizeof(act));
> + act.sa_handler = SIG_DFL;
> + sigaction(SIGCHLD, &act, NULL);
> +
> + setsid();
> + close(pipefds[0]);
> + reopen_fd_to_null(0);
> + reopen_fd_to_null(1);
> + reopen_fd_to_null(2);
> +
> + pid = fork();
> + if (!pid) {
> + int fd;
> + char buf[32]; /* hopefully big enough */
> + const char *arg;
> +
> + if (strcmp(mode, "hibernate") == 0) {
> + arg = "--hibernate";
> + } else if (strcmp(mode, "sleep") == 0) {
> + arg = "--suspend";
> + } else if (strcmp(mode, "hybrid") == 0) {
> + arg = "--suspend-hybrid";
> + } else {
> + _exit(SUS_MODE_NOT_SUPPORTED);
> + }
> +
> + if (has_pmutils) {
> + execle(pmutils_path, pmutils_bin, arg, NULL, environ);
> + }
> +
> + /*
> + * If we get here either pm-utils is not installed or execle() has
> + * failed. Let's try the manual approach if mode is not hybrid (as
> + * it's only supported by pm-utils)
> + */
> +
> + if (strcmp(mode, "hybrid") == 0) {
> + _exit(SUS_MODE_NOT_SUPPORTED);
> + }
> +
> + fd = open(LINUX_SYS_STATE_FILE, O_RDONLY);
> + if (fd < 0) {
> + _exit(SUS_MODE_NOT_SUPPORTED);
> + }
> +
> + ret = read(fd, buf, sizeof(buf));
You want "sizeof(buf)-1" here, otherwise if read return 'ret'
set to exactly sizeof(buf)...
> + if (ret <= 0) {
> + _exit(SUS_MODE_NOT_SUPPORTED);
> + }
> +
> + buf[ret] = '\0';
...this becomes a stack overflow.
> + has_pmutils = find_executable_file(pmutils_bin, pmutils_path,
> + sizeof(pmutils_path));
> +
> + pid = fork();
> + if (pid == 0) {
> + /* child */
> + int fd;
> + const char *cmd;
> +
> + setsid();
> + reopen_fd_to_null(0);
> + reopen_fd_to_null(1);
> + reopen_fd_to_null(2);
> +
> + if (has_pmutils) {
> + execle(pmutils_path, pmutils_bin, NULL, environ);
You could just use execl() and drop the trailing 'environ' here,
since that is the default anyway.
> + }
> +
> + /*
> + * If we get here either pm-utils is not installed or execle() has
> + * failed. Let's try the manual approach if mode is not hybrid (as
> + * it's only supported by pm-utils)
> + */
> +
> + slog("could not execute %s\n", pmutils_bin);
> + if (strcmp(mode, "hybrid") == 0) {
> + _exit(EXIT_FAILURE);
> + }
> +
> + slog("trying to suspend using the manual method...\n");
> +
> + fd = open(LINUX_SYS_STATE_FILE, O_WRONLY);
> + if (fd < 0) {
> + slog("can't open file %s: %s\n", LINUX_SYS_STATE_FILE,
> + strerror(errno));
> + _exit(EXIT_FAILURE);
> + }
> +
> + cmd = strcmp(mode, "sleep") == 0 ? "mem" : "disk";
> + if (write(fd, cmd, strlen(cmd)) < 0) {
> + slog("failued to write to %s\n", LINUX_SYS_STATE_FILE);
> + _exit(EXIT_FAILURE);
> + }
> +
> + _exit(EXIT_SUCCESS);
> + } else if (pid < 0) {
> + error_set(err, QERR_UNDEFINED_ERROR);
> + return;
> + }
> +}
> +
> /* register init/cleanup routines for stateful command groups */
> void ga_command_state_init(GAState *s, GACommandState *cs)
> {
Regards,
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
next prev parent reply other threads:[~2012-01-16 21:06 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-01-16 20:09 [Qemu-devel] [PATCH v6 0/2]: qemu-ga: Add the guest-suspend command Luiz Capitulino
2012-01-16 20:09 ` [Qemu-devel] [PATCH 1/2] qemu-ga: set O_NONBLOCK for serial channels Luiz Capitulino
2012-01-16 20:09 ` [Qemu-devel] [PATCH 2/2] qemu-ga: Add the guest-suspend command Luiz Capitulino
2012-01-16 21:06 ` Daniel P. Berrange [this message]
2012-01-17 12:18 ` Luiz Capitulino
2012-01-17 12:27 ` Daniel P. Berrange
2012-01-16 22:17 ` Michael Roth
2012-01-17 12:22 ` Luiz Capitulino
-- strict thread matches above, loose matches on Subject: below --
2012-01-17 13:27 [Qemu-devel] [PATCH v7 0/2]: " Luiz Capitulino
2012-01-17 13:27 ` [Qemu-devel] [PATCH 2/2] " Luiz Capitulino
2012-01-13 19:15 [Qemu-devel] [PATCH v5 0/2]: " Luiz Capitulino
2012-01-13 19:15 ` [Qemu-devel] [PATCH 2/2] " Luiz Capitulino
2012-01-13 21:48 ` Eric Blake
2012-01-16 10:51 ` Jamie Lokier
2012-01-16 15:59 ` Eric Blake
2012-01-17 10:57 ` Jamie Lokier
2012-01-18 19:13 ` Eric Blake
2012-01-16 15:46 ` Luiz Capitulino
2012-01-16 17:08 ` Luiz Capitulino
2012-01-16 17:13 ` Daniel P. Berrange
2012-01-16 17:18 ` Luiz Capitulino
2012-01-16 17:23 ` Luiz Capitulino
2012-01-16 20:02 ` Michael Roth
2012-01-16 20:35 ` Daniel P. Berrange
2012-01-16 22:06 ` Michael Roth
2012-01-17 11:05 ` Jamie Lokier
2012-01-16 20:08 ` Eric Blake
2012-01-16 20:19 ` Luiz Capitulino
2012-01-16 21:10 ` Eric Blake
2012-01-04 19:45 [Qemu-devel] [PATCH v4 0/2]: " Luiz Capitulino
2012-01-04 19:45 ` [Qemu-devel] [PATCH 2/2] " Luiz Capitulino
2012-01-04 20:00 ` Michael Roth
2012-01-04 20:03 ` Eric Blake
2012-01-05 12:29 ` Luiz Capitulino
2012-01-05 12:46 ` Daniel P. Berrange
2012-01-05 12:58 ` Luiz Capitulino
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20120116210627.GD12789@redhat.com \
--to=berrange@redhat.com \
--cc=eblake@redhat.com \
--cc=jcody@redhat.com \
--cc=lcapitulino@redhat.com \
--cc=mdroth@linux.vnet.ibm.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.