mirror of
https://github.com/kdave/btrfs-progs
synced 2024-12-26 16:12:34 +00:00
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 <peter@stuge.se> Signed-off-by: Josef Bacik <josef@redhat.com> Signed-off-by: David Sterba <dsterba@suse.cz> Signed-off-by: Chris Mason <chris.mason@fusionio.com>
This commit is contained in:
parent
3d86ac20b7
commit
e35450fa53
@ -27,9 +27,11 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <lzo/lzoconf.h>
|
||||
#include <lzo/lzo1x.h>
|
||||
#include <zlib.h>
|
||||
#include <regex.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user