[Libguestfs] [PATCH] inspect: list applications with APK

Pino Toscano ptoscano at redhat.com
Mon Mar 7 16:25:57 UTC 2016


Implement the helper function for guestfs_inspect_list_applications2 to
be able to parse the list of installed applications with the APK package
manager (used on Alpine Linux).
---
 src/inspect-apps.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 121 insertions(+)

diff --git a/src/inspect-apps.c b/src/inspect-apps.c
index b54cf07..78c32bf 100644
--- a/src/inspect-apps.c
+++ b/src/inspect-apps.c
@@ -49,6 +49,7 @@ static struct guestfs_application2_list *list_applications_rpm (guestfs_h *g, st
 #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_apk (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 *);
@@ -140,6 +141,11 @@ guestfs_impl_inspect_list_applications2 (guestfs_h *g, const char *root)
 	break;
 
       case OS_PACKAGE_FORMAT_APK:
+        ret = list_applications_apk (g, fs);
+        if (ret == NULL)
+          return NULL;
+        break;
+
       case OS_PACKAGE_FORMAT_EBUILD:
       case OS_PACKAGE_FORMAT_PISI:
       case OS_PACKAGE_FORMAT_PKGSRC:
@@ -655,6 +661,121 @@ list_applications_pacman (guestfs_h *g, struct inspect_fs *fs)
   return ret;
 }
 
+static struct guestfs_application2_list *
+list_applications_apk (guestfs_h *g, struct inspect_fs *fs)
+{
+  CLEANUP_FREE char *installed = NULL, *line = NULL;
+  struct guestfs_application2_list *apps = NULL, *ret = NULL;
+  FILE *fp;
+  size_t allocsize = 0;
+  ssize_t len;
+  int32_t epoch = 0;
+  CLEANUP_FREE char *name = NULL, *version = NULL, *release = NULL, *arch = NULL,
+    *url = NULL, *description = NULL;
+
+  installed = guestfs_int_download_to_tmp (g, fs, "/lib/apk/db/installed",
+                                           "installed", MAX_PKG_DB_SIZE);
+  if (installed == NULL)
+    return NULL;
+
+  fp = fopen (installed, "r");
+  if (fp == NULL) {
+    perrorf (g, "fopen: %s", installed);
+    goto out;
+  }
+
+  /* Allocate 'apps' list. */
+  apps = safe_malloc (g, sizeof *apps);
+  apps->len = 0;
+  apps->val = NULL;
+
+  /* Read the temporary file.  Each package entry is separated by
+   * a blank line.  Each package line is <character>:<field>.
+   */
+  while ((len = getline (&line, &allocsize, fp)) != -1) {
+    if (len > 0 && line[len-1] == '\n') {
+      line[len-1] = '\0';
+      --len;
+    }
+
+    if (len > 1 && line[1] != ':') {
+      /* Invalid line format.  Should we fail instead? */
+      continue;
+    }
+
+    switch (line[0]) {
+    case '\0':
+      if (name && version && (epoch >= 0))
+        add_application (g, apps, name, "", epoch, version, release ? : "",
+                         arch ? : "", "", "", url ? : "", description ? : "");
+      free (name);
+      free (version);
+      free (release);
+      free (arch);
+      free (url);
+      free (description);
+      name = version = release = arch = url = description = NULL;
+      break;
+    case 'A':
+      free (arch);
+      arch = safe_strdup (g, &line[2]);
+      break;
+    case 'P':
+      free (name);
+      name = safe_strdup (g, &line[2]);
+      break;
+    case 'T':
+      free (description);
+      description = safe_strdup (g, &line[2]);
+      break;
+    case 'U':
+      free (url);
+      url = safe_strdup (g, &line[2]);
+      break;
+    case 'V':
+      free (version);
+      free (release);
+      char *p1, *p2;
+      p1 = strchr (&line[2], ':');
+      if (p1) {
+        *p1++ = '\0';
+        epoch = guestfs_int_parse_unsigned_int (g, &line[2]); /* -1 on error */
+      } else {
+        p1 = &line[2];
+        epoch = 0;
+      }
+      p2 = strchr (p1, '-');
+      if (p2) {
+        *p2++ = '\0';
+        /* Skip the leading 'r' in revisions. */
+        if (p2[0] == 'r')
+          ++p2;
+        release = safe_strdup (g, p2);
+      } else {
+        release = NULL;
+      }
+      version = safe_strdup (g, p1);
+      break;
+    }
+  }
+
+  if (fclose (fp) == -1) {
+    perrorf (g, "fclose: %s", installed);
+    goto out;
+  }
+
+  ret = apps;
+
+ out:
+  if (ret == NULL)
+    guestfs_free_application2_list (apps);
+  /*
+  if (fp)
+    fclose (fp);
+  */
+  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.5.0




More information about the Libguestfs mailing list