This allows us to remove two unused internal functions handling string
lists.
---
generator/states-connect-socket-activation.c | 59 ++++++-------
generator/states-connect.c | 8 +-
generator/states-newstyle-opt-meta-context.c | 22 ++---
lib/Makefile.am | 2 +
lib/connect.c | 22 +----
lib/crypto.c | 36 ++++----
lib/handle.c | 28 +++---
lib/internal.h | 10 ++-
lib/uri.c | 89 +++++++++-----------
lib/utils.c | 43 +++-------
10 files changed, 133 insertions(+), 186 deletions(-)
diff --git a/generator/states-connect-socket-activation.c
b/generator/states-connect-socket-activation.c
index ee08dff..5f4cfbd 100644
--- a/generator/states-connect-socket-activation.c
+++ b/generator/states-connect-socket-activation.c
@@ -47,11 +47,11 @@ extern char **environ;
static char **
prepare_socket_activation_environment (void)
{
- char **env = NULL;
+ string_vector env = empty_vector;
char *p0 = NULL, *p1 = NULL;
- size_t i, len;
- void *vp;
+ size_t i;
+ /* Reserve slots env[0] and env[1]. */
p0 = strdup ("LISTEN_PID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
if (p0 == NULL)
goto err;
@@ -59,38 +59,35 @@ prepare_socket_activation_environment (void)
if (p1 == NULL)
goto err;
- /* Copy the current environment. */
- env = nbd_internal_copy_string_list (environ);
- if (env == NULL)
+ if (string_vector_append (&env, p0) == -1 ||
+ string_vector_append (&env, p1) == -1)
goto err;
- /* Reserve slots env[0] and env[1]. */
- len = nbd_internal_string_list_length (env);
- vp = realloc (env,
- sizeof (char *) * (len + 3)); /* include final NULL entry */
- if (vp == NULL)
- goto err;
- env = vp;
- memmove (&env[2], &env[0], sizeof (char *) * (len + 1));
-
- env[0] = p0; /* Code below assumes env[0] is LISTEN_PID. */
- env[1] = p1;
-
- /* Remove any existing LISTEN_PID or LISTEN_FDS instances. */
- for (i = 2; env[i] != NULL; ++i) {
- if (strncmp (env[i], "LISTEN_PID=", PREFIX_LENGTH) == 0 ||
- strncmp (env[i], "LISTEN_FDS=", PREFIX_LENGTH) == 0) {
- memmove (&env[i], &env[i+1],
- sizeof (char *) * (nbd_internal_string_list_length (&env[i])));
- i--;
+ /* Append the current environment, but remove LISTEN_PID, LISTEN_FDS. */
+ for (i = 0; environ[i] != NULL; ++i) {
+ if (strncmp (environ[i], "LISTEN_PID=", PREFIX_LENGTH) != 0 &&
+ strncmp (environ[i], "LISTEN_FDS=", PREFIX_LENGTH) != 0) {
+ char *copy = strdup (environ[i]);
+ if (copy == NULL)
+ goto err;
+ if (string_vector_append (&env, copy) == -1) {
+ free (copy);
+ goto err;
+ }
}
}
- return env;
+ /* The environ must be NULL-terminated. */
+ if (string_vector_append (&env, NULL) == -1)
+ goto err;
+
+ return env.ptr;
err:
set_error (errno, "malloc");
- nbd_internal_free_string_list (env);
+ for (i = 2; env.ptr[i] != NULL; ++i)
+ free (env.ptr[i]);
+ free (env.ptr);
free (p0);
free (p1);
return NULL;
@@ -105,8 +102,8 @@ STATE_MACHINE {
int flags;
assert (!h->sock);
- assert (h->argv);
- assert (h->argv[0]);
+ assert (h->argv.ptr);
+ assert (h->argv.ptr[0]);
/* Use /tmp instead of TMPDIR because we must ensure the path is
* short enough to store in the sockaddr_un. On some platforms this
@@ -201,8 +198,8 @@ STATE_MACHINE {
signal (SIGPIPE, SIG_DFL);
environ = env;
- execvp (h->argv[0], h->argv);
- nbd_internal_fork_safe_perror (h->argv[0]);
+ execvp (h->argv.ptr[0], h->argv.ptr);
+ nbd_internal_fork_safe_perror (h->argv.ptr[0]);
if (errno == ENOENT)
_exit (127);
else
diff --git a/generator/states-connect.c b/generator/states-connect.c
index 33ae844..392879d 100644
--- a/generator/states-connect.c
+++ b/generator/states-connect.c
@@ -210,8 +210,8 @@ STATE_MACHINE {
int flags;
assert (!h->sock);
- assert (h->argv);
- assert (h->argv[0]);
+ assert (h->argv.ptr);
+ assert (h->argv.ptr[0]);
if (socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sv) == -1) {
SET_NEXT_STATE (%.DEAD);
set_error (errno, "socketpair");
@@ -237,8 +237,8 @@ STATE_MACHINE {
/* Restore SIGPIPE back to SIG_DFL. */
signal (SIGPIPE, SIG_DFL);
- execvp (h->argv[0], h->argv);
- nbd_internal_fork_safe_perror (h->argv[0]);
+ execvp (h->argv.ptr[0], h->argv.ptr);
+ nbd_internal_fork_safe_perror (h->argv.ptr[0]);
if (errno == ENOENT)
_exit (127);
else
diff --git a/generator/states-newstyle-opt-meta-context.c
b/generator/states-newstyle-opt-meta-context.c
index fe82252..bbf155e 100644
--- a/generator/states-newstyle-opt-meta-context.c
+++ b/generator/states-newstyle-opt-meta-context.c
@@ -20,7 +20,7 @@
STATE_MACHINE {
NEWSTYLE.OPT_META_CONTEXT.START:
- size_t i, nr_queries;
+ size_t i;
uint32_t len, opt;
/* If the server doesn't support SRs then we must skip this group.
@@ -38,8 +38,7 @@ STATE_MACHINE {
else {
assert (CALLBACK_IS_NULL (h->opt_cb.fn.context));
opt = NBD_OPT_SET_META_CONTEXT;
- if (!h->structured_replies ||
- nbd_internal_string_list_length (h->request_meta_contexts) == 0) {
+ if (!h->structured_replies || h->request_meta_contexts.size == 0) {
SET_NEXT_STATE (%^OPT_GO.START);
return 0;
}
@@ -49,9 +48,8 @@ STATE_MACHINE {
/* Calculate the length of the option request data. */
len = 4 /* exportname len */ + strlen (h->export_name) + 4 /* nr queries */;
- nr_queries = nbd_internal_string_list_length (h->request_meta_contexts);
- for (i = 0; i < nr_queries; ++i)
- len += 4 /* length of query */ + strlen (h->request_meta_contexts[i]);
+ for (i = 0; i < h->request_meta_contexts.size; ++i)
+ len += 4 /* length of query */ + strlen (h->request_meta_contexts.ptr[i]);
h->sbuf.option.version = htobe64 (NBD_NEW_VERSION);
h->sbuf.option.option = htobe32 (opt);
@@ -89,8 +87,7 @@ STATE_MACHINE {
switch (send_from_wbuf (h)) {
case -1: SET_NEXT_STATE (%.DEAD); return 0;
case 0:
- h->sbuf.nrqueries =
- htobe32 (nbd_internal_string_list_length (h->request_meta_contexts));
+ h->sbuf.nrqueries = htobe32 (h->request_meta_contexts.size);
h->wbuf = &h->sbuf;
h->wlen = sizeof h->sbuf.nrqueries;
h->wflags = MSG_MORE;
@@ -108,13 +105,12 @@ STATE_MACHINE {
return 0;
NEWSTYLE.OPT_META_CONTEXT.PREPARE_NEXT_QUERY:
- const char *query = !h->request_meta_contexts ? NULL
- : h->request_meta_contexts[h->querynum];
-
- if (query == NULL) { /* end of list of requested meta contexts */
+ if (h->querynum >= h->request_meta_contexts.size) {
+ /* end of list of requested meta contexts */
SET_NEXT_STATE (%PREPARE_FOR_REPLY);
return 0;
}
+ const char *query = h->request_meta_contexts.ptr[h->querynum];
h->sbuf.len = htobe32 (strlen (query));
h->wbuf = &h->sbuf.len;
@@ -124,7 +120,7 @@ STATE_MACHINE {
return 0;
NEWSTYLE.OPT_META_CONTEXT.SEND_QUERYLEN:
- const char *query = h->request_meta_contexts[h->querynum];
+ const char *query = h->request_meta_contexts.ptr[h->querynum];
switch (send_from_wbuf (h)) {
case -1: SET_NEXT_STATE (%.DEAD); return 0;
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 9fd6331..968e41a 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -62,6 +62,7 @@ libnbd_la_SOURCES = \
libnbd_la_CPPFLAGS = \
-I$(top_srcdir)/include \
-I$(top_srcdir)/common/include \
+ -I$(top_srcdir)/common/utils \
-Dsysconfdir=\"$(sysconfdir)\" \
$(NULL)
libnbd_la_CFLAGS = \
@@ -71,6 +72,7 @@ libnbd_la_CFLAGS = \
$(LIBXML2_CFLAGS) \
$(NULL)
libnbd_la_LIBADD = \
+ $(top_builddir)/common/utils/libutils.la \
$(GNUTLS_LIBS) \
$(LIBXML2_LIBS) \
$(NULL)
diff --git a/lib/connect.c b/lib/connect.c
index 7e42b14..99781cd 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -249,18 +249,11 @@ nbd_unlocked_aio_connect_socket (struct nbd_handle *h, int sock)
int
nbd_unlocked_aio_connect_command (struct nbd_handle *h, char **argv)
{
- char **copy;
-
- copy = nbd_internal_copy_string_list (argv);
- if (!copy) {
- set_error (errno, "copy_string_list");
+ if (nbd_internal_set_argv (&h->argv, argv) == -1) {
+ set_error (errno, "realloc");
return -1;
}
- if (h->argv)
- nbd_internal_free_string_list (h->argv);
- h->argv = copy;
-
return nbd_internal_run (h, cmd_connect_command);
}
@@ -268,17 +261,10 @@ int
nbd_unlocked_aio_connect_systemd_socket_activation (struct nbd_handle *h,
char **argv)
{
- char **copy;
-
- copy = nbd_internal_copy_string_list (argv);
- if (!copy) {
- set_error (errno, "copy_string_list");
+ if (nbd_internal_set_argv (&h->argv, argv) == -1) {
+ set_error (errno, "realloc");
return -1;
}
- if (h->argv)
- nbd_internal_free_string_list (h->argv);
- h->argv = copy;
-
return nbd_internal_run (h, cmd_connect_sa);
}
diff --git a/lib/crypto.c b/lib/crypto.c
index 516651c..a9b3789 100644
--- a/lib/crypto.c
+++ b/lib/crypto.c
@@ -31,6 +31,7 @@
#endif
#include "internal.h"
+#include "vector.h"
int
nbd_unlocked_set_tls (struct nbd_handle *h, int tls)
@@ -107,11 +108,13 @@ nbd_unlocked_set_tls_username (struct nbd_handle *h, const char
*username)
return 0;
}
+DEFINE_VECTOR_TYPE (string, char)
+
char *
nbd_unlocked_get_tls_username (struct nbd_handle *h)
{
char *s, *ret;
- size_t len;
+ string str = empty_vector;
if (h->tls_username) {
ret = strdup (h->tls_username);
@@ -137,31 +140,22 @@ nbd_unlocked_get_tls_username (struct nbd_handle *h)
return ret;
}
- len = 16;
- ret = NULL;
- while (ret == NULL) {
- char *oldret = ret;
-
- ret = realloc (oldret, len);
- if (ret == NULL) {
- set_error (errno, "realloc");
- free (oldret);
- return NULL;
+ for (;;) {
+ if (getlogin_r (str.ptr, str.alloc) == 0) {
+ return str.ptr;
}
-
- if (getlogin_r (ret, len) != 0) {
- if (errno == ERANGE) {
- /* Try again with a larger buffer. */
- len *= 2;
- continue;
- }
+ else if (errno != ERANGE) {
set_error (errno, "getlogin_r");
- free (ret);
+ free (str.ptr);
+ return NULL;
+ }
+ /* Try again with a larger buffer. */
+ if (string_reserve (&str, str.alloc == 0 ? 16 : str.alloc * 2) == -1) {
+ set_error (errno, "realloc");
+ free (str.ptr);
return NULL;
}
}
-
- return ret;
}
int
diff --git a/lib/handle.c b/lib/handle.c
index 35fe066..841514a 100644
--- a/lib/handle.c
+++ b/lib/handle.c
@@ -129,7 +129,8 @@ nbd_close (struct nbd_handle *h)
free_cmd_list (h->cmds_to_issue);
free_cmd_list (h->cmds_in_flight);
free_cmd_list (h->cmds_done);
- nbd_internal_free_string_list (h->argv);
+ string_vector_iter (&h->argv, (void *) free);
+ free (h->argv.ptr);
if (h->sa_sockpath) {
if (h->pid > 0)
kill (h->pid, SIGTERM);
@@ -153,7 +154,8 @@ nbd_close (struct nbd_handle *h)
free (h->tls_certificates);
free (h->tls_username);
free (h->tls_psk_file);
- nbd_internal_free_string_list (h->request_meta_contexts);
+ string_vector_iter (&h->request_meta_contexts, (void *) free);
+ free (h->request_meta_contexts.ptr);
free (h->hname);
pthread_mutex_destroy (&h->lock);
free (h);
@@ -285,8 +287,6 @@ int
nbd_unlocked_add_meta_context (struct nbd_handle *h, const char *name)
{
char *copy;
- size_t len;
- char **list;
if (strnlen (name, NBD_MAX_STRING + 1) > NBD_MAX_STRING) {
set_error (ENAMETOOLONG, "meta context name too long for NBD protocol");
@@ -298,17 +298,12 @@ nbd_unlocked_add_meta_context (struct nbd_handle *h, const char
*name)
set_error (errno, "strdup");
return -1;
}
- len = nbd_internal_string_list_length (h->request_meta_contexts);
- list = realloc (h->request_meta_contexts,
- sizeof (char *) * (len+2 /* + new entry + NULL */));
- if (list == NULL) {
+
+ if (string_vector_append (&h->request_meta_contexts, copy) == -1) {
free (copy);
set_error (errno, "realloc");
return -1;
}
- h->request_meta_contexts = list;
- list[len] = copy;
- list[len+1] = NULL;
return 0;
}
@@ -316,21 +311,20 @@ nbd_unlocked_add_meta_context (struct nbd_handle *h, const char
*name)
ssize_t
nbd_unlocked_get_nr_meta_contexts (struct nbd_handle *h)
{
- return nbd_internal_string_list_length (h->request_meta_contexts);
+ return h->request_meta_contexts.size;
}
char *
nbd_unlocked_get_meta_context (struct nbd_handle *h, size_t i)
{
- size_t len = nbd_internal_string_list_length (h->request_meta_contexts);
char *ret;
- if (i >= len) {
+ if (i >= h->request_meta_contexts.size) {
set_error (EINVAL, "meta context request out of range");
return NULL;
}
- ret = strdup (h->request_meta_contexts[i]);
+ ret = strdup (h->request_meta_contexts.ptr[i]);
if (ret == NULL)
set_error (errno, "strdup");
@@ -340,8 +334,8 @@ nbd_unlocked_get_meta_context (struct nbd_handle *h, size_t i)
int
nbd_unlocked_clear_meta_contexts (struct nbd_handle *h)
{
- nbd_internal_free_string_list (h->request_meta_contexts);
- h->request_meta_contexts = NULL;
+ string_vector_iter (&h->request_meta_contexts, (void *) free);
+ string_vector_reset (&h->request_meta_contexts);
return 0;
}
diff --git a/lib/internal.h b/lib/internal.h
index ad1eeb9..d4f324e 100644
--- a/lib/internal.h
+++ b/lib/internal.h
@@ -40,6 +40,7 @@
#include "byte-swapping.h"
#include "states.h"
#include "unlocked.h"
+#include "vector.h"
/* Define unlikely macro, but only for GCC. These are used to move
* debug and error handling code out of hot paths, making the hot path
@@ -82,6 +83,8 @@ struct command_cb {
nbd_completion_callback completion;
};
+DEFINE_VECTOR_TYPE (string_vector, char *)
+
struct nbd_handle {
/* Unique name assigned to this handle for debug messages
* (to avoid having to print actual pointers).
@@ -102,7 +105,7 @@ struct nbd_handle {
/* Desired metadata contexts. */
bool request_sr;
- char **request_meta_contexts;
+ string_vector request_meta_contexts;
/* Allowed in URIs, see lib/uri.c. */
uint32_t uri_allow_transports;
@@ -249,7 +252,7 @@ struct nbd_handle {
* the subprocess so we can wait on it when the connection is
* closed.
*/
- char **argv;
+ string_vector argv;
pid_t pid;
/* When using systemd socket activation, this directory and socket
@@ -454,9 +457,8 @@ extern int nbd_internal_aio_get_direction (enum state state);
/* utils.c */
extern void nbd_internal_hexdump (const void *data, size_t len, FILE *fp);
-extern size_t nbd_internal_string_list_length (char **argv);
-extern char **nbd_internal_copy_string_list (char **argv);
extern void nbd_internal_free_string_list (char **argv);
+extern int nbd_internal_set_argv (string_vector *v, char **argv);
extern const char *nbd_internal_fork_safe_itoa (long v, char *buf, size_t len);
extern void nbd_internal_fork_safe_perror (const char *s);
extern char *nbd_internal_printable_buffer (const void *buf, size_t count);
diff --git a/lib/uri.c b/lib/uri.c
index 79e9b41..9f5a290 100644
--- a/lib/uri.c
+++ b/lib/uri.c
@@ -27,6 +27,7 @@
#include <assert.h>
#include "internal.h"
+#include "vector.h"
#ifdef HAVE_LIBXML2
@@ -47,23 +48,24 @@ struct uri_query {
char *value;
};
+DEFINE_VECTOR_TYPE (uri_query_list, struct uri_query)
+
/* Parse the query_raw substring of a URI into a list of decoded queries.
- * Return the length of the list, or -1 on error.
+ * Return 0 on success or -1 on error.
*/
static int
-parse_uri_queries (const char *query_raw, struct uri_query **list)
+parse_uri_queries (const char *query_raw, uri_query_list *list)
{
/* Borrows from libvirt's viruri.c:virURIParseParams() */
const char *end, *eq;
const char *query = query_raw;
- int nqueries = 0;
- struct uri_query *tmp;
+ size_t i;
if (!query || !*query)
return 0;
while (*query) {
- char *name = NULL, *value = NULL;
+ struct uri_query q = {0};
/* Find the next separator, or end of the string. */
end = strchr (query, '&');
@@ -83,14 +85,14 @@ parse_uri_queries (const char *query_raw, struct uri_query **list)
/* If there is no '=' character, then we have just "name"
* and consistent with CGI.pm we assume value is "".
*/
- name = xmlURIUnescapeString (query, end - query, NULL);
- if (!name) goto error;
+ q.name = xmlURIUnescapeString (query, end - query, NULL);
+ if (!q.name) goto error;
} else if (eq+1 == end) {
/* Or if we have "name=" here (works around annoying
* problem when calling xmlURIUnescapeString with len = 0).
*/
- name = xmlURIUnescapeString (query, eq - query, NULL);
- if (!name) goto error;
+ q.name = xmlURIUnescapeString (query, eq - query, NULL);
+ if (!q.name) goto error;
} else if (query == eq) {
/* If the '=' character is at the beginning then we have
* "=value" and consistent with CGI.pm we _ignore_ this.
@@ -98,50 +100,43 @@ parse_uri_queries (const char *query_raw, struct uri_query **list)
goto next;
} else {
/* Otherwise it's "name=value". */
- name = xmlURIUnescapeString (query, eq - query, NULL);
- if (!name)
+ q.name = xmlURIUnescapeString (query, eq - query, NULL);
+ if (!q.name)
goto error;
- value = xmlURIUnescapeString (eq+1, end - (eq+1), NULL);
- if (!value) {
- free (name);
+ q.value = xmlURIUnescapeString (eq+1, end - (eq+1), NULL);
+ if (!q.value) {
+ free (q.name);
goto error;
}
}
- if (!value) {
- value = strdup ("");
- if (!value) {
- free (name);
+ if (!q.value) {
+ q.value = strdup ("");
+ if (!q.value) {
+ free (q.name);
goto error;
}
}
- /* Append to the parameter set. */
- tmp = realloc (*list, sizeof (*tmp) * (nqueries + 1));
- if (tmp == NULL) {
- free (name);
- free (value);
+ /* Append to the list of queries. */
+ if (uri_query_list_append (list, q) == -1) {
+ free (q.name);
+ free (q.value);
goto error;
}
- *list = tmp;
- tmp[nqueries].name = name;
- tmp[nqueries].value = value;
- nqueries++;
next:
query = end;
if (*query) query++; /* skip '&' separator */
}
- return nqueries;
+ return 0;
error:
- tmp = *list;
- while (nqueries-- > 0) {
- free (tmp[nqueries].name);
- free (tmp[nqueries].value);
+ for (i = 0; i < list->size; ++list) {
+ free (list->ptr[i].name);
+ free (list->ptr[i].value);
}
- free (tmp);
- *list = NULL;
+ uri_query_list_reset (list);
return -1;
}
@@ -151,8 +146,7 @@ nbd_unlocked_aio_connect_uri (struct nbd_handle *h, const char
*raw_uri)
xmlURIPtr uri = NULL;
enum { tcp, unix_sock, vsock } transport;
bool tls, socket_required;
- struct uri_query *queries = NULL;
- int nqueries = -1;
+ uri_query_list queries = empty_vector;
int i, r;
int ret = -1;
const char *unixsocket = NULL;
@@ -164,8 +158,7 @@ nbd_unlocked_aio_connect_uri (struct nbd_handle *h, const char
*raw_uri)
set_error (EINVAL, "unable to parse URI: %s", raw_uri);
goto cleanup;
}
- nqueries = parse_uri_queries (uri->query_raw, &queries);
- if (nqueries == -1) {
+ if (parse_uri_queries (uri->query_raw, &queries) == -1) {
set_error (EINVAL, "unable to parse URI queries: %s", uri->query_raw);
goto cleanup;
}
@@ -235,9 +228,9 @@ nbd_unlocked_aio_connect_uri (struct nbd_handle *h, const char
*raw_uri)
}
/* Parse the socket parameter. */
- for (i = 0; i < nqueries; i++) {
- if (strcmp (queries[i].name, "socket") == 0)
- unixsocket = queries[i].value;
+ for (i = 0; i < queries.size; i++) {
+ if (strcmp (queries.ptr[i].name, "socket") == 0)
+ unixsocket = queries.ptr[i].value;
}
if (socket_required && !unixsocket) {
@@ -257,15 +250,15 @@ nbd_unlocked_aio_connect_uri (struct nbd_handle *h, const char
*raw_uri)
goto cleanup;
/* Look for some tls-* parameters. XXX More to come. */
- for (i = 0; i < nqueries; i++) {
- if (strcmp (queries[i].name, "tls-psk-file") == 0) {
+ for (i = 0; i < queries.size; i++) {
+ if (strcmp (queries.ptr[i].name, "tls-psk-file") == 0) {
if (! h->uri_allow_local_file) {
set_error (EPERM,
"local file access (tls-psk-file) is not allowed, "
"call nbd_set_uri_allow_local_file to enable this");
goto cleanup;
}
- if (nbd_unlocked_set_tls_psk_file (h, queries[i].value) == -1)
+ if (nbd_unlocked_set_tls_psk_file (h, queries.ptr[i].value) == -1)
goto cleanup;
}
}
@@ -333,11 +326,11 @@ nbd_unlocked_aio_connect_uri (struct nbd_handle *h, const char
*raw_uri)
ret = 0;
cleanup:
- while (nqueries-- > 0) {
- free (queries[nqueries].name);
- free (queries[nqueries].value);
+ for (i = 0; i < queries.size; ++i) {
+ free (queries.ptr[i].name);
+ free (queries.ptr[i].value);
}
- free (queries);
+ free (queries.ptr);
xmlFreeURI (uri);
return ret;
}
diff --git a/lib/utils.c b/lib/utils.c
index 6e5bdeb..c3f4c4c 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -52,42 +52,25 @@ nbd_internal_hexdump (const void *data, size_t len, FILE *fp)
}
}
-size_t
-nbd_internal_string_list_length (char **argv)
+/* Replace the string_vector with a deep copy of argv (including final NULL). */
+int
+nbd_internal_set_argv (string_vector *v, char **argv)
{
- size_t ret;
+ size_t i;
- if (argv == NULL)
- return 0;
+ string_vector_reset (v);
- for (ret = 0; argv[ret] != NULL; ++ret)
- ;
- return ret;
-}
-
-char **
-nbd_internal_copy_string_list (char **argv)
-{
- size_t i, j, n;
- char **ret;
-
- n = nbd_internal_string_list_length (argv);
- ret = calloc (n+1, sizeof (char *));
- if (!ret)
- return NULL;
-
- for (i = 0; i < n; ++i) {
- ret[i] = strdup (argv[i]);
- if (ret[i] == NULL) {
- for (j = 0; j < i; ++j)
- free (ret[j]);
- free (ret);
- return NULL;
+ for (i = 0; argv[i] != NULL; ++i) {
+ char *copy = strdup (argv[i]);
+ if (copy == NULL)
+ return -1;
+ if (string_vector_append (v, copy) == -1) {
+ free (copy);
+ return -1;
}
}
- ret[n] = NULL;
- return ret;
+ return string_vector_append (v, NULL);
}
void
--
2.29.0.rc2