qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH][RFC] Allowing QEMU to directly execute a directory


From: Jorge Lucángeli Obes
Subject: [Qemu-devel] [PATCH][RFC] Allowing QEMU to directly execute a directory (and storing command line options in it)
Date: Fri, 31 Aug 2007 15:19:00 -0300

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;
 }

Attachment: exec_dir.patch
Description: Text Data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]