diff mbox

[RFC,5/5] btrfs-progs: let this feature works at subvolume command group.

Message ID 5020D899.4070301@oracle.com (mailing list archive)
State New, archived
Headers show

Commit Message

jeff.liu Aug. 7, 2012, 8:58 a.m. UTC
make this feature works as `btrfs subvolume diff-snapshot [options] <src> <dest>`.


Signed-off-by: Jie Liu <jeff.liu@oracle.com>

---
 cmds-subvolume.c |   90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 90 insertions(+), 0 deletions(-)
diff mbox

Patch

diff --git a/cmds-subvolume.c b/cmds-subvolume.c
index 3508ce6..e7cc3cc 100644
--- a/cmds-subvolume.c
+++ b/cmds-subvolume.c
@@ -28,6 +28,7 @@ 
 #include "ioctl.h"
 
 #include "commands.h"
+#include "diff-snapshot.h"
 
 /* btrfs-list.c */
 int list_subvols(int fd, int print_parent, int get_default);
@@ -515,6 +516,94 @@  static int cmd_find_new(int argc, char **argv)
 	return 0;
 }
 
+static const char * const cmd_snapshot_diff_usage[] = {
+	"btrfs subvolume diff-snapshot [options] <source> <dest>",
+	"List the differences between two snapshots",
+	"By default, list all changes in destination snapshot towards source",
+	"",
+	"-n	list the new items in destination snapshot\n",
+	"-r	list the removed items in destination snapshot\n",
+	"-u	list the updated items in destination snapshot\n",
+	NULL
+};
+
+static int cmd_snapshot_diff(int argc, char **argv)
+{
+	int ret;
+	int src_fd;
+	int dst_fd;
+	char *src_snapshot;
+	char *dest_snapshot;
+	unsigned int flags = 0;
+
+	while (1) {
+		int c = getopt(argc, argv, "rnu");
+		if (c < 0)
+			break;
+		switch (c) {
+		case 'r':
+			flags |= SNAPSHOT_DIFF_LIST_REMOVED_ITEM;
+			break;
+		case 'n':
+			flags |= SNAPSHOT_DIFF_LIST_NEW_ITEM;
+			break;
+		case 'u':
+			flags |= SNAPSHOT_DIFF_LIST_UPDATED_ITEM;
+			break;
+		default:
+			fprintf(stderr, "ERROR: snapshot diff args invalid.\n"
+					" -r  list removed items\n"
+					" -n  list new items\n"
+					" -u  list updated items\n");
+			return 1;
+		}
+	}
+
+	src_snapshot = argv[argc - 2];
+	dest_snapshot = argv[argc - 1];
+
+	ret = test_issubvolume(src_snapshot);
+	if (ret < 0) {
+		fprintf(stderr, "ERROR: error accessing '%s'\n",
+			src_snapshot);
+		return 12;
+	}
+	if (!ret) {
+		fprintf(stderr, "ERROR: '%s' is not a subvolume\n",
+			src_snapshot);
+		return 13;
+	}
+
+	ret = test_issubvolume(dest_snapshot);
+	if (ret < 0) {
+		fprintf(stderr, "ERROR: error accessing '%s'\n",
+			dest_snapshot);
+		return 12;
+	}
+	if (!ret) {
+		fprintf(stderr, "ERROR: '%s' is not a subvolume\n",
+			dest_snapshot);
+		return 13;
+	}
+
+	src_fd = open_file_or_dir(src_snapshot);
+	if (src_fd < 0) {
+		fprintf(stderr, "ERROR: can't access '%s'\n", src_snapshot);
+		return 12;
+	}
+
+	dst_fd = open_file_or_dir(dest_snapshot);
+	if (dst_fd < 0) {
+		fprintf(stderr, "ERROR: can't access '%s'\n", dest_snapshot);
+		return 12;
+	}
+
+	ret = snapshot_diff(src_fd, dst_fd, src_snapshot, dest_snapshot, flags);
+	if (ret)
+		return 19;
+	return 0;
+}
+
 const struct cmd_group subvolume_cmd_group = {
 	subvolume_cmd_group_usage, NULL, {
 		{ "create", cmd_subvol_create, cmd_subvol_create_usage, NULL, 0 },
@@ -526,6 +615,7 @@  const struct cmd_group subvolume_cmd_group = {
 		{ "set-default", cmd_subvol_set_default,
 			cmd_subvol_set_default_usage, NULL, 0 },
 		{ "find-new", cmd_find_new, cmd_find_new_usage, NULL, 0 },
+		{ "diff-snapshot", cmd_snapshot_diff, cmd_snapshot_diff_usage, NULL, 0 },
 		{ 0, 0, 0, 0, 0 }
 	}
 };