--- generator/actions.ml | 6 ++++++ src/inspect-apps.c | 46 +++++++++++++++++++++++++--------------------- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/generator/actions.ml b/generator/actions.ml index dc71234..afafe9b 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -1527,6 +1527,12 @@ The release string of the application or package, for package managers that use this. If unavailable this is returned as an empty string C<\"\">. +=item C<app_arch> + +The architecture string of the application or package, for package +managers that use this. If unavailable this is returned as an empty +string C<\"\">. + =item C<app_install_path> The installation path of the application (on operating systems diff --git a/src/inspect-apps.c b/src/inspect-apps.c index 3dbfb5b..c8e586f 100644 --- a/src/inspect-apps.c +++ b/src/inspect-apps.c @@ -31,7 +31,6 @@ #ifdef HAVE_ENDIAN_H #include <endian.h> #endif -#include <arpa/inet.h> #include <pcre.h> @@ -126,7 +125,7 @@ guestfs__inspect_list_applications (guestfs_h *g, const char *root) #ifdef DB_DUMP /* This data comes from the Name database, and contains the application - * names and the first 4 bytes of the link field. + * names and the first 4 bytes of each link field. */ struct rpm_names_list { struct rpm_name *names; @@ -162,22 +161,30 @@ read_rpm_name (guestfs_h *g, void *listv) { struct rpm_names_list *list = listv; + const unsigned char *link_p; char *name; /* Ignore bogus entries. */ if (keylen == 0 || valuelen < 4) return 0; - /* 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'; - - list->names = safe_realloc (g, list->names, - (list->len + 1) * sizeof (struct rpm_name)); - list->names[list->len].name = name; - memcpy (list->names[list->len].link, value, 4); - list->len++; + /* A name entry will have as many links as installed instances of + * that pacakge. For example, if glibc.i686 and glibc.x86_64 are + * both installed, then there will be a link for each Packages + * entry. Add an entry onto list for all installed instances. + */ + for (link_p = value; link_p < value + valuelen; link_p += 8) { + /* 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'; + + list->names = safe_realloc (g, list->names, + (list->len + 1) * sizeof (struct rpm_name)); + list->names[list->len].name = name; + memcpy (list->names[list->len].link, link_p, 4); + list->len++; + } return 0; } @@ -199,12 +206,12 @@ get_rpm_header_tag (guestfs_h *g, const void *header_start, size_t header_len, u * http://www.rpm.org/max-rpm/s1-rpm-file-format-rpm-file-format.html#S2-RPM-FI... */ - num_fields = ntohl (*(uint32_t *) header_start); + num_fields = be32toh (*(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)); + while (cursor < store && cursor < header_start + header_len) { + if (be32toh (*(uint32_t *) cursor) == tag){ + offset = be32toh(*(uint32_t *) (cursor + 8)); return safe_strdup(g, store + offset); } cursor += 16; @@ -257,14 +264,11 @@ read_package (guestfs_h *g, /* Add the application and what we know. */ add_application (g, data->apps, entry->name, "", 0, version, release, - arch ? arch : "(none)", "", "", "", ""); + arch ? arch : "", "", "", "", ""); free (version); free (release); - if (arch) - /* arch will occasionally be NULL, because some packages - * (e.g. "gpgkeys") do not have an arch */ - free (arch); + free (arch); return 0; } -- 1.7.11.4