test-tool: Print FEBOOTSTRAP_* environment variables (RHBZ#671082).
[libguestfs.git] / src / inspect_apps.c
index df99df9..8bd3a02 100644 (file)
@@ -126,119 +126,63 @@ guestfs__inspect_list_applications (guestfs_h *g, const char *root)
 }
 
 #ifdef DB_DUMP
-static struct guestfs_application_list *
-list_applications_rpm (guestfs_h *g, struct inspect_fs *fs)
-{
-  const char *basename = "rpm_Name";
-  char tmpdir_basename[strlen (g->tmpdir) + strlen (basename) + 2];
-  snprintf (tmpdir_basename, sizeof tmpdir_basename, "%s/%s",
-            g->tmpdir, basename);
-
-  if (guestfs___download_to_tmp (g, "/var/lib/rpm/Name", basename,
-                                 MAX_PKG_DB_SIZE) == -1)
-    return NULL;
 
-  struct guestfs_application_list *apps = NULL, *ret = NULL;
-#define cmd_len (strlen (tmpdir_basename) + 64)
-  char cmd[cmd_len];
-  FILE *pp = NULL;
-  char line[1024];
-  size_t len;
+static int
+read_rpm_name (guestfs_h *g,
+               const unsigned char *key, size_t keylen,
+               const unsigned char *value, size_t valuelen,
+               void *appsv)
+{
+  struct guestfs_application_list *apps = appsv;
+  char *name;
 
-  snprintf (cmd, cmd_len, DB_DUMP " -p '%s'", tmpdir_basename);
+  /* The name (key) field won't be NUL-terminated, so we must do that. */
+  name = safe_malloc (g, keylen+1);
+  memcpy (name, key, keylen);
+  name[keylen] = '\0';
 
-  debug (g, "list_applications_rpm: %s", cmd);
+  add_application (g, apps, name, "", 0, "", "", "", "", "", "");
 
-  pp = popen (cmd, "r");
-  if (pp == NULL) {
-    perrorf (g, "popen: %s", cmd);
-    goto out;
-  }
+  free (name);
 
-  /* Ignore everything to end-of-header marker. */
-  for (;;) {
-    if (fgets (line, sizeof line, pp) == NULL) {
-      error (g, _("unexpected end of output from db_dump command"));
-      goto out;
-    }
+  return 0;
+}
 
-    len = strlen (line);
-    if (len > 0 && line[len-1] == '\n') {
-      line[len-1] = '\0';
-      len--;
-    }
+static struct guestfs_application_list *
+list_applications_rpm (guestfs_h *g, struct inspect_fs *fs)
+{
+  char *Name = NULL;
 
-    if (STREQ (line, "HEADER=END"))
-      break;
-  }
+  Name = guestfs___download_to_tmp (g, fs,
+                                    "/var/lib/rpm/Name", "rpm_Name",
+                                    MAX_PKG_DB_SIZE);
+  if (Name == NULL)
+    return NULL;
 
   /* Allocate 'apps' list. */
+  struct guestfs_application_list *apps;
   apps = safe_malloc (g, sizeof *apps);
   apps->len = 0;
   apps->val = NULL;
 
-  /* Read alternate lines until end of data marker. */
-  for (;;) {
-    if (fgets (line, sizeof line, pp) == NULL) {
-      error (g, _("unexpected end of output from db_dump command"));
-      goto out;
-    }
-
-    len = strlen (line);
-    if (len > 0 && line[len-1] == '\n') {
-      line[len-1] = '\0';
-      len--;
-    }
-
-    if (STREQ (line, "DATA=END"))
-      break;
-
-    char *p = line;
-    if (len > 0 && line[0] == ' ')
-      p = line+1;
-    /* Ignore any application name that contains non-printable chars.
-     * In the db_dump output these would be escaped with backslash, so
-     * we can just ignore any such line.
-     */
-    if (strchr (p, '\\') == NULL)
-      add_application (g, apps, p, "", 0, "", "", "", "", "", "");
-
-    /* Discard next line. */
-    if (fgets (line, sizeof line, pp) == NULL) {
-      error (g, _("unexpected end of output from db_dump command"));
-      goto out;
-    }
-  }
-
-  /* Catch errors from the db_dump command. */
-  if (pclose (pp) == -1) {
-    perrorf (g, "pclose: %s", cmd);
-    goto out;
-  }
-  pp = NULL;
-
-  ret = apps;
-
- out:
-  if (ret == NULL && apps != NULL)
+  if (guestfs___read_db_dump (g, Name, apps, read_rpm_name) == -1) {
     guestfs_free_application_list (apps);
-  if (pp)
-    pclose (pp);
+    free (Name);
+    return NULL;
+  }
 
-  return ret;
+  return apps;
 }
+
 #endif /* defined DB_DUMP */
 
 static struct guestfs_application_list *
 list_applications_deb (guestfs_h *g, struct inspect_fs *fs)
 {
-  const char *basename = "deb_status";
-  char tmpdir_basename[strlen (g->tmpdir) + strlen (basename) + 2];
-  snprintf (tmpdir_basename, sizeof tmpdir_basename, "%s/%s",
-            g->tmpdir, basename);
-
-  if (guestfs___download_to_tmp (g, "/var/lib/dpkg/status", basename,
-                                 MAX_PKG_DB_SIZE) == -1)
+  char *status = NULL;
+  status = guestfs___download_to_tmp (g, fs, "/var/lib/dpkg/status", "status",
+                                      MAX_PKG_DB_SIZE);
+  if (status == NULL)
     return NULL;
 
   struct guestfs_application_list *apps = NULL, *ret = NULL;
@@ -248,9 +192,9 @@ list_applications_deb (guestfs_h *g, struct inspect_fs *fs)
   char *name = NULL, *version = NULL, *release = NULL;
   int installed_flag = 0;
 
-  fp = fopen (tmpdir_basename, "r");
+  fp = fopen (status, "r");
   if (fp == NULL) {
-    perrorf (g, "fopen: %s", tmpdir_basename);
+    perrorf (g, "fopen: %s", status);
     goto out;
   }
 
@@ -306,7 +250,7 @@ list_applications_deb (guestfs_h *g, struct inspect_fs *fs)
   }
 
   if (fclose (fp) == -1) {
-    perrorf (g, "fclose: %s", tmpdir_basename);
+    perrorf (g, "fclose: %s", status);
     goto out;
   }
   fp = NULL;
@@ -321,6 +265,7 @@ list_applications_deb (guestfs_h *g, struct inspect_fs *fs)
   free (name);
   free (version);
   free (release);
+  free (status);
   return ret;
 }
 
@@ -329,34 +274,31 @@ static void list_applications_windows_from_path (guestfs_h *g, hive_h *h, struct
 static struct guestfs_application_list *
 list_applications_windows (guestfs_h *g, struct inspect_fs *fs)
 {
-  const char *basename = "software";
-  char tmpdir_basename[strlen (g->tmpdir) + strlen (basename) + 2];
-  snprintf (tmpdir_basename, sizeof tmpdir_basename, "%s/%s",
-            g->tmpdir, basename);
-
   size_t len = strlen (fs->windows_systemroot) + 64;
   char software[len];
   snprintf (software, len, "%s/system32/config/software",
             fs->windows_systemroot);
 
   char *software_path = guestfs___case_sensitive_path_silently (g, software);
-  if (!software_path)
-    /* If the software hive doesn't exist, just accept that we cannot
-     * list windows apps.
-     */
-    return 0;
+  if (!software_path) {
+    /* Missing software hive is a problem. */
+    error (g, "no HKLM\\SOFTWARE hive found in the guest");
+    return NULL;
+  }
 
+  char *software_hive = NULL;
   struct guestfs_application_list *ret = NULL;
   hive_h *h = NULL;
 
-  if (guestfs___download_to_tmp (g, software_path, basename,
-                                 MAX_REGISTRY_SIZE) == -1)
+  software_hive = guestfs___download_to_tmp (g, fs, software_path, "software",
+                                             MAX_REGISTRY_SIZE);
+  if (software_hive == NULL)
     goto out;
 
   free (software_path);
   software_path = NULL;
 
-  h = hivex_open (tmpdir_basename, g->verbose ? HIVEX_OPEN_VERBOSE : 0);
+  h = hivex_open (software_hive, g->verbose ? HIVEX_OPEN_VERBOSE : 0);
   if (h == NULL) {
     perrorf (g, "hivex_open");
     goto out;
@@ -384,6 +326,7 @@ list_applications_windows (guestfs_h *g, struct inspect_fs *fs)
  out:
   if (h) hivex_close (h);
   free (software_path);
+  free (software_hive);
 
   return ret;
 }