Add support for tpk packages 32/197632/5
authorMateusz Moscicki <m.moscicki2@partner.samsung.com>
Mon, 14 Jan 2019 12:41:50 +0000 (13:41 +0100)
committerMateusz Moscicki <m.moscicki2@partner.samsung.com>
Thu, 17 Jan 2019 15:11:49 +0000 (16:11 +0100)
Change-Id: Ic625678478e3dc888bea786bb203ef021c579228

src/crash-manager/so-info.c

index 07032b5..554edc4 100644 (file)
@@ -284,9 +284,116 @@ char* get_rpm_info(rpmts ts, const char* filename)
        return rpm_info;
 }
 
+struct rpm_file {
+       char *pkg_name;
+       char *file_name;
+};
+
+GSList* create_tpk_list(rpmts ts)
+{
+       GSList *tpk_list = NULL;
+
+       rpmdbMatchIterator mi = rpmtsInitIterator(ts, RPMTAG_NAME, NULL, 0);
+       if (mi == NULL) {
+               _E("Failed to init rpmdb match iterator");
+               goto end;
+       }
+
+       for (Header h = rpmdbNextIterator(mi); h; h = rpmdbNextIterator(mi)) {
+               const char *pkg_name = headerGetString(h, RPMTAG_NAME);
+               if (pkg_name == NULL)
+                       continue;
+               rpmfi fi = rpmfiNew(NULL, h, RPMTAG_FILENAMES, 0);
+
+               while (rpmfiNext(fi) != -1) {
+                       const char *file_name = rpmfiFN(fi);
+                       size_t file_name_len = strlen(file_name);
+
+                       if (file_name_len < 4 ||
+                           strcmp(&file_name[file_name_len-4], ".tpk") != 0)
+                               continue;
+
+                       struct rpm_file *rpm = (struct rpm_file*)malloc(sizeof(rpm));
+                       if (rpm == NULL) {
+                               _E("malloc() error (%m). Report (*.so_info) may be incomplete.");
+                               continue;
+                       }
+
+                       const char *version = headerGetString(h, RPMTAG_VERSION);
+                       const char *release = headerGetString(h, RPMTAG_RELEASE);
+                       const char *arch = headerGetString(h, RPMTAG_ARCH);
+
+                       if (version == NULL || release == NULL || arch == NULL)
+                               continue;
+
+                       if (asprintf(&rpm->pkg_name, "%s;%s;%s;%s",
+                                       pkg_name, version, release, arch) == -1) {
+                               _E("asprintf() error: %m");
+                               free(rpm);
+                               continue;
+                       }
+                       rpm->file_name = strdup(file_name);
+                       if (rpm->file_name == NULL) {
+                               _E("strdup() error: %m");
+                               free(rpm->pkg_name);
+                               free(rpm);
+                               continue;
+                       }
+                       tpk_list = g_slist_append(tpk_list, rpm);
+               }
+       }
+       rpmdbFreeIterator(mi);
+
+       if (tpk_list == NULL)
+               _E("No RPM packages containing *.tpk files found");
+end:
+       return tpk_list;
+}
+
+char* get_app_name_from_path(const char *file_path)
+{
+       static const char *prefix[] = {"/usr/apps/",
+                                       "/opt/usr/globalapps/",
+                                       NULL};
+
+       for (size_t i = 0; i < ARRAY_SIZE(prefix); i++) {
+               if (strncmp(file_path, prefix[i], strlen(prefix[i])) != 0)
+                       continue;
+
+               const char *app_name = &file_path[strlen(prefix[i])];
+
+               char *end_of_name = strchr(app_name, '/');
+               if (end_of_name != NULL)
+                       return strndup(app_name, end_of_name - app_name);
+       }
+       return NULL;
+}
+
+char* get_rpm_info_for_tpk(GSList *tpk_list, const char *file_path)
+{
+       char *app_name = get_app_name_from_path(file_path);
+       if (app_name == NULL)
+               return NULL;
+
+       char *res = NULL;
+
+       for (GSList *iterator = tpk_list; iterator; iterator = iterator->next) {
+               struct rpm_file *rpm_pkg = (struct rpm_file *)iterator->data;
+
+               if (strstr(rpm_pkg->file_name, app_name) != NULL) {
+                       res = strdup(rpm_pkg->pkg_name);
+                       break;
+               }
+       }
+
+       free(app_name);
+       return res;
+}
+
 void get_and_save_so_info(char *map_path, char *out_path)
 {
        GSList *file_list = get_filepaths(map_path);
+       GSList *tpk_list = NULL;
 
        char *rpm_info;
        FILE *f = fopen(out_path, "w");
@@ -306,6 +413,12 @@ void get_and_save_so_info(char *map_path, char *out_path)
                        int fret;
 
                        rpm_info = get_rpm_info(ts, file_path);
+                       if (rpm_info == NULL) {
+                               if (tpk_list == NULL)
+                                       tpk_list = create_tpk_list(ts);
+                               if (tpk_list != NULL)
+                                       rpm_info = get_rpm_info_for_tpk(tpk_list, file_path);
+                       }
                        if (rpm_info == NULL)
                                fret = fprintf(f, "%s %s\n", file_path, build_id);
                        else {
@@ -326,7 +439,15 @@ void get_and_save_so_info(char *map_path, char *out_path)
        for (GSList *iterator = file_list; iterator; iterator = iterator->next)
                free(iterator->data);
 
+       for (GSList *iterator = tpk_list; iterator; iterator = iterator->next) {
+               struct rpm_file *rpm = (struct rpm_file*)iterator->data;
+               free(rpm->file_name);
+               free(rpm->pkg_name);
+               free(rpm);
+       }
+
        g_slist_free(file_list);
+       g_slist_free(tpk_list);
 
        free_rpm(ts);
 }