diff --git a/Makefile.am b/Makefile.am index c733ffd3..efd4beb6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -76,6 +76,8 @@ swupd_SOURCES = \ src/info.c \ src/lib/archives.c \ src/lib/archives.h \ + src/lib/comp_functions.c \ + src/lib/comp_functions.h \ src/lib/config_file.c \ src/lib/config_file.h \ src/lib/formatter_json.c \ @@ -116,6 +118,8 @@ swupd_SOURCES = \ src/subscriptions.c \ src/swupd_build_opts.h \ src/swupd_build_variant.h \ + src/swupd_comp_functions.c \ + src/swupd_comp_functions.h \ src/swupd_curl.h \ src/swupd_curl_internal.h \ src/swupd_exit_codes.h \ diff --git a/src/bundle_info.c b/src/bundle_info.c index 5eeda173..9ec3b4ea 100644 --- a/src/bundle_info.c +++ b/src/bundle_info.c @@ -280,11 +280,11 @@ static enum swupd_code get_bundle_dependencies(struct manifest *manifest, struct /* from the list of dependencies, remove those that were * directly pulled by the bundle so we are left only with the ones * indirectly pulled */ - *indirect_includes = list_sort(*indirect_includes, subscription_sort_component); + *indirect_includes = list_sort(*indirect_includes, cmp_subscription_component); manifest->includes = list_sort(manifest->includes, strcmp_wrapper); manifest->optional = list_sort(manifest->optional, strcmp_wrapper); - *indirect_includes = list_sorted_filter_common_elements(*indirect_includes, manifest->includes, subscription_bundlename_strcmp, NULL); - *indirect_includes = list_sorted_filter_common_elements(*indirect_includes, manifest->optional, subscription_bundlename_strcmp, NULL); + *indirect_includes = list_sorted_filter_common_elements(*indirect_includes, manifest->includes, cmp_sub_component_string, NULL); + *indirect_includes = list_sorted_filter_common_elements(*indirect_includes, manifest->optional, cmp_sub_component_string, NULL); return SWUPD_OK; } diff --git a/src/bundle_list.c b/src/bundle_list.c index 5de86792..82ab8195 100644 --- a/src/bundle_list.c +++ b/src/bundle_list.c @@ -258,7 +258,7 @@ static enum swupd_code show_included_bundles(char *bundle_name, int version) if (verbose) { ret = subscription_get_tree(bundles, &subs, mom, true, 0); } else { - subs = list_sort(subs, subscription_sort_component); + subs = list_sort(subs, cmp_subscription_component); iter = list_head(subs); while (iter) { bundle_sub = iter->data; @@ -306,7 +306,7 @@ static enum swupd_code list_installable_bundles(int version) progress_next_step("list_bundles", PROGRESS_UNDEFINED); info("All available bundles:\n"); - list = MoM->manifests = list_sort(MoM->manifests, file_sort_filename); + list = MoM->manifests = list_sort(MoM->manifests, cmp_file_filename_is_deleted); while (list) { file = list->data; list = list->next; diff --git a/src/bundle_remove.c b/src/bundle_remove.c index 6f1f9c68..5d32d733 100644 --- a/src/bundle_remove.c +++ b/src/bundle_remove.c @@ -143,25 +143,7 @@ static void remove_tracked(const char *bundle) free_string(&tracking_file); } -static int find_manifest(const void *a, const void *b) -{ - struct manifest *A; - char *B; - int ret; - - A = (struct manifest *)a; - B = (char *)b; - - ret = strcmp(A->component, B); - if (ret != 0) { - return ret; - } - - /* we found a match*/ - return 0; -} - -static int filter_files_to_delete(const void *a, const void *b) +static int filter_file_to_delete(const void *a, const void *b) { struct file *A, *B; int ret; @@ -247,7 +229,7 @@ static void get_removable_dependencies(struct manifest *mom, struct list **bundl for (iter = mom->submanifests; iter; iter = iter->next) { m = iter->data; bundle = m->component; - if (!list_search(candidates_for_removal, bundle, manifest_bundlename_strcmp)) { + if (!list_search(candidates_for_removal, bundle, cmp_manifest_component_string)) { recurse_dependencies(mom, bundle, &required_bundles, is_installed); } } @@ -258,7 +240,7 @@ static void get_removable_dependencies(struct manifest *mom, struct list **bundl while (iter) { m = iter->data; bundle = m->component; - if (list_search(required_bundles, bundle, manifest_bundlename_strcmp)) { + if (list_search(required_bundles, bundle, cmp_manifest_component_string)) { if (iter == candidates_for_removal) { if (iter->next) { candidates_for_removal = iter->next; @@ -277,9 +259,9 @@ static void get_removable_dependencies(struct manifest *mom, struct list **bundl for (iter = candidates_for_removal; iter; iter = iter->next) { m = iter->data; bundle = m->component; - list_move_item(bundle, &mom->submanifests, bundles_to_remove, find_manifest); + list_move_item(bundle, &mom->submanifests, bundles_to_remove, cmp_manifest_component_string); } - *bundles_to_remove = list_sort(*bundles_to_remove, manifest_component_strcmp); + *bundles_to_remove = list_sort(*bundles_to_remove, cmp_manifest_component); list_free_list_and_data(candidates_for_removal, manifest_free_data); list_free_list_and_data(required_bundles, manifest_free_data); @@ -394,7 +376,7 @@ enum swupd_code execute_remove_bundles(struct list *bundles) char *dep; for (iter = list_head(reqd_by); iter; iter = iter->next) { dep = iter->data; - list_move_item(dep, ¤t_mom->submanifests, &bundles_to_remove, find_manifest); + list_move_item(dep, ¤t_mom->submanifests, &bundles_to_remove, cmp_manifest_component_string); remove_tracked(dep); } list_free_list_and_data(reqd_by, free); @@ -405,7 +387,7 @@ enum swupd_code execute_remove_bundles(struct list *bundles) * "deletable" move the manifest of the bundle * to be remove from the list of subscribed * bundles to the list of bundles to be removed */ - list_move_item(bundle, ¤t_mom->submanifests, &bundles_to_remove, find_manifest); + list_move_item(bundle, ¤t_mom->submanifests, &bundles_to_remove, cmp_manifest_component_string); remove_tracked(bundle); } @@ -432,7 +414,7 @@ enum swupd_code execute_remove_bundles(struct list *bundles) /* sanitize files to remove; if a file is needed by a bundle that * is installed, it should be kept in the system */ - files_to_remove = list_sorted_filter_common_elements(files_to_remove, current_mom->files, filter_files_to_delete, NULL); + files_to_remove = list_sorted_filter_common_elements(files_to_remove, current_mom->files, filter_file_to_delete, NULL); if (list_len(files_to_remove) > 0) { info("\nDeleting bundle files...\n"); diff --git a/src/extra_files.c b/src/extra_files.c index f2d8987d..7df8889f 100644 --- a/src/extra_files.c +++ b/src/extra_files.c @@ -48,12 +48,6 @@ static int nF = 0; /* Number of filerecords */ static const regex_t *path_whitelist; static int path_prefix_len; -/* Helper function to call from nftw */ -static inline int bsearch_helper(const void *A, const void *B) -{ - return strcmp(*(const char **)A, ((struct filerecord *)B)->filename); -} - static int record_filename(const char *name, const struct stat *stat __attribute__((unused)), int type, struct FTW *ftw __attribute__((unused))) { /* Name as it would appear in manifest, f.i. /usr */ @@ -84,12 +78,6 @@ static int record_filename(const char *name, const struct stat *stat __attribute return 0; } -/* qsort helper function */ -static int qsort_helper(const void *A, const void *B) -{ - return strcmp(((struct filerecord *)A)->filename, ((struct filerecord *)B)->filename); -} - /* return true if the function deletes the specified filename, otherwise false */ static bool handle(const char *filename, bool is_dir, bool fix) { @@ -133,7 +121,7 @@ enum swupd_code walk_tree(struct manifest *manifest, const char *start, bool fix } goto tidy; /* Already printed out of memory */ } - qsort(F, nF, sizeof(*F), &qsort_helper); + qsort(F, nF, sizeof(*F), &cmp_filerecord_filename); /* Interesting question, would it be faster to sort this linked list, * or convert it to an array of pointers, or just pull them off one * at a time? Try one at a time first. @@ -149,7 +137,7 @@ enum swupd_code walk_tree(struct manifest *manifest, const char *start, bool fix if (file->is_deleted && !file->is_ghosted) { continue; } - found = bsearch(&file->filename, F, nF, sizeof(*F), &bsearch_helper); + found = bsearch(&file->filename, F, nF, sizeof(*F), &cmp_string_filerecord_filename); if (found) { found->in_manifest = true; } diff --git a/src/fullfile.c b/src/fullfile.c index 19d9d763..30af7300 100644 --- a/src/fullfile.c +++ b/src/fullfile.c @@ -30,21 +30,6 @@ //FIXME #562 #define MAX_XFER 15 -static int compare_fullfile(const void *a, const void *b) -{ - struct file *file1 = (struct file *)a; - struct file *file2 = (struct file *)b; - int comp; - - comp = strcmp(file1->hash, file2->hash); - if (comp != 0) { - return comp; - } - - /* they have the same hash, now let's check the version */ - return file1->last_change - file2->last_change; -} - static int download_mix_file(struct file *file) { int ret = -1; @@ -226,12 +211,12 @@ int download_fullfiles(struct list *files, int *num_downloads) complete = 0; if (list_length < MAX_FILES) { /* remove tar duplicates from the list first */ - need_download = list_sort(need_download, file_sort_hash); + need_download = list_sort(need_download, cmp_file_hash); /* different directories may need the same tar, in those cases it needs * to be downloaded only once, the tar for each file is downloaded from * /files/.tar */ - need_download = list_sorted_deduplicate(need_download, compare_fullfile, NULL); + need_download = list_sorted_deduplicate(need_download, cmp_file_hash_last_change, NULL); download_progress.total_download_size = fullfile_query_total_download_size(need_download); if (download_progress.total_download_size > 0) { diff --git a/src/hash.c b/src/hash.c index 405b5483..58070ec1 100644 --- a/src/hash.c +++ b/src/hash.c @@ -256,14 +256,6 @@ bool verify_file_lazy(char *filename) return !hash_is_zeros(local.hash); } -static int file_name_cmp(const void *a, const void *b) -{ - const struct file *fa = a; - const struct file *fb = b; - - return strcmp(fa->filename, fb->filename); -} - /* Compares the hash for BUNDLE with that listed in the Manifest.MoM. If the * hash check fails, we should assume the bundle manifest is incorrect and * discard it. A retry should then force redownloading of the bundle manifest. @@ -274,7 +266,7 @@ int verify_bundle_hash(struct manifest *mom, struct file *bundle) char *local = NULL, *cached; int ret = 0; - current = list_search(list_head(mom->manifests), bundle, file_name_cmp); + current = list_search(list_head(mom->manifests), bundle, cmp_file_filename); if (!current) { return -1; } diff --git a/src/lib/comp_functions.c b/src/lib/comp_functions.c new file mode 100644 index 00000000..f4a03ed0 --- /dev/null +++ b/src/lib/comp_functions.c @@ -0,0 +1,39 @@ +/* + * Software Updater - client side + * + * Copyright © 2012-2020 Intel Corporation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 or later of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#define _GNU_SOURCE + +#include + +#include "comp_functions.h" + +/** + * All comparison functions in this file should match this type definition: + * typedef int (*comparison_fn_t)(const void *a, const void *b); + * + * They should behave like this (similar to strcmp): + * - return 0 if a is equal to b + * - return any number "< 0" if a is lower than b + * - return any number "> 0" if a is bigger than b + */ + +int strcmp_wrapper(const void *a, const void *b) +{ + return strcmp((const char *)a, (const char *)b); +} diff --git a/src/lib/comp_functions.h b/src/lib/comp_functions.h new file mode 100644 index 00000000..f1ca73c7 --- /dev/null +++ b/src/lib/comp_functions.h @@ -0,0 +1,26 @@ +#ifndef __COMP_FUNCTIONS_H +#define __COMP_FUNCTIONS_H + +/** + * @file + * @brief Compare like functions. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Definition of a funtion type to compare two elements + */ +typedef int (*comparison_fn_t)(const void *a, const void *b); + +/** + * @brief strcmp wrapper casting void * to char *. + */ +int strcmp_wrapper(const void *a, const void *b); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/list.h b/src/lib/list.h index 4beaa00c..853ebd5d 100644 --- a/src/lib/list.h +++ b/src/lib/list.h @@ -20,6 +20,8 @@ #include #include +#include "comp_functions.h" + /** * @brief List node. */ @@ -32,15 +34,6 @@ struct list { struct list *next; }; -/** - * @brief Callback to compare two datas in a list. - * The comparison function should return 0 if a is equal to b, - * any number "< 0" if a is lower than b and any number "> 0" if - * a is bigger than b. - * This behavior is similar to strcmp() and other standard compare functions. - */ -typedef int (*comparison_fn_t)(const void *a, const void *b); - /** @brief Callback to free data used in list. */ typedef void (*list_free_data_fn_t)(void *data); diff --git a/src/lib/strings.c b/src/lib/strings.c index 9e162ee2..7ce4ff80 100644 --- a/src/lib/strings.c +++ b/src/lib/strings.c @@ -204,8 +204,3 @@ char *str_subchar(const char *str, char c1, char c2) return new; } - -int strcmp_wrapper(const void *a, const void *b) -{ - return strcmp((const char *)a, (const char *)b); -} diff --git a/src/lib/strings.h b/src/lib/strings.h index ecd4dbec..ee21bea8 100644 --- a/src/lib/strings.h +++ b/src/lib/strings.h @@ -12,11 +12,6 @@ extern "C" { #endif -/** - * @brief strcmp wrapper casting void * to char *. - */ -int strcmp_wrapper(const void *a, const void *b); - /** * Save in strp a new allocated string with content printed from fmt and * parameters using vasprintf. Abort on memory allocation errors. diff --git a/src/manifest.c b/src/manifest.c index 6b1662a0..57f519e0 100644 --- a/src/manifest.c +++ b/src/manifest.c @@ -43,52 +43,6 @@ #define MANIFEST_LINE_MAXLEN 8192 -/* sort by full path filename */ -int file_sort_filename(const void *a, const void *b) -{ - struct file *A, *B; - int ret; - A = (struct file *)a; - B = (struct file *)b; - - ret = strcmp(A->filename, B->filename); - if (ret) { - return ret; - } - if (A->is_deleted > B->is_deleted) { - return 1; - } - if (A->is_deleted < B->is_deleted) { - return -1; - } - - return 0; -} - -int file_sort_filename_reverse(const void *a, const void *b) -{ - struct file *A, *B; - int ret; - A = (struct file *)a; - B = (struct file *)b; - - ret = strcmp(A->filename, B->filename); - - return -ret; -} - -int file_sort_hash(const void *a, const void *b) -{ - struct file *A, *B; - int ret; - A = (struct file *)a; - B = (struct file *)b; - - ret = strcmp(A->hash, B->hash); - - return ret; -} - static struct manifest *manifest_from_file(int version, char *component, bool header_only, bool is_mix) { char *filename; @@ -557,8 +511,8 @@ void link_manifests(struct manifest *m1, struct manifest *m2) struct list *list1, *list2; struct file *file1, *file2; - m1->files = list_sort(m1->files, file_sort_filename); - m2->files = list_sort(m2->files, file_sort_filename); + m1->files = list_sort(m1->files, cmp_file_filename_is_deleted); + m2->files = list_sort(m2->files, cmp_file_filename_is_deleted); list1 = list_head(m1->files); list2 = list_head(m2->files); @@ -614,8 +568,8 @@ void link_submanifests(struct manifest *m1, struct manifest *m2, struct list *su struct list *list1, *list2; struct file *file1, *file2; - m1->manifests = list_sort(m1->manifests, file_sort_filename); - m2->manifests = list_sort(m2->manifests, file_sort_filename); + m1->manifests = list_sort(m1->manifests, cmp_file_filename_is_deleted); + m2->manifests = list_sort(m2->manifests, cmp_file_filename_is_deleted); list1 = list_head(m1->manifests); list2 = list_head(m2->manifests); @@ -720,7 +674,7 @@ struct list *consolidate_files(struct list *files) struct list *list, *next, *tmp; struct file *file1, *file2; - files = list_sort(files, file_sort_filename); + files = list_sort(files, cmp_file_filename_is_deleted); /* Two pointers ("list" and "next") traverse the consolidated, filename sorted * struct list of files. The "list" pointer is marched forward through the @@ -835,7 +789,7 @@ static struct list *list_common_files(struct list *list1, struct list *list2) l2 = list_clone(list2); combined = list_concat(l1, l2); - combined = list_sort(combined, file_sort_filename); + combined = list_sort(combined, cmp_file_filename_is_deleted); for (list = list_head(combined); list; list = list->next) { if (list->next == NULL) { @@ -899,7 +853,7 @@ struct list *filter_out_existing_files(struct list *to_install_files, struct lis /* remove the common files from the to_install_files */ to_install_files = list_concat(to_install_files, common); - to_install_files = list_sort(to_install_files, file_sort_filename); + to_install_files = list_sort(to_install_files, cmp_file_filename_is_deleted); list = list_head(to_install_files); while (list) { if (list->next == NULL) { @@ -1053,14 +1007,9 @@ void deduplicate_files_from_manifest(struct manifest **m1, struct manifest *m2) bmanifest->files = list_head(preserver); } -static int file_bundlename_strcmp(const void *a, const void *b) -{ - return strcmp(((struct file *)a)->filename, (const char *)b); -} - struct file *mom_search_bundle(struct manifest *mom, const char *bundlename) { - return list_search(mom->manifests, bundlename, file_bundlename_strcmp); + return list_search(mom->manifests, bundlename, cmp_file_filename_string); } /* This performs a linear search through the files list. */ @@ -1114,11 +1063,6 @@ void manifest_free_array(struct file **array) free(array); } -static int cmpnames(const void *a, const void *b) -{ - return strcmp((*(struct file **)a)->filename, (*(struct file **)b)->filename); -} - static bool is_version_data(const char *filename) { if (strcmp(filename, "/usr/lib/os-release") == 0 || @@ -1140,7 +1084,7 @@ int enforce_compliant_manifest(struct file **a, struct file **b, int searchsize, struct file **found; int ret = 0; - qsort(b, size, sizeof(struct file *), cmpnames); + qsort(b, size, sizeof(struct file *), cmp_file_filename_ptr); info("Checking manifest uniqueness...\n"); for (int i = 0; i < searchsize; i++) { found = bsearch(a[i], b, size, sizeof(struct file *), bsearch_file_helper); @@ -1221,19 +1165,6 @@ int mom_get_manifests_list(struct manifest *mom, struct list **manifest_list, fi return last_error; } -int manifest_bundlename_strcmp(const void *a, const void *b) -{ - return strcmp(((struct manifest *)a)->component, (const char *)b); -} - -int manifest_component_strcmp(const void *a, const void *b) -{ - struct manifest *m1 = (struct manifest *)a; - struct manifest *m2 = (struct manifest *)b; - - return strcmp(m1->component, m2->component); -} - int recurse_dependencies(struct manifest *mom, const char *bundle, struct list **manifests, filter_fn_t filter_fn) { int err = 0; @@ -1244,7 +1175,7 @@ int recurse_dependencies(struct manifest *mom, const char *bundle, struct list * return 0; } - if (list_search(*manifests, bundle, manifest_bundlename_strcmp)) { + if (list_search(*manifests, bundle, cmp_manifest_component_string)) { return 0; } diff --git a/src/manifest.h b/src/manifest.h index 1e8519ef..871f952d 100644 --- a/src/manifest.h +++ b/src/manifest.h @@ -97,17 +97,6 @@ int mom_get_manifests_list(struct manifest *mom, struct list **manifest_list, fi */ int recurse_dependencies(struct manifest *mom, const char *bundle, struct list **manifests, filter_fn_t filter_fn); -/** - * @brief Compares the "component" of a manifest "a" to a string "b" - */ -int manifest_bundlename_strcmp(const void *a, const void *b); - -/** - * @brief Compares the "component" of a manifest "a" - * to the "component" of string "b" - */ -int manifest_component_strcmp(const void *a, const void *b); - #ifdef __cplusplus } #endif diff --git a/src/search_file.c b/src/search_file.c index 45524372..5671ea3e 100644 --- a/src/search_file.c +++ b/src/search_file.c @@ -84,14 +84,6 @@ static int bundle_cmp(const void *bundle, const void *bundle_name) return strcmp(b->bundle_name, bundle_name); } -static int manifest_name_cmp(const void *a, const void *b) -{ - const struct manifest *ma = a; - const struct manifest *mb = b; - - return strcmp(ma->component, mb->component); -} - static int manifest_str_cmp(const void *manifest, const void *manifest_name) { const struct manifest *m = manifest; @@ -345,7 +337,7 @@ static int do_search(struct manifest *mom, const char *search_term) int regexp_err; if (sort == SORT_TYPE_ALPHA_BUNDLES_ONLY || sort == SORT_TYPE_ALPHA) { - manifest_list = list_sort(manifest_list, manifest_name_cmp); + manifest_list = list_sort(manifest_list, cmp_manifest_component); } else if (sort == SORT_TYPE_SIZE) { // pre process the bundle size of all bundles for sorting for (l = manifest_list; l; l = l->next) { diff --git a/src/subscriptions.c b/src/subscriptions.c index 0400df47..4dd9ff8c 100644 --- a/src/subscriptions.c +++ b/src/subscriptions.c @@ -53,23 +53,6 @@ struct list *free_list_file(struct list *item) return list_free_item(item, free_file_data); } -int subscription_bundlename_strcmp(const void *a, const void *b) -{ - return strcmp(((struct sub *)a)->component, (const char *)b); -} - -int subscription_sort_component(const void *a, const void *b) -{ - struct sub *A, *B; - int ret; - A = (struct sub *)a; - B = (struct sub *)b; - - ret = strcmp(A->component, B->component); - - return ret; -} - /* Custom content comes from a different location and is not required to * have os-core added */ void read_subscriptions(struct list **subs) @@ -112,7 +95,7 @@ void read_subscriptions(struct list **subs) create_and_append_subscription(subs, "os-core"); } - *subs = list_sort(*subs, subscription_sort_component); + *subs = list_sort(*subs, cmp_subscription_component); } static bool set_subscription_obligation(struct list *subs, char *component, bool is_optional) diff --git a/src/swupd.h b/src/swupd.h index 97b5cf61..cfc802f8 100644 --- a/src/swupd.h +++ b/src/swupd.h @@ -15,6 +15,7 @@ #include "config_loader.h" #include "globals.h" #include "lib/archives.h" +#include "lib/comp_functions.h" #include "lib/config_file.h" #include "lib/formatter_json.h" #include "lib/list.h" @@ -26,6 +27,7 @@ #include "manifest.h" #include "progress.h" #include "scripts.h" +#include "swupd_comp_functions.h" #include "swupd_curl.h" #include "swupd_exit_codes.h" #include "swupd_progress.h" @@ -175,9 +177,6 @@ extern int get_server_format(int server_version); extern bool ignore(struct file *file); extern void apply_heuristics(struct file *file); -extern int file_sort_filename(const void *a, const void *b); -extern int file_sort_filename_reverse(const void *a, const void *b); -extern int file_sort_hash(const void *a, const void *b); extern struct manifest *load_mom(int version, bool mix_exists, int *err); extern struct manifest *load_manifest(int version, struct file *file, struct manifest *mom, bool header_only, int *err); extern struct manifest *load_manifest_full(int version, bool mix); @@ -327,8 +326,6 @@ extern void create_and_append_subscription(struct list **subs, const char *compo extern char *get_tracking_dir(void); extern int add_subscriptions(struct list *bundles, struct list **subs, struct manifest *mom, bool find_all, int recursion); extern int subscription_get_tree(struct list *bundles, struct list **subs, struct manifest *mom, bool find_all, int recursion); -extern int subscription_bundlename_strcmp(const void *a, const void *b); -extern int subscription_sort_component(const void *a, const void *b); /* bundle_add.c */ extern enum swupd_code execute_bundle_add(struct list *bundles_list); diff --git a/src/swupd_comp_functions.c b/src/swupd_comp_functions.c new file mode 100644 index 00000000..f83d7434 --- /dev/null +++ b/src/swupd_comp_functions.c @@ -0,0 +1,136 @@ +/* + * Software Updater - client side + * + * Copyright © 2012-2020 Intel Corporation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 or later of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#define _GNU_SOURCE + +#include + +#include "swupd.h" + +/** + * All functions in this file should match this type definition: + * typedef int (*comparison_fn_t)(const void *a, const void *b); + * + * They should behave like this (similar to strcmp): + * - return 0 if a is equal to b + * - return any number "< 0" if a is lower than b + * - return any number "> 0" if a is bigger than b + * + * Naming convention: + * + * If both elements being compared are the same type and subtype: + * cmp__ + * + * If both elements being compared are different type or subtype: + * cmp____ + */ + +int cmp_string_filerecord_filename(const void *a, const void *b) +{ + return strcmp(*(const char **)a, ((struct filerecord *)b)->filename); +} + +int cmp_file_filename(const void *a, const void *b) +{ + return strcmp(((struct file *)a)->filename, ((struct file *)b)->filename); +} + +int cmp_file_filename_ptr(const void *a, const void *b) +{ + return strcmp((*(struct file **)a)->filename, (*(struct file **)b)->filename); +} + +int cmp_filerecord_filename(const void *a, const void *b) +{ + return strcmp(((struct filerecord *)a)->filename, ((struct filerecord *)b)->filename); +} + +int cmp_file_hash(const void *a, const void *b) +{ + return strcmp(((struct file *)a)->hash, ((struct file *)b)->hash); +} + +int cmp_manifest_component(const void *a, const void *b) +{ + return strcmp(((struct manifest *)a)->component, ((struct manifest *)b)->component); +} + +int cmp_subscription_component(const void *a, const void *b) +{ + return strcmp(((struct sub *)a)->component, ((struct sub *)b)->component); +} + +int cmp_manifest_component_string(const void *a, const void *b) +{ + return strcmp(((struct manifest *)a)->component, (const char *)b); +} + +int cmp_file_filename_string(const void *a, const void *b) +{ + return strcmp(((struct file *)a)->filename, (const char *)b); +} + +int cmp_sub_component_string(const void *a, const void *b) +{ + return strcmp(((struct sub *)a)->component, (const char *)b); +} + +int cmp_file_filename_reverse(const void *a, const void *b) +{ + int ret; + + ret = cmp_file_filename(a, b); + return -ret; +} + +int cmp_file_hash_last_change(const void *a, const void *b) +{ + struct file *file1 = (struct file *)a; + struct file *file2 = (struct file *)b; + int comp; + + comp = strcmp(file1->hash, file2->hash); + if (comp != 0) { + return comp; + } + + /* they have the same hash, now let's check the version */ + return file1->last_change - file2->last_change; +} + +int cmp_file_filename_is_deleted(const void *a, const void *b) +{ + struct file *A, *B; + int ret; + A = (struct file *)a; + B = (struct file *)b; + + ret = strcmp(A->filename, B->filename); + if (ret) { + return ret; + } + if (A->is_deleted > B->is_deleted) { + return 1; + } + if (A->is_deleted < B->is_deleted) { + return -1; + } + + return 0; +} diff --git a/src/swupd_comp_functions.h b/src/swupd_comp_functions.h new file mode 100644 index 00000000..29100857 --- /dev/null +++ b/src/swupd_comp_functions.h @@ -0,0 +1,56 @@ +#ifndef __SWUPD_COMP_FUNCTIONS__ +#define __SWUPD_COMP_FUNCTIONS__ + +/** + * @file + * @brief Compare-like functions used as arguments of other swupd functions + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* compare file->filename with file->filename */ +int cmp_file_filename(const void *a, const void *b); + +/* compare a pointer to file->filename with a pointer to file->filename */ +int cmp_file_filename_ptr(const void *a, const void *b); + +/* compare file->hash with file->hash */ +int cmp_file_hash(const void *a, const void *b); + +/* compare filerecord->filename with filerecord->filename */ +int cmp_filerecord_filename(const void *a, const void *b); + +/* compare manifest->component with manifest->component */ +int cmp_manifest_component(const void *a, const void *b); + +/* compare sub->component with sub->component */ +int cmp_subscription_component(const void *a, const void *b); + +/* compare manifest->component with a string */ +int cmp_manifest_component_string(const void *a, const void *b); + +/* compare file->filename with a string */ +int cmp_file_filename_string(const void *a, const void *b); + +/* compare sub->component with a string */ +int cmp_sub_component_string(const void *a, const void *b); + +/* compare a string with filerecord->filename */ +int cmp_string_filerecord_filename(const void *a, const void *b); + +/* compare file->filename with file->filename + * @returns an inverse result */ +int cmp_file_filename_reverse(const void *a, const void *b); + +/* compare file->hash, file->last_change with file->hash, file->last_change */ +int cmp_file_hash_last_change(const void *a, const void *b); + +/* compare file->filename, file->is_deleted with file->filename, file->is_deleted */ +int cmp_file_filename_is_deleted(const void *a, const void *b); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/update.c b/src/update.c index 662b9db9..2899f7b4 100644 --- a/src/update.c +++ b/src/update.c @@ -505,7 +505,7 @@ version_check: /* need update list in filename order to insure directories are * created before their contents */ timelist_timer_start(globals.global_times, "Update loop"); - updates = list_sort(updates, file_sort_filename); + updates = list_sort(updates, cmp_file_filename_is_deleted); ret = update_loop(updates, server_manifest); if (ret == 0 && !download_only) { diff --git a/src/verify.c b/src/verify.c index 8b13edca..3c05f0c8 100644 --- a/src/verify.c +++ b/src/verify.c @@ -485,7 +485,7 @@ static void remove_orphaned_files(struct manifest *official_manifest, bool repai info("%s extraneous files\n", repair ? "Removing" : "Checking for"); - official_manifest->files = list_sort(official_manifest->files, file_sort_filename_reverse); + official_manifest->files = list_sort(official_manifest->files, cmp_file_filename_reverse); iter = list_head(official_manifest->files); while (iter) { @@ -775,7 +775,7 @@ static enum swupd_code deal_with_extra_files(struct manifest *manifest, bool fix return ret; } -static int find_unsafe_to_delete(const void *a, const void *b) +static int filter_file_unsafe_to_delete(const void *a, const void *b) { struct file *A, *B; int ret; @@ -1056,7 +1056,7 @@ enum swupd_code execute_verify(void) * are compared against the full list of consolidated files * from all bundles so we don't end up deleting a file that * is needed by another bundle */ - bundles_files = list_sorted_filter_common_elements(bundles_files, all_files, find_unsafe_to_delete, NULL); + bundles_files = list_sorted_filter_common_elements(bundles_files, all_files, filter_file_unsafe_to_delete, NULL); official_manifest->files = bundles_files; /* at this point we no longer need the data regarding bundles @@ -1171,7 +1171,7 @@ brick_the_system_and_clean_curl: char *bundle = iter->data; /* make sure the bundle was in fact valid and will * be installed before creating the tracking file */ - if (list_search(bundles_subs, bundle, subscription_bundlename_strcmp)) { + if (list_search(bundles_subs, bundle, cmp_sub_component_string)) { track_bundle_in_statedir(bundle, new_os_statedir); } }