--path-regex' syntax does not map well to restoring specific files. this patch introduces --path-from-file which takes a file listing files to restore. that file is memory mapped, and for every leaf, memmem is used to check if fs_file is in that list.
Signed-off-by: Henrik Asp <solenski...@gmail.com> Tested-by: Henrik Asp <solenski...@gmail.com> --- cmds-restore.c | 48 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/cmds-restore.c b/cmds-restore.c index dd0b242..5fa0b98 100644 --- a/cmds-restore.c +++ b/cmds-restore.c @@ -16,7 +16,6 @@ * Boston, MA 021110-1307, USA. */ - #include "kerncompat.h" #include <ctype.h> @@ -33,6 +32,7 @@ #include <getopt.h> #include <sys/types.h> #include <sys/xattr.h> +#include <sys/mman.h> #include "ctree.h" #include "disk-io.h" @@ -932,7 +932,9 @@ out: static int search_dir(struct btrfs_root *root, struct btrfs_key *key, const char *output_rootdir, const char *in_dir, - const regex_t *mreg) + const regex_t *mreg, + const char *mfile, + const int msize) { struct btrfs_path *path; struct extent_buffer *leaf; @@ -1040,6 +1042,9 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key, if (mreg && REG_NOMATCH == regexec(mreg, fs_name, 0, NULL, 0)) goto next; + if (mfile && NULL == memmem(mfile, msize, fs_name, strlen(fs_name))) + goto next; + /* full path from system root */ snprintf(path_name, PATH_MAX, "%s%s", output_rootdir, fs_name); @@ -1142,7 +1147,7 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key, } loops = 0; ret = search_dir(search_root, &location, - output_rootdir, dir, mreg); + output_rootdir, dir, mreg, mfile, msize); free(dir); if (ret) { fprintf(stderr, "Error searching %s\n", @@ -1402,6 +1407,9 @@ const char * const cmd_restore_usage[] = { " you have to use following syntax (possibly quoted):", " ^/(|home(|/username(|/Desktop(|/.*))))$", "-c ignore case (--path-regex only)", + "--path-from-file <file>", + " restore only filenames from file,", + " one file per line, case sensitive", NULL }; @@ -1422,11 +1430,17 @@ int cmd_restore(int argc, char **argv) int match_cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE; regex_t match_reg, *mreg = NULL; char reg_err[256]; + char *mfile = NULL; + int msize = 0; + const char *match_filename = NULL; + struct stat match_filestat; + int match_fd = 0; while (1) { int opt; static const struct option long_options[] = { { "path-regex", required_argument, NULL, 256}, + { "path-from-file", required_argument, NULL, 255}, { "dry-run", no_argument, NULL, 'D'}, { "metadata", no_argument, NULL, 'm'}, { "symlinks", no_argument, NULL, 'S'}, @@ -1503,6 +1517,9 @@ int cmd_restore(int argc, char **argv) case 256: match_regstr = optarg; break; + case 255: + match_filename = optarg; + break; case 'x': get_xattrs = 1; break; @@ -1599,14 +1616,37 @@ int cmd_restore(int argc, char **argv) mreg = &match_reg; } + if (match_filename) { + if ((match_fd = open(match_filename, O_RDONLY)) == -1) { + fprintf(stderr, "Failed to open file: %s\n", match_filename); + goto out; + } + if ((fstat (match_fd, &match_filestat)) == -1) { + fprintf(stderr, "Failed to stat file: %s\n", match_filename); + goto out; + } + msize = match_filestat.st_size; + if ((mfile = mmap(0, match_filestat.st_size, PROT_READ, MAP_PRIVATE, match_fd, 0)) == (char*) -1) { + fprintf(stderr, "Failed to map file: %s\n", match_filename); + mfile = NULL; + goto out; + } + if (close(match_fd) == -1) { + fprintf(stderr, "Failed to close file: %s\n", match_filename); + goto out; + } + } + if (dry_run) printf("This is a dry-run, no files are going to be restored\n"); - ret = search_dir(root, &key, dir_name, "", mreg); + ret = search_dir(root, &key, dir_name, "", mreg, mfile, msize); out: if (mreg) regfree(mreg); + if (mfile) + munmap(mfile, match_filestat.st_size); close_ctree(root); return !!ret; } -- 2.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html