From 2f0c2a29ab13b17ae1cc21effcf532f2447b7c8c Mon Sep 17 00:00:00 2001 From: Peter Stuge Date: Fri, 25 Nov 2011 01:03:58 +0100 Subject: [PATCH 23/35] 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 --- restore.c | 40 ++++++++++++++++++++++++++++++++++------ 1 files changed, 34 insertions(+), 6 deletions(-) diff --git a/restore.c b/restore.c index 0b92ed5..e65746a 100644 --- a/restore.c +++ b/restore.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include "kerncompat.h" #include "ctree.h" #include "disk-io.h" @@ -451,7 +453,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; @@ -558,6 +561,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); @@ -669,7 +675,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) @@ -690,8 +696,8 @@ next: static void usage() { - fprintf(stderr, "Usage: restore [-svio] [-t disk offset] " - "\n"); + fprintf(stderr, "Usage: restore [-svioc] [-t disk offset] " + "[-m regex] \n"); } static struct btrfs_root *open_fs(const char *dev, u64 root_location, int super_mirror) @@ -784,8 +790,12 @@ int main(int argc, char **argv) int opt; int super_mirror = 0; int find_dir = 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:")) != -1) { + while ((opt = getopt(argc, argv, "sviot:u:df:r:cm:")) != -1) { switch (opt) { case 's': get_snaps = 1; @@ -836,6 +846,12 @@ int main(int argc, char **argv) exit(1); } break; + case 'c': + match_cflags |= REG_ICASE; + break; + case 'm': + match_regstr = optarg; + break; default: usage(); exit(1); @@ -906,9 +922,21 @@ int main(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; } -- 1.7.6.233.gd79bc