From 86786b94cacdd18cf1245bdda29f23e8a3e271dc Mon Sep 17 00:00:00 2001 From: Castulo Martinez Date: Thu, 16 Jan 2020 08:10:23 -0800 Subject: [PATCH] Organizing compare like functions We used compare-like functions as arguments to other functions that filter, sort, compare data. These functions are scattered accros the code and they are sometimes difficult to identify so there is a lot of code duplication. This commit organizes all the compare like functions throughout the code in the same place and with standard naming so it is easier to find them and reuse them. Closes #1167 Signed-off-by: Castulo Martinez --- Makefile.am | 4 ++ src/bundle_info.c | 6 +- src/bundle_list.c | 4 +- src/bundle_remove.c | 34 +++------- src/extra_files.c | 16 +---- src/fullfile.c | 19 +----- src/hash.c | 10 +-- src/lib/comp_functions.c | 39 +++++++++++ src/lib/comp_functions.h | 26 +++++++ src/lib/list.h | 11 +-- src/lib/strings.c | 5 -- src/lib/strings.h | 5 -- src/manifest.c | 89 +++--------------------- src/manifest.h | 11 --- src/search_file.c | 10 +-- src/subscriptions.c | 19 +----- src/swupd.h | 7 +- src/swupd_comp_functions.c | 136 +++++++++++++++++++++++++++++++++++++ src/swupd_comp_functions.h | 56 +++++++++++++++ src/update.c | 2 +- src/verify.c | 8 +-- 21 files changed, 300 insertions(+), 217 deletions(-) create mode 100644 src/lib/comp_functions.c create mode 100644 src/lib/comp_functions.h create mode 100644 src/swupd_comp_functions.c create mode 100644 src/swupd_comp_functions.h 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); } }