#define BID_SNAME ".note.gnu.build-id"
+struct rpm_info {
+ char *file_path;
+ char *app_name;
+ char *build_id;
+ char *rpm_info;
+};
+
+void rpm_info_free(struct rpm_info* ri)
+{
+ free(ri->file_path);
+ free(ri->app_name);
+ free(ri->build_id);
+ free(ri->rpm_info);
+ free(ri);
+}
static unsigned char *map_file(const char *filename, int64_t *size)
{
}
}
-char* get_rpm_info_as_string(Header h)
+char* get_rpm_info_as_string_for_pkgname(Header h, const char *pkg_name)
{
- const char *name, *version, *release, *arch;
+ char *result = NULL;
- name = headerGetString(h, RPMTAG_NAME);
- version = headerGetString(h, RPMTAG_VERSION);
- release = headerGetString(h, RPMTAG_RELEASE);
- arch = headerGetString(h, RPMTAG_ARCH);
+ const char *version = headerGetString(h, RPMTAG_VERSION);
+ const char *release = headerGetString(h, RPMTAG_RELEASE);
+ const char *arch = headerGetString(h, RPMTAG_ARCH);
- int info_len = strlen(name) + strlen(version) +
- strlen(release) + strlen(arch) + 3;
+ if (version == NULL || release == NULL || arch == NULL)
+ _E("Failed to get version, release and arch for: %s", pkg_name);
+ else if (asprintf(&result, "%s;%s;%s;%s", pkg_name, version, release, arch) == -1)
+ _E("asprintf() error: %m");
- char *res = (char *)malloc(info_len + 1);
- if (res == NULL) {
- _E("Failed to allocate memory: %m");
- return NULL;
- }
- snprintf(res, info_len + 1, "%s;%s;%s;%s", name, version, release, arch);
+ return result;
+}
- return res;
+char* get_rpm_info_as_string(Header h)
+{
+ const char *name = headerGetString(h, RPMTAG_NAME);
+ return get_rpm_info_as_string_for_pkgname(h, name);
}
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)
+void search_for_tpk(rpmts ts, GSList *pkgs)
{
- GSList *tpk_list = NULL;
-
rpmdbMatchIterator mi = rpmtsInitIterator(ts, RPMTAG_NAME, NULL, 0);
if (mi == NULL) {
_E("Failed to init rpmdb match iterator");
- goto end;
+ return;
}
- for (Header h = rpmdbNextIterator(mi); h; h = rpmdbNextIterator(mi)) {
+ guint count = g_slist_length(pkgs); // Initial number of packets with empty rpm_info
+
+ for (Header h = rpmdbNextIterator(mi); count > 0 && 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) {
+ while (count > 0 && rpmfiNext(fi) != -1) {
const char *file_name = rpmfiFN(fi);
size_t file_name_len = strlen(file_name);
strcmp(&file_name[file_name_len-4], ".tpk") != 0)
continue;
- const char *version = headerGetString(h, RPMTAG_VERSION);
- const char *release = headerGetString(h, RPMTAG_RELEASE);
- const char *arch = headerGetString(h, RPMTAG_ARCH);
+ for (GSList *iterator = pkgs; iterator; iterator = iterator->next) {
+ struct rpm_info *ri = (struct rpm_info *)iterator->data;
+ if (ri->rpm_info != NULL)
+ continue;
- if (version == NULL || release == NULL || arch == NULL)
- continue;
+ if (strstr(file_name, ri->app_name) == NULL)
+ 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;
- }
+ char *info = get_rpm_info_as_string_for_pkgname(h, pkg_name);
+ if (info == 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;
+ ri->rpm_info = info;
+ count--;
+ break;
}
- tpk_list = g_slist_append(tpk_list, rpm);
}
+
+ rpmfiFree(fi);
}
- rpmdbFreeIterator(mi);
- if (tpk_list == NULL)
- _E("No RPM packages containing *.tpk files found");
-end:
- return tpk_list;
+ rpmdbFreeIterator(mi);
}
char* get_app_name_from_path(const char *file_path)
return NULL;
}
-char* get_rpm_info_for_tpk(GSList *tpk_list, const char *file_path)
+void get_and_save_so_info(char *map_path, char *out_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;
- }
+ FILE *f = fopen(out_path, "w");
+ if (f == NULL) {
+ _E("Failed to open file for writing %s: %m", out_path);
+ return;
}
- 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");
+ GSList *pkgs_not_found = NULL;
rpmts ts = init_rpm();
- if (f == NULL) {
- _E("Failed to open file for writing %s: %m", out_path);
- } else {
- char *build_id = NULL;
- for (GSList *iterator = file_list; iterator; iterator = iterator->next) {
- char *file_path = (char *)iterator->data;
-
- if (get_build_id(file_path, &build_id) <= 0 || build_id == NULL)
- continue;
+ for (GSList *iterator = file_list; iterator; iterator = iterator->next) {
+ char *file_path = (char *)iterator->data;
- int fret;
+ char *build_id = NULL;
+ if (get_build_id(file_path, &build_id) <= 0 || build_id == NULL)
+ continue;
- 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);
+ char *rpm_info = get_rpm_info(ts, file_path);
+ if (rpm_info == NULL) {
+ struct rpm_info *ri = malloc(sizeof(struct rpm_info));
+ if (ri == NULL) {
+ _E("malloc error: %m");
+ free(build_id);
+ break;
}
- if (rpm_info == NULL)
- fret = fprintf(f, "%s %s\n", file_path, build_id);
- else {
- fret = fprintf(f, "%s %s %s\n", file_path, build_id, rpm_info);
- free(rpm_info);
+ ri->file_path = strdup(file_path);
+ if (ri->file_path == NULL) {
+ _E("strdup error: %m");
+ free(build_id);
+ free(ri);
+ break;
}
-
+ ri->app_name = get_app_name_from_path(file_path);
+ ri->build_id = build_id;
+ ri->rpm_info = NULL;
+ pkgs_not_found = g_slist_append(pkgs_not_found, ri);
+ } else {
+ int fret = fprintf(f, "%s %s %s\n", file_path, build_id, rpm_info);
+ free(rpm_info);
free(build_id);
if (fret < 0) {
- _E("Failed to write to file %s", out_path);
+ _E("Failed to write to file %s: %m", out_path);
break;
}
}
- fclose(f);
}
- for (GSList *iterator = file_list; iterator; iterator = iterator->next)
- free(iterator->data);
+ search_for_tpk(ts, pkgs_not_found);
+
+ for (GSList *iterator = pkgs_not_found; iterator; iterator = iterator->next) {
+ struct rpm_info *ri = (struct rpm_info*)iterator->data;
+ int fret;
+
+ if (ri->rpm_info == NULL)
+ fret = fprintf(f, "%s %s\n", ri->file_path, ri->build_id);
+ else
+ fret = fprintf(f, "%s %s %s\n", ri->file_path, ri->build_id, ri->rpm_info);
+
+ if (fret < 0)
+ _E("Failed to write to file %s: %m", out_path);
- 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);
+ rpm_info_free(ri);
}
+ g_slist_free(pkgs_not_found);
+
+ fclose(f);
+
+ for (GSList *iterator = file_list; iterator; iterator = iterator->next)
+ free(iterator->data);
+
g_slist_free(file_list);
- g_slist_free(tpk_list);
free_rpm(ts);
}