Add TODO file.
[febootstrap.git] / helper / appliance.c
index 4cbebf4..c4d0b32 100644 (file)
@@ -77,6 +77,7 @@ create_appliance (const char *hostcpu,
 
   iterate_inputs (inputs, nr_inputs, writer);
 
+  writer->wr_file ("/lib/modules");
   /* Kernel modules (3). */
   add_kernel_modules (whitelist, modpath, writer);
 
@@ -123,27 +124,33 @@ 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);
+    /* Ignore *~ files created by editors. */
+    size_t len = strlen (d->d_name);
+    if (len > 0 && d->d_name[len-1] == '~')
+      continue;
+
+    add_string (&entries, &nr_entries, &nr_alloc, d->d_name);
   }
 
   if (errno != 0)
@@ -151,6 +158,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.
@@ -169,6 +197,9 @@ static void
 add_kernel_modules (const char *whitelist_file, const char *modpath,
                     struct writer *writer)
 {
+  if (verbose)
+    print_timestamped_message ("adding kernel modules");
+
   char **whitelist = NULL;
   if (whitelist_file != NULL)
     whitelist = load_file (whitelist_file);
@@ -253,7 +284,9 @@ add_hostfiles (const char *hostfiles_file, struct writer *writer)
     if (strchr (hostfile, '*') || strchr (hostfile, '?')) {
       char *dirname = xstrdup (hostfile);
       char *patt = strrchr (dirname, '/');
-      assert (patt);
+      if (!patt)
+        error (EXIT_FAILURE, 0, "%s: line %zu: invalid pattern\n(is this file a supermin appliance hostfiles file?)",
+               hostfiles_file, i+1);
       *patt++ = '\0';
 
       char **files = read_dir (dirname);