[Libguestfs] [PATCH nbdkit 2/9] floppy, iso, split, ssh: Use new vector type to store lists of strings.

Richard W.M. Jones
Wed, 15 Apr 2020 16:16:43 -0000

These plugins have in common that they store either a list of
allocated strings or a list of constant strings.  Define either
string_vector or const_string_vector as appropriate and use it to
store these lists.
---
 plugins/iso/Makefile.am         |  1 +
 plugins/split/Makefile.am       |  1 +
 plugins/floppy/virtual-floppy.h |  7 +++--
 plugins/floppy/directory-lfn.c  | 35 +++++++++-------------
 plugins/floppy/virtual-floppy.c | 11 +++----
 plugins/iso/iso.c               | 25 ++++++----------
 plugins/split/split.c           | 51 +++++++++++++++------------------
 plugins/ssh/ssh.c               | 24 +++++++---------
 8 files changed, 69 insertions(+), 86 deletions(-)

diff --git a/plugins/iso/Makefile.am b/plugins/iso/Makefile.am
index a0fd337a..d20e1768 100644
--- a/plugins/iso/Makefile.am
+++ b/plugins/iso/Makefile.am
@@ -43,6 +43,7 @@ nbdkit_iso_plugin_la_SOURCES = \
 	$(NULL)

 nbdkit_iso_plugin_la_CPPFLAGS = \
+	-I$(top_srcdir)/common/include \
 	-I$(top_srcdir)/common/utils \
 	-I$(top_srcdir)/include \
 	-I. \
diff --git a/plugins/split/Makefile.am b/plugins/split/Makefile.am
index d8218b9a..14af56f1 100644
--- a/plugins/split/Makefile.am
+++ b/plugins/split/Makefile.am
@@ -42,6 +42,7 @@ nbdkit_split_plugin_la_SOURCES = \

 nbdkit_split_plugin_la_CPPFLAGS = \
 	-I$(top_srcdir)/include \
+	-I$(top_srcdir)/common/include \
 	-I$(top_srcdir)/common/utils \
 	$(NULL)
 nbdkit_split_plugin_la_CFLAGS = $(WARNINGS_CFLAGS)
diff --git a/plugins/floppy/virtual-floppy.h b/plugins/floppy/virtual-floppy.h
index 9617d386..30643df4 100644
--- a/plugins/floppy/virtual-floppy.h
+++ b/plugins/floppy/virtual-floppy.h
@@ -37,6 +37,7 @@
 #include <sys/stat.h>

 #include "regions.h"
