summaryrefslogtreecommitdiffstats
path: root/helper
diff options
context:
space:
mode:
authorRichard Jones <rjones@redhat.com>2010-08-27 17:03:57 +0100
committerRichard Jones <rjones@redhat.com>2010-08-27 17:08:44 +0100
commit6066c3e245a28b55dd1c02d2dd1b524d83068ef3 (patch)
tree57035b10623d2b5150f5198c99d215af058a7cfb /helper
parent8e6a3ac4051e639b9ef17c4049e6cc11dab1bc76 (diff)
downloadfebootstrap-6066c3e245a28b55dd1c02d2dd1b524d83068ef3.tar.gz
febootstrap-6066c3e245a28b55dd1c02d2dd1b524d83068ef3.tar.xz
febootstrap-6066c3e245a28b55dd1c02d2dd1b524d83068ef3.zip
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
Diffstat (limited to 'helper')
-rw-r--r--helper/appliance.c40
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.