/* add a bundle_result to the results list */ static void add_bundle_file_result(char *bundlename, char *filename, double score) { struct bundle_result *bundle = NULL; struct file_result *file; struct list *ptr; ptr = results; while (ptr) { struct bundle_result *item; item = ptr->data; if (strcmp(item->bundle_name, bundlename) == 0) { bundle = item; break; } ptr = ptr->next; } if (!bundle) { bundle = calloc(sizeof(struct bundle_result), 1); ON_NULL_ABORT(bundle); results = list_append_data(results, bundle); strncpy(bundle->bundle_name, bundlename, BUNDLE_NAME_MAXLEN - 1); /* record if the bundle is tracked on the system */ bundle->is_tracked = is_tracked_bundle(bundlename); } file = calloc(sizeof(struct file_result), 1); ON_NULL_ABORT(file); file->filename = strdup_or_die(filename); bundle->files = list_append_data(bundle->files, file); file->score = score; bundle->score += score; }
static struct time *alloc_time() { struct time *t = calloc(1, sizeof(struct time)); ON_NULL_ABORT(t); return t; }
/* Return a duplicated copy of the string using strdup(). * Abort if there's no memory to allocate the new string. */ char *strdup_or_die(const char *const str) { char *result; result = strdup(str); ON_NULL_ABORT(result); return result; }
timelist *timelist_new(void) { timelist *head = malloc(sizeof(timelist)); ON_NULL_ABORT(head); TAILQ_INIT(head); timelist_timer_start(head, "Total execution time"); return head; }
static struct list *list_alloc_item(void *data) { struct list *item; item = (struct list *)malloc(sizeof(struct list)); ON_NULL_ABORT(item); item->data = data; item->next = NULL; item->prev = NULL; return item; }
static char *read_mom_contents(int version) { char *mom_path = NULL; string_or_die(&mom_path, "%s/%d/Manifest.MoM", state_dir, version); FILE *f = fopen(mom_path, "r"); free_string(&mom_path); if (!f) { /* This is a best effort. */ return NULL; } char *contents = NULL; int fd = fileno(f); if (fd == -1) { goto end; } int ret; struct stat stat; ret = fstat(fd, &stat); if (ret != 0) { goto end; } contents = malloc(stat.st_size + 1); ON_NULL_ABORT(contents); ret = fread(contents, stat.st_size, 1, f); if (ret != 1) { free(contents); contents = NULL; } else { contents[stat.st_size] = 0; } end: fclose(f); return contents; }
/* do_search() * Description: Perform a lookup of the specified search string in all Clear manifests * for the current os release. */ static void do_search(struct manifest *MoM, char search_type, char *search_term) { struct list *list; struct list *sublist; struct file *file; struct file *subfile; struct list *bundle_info = NULL; struct manifest *subman = NULL; int i; bool done_with_bundle, done_with_search = false; bool hit = false; bool man_load_failures = false; long hit_count = 0; list = MoM->manifests; while (list && !done_with_search) { file = list->data; list = list->next; done_with_bundle = false; /* Load sub-manifest */ subman = load_manifest(file->last_change, file, MoM, false); if (!subman) { fprintf(stderr, "Failed to load manifest %s\n", file->filename); man_load_failures = true; continue; } /* record contentsize and includes for install size calculation */ struct bundle_result *bundle = NULL; bundle = calloc(sizeof(struct bundle_result), 1); ON_NULL_ABORT(bundle); /* copy relevant information over for future use */ strncpy(bundle->bundle_name, subman->component, BUNDLE_NAME_MAXLEN - 1); bundle->topsize = subman->contentsize; /* do a deep copy of the includes list */ bundle->includes = list_deep_clone_strs(subman->includes); bundle_info = list_prepend_data(bundle_info, bundle); if (display_files) { /* Display bundle name. Marked up for pattern matchability */ fprintf(stderr, "--Bundle: %s--\n", file->filename); } /* Loop through sub-manifest, searching for files matching the desired pattern */ sublist = subman->files; while (sublist && !done_with_bundle) { subfile = sublist->data; sublist = sublist->next; if ((!subfile->is_file) && (!subfile->is_link)) { continue; } if (display_files) { /* Just display filename */ file_search(subfile->filename, NULL, NULL); } else if (search_type == '0') { /* Search for exact match, not path addition */ if (file_search(subfile->filename, "", search_term)) { report_find(file->filename, subfile->filename, search_term); hit = true; } } else if (search_type == 'l') { /* Check each supported library path for a match */ for (i = 0; lib_paths[i] != NULL; i++) { if (file_search(subfile->filename, lib_paths[i], search_term)) { report_find(file->filename, subfile->filename, search_term); hit = true; } } } else if (search_type == 'b') { /* Check each supported path for binaries */ for (i = 0; bin_paths[i] != NULL; i++) { if (file_search(subfile->filename, bin_paths[i], search_term)) { report_find(file->filename, subfile->filename, search_term); hit = true; } } } else { fprintf(stderr, "Unrecognized search type. -b or -l supported\n"); done_with_search = true; break; } /* Determine the level of completion we've reached */ if (hit) { if (scope == 'b') { done_with_bundle = true; } else if (scope == 'o') { done_with_bundle = true; done_with_search = true; } hit_count++; } hit = false; } free_manifest(subman); } if (!hit_count) { fprintf(stderr, "Search term not found.\n"); } bool display_size = (scope != 'o' && !man_load_failures); if (display_size) { apply_size_penalty(bundle_info); } list_free_list_and_data(bundle_info, free_bundle_result_data); if (num_results != INT_MAX) { sort_results(); } else { results = list_sort(results, bundle_size_cmp); } if (csv_format) { print_csv_results(); } else { print_final_results(display_size); } list_free_list_and_data(results, free_bundle_result_data); }