[Libguestfs] [PATCH] list-applications: Add support for pacman

Nikos Skalkotos skalkoto at gmail.com
Sun Nov 16 13:24:16 UTC 2014


Extend the guestfs_inspect_list_applications2 API call to work on Arch
Linux guest images.
---
 src/inspect-apps.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 125 insertions(+)

diff --git a/src/inspect-apps.c b/src/inspect-apps.c
index b62b432..b7a3b0e 100644
--- a/src/inspect-apps.c
+++ b/src/inspect-apps.c
@@ -60,6 +60,7 @@
 static struct guestfs_application2_list *list_applications_rpm (guestfs_h *g, struct inspect_fs *fs);
 #endif
 static struct guestfs_application2_list *list_applications_deb (guestfs_h *g, struct inspect_fs *fs);
+static struct guestfs_application2_list *list_applications_pacman (guestfs_h *g, struct inspect_fs *fs);
 static struct guestfs_application2_list *list_applications_windows (guestfs_h *g, struct inspect_fs *fs);
 static void add_application (guestfs_h *g, struct guestfs_application2_list *, const char *name, const char *display_name, int32_t epoch, const char *version, const char *release, const char *arch, const char *install_path, const char *publisher, const char *url, const char *description);
 static void sort_applications (struct guestfs_application2_list *);
@@ -145,6 +146,11 @@ guestfs__inspect_list_applications2 (guestfs_h *g, const char *root)
         break;
 
       case OS_PACKAGE_FORMAT_PACMAN:
+	ret = list_applications_pacman (g, fs);
+	if (ret == NULL)
+	  return NULL;
+	break;
+
       case OS_PACKAGE_FORMAT_EBUILD:
       case OS_PACKAGE_FORMAT_PISI:
       case OS_PACKAGE_FORMAT_PKGSRC:
@@ -494,6 +500,125 @@ list_applications_deb (guestfs_h *g, struct inspect_fs *fs)
   return ret;
 }
 
+static struct guestfs_application2_list *
+list_applications_pacman (guestfs_h *g, struct inspect_fs *fs)
+{
+  CLEANUP_FREE char *desc_file = NULL, *fname = NULL;
+  struct guestfs_application2_list *apps = NULL, *ret = NULL;
+  struct guestfs_dirent *curr = NULL;
+  FILE *fp;
+  char line[1024];
+  size_t i, len;
+  CLEANUP_FREE char *name = NULL, *version = NULL, *desc = NULL;
+  CLEANUP_FREE char *arch = NULL, *url = NULL;
+  char *release = NULL;
+  char **key = NULL;
+  const size_t path_len = strlen ("/var/lib/pacman/local/") + strlen ("/desc");
+  struct guestfs_dirent_list *local_db = NULL;
+
+  local_db = guestfs_readdir (g, "/var/lib/pacman/local");
+  if (local_db == NULL)
+    return NULL;
+
+  /* Allocate 'apps' list. */
+  apps = safe_malloc (g, sizeof *apps);
+  apps->len = 0;
+  apps->val = NULL;
+
+
+  for (i = 0; i < local_db->len; i++) {
+    curr = &local_db->val[i];
+
+    if (curr->ftyp != 'd' || STREQ (curr->name, ".") || STREQ (curr->name, ".."))
+      continue;
+
+    free (fname);
+    fname = safe_malloc (g, strlen (curr->name) + path_len + 1);
+    sprintf (fname, "/var/lib/pacman/local/%s/desc", curr->name);
+    free (desc_file);
+    desc_file = guestfs___download_to_tmp (g, fs, fname, curr->name, 8192);
+
+    /* The desc files are small (4K). If the desc file does not exist, or is
+     * larger than the 8K limit we've used, the database is probably corrupted,
+     * but we'll continue with the next package anyway.
+     */
+    if (desc_file == NULL)
+      continue;
+
+    fp = fopen (desc_file, "r");
+    if (fp == NULL) {
+      perrorf (g, "fopen: %s", desc_file);
+      goto out;
+    }
+
+    while (fgets (line, sizeof line, fp) != NULL) {
+      len = strlen (line);
+      if (len > 0 && line[len-1] == '\n') {
+        line[--len] = '\0';
+      }
+
+      /* empty line */
+      if (len == 0) {
+        key = NULL;
+        continue;
+      }
+
+      if (key != NULL) {
+        *key = safe_strdup (g, line);
+        key = NULL;
+        continue;
+      }
+
+      if (STREQ(line, "%NAME%"))
+        key = &name;
+      else if (STREQ(line, "%VERSION%"))
+        key = &version;
+      else if (STREQ(line, "%DESC%"))
+        key = &desc;
+      else if (STREQ(line, "%URL%"))
+        key = &url;
+      else if (STREQ(line, "%ARCH%"))
+        key = &arch;
+    }
+
+    if (name) {
+      if (version) {
+        char *p = strchr (version, '-');
+        if (p) {
+          *p = '\0';
+          release = p + 1;
+        }
+      }
+      add_application (g, apps, name, "", 0, version ? : "", release ? : "",
+                       arch ? : "", "", "", url ? : "", desc ? : "");
+    }
+
+    free (name);
+    free (version);
+    free (desc);
+    free (arch);
+    free (url);
+    name = version = desc = arch = url = NULL;
+    release = NULL; /* Haven't allocated memory for release */
+
+    if (fclose (fp) == -1) {
+      perrorf (g, "fclose: %s", desc_file);
+      goto out;
+    }
+
+  }
+
+  ret = apps;
+
+  out:
+    guestfs_free_dirent_list (local_db);
+
+    if (ret == NULL)
+      guestfs_free_application2_list (apps);
+
+  return ret;
+}
+
 static void list_applications_windows_from_path (guestfs_h *g, struct guestfs_application2_list *apps, const char **path, size_t path_len);
 
 static struct guestfs_application2_list *
-- 
2.1.3




More information about the Libguestfs mailing list