From caedd919a9695ceceb5fcd35cfc91833cc369f0c Mon Sep 17 00:00:00 2001 From: Mateusz Moscicki Date: Tue, 17 Jul 2018 13:43:39 +0200 Subject: [PATCH] Add own implementation of getting rpm packages info Calling the external rpm command is too slow, especially for binaries with many shared object dependencies. Change-Id: I48a86c0a0067bb2d37b7b7a12abae5d611c8b572 --- packaging/crash-worker.spec | 1 + src/crash-manager/CMakeLists.txt | 1 + src/crash-manager/so-info.c | 92 +++++++++++++++++++++++++++++++--------- 3 files changed, 74 insertions(+), 20 deletions(-) diff --git a/packaging/crash-worker.spec b/packaging/crash-worker.spec index 7177835..773c552 100644 --- a/packaging/crash-worker.spec +++ b/packaging/crash-worker.spec @@ -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) diff --git a/src/crash-manager/CMakeLists.txt b/src/crash-manager/CMakeLists.txt index d95e846..5fe5b19 100644 --- a/src/crash-manager/CMakeLists.txt +++ b/src/crash-manager/CMakeLists.txt @@ -26,6 +26,7 @@ pkg_check_modules(crash-manager_pkgs REQUIRED libtzplatform-config iniparser gio-2.0 + rpm ) FOREACH(flag ${crash-manager_pkgs_CFLAGS}) diff --git a/src/crash-manager/so-info.c b/src/crash-manager/so-info.c index 0ef0bc7..53ad1fe 100644 --- a/src/crash-manager/so-info.c +++ b/src/crash-manager/so-info.c @@ -28,16 +28,15 @@ #include #include #include +#include +#include +#include +#include #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); } -- 2.7.4