/* this function is intended to encapsulate the basic swupd * initializations for the majority of commands, that is: * - Make sure root is the user running the code * - Initialize globals * - initialize mounted directories * - Create necessary directories * - Get the lock * - Initialize curl * - Initialize signature checking */ int swupd_init(void) { int ret = 0; check_root(); record_fds(); /* Check that our system time is reasonably valid before continuing, * or the certificate verification will fail with invalid time */ if (timecheck) { if (!verify_time()) { ret = EBADTIME; goto out_fds; } } if (!init_globals()) { ret = EINIT_GLOBALS; goto out_fds; } get_mounted_directories(); if (create_required_dirs()) { ret = EREQUIRED_DIRS; goto out_fds; } if (p_lockfile() < 0) { ret = ELOCK_FILE; goto out_fds; } if (swupd_curl_init() != 0) { ret = ECURL_INIT; goto out_close_lock; } /* If --nosigcheck, we do not attempt any signature checking */ if (sigcheck && !initialize_signature()) { ret = ESIGNATURE; terminate_signature(); goto out_close_lock; } return ret; out_close_lock: v_lockfile(); out_fds: dump_file_descriptor_leaks(); return ret; }
/* * list_installable_bundles() * Parse the full manifest for the current version of the OS and print * all available bundles. */ int list_installable_bundles() { struct list *list; struct file *file; struct manifest *MoM = NULL; int current_version; int lock_fd; int ret; if (!init_globals()) { return EINIT_GLOBALS; } current_version = read_version_from_subvol_file(path_prefix); if (swupd_init(&lock_fd) != 0) { printf("Error: Failed updater initialization. Exiting now\n"); return ECURL_INIT; } ret = create_required_dirs(); if (ret != 0) { printf("State directory %s cannot be recreated, aborting removal\n", STATE_DIR); v_lockfile(lock_fd); return EXIT_FAILURE; } get_mounted_directories(); if (!check_network()) { printf("Error: Network issue, unable to download manifest\n"); v_lockfile(lock_fd); return EXIT_FAILURE; } swupd_curl_set_current_version(current_version); ret = load_manifests(current_version, current_version, "MoM", NULL, &MoM); if (ret != 0) { v_lockfile(lock_fd); return ret; } list = MoM->manifests; while (list) { file = list->data; list = list->next; printf("%s\n", file->filename); } free_manifest(MoM); v_lockfile(lock_fd); return 0; }
/* this function is intended to encapsulate the basic swupd * initializations for the majority of commands, that is: * - Make sure root is the user running the code * - Initialize log facility * - Get the lock * - initialize mounted directories * - Initialize curl */ int swupd_init(int *lock_fd) { int ret = 0; check_root(); if (!init_globals()) { ret = EINIT_GLOBALS; goto out_fds; } get_mounted_directories(); if (create_required_dirs()) { ret = EREQUIRED_DIRS; goto out_fds; } *lock_fd = p_lockfile(); if (*lock_fd < 0) { ret = ELOCK_FILE; goto out_fds; } if (swupd_curl_init() != 0) { ret = ECURL_INIT; goto out_close_lock; } if (!initialize_signature()) { ret = ESIGNATURE; terminate_signature(); goto out_close_lock; } return ret; out_close_lock: v_lockfile(*lock_fd); out_fds: dump_file_descriptor_leaks(); return ret; }
int search_main(int argc, char **argv) { int ret = 0; int lock_fd; struct manifest *MoM = NULL; if (!parse_options(argc, argv) || create_required_dirs()) { return EXIT_FAILURE; } if (search_type == '0') { /* Default to a system-side search */ search_type = 'e'; } if (!init_globals()) { ret = EINIT_GLOBALS; goto clean_exit; } ret = swupd_init(&lock_fd); if (ret != 0) { printf("Failed swupd initialization, exiting now.\n"); goto clean_exit; } if (!check_network()) { printf("Error: Network issue, unable to proceed with update\n"); ret = EXIT_FAILURE; goto clean_exit; } if (!init) { printf("Searching for '%s'\n\n", search_string); } ret = download_manifests(&MoM); if (ret != 0) { printf("Error: Failed to download manifests\n"); goto clean_exit; } if (init) { printf("Successfully retreived manifests. Exiting\n"); ret = 0; goto clean_exit; } /* Arbitrary upper limit to ensure we aren't getting handed garbage */ if (!display_files && ((strlen(search_string) <= 0) || (strlen(search_string) > NAME_MAX))) { printf("Error - search string invalid\n"); ret = EXIT_FAILURE; goto clean_exit; } do_search(MoM, search_type, search_string); clean_exit: free_manifest(MoM); free_globals(); swupd_curl_cleanup(); return ret; }
/* 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; }
/* This function is a fresh new implementation for a bundle * remove without being tied to verify loop, this means * improved speed and space as well as more roubustness and * flexibility. What it does is basically: * * 1) Read MoM and load all submanifests except the one to be * removed and then consolidate them. * 2) Load the removed bundle submanifest. * 3) Order the file list by filename * 4) Deduplicate removed submanifest file list that happens * to be on the MoM (minus bundle to be removed). * 5) iterate over to be removed bundle submanifest file list * performing a unlink(2) for each filename. * 6) Done. */ int remove_bundle(const char *bundle_name) { int lock_fd; int ret = 0; int current_version = CURRENT_OS_VERSION; struct manifest *current_mom, *bundle_manifest; /* Initially we don't support format nor path_prefix * for bundle_rm but eventually that will be added, then * set_format_string() and init_globals() must be pulled out * to the caller to properly initialize in case those opts * passed to the command. */ set_format_string(NULL); if (!init_globals()) { return EINIT_GLOBALS; } ret = swupd_init(&lock_fd); if (ret != 0) { printf("Failed updater initialization, exiting now.\n"); return ret; } /* os-core bundle not allowed to be removed... * although this is going to be caught later because of all files * being marked as 'duplicated' and note removing anything * anyways, better catch here and return success, no extra work to be done. */ if (strcmp(bundle_name, "os-core") == 0) { ret = EBUNDLE_NOT_TRACKED; goto out_free_curl; } if (!is_tracked_bundle(bundle_name)) { ret = EBUNDLE_NOT_TRACKED; goto out_free_curl; } 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 removal\n", STATE_DIR); goto out_free_curl; } ret = load_manifests(current_version, current_version, "MoM", NULL, ¤t_mom); if (ret != 0) { goto out_free_curl; } /* load all tracked bundles into memory */ read_subscriptions_alt(); /* now popout the one to be removed */ ret = unload_tracked_bundle(bundle_name); if (ret != 0) { goto out_free_mom; } subscription_versions_from_MoM(current_mom, 0); /* load all submanifest minus the one to be removed */ recurse_manifest(current_mom, NULL); consolidate_submanifests(current_mom); /* Now that we have the consolidated list of all files, load bundle to be removed submanifest*/ ret = load_bundle_manifest(bundle_name, current_version, &bundle_manifest); if (ret != 0) { goto out_free_mom; } /* deduplication needs file list sorted by filename, do so */ bundle_manifest->files = list_sort(bundle_manifest->files, file_sort_filename); deduplicate_files_from_manifest(&bundle_manifest, current_mom); printf("Deleting bundle files...\n"); remove_files_in_manifest_from_fs(bundle_manifest); printf("Untracking bundle from system...\n"); rm_bundle_file(bundle_name); printf("Success: Bundle removed\n"); free_manifest(bundle_manifest); out_free_mom: free_manifest(current_mom); out_free_curl: if (ret) { printf("Error: Bundle remove failed\n"); } swupd_curl_cleanup(); v_lockfile(lock_fd); dump_file_descriptor_leaks(); return ret; }