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

[Libguestfs] [PATCH febootstrap 1/2] helper: Visit directory entries in order.



-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
libguestfs lets you edit virtual machines.  Supports shell scripting,
bindings from many languages.  http://et.redhat.com/~rjones/libguestfs/
See what it can do: http://et.redhat.com/~rjones/libguestfs/recipes.html
>From 6066c3e245a28b55dd1c02d2dd1b524d83068ef3 Mon Sep 17 00:00:00 2001
From: Richard Jones <rjones redhat com>
Date: Fri, 27 Aug 2010 17:03:57 +0100
Subject: [PATCH 1/2] helper: Visit directory entries in order.

Previously in febootstrap-supermin-helper we would visit the
files in supermin.d in arbitrary (ie. readdir) order.  This has
caused a series of heisenbugs where some implicit dependency
between these files has not been honoured.  The latest one is
that '/etc/localtime' can be added to the appliance before '/etc'
has been created (and this operation fails).

Instead of continuing to chase these, this commit forces us to
visit the files in filename order by sorting them before visiting
them.

Note that in libguestfs, the current order is sufficient, because
the files are called:

base.img
daemon.img
hostfiles
---
 helper/appliance.c |   40 +++++++++++++++++++++++++++++++---------
 1 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/helper/appliance.c b/helper/appliance.c
index 4cbebf4..e014b12 100644
--- a/helper/appliance.c
+++ b/helper/appliance.c
@@ -123,27 +123,28 @@ iterate_inputs (char **inputs, int nr_inputs, struct writer *writer)
   }
 }
 
+static int
+string_compare (const void *p1, const void *p2)
+{
+  return strcmp (* (char * const *) p1, * (char * const *) p2);
+}
+
 static void
 iterate_input_directory (const char *dirname, int dirfd, struct writer *writer)
 {
-  char path[PATH_MAX];
-  strcpy (path, dirname);
-  size_t len = strlen (dirname);
-  path[len++] = '/';
-
-  char *inputs[] = { path };
-
   DIR *dir = fdopendir (dirfd);
   if (dir == NULL)
     error (EXIT_FAILURE, errno, "fdopendir: %s", dirname);
 
+  char **entries = NULL;
+  size_t nr_entries = 0, nr_alloc = 0;
+
   struct dirent *d;
   while ((errno = 0, d = readdir (dir)) != NULL) {
     if (d->d_name[0] == '.') /* ignore ., .. and any hidden files. */
       continue;
 
-    strcpy (&path[len], d->d_name);
-    iterate_inputs (inputs, 1, writer);
+    add_string (&entries, &nr_entries, &nr_alloc, d->d_name);
   }
 
   if (errno != 0)
@@ -151,6 +152,27 @@ iterate_input_directory (const char *dirname, int dirfd, struct writer *writer)
 
   if (closedir (dir) == -1)
     error (EXIT_FAILURE, errno, "closedir: %s", dirname);
+
+  add_string (&entries, &nr_entries, &nr_alloc, NULL);
+
+  /* Visit directory entries in order.  In febootstrap <= 2.8 we
+   * didn't impose any order, but that led to some difficult
+   * heisenbugs.
+   */
+  sort (entries, string_compare);
+
+  char path[PATH_MAX];
+  strcpy (path, dirname);
+  size_t len = strlen (dirname);
+  path[len++] = '/';
+
+  char *inputs[] = { path };
+
+  size_t i;
+  for (i = 0; entries[i] != NULL; ++i) {
+    strcpy (&path[len], entries[i]);
+    iterate_inputs (inputs, 1, writer);
+  }
 }
 
 /* Copy kernel modules.
-- 
1.7.1


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