|
|
ffd6ed |
From dfa319bc27420a611311834108e6807b300fc2b3 Mon Sep 17 00:00:00 2001
|
|
|
ffd6ed |
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
|
ffd6ed |
Date: Tue, 9 Jun 2015 17:53:05 +0100
|
|
|
ffd6ed |
Subject: [PATCH] p2v: Correct parsing of /proc/cmdline, including quoting.
|
|
|
ffd6ed |
|
|
|
ffd6ed |
Fix the parsing of /proc/cmdline, including allowing double quoting of
|
|
|
ffd6ed |
parameters.
|
|
|
ffd6ed |
|
|
|
ffd6ed |
This allows you to pass parameters to p2v on the command line which
|
|
|
ffd6ed |
include spaces.
|
|
|
ffd6ed |
|
|
|
ffd6ed |
(cherry picked from commit 716244c33718c866edce9e7ee8f21ee612f53337)
|
|
|
ffd6ed |
---
|
|
|
ffd6ed |
p2v/Makefile.am | 1 +
|
|
|
ffd6ed |
p2v/kernel-cmdline.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
ffd6ed |
p2v/kernel.c | 143 ++++++++++++++++----------------------
|
|
|
ffd6ed |
p2v/main.c | 55 ++++-----------
|
|
|
ffd6ed |
p2v/p2v.h | 10 ++-
|
|
|
ffd6ed |
po/POTFILES | 1 +
|
|
|
ffd6ed |
6 files changed, 277 insertions(+), 126 deletions(-)
|
|
|
ffd6ed |
create mode 100644 p2v/kernel-cmdline.c
|
|
|
ffd6ed |
|
|
|
ffd6ed |
diff --git a/p2v/Makefile.am b/p2v/Makefile.am
|
|
|
ffd6ed |
index c9d6b6f..cafe597 100644
|
|
|
ffd6ed |
--- a/p2v/Makefile.am
|
|
|
ffd6ed |
+++ b/p2v/Makefile.am
|
|
|
ffd6ed |
@@ -49,6 +49,7 @@ virt_p2v_SOURCES = \
|
|
|
ffd6ed |
copying.c \
|
|
|
ffd6ed |
gui.c \
|
|
|
ffd6ed |
kernel.c \
|
|
|
ffd6ed |
+ kernel-cmdline.c \
|
|
|
ffd6ed |
main.c \
|
|
|
ffd6ed |
miniexpect.c \
|
|
|
ffd6ed |
miniexpect.h \
|
|
|
ffd6ed |
diff --git a/p2v/kernel-cmdline.c b/p2v/kernel-cmdline.c
|
|
|
ffd6ed |
new file mode 100644
|
|
|
ffd6ed |
index 0000000..142108a
|
|
|
ffd6ed |
--- /dev/null
|
|
|
ffd6ed |
+++ b/p2v/kernel-cmdline.c
|
|
|
ffd6ed |
@@ -0,0 +1,193 @@
|
|
|
ffd6ed |
+/* virt-p2v
|
|
|
ffd6ed |
+ * Copyright (C) 2015 Red Hat Inc.
|
|
|
ffd6ed |
+ *
|
|
|
ffd6ed |
+ * This program is free software; you can redistribute it and/or modify
|
|
|
ffd6ed |
+ * it under the terms of the GNU General Public License as published by
|
|
|
ffd6ed |
+ * the Free Software Foundation; either version 2 of the License, or
|
|
|
ffd6ed |
+ * (at your option) any later version.
|
|
|
ffd6ed |
+ *
|
|
|
ffd6ed |
+ * This program is distributed in the hope that it will be useful,
|
|
|
ffd6ed |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
ffd6ed |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
ffd6ed |
+ * GNU General Public License for more details.
|
|
|
ffd6ed |
+ *
|
|
|
ffd6ed |
+ * You should have received a copy of the GNU General Public License
|
|
|
ffd6ed |
+ * along with this program; if not, write to the Free Software
|
|
|
ffd6ed |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
ffd6ed |
+ */
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+/* Read /proc/cmdline.
|
|
|
ffd6ed |
+ *
|
|
|
ffd6ed |
+ * We only support double quoting, consistent with the Linux
|
|
|
ffd6ed |
+ * documentation.
|
|
|
ffd6ed |
+ * https://www.kernel.org/doc/Documentation/kernel-parameters.txt
|
|
|
ffd6ed |
+ *
|
|
|
ffd6ed |
+ * systemd supports single and double quoting and single character
|
|
|
ffd6ed |
+ * escaping, but we don't support all that.
|
|
|
ffd6ed |
+ *
|
|
|
ffd6ed |
+ * Returns a list of key, value pairs, terminated by NULL.
|
|
|
ffd6ed |
+ */
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+#include <config.h>
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+#include <stdio.h>
|
|
|
ffd6ed |
+#include <stdlib.h>
|
|
|
ffd6ed |
+#include <string.h>
|
|
|
ffd6ed |
+#include <unistd.h>
|
|
|
ffd6ed |
+#include <errno.h>
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+#include "p2v.h"
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+static void
|
|
|
ffd6ed |
+add_null (char ***argv, size_t *lenp)
|
|
|
ffd6ed |
+{
|
|
|
ffd6ed |
+ (*lenp)++;
|
|
|
ffd6ed |
+ *argv = realloc (*argv, *lenp * sizeof (char *));
|
|
|
ffd6ed |
+ if (*argv == NULL) {
|
|
|
ffd6ed |
+ perror ("realloc");
|
|
|
ffd6ed |
+ exit (EXIT_FAILURE);
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+ (*argv)[(*lenp)-1] = NULL;
|
|
|
ffd6ed |
+}
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+static void
|
|
|
ffd6ed |
+add_string (char ***argv, size_t *lenp, const char *str, size_t len)
|
|
|
ffd6ed |
+{
|
|
|
ffd6ed |
+ add_null (argv, lenp);
|
|
|
ffd6ed |
+ (*argv)[(*lenp)-1] = strndup (str, len);
|
|
|
ffd6ed |
+ if ((*argv)[(*lenp)-1] == NULL) {
|
|
|
ffd6ed |
+ perror ("strndup");
|
|
|
ffd6ed |
+ exit (EXIT_FAILURE);
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+}
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+char **
|
|
|
ffd6ed |
+parse_cmdline_string (const char *cmdline)
|
|
|
ffd6ed |
+{
|
|
|
ffd6ed |
+ char **ret = NULL;
|
|
|
ffd6ed |
+ size_t len = 0;
|
|
|
ffd6ed |
+ const char *p, *key = NULL, *value = NULL;
|
|
|
ffd6ed |
+ enum {
|
|
|
ffd6ed |
+ KEY_START = 0,
|
|
|
ffd6ed |
+ KEY,
|
|
|
ffd6ed |
+ VALUE_START,
|
|
|
ffd6ed |
+ VALUE,
|
|
|
ffd6ed |
+ VALUE_QUOTED
|
|
|
ffd6ed |
+ } state = 0;
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ for (p = cmdline; *p; p++) {
|
|
|
ffd6ed |
+ switch (state) {
|
|
|
ffd6ed |
+ case KEY_START: /* looking for the start of a key */
|
|
|
ffd6ed |
+ if (*p == ' ') continue;
|
|
|
ffd6ed |
+ key = p;
|
|
|
ffd6ed |
+ state = KEY;
|
|
|
ffd6ed |
+ break;
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ case KEY: /* reading key */
|
|
|
ffd6ed |
+ if (*p == ' ') {
|
|
|
ffd6ed |
+ add_string (&ret, &len, key, p-key);
|
|
|
ffd6ed |
+ add_string (&ret, &len, "", 0);
|
|
|
ffd6ed |
+ state = KEY_START;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+ else if (*p == '=') {
|
|
|
ffd6ed |
+ add_string (&ret, &len, key, p-key);
|
|
|
ffd6ed |
+ state = VALUE_START;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+ break;
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ case VALUE_START: /* looking for the start of a value */
|
|
|
ffd6ed |
+ if (*p == ' ') {
|
|
|
ffd6ed |
+ add_string (&ret, &len, "", 0);
|
|
|
ffd6ed |
+ state = KEY_START;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+ else if (*p == '"') {
|
|
|
ffd6ed |
+ value = p+1;
|
|
|
ffd6ed |
+ state = VALUE_QUOTED;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+ else {
|
|
|
ffd6ed |
+ value = p;
|
|
|
ffd6ed |
+ state = VALUE;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+ break;
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ case VALUE: /* reading unquoted value */
|
|
|
ffd6ed |
+ if (*p == ' ') {
|
|
|
ffd6ed |
+ add_string (&ret, &len, value, p-value);
|
|
|
ffd6ed |
+ state = KEY_START;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+ break;
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ case VALUE_QUOTED: /* reading quoted value */
|
|
|
ffd6ed |
+ if (*p == '"') {
|
|
|
ffd6ed |
+ add_string (&ret, &len, value, p-value);
|
|
|
ffd6ed |
+ state = KEY_START;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+ break;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ switch (state) {
|
|
|
ffd6ed |
+ case KEY_START: break;
|
|
|
ffd6ed |
+ case KEY: /* key followed by end of string */
|
|
|
ffd6ed |
+ add_string (&ret, &len, key, p-key);
|
|
|
ffd6ed |
+ add_string (&ret, &len, "", 0);
|
|
|
ffd6ed |
+ break;
|
|
|
ffd6ed |
+ case VALUE_START: /* key= followed by end of string */
|
|
|
ffd6ed |
+ add_string (&ret, &len, "", 0);
|
|
|
ffd6ed |
+ break;
|
|
|
ffd6ed |
+ case VALUE: /* key=value followed by end of string */
|
|
|
ffd6ed |
+ add_string (&ret, &len, value, p-value);
|
|
|
ffd6ed |
+ break;
|
|
|
ffd6ed |
+ case VALUE_QUOTED: /* unterminated key="value" */
|
|
|
ffd6ed |
+ fprintf (stderr, "%s: warning: unterminated quoted string on kernel command line\n",
|
|
|
ffd6ed |
+ guestfs_int_program_name);
|
|
|
ffd6ed |
+ add_string (&ret, &len, value, p-value);
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ add_null (&ret, &len;;
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ return ret;
|
|
|
ffd6ed |
+}
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+char **
|
|
|
ffd6ed |
+parse_proc_cmdline (void)
|
|
|
ffd6ed |
+{
|
|
|
ffd6ed |
+ CLEANUP_FCLOSE FILE *fp = NULL;
|
|
|
ffd6ed |
+ CLEANUP_FREE char *cmdline = NULL;
|
|
|
ffd6ed |
+ size_t len = 0;
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ fp = fopen ("/proc/cmdline", "re");
|
|
|
ffd6ed |
+ if (fp == NULL) {
|
|
|
ffd6ed |
+ perror ("/proc/cmdline");
|
|
|
ffd6ed |
+ return NULL;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ if (getline (&cmdline, &len, fp) == -1) {
|
|
|
ffd6ed |
+ perror ("getline");
|
|
|
ffd6ed |
+ return NULL;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ /* 'len' is not the length of the string, but the length of the
|
|
|
ffd6ed |
+ * buffer. We need to chomp the string.
|
|
|
ffd6ed |
+ */
|
|
|
ffd6ed |
+ len = strlen (cmdline);
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ if (len >= 1 && cmdline[len-1] == '\n')
|
|
|
ffd6ed |
+ cmdline[len-1] = '\0';
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ return parse_cmdline_string (cmdline);
|
|
|
ffd6ed |
+}
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+const char *
|
|
|
ffd6ed |
+get_cmdline_key (char **argv, const char *key)
|
|
|
ffd6ed |
+{
|
|
|
ffd6ed |
+ size_t i;
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ for (i = 0; argv[i] != NULL; i += 2) {
|
|
|
ffd6ed |
+ if (STREQ (argv[i], key))
|
|
|
ffd6ed |
+ return argv[i+1];
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ /* Not found. */
|
|
|
ffd6ed |
+ return NULL;
|
|
|
ffd6ed |
+}
|
|
|
ffd6ed |
diff --git a/p2v/kernel.c b/p2v/kernel.c
|
|
|
ffd6ed |
index 481ac78..88d18bd 100644
|
|
|
ffd6ed |
--- a/p2v/kernel.c
|
|
|
ffd6ed |
+++ b/p2v/kernel.c
|
|
|
ffd6ed |
@@ -35,46 +35,38 @@
|
|
|
ffd6ed |
static void notify_ui_callback (int type, const char *data);
|
|
|
ffd6ed |
|
|
|
ffd6ed |
void
|
|
|
ffd6ed |
-kernel_configuration (struct config *config, const char *cmdline)
|
|
|
ffd6ed |
+kernel_configuration (struct config *config, char **cmdline, int cmdline_source)
|
|
|
ffd6ed |
{
|
|
|
ffd6ed |
- const char *r;
|
|
|
ffd6ed |
- size_t len;
|
|
|
ffd6ed |
+ const char *p;
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r = strstr (cmdline, "p2v.server=");
|
|
|
ffd6ed |
- assert (r); /* checked by caller */
|
|
|
ffd6ed |
- r += 5+6;
|
|
|
ffd6ed |
- len = strcspn (r, " ");
|
|
|
ffd6ed |
+ p = get_cmdline_key (cmdline, "p2v.server");
|
|
|
ffd6ed |
+ assert (p); /* checked by caller */
|
|
|
ffd6ed |
free (config->server);
|
|
|
ffd6ed |
- config->server = strndup (r, len);
|
|
|
ffd6ed |
+ config->server = strdup (p);
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r = strstr (cmdline, "p2v.port=");
|
|
|
ffd6ed |
- if (r) {
|
|
|
ffd6ed |
- r += 5+4;
|
|
|
ffd6ed |
- if (sscanf (r, "%d", &config->port) != 1) {
|
|
|
ffd6ed |
+ p = get_cmdline_key (cmdline, "p2v.port");
|
|
|
ffd6ed |
+ if (p) {
|
|
|
ffd6ed |
+ if (sscanf (p, "%d", &config->port) != 1) {
|
|
|
ffd6ed |
fprintf (stderr, "%s: cannot parse p2v.port from kernel command line",
|
|
|
ffd6ed |
guestfs_int_program_name);
|
|
|
ffd6ed |
exit (EXIT_FAILURE);
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r = strstr (cmdline, "p2v.username=");
|
|
|
ffd6ed |
- if (r) {
|
|
|
ffd6ed |
- r += 5+8;
|
|
|
ffd6ed |
- len = strcspn (r, " ");
|
|
|
ffd6ed |
+ p = get_cmdline_key (cmdline, "p2v.username");
|
|
|
ffd6ed |
+ if (p) {
|
|
|
ffd6ed |
free (config->username);
|
|
|
ffd6ed |
- config->username = strndup (r, len);
|
|
|
ffd6ed |
+ config->username = strdup (p);
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r = strstr (cmdline, "p2v.password=");
|
|
|
ffd6ed |
- if (r) {
|
|
|
ffd6ed |
- r += 5+8;
|
|
|
ffd6ed |
- len = strcspn (r, " ");
|
|
|
ffd6ed |
+ p = get_cmdline_key (cmdline, "p2v.password");
|
|
|
ffd6ed |
+ if (p) {
|
|
|
ffd6ed |
free (config->password);
|
|
|
ffd6ed |
- config->password = strndup (r, len);
|
|
|
ffd6ed |
+ config->password = strdup (p);
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r = strstr (cmdline, "p2v.sudo");
|
|
|
ffd6ed |
- if (r)
|
|
|
ffd6ed |
+ p = get_cmdline_key (cmdline, "p2v.sudo");
|
|
|
ffd6ed |
+ if (p)
|
|
|
ffd6ed |
config->sudo = 1;
|
|
|
ffd6ed |
|
|
|
ffd6ed |
/* We should now be able to connect and interrogate virt-v2v
|
|
|
ffd6ed |
@@ -88,30 +80,26 @@ kernel_configuration (struct config *config, const char *cmdline)
|
|
|
ffd6ed |
exit (EXIT_FAILURE);
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r = strstr (cmdline, "p2v.name=");
|
|
|
ffd6ed |
- if (r) {
|
|
|
ffd6ed |
- r += 5+4;
|
|
|
ffd6ed |
- len = strcspn (r, " ");
|
|
|
ffd6ed |
+ p = get_cmdline_key (cmdline, "p2v.name");
|
|
|
ffd6ed |
+ if (p) {
|
|
|
ffd6ed |
free (config->guestname);
|
|
|
ffd6ed |
- config->guestname = strndup (r, len);
|
|
|
ffd6ed |
+ config->guestname = strdup (p);
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r = strstr (cmdline, "p2v.vcpus=");
|
|
|
ffd6ed |
- if (r) {
|
|
|
ffd6ed |
- r += 5+5;
|
|
|
ffd6ed |
- if (sscanf (r, "%d", &config->vcpus) != 1) {
|
|
|
ffd6ed |
+ p = get_cmdline_key (cmdline, "p2v.vcpus");
|
|
|
ffd6ed |
+ if (p) {
|
|
|
ffd6ed |
+ if (sscanf (p, "%d", &config->vcpus) != 1) {
|
|
|
ffd6ed |
fprintf (stderr, "%s: cannot parse p2v.vcpus from kernel command line\n",
|
|
|
ffd6ed |
guestfs_int_program_name);
|
|
|
ffd6ed |
exit (EXIT_FAILURE);
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r = strstr (cmdline, "p2v.memory=");
|
|
|
ffd6ed |
- if (r) {
|
|
|
ffd6ed |
+ p = get_cmdline_key (cmdline, "p2v.memory");
|
|
|
ffd6ed |
+ if (p) {
|
|
|
ffd6ed |
char mem_code[2];
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r += 5+6;
|
|
|
ffd6ed |
- if (sscanf (r, "%" SCNu64 "%c", &config->memory, mem_code) != 1) {
|
|
|
ffd6ed |
+ if (sscanf (p, "%" SCNu64 "%c", &config->memory, mem_code) != 1) {
|
|
|
ffd6ed |
fprintf (stderr, "%s: cannot parse p2v.memory from kernel command line\n",
|
|
|
ffd6ed |
guestfs_int_program_name);
|
|
|
ffd6ed |
exit (EXIT_FAILURE);
|
|
|
ffd6ed |
@@ -128,88 +116,75 @@ kernel_configuration (struct config *config, const char *cmdline)
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r = strstr (cmdline, "p2v.disks=");
|
|
|
ffd6ed |
- if (r) {
|
|
|
ffd6ed |
+ p = get_cmdline_key (cmdline, "p2v.disks");
|
|
|
ffd6ed |
+ if (p) {
|
|
|
ffd6ed |
CLEANUP_FREE char *t;
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r += 5+5;
|
|
|
ffd6ed |
- len = strcspn (r, " ");
|
|
|
ffd6ed |
- t = strndup (r, len);
|
|
|
ffd6ed |
+ t = strdup (p);
|
|
|
ffd6ed |
guestfs_int_free_string_list (config->disks);
|
|
|
ffd6ed |
config->disks = guestfs_int_split_string (',', t);
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r = strstr (cmdline, "p2v.removable=");
|
|
|
ffd6ed |
- if (r) {
|
|
|
ffd6ed |
+ p = get_cmdline_key (cmdline, "p2v.removable");
|
|
|
ffd6ed |
+ if (p) {
|
|
|
ffd6ed |
CLEANUP_FREE char *t;
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r += 5+9;
|
|
|
ffd6ed |
- len = strcspn (r, " ");
|
|
|
ffd6ed |
- t = strndup (r, len);
|
|
|
ffd6ed |
+ t = strdup (p);
|
|
|
ffd6ed |
guestfs_int_free_string_list (config->removable);
|
|
|
ffd6ed |
config->removable = guestfs_int_split_string (',', t);
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r = strstr (cmdline, "p2v.interfaces=");
|
|
|
ffd6ed |
- if (r) {
|
|
|
ffd6ed |
+ p = get_cmdline_key (cmdline, "p2v.interfaces");
|
|
|
ffd6ed |
+ if (p) {
|
|
|
ffd6ed |
CLEANUP_FREE char *t;
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r += 5+10;
|
|
|
ffd6ed |
- len = strcspn (r, " ");
|
|
|
ffd6ed |
- t = strndup (r, len);
|
|
|
ffd6ed |
+ t = strdup (p);
|
|
|
ffd6ed |
guestfs_int_free_string_list (config->interfaces);
|
|
|
ffd6ed |
config->interfaces = guestfs_int_split_string (',', t);
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r = strstr (cmdline, "p2v.network=");
|
|
|
ffd6ed |
- if (r) {
|
|
|
ffd6ed |
+ p = get_cmdline_key (cmdline, "p2v.network");
|
|
|
ffd6ed |
+ if (p) {
|
|
|
ffd6ed |
CLEANUP_FREE char *t;
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r += 5+7;
|
|
|
ffd6ed |
- len = strcspn (r, " ");
|
|
|
ffd6ed |
- t = strndup (r, len);
|
|
|
ffd6ed |
+ t = strdup (p);
|
|
|
ffd6ed |
guestfs_int_free_string_list (config->network_map);
|
|
|
ffd6ed |
config->network_map = guestfs_int_split_string (',', t);
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r = strstr (cmdline, "p2v.o=");
|
|
|
ffd6ed |
- if (r) {
|
|
|
ffd6ed |
- r += 5+1;
|
|
|
ffd6ed |
- len = strcspn (r, " ");
|
|
|
ffd6ed |
+ p = get_cmdline_key (cmdline, "p2v.o");
|
|
|
ffd6ed |
+ if (p) {
|
|
|
ffd6ed |
free (config->output);
|
|
|
ffd6ed |
- config->output = strndup (r, len);
|
|
|
ffd6ed |
+ config->output = strdup (p);
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r = strstr (cmdline, "p2v.oa=sparse");
|
|
|
ffd6ed |
- if (r)
|
|
|
ffd6ed |
- config->output_allocation = OUTPUT_ALLOCATION_SPARSE;
|
|
|
ffd6ed |
-
|
|
|
ffd6ed |
- r = strstr (cmdline, "p2v.oa=preallocated");
|
|
|
ffd6ed |
- if (r)
|
|
|
ffd6ed |
- config->output_allocation = OUTPUT_ALLOCATION_PREALLOCATED;
|
|
|
ffd6ed |
+ p = get_cmdline_key (cmdline, "p2v.oa");
|
|
|
ffd6ed |
+ if (p) {
|
|
|
ffd6ed |
+ if (STREQ (p, "sparse"))
|
|
|
ffd6ed |
+ config->output_allocation = OUTPUT_ALLOCATION_SPARSE;
|
|
|
ffd6ed |
+ else if (STREQ (p, "preallocated"))
|
|
|
ffd6ed |
+ config->output_allocation = OUTPUT_ALLOCATION_PREALLOCATED;
|
|
|
ffd6ed |
+ else
|
|
|
ffd6ed |
+ fprintf (stderr, "%s: warning: don't know what p2v.oa=%s means\n",
|
|
|
ffd6ed |
+ guestfs_int_program_name, p);
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r = strstr (cmdline, "p2v.oc=");
|
|
|
ffd6ed |
- if (r) {
|
|
|
ffd6ed |
- r += 5+2;
|
|
|
ffd6ed |
- len = strcspn (r, " ");
|
|
|
ffd6ed |
+ p = get_cmdline_key (cmdline, "p2v.oc");
|
|
|
ffd6ed |
+ if (p) {
|
|
|
ffd6ed |
free (config->output_connection);
|
|
|
ffd6ed |
- config->output_connection = strndup (r, len);
|
|
|
ffd6ed |
+ config->output_connection = strdup (p);
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r = strstr (cmdline, "p2v.of=");
|
|
|
ffd6ed |
- if (r) {
|
|
|
ffd6ed |
- r += 5+2;
|
|
|
ffd6ed |
- len = strcspn (r, " ");
|
|
|
ffd6ed |
+ p = get_cmdline_key (cmdline, "p2v.of");
|
|
|
ffd6ed |
+ if (p) {
|
|
|
ffd6ed |
free (config->output_format);
|
|
|
ffd6ed |
- config->output_format = strndup (r, len);
|
|
|
ffd6ed |
+ config->output_format = strdup (p);
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- r = strstr (cmdline, "p2v.os=");
|
|
|
ffd6ed |
- if (r) {
|
|
|
ffd6ed |
- r += 5+2;
|
|
|
ffd6ed |
- len = strcspn (r, " ");
|
|
|
ffd6ed |
+ p = get_cmdline_key (cmdline, "p2v.os");
|
|
|
ffd6ed |
+ if (p) {
|
|
|
ffd6ed |
free (config->output_storage);
|
|
|
ffd6ed |
- config->output_storage = strndup (r, len);
|
|
|
ffd6ed |
+ config->output_storage = strdup (p);
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
|
|
|
ffd6ed |
/* Perform the conversion in text mode. */
|
|
|
ffd6ed |
diff --git a/p2v/main.c b/p2v/main.c
|
|
|
ffd6ed |
index 2dba1b8..4e67992 100644
|
|
|
ffd6ed |
--- a/p2v/main.c
|
|
|
ffd6ed |
+++ b/p2v/main.c
|
|
|
ffd6ed |
@@ -44,7 +44,6 @@ char **all_interfaces;
|
|
|
ffd6ed |
static void set_config_defaults (struct config *config);
|
|
|
ffd6ed |
static void find_all_disks (void);
|
|
|
ffd6ed |
static void find_all_interfaces (void);
|
|
|
ffd6ed |
-static char *read_cmdline (void);
|
|
|
ffd6ed |
static int cpuinfo_flags (void);
|
|
|
ffd6ed |
|
|
|
ffd6ed |
enum { HELP_OPTION = CHAR_MAX + 1 };
|
|
|
ffd6ed |
@@ -99,7 +98,8 @@ main (int argc, char *argv[])
|
|
|
ffd6ed |
gboolean gui_possible;
|
|
|
ffd6ed |
int c;
|
|
|
ffd6ed |
int option_index;
|
|
|
ffd6ed |
- char *cmdline = NULL;
|
|
|
ffd6ed |
+ char **cmdline = NULL;
|
|
|
ffd6ed |
+ int cmdline_source = 0;
|
|
|
ffd6ed |
struct config *config = new_config ();
|
|
|
ffd6ed |
|
|
|
ffd6ed |
setlocale (LC_ALL, "");
|
|
|
ffd6ed |
@@ -120,7 +120,8 @@ main (int argc, char *argv[])
|
|
|
ffd6ed |
display_long_options (long_options);
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
else if (STREQ (long_options[option_index].name, "cmdline")) {
|
|
|
ffd6ed |
- cmdline = strdup (optarg);
|
|
|
ffd6ed |
+ cmdline = parse_cmdline_string (optarg);
|
|
|
ffd6ed |
+ cmdline_source = CMDLINE_SOURCE_COMMAND_LINE;
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
else {
|
|
|
ffd6ed |
fprintf (stderr, _("%s: unknown long option: %s (%d)\n"),
|
|
|
ffd6ed |
@@ -158,16 +159,18 @@ main (int argc, char *argv[])
|
|
|
ffd6ed |
* If /proc/cmdline contains p2v.debug then we enable verbose mode
|
|
|
ffd6ed |
* even for interactive configuration.
|
|
|
ffd6ed |
*/
|
|
|
ffd6ed |
- if (cmdline == NULL)
|
|
|
ffd6ed |
- cmdline = read_cmdline ();
|
|
|
ffd6ed |
- if (cmdline == NULL)
|
|
|
ffd6ed |
- goto gui;
|
|
|
ffd6ed |
+ if (cmdline == NULL) {
|
|
|
ffd6ed |
+ cmdline = parse_proc_cmdline ();
|
|
|
ffd6ed |
+ if (cmdline == NULL)
|
|
|
ffd6ed |
+ goto gui;
|
|
|
ffd6ed |
+ cmdline_source = CMDLINE_SOURCE_PROC_CMDLINE;
|
|
|
ffd6ed |
+ }
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- if (strstr (cmdline, "p2v.debug"))
|
|
|
ffd6ed |
+ if (get_cmdline_key (cmdline, "p2v.debug") != NULL)
|
|
|
ffd6ed |
config->verbose = 1;
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- if (strstr (cmdline, "p2v.server="))
|
|
|
ffd6ed |
- kernel_configuration (config, cmdline);
|
|
|
ffd6ed |
+ if (get_cmdline_key (cmdline, "p2v.server") != NULL)
|
|
|
ffd6ed |
+ kernel_configuration (config, cmdline, cmdline_source);
|
|
|
ffd6ed |
else {
|
|
|
ffd6ed |
gui:
|
|
|
ffd6ed |
if (!gui_possible)
|
|
|
ffd6ed |
@@ -176,7 +179,7 @@ main (int argc, char *argv[])
|
|
|
ffd6ed |
gui_application (config);
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- free (cmdline);
|
|
|
ffd6ed |
+ guestfs_int_free_string_list (cmdline);
|
|
|
ffd6ed |
|
|
|
ffd6ed |
exit (EXIT_SUCCESS);
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
@@ -498,36 +501,6 @@ find_all_interfaces (void)
|
|
|
ffd6ed |
qsort (all_interfaces, nr_interfaces, sizeof (char *), compare);
|
|
|
ffd6ed |
}
|
|
|
ffd6ed |
|
|
|
ffd6ed |
-/* Read /proc/cmdline. */
|
|
|
ffd6ed |
-static char *
|
|
|
ffd6ed |
-read_cmdline (void)
|
|
|
ffd6ed |
-{
|
|
|
ffd6ed |
- CLEANUP_FCLOSE FILE *fp = NULL;
|
|
|
ffd6ed |
- char *ret = NULL;
|
|
|
ffd6ed |
- size_t len;
|
|
|
ffd6ed |
-
|
|
|
ffd6ed |
- fp = fopen ("/proc/cmdline", "re");
|
|
|
ffd6ed |
- if (fp == NULL) {
|
|
|
ffd6ed |
- perror ("/proc/cmdline");
|
|
|
ffd6ed |
- return NULL;
|
|
|
ffd6ed |
- }
|
|
|
ffd6ed |
-
|
|
|
ffd6ed |
- if (getline (&ret, &len, fp) == -1) {
|
|
|
ffd6ed |
- perror ("getline");
|
|
|
ffd6ed |
- return NULL;
|
|
|
ffd6ed |
- }
|
|
|
ffd6ed |
-
|
|
|
ffd6ed |
- /* 'len' is not the length of the string, but the length of the
|
|
|
ffd6ed |
- * buffer. We need to chomp the string.
|
|
|
ffd6ed |
- */
|
|
|
ffd6ed |
- len = strlen (ret);
|
|
|
ffd6ed |
-
|
|
|
ffd6ed |
- if (len >= 1 && ret[len-1] == '\n')
|
|
|
ffd6ed |
- ret[len-1] = '\0';
|
|
|
ffd6ed |
-
|
|
|
ffd6ed |
- return ret;
|
|
|
ffd6ed |
-}
|
|
|
ffd6ed |
-
|
|
|
ffd6ed |
/* Read the list of flags from /proc/cpuinfo. */
|
|
|
ffd6ed |
static int
|
|
|
ffd6ed |
cpuinfo_flags (void)
|
|
|
ffd6ed |
diff --git a/p2v/p2v.h b/p2v/p2v.h
|
|
|
ffd6ed |
index c5427a7..41d305d 100644
|
|
|
ffd6ed |
--- a/p2v/p2v.h
|
|
|
ffd6ed |
+++ b/p2v/p2v.h
|
|
|
ffd6ed |
@@ -85,8 +85,16 @@ extern struct config *new_config (void);
|
|
|
ffd6ed |
extern struct config *copy_config (struct config *);
|
|
|
ffd6ed |
extern void free_config (struct config *);
|
|
|
ffd6ed |
|
|
|
ffd6ed |
+/* kernel-cmdline.c */
|
|
|
ffd6ed |
+extern char **parse_cmdline_string (const char *cmdline);
|
|
|
ffd6ed |
+extern char **parse_proc_cmdline (void);
|
|
|
ffd6ed |
+extern const char *get_cmdline_key (char **cmdline, const char *key);
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+#define CMDLINE_SOURCE_COMMAND_LINE 1 /* --cmdline */
|
|
|
ffd6ed |
+#define CMDLINE_SOURCE_PROC_CMDLINE 2 /* /proc/cmdline */
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
/* kernel.c */
|
|
|
ffd6ed |
-extern void kernel_configuration (struct config *, const char *cmdline);
|
|
|
ffd6ed |
+extern void kernel_configuration (struct config *, char **cmdline, int cmdline_source);
|
|
|
ffd6ed |
|
|
|
ffd6ed |
/* gui.c */
|
|
|
ffd6ed |
extern void gui_application (struct config *);
|
|
|
ffd6ed |
diff --git a/po/POTFILES b/po/POTFILES
|
|
|
ffd6ed |
index 320710f..7c99fd0 100644
|
|
|
ffd6ed |
--- a/po/POTFILES
|
|
|
ffd6ed |
+++ b/po/POTFILES
|
|
|
ffd6ed |
@@ -258,6 +258,7 @@ p2v/config.c
|
|
|
ffd6ed |
p2v/conversion.c
|
|
|
ffd6ed |
p2v/copying.c
|
|
|
ffd6ed |
p2v/gui.c
|
|
|
ffd6ed |
+p2v/kernel-cmdline.c
|
|
|
ffd6ed |
p2v/kernel.c
|
|
|
ffd6ed |
p2v/main.c
|
|
|
ffd6ed |
p2v/miniexpect.c
|
|
|
ffd6ed |
--
|
|
|
ffd6ed |
1.8.3.1
|
|
|
ffd6ed |
|