Implement --file option for diagnose/repair

When diagnosing/repairing a system, sometimes is useful to only
diagnose/repair a specific file or path.

This commit implements the --file option for diagnose/repair so a file
or path can be diagnosed only instead of doing it to the whole OS or a
whole bundle.

Closes #1150

Signed-off-by: Castulo Martinez <castulo.martinez@intel.com>
This commit is contained in:
Castulo Martinez
2020-01-28 15:01:47 -08:00
committed by Otavio Pontes
parent ade1f3f75e
commit a562fb4fd3
16 changed files with 673 additions and 60 deletions
+6
View File
@@ -282,6 +282,9 @@
# Like --picky, but it only searches for extra files (boolean value)
#extra_files_only=<true/false>
# Forces swupd to only diagnose the specified file or directory (recursively)
#file=[PATH]
[repair]
@@ -319,6 +322,9 @@
# Like --picky, but it only removes extra files (boolean value)
#extra_files_only=<true/false>
# Forces swupd to only repair the specified file or directory (recursively)
#file=[PATH]
[os-install]
+2 -2
View File
@@ -5,7 +5,7 @@ Release vX.XX.XX
Bug Fixes:
Features:
- Add a bundle-remove --recursive flag to remove a bundle and all its dependencies from
the system (with some exceptions, e.g. dependencies required by other installed bundles).
- Add the --file flag to diagnose and repair to allow users to diagnose/repair a specific
file or directory (recursively).
Tests:
+10
View File
@@ -483,6 +483,11 @@ SUBCOMMANDS
Like ``--picky``, but it only looks for extra files. It omits checking
hash values, and for missing files, directories and/or symlinks.
- ``--file``
Forces swupd to only diagnose the specified file or directory
(recursively).
``repair``
Correct any issues found. This will overwrite incorrect file content,
@@ -558,6 +563,11 @@ SUBCOMMANDS
Like ``--picky``, but it only removes extra files. It omits repairing
corrupt files, and adding missing files, directories and/or symlinks.
- ``--file``
Forces swupd to only repair the specified file or directory
(recursively).
``os-install``
Perform system software installation in the specified location. Install
+6 -2
View File
@@ -672,9 +672,9 @@ enum swupd_code verify_fix_path(char *targetpath, struct manifest *target_MoM)
/* this subpart of the path does exist, nothing to be done */
continue;
}
info("Hash did not match for path : %s ... fixing\n", path);
warn_unlabeled(" -> Corrupt directory: %s", target);
} else if (ret == -1 && errno == ENOENT) {
info("Path %s is missing on the file system ... fixing\n", path);
warn_unlabeled(" -> Missing directory: %s", target);
} else {
goto end;
}
@@ -692,6 +692,7 @@ enum swupd_code verify_fix_path(char *targetpath, struct manifest *target_MoM)
string_or_die(&url, "%s/%i/files/%s.tar", globals.content_url, file->last_change, file->hash);
ret = swupd_curl_get_file(url, tar_dotfile);
if (ret != 0) {
warn_unlabeled(" -> not fixed\n");
error("Failed to download file %s in verify_fix_path\n", file->filename);
ret = SWUPD_COULDNT_DOWNLOAD_FILE;
unlink(tar_dotfile);
@@ -699,6 +700,7 @@ enum swupd_code verify_fix_path(char *targetpath, struct manifest *target_MoM)
}
if (untar_full_download(file) != 0) {
warn_unlabeled(" -> not fixed\n");
error("Failed to untar file %s\n", file->filename);
ret = SWUPD_COULDNT_UNTAR_FILE;
goto end;
@@ -708,9 +710,11 @@ enum swupd_code verify_fix_path(char *targetpath, struct manifest *target_MoM)
if (ret != 0) {
/* do_staging returns a swupd_code on error,
* just propagate the error */
warn_unlabeled(" -> not fixed\n");
error("Path %s failed to stage in verify_fix_path\n", path);
goto end;
}
warn_unlabeled(" -> fixed\n");
}
end:
free_string(&target);
+5
View File
@@ -190,6 +190,11 @@ char *sys_path_join(const char *prefix, const char *path);
*/
bool is_root(void);
/**
* @brief Check if the provided path is a directory
*/
bool is_dir(const char *path);
/**
* @brief Remove file or directory.
*
+21 -2
View File
@@ -24,6 +24,7 @@
#include "swupd.h"
#define FLAG_EXTRA_FILES_ONLY 2000
#define FLAG_FILE 2001
static const char picky_tree_default[] = "/usr";
static const char picky_whitelist_default[] = "/usr/lib/modules|/usr/lib/kernel|/usr/local|/usr/src";
@@ -33,6 +34,7 @@ static bool cmdline_option_picky = false;
static bool cmdline_option_quick = false;
static int cmdline_option_version = 0;
static char *cmdline_option_picky_tree = NULL;
static char *cmdline_option_file = NULL;
static const char *cmdline_option_picky_whitelist = picky_whitelist_default;
static bool cmdline_option_extra_files_only = false;
static struct list *cmdline_bundles = NULL;
@@ -51,6 +53,7 @@ static const struct option prog_opts[] = {
{ "quick", no_argument, 0, 'q' },
{ "extra-files-only", no_argument, 0, FLAG_EXTRA_FILES_ONLY },
{ "bundles", required_argument, 0, 'B' },
{ "file", required_argument, 0, FLAG_FILE },
};
static void print_help(void)
@@ -71,6 +74,7 @@ static void print_help(void)
print(" -X, --picky-tree=[PATH] Changes the path where --picky and --extra-files-only look for extra files\n");
print(" -w, --picky-whitelist=[RE] Directories that match the regex get skipped during --picky. Example: /usr/man|/usr/doc\n");
print(" --extra-files-only Like --picky, but it only performs this task\n");
print(" --file Forces swupd to only repair the specified file or directory (recursively)\n");
print("\n");
}
@@ -122,6 +126,11 @@ static bool parse_opt(int opt, char *optarg)
return false;
}
return true;
case FLAG_FILE:
cmdline_option_file = strdup_or_die(optarg);
/* Remove trailing '/' at the end of file/dir if any */
remove_trailing_slash(cmdline_option_file);
return true;
default:
return false;
}
@@ -211,7 +220,6 @@ enum swupd_code repair_main(int argc, char **argv)
{
enum swupd_code ret = SWUPD_OK;
int steps_in_repair;
string_or_die(&cmdline_option_picky_tree, "%s", picky_tree_default);
if (!parse_options(argc, argv)) {
print("\n");
@@ -222,10 +230,17 @@ enum swupd_code repair_main(int argc, char **argv)
ret = swupd_init(SWUPD_ALL);
if (ret != SWUPD_OK) {
error("Failed swupd initialization, exiting now\n");
free_string(&cmdline_option_picky_tree);
return ret;
}
/* if the --file flag was used, use that path for --picky as well
* unless --picky-tree was also specified, if none use default */
if (!cmdline_option_picky_tree && !cmdline_option_file) {
string_or_die(&cmdline_option_picky_tree, "%s", picky_tree_default);
} else if (!cmdline_option_picky_tree) {
cmdline_option_picky_tree = cmdline_option_file;
}
/* set options needed for the verify --fix command */
verify_set_option_install(false);
verify_set_option_fix(true);
@@ -237,6 +252,7 @@ enum swupd_code repair_main(int argc, char **argv)
verify_set_picky_tree(cmdline_option_picky_tree);
verify_set_extra_files_only(cmdline_option_extra_files_only);
verify_set_option_bundles(cmdline_bundles);
verify_set_option_file(cmdline_option_file);
/*
* Steps for repair:
@@ -265,6 +281,9 @@ enum swupd_code repair_main(int argc, char **argv)
/* run verify --fix */
ret = execute_verify();
if (cmdline_option_picky_tree != cmdline_option_file) {
free_string(&cmdline_option_file);
}
free_string(&cmdline_option_picky_tree);
if (picky_whitelist) {
regfree(picky_whitelist);
+2 -3
View File
@@ -97,13 +97,12 @@ enum swupd_code do_staging(struct file *file, struct manifest *MoM)
ret = stat(targetpath, &s);
if ((ret == -1) && (errno == ENOENT)) {
if (MoM) {
warn("Update target directory does not exist: %s. Trying to fix it\n", targetpath);
verify_fix_path(dir, MoM);
} else {
debug("Update target directory does not exist: %s. Auto-fix disabled\n", targetpath);
debug("Target directory does not exist: %s. Auto-fix disabled\n", targetpath);
}
} else if (!S_ISDIR(s.st_mode)) {
error("Update target exists but is NOT a directory: %s\n", targetpath);
error("Target exists but is NOT a directory: %s\n", targetpath);
}
if (!realpath(targetpath, real_path)) {
+1
View File
@@ -363,6 +363,7 @@ extern void verify_set_option_picky(bool opt);
extern void verify_set_picky_whitelist(regex_t *whitelist);
extern void verify_set_picky_tree(char *picky_tree);
extern void verify_set_extra_files_only(bool opt);
extern void verify_set_option_file(char *path);
/* repair.c */
extern regex_t *compile_whitelist(const char *whitelist_pattern);
+117 -36
View File
@@ -38,7 +38,9 @@
#include "swupd.h"
#define FLAG_EXTRA_FILES_ONLY 2000
#define FLAG_FILE 2001
static const char picky_tree_default[] = "/usr";
static const char picky_whitelist_default[] = "/usr/lib/modules|/usr/lib/kernel|/usr/local|/usr/src";
static bool warning_printed = false;
@@ -50,6 +52,7 @@ static bool cmdline_option_fix = false;
static bool cmdline_option_picky = false;
static char *cmdline_option_statedir_cache = NULL;
static char *cmdline_option_picky_tree = NULL;
static char *cmdline_option_file = NULL;
static const char *cmdline_option_picky_whitelist = picky_whitelist_default;
static bool cmdline_option_install = false;
static bool cmdline_option_quick = false;
@@ -76,6 +79,7 @@ static const struct option prog_opts[] = {
{ "quick", no_argument, 0, 'q' },
{ "bundles", required_argument, 0, 'B' },
{ "extra-files-only", no_argument, 0, FLAG_EXTRA_FILES_ONLY },
{ "file", required_argument, 0, FLAG_FILE },
};
/* setter functions */
@@ -152,17 +156,34 @@ void verify_set_extra_files_only(bool opt)
cmdline_option_extra_files_only = opt;
}
void verify_set_option_file(char *path)
{
free_string(&cmdline_option_file);
cmdline_option_file = path;
}
static void print_if_verify(const char *option)
{
if (cmdline_command_verify) {
print("%s", option);
}
}
static void print_if_diagnose(const char *option)
{
if (!cmdline_command_verify) {
print("%s", option);
}
}
static void print_help(void)
{
print("Performs a system software installation verification\n\n");
print("Usage:\n");
if (cmdline_command_verify) {
print(" swupd verify [OPTION...]\n\n");
print("Warning: The \"swupd verify\" command has been superseded\n");
print("Please consider using \"swupd diagnose\", \"swupd repair\" or \"swupd os-install\" instead\n\n");
} else {
print(" swupd diagnose [OPTION...]\n\n");
}
print_if_verify(" swupd verify [OPTION...]\n\n");
print_if_verify("Warning: The \"swupd verify\" command has been superseded\n");
print_if_verify("Please consider using \"swupd diagnose\", \"swupd repair\" or \"swupd os-install\" instead\n\n");
print_if_diagnose(" swupd diagnose [OPTION...]\n\n");
global_print_help();
@@ -171,18 +192,16 @@ static void print_help(void)
print(" -x, --force Attempt to proceed even if non-critical errors found\n");
print(" -q, --quick Don't check for corrupt files, only fix missing files\n");
print(" -B, --bundles=[BUNDLES] Forces swupd to only %s the specified BUNDLES. Example: --bundles=os-core,vi\n", cmdline_command_verify ? "verify" : "diagnose");
if (cmdline_command_verify) {
print(" -m, --manifest=[VER] This option has been superseded. Please consider using the -V option instead\n");
print(" -f, --fix This option has been superseded, please consider using \"swupd repair\" instead\n");
print(" -i, --install This option has been superseded, please consider using \"swupd os-install\" instead\n");
print(" -Y, --picky Also list (without --fix) or remove (with --fix) files which should not exist\n");
} else {
print(" -Y, --picky Also list files which should not exist. By default swupd only looks for them at /usr\n");
print(" skipping /usr/lib/modules, /usr/lib/kernel, /usr/local, and /usr/src\n");
}
print_if_verify(" -m, --manifest=[VER] This option has been superseded. Please consider using the -V option instead\n");
print_if_verify(" -f, --fix This option has been superseded, please consider using \"swupd repair\" instead\n");
print_if_verify(" -i, --install This option has been superseded, please consider using \"swupd os-install\" instead\n");
print_if_verify(" -Y, --picky Also list (without --fix) or remove (with --fix) files which should not exist\n");
print_if_diagnose(" -Y, --picky Also list files which should not exist. By default swupd only looks for them at /usr\n");
print_if_diagnose(" skipping /usr/lib/modules, /usr/lib/kernel, /usr/local, and /usr/src\n");
print(" -X, --picky-tree=[PATH] Changes the path where --picky and --extra-files-only look for extra files\n");
print(" -w, --picky-whitelist=[RE] Directories that match the regex get skipped during --picky. Example: /usr/bin|/usr/doc\n");
print(" --extra-files-only Like --picky, but it only performs this task\n");
print_if_diagnose(" --file Forces swupd to only diagnose the specified file or directory (recursively)\n");
print("\n");
}
@@ -254,7 +273,7 @@ static int check_files_hash(struct list *files)
}
/* allow optimization of install case */
static int get_required_files(struct manifest *official_manifest, struct list *subs)
static int get_required_files(struct manifest *official_manifest, struct list *required_files, struct list *subs)
{
int ret;
@@ -265,7 +284,7 @@ static int get_required_files(struct manifest *official_manifest, struct list *s
progress_next_step("check_files_hash", PROGRESS_BAR);
print("\n");
if (check_files_hash(official_manifest->files)) {
if (check_files_hash(required_files)) {
/* we don't need to do these steps, we already have the files,
* just complete the steps */
progress_next_step("validate_fullfiles", PROGRESS_BAR);
@@ -274,7 +293,7 @@ static int get_required_files(struct manifest *official_manifest, struct list *s
return 0;
}
ret = download_fullfiles(official_manifest->files, NULL);
ret = download_fullfiles(required_files, NULL);
if (ret) {
error("Unable to download necessary files for this OS release\n");
}
@@ -325,15 +344,15 @@ out:
}
/* for each missing but expected file, (re)add the file */
static void add_missing_files(struct manifest *official_manifest, bool repair)
static void add_missing_files(struct manifest *official_manifest, struct list *files_to_verify, bool repair)
{
int ret;
struct file local;
struct list *iter;
int list_length = list_len(official_manifest->files);
int list_length = list_len(files_to_verify);
int complete = 0;
iter = list_head(official_manifest->files);
iter = list_head(files_to_verify);
while (iter) {
struct file *file;
char *fullname;
@@ -452,7 +471,7 @@ end:
free_string(&fullname);
}
static void deal_with_hash_mismatches(struct manifest *official_manifest, bool repair)
static void deal_with_hash_mismatches(struct manifest *official_manifest, struct list *files_to_verify, bool repair)
{
struct list *iter;
int complete = 0;
@@ -462,7 +481,7 @@ static void deal_with_hash_mismatches(struct manifest *official_manifest, bool r
/* for each expected and present file which hash-mismatches vs
* the manifest, replace the file */
iter = list_head(official_manifest->files);
iter = list_head(files_to_verify);
list_length = list_len(iter);
while (iter) {
@@ -476,18 +495,18 @@ static void deal_with_hash_mismatches(struct manifest *official_manifest, bool r
}
}
static void remove_orphaned_files(struct manifest *official_manifest, bool repair)
static void remove_orphaned_files(struct list *files_to_verify, bool repair)
{
int ret;
struct list *iter;
int list_length = list_len(official_manifest->files);
int list_length = list_len(files_to_verify);
int complete = 0;
info("%s extraneous files\n", repair ? "Removing" : "Checking for");
official_manifest->files = list_sort(official_manifest->files, cmp_file_filename_reverse);
files_to_verify = list_sort(files_to_verify, cmp_file_filename_reverse);
iter = list_head(official_manifest->files);
iter = list_head(files_to_verify);
while (iter) {
struct file *file;
char *fullname;
@@ -646,6 +665,11 @@ static bool parse_opt(int opt, char *optarg)
case FLAG_EXTRA_FILES_ONLY:
cmdline_option_extra_files_only = optarg_to_bool(optarg);
return true;
case FLAG_FILE:
cmdline_option_file = strdup_or_die(optarg);
/* Remove trailing '/' at the end of file/dir if any */
remove_trailing_slash(cmdline_option_file);
return true;
default:
return false;
}
@@ -718,6 +742,13 @@ static bool parse_options(int argc, char **argv)
info("\n");
}
/* new options should not be allowed for the legacy verify command
* since it has been superseded, to motivate users to use diagnose/repair */
if (cmdline_option_file) {
error("unrecognized option '--file'\n");
return false;
}
} else {
/* flag restrictions for "diagnose" */
@@ -725,6 +756,7 @@ static bool parse_options(int argc, char **argv)
error("'latest' not supported for --version\n");
return false;
}
if (cmdline_option_bundles) {
if (cmdline_option_picky) {
error("--bundles and --picky options are mutually exclusive\n");
@@ -799,6 +831,23 @@ static int filter_file_unsafe_to_delete(const void *a, const void *b)
return -1;
}
static struct list *keep_matching_path(struct list *all_files)
{
struct list *matching_files = NULL;
struct list *iter = NULL;
struct file *file;
for (iter = all_files; iter; iter = iter->next) {
file = iter->data;
if (strncmp(cmdline_option_file, file->filename, strlen(cmdline_option_file)) == 0) {
/* preserving the order is important */
matching_files = list_append_data(matching_files, file);
}
}
return list_head(matching_files);
}
/* This function does a simple verification of files listed in the
* subscribed bundle manifests. If the optional "fix" or "install" parameter
* is specified, the disk will be modified at each point during the
@@ -817,6 +866,7 @@ enum swupd_code execute_verify(void)
struct list *bundles_submanifests = NULL;
struct list *all_files = NULL;
struct list *bundles_files = NULL;
struct list *files_to_verify = NULL;
struct list *iter;
bool use_latest = false;
bool invalid_bundle = false;
@@ -1036,6 +1086,7 @@ enum swupd_code execute_verify(void)
goto clean_and_exit;
}
official_manifest->submanifests = all_submanifests;
if (cmdline_option_bundles) {
bundles_submanifests = recurse_manifest(official_manifest, bundles_subs, NULL, false, NULL);
if (!bundles_submanifests) {
@@ -1066,6 +1117,23 @@ enum swupd_code execute_verify(void)
}
timelist_timer_stop(globals.global_times);
/* get the list of files to verify */
files_to_verify = official_manifest->files;
if (cmdline_option_file) {
/* the user specified a file or path to verify, use that instead */
files_to_verify = keep_matching_path(official_manifest->files);
info("\n");
if (files_to_verify) {
char *file_path = sys_path_join(globals.path_prefix, cmdline_option_file);
info("Limiting diagnose to the following %s:\n", is_dir(file_path) ? "directory (recursively)" : "file");
free_string(&file_path);
info(" - %s\n", cmdline_option_file);
} else {
/* we are done, nothing to be done */
goto report_and_exit;
}
}
if (cmdline_option_extra_files_only) {
/* user wants to deal only with the extra files, so skip everything else */
goto extra_files;
@@ -1075,11 +1143,11 @@ enum swupd_code execute_verify(void)
timelist_timer_start(globals.global_times, "Get required files");
/* get the initial number of files to be inspected */
counts.checked = list_len(official_manifest->files);
counts.checked = list_len(files_to_verify);
/* when fixing or installing we need input files */
if (cmdline_option_fix || cmdline_option_install) {
ret = get_required_files(official_manifest, selected_subs);
ret = get_required_files(official_manifest, files_to_verify, selected_subs);
if (ret != 0) {
ret = SWUPD_COULDNT_DOWNLOAD_FILE;
goto clean_and_exit;
@@ -1123,7 +1191,7 @@ enum swupd_code execute_verify(void)
} else {
info("\nChecking for missing files\n");
}
add_missing_files(official_manifest, cmdline_option_fix || cmdline_option_install);
add_missing_files(official_manifest, files_to_verify, cmdline_option_fix || cmdline_option_install);
timelist_timer_stop(globals.global_times);
if (cmdline_option_quick) {
@@ -1134,7 +1202,7 @@ enum swupd_code execute_verify(void)
/* repair corrupt files */
timelist_timer_start(globals.global_times, "Fixing modified files");
progress_next_step("fix_files", PROGRESS_BAR);
deal_with_hash_mismatches(official_manifest, cmdline_option_fix);
deal_with_hash_mismatches(official_manifest, files_to_verify, cmdline_option_fix);
timelist_timer_stop(globals.global_times);
/* remove orphaned files, removing files could be
@@ -1142,7 +1210,7 @@ enum swupd_code execute_verify(void)
timelist_timer_start(globals.global_times, "Removing orphaned files");
if ((counts.not_fixed == 0) && (counts.not_replaced == 0)) {
progress_next_step("remove_extraneous_files", PROGRESS_BAR);
remove_orphaned_files(official_manifest, cmdline_option_fix);
remove_orphaned_files(files_to_verify, cmdline_option_fix);
}
timelist_timer_stop(globals.global_times);
@@ -1179,6 +1247,7 @@ brick_the_system_and_clean_curl:
}
/* report a summary of what we managed to do and not do */
report_and_exit:
info("Inspected %i file%s\n", counts.checked, (counts.checked == 1 ? "" : "s"));
if (counts.missing) {
@@ -1236,6 +1305,9 @@ brick_the_system_and_clean_curl:
/* this concludes the critical section, after this point it's clean up time, the disk content is finished and final */
clean_and_exit:
if (cmdline_option_file) {
list_free_list(files_to_verify);
}
free_subscriptions(&all_subs);
free_subscriptions(&bundles_subs);
/* if the --bundles flag was used the official_manifest contains
@@ -1331,7 +1403,7 @@ enum swupd_code verify_main(int argc, char **argv)
{
enum swupd_code ret = SWUPD_OK;
const int steps_in_verify = 12;
string_or_die(&cmdline_option_picky_tree, "/usr");
string_or_die(&cmdline_option_picky_tree, "%s", picky_tree_default);
/* set option needed so we know the legacy "verify" command was used */
verify_set_command_verify(true);
@@ -1388,7 +1460,6 @@ enum swupd_code diagnose_main(int argc, char **argv)
{
enum swupd_code ret = SWUPD_OK;
int steps_in_diagnose;
string_or_die(&cmdline_option_picky_tree, "/usr");
if (!parse_options(argc, argv)) {
print("\n");
@@ -1399,10 +1470,17 @@ enum swupd_code diagnose_main(int argc, char **argv)
ret = swupd_init(SWUPD_ALL);
if (ret != SWUPD_OK) {
error("Failed swupd initialization, exiting now\n");
free_string(&cmdline_option_picky_tree);
return ret;
}
/* if the --file flag was used, use that path for --picky as well
* unless --picky-tree was also specified, if none use default */
if (!cmdline_option_picky_tree && !cmdline_option_file) {
string_or_die(&cmdline_option_picky_tree, "%s", picky_tree_default);
} else if (!cmdline_option_picky_tree) {
cmdline_option_picky_tree = cmdline_option_file;
}
/*
* Steps for diagnose:
* 1) load_manifests (with --extra-files-only jumps to step 5)
@@ -1423,6 +1501,9 @@ enum swupd_code diagnose_main(int argc, char **argv)
/* diagnose */
ret = execute_verify();
if (cmdline_option_picky_tree != cmdline_option_file) {
free_string(&cmdline_option_file);
}
free_string(&cmdline_option_picky_tree);
if (picky_whitelist) {
regfree(picky_whitelist);
+2 -2
View File
@@ -63,10 +63,10 @@ _swupd()
opts="$global --version --library --binary --top --csv --init --order "
break;;
("diagnose")
opts="$global --version --picky --picky-tree --picky-whitelist --quick --force --extra-files-only --bundles "
opts="$global --version --picky --picky-tree --picky-whitelist --quick --force --extra-files-only --bundles --file "
break;;
("repair")
opts="$global --version --picky --picky-tree --picky-whitelist --quick --force --extra-files-only --bundles "
opts="$global --version --picky --picky-tree --picky-whitelist --quick --force --extra-files-only --bundles --file "
break;;
("os-install")
opts="$global --version --force --bundles --statedir-cache --download --skip-optional"
+2
View File
@@ -324,6 +324,7 @@ if [[ -n "$state" ]]; then
'(help -w --picky-whitelist)'{-w,--picky-whitelist=}'[Directories that match the regex get skipped. Example\: /var|/etc/machine-id. Default\: /usr/lib/modules|/usr/lib/kernel|/usr/local|/usr/src]:picky-whitelist:()'
'(help)--extra-files-only[Only list files which should not exist]'
'(help -B --bundles)'{-B,--bundles=}'[Forces swupd to only diagnose the specified BUNDLES. Example: --bundles=os-core,vi]:bundles:()'
'(help)--file[Forces swupd to only diagnose the specified file or directory (recursively)]'
)
_arguments $diagnoses && ret=0
;;
@@ -338,6 +339,7 @@ if [[ -n "$state" ]]; then
'(help -X --picky-tree)'{-X,--picky-tree=}'[Selects the sub-tree where --picky and --extra-files-only looks for extra files. Default\: /usr]:picky-tree: _path_files -/'
'(help)--extra-files-only[Only remove files which should not exist]'
'(help -B --bundles)'{-B,--bundles=}'[Forces swupd to only repair the specified BUNDLES. Example: --bundles=os-core,vi]:bundles:()'
'(help)--file[Forces swupd to only repair the specified file or directory (recursively)]'
)
_arguments $repair && ret=0
;;
@@ -22,15 +22,14 @@ test_setup() {
@test "ADD022: When adding a bundle and a path is missing on the fs, bundle-add fixes it" {
run sudo sh -c "$SWUPD bundle-add $SWUPD_OPTS test-bundle1"
assert_status_is 0
assert_status_is "$SWUPD_OK"
expected_output=$(cat <<-EOM
Loading required manifests...
No packs need to be downloaded
Validate downloaded files
Starting download of remaining update content. This may take a while...
Installing files...
Warning: Update target directory does not exist: $TEST_DIRNAME/testfs/target-dir/foo/bar. Trying to fix it
Path /foo/bar is missing on the file system ... fixing
-> Missing directory: $PATH_PREFIX/foo/bar -> fixed
Calling post-update helper scripts
Successfully installed 1 bundle
EOM
+208
View File
@@ -0,0 +1,208 @@
#!/usr/bin/env bats
# Author: Castulo Martinez
# Email: castulo.martinez@intel.com
load "../testlib"
test_setup() {
create_test_environment -r "$TEST_NAME" 10 1
create_bundle -L -n test-bundle1 -f /foo/file_1,/bar/file_2 "$TEST_NAME"
create_version "$TEST_NAME" 20 10 1
update_bundle -p "$TEST_NAME" test-bundle1 --update /foo/file_1
update_bundle -p "$TEST_NAME" test-bundle1 --delete /bar/file_2
update_bundle "$TEST_NAME" test-bundle1 --add /baz/file_3
update_bundle "$TEST_NAME" test-bundle1 --add /bar/file_4
update_bundle "$TEST_NAME" test-bundle1 --add /bar/bat/file_5
set_current_version "$TEST_NAME" 20
# adding an untracked files into an untracked directory (/bat)
sudo mkdir "$TARGETDIR"/bat
sudo touch "$TARGETDIR"/bat/untracked_file1
# adding an untracked file into tracked directory (/bar)
sudo touch "$TARGETDIR"/bar/untracked_file2
# adding an untracked file into /usr
sudo touch "$TARGETDIR"/usr/untracked_file3
}
@test "DIA022: Diagnose can be limited to a specific file" {
# if the user uses the --file option, the diagnose is limited to the
# file/directory specified by the user
run sudo sh -c "$SWUPD diagnose $SWUPD_OPTS --file /baz/file_3"
assert_status_is "$SWUPD_NO"
expected_output=$(cat <<-EOM
Diagnosing version 20
Downloading missing manifests...
Limiting diagnose to the following file:
- /baz/file_3
Checking for missing files
-> Missing file: $PATH_PREFIX/baz/file_3
Checking for corrupt files
Checking for extraneous files
Inspected 1 file
1 file was missing
Use "swupd repair" to correct the problems in the system
Diagnose successful
EOM
)
assert_is_output "$expected_output"
}
@test "DIA023: Diagnose picky can be limited to a specific file" {
# if the user uses the --file + --picky options, the diagnose is limited to the
# file/directory specified by the user and looks for extra files in the
# same path only
run sudo sh -c "$SWUPD diagnose $SWUPD_OPTS --file /baz/file_3 --picky"
assert_status_is "$SWUPD_NO"
expected_output=$(cat <<-EOM
Diagnosing version 20
Downloading missing manifests...
Limiting diagnose to the following file:
- /baz/file_3
Checking for missing files
-> Missing file: $PATH_PREFIX/baz/file_3
Checking for corrupt files
Checking for extraneous files
Checking for extra files under $PATH_PREFIX/baz/file_3
Inspected 1 file
1 file was missing
Use "swupd repair" to correct the problems in the system
Diagnose successful
EOM
)
assert_is_output "$expected_output"
}
@test "DIA024: Diagnose can be limited to a specific path" {
# if the user uses the --file option, the diagnose is limited to the
# file/directory specified by the user
run sudo sh -c "$SWUPD diagnose $SWUPD_OPTS --file /bar"
assert_status_is "$SWUPD_NO"
expected_output=$(cat <<-EOM
Diagnosing version 20
Downloading missing manifests...
Limiting diagnose to the following directory (recursively):
- /bar
Checking for missing files
-> Missing file: $PATH_PREFIX/bar/bat
-> Missing file: $PATH_PREFIX/bar/bat/file_5
-> Missing file: $PATH_PREFIX/bar/file_4
Checking for corrupt files
Checking for extraneous files
-> File that should be deleted: $PATH_PREFIX/bar/file_2
Inspected 5 files
3 files were missing
1 file found which should be deleted
Use "swupd repair" to correct the problems in the system
Diagnose successful
EOM
)
assert_is_output "$expected_output"
}
@test "DIA025: Diagnose can be limited to a specific path to look for extra files only" {
# if the user uses the --file + --extra-files-only option, swupd should only look for
# extra files in the path specified by the user
run sudo sh -c "$SWUPD diagnose $SWUPD_OPTS --file /bar --extra-files-only"
assert_status_is "$SWUPD_NO"
expected_output=$(cat <<-EOM
Diagnosing version 20
Downloading missing manifests...
Limiting diagnose to the following directory (recursively):
- /bar
Checking for extra files under $PATH_PREFIX/bar
-> Extra file: $PATH_PREFIX/bar/untracked_file2
-> Extra file: $PATH_PREFIX/bar/file_2
Inspected 2 files
2 files found which should be deleted
Use "swupd repair --picky" to correct the problems in the system
Diagnose successful
EOM
)
assert_is_output "$expected_output"
}
@test "DIA026: Diagnose can be limited to a specific path and can look for extra files in another path" {
# if the user uses the --file option with --picky-tree,
# the latter should take precedence
run sudo sh -c "$SWUPD diagnose $SWUPD_OPTS --file /bar --picky --picky-tree /usr"
assert_status_is "$SWUPD_NO"
expected_output=$(cat <<-EOM
Diagnosing version 20
Downloading missing manifests...
Limiting diagnose to the following directory (recursively):
- /bar
Checking for missing files
-> Missing file: $PATH_PREFIX/bar/bat
-> Missing file: $PATH_PREFIX/bar/bat/file_5
-> Missing file: $PATH_PREFIX/bar/file_4
Checking for corrupt files
Checking for extraneous files
-> File that should be deleted: $PATH_PREFIX/bar/file_2
Checking for extra files under $PATH_PREFIX/usr
-> Extra file: $PATH_PREFIX/usr/untracked_file3
-> Extra file: $PATH_PREFIX/usr/share/defaults/swupd/versionurl
-> Extra file: $PATH_PREFIX/usr/share/defaults/swupd/contenturl
Inspected 8 files
3 files were missing
4 files found which should be deleted
Use "swupd repair --picky" to correct the problems in the system
Diagnose successful
EOM
)
assert_is_output "$expected_output"
}
@test "DIA027: Diagnose can be limited to a specific path for a specific bundle" {
# if the --bundles and --file options are used together, swupd should only
# look in the specified path and only for files that are part of the specified
# bundle
write_to_protected_file -a "$PATH_PREFIX"/usr/share/clear/bundles/os-core "corrupting the file"
write_to_protected_file -a "$PATH_PREFIX"/usr/share/clear/bundles/test-bundle1 "corrupting the file"
run sudo sh -c "$SWUPD diagnose $SWUPD_OPTS --bundle test-bundle1 --file /usr/share/clear/bundles"
assert_status_is "$SWUPD_NO"
expected_output=$(cat <<-EOM
Diagnosing version 20
Limiting diagnose to the following bundles:
- test-bundle1
Downloading missing manifests...
Limiting diagnose to the following directory (recursively):
- /usr/share/clear/bundles
Checking for missing files
Checking for corrupt files
-> Hash mismatch for file: $PATH_PREFIX/usr/share/clear/bundles/test-bundle1
Checking for extraneous files
Inspected 1 file
1 file did not match
Use "swupd repair" to correct the problems in the system
Diagnose successful
EOM
)
assert_is_output "$expected_output"
}
+279
View File
@@ -0,0 +1,279 @@
#!/usr/bin/env bats
# Author: Castulo Martinez
# Email: castulo.martinez@intel.com
load "../testlib"
test_setup() {
create_test_environment -r "$TEST_NAME" 10 1
create_bundle -L -n test-bundle1 -f /foo/file_1,/bar/file_2 -d /baz/testdir "$TEST_NAME"
create_version "$TEST_NAME" 20 10 1
update_bundle -p "$TEST_NAME" test-bundle1 --update /foo/file_1
update_bundle -p "$TEST_NAME" test-bundle1 --delete /bar/file_2
update_bundle "$TEST_NAME" test-bundle1 --add /baz/testdir/file_3
update_bundle "$TEST_NAME" test-bundle1 --add /bar/file_4
update_bundle "$TEST_NAME" test-bundle1 --add /bar/bat/file_5
set_current_version "$TEST_NAME" 20
# adding an untracked files into an untracked directory (/bat)
sudo mkdir "$TARGETDIR"/bat
sudo touch "$TARGETDIR"/bat/untracked_file1
# adding an untracked file into tracked directory (/bar)
sudo touch "$TARGETDIR"/bar/untracked_file2
# adding an untracked file into /usr
sudo touch "$TARGETDIR"/usr/untracked_file3
}
@test "REP038: Repair can be limited to a specific file" {
# if the user uses the --file option, the repair is limited to the
# file/directory specified by the user
run sudo sh -c "$SWUPD repair $SWUPD_OPTS --file /baz/testdir/file_3"
assert_status_is "$SWUPD_OK"
expected_output=$(cat <<-EOM
Diagnosing version 20
Downloading missing manifests...
Limiting diagnose to the following file:
- /baz/testdir/file_3
Checking for corrupt files
Validate downloaded files
Starting download of remaining update content. This may take a while...
Adding any missing files
-> Missing file: $PATH_PREFIX/baz/testdir/file_3 -> fixed
Repairing corrupt files
Removing extraneous files
Inspected 1 file
1 file was missing
1 of 1 missing files were replaced
0 of 1 missing files were not replaced
Calling post-update helper scripts
Repair successful
EOM
)
assert_is_output "$expected_output"
}
@test "REP039: Repair extra files only can be limited to a specific file" {
# if the user uses the --file + --picky options, the repair is limited to the
# file/directory specified by the user and looks for extra files in the
# same path only
run sudo sh -c "$SWUPD repair $SWUPD_OPTS --file /foo/file_1 --extra-files-only"
assert_status_is "$SWUPD_OK"
expected_output=$(cat <<-EOM
Diagnosing version 20
Downloading missing manifests...
Limiting diagnose to the following file:
- /foo/file_1
Removing extra files under $PATH_PREFIX/foo/file_1
Inspected 0 files
Calling post-update helper scripts
Repair successful
EOM
)
assert_is_output "$expected_output"
}
@test "REP040: Repair can fix a specific file even if its parent directory is missing" {
# if the user uses the --file option, the repair is limited to the
# file/directory specified by the user. If a file was specified to be
# verified, but part of its path is missing or corrput, fix it anyway
sudo rm -rf "$PATH_PREFIX"/baz
run sudo sh -c "$SWUPD repair $SWUPD_OPTS --file /baz/testdir/file_3"
assert_status_is "$SWUPD_OK"
expected_output=$(cat <<-EOM
Diagnosing version 20
Downloading missing manifests...
Limiting diagnose to the following file:
- /baz/testdir/file_3
Checking for corrupt files
Validate downloaded files
Starting download of remaining update content. This may take a while...
Adding any missing files
-> Missing directory: $PATH_PREFIX/baz -> fixed
-> Missing directory: $PATH_PREFIX/baz/testdir -> fixed
-> Missing file: $PATH_PREFIX/baz/testdir/file_3 -> fixed
Repairing corrupt files
Removing extraneous files
Inspected 1 file
1 file was missing
1 of 1 missing files were replaced
0 of 1 missing files were not replaced
Calling post-update helper scripts
Repair successful
EOM
)
assert_is_output "$expected_output"
}
@test "REP041: Repair can be limited to a specific path" {
# if the user uses the --file option, the repair is limited to the
# file/directory specified by the user
run sudo sh -c "$SWUPD repair $SWUPD_OPTS --file /bar"
assert_status_is "$SWUPD_OK"
expected_output=$(cat <<-EOM
Diagnosing version 20
Downloading missing manifests...
Limiting diagnose to the following directory (recursively):
- /bar
Checking for corrupt files
Validate downloaded files
Starting download of remaining update content. This may take a while...
Adding any missing files
-> Missing file: $PATH_PREFIX/bar/bat -> fixed
-> Missing file: $PATH_PREFIX/bar/bat/file_5 -> fixed
-> Missing file: $PATH_PREFIX/bar/file_4 -> fixed
Repairing corrupt files
Removing extraneous files
-> File that should be deleted: $PATH_PREFIX/bar/file_2 -> deleted
Inspected 5 files
3 files were missing
3 of 3 missing files were replaced
0 of 3 missing files were not replaced
1 file found which should be deleted
1 of 1 files were deleted
0 of 1 files were not deleted
Calling post-update helper scripts
Repair successful
EOM
)
assert_is_output "$expected_output"
}
@test "REP042: Repair picky can be limited to a specific path" {
# if the user uses the --file + --picky option, the repair is limited to the
# file/directory specified by the user and swupd will only look for extra files
# in the provided path
run sudo sh -c "$SWUPD repair $SWUPD_OPTS --file /bar --picky"
assert_status_is "$SWUPD_OK"
expected_output=$(cat <<-EOM
Diagnosing version 20
Downloading missing manifests...
Limiting diagnose to the following directory (recursively):
- /bar
Checking for corrupt files
Validate downloaded files
Starting download of remaining update content. This may take a while...
Adding any missing files
-> Missing file: $PATH_PREFIX/bar/bat -> fixed
-> Missing file: $PATH_PREFIX/bar/bat/file_5 -> fixed
-> Missing file: $PATH_PREFIX/bar/file_4 -> fixed
Repairing corrupt files
Removing extraneous files
-> File that should be deleted: $PATH_PREFIX/bar/file_2 -> deleted
Removing extra files under $PATH_PREFIX/bar
-> Extra file: $PATH_PREFIX/bar/untracked_file2 -> deleted
Inspected 6 files
3 files were missing
3 of 3 missing files were replaced
0 of 3 missing files were not replaced
2 files found which should be deleted
2 of 2 files were deleted
0 of 2 files were not deleted
Calling post-update helper scripts
Repair successful
EOM
)
assert_is_output "$expected_output"
}
@test "REP043: Repair can be limited to a specific path and can look for extra files in another path" {
# if the user uses the --file option with --picky-tree,
# the latter should take precedence
run sudo sh -c "$SWUPD repair $SWUPD_OPTS --file /bar --picky --picky-tree /usr"
assert_status_is "$SWUPD_OK"
expected_output=$(cat <<-EOM
Diagnosing version 20
Downloading missing manifests...
Limiting diagnose to the following directory (recursively):
- /bar
Checking for corrupt files
Validate downloaded files
Starting download of remaining update content. This may take a while...
Adding any missing files
-> Missing file: $PATH_PREFIX/bar/bat -> fixed
-> Missing file: $PATH_PREFIX/bar/bat/file_5 -> fixed
-> Missing file: $PATH_PREFIX/bar/file_4 -> fixed
Repairing corrupt files
Removing extraneous files
-> File that should be deleted: $PATH_PREFIX/bar/file_2 -> deleted
Removing extra files under $PATH_PREFIX/usr
-> Extra file: $PATH_PREFIX/usr/untracked_file3 -> deleted
-> Extra file: $PATH_PREFIX/usr/share/defaults/swupd/versionurl -> deleted
-> Extra file: $PATH_PREFIX/usr/share/defaults/swupd/contenturl -> deleted
Inspected 8 files
3 files were missing
3 of 3 missing files were replaced
0 of 3 missing files were not replaced
4 files found which should be deleted
4 of 4 files were deleted
0 of 4 files were not deleted
Calling post-update helper scripts
Repair successful
EOM
)
assert_is_output "$expected_output"
}
@test "REP044: Repair can be limited to a specific path for a specific bundle" {
# if the --bundles and --file options are used together, swupd should only
# look in the specified path and only for files that are part of the specified
# bundle
write_to_protected_file -a "$PATH_PREFIX"/usr/share/clear/bundles/os-core "corrupting the file"
write_to_protected_file -a "$PATH_PREFIX"/usr/share/clear/bundles/test-bundle1 "corrupting the file"
run sudo sh -c "$SWUPD repair $SWUPD_OPTS --bundle test-bundle1 --file /usr/share/clear/bundles"
assert_status_is "$SWUPD_OK"
expected_output=$(cat <<-EOM
Diagnosing version 20
Limiting diagnose to the following bundles:
- test-bundle1
Downloading missing manifests...
Limiting diagnose to the following directory (recursively):
- /usr/share/clear/bundles
Checking for corrupt files
Validate downloaded files
Starting download of remaining update content. This may take a while...
Adding any missing files
Repairing corrupt files
-> Hash mismatch for file: $PATH_PREFIX/usr/share/clear/bundles/test-bundle1 -> fixed
Removing extraneous files
Inspected 1 file
1 file did not match
1 of 1 files were repaired
0 of 1 files were not repaired
Calling post-update helper scripts
Repair successful
EOM
)
assert_is_output "$expected_output"
}
@@ -38,9 +38,8 @@ test_setup() {
Validate downloaded files
Starting download of remaining update content. This may take a while...
Installing files...
Warning: Update target directory does not exist: .*/target-dir/usr/foo. Trying to fix it
Hash did not match for path : /usr ... fixing
Path /usr/foo is missing on the file system ... fixing
-> Corrupt directory: $PATH_PREFIX/usr -> fixed
-> Missing directory: $PATH_PREFIX/usr/foo -> fixed
Update was applied
Calling post-update helper scripts
1 files were not in a pack
@@ -5,11 +5,11 @@ load "../testlib"
test_setup() {
create_test_environment "$TEST_NAME"
create_bundle -L -n test-bundle -f /usr/foo/test-file "$TEST_NAME"
create_bundle -L -n test-bundle -f /foo/bar/baz/test-file "$TEST_NAME"
# remove the foo dir
sudo rm -rf "$TARGETDIR"/usr/foo
sudo rm -rf "$TARGETDIR"/foo
create_version "$TEST_NAME" 100 10
update_bundle "$TEST_NAME" test-bundle --update /usr/foo/test-file
update_bundle "$TEST_NAME" test-bundle --update /foo/bar/baz/test-file
}
@@ -35,8 +35,9 @@ test_setup() {
Validate downloaded files
Starting download of remaining update content. This may take a while...
Installing files...
Warning: Update target directory does not exist: .*/target-dir/usr/foo. Trying to fix it
Path /usr/foo is missing on the file system ... fixing
-> Missing directory: $PATH_PREFIX/foo -> fixed
-> Missing directory: $PATH_PREFIX/foo/bar -> fixed
-> Missing directory: $PATH_PREFIX/foo/bar/baz -> fixed
Update was applied
Calling post-update helper scripts
1 files were not in a pack
@@ -44,8 +45,8 @@ test_setup() {
EOM
)
assert_regex_is_output "$expected_output"
assert_dir_exists "$TARGETDIR"/usr/foo
assert_file_exists "$TARGETDIR"/usr/foo/test-file
assert_dir_exists "$TARGETDIR"/foo/bar/baz
assert_file_exists "$TARGETDIR"/foo/bar/baz/test-file
}