int rename_all_files_to_final(struct list *updates) { int ret, update_errs = 0, update_good = 0, skip = 0; struct list *list; list = list_head(updates); while (list) { struct file *file; file = list->data; list = list->next; if (file->do_not_update) { skip += 1; continue; } ret = rename_staged_file_to_final(file); if (ret != 0) { update_errs += 1; } else { update_good += 1; } } return update_count - update_good - update_errs - (update_skip - skip); }
int rename_all_files_to_final(struct list *updates) { int ret, update_errs = 0, update_good = 0, skip = 0; struct list *list; unsigned int complete = 0; unsigned int list_length = list_len(updates); list = list_head(updates); while (list) { struct file *file; file = list->data; list = list->next; complete++; if (file->do_not_update) { skip += 1; continue; } ret = rename_staged_file_to_final(file); if (ret != 0) { update_errs += 1; } else { update_good += 1; } print_progress(complete, list_length); } print_progress(list_length, list_length); /* Force out 100% */ printf("\n"); return update_count - update_good - update_errs - (update_skip - skip); }
/* Bundle install one ore more bundles passed in bundles * param as a null terminated array of strings */ int install_bundles(char **bundles) { int lock_fd; int ret = 0; int current_version; struct manifest *mom; struct list *iter; struct sub *sub; struct file *file; /* step 1: initialize swupd and get current version from OS */ if (!init_globals()) { return EINIT_GLOBALS; } ret = swupd_init(&lock_fd); if (ret != 0) { printf("Failed updater initialization, exiting now.\n"); return ret; } current_version = read_version_from_subvol_file(path_prefix); swupd_curl_set_current_version(current_version); /* first of all, make sure STATE_DIR is there, recreate if necessary*/ ret = create_required_dirs(); if (ret != 0) { printf("State directory %s cannot be recreated, aborting installation\n", STATE_DIR); goto clean_and_exit; } ret = load_manifests(current_version, current_version, "MoM", NULL, &mom); if (ret != 0) { printf("Cannot load official manifest MoM for version %i\n", current_version); ret = EMOM_NOTFOUND; goto clean_and_exit; } /* step 2: check bundle args are valid if so populate subs struct */ int i; for (i = 0; *bundles; ++bundles) { if (is_tracked_bundle(*bundles)) { printf("%s bundle already installed, skipping it\n", *bundles); continue; } if (!manifest_has_component(mom, *bundles)) { printf("%s bundle name is invalid, skipping it...\n", *bundles); continue; } if (component_subscribed(*bundles)) { continue; } create_and_append_subscription(*bundles); i++; printf("Added bundle %s for installation\n", *bundles); } if (i == 0) { printf("There are no pending bundles to install, exiting now\n"); ret = EBUNDLE_INSTALL; goto clean_manifest_and_exit; } subscription_versions_from_MoM(mom, 0); recurse_manifest(mom, NULL); consolidate_submanifests(mom); /* step 3: download neccessary packs */ ret = rm_staging_dir_contents("download"); printf("Downloading required packs...\n"); ret = download_subscribed_packs(0, current_version, true); if (ret != 0) { printf("pack downloads failed, cannot proceed with the installation, exiting.\n"); goto clean_subs_and_exit; } /* step 4: Install all bundle(s) files into the fs */ printf("Installing bundle(s) files...\n"); iter = list_head(mom->files); while (iter) { file = iter->data; iter = iter->next; if (file->is_deleted || file->do_not_update || ignore(file)) { continue; } ret = do_staging(file); if (ret == 0) { rename_staged_file_to_final(file); } } sync(); /* step 5: create bundle(s) subscription entries to track them * * Strictly speaking each manifest has an entry to write its own bundle filename * and thus tracking automagically, here just making sure. */ iter = list_head(subs); while (iter) { sub = iter->data; iter = iter->next; printf("Tracking %s bundle on the system\n", sub->component); ret = track_bundle_in_system(sub->component); if (ret != 0) { printf("Cannot track %s bundle on the system\n", sub->component); } } /* Run any scripts that are needed to complete update */ run_scripts(); ret = 0; printf("Bundle(s) installation done.\n"); clean_subs_and_exit: free_subscriptions(); clean_manifest_and_exit: free_manifest(mom); clean_and_exit: swupd_curl_cleanup(); v_lockfile(lock_fd); dump_file_descriptor_leaks(); free_globals(); return ret; }
int install_bundles(struct list *bundles, int current_version, struct manifest *mom) { int ret; struct file *file; struct list *iter; struct list *to_install_bundles, *to_install_files; /* step 1: check bundle args are valid if so populate subs struct */ ret = add_subscriptions(bundles, current_version, mom); if (ret) { if (ret == 1) { printf("bundle(s) already installed, exiting now\n"); } ret = EBUNDLE_INSTALL; goto out; } subscription_versions_from_MoM(mom, 0); to_install_bundles = recurse_manifest(mom, NULL); if (!to_install_bundles) { printf("Error: Cannot load to install bundles\n"); ret = ERECURSE_MANIFEST; goto out; } to_install_files = files_from_bundles(to_install_bundles); to_install_files = consolidate_files(to_install_files); /* step 2: download neccessary packs */ (void)rm_staging_dir_contents("download"); printf("Downloading packs...\n"); (void)download_subscribed_packs(true); /* step 3: Add tracked bundles */ read_subscriptions_alt(); subscription_versions_from_MoM(mom, 0); mom->submanifests = recurse_manifest(mom, NULL); if (!mom->submanifests) { printf("Error: Cannot load installed bundles\n"); ret = ERECURSE_MANIFEST; goto out; } mom->files = files_from_bundles(mom->submanifests); mom->files = consolidate_files(mom->files); /* step 4: Install all bundle(s) files into the fs */ printf("Installing bundle(s) files...\n"); iter = list_head(to_install_files); while (iter) { file = iter->data; iter = iter->next; if (file->is_deleted || file->do_not_update || ignore(file)) { continue; } ret = do_staging(file, mom); if (ret) { ret = verify_fix_path(file->filename, mom); } if (ret) { ret = EBUNDLE_INSTALL; goto out; } } iter = list_head(to_install_files); while (iter) { file = iter->data; iter = iter->next; if (file->is_deleted || file->do_not_update || ignore(file)) { continue; } /* This was staged by verify_fix_path */ if (!file->staging) { file = search_file_in_manifest(mom, file->filename); } rename_staged_file_to_final(file); } sync(); /* step 5: Run any scripts that are needed to complete update */ run_scripts(); ret = 0; printf("Bundle(s) installation done.\n"); out: free_subscriptions(); return ret; }
int install_bundles(struct list *bundles, int current_version, struct manifest *mom) { int ret; struct file *file; struct list *iter; struct sub *sub; /* step 1: check bundle args are valid if so populate subs struct */ ret = add_subscriptions(bundles, current_version, mom); if (ret) { if (ret == 1) { printf("bundle(s) already installed, exiting now\n"); } ret = EBUNDLE_INSTALL; goto out; } subscription_versions_from_MoM(mom, 0); ret = recurse_manifest(mom, NULL); if (ret != 0) { printf("Error: Cannot load MoM sub-manifests (ret = %d)\n", ret); ret = ERECURSE_MANIFEST; goto out; } consolidate_submanifests(mom); /* step 2: download neccessary packs */ (void)rm_staging_dir_contents("download"); printf("Downloading required packs...\n"); ret = download_subscribed_packs(true); if (ret != 0) { printf("pack downloads failed, cannot proceed with the installation, exiting.\n"); goto out; } /* step 3: Install all bundle(s) files into the fs */ printf("Installing bundle(s) files...\n"); iter = list_head(mom->files); while (iter) { file = iter->data; iter = iter->next; if (file->is_deleted || file->do_not_update || ignore(file)) { continue; } ret = do_staging(file, mom); if (ret == 0) { rename_staged_file_to_final(file); } } sync(); /* step 4: create bundle(s) subscription entries to track them * * Strictly speaking each manifest has an entry to write its own bundle filename * and thus tracking automagically, here just making sure. */ iter = list_head(subs); while (iter) { sub = iter->data; iter = iter->next; printf("Tracking %s bundle on the system\n", sub->component); ret = track_bundle_in_system(sub->component); if (ret != 0) { printf("Cannot track %s bundle on the system\n", sub->component); } } /* step 5: Run any scripts that are needed to complete update */ run_scripts(); ret = 0; printf("Bundle(s) installation done.\n"); out: free_subscriptions(); return ret; }
static void deal_with_hash_mismatches(struct manifest *official_manifest, bool repair) { int ret; struct list *iter; /* for each expected and present file which hash-mismatches vs the manifest, replace the file */ iter = list_head(official_manifest->files); while (iter) { struct file *file; char *fullname; file = iter->data; iter = iter->next; // Note: boot files not marked as deleted are candidates for verify/fix if (file->is_deleted || ignore(file)) { continue; } file_checked_count++; // do_not_update set by earlier check, so account as checked if (file->do_not_update) { continue; } /* compare the hash and report mismatch */ fullname = mk_full_filename(path_prefix, file->filename); if (fullname == NULL) { abort(); } if (verify_file(file, fullname)) { free(fullname); continue; } else { file_mismatch_count++; printf("Hash mismatch for file: %s\n", fullname); } /* if not repairing, we're done */ if (!repair) { free(fullname); continue; } /* install the new file (on miscompare + fix) */ ret = do_staging(file, official_manifest); if (ret == 0) { rename_staged_file_to_final(file); } /* at the end of all this, verify the hash again to judge success */ if (verify_file(file, fullname)) { file_fixed_count++; printf("\tfixed\n"); } else { file_not_fixed_count++; printf("\tnot fixed\n"); } free(fullname); } }
/* for each missing but expected file, (re)add the file */ static void add_missing_files(struct manifest *official_manifest) { int ret; struct file local; struct list *iter; iter = list_head(official_manifest->files); while (iter) { struct file *file; char *fullname; file = iter->data; iter = iter->next; if ((file->is_deleted) || (file->do_not_update)) { continue; } fullname = mk_full_filename(path_prefix, file->filename); if (fullname == NULL) { abort(); } memset(&local, 0, sizeof(struct file)); local.filename = file->filename; populate_file_struct(&local, fullname); ret = compute_hash_lazy(&local, fullname); if (ret != 0) { file_not_replaced_count++; free(fullname); continue; } /* compare the hash and report mismatch */ if (hash_is_zeros(local.hash)) { file_missing_count++; if (cmdline_option_install == false) { printf("Missing file: %s\n", fullname); } } else { free(fullname); continue; } /* install the new file (on miscompare + fix) */ ret = do_staging(file, official_manifest); if (ret == 0) { rename_staged_file_to_final(file); } /* verify the hash again to judge success */ populate_file_struct(&local, fullname); if (cmdline_option_quick) { ret = compute_hash_lazy(&local, fullname); } else { ret = compute_hash(&local, fullname); } if ((ret != 0) || hash_needs_work(file, local.hash)) { file_not_replaced_count++; printf("\tnot fixed\n"); } else { file_replaced_count++; file->do_not_update = 1; if (cmdline_option_install == false) { printf("\tfixed\n"); } } free(fullname); } }