Add own implementation of getting rpm packages info 82/184382/4
authorMateusz Moscicki <m.moscicki2@partner.samsung.com>
Tue, 17 Jul 2018 11:43:39 +0000 (13:43 +0200)
committerMateusz Moscicki <m.moscicki2@partner.samsung.com>
Thu, 19 Jul 2018 10:00:56 +0000 (12:00 +0200)
Calling the external rpm command is too slow, especially for binaries
with many shared object dependencies.

Change-Id: I48a86c0a0067bb2d37b7b7a12abae5d611c8b572

packaging/crash-worker.spec
src/crash-manager/CMakeLists.txt
src/crash-manager/so-info.c

index 7177835..773c552 100644 (file)
@@ -21,6 +21,7 @@ BuildRequires:  pkgconfig(libtzplatform-config)
 BuildRequires:  pkgconfig(iniparser)
 BuildRequires:  pkgconfig(capi-system-info)
 BuildRequires:  pkgconfig(glib-2.0)
+BuildRequires:  pkgconfig(rpm)
 BuildRequires:  cmake
 
 BuildRequires:  pkgconfig(libunwind-ptrace)
index d95e846..5fe5b19 100644 (file)
@@ -26,6 +26,7 @@ pkg_check_modules(crash-manager_pkgs REQUIRED
        libtzplatform-config
        iniparser
        gio-2.0
+       rpm
        )
 
 FOREACH(flag ${crash-manager_pkgs_CFLAGS})
index 0ef0bc7..53ad1fe 100644 (file)
 #include <stdarg.h>
 #include <unistd.h>
 #include <glib.h>
+#include <rpm/rpmdb.h>
+#include <rpm/rpmts.h>
+#include <rpm/rpmlib.h>
+#include <rpm/header.h>
 #include "shared/log.h"
 #include "shared/util.h"
 
 #define BID_SNAME ".note.gnu.build-id"
 
-#define CMD_RPM "rpm -qf %s --qf '%%{NAME};%%{VERSION};%%{RELEASE};%%{ARCH}'"
-#define CMD_RPM_LEN sizeof(CMD_RPM)
-
-#define RPM_INFO_MAXLEN PATH_MAX
-
 
 static unsigned char *map_file(const char *filename, int64_t *size)
 {
@@ -219,33 +218,81 @@ GSList* get_filepaths(char *map_path)
        return file_list;
 }
 
-int get_rpm_info(char *filename, char *rpm_info)
+rpmts init_rpm()
 {
-       if (!filename) {
-               _E("Invalid filename");
-               return -1;
+       rpmts ts = rpmtsCreate();
+       if (rpmReadConfigFiles(NULL, NULL) < 0) {
+               _E("rpmReadConfigFiles failed\n");
+               rpmtsFree(ts);
+               return NULL;
+       }
+       return ts;
+}
+
+void free_rpm(rpmts ts)
+{
+       if (ts != NULL) {
+               rpmtsFree(ts);
+               rpmFreeRpmrc();
        }
+}
 
-       char *args[] = {"rpm", "-qf", filename, "--qf", "%{NAME};%{VERSION};%{RELEASE};%{ARCH}", NULL};
+char* get_rpm_info_as_string(Header h)
+{
+       const char *name, *version, *release, *arch;
 
-       int readed;
-       if ((readed = run_command_write_fd_timeout("rpm", args, NULL, 0, rpm_info, RPM_INFO_MAXLEN, 60)) < 0) {
-               _E("Failed to get information about rpm installed packages");
-               return -1;
-       } else {
-               rpm_info[readed] = 0;
+       name = headerGetString(h, RPMTAG_NAME);
+       version = headerGetString(h, RPMTAG_VERSION);
+       release = headerGetString(h, RPMTAG_RELEASE);
+       arch = headerGetString(h, RPMTAG_ARCH);
+
+       int info_len = strlen(name) + strlen(version) +
+                                  strlen(release) + strlen(arch) + 3;
+
+       char *res = (char *)malloc(info_len + 1);
+       if (res == NULL) {
+               _E("Failed to allocate memory: %m");
+               return NULL;
        }
+       snprintf(res, info_len, "%s;%s;%s;%s", name, version, release, arch);
 
-       return 0;
+       return res;
+}
+
+char* get_rpm_info(rpmts ts, const char* filename)
+{
+       char *rpm_info = NULL;
+
+       if (ts == NULL)
+               return NULL;
+
+       rpmdbMatchIterator mi = rpmtsInitIterator(ts, RPMDBI_INSTFILENAMES, filename, 0);
+       if (mi == NULL) {
+               _E("Not found RPM package for %s\n", filename);
+               return NULL;
+       }
+
+       Header h = rpmdbNextIterator(mi);
+
+       if (h != NULL)
+               rpm_info = get_rpm_info_as_string(h);
+       else {
+               _E("rpmdbNextIterator error\n");
+               rpm_info = NULL;
+       }
+       rpmdbFreeIterator(mi);
+       return rpm_info;
 }
 
 void get_and_save_so_info(char *map_path, char *out_path)
 {
        GSList *file_list = get_filepaths(map_path);
 
-       char rpm_info[RPM_INFO_MAXLEN+1];
+       char *rpm_info;
        FILE *f = fopen(out_path, "w");
 
+       rpmts ts = init_rpm();
+
        if (f == NULL) {
                _E("Failed to open file for writing %s: %m", out_path);
        } else {
@@ -258,10 +305,13 @@ void get_and_save_so_info(char *map_path, char *out_path)
 
                        int fret;
 
-                       if (get_rpm_info(file_path, rpm_info) != 0)
+                       rpm_info = get_rpm_info(ts, file_path);
+                       if (rpm_info == NULL)
                                fret = fprintf(f, "%s %s\n", file_path, build_id);
-                       else
+                       else {
                                fret = fprintf(f, "%s %s %s\n", file_path, build_id, rpm_info);
+                               free(rpm_info);
+                       }
 
                        free(build_id);
 
@@ -277,4 +327,6 @@ void get_and_save_so_info(char *map_path, char *out_path)
                free(iterator->data);
 
        g_slist_free(file_list);
+
+       free_rpm(ts);
 }