static void free_bundle_result_data(void *data) { struct bundle_result *br = (struct bundle_result *)data; if (!br) { return; } list_free_list_and_data(br->files, file_result_free); list_free_list_and_data(br->includes, free); free(br); }
void hashmap_free_hash_and_data(struct hashmap *hashmap, free_data_fn_t free_data) { int i; for (i = 0; i < HASH_SIZE(hashmap->mask_bits); i++) { list_free_list_and_data(hashmap->map[i], free_data); } free(hashmap); }
void clean_curl_multi_queue(void) { int i; struct swupd_curl_hashbucket *bucket; for (i = 0; i < SWUPD_CURL_HASH_BUCKETS; i++) { bucket = &swupd_curl_hashmap[i]; pthread_mutex_lock(&bucket->mutex); list_free_list_and_data(bucket->list, free_curl_list_data); bucket->list = NULL; pthread_mutex_unlock(&bucket->mutex); } }
int hashdump_main(int argc, char **argv) { struct list *opts = NULL; int ret = -1; if (!parse_options(argc, argv, &opts)) { print_help(argv[0]); goto finish; } ret = dbus_client_call_method("HashDump", opts, DBUS_CMD_SINGLE_ARG, (argv + optind)); finish: list_free_list_and_data(opts, free_command_option); return ret; }
void list_free_list(struct list *list) { list_free_list_and_data(list, NULL); }
/* 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); }
int main(int argc, char **argv) { struct list *list = NULL; struct list *list1, *list2; struct list *item, *item2, *item3, *head, *tail; unsigned int i; struct timeval tod; unsigned int seed; unsigned int len = TEST_LIST_LEN; clock_t t; unsigned int *data; /* List length must be greater than 3 for all tests to work */ if (argc > 1) { len = atoi(argv[1]); } if (len < 4) { printf("List length must be at least 4 for tests.\n"); return EXIT_FAILURE; } /* seed the random generator so that we get different lists each time */ gettimeofday(&tod, NULL); seed = (unsigned int) tod.tv_sec; srand(seed); /* create a list with random data between 0 and len */ for (i = 1; i <= len; i++) { data = malloc(sizeof(unsigned int)); if (!data) { printf("data allocation failed\n"); exit(-1); } *data = (unsigned int) rand() % len; list = list_append_data(list, data); } printf("List constructed, seed = %d, len = %d\n", seed, list_len(list)); t = clock(); list = list_sort(list, data_compare); t = clock() - t; /* check list elements are in right order */ if (check_list_order(list, 1) != 0) { printf ("Sorted (1) List is in wrong order\n"); return EXIT_FAILURE; } /* check sorted list has the expected len */ if (list_len(list) != len) { printf("Wrong sorted (1) list len = %d instead of %d", i, len); return EXIT_FAILURE; } // dump_list(list); printf("List sorted in %f seconds\n", (float) t / CLOCKS_PER_SEC); /* sort again on sorted list to check special case */ t = clock(); list = list_sort(list, data_compare); t = clock() - t; if (check_list_order(list, 1) != 0) { printf ("Sorted (2) List is in wrong order\n"); return EXIT_FAILURE; } if (list_len(list) != len) { printf("Wrong sorted (2) list len = %d instead of %d", i, len); return EXIT_FAILURE; } // dump_list(list); printf("Sorted list sorted again in %f seconds\n", (float) t / CLOCKS_PER_SEC); /* reverse sort from sorted state */ t = clock(); list = list_sort(list, data_compare_reverse); t = clock() - t; if (check_list_order(list, -1) != 0) { printf ("Sorted (3) List is in wrong order\n"); return EXIT_FAILURE; } if (list_len(list) != len) { printf("Wrong sorted (3) list len = %d instead of %d", i, len); return EXIT_FAILURE; } // dump_list(list); printf("Sorted list sorted reverse in %f seconds\n", (float) t / CLOCKS_PER_SEC); /* Check freeing the head item. * This must return the 2nd item, which must be the new head */ head = list_head(list); item2 = head->next; list = list_free_item(head, free); if (list != item2) { printf("removing head item did not return 2nd item\n"); return EXIT_FAILURE; } if (item2->prev) { printf("item returned after removing head is not new head\n"); return EXIT_FAILURE; } if (list_len(item2) != len - 1) { printf("removing head item did not result in the right list len\n"); return EXIT_FAILURE; } printf ("Removing head correctly returned 2nd item as new head\n"); /* Check freeing middle item, must return previous item */ head = list_head(list); item2 = head->next; item3 = item2->next; list = list_free_item(item2, free); if (list != head) { printf("removing 2nd item did not return head item\n"); return EXIT_FAILURE; } if ((head != item3->prev) || (head->next != item3)) { printf("removing 2nd item did not link 3rd item to head\n"); return EXIT_FAILURE; } if (list_len(list) != len - 2) { printf("removing 2nd item did not result in the right list len\n"); return EXIT_FAILURE; } printf ("Removing middle item correctly returned previous item\n"); /* Check freeing tail, must return new tail */ tail = list_tail(list); item = tail->prev; list = list_free_item(tail, free); if (list != item) { printf("removing tail did not return prev item\n"); return EXIT_FAILURE; } tail = list_tail(list); if (list != tail) { printf("removing tail did not return new tail\n"); return EXIT_FAILURE; } if (list_len(list) != len - 3) { printf("removing tail did not result in the right list len\n"); return EXIT_FAILURE; } printf ("Removing tail correctly returned previous item as new tail\n"); list_free_list_and_data(list, free); list = NULL; /* Check list_concat */ list1 = NULL; list2 = NULL; for (i = 3; i > 0; i--) { data = malloc(sizeof(unsigned int)); if (!data) { printf("data allocation failed\n"); exit(-1); } *data = (unsigned int) i; list1 = list_prepend_data(list1, data); } for (i = 6; i > 3; i--) { data = malloc(sizeof(unsigned int)); if (!data) { printf("data allocation failed\n"); exit(-1); } *data = (unsigned int) i; list2 = list_prepend_data(list2, data); } /* Check concat one list with empty list */ list = list_concat(list1, NULL); if (list_len(list) != 3) { printf("concat(list1, NULL) did not result in a list len of 3\n"); return EXIT_FAILURE; } if (list != list1) { printf("concat(list1, NULL) did not return list1\n"); return EXIT_FAILURE; } if (list_head(list) != list) { printf("concat(list1, NULL) did not return list1 head\n"); return EXIT_FAILURE; } if (*((unsigned int*)(list->data)) != 1) { printf("concat(list1, NULL) head is wrong\n"); return EXIT_FAILURE; } printf ("concat(list1, NULL) is OK\n"); // dump_list(list); /* Check concat empty list with one list*/ list = list_concat(NULL, list2); if (list_len(list) != 3) { printf("concat(NULL, list2) did not result in a list len of 3\n"); return EXIT_FAILURE; } if (list != list2) { printf("concat(NULL, list2) did not return list2\n"); return EXIT_FAILURE; } if (list_head(list) != list) { printf("concat(NULL, list2) did not return list2 head\n"); return EXIT_FAILURE; } if (*((unsigned int*)(list->data)) != 4) { printf("concat(NULL, list2) head is wrong\n"); return EXIT_FAILURE; } printf ("concat(NULL, list2) is OK\n"); // dump_list(list); /* Check concat two lists */ list = list_concat(list1->next, list2->next->next); if (list_len(list) != 6) { printf("concat(list1, list2) did not result in a list len of 6\n"); return EXIT_FAILURE; } if (*((unsigned int*)(list->data)) != 1) { printf("concat(list1, list2) did not return list1 head\n"); return EXIT_FAILURE; } if (*((unsigned int*)(list->next->next->next->data)) != 4) { printf("concat(list1, list2) 4th item is not 4\n"); return EXIT_FAILURE; } printf ("concat(list1, list2) is OK\n"); // dump_list(list); list_free_list_and_data(list, free); printf ("*** ALL LIST TESTS COMPLETED OK***\n"); return EXIT_SUCCESS; }
/* This function is meant to be called while staging file to fix any missing/incorrect paths. * While staging a file, if its parent directory is missing, this would try to create the path * by breaking it into sub-paths and fixing them top down. * Here, target_MoM is the consolidated manifest for the version you are trying to update/verify. */ int verify_fix_path(char *targetpath, struct manifest *target_MoM) { struct list *path_list = NULL; /* path_list contains the subparts in the path */ char *path; char *tmp = NULL, *target = NULL; char *url = NULL; struct stat sb; int ret = 0; struct file *file; char *tar_dotfile = NULL; struct list *list1 = NULL; /* This shouldn't happen */ if (strcmp(targetpath, "/") == 0) { return ret; } /* Removing trailing '/' from the path */ path = strdup(targetpath); if (path[strlen(path) - 1] == '/') { path[strlen(path) - 1] = '\0'; } /* Breaking down the path into parts. * eg. Path /usr/bin/foo will be broken into /usr,/usr/bin and /usr/bin/foo */ while (strcmp(path, "/") != 0) { path_list = list_prepend_data(path_list, strdup(path)); tmp = strdup(dirname(path)); free(path); path = tmp; } free(path); list1 = list_head(path_list); while (list1) { path = list1->data; list1 = list1->next; target = mk_full_filename(path_prefix, path); /* Search for the file in the manifest, to get the hash for the file */ file = search_file_in_manifest(target_MoM, path); if (file == NULL) { printf("Error: Path %s not found in any of the subscribed manifests" "in verify_fix_path for path_prefix %s\n", path, path_prefix); ret = -1; goto end; } if (file->is_deleted) { printf("Error: Path %s found deleted in verify_fix_path\n", path); ret = -1; goto end; } ret = stat(target, &sb); if (ret == 0) { if (verify_file(file, target)) { continue; } printf("Hash did not match for path : %s\n", path); } else if (ret == -1 && errno == ENOENT) { printf("Path %s is missing on the file system\n", path); } else { goto end; } string_or_die(&tar_dotfile, "%s/download/.%s.tar", state_dir, file->hash); // clean up in case any prior download failed in a partial state unlink(tar_dotfile); string_or_die(&url, "%s/%i/files/%s.tar", content_url, file->last_change, file->hash); ret = swupd_curl_get_file(url, tar_dotfile, NULL, NULL, false); if (ret != 0) { printf("Error: Failed to download file %s in verify_fix_path\n", file->filename); unlink(tar_dotfile); goto end; } if (untar_full_download(file) != 0) { printf("Error: Failed to untar file %s\n", file->filename); ret = -1; goto end; } ret = do_staging(file, target_MoM); if (ret != 0) { printf("Error: Path %s failed to stage in verify_fix_path\n", path); goto end; } } end: if (target) { free(target); } if (tar_dotfile) { free(tar_dotfile); } if (url) { free(url); } list_free_list_and_data(path_list, free_path_data); return ret; }
/* This function is meant to be called while staging file to fix any missing/incorrect paths. * While staging a file, if its parent directory is missing, this would try to create the path * by breaking it into sub-paths and fixing them top down. * Here, target_MoM is the consolidated manifest for the version you are trying to update/verify. */ int verify_fix_path(char *targetpath, struct manifest *target_MoM) { struct list *path_list = NULL; /* path_list contains the subparts in the path */ char *path; char *tmp = NULL, *target = NULL; char *url = NULL; struct stat sb; int ret = 0; struct file *file; char *tar_dotfile = NULL; struct list *list1 = NULL; /* This shouldn't happen */ if (strcmp(targetpath, "/") == 0) { return ret; } /* Removing trailing '/' from the path */ path = strdup_or_die(targetpath); if (path[strlen(path) - 1] == '/') { path[strlen(path) - 1] = '\0'; } /* Breaking down the path into parts. * eg. Path /usr/bin/foo will be broken into /usr,/usr/bin and /usr/bin/foo */ while (strcmp(path, "/") != 0) { path_list = list_prepend_data(path_list, strdup_or_die(path)); tmp = strdup_or_die(dirname(path)); free_string(&path); path = tmp; } free_string(&path); list1 = list_head(path_list); while (list1) { path = list1->data; list1 = list1->next; free_string(&target); free_string(&tar_dotfile); free_string(&url); target = mk_full_filename(path_prefix, path); /* Search for the file in the manifest, to get the hash for the file */ file = search_file_in_manifest(target_MoM, path); if (file == NULL) { fprintf(stderr, "Error: Path %s not found in any of the subscribed manifests" "in verify_fix_path for path_prefix %s\n", path, path_prefix); ret = -1; goto end; } if (file->is_deleted) { fprintf(stderr, "Error: Path %s found deleted in verify_fix_path\n", path); ret = -1; goto end; } ret = stat(target, &sb); if (ret == 0) { if (verify_file(file, target)) { continue; } fprintf(stderr, "Hash did not match for path : %s ... fixing\n", path); } else if (ret == -1 && errno == ENOENT) { fprintf(stderr, "Path %s is missing on the file system ... fixing\n", path); } else { goto end; } /* In some circumstances (Docker using layers between updates/bundle adds, * corrupt staging content) we could have content which fails to stage. * In order to avoid this causing failure in verify_fix_path, remove the * staging content before proceeding. This also cleans up in case any prior * download failed in a partial state. */ unlink_all_staged_content(file); string_or_die(&tar_dotfile, "%s/download/.%s.tar", state_dir, file->hash); string_or_die(&url, "%s/%i/files/%s.tar", content_url, file->last_change, file->hash); ret = swupd_curl_get_file(url, tar_dotfile); if (ret != 0) { fprintf(stderr, "Error: Failed to download file %s in verify_fix_path\n", file->filename); unlink(tar_dotfile); goto end; } if (untar_full_download(file) != 0) { fprintf(stderr, "Error: Failed to untar file %s\n", file->filename); ret = -1; goto end; } ret = do_staging(file, target_MoM); if (ret != 0) { fprintf(stderr, "Error: Path %s failed to stage in verify_fix_path\n", path); goto end; } } end: free_string(&target); free_string(&tar_dotfile); free_string(&url); list_free_list_and_data(path_list, free_path_data); return ret; }