From: "Richard W.M. Jones" <rjones(a)redhat.com>
This is so we will be able to reuse the same code in the OCaml tools.
This is just code motion.
(cherry picked from commit 4d7c14fdbb372d6ad5ef729b6969078b5fdb68da)
---
align/Makefile.am | 4 +-
cat/Makefile.am | 4 +-
cat/virt-cat.c | 6 +-
cat/virt-ls.c | 6 +-
df/Makefile.am | 4 +-
df/main.c | 6 +-
edit/Makefile.am | 4 +-
edit/virt-edit.c | 6 +-
fish/Makefile.am | 4 +-
fish/fish.c | 6 +-
fish/options.c | 283 ++++------------------------------------
fish/uri.c | 318 +++++++++++++++++++++++++++++++++++++++++++++
fish/uri.h | 46 +++++++
format/Makefile.am | 4 +-
fuse/Makefile.am | 4 +-
inspector/Makefile.am | 4 +-
inspector/virt-inspector.c | 6 +-
po/POTFILES | 1 +
rescue/Makefile.am | 4 +-
rescue/virt-rescue.c | 12 +-
20 files changed, 456 insertions(+), 276 deletions(-)
create mode 100644 fish/uri.c
create mode 100644 fish/uri.h
diff --git a/align/Makefile.am b/align/Makefile.am
index 285f9f1..b243823 100644
--- a/align/Makefile.am
+++ b/align/Makefile.am
@@ -38,7 +38,9 @@ SHARED_SOURCE_FILES = \
../fish/inspect.c \
../fish/keys.c \
../fish/options.h \
- ../fish/options.c
+ ../fish/options.c \
+ ../fish/uri.h \
+ ../fish/uri.c
virt_alignment_scan_SOURCES = \
$(SHARED_SOURCE_FILES) \
diff --git a/cat/Makefile.am b/cat/Makefile.am
index 5f6c2fc..b9df9cd 100644
--- a/cat/Makefile.am
+++ b/cat/Makefile.am
@@ -35,7 +35,9 @@ SHARED_SOURCE_FILES = \
../fish/inspect.c \
../fish/keys.c \
../fish/options.h \
- ../fish/options.c
+ ../fish/options.c \
+ ../fish/uri.h \
+ ../fish/uri.c
virt_cat_SOURCES = \
$(SHARED_SOURCE_FILES) \
diff --git a/cat/virt-cat.c b/cat/virt-cat.c
index f752a1a..e86ecf3 100644
--- a/cat/virt-cat.c
+++ b/cat/virt-cat.c
@@ -186,7 +186,11 @@ main (int argc, char *argv[])
exit (EXIT_FAILURE);
}
drv->type = drv_a;
- drv->a.filename = argv[optind];
+ drv->a.filename = strdup (argv[optind]);
+ if (!drv->a.filename) {
+ perror ("strdup");
+ exit (EXIT_FAILURE);
+ }
drv->next = drvs;
drvs = drv;
} else { /* simulate -d option */
diff --git a/cat/virt-ls.c b/cat/virt-ls.c
index 3ebd633..1c449c2 100644
--- a/cat/virt-ls.c
+++ b/cat/virt-ls.c
@@ -291,7 +291,11 @@ main (int argc, char *argv[])
exit (EXIT_FAILURE);
}
drv->type = drv_a;
- drv->a.filename = argv[optind];
+ drv->a.filename = strdup (argv[optind]);
+ if (!drv->a.filename) {
+ perror ("strdup");
+ exit (EXIT_FAILURE);
+ }
drv->next = drvs;
drvs = drv;
} else { /* simulate -d option */
diff --git a/df/Makefile.am b/df/Makefile.am
index 1288d10..38a628c 100644
--- a/df/Makefile.am
+++ b/df/Makefile.am
@@ -33,7 +33,9 @@ SHARED_SOURCE_FILES = \
../fish/inspect.c \
../fish/keys.c \
../fish/options.h \
- ../fish/options.c
+ ../fish/options.c \
+ ../fish/uri.h \
+ ../fish/uri.c
virt_df_SOURCES = \
$(SHARED_SOURCE_FILES) \
diff --git a/df/main.c b/df/main.c
index 5524070..0eee3cb 100644
--- a/df/main.c
+++ b/df/main.c
@@ -220,7 +220,11 @@ main (int argc, char *argv[])
exit (EXIT_FAILURE);
}
drv->type = drv_a;
- drv->a.filename = argv[optind];
+ drv->a.filename = strdup (argv[optind]);
+ if (!drv->a.filename) {
+ perror ("strdup");
+ exit (EXIT_FAILURE);
+ }
drv->next = drvs;
drvs = drv;
} else { /* simulate -d option */
diff --git a/edit/Makefile.am b/edit/Makefile.am
index 01828a7..9d92be7 100644
--- a/edit/Makefile.am
+++ b/edit/Makefile.am
@@ -31,7 +31,9 @@ SHARED_SOURCE_FILES = \
../fish/inspect.c \
../fish/keys.c \
../fish/options.h \
- ../fish/options.c
+ ../fish/options.c \
+ ../fish/uri.h \
+ ../fish/uri.c
virt_edit_SOURCES = \
$(SHARED_SOURCE_FILES) \
diff --git a/edit/virt-edit.c b/edit/virt-edit.c
index 05e88e2..5690f8d 100644
--- a/edit/virt-edit.c
+++ b/edit/virt-edit.c
@@ -223,7 +223,11 @@ main (int argc, char *argv[])
exit (EXIT_FAILURE);
}
drv->type = drv_a;
- drv->a.filename = argv[optind];
+ drv->a.filename = strdup (argv[optind]);
+ if (!drv->a.filename) {
+ perror ("strdup");
+ exit (EXIT_FAILURE);
+ }
drv->next = drvs;
drvs = drv;
} else { /* simulate -d option */
diff --git a/fish/Makefile.am b/fish/Makefile.am
index 3e4995c..0c8ad17 100644
--- a/fish/Makefile.am
+++ b/fish/Makefile.am
@@ -70,7 +70,9 @@ SHARED_SOURCE_FILES = \
options.h \
options.c \
progress.h \
- progress.c
+ progress.c \
+ uri.h \
+ uri.c
guestfish_SOURCES = \
$(generator_built) \
diff --git a/fish/fish.c b/fish/fish.c
index 2b5a877..7ca03d1 100644
--- a/fish/fish.c
+++ b/fish/fish.c
@@ -429,7 +429,11 @@ main (int argc, char *argv[])
exit (EXIT_FAILURE);
}
drv->type = drv_a;
- drv->a.filename = argv[optind];
+ drv->a.filename = strdup (argv[optind]);
+ if (!drv->a.filename) {
+ perror ("strdup");
+ exit (EXIT_FAILURE);
+ }
drv->next = drvs;
drvs = drv;
} else { /* simulate -d option */
diff --git a/fish/options.c b/fish/options.c
index 5c55b38..6d63afa 100644
--- a/fish/options.c
+++ b/fish/options.c
@@ -25,22 +25,15 @@
#include <errno.h>
#include <libintl.h>
-#include <libxml/uri.h>
-
-#include "c-ctype.h"
-
#include "guestfs.h"
#include "options.h"
-
-static int is_uri (const char *arg);
-static void parse_uri (const char *arg, const char *format, struct drv *drv);
-static char *query_get (xmlURIPtr uri, const char *search_name);
-static char **make_server (xmlURIPtr uri, const char *socket);
+#include "uri.h"
/* Handle the '-a' option when passed on the command line. */
void
option_a (const char *arg, const char *format, struct drv **drvsp)
{
+ struct uri uri;
struct drv *drv;
drv = calloc (1, sizeof (struct drv));
@@ -49,268 +42,39 @@ option_a (const char *arg, const char *format, struct drv **drvsp)
exit (EXIT_FAILURE);
}
- /* Does it look like a URI? */
- if (is_uri (arg))
- parse_uri (arg, format, drv);
- else {
+ if (parse_uri (arg, &uri) == -1)
+ exit (EXIT_FAILURE);
+
+ if (STREQ (uri.protocol, "file")) {
/* Ordinary file. */
- if (access (arg, R_OK) != 0) {
- perror (arg);
+ if (access (uri.path, R_OK) != 0) {
+ perror (uri.path);
exit (EXIT_FAILURE);
}
drv->type = drv_a;
drv->nr_drives = -1;
- drv->a.filename = (char *) arg;
+ drv->a.filename = uri.path;
drv->a.format = format;
+
+ free (uri.protocol);
+ }
+ else {
+ /* Remote storage. */
+ drv->type = drv_uri;
+ drv->nr_drives = -1;
+ drv->uri.path = uri.path;
+ drv->uri.protocol = uri.protocol;
+ drv->uri.server = uri.server;
+ drv->uri.username = uri.username;
+ drv->uri.format = format;
+ drv->uri.orig_uri = arg;
}
drv->next = *drvsp;
*drvsp = drv;
}
-/* Does it "look like" a URI? A short lower-case ASCII string
- * followed by "://" will do. Note that we properly parse the URI
- * later on using libxml2.
- */
-static int
-is_uri (const char *arg)
-{
- const char *p;
-
- p = strstr (arg, "://");
- if (!p)
- return 0;
-
- if (p - arg >= 8)
- return 0;
-
- for (p--; p >= arg; p--) {
- if (!c_islower (*p))
- return 0;
- }
-
- return 1;
-}
-
-static void
-parse_uri (const char *arg, const char *format, struct drv *drv)
-{
- CLEANUP_XMLFREEURI xmlURIPtr uri = NULL;
- CLEANUP_FREE char *socket = NULL;
- char *path;
- char *protocol;
- char **server;
- char *username;
-
- uri = xmlParseURI (arg);
- if (!uri) {
- fprintf (stderr, _("%s: --add: could not parse URI '%s'\n"),
- program_name, arg);
- exit (EXIT_FAILURE);
- }
-
- /* Note we don't do much checking of the parsed URI, since the
- * underlying function 'guestfs_add_drive_opts' will check for us.
- * So just the basics here.
- */
- if (uri->scheme == NULL) {
- /* Probably can never happen. */
- fprintf (stderr, _("%s: --add %s: scheme of URI is NULL\n"),
- program_name, arg);
- exit (EXIT_FAILURE);
- }
-
- socket = query_get (uri, "socket");
-
- if (uri->server && STRNEQ (uri->server, "") && socket)
{
- fprintf (stderr, _("%s: --add %s: cannot both a server name and a socket query
parameter\n"),
- program_name, arg);
- exit (EXIT_FAILURE);
- }
-
- /* Is this needed? XXX
- if (socket && socket[0] != '/') {
- fprintf (stderr, _("%s: --add %s: socket query parameter must be an absolute
path\n"),
- program_name, arg);
- exit (EXIT_FAILURE);
- }
- */
-
- protocol = strdup (uri->scheme);
- if (protocol == NULL) {
- perror ("strdup");
- exit (EXIT_FAILURE);
- }
-
- server = make_server (uri, socket);
-
- if (uri->user && STRNEQ (uri->user, "")) {
- username = strdup (uri->user);
- if (!username) {
- perror ("username");
- exit (EXIT_FAILURE);
- }
- }
- else username = NULL;
-
- path = strdup (uri->path ? uri->path : "");
- if (!path) {
- perror ("path");
- exit (EXIT_FAILURE);
- }
-
- drv->type = drv_uri;
- drv->nr_drives = -1;
- drv->uri.path = path;
- drv->uri.protocol = protocol;
- drv->uri.server = server;
- drv->uri.username = username;
- drv->uri.format = format;
- drv->uri.orig_uri = arg;
-}
-
-/* Code inspired by libvirt src/util/viruri.c, written by danpb,
- * released under a compatible license.
- */
-static char *
-query_get (xmlURIPtr uri, const char *search_name)
-{
- /* XXX libvirt uses deprecated uri->query field. Why? */
- const char *query = uri->query_raw;
- const char *end, *eq;
-
- if (!query || STREQ (query, ""))
- return NULL;
-
- while (*query) {
- CLEANUP_FREE char *name = NULL;
- char *value = NULL;
-
- /* Find the next separator, or end of the string. */
- end = strchr (query, '&');
- if (!end)
- end = strchr(query, ';');
- if (!end)
- end = query + strlen (query);
-
- /* Find the first '=' character between here and end. */
- eq = strchr(query, '=');
- if (eq && eq >= end) eq = NULL;
-
- /* Empty section (eg. "&&"). */
- if (end == query)
- goto next;
-
- /* If there is no '=' character, then we have just "name"
- * and consistent with CGI.pm we assume value is "".
- */
- else if (!eq) {
- name = xmlURIUnescapeString (query, end - query, NULL);
- if (!name) goto no_memory;
- }
- /* Or if we have "name=" here (works around annoying
- * problem when calling xmlURIUnescapeString with len = 0).
- */
- else if (eq+1 == end) {
- name = xmlURIUnescapeString (query, eq - query, NULL);
- if (!name) goto no_memory;
- }
- /* If the '=' character is at the beginning then we have
- * "=value" and consistent with CGI.pm we _ignore_ this.
- */
- else if (query == eq)
- goto next;
-
- /* Otherwise it's "name=value". */
- else {
- name = xmlURIUnescapeString (query, eq - query, NULL);
- if (!name)
- goto no_memory;
- value = xmlURIUnescapeString (eq+1, end - (eq+1), NULL);
- if (!value) {
- goto no_memory;
- }
- }
-
- /* Is it the name we're looking for? */
- if (STREQ (name, search_name)) {
- if (!value) {
- value = strdup ("");
- if (!value)
- goto no_memory;
- }
- return value;
- }
-
- free (value);
-
- next:
- query = end;
- if (*query)
- query++; /* skip '&' separator */
- }
-
- /* search_name not found */
- return NULL;
-
- no_memory:
- perror ("malloc");
- exit (EXIT_FAILURE);
-}
-
-/* Construct either a tcp: server list of a unix: server list or
- * nothing at all from '-a' option URI.
- */
-static char **
-make_server (xmlURIPtr uri, const char *socket)
-{
- char **ret;
- char *server;
-
- /* If the server part of the URI is specified, then this is a TCP
- * connection.
- */
- if (uri->server && STRNEQ (uri->server, "")) {
- if (uri->port == 0) {
- if (asprintf (&server, "tcp:%s", uri->server) == -1) {
- perror ("asprintf");
- exit (EXIT_FAILURE);
- }
- }
- else {
- if (asprintf (&server, "tcp:%s:%d", uri->server, uri->port) ==
-1) {
- perror ("asprintf");
- exit (EXIT_FAILURE);
- }
- }
- }
- /* Otherwise, ?socket query parameter means it's a Unix domain
- * socket connection.
- */
- else if (socket != NULL) {
- if (asprintf (&server, "unix:%s", socket) == -1) {
- perror ("asprintf");
- exit (EXIT_FAILURE);
- }
- }
- /* Otherwise, no server parameter is needed. */
- else return NULL;
-
- /* The .server parameter is in fact a list of strings, although
- * only a singleton is passed by us.
- */
- ret = malloc (sizeof (char *) * 2);
- if (ret == NULL) {
- perror ("malloc");
- exit (EXIT_FAILURE);
- }
- ret[0] = server;
- ret[1] = NULL;
-
- return ret;
-}
-
char
add_drives (struct drv *drv, char next_drive)
{
@@ -488,7 +252,8 @@ free_drives (struct drv *drv)
switch (drv->type) {
case drv_a:
- /* a.filename and a.format are optargs, don't free them */
+ free (drv->a.filename);
+ /* a.format is an optarg, so don't free it */
break;
case drv_uri:
free (drv->uri.path);
diff --git a/fish/uri.c b/fish/uri.c
new file mode 100644
index 0000000..9c0892f
--- /dev/null
+++ b/fish/uri.c
@@ -0,0 +1,318 @@
+/* libguestfs - mini library for parsing -a URI parameters
+ * Copyright (C) 2013 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <libintl.h>
+
+#include <libxml/uri.h>
+
+#include "c-ctype.h"
+
+#include "guestfs.h"
+#include "guestfs-internal-frontend.h"
+#include "uri.h"
+
+static int is_uri (const char *arg);
+static int parse (const char *arg, char **path_ret, char **protocol_ret, char
***server_ret, char **username_ret);
+static char *query_get (xmlURIPtr uri, const char *search_name);
+static int make_server (xmlURIPtr uri, const char *socket, char ***ret);
+
+int
+parse_uri (const char *arg, struct uri *uri_ret)
+{
+ char *path;
+ char *protocol;
+ char **server;
+ char *username;
+
+ /* Does it look like a URI? */
+ if (is_uri (arg)) {
+ if (parse (arg, &path, &protocol, &server, &username) == -1)
+ return -1;
+ }
+ else {
+ /* Ordinary file. */
+ path = strdup (arg);
+ if (!path) {
+ perror ("strdup");
+ return -1;
+ }
+ protocol = strdup ("file");
+ if (!protocol) {
+ perror ("strdup");
+ free (path);
+ return -1;
+ }
+ server = NULL;
+ username = NULL;
+ }
+
+ uri_ret->path = path;
+ uri_ret->protocol = protocol;
+ uri_ret->server = server;
+ uri_ret->username = username;
+ return 0;
+}
+
+/* Does it "look like" a URI? A short lower-case ASCII string
+ * followed by "://" will do. Note that we properly parse the URI
+ * later on using libxml2.
+ */
+static int
+is_uri (const char *arg)
+{
+ const char *p;
+
+ p = strstr (arg, "://");
+ if (!p)
+ return 0;
+
+ if (p - arg >= 8)
+ return 0;
+
+ for (p--; p >= arg; p--) {
+ if (!c_islower (*p))
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
+parse (const char *arg, char **path_ret, char **protocol_ret,
+ char ***server_ret, char **username_ret)
+{
+ CLEANUP_XMLFREEURI xmlURIPtr uri = NULL;
+ CLEANUP_FREE char *socket = NULL;
+
+ uri = xmlParseURI (arg);
+ if (!uri) {
+ fprintf (stderr, _("%s: --add: could not parse URI '%s'\n"),
+ program_name, arg);
+ return -1;
+ }
+
+ /* Note we don't do much checking of the parsed URI, since the
+ * underlying function 'guestfs_add_drive_opts' will check for us.
+ * So just the basics here.
+ */
+ if (uri->scheme == NULL || STREQ (uri->scheme, "")) {
+ /* Probably can never happen. */
+ fprintf (stderr, _("%s: %s: scheme of URI is NULL or empty\n"),
+ program_name, arg);
+ return -1;
+ }
+
+ socket = query_get (uri, "socket");
+
+ if (uri->server && STRNEQ (uri->server, "") && socket)
{
+ fprintf (stderr, _("%s: %s: cannot both a server name and a socket query
parameter\n"),
+ program_name, arg);
+ return -1;
+ }
+
+ /* Is this needed? XXX
+ if (socket && socket[0] != '/') {
+ fprintf (stderr, _("%s: --add %s: socket query parameter must be an absolute
path\n"),
+ program_name, arg);
+ return -1;
+ }
+ */
+
+ *protocol_ret = strdup (uri->scheme);
+ if (*protocol_ret == NULL) {
+ perror ("strdup");
+ return -1;
+ }
+
+ if (make_server (uri, socket, server_ret) == -1) {
+ free (*protocol_ret);
+ return -1;
+ }
+
+ if (uri->user && STRNEQ (uri->user, "")) {
+ *username_ret = strdup (uri->user);
+ if (*username_ret == NULL) {
+ perror ("username");
+ free (*protocol_ret);
+ guestfs___free_string_list (*server_ret);
+ return -1;
+ }
+ }
+ else *username_ret = NULL;
+
+ *path_ret = strdup (uri->path ? uri->path : "");
+ if (!*path_ret) {
+ perror ("path");
+ free (*protocol_ret);
+ guestfs___free_string_list (*server_ret);
+ free (*username_ret);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Code inspired by libvirt src/util/viruri.c, written by danpb,
+ * released under a compatible license.
+ */
+static char *
+query_get (xmlURIPtr uri, const char *search_name)
+{
+ /* XXX libvirt uses deprecated uri->query field. Why? */
+ const char *query = uri->query_raw;
+ const char *end, *eq;
+
+ if (!query || STREQ (query, ""))
+ return NULL;
+
+ while (*query) {
+ CLEANUP_FREE char *name = NULL;
+ char *value = NULL;
+
+ /* Find the next separator, or end of the string. */
+ end = strchr (query, '&');
+ if (!end)
+ end = strchr(query, ';');
+ if (!end)
+ end = query + strlen (query);
+
+ /* Find the first '=' character between here and end. */
+ eq = strchr(query, '=');
+ if (eq && eq >= end) eq = NULL;
+
+ /* Empty section (eg. "&&"). */
+ if (end == query)
+ goto next;
+
+ /* If there is no '=' character, then we have just "name"
+ * and consistent with CGI.pm we assume value is "".
+ */
+ else if (!eq) {
+ name = xmlURIUnescapeString (query, end - query, NULL);
+ if (!name) goto no_memory;
+ }
+ /* Or if we have "name=" here (works around annoying
+ * problem when calling xmlURIUnescapeString with len = 0).
+ */
+ else if (eq+1 == end) {
+ name = xmlURIUnescapeString (query, eq - query, NULL);
+ if (!name) goto no_memory;
+ }
+ /* If the '=' character is at the beginning then we have
+ * "=value" and consistent with CGI.pm we _ignore_ this.
+ */
+ else if (query == eq)
+ goto next;
+
+ /* Otherwise it's "name=value". */
+ else {
+ name = xmlURIUnescapeString (query, eq - query, NULL);
+ if (!name)
+ goto no_memory;
+ value = xmlURIUnescapeString (eq+1, end - (eq+1), NULL);
+ if (!value) {
+ goto no_memory;
+ }
+ }
+
+ /* Is it the name we're looking for? */
+ if (STREQ (name, search_name)) {
+ if (!value) {
+ value = strdup ("");
+ if (!value)
+ goto no_memory;
+ }
+ return value;
+ }
+
+ free (value);
+
+ next:
+ query = end;
+ if (*query)
+ query++; /* skip '&' separator */
+ }
+
+ /* search_name not found */
+ return NULL;
+
+ no_memory:
+ perror ("malloc");
+ return NULL;
+}
+
+/* Construct either a tcp: server list of a unix: server list or
+ * nothing at all from '-a' option URI.
+ */
+static int
+make_server (xmlURIPtr uri, const char *socket, char ***ret)
+{
+ char *server;
+
+ /* If the server part of the URI is specified, then this is a TCP
+ * connection.
+ */
+ if (uri->server && STRNEQ (uri->server, "")) {
+ if (uri->port == 0) {
+ if (asprintf (&server, "tcp:%s", uri->server) == -1) {
+ perror ("asprintf");
+ return -1;
+ }
+ }
+ else {
+ if (asprintf (&server, "tcp:%s:%d", uri->server, uri->port) ==
-1) {
+ perror ("asprintf");
+ return -1;
+ }
+ }
+ }
+ /* Otherwise, ?socket query parameter means it's a Unix domain
+ * socket connection.
+ */
+ else if (socket != NULL) {
+ if (asprintf (&server, "unix:%s", socket) == -1) {
+ perror ("asprintf");
+ return -1;
+ }
+ }
+ /* Otherwise, no server parameter is needed. */
+ else {
+ *ret = NULL;
+ return 0;
+ }
+
+ /* The .server parameter is in fact a list of strings, although
+ * only a singleton is passed by us.
+ */
+ *ret = malloc (sizeof (char *) * 2);
+ if (*ret == NULL) {
+ perror ("malloc");
+ return -1;
+ }
+ (*ret)[0] = server;
+ (*ret)[1] = NULL;
+
+ return 0;
+}
diff --git a/fish/uri.h b/fish/uri.h
new file mode 100644
index 0000000..420d20c
--- /dev/null
+++ b/fish/uri.h
@@ -0,0 +1,46 @@
+/* libguestfs - mini library for parsing -a URI parameters
+ * Copyright (C) 2013 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#ifndef FISH_URI_H
+#define FISH_URI_H
+
+struct uri {
+ char *path; /* disk path */
+ char *protocol; /* protocol (eg. "file", "nbd") */
+ char **server; /* server(s) - can be NULL */
+ char *username; /* username - can be NULL */
+};
+
+/* Parse the '-a' option parameter 'arg', and place the result in
+ * '*uri_ret'.
+ *
+ * If it doesn't look like a URI then uri_ret->path will be the same
+ * as 'arg' (copied) and uri_ret->protocol will be "file".
+ *
+ * If it looks like a URI and can be parsed, then the other fields will
+ * be filled in as appropriate.
+ *
+ * The caller should free the fields from the struct after use.
+ *
+ * Returns 0 if parsing went OK, or -1 if there was an error.
+ */
+extern int parse_uri (const char *arg, struct uri *uri_ret);
+
+#endif /* FISH_URI_H */
diff --git a/format/Makefile.am b/format/Makefile.am
index a0d1ed4..c93edc9 100644
--- a/format/Makefile.am
+++ b/format/Makefile.am
@@ -30,7 +30,9 @@ SHARED_SOURCE_FILES = \
../fish/inspect.c \
../fish/keys.c \
../fish/options.h \
- ../fish/options.c
+ ../fish/options.c \
+ ../fish/uri.h \
+ ../fish/uri.c
virt_format_SOURCES = \
$(SHARED_SOURCE_FILES) \
diff --git a/fuse/Makefile.am b/fuse/Makefile.am
index 6335bbb..d10ff7d 100644
--- a/fuse/Makefile.am
+++ b/fuse/Makefile.am
@@ -42,7 +42,9 @@ SHARED_SOURCE_FILES = \
../fish/inspect.c \
../fish/keys.c \
../fish/options.h \
- ../fish/options.c
+ ../fish/options.c \
+ ../fish/uri.h \
+ ../fish/uri.c
# guestmount
diff --git a/inspector/Makefile.am b/inspector/Makefile.am
index 1967fe8..a5aa3c1 100644
--- a/inspector/Makefile.am
+++ b/inspector/Makefile.am
@@ -57,7 +57,9 @@ SHARED_SOURCE_FILES = \
../fish/inspect.c \
../fish/keys.c \
../fish/options.h \
- ../fish/options.c
+ ../fish/options.c \
+ ../fish/uri.h \
+ ../fish/uri.c
virt_inspector_SOURCES = \
$(SHARED_SOURCE_FILES) \
diff --git a/inspector/virt-inspector.c b/inspector/virt-inspector.c
index 146f211..a070a3a 100644
--- a/inspector/virt-inspector.c
+++ b/inspector/virt-inspector.c
@@ -199,7 +199,11 @@ main (int argc, char *argv[])
exit (EXIT_FAILURE);
}
drv->type = drv_a;
- drv->a.filename = argv[optind];
+ drv->a.filename = strdup (argv[optind]);
+ if (!drv->a.filename) {
+ perror ("strdup");
+ exit (EXIT_FAILURE);
+ }
drv->next = drvs;
drvs = drv;
} else { /* simulate -d option */
diff --git a/po/POTFILES b/po/POTFILES
index 457e129..bcefe16 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -143,6 +143,7 @@ fish/setenv.c
fish/supported.c
fish/tilde.c
fish/time.c
+fish/uri.c
format/format.c
fuse/guestmount.c
fuse/guestunmount.c
diff --git a/rescue/Makefile.am b/rescue/Makefile.am
index f694223..7d23ee2 100644
--- a/rescue/Makefile.am
+++ b/rescue/Makefile.am
@@ -31,7 +31,9 @@ SHARED_SOURCE_FILES = \
../fish/inspect.c \
../fish/keys.c \
../fish/options.h \
- ../fish/options.c
+ ../fish/options.c \
+ ../fish/uri.h \
+ ../fish/uri.c
virt_rescue_SOURCES = \
$(SHARED_SOURCE_FILES) \
diff --git a/rescue/virt-rescue.c b/rescue/virt-rescue.c
index 6c6e306..65dd473 100644
--- a/rescue/virt-rescue.c
+++ b/rescue/virt-rescue.c
@@ -256,7 +256,11 @@ main (int argc, char *argv[])
exit (EXIT_FAILURE);
}
drv->type = drv_a;
- drv->a.filename = argv[optind];
+ drv->a.filename = strdup (argv[optind]);
+ if (!drv->a.filename) {
+ perror ("strdup");
+ exit (EXIT_FAILURE);
+ }
drv->next = drvs;
drvs = drv;
} else { /* simulate -d option */
@@ -570,7 +574,11 @@ add_scratch_disk (struct drv **drvs)
}
drv->type = drv_a;
drv->nr_drives = -1;
- drv->a.filename = filename;
+ drv->a.filename = strdup (filename);
+ if (!drv->a.filename) {
+ perror ("strdup");
+ exit (EXIT_FAILURE);
+ }
drv->a.format = "raw";
drv->next = *drvs;
*drvs = drv;
--
1.8.3.1