[Libguestfs] [PATCH] lib: update inspect_list_applications to return app_arch (RHBZ#859949)

John Eckersberg jeckersb at redhat.com
Mon Oct 15 20:30:24 UTC 2012


(Work in progress)

For now this only works for RPM, the others just return an empty string.
---
 generator/structs.ml |  1 +
 src/inspect-apps.c   | 88 +++++++++++++++++++++++++++++-----------------------
 2 files changed, 51 insertions(+), 38 deletions(-)

diff --git a/generator/structs.ml b/generator/structs.ml
index d62fcc5..8ac9fc5 100644
--- a/generator/structs.ml
+++ b/generator/structs.ml
@@ -183,6 +183,7 @@ let structs = [
     "app_epoch", FInt32;
     "app_version", FString;
     "app_release", FString;
+    "app_arch", FString;
     "app_install_path", FString;
     "app_trans_path", FString;
     "app_publisher", FString;
diff --git a/src/inspect-apps.c b/src/inspect-apps.c
index f65c70a..3dbfb5b 100644
--- a/src/inspect-apps.c
+++ b/src/inspect-apps.c
@@ -31,6 +31,7 @@
 #ifdef HAVE_ENDIAN_H
 #include <endian.h>
 #endif
+#include <arpa/inet.h>
 
 #include <pcre.h>
 
@@ -46,7 +47,7 @@ static struct guestfs_application_list *list_applications_rpm (guestfs_h *g, str
 #endif
 static struct guestfs_application_list *list_applications_deb (guestfs_h *g, struct inspect_fs *fs);
 static struct guestfs_application_list *list_applications_windows (guestfs_h *g, struct inspect_fs *fs);
-static void add_application (guestfs_h *g, struct guestfs_application_list *, const char *name, const char *display_name, int32_t epoch, const char *version, const char *release, const char *install_path, const char *publisher, const char *url, const char *description);
+static void add_application (guestfs_h *g, struct guestfs_application_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_application_list *);
 
 /* Unlike the simple inspect-get-* calls, this one assumes that the
@@ -181,6 +182,37 @@ read_rpm_name (guestfs_h *g,
   return 0;
 }
 
+/* tag constants, see rpmtag.h in RPM for complete list */
+#define RPMTAG_VERSION 1001
+#define RPMTAG_RELEASE 1002
+#define RPMTAG_ARCH    1022
+
+static char *
+get_rpm_header_tag (guestfs_h *g, const void *header_start, size_t header_len, uint32_t tag)
+{
+  uint32_t num_fields, offset;
+  const void *cursor = header_start + 8, *store;
+
+  /* This function parses the RPM header structure to pull out various
+   * tag strings (version, release, arch, etc.).  For more detail on the
+   * header format, see:
+   * http://www.rpm.org/max-rpm/s1-rpm-file-format-rpm-file-format.html#S2-RPM-FILE-FORMAT-HEADER
+   */
+
+  num_fields = ntohl (*(uint32_t *) header_start);
+  store = header_start + 8 + (16 * num_fields);
+
+  while (cursor < store ){
+    if (ntohl (*(uint32_t *) cursor) == tag){
+      offset = ntohl(*(uint32_t *) (cursor + 8));
+      return safe_strdup(g, store + offset);
+    }
+    cursor += 16;
+  }
+
+  return NULL;
+}
+
 struct read_package_data {
   struct rpm_names_list *list;
   struct guestfs_application_list *apps;
@@ -194,16 +226,13 @@ read_package (guestfs_h *g,
 {
   struct read_package_data *data = datav;
   struct rpm_name nkey, *entry;
-  char *p;
-  size_t len;
-  ssize_t max;
-  char *nul_name_nul, *version, *release;
+  char *version, *release, *arch;
 
   /* This function reads one (key, value) pair from the Packages
    * database.  The key is the link field (see struct rpm_name).  The
-   * value is a long binary string, but we can extract the version
-   * number from it as below.  First we have to look up the link field
-   * in the list of links (which is sorted by link field).
+   * value is a long binary string, but we can extract the header data
+   * from it as below.  First we have to look up the link field in the
+   * list of links (which is sorted by link field).
    */
 
   /* Ignore bogus entries. */
@@ -219,41 +248,23 @@ read_package (guestfs_h *g,
 
   /* We found a matching link entry, so that gives us the application
    * name (entry->name).  Now we can get other data for this
-   * application out of the binary value string.  XXX This is a real
-   * hack.
+   * application out of the binary value string.
    */
 
-  /* Look for \0<name>\0 */
-  len = strlen (entry->name);
-  nul_name_nul = safe_malloc (g, len + 2);
-  nul_name_nul[0] = '\0';
-  memcpy (&nul_name_nul[1], entry->name, len);
-  nul_name_nul[len+1] = '\0';
-  p = memmem (value, valuelen, nul_name_nul, len+2);
-  free (nul_name_nul);
-  if (!p)
-    return 0;
-
-  /* Following that are \0-delimited version and release fields. */
-  p += len + 2; /* Note we have to skip \0 + name + \0. */
-  max = valuelen - (p - (char *) value);
-  if (max < 0)
-    max = 0;
-  version = safe_strndup (g, p, max);
-
-  len = strlen (version);
-  p += len + 1;
-  max = valuelen - (p - (char *) value);
-  if (max < 0)
-    max = 0;
-  release = safe_strndup (g, p, max);
+  version = get_rpm_header_tag(g, value, valuelen, RPMTAG_VERSION);
+  release = get_rpm_header_tag(g, value, valuelen, RPMTAG_RELEASE);
+  arch = get_rpm_header_tag(g, value, valuelen, RPMTAG_ARCH);
 
   /* Add the application and what we know. */
   add_application (g, data->apps, entry->name, "", 0, version, release,
-                   "", "", "", "");
+                   arch ? arch : "(none)", "", "", "", "");
 
   free (version);
   free (release);
+  if (arch)
+    /* arch will occasionally be NULL, because some packages
+     * (e.g. "gpgkeys") do not have an arch */
+    free (arch);
 
   return 0;
 }
@@ -378,7 +389,7 @@ list_applications_deb (guestfs_h *g, struct inspect_fs *fs)
     else if (STREQ (line, "")) {
       if (installed_flag && name && version)
         add_application (g, apps, name, "", 0, version, release ? : "",
-                         "", "", "", "");
+                         "", "", "", "", "");
       free (name);
       free (version);
       free (release);
@@ -519,7 +530,7 @@ list_applications_windows_from_path (guestfs_h *g,
 
         add_application (g, apps, name, display_name, 0,
                          version ? : "",
-                         "",
+                         "", "",
                          install_path ? : "",
                          publisher ? : "",
                          url ? : "",
@@ -542,7 +553,7 @@ list_applications_windows_from_path (guestfs_h *g,
 static void
 add_application (guestfs_h *g, struct guestfs_application_list *apps,
                  const char *name, const char *display_name, int32_t epoch,
-                 const char *version, const char *release,
+                 const char *version, const char *release, const char *arch,
                  const char *install_path,
                  const char *publisher, const char *url,
                  const char *description)
@@ -555,6 +566,7 @@ add_application (guestfs_h *g, struct guestfs_application_list *apps,
   apps->val[apps->len-1].app_epoch = epoch;
   apps->val[apps->len-1].app_version = safe_strdup (g, version);
   apps->val[apps->len-1].app_release = safe_strdup (g, release);
+  apps->val[apps->len-1].app_arch = safe_strdup (g, arch);
   apps->val[apps->len-1].app_install_path = safe_strdup (g, install_path);
   /* XXX Translated path is not implemented yet. */
   apps->val[apps->len-1].app_trans_path = safe_strdup (g, "");
-- 
1.7.11.4




More information about the Libguestfs mailing list