+#include "vector.h"

 struct partition_entry {
   uint8_t bootable;             /* 0x00 or 0x80 if bootable */
@@ -130,6 +131,9 @@ struct dir_entry {
   uint32_t size;                /* 0x1C - file size */
 } __attribute__((packed));

+/* Appendable list of struct dir_entry. */
+DEFINE_VECTOR_TYPE(dir_entries, struct dir_entry);
+
 /* On disk directory entry (LFN). */
 struct lfn_entry {
   uint8_t seq;                  /* sequence number */
@@ -162,8 +166,7 @@ struct dir {
   size_t nr_files;

   /* On disk directory table. */
-  struct dir_entry *table;
-  size_t table_entries;
+  dir_entries table;
 };

 struct virtual_floppy {
diff --git a/plugins/floppy/directory-lfn.c b/plugins/floppy/directory-lfn.c
index 10caf84b..e06680e9 100644
--- a/plugins/floppy/directory-lfn.c
+++ b/plugins/floppy/directory-lfn.c
@@ -71,7 +71,7 @@ static void set_times (const struct stat *statbuf, struct
dir_entry *entry);
 static int convert_long_file_names (struct lfn *lfns, size_t n);
 static int convert_to_utf16le (const char *name, char **out, size_t
*output_len);
 static void free_lfns (struct lfn *lfns, size_t n);
-static ssize_t extend_dir_table (size_t di, struct virtual_floppy *floppy);
+static ssize_t append_dir_table (size_t di, const struct dir_entry *entry,
struct virtual_floppy *floppy);

 /* Create the on disk directory table for dirs[di]. */
 int
@@ -178,10 +178,9 @@ add_volume_label (const char *label, size_t di, struct
virtual_floppy *floppy)
   pad_string (label, 11, entry.name);
   entry.attributes = DIR_ENTRY_VOLUME_LABEL; /* Same as dosfstools. */

-  i = extend_dir_table (di, floppy);
+  i = append_dir_table (di, &entry, floppy);
   if (i == -1)
     return -1;
-  floppy->dirs[di].table[i] = entry;
   return 0;
 }

@@ -199,10 +198,9 @@ add_dot_entries (size_t di, struct virtual_floppy *floppy)
   entry.attributes = DIR_ENTRY_SUBDIRECTORY;
   set_times (&floppy->dirs[di].statbuf, &entry);

-  i = extend_dir_table (di, floppy);
+  i = append_dir_table (di, &entry, floppy);
   if (i == -1)
     return -1;
-  floppy->dirs[di].table[i] = entry;

   memset (&entry, 0, sizeof entry);
   pad_string ("..", 11, entry.name);
@@ -210,10 +208,9 @@ add_dot_entries (size_t di, struct virtual_floppy *floppy)
   pdi = floppy->dirs[di].pdi;
   set_times (&floppy->dirs[pdi].statbuf, &entry);

-  i = extend_dir_table (di, floppy);
+  i = append_dir_table (di, &entry, floppy);
   if (i == -1)
     return -1;
-  floppy->dirs[di].table[i] = entry;

   return 0;
 }
@@ -288,10 +285,9 @@ add_directory_entry (const struct lfn *lfn,
     memcpy (lfn_entry.name2, &s[5], 6*2);
     memcpy (lfn_entry.name3, &s[11], 2*2);

-    i = extend_dir_table (di, floppy);
+    i = append_dir_table (di, (const struct dir_entry *) &lfn_entry,
floppy);
     if (i == -1)
       return -1;
-    memcpy (&floppy->dirs[di].table[i], &lfn_entry, sizeof (struct
dir_entry));
   }

   /* Create the 8.3 (short name / DOS-compatible) entry. */
@@ -305,10 +301,9 @@ add_directory_entry (const struct lfn *lfn,
    * update_directory_first_cluster.
    */

-  i = extend_dir_table (di, floppy);
+  i = append_dir_table (di, &entry, floppy);
   if (i == -1)
     return -1;
-  floppy->dirs[di].table[i] = entry;

   return 0;
 }
@@ -530,22 +525,18 @@ free_lfns (struct lfn *lfns, size_t n)
   free (lfns);
 }

-/* Extend dirs[di].table by 1 directory entry. */
+/* Append entry to dirs[di].table.  Returns the index of the new entry. */
 static ssize_t
-extend_dir_table (size_t di, struct virtual_floppy *floppy)
+append_dir_table (size_t di, const struct dir_entry *entry,
+                  struct virtual_floppy *floppy)
 {
-  struct dir_entry *p;
   size_t i;

-  i = floppy->dirs[di].table_entries;
-  p = realloc (floppy->dirs[di].table, sizeof (struct dir_entry) * (i+1));
-  if (p == NULL) {
+  i = floppy->dirs[di].table.size;
+  if (dir_entries_append (&floppy->dirs[di].table, *entry) == -1) {
     nbdkit_error ("realloc: %m");
     return -1;
   }
-  floppy->dirs[di].table = p;
-  floppy->dirs[di].table_entries++;
-  memset (&floppy->dirs[di].table[i], 0, sizeof (struct dir_entry));
   return i;
 }

@@ -570,8 +561,8 @@ update_directory_first_cluster (size_t di, struct
virtual_floppy *floppy)
    * table entries.
    */
   i = 0;
-  for (j = 0; j < floppy->dirs[di].table_entries; ++j) {
-    entry = &floppy->dirs[di].table[j];
+  for (j = 0; j < floppy->dirs[di].table.size; ++j) {
+    entry = &floppy->dirs[di].table.ptr[j];

     /* Skip LFN entries. */
     if (entry->attributes == 0xf)
diff --git a/plugins/floppy/virtual-floppy.c b/plugins/floppy/virtual-floppy.c
index fc0cafa8..ad192976 100644
--- a/plugins/floppy/virtual-floppy.c
+++ b/plugins/floppy/virtual-floppy.c
@@ -117,7 +117,7 @@ create_virtual_floppy (const char *dir, const char *label,
   for (i = 0; i < floppy->nr_dirs; ++i) {
     floppy->dirs[i].first_cluster = cluster;
     nr_bytes -      ROUND_UP (floppy->dirs[i].table_entries * sizeof (struct
dir_entry),
+      ROUND_UP (floppy->dirs[i].table.size * sizeof (struct dir_entry),
                 CLUSTER_SIZE);
     floppy->data_size += nr_bytes;
     nr_clusters = nr_bytes / CLUSTER_SIZE;
@@ -221,7 +221,7 @@ free_virtual_floppy (struct virtual_floppy *floppy)
     free (floppy->dirs[i].name);
     free (floppy->dirs[i].subdirs);
     free (floppy->dirs[i].files);
-    free (floppy->dirs[i].table);
+    free (floppy->dirs[i].table.ptr);
   }
   free (floppy->dirs);
 }
@@ -677,14 +677,15 @@ create_regions (struct virtual_floppy *floppy)
     /* Directories can never be completely empty because of the volume
      * label (root) or "." and ".." entries (non-root).
      */
-    assert (floppy->dirs[i].table_entries > 0);
+    assert (floppy->dirs[i].table.size > 0);

     if (append_region_len (&floppy->regions,
                            i == 0 ? "root directory" :
floppy->dirs[i].name,
-                           floppy->dirs[i].table_entries *
+                           floppy->dirs[i].table.size *
                            sizeof (struct dir_entry),
                            0, CLUSTER_SIZE,
-                           region_data, (void *) floppy->dirs[i].table) ==
-1)
+                           region_data,
+                           (void *) floppy->dirs[i].table.ptr) == -1)
       return -1;
   }

diff --git a/plugins/iso/iso.c b/plugins/iso/iso.c
index 92554ace..733bcb60 100644
--- a/plugins/iso/iso.c
+++ b/plugins/iso/iso.c
@@ -43,10 +43,11 @@

 #include "cleanup.h"
 #include "utils.h"
+#include "vector.h"

 /* List of directories parsed from the command line. */
-static char **dirs = NULL;
-static size_t nr_dirs = 0;
+DEFINE_VECTOR_TYPE(string_vector, char *);
+static string_vector dirs = empty_vector;

 /* genisoimage or mkisofs program, picked at compile time, but can be
  * overridden at run time.
@@ -98,9 +99,9 @@ make_iso (void)
   fprintf (fp, " -quiet");
   if (params)
     fprintf (fp, " %s", params);
-  for (i = 0; i < nr_dirs; ++i) {
+  for (i = 0; i < dirs.size; ++i) {
     fputc (' ', fp);
-    shell_quote (dirs[i], fp);
+    shell_quote (dirs.ptr[i], fp);
   }
   /* Redirect output to the temporary file. */
   fprintf (fp, " >&%d", fd);
@@ -122,11 +123,8 @@ make_iso (void)
 static void
 iso_unload (void)
 {
-  size_t i;
-
-  for (i = 0; i < nr_dirs; ++i)
-    free (dirs[i]);
-  free (dirs);
+  string_vector_iter (&dirs, (void *) free);
+  free (dirs.ptr);

   if (fd >= 0)
     close (fd);
@@ -135,7 +133,6 @@ iso_unload (void)
 static int
 iso_config (const char *key, const char *value)
 {
-  char **new_dirs;
   char *dir;

   if (strcmp (key, "dir") == 0) {
@@ -143,15 +140,11 @@ iso_config (const char *key, const char *value)
     if (dir == NULL)
       return -1;

-    new_dirs = realloc (dirs, sizeof (char *) * (nr_dirs + 1));
-    if (new_dirs == NULL) {
+    if (string_vector_append (&dirs, dir) == -1) {
       nbdkit_error ("realloc: %m");
       free (dir);
       return -1;
     }
-    dirs = new_dirs;
-    dirs[nr_dirs] = dir;
-    nr_dirs++;
   }
   else if (strcmp (key, "params") == 0) {
     params = value;
@@ -170,7 +163,7 @@ iso_config (const char *key, const char *value)
 static int
 iso_config_complete (void)
 {
-  if (nr_dirs == 0) {
+  if (dirs.size == 0) {
     nbdkit_error ("you must supply the dir=<DIRECTORY> parameter
"
                   "after the plugin name on the command line");
     return -1;
diff --git a/plugins/split/split.c b/plugins/split/split.c
index 70fd4d40..a12b1037 100644
--- a/plugins/split/split.c
+++ b/plugins/split/split.c
@@ -47,10 +47,11 @@
 #include <nbdkit-plugin.h>

 #include "cleanup.h"
+#include "vector.h"

 /* The files. */
-static char **filenames = NULL;
-static size_t nr_files = 0;
+DEFINE_VECTOR_TYPE(string_vector, char *);
+static string_vector filenames = empty_vector;

 /* Any callbacks using lseek must be protected by this lock. */
 static pthread_mutex_t lseek_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -58,29 +59,23 @@ static pthread_mutex_t lseek_lock =
PTHREAD_MUTEX_INITIALIZER;
 static void
 split_unload (void)
 {
-  size_t i;
-
-  for (i = 0; i < nr_files; ++i)
-    free (filenames[i]);
-  free (filenames);
+  string_vector_iter (&filenames, (void *) free);
+  free (filenames.ptr);
 }

 static int
 split_config (const char *key, const char *value)
 {
-  char **new_filenames;
+  char *s;

   if (strcmp (key, "file") == 0) {
-    new_filenames = realloc (filenames, (nr_files+1) * sizeof (char *));
-    if (new_filenames == NULL) {
-      nbdkit_error ("malloc: %m");
+    s = nbdkit_realpath (value);
+    if (s == NULL)
+      return -1;
+    if (string_vector_append (&filenames, s) == -1) {
+      nbdkit_error ("realloc: %m");
       return -1;
     }
-    filenames = new_filenames;
-    filenames[nr_files] = nbdkit_realpath (value);
-    if (filenames[nr_files] == NULL)
-      return -1;
-    nr_files++;
   }
   else {
     nbdkit_error ("unknown parameter '%s'", key);
@@ -122,13 +117,13 @@ split_open (int readonly)
     return NULL;
   }

-  h->files = malloc (nr_files * sizeof (struct file));
+  h->files = malloc (filenames.size * sizeof (struct file));
   if (h->files == NULL) {
     nbdkit_error ("malloc: %m");
     free (h);
     return NULL;
   }
-  for (i = 0; i < nr_files; ++i)
+  for (i = 0; i < filenames.size; ++i)
     h->files[i].fd = -1;

   /* Open the files. */
@@ -138,34 +133,34 @@ split_open (int readonly)
   else
     flags |= O_RDWR;

-  for (i = 0; i < nr_files; ++i) {
-    h->files[i].fd = open (filenames[i], flags);
+  for (i = 0; i < filenames.size; ++i) {
+    h->files[i].fd = open (filenames.ptr[i], flags);
     if (h->files[i].fd == -1) {
-      nbdkit_error ("open: %s: %m", filenames[i]);
+      nbdkit_error ("open: %s: %m", filenames.ptr[i]);
       goto err;
     }
   }

   offset = 0;
-  for (i = 0; i < nr_files; ++i) {
+  for (i = 0; i < filenames.size; ++i) {
     h->files[i].offset = offset;

     if (fstat (h->files[i].fd, &statbuf) == -1) {
-      nbdkit_error ("stat: %s: %m", filenames[i]);
+      nbdkit_error ("stat: %s: %m", filenames.ptr[i]);
       goto err;
     }
     h->files[i].size = statbuf.st_size;
     offset += statbuf.st_size;

     nbdkit_debug ("file[%zu]=%s: offset=%" PRIu64 ",
size=%" PRIu64,
-                  i, filenames[i], h->files[i].offset, h->files[i].size);
+                  i, filenames.ptr[i], h->files[i].offset,
h->files[i].size);

 #ifdef SEEK_HOLE
     /* Test if this file supports extents. */
     ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&lseek_lock);
     r = lseek (h->files[i].fd, 0, SEEK_DATA);
     if (r == -1 && errno != ENXIO) {
-      nbdkit_debug ("disabling extents: lseek on %s: %m",
filenames[i]);
+      nbdkit_debug ("disabling extents: lseek on %s: %m",
filenames.ptr[i]);
       h->files[i].can_extents = false;
     }
     else
@@ -180,7 +175,7 @@ split_open (int readonly)
   return h;

  err:
-  for (i = 0; i < nr_files; ++i) {
+  for (i = 0; i < filenames.size; ++i) {
     if (h->files[i].fd >= 0)
       close (h->files[i].fd);
   }
@@ -196,7 +191,7 @@ split_close (void *handle)
   struct handle *h = handle;
   size_t i;

-  for (i = 0; i < nr_files; ++i)
+  for (i = 0; i < filenames.size; ++i)
     close (h->files[i].fd);
   free (h->files);
   free (h);
@@ -243,7 +238,7 @@ static struct file *
 get_file (struct handle *h, uint64_t offset)
 {
   return bsearch (&offset, h->files,
-                  nr_files, sizeof (struct file),
+                  filenames.size, sizeof (struct file),
                   compare_offset);
 }

diff --git a/plugins/ssh/ssh.c b/plugins/ssh/ssh.c
index 1fd5f223..ce91ab3f 100644
--- a/plugins/ssh/ssh.c
+++ b/plugins/ssh/ssh.c
@@ -50,6 +50,9 @@
 #include <nbdkit-plugin.h>

 #include "minmax.h"
+#include "vector.h"
+
+DEFINE_VECTOR_TYPE(const_string_vector, const char *);

 static const char *host = NULL;
 static const char *path = NULL;
@@ -58,8 +61,7 @@ static const char *user = NULL;
 static char *password = NULL;
 static bool verify_remote_host = true;
 static const char *known_hosts = NULL;
-static const char **identity = NULL;
-static size_t nr_identities = 0;
+static const_string_vector identities = empty_vector;
 static uint32_t timeout = 0;
 static bool compression = false;

@@ -98,7 +100,7 @@ log_callback (int priority, const char *function, const char
*message, void *vp)
 static void
 ssh_unload (void)
 {
-  free (identity);
+  free (identities.ptr);
   free (password);
 }

@@ -133,16 +135,11 @@ ssh_config (const char *key, const char *value)
     known_hosts = value; /* %-expanded, cannot use nbdkit_absolute_path */

   else if (strcmp (key, "identity") == 0) {
-    const char **new_identity -      realloc (identity, (nr_identities+1) *
sizeof (const char *));
-    if (new_identity == NULL) {
+    /* %-expanded, cannot use nbdkit_absolute_path on value */
+    if (const_string_vector_append (&identities, value) == -1) {
       nbdkit_error ("realloc: %m");
       return -1;
     }
-    identity = new_identity;
-    /* %-expanded, cannot use nbdkit_absolute_path */
-    identity[nr_identities] = value;
-    nr_identities++;
   }

   else if (strcmp (key, "verify-remote-host") == 0) {
@@ -410,11 +407,12 @@ ssh_open (int readonly)
      * as this file is rarely present.
      */
   }
-  for (i = 0; i < nr_identities; ++i) {
-    r = ssh_options_set (h->session, SSH_OPTIONS_ADD_IDENTITY, identity[i]);
+  for (i = 0; i < identities.size; ++i) {
+    r = ssh_options_set (h->session,
+                         SSH_OPTIONS_ADD_IDENTITY, identities.ptr[i]);
     if (r != SSH_OK) {
       nbdkit_error ("failed to add identity in libssh session: %s:
%s",
-                    identity[i], ssh_get_error (h->session));
+                    identities.ptr[i], ssh_get_error (h->session));
       goto err;
     }
   }
--
2.25.0