qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Anthony Liguori <anthony@codemonkey.ws>
To: "Jorge Lucángeli Obes" <t4m5yn@gmail.com>
Cc: kvm-devel@lists.sourceforge.net, qemu-devel@nongnu.org
Subject: [Qemu-devel] Re: [kvm-devel] [PATCH][RFC] Allowing QEMU to directly execute a directory (and storing command line options in it)
Date: Fri, 31 Aug 2007 13:54:17 -0500	[thread overview]
Message-ID: <1188586457.8543.2.camel@squirrel> (raw)
In-Reply-To: <59abf66e0708311119p2b83fcffg31fac1c298cfc10a@mail.gmail.com>

It makes little sense to pass a directory when you can pass a config
file and assume that the directory the config file is in is the CWD.

For instance, if vm.cfg contained just the command line arguments, you
could have:

MyImage/vm.cfg:        -hda disk0.qcow -m 512
MyImage/disk0.qcow:    <disk image>

And then do:

qemu -c MyImage/vm.cfg

Regards,

Anthony Liguori


On Fri, 2007-08-31 at 15:19 -0300, Jorge Lucángeli Obes wrote:
> Hi all,
> 
> The last time this issue was discussed, the executable-directory idea
> gained more consensus than the snapshot-based idea. This patch
> implements my perception of the first idea. Non-Windows for now, as I
> can't test on a Windows system. Suggestions and constructive criticism
> more than welcome.
> 
> Cheers,
> Jorge
> 
> This patch allows QEMU to execute a directory with a special format.
> 
> This patch allows storing command line options in a configuration file inside
> a directory and then directly executing that directory. A simple check is
> included to prevent the configuration file to access image files outside
> the executed directory. Extra command line options can be passed on invocation,
> which will take precedence over the ones stored in the configuration file.
> 
> The configuration file specifies, on its first line, the image file to use.
> The rest of the file specifies command line options separated by spaces or
> newlines. Careful reconstruction of the command line makes sure the speficied
> image file gets executed even if other image files were included later in the
> configuration file.
> 
> Signed-off-by: Jorge Lucángeli Obes
> ---
> diff --git a/qemu/vl.c b/qemu/vl.c
> index fcc899b..88cefd2 100644
> --- a/qemu/vl.c
> +++ b/qemu/vl.c
> @@ -42,8 +42,8 @@
>  #include <netinet/in.h>
>  #include <dirent.h>
>  #include <netdb.h>
> -#ifdef _BSD
>  #include <sys/stat.h>
> +#ifdef _BSD
>  #ifndef __APPLE__
>  #include <libutil.h>
>  #endif
> @@ -6367,9 +6367,16 @@ int main_loop(void)
>  void help(void)
>  {
>      printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c)
> 2003-2007 Fabrice Bellard\n"
> -           "usage: %s [options] [disk_image]\n"
> +           "usage: %s [options] [disk_image|folder]\n"
>             "\n"
> +#ifdef _WIN32
>             "'disk_image' is a raw hard image image for IDE hard disk 0\n"
> +#else
> +           "'disk_image' is a raw hard image image for IDE hard disk 0 or\n"
> +           "'folder' is a folder with a file 'config' containing in
> the first line\n"
> +           "the name of an image file inside the folder and in the
> rest of the file\n"
> +           "options separated by ' ' or '\\n'\n"
> +#endif
>             "\n"
>             "Standard options:\n"
>             "-M machine      select emulated machine (-M ? for list)\n"
> @@ -6892,6 +6899,20 @@ void qemu_get_launch_info(int *argc, char
> ***argv, int *opt_daemonize, const cha
>      *opt_incoming = incoming;
>  }
> 
> +char *dir_file_cat(const char *folder, const char *file) {
> +    int foldlen = strlen(folder);
> +    int filelen = strlen(file);
> +    int reslen = foldlen + 1 + filelen + 1;
> +
> +    char *res = malloc(sizeof(char) * reslen);
> +
> +    pstrcpy(res, reslen, folder);
> +    strncat(res, "/", 1);
> +    strncat(res, file, filelen);
> +
> +    return res;
> +}
> +
>  int main(int argc, char **argv)
>  {
>  #ifdef CONFIG_GDBSTUB
> @@ -7003,7 +7024,120 @@ int main(int argc, char **argv)
> 
>      nb_nics = 0;
>      /* default mac address of the first network interface */
> +
> +#ifndef _WIN32
> +#define DIR_CMDLINE_SIZE 1<<13
> +    int hd_found = 0;
> +    char *dir, *opts;
> +    struct stat *s = NULL;
> +
> +    optind = 1;
> +    for(;;) {
> +        if (optind >= argc)
> +            break;
> +
> +        dir = argv[optind++];
> +
> +        if (dir[0] != '-') {
> +            hd_found = 1;
> +            break;
> +        }
> +    }
> 
> +    if (hd_found) {
> +        s = malloc(sizeof(*s));
> +
> +        if (stat(dir, s) < 0) {
> +            /* Error */
> +            fprintf(stderr, "unable to stat: '%s'\n",
> +                    dir);
> +            exit(1);
> +        }
> +
> +        if (S_ISDIR(s->st_mode)) {
> +            /* The user specified a directory, search for ./config */
> +            int configlen = strlen(dir);
> +            configlen += 8; /* "/config\0" */
> +            char *config = malloc(sizeof(char) * configlen);
> +
> +            pstrcpy(config, configlen, dir);
> +            strncat(config, "/config", 7);
> +
> +            int fd_config;
> +
> +            if ((fd_config = open(config, 0)) < 0) {
> +                /* Error */
> +                if (errno == ENOENT)
> +                    fprintf(stderr, "config file not found: '%s'\n",
> +                            config);
> +                else
> +                    fprintf(stderr, "unable to open config file: '%s'\n",
> +                            config);
> +                exit(1);
> +            }
> +
> +            opts = malloc(sizeof(char) * (DIR_CMDLINE_SIZE));
> +
> +            ssize_t readb = read(fd_config, opts, (DIR_CMDLINE_SIZE) - 1);
> +
> +            opts[readb] = '\0';
> +
> +            char *filename = strsep(&opts, "\n");
> +
> +            if (filename == NULL) {
> +                /* Error */
> +                fprintf(stderr, "malformed configuration file: '%s'\n",
> +                        config);
> +                exit(1);
> +            } else if (strchr(filename, '/') != NULL) {
> +                /* Error */
> +                fprintf(stderr, "'%s' may point outside folder '%s'\n"
> +                                "avoid using '/' in config file\n",
> +                        filename, dir);
> +                exit(1);
> +            }
> +
> +            char tmpopts[DIR_CMDLINE_SIZE];
> +            int done = 0;
> +            unsigned int nbtoks = 0;
> +            char *tok;
> +
> +            pstrcpy(tmpopts, DIR_CMDLINE_SIZE, opts);
> +
> +            do {
> +                tok = strtok(nbtoks == 0? tmpopts : NULL, " \n");
> +
> +                if (tok != NULL)
> +                    nbtoks++;
> +                else
> +                    done = 1;
> +            } while (!done);
> +
> +            if (nbtoks > 0) {
> +                char **argvprime = malloc((nbtoks + argc + 1) * sizeof(char*));
> +
> +                argvprime[0] = argv[0];
> +
> +                for (i = 0; i < nbtoks; i++)
> +                    argvprime[i + 1] = strtok(i == 0? opts : NULL, " \n");
> +
> +                for (i = 1; i < argc; i++)
> +                    argvprime[nbtoks + i] = argv[i];
> +
> +                argvprime[nbtoks + argc] = dir_file_cat(dir, filename);
> +
> +                argv = argvprime;
> +                argc = nbtoks + argc + 1;
> +
> +                for (i = 0; i < argc; i++)
> +                    printf("argv[%d] = %s\n", i, argv[i]);
> +            }
> +        }
> +    }
> +
> +    free(s);
> +#endif
> +
>      optind = 1;
>      for(;;) {
>          if (optind >= argc)
> @@ -7773,5 +7907,10 @@ int main(int argc, char **argv)
> 
>      main_loop();
>      quit_timers();
> +
> +    /* argv was overwritten when parsing config file */
> +    if (hd_found)
> +    	free(argv);
> +
>      return 0;
>  }
> -------------------------------------------------------------------------
> This SF.net email is sponsored by: Splunk Inc.
> Still grepping through log files to find problems?  Stop.
> Now Search log events and configuration files using AJAX and a browser.
> Download your FREE copy of Splunk now >>  http://get.splunk.com/
> _______________________________________________ kvm-devel mailing list kvm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kvm-devel

  reply	other threads:[~2007-08-31 18:54 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-08-31 18:19 [Qemu-devel] [PATCH][RFC] Allowing QEMU to directly execute a directory (and storing command line options in it) Jorge Lucángeli Obes
2007-08-31 18:54 ` Anthony Liguori [this message]
2007-08-31 19:05   ` [Qemu-devel] Re: [kvm-devel] " Jorge Lucángeli Obes
2007-08-31 19:13     ` Anthony Liguori
2007-09-01 11:02   ` Markus Hitter
2007-09-01 14:26     ` Luke -Jr
2007-09-01 14:49       ` Andreas Färber
2007-09-01 14:39     ` Andreas Färber
2007-09-01 18:45       ` Jorge Lucángeli Obes
2007-09-01 19:52         ` Andreas Färber
2007-09-01 20:26           ` Jorge Lucángeli Obes
2007-09-03  9:19             ` Philip Boulain
2007-09-03 10:01               ` Christian Brunschen
2007-09-03 11:10                 ` Philip Boulain
2007-09-03 11:40                 ` Andreas Färber
2007-09-03 13:54                   ` Andreas Färber
2007-09-03 14:54               ` Luke -Jr

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=1188586457.8543.2.camel@squirrel \
    --to=anthony@codemonkey.ws \
    --cc=kvm-devel@lists.sourceforge.net \
    --cc=qemu-devel@nongnu.org \
    --cc=t4m5yn@gmail.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).