From e35450fa53139572afdd759619610cc7f5277626 Mon Sep 17 00:00:00 2001 From: Peter Stuge Date: Fri, 25 Nov 2011 01:03:58 +0100 Subject: [PATCH] restore: Add regex matching of paths and files to be restored The option -m is used to specify the regex string. -c is used to specify case insensitive matching. -i was already taken. In order to restore only a single folder somewhere in the btrfs tree, it is unfortunately neccessary to construct a slightly nontrivial regex, e.g.: restore -m '^/(|home(|/username(|/Desktop(|/.*))))$' /dev/sdb2 /output This is needed in order to match each directory along the way to the Desktop directory, as well as all contents below the Desktop directory. Signed-off-by: Peter Stuge Signed-off-by: Josef Bacik Signed-off-by: David Sterba Signed-off-by: Chris Mason --- cmds-restore.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/cmds-restore.c b/cmds-restore.c index e48df403..1aae3902 100644 --- a/cmds-restore.c +++ b/cmds-restore.c @@ -27,9 +27,11 @@ #include #include #include +#include #include #include #include +#include #include "ctree.h" #include "disk-io.h" @@ -539,7 +541,8 @@ set_size: } static int search_dir(struct btrfs_root *root, struct btrfs_key *key, - const char *output_rootdir, const char *dir) + const char *output_rootdir, const char *dir, + const regex_t *mreg) { struct btrfs_path *path; struct extent_buffer *leaf; @@ -646,6 +649,9 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key, /* full path from root of btrfs being restored */ snprintf(fs_name, 4096, "%s/%s", dir, filename); + if (REG_NOMATCH == regexec(mreg, fs_name, 0, NULL, 0)) + goto next; + /* full path from system root */ snprintf(path_name, 4096, "%s%s", output_rootdir, fs_name); @@ -759,7 +765,7 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key, } loops = 0; ret = search_dir(search_root, &location, - output_rootdir, dir); + output_rootdir, dir, mreg); free(dir); if (ret) { if (ignore_errors) @@ -990,8 +996,13 @@ int cmd_restore(int argc, char **argv) int super_mirror = 0; int find_dir = 0; int list_roots = 0; + const char *match_regstr = NULL; + int match_cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE; + regex_t match_reg, *mreg = NULL; + char reg_err[256]; + + while ((opt = getopt(argc, argv, "sviot:u:df:r:lcm:")) != -1) { - while ((opt = getopt(argc, argv, "sviot:u:df:r:l")) != -1) { switch (opt) { case 's': get_snaps = 1; @@ -1045,6 +1056,12 @@ int cmd_restore(int argc, char **argv) case 'l': list_roots = 1; break; + case 'c': + match_cflags |= REG_ICASE; + break; + case 'm': + match_regstr = optarg; + break; default: usage(cmd_restore_usage); } @@ -1116,9 +1133,21 @@ int cmd_restore(int argc, char **argv) key.objectid = BTRFS_FIRST_FREE_OBJECTID; } - ret = search_dir(root, &key, dir_name, ""); + if (match_regstr) { + ret = regcomp(&match_reg, match_regstr, match_cflags); + if (ret) { + regerror(ret, &match_reg, reg_err, sizeof(reg_err)); + fprintf(stderr, "Regex compile failed: %s\n", reg_err); + goto out; + } + mreg = &match_reg; + } + + ret = search_dir(root, &key, dir_name, "", mreg); out: + if (mreg) + regfree(mreg); close_ctree(root); return ret; }