linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] btrfs-progs: restore: make btrfs restore able to read a file which lists files to restore
@ 2016-02-22 17:53 Henrik Asp
  2016-02-22 23:32 ` Duncan
  2016-02-24 11:51 ` David Sterba
  0 siblings, 2 replies; 4+ messages in thread
From: Henrik Asp @ 2016-02-22 17:53 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Henrik Asp

--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 <solenskiner@gmail.com>
Tested-by: Henrik Asp <solenskiner@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


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-02-24 13:01 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-02-22 17:53 [PATCH] btrfs-progs: restore: make btrfs restore able to read a file which lists files to restore Henrik Asp
2016-02-22 23:32 ` Duncan
2016-02-24 11:51 ` David Sterba
2016-02-24 13:01   ` Henrik Asp

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).