Exemple #1
0
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);
}
Exemple #2
0
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);
}
Exemple #3
0
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;
}
Exemple #5
0
void list_free_list(struct list *list)
{
	list_free_list_and_data(list, NULL);
}
Exemple #6
0
/* 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);
}
Exemple #7
0
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;
}
Exemple #8
0
/* 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;
}
Exemple #9
0
/* 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;
}