[PATCHES] vfs_shadow_copy2: allow snapshots outside share's root

Uri Simchoni uri at samba.org
Thu Oct 29 22:41:28 UTC 2015


Hi,

I may just be misconfiguring shadow_copy2 here, but it does seem like a 
bug to me, so here's a fix and some tests.

I filed https://bugzilla.samba.org/show_bug.cgi?id=11580 where I 
describe what kind of snapshot setup I'm using, and how I configure 
shadow_copy2 for that.

- If there's a way to get this to work without the patch - I'd love to 
stand corrected
- Haven't wrapped my mind around "snapshots everywhere" - need to verify 
this isn't broken by the fix, however I figured I'd submit the patch 
anyway to get feedback if it's a non-bug.

Thanks,
Uri.

-------------- next part --------------
From 4c72b4a9dd36a962bfb14826501e293834b64f75 Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Thu, 29 Oct 2015 22:24:30 +0200
Subject: [PATCH 1/3] vfs_shadow_copy2: add a blackbox test for snapshots
 inside the share

Add a blackbox test for listing previous versions of a file where
the snapshots reside inside the share directory.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=11580

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 selftest/target/Samba3.pm                | 42 ++++++++++++++++++++++++++++++
 source3/script/tests/test_shadow_copy.sh | 44 ++++++++++++++++++++++++++++++++
 source3/selftest/tests.py                |  1 +
 3 files changed, 87 insertions(+)
 create mode 100755 source3/script/tests/test_shadow_copy.sh

diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index f66aea7..a6dec44 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -807,6 +807,26 @@ map to guest = bad user
 	return $vars;
 }
 
+sub create_snapshots($$$)
+{
+	my ($self, $path, $fname) = @_;
+
+	my @snapshots = ("\@GMT-2015.10.29-11.44.24",
+			 "\@GMT-2016.10.29-11.44.24",
+			 "\@GMT-2017.10.29-11.44.24");
+
+	foreach my $snap (@snapshots) {
+		mkdir("$path/$snap", 0777);
+		unless (open(SNAP_FILE, ">$path/$snap/$fname")) {
+			warn("Unable to open $path/$snap/$fname");
+			return undef;
+		}
+		close (SNAP_FILE);
+	}
+
+	return 1;
+}
+
 sub stop_sig_term($$) {
 	my ($self, $pid) = @_;
 	kill("USR1", $pid) or kill("ALRM", $pid) or warn("Unable to kill $pid: $!");
@@ -1109,6 +1129,9 @@ sub provision($$$$$$$$)
 	my $manglenames_shrdir="$shrdir/manglenames";
 	push(@dirs,$manglenames_shrdir);
 
+	my $intsnap_shrdir="$shrdir/intsnap";
+	push(@dirs,$intsnap_shrdir);
+
 	# this gets autocreated by winbindd
 	my $wbsockdir="$prefix_abs/winbindd";
 	my $wbsockprivdir="$lockdir/winbindd_privileged";
@@ -1198,6 +1221,19 @@ sub provision($$$$$$$$)
         my $manglename_target = "$manglenames_shrdir/foo:bar";
 	mkdir($manglename_target, 0777);
 
+	##
+	## create intsnap  directory layout
+	##
+        unless (open(SNAP_MAIN_FILE, ">$intsnap_shrdir/foo")) {
+                warn("Unable to open $intsnap_shrdir/foo");
+                return undef;
+        }
+        close(SNAP_MAIN_FILE);
+	mkdir("$intsnap_shrdir/.snapshots");
+	if (not defined($self->create_snapshots("$intsnap_shrdir/.snapshots", "foo"))) {
+		return undef;
+	}
+
 	my $conffile="$libdir/server.conf";
 
 	my $nss_wrapper_pl = "$ENV{PERL} $self->{srcdir}/lib/nss_wrapper/nss_wrapper.pl";
@@ -1502,6 +1538,12 @@ sub provision($$$$$$$$)
 	shell_snap:delete command = $fake_snap_pl --delete
 	# a relative path here fails, the snapshot dir is no longer found
 	shadow:snapdir = $shrdir/.snapshots
+
+[intsnap]
+	path = $intsnap_shrdir
+	comment = share with previous versions inside share root
+	vfs objects = shadow_copy2
+	shadow:mountpoint = $intsnap_shrdir
 	";
 	close(CONF);
 
diff --git a/source3/script/tests/test_shadow_copy.sh b/source3/script/tests/test_shadow_copy.sh
new file mode 100755
index 0000000..cabd161
--- /dev/null
+++ b/source3/script/tests/test_shadow_copy.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+#
+# Blackbox test for shadow_copy2 VFS.
+#
+
+if [ $# -lt 6 ]; then
+cat <<EOF
+Usage: test_shadow_copy SERVER SERVER_IP DOMAIN USERNAME PASSWORD SMBCLIENT
+EOF
+exit 1;
+fi
+
+SERVER=${1}
+SERVER_IP=${2}
+DOMAIN=${3}
+USERNAME=${4}
+PASSWORD=${5}
+SMBCLIENT=${6}
+shift 6
+SMBCLIENT="$VALGRIND ${SMBCLIENT}"
+ADDARGS="$*"
+
+incdir=`dirname $0`/../../../testprogs/blackbox
+. $incdir/subunit.sh
+
+failed=0
+
+# Test listing previous versions of a file
+test_count_versions()
+{
+    versions=`$SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$1" -I $SERVER_IP -c "allinfo foo" | grep "^create_time:" | wc -l`
+    if [ "$versions" = "4" ] ; then
+        true
+    else
+        echo "expected 4 versions of foo, got $versions"
+        false
+    fi
+}
+
+testit "counting previous versions inside share" \
+   test_count_versions intsnap || \
+   failed=`expr $failed + 1`
+
+exit $failed
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index 048675a..6a4f69a 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -178,6 +178,7 @@ for env in ["fileserver"]:
     plantestsuite("samba3.blackbox.preserve_case (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_preserve_case.sh"), '$SERVER', '$DOMAIN', '$USERNAME', '$PASSWORD', '$PREFIX', smbclient3])
     plantestsuite("samba3.blackbox.dfree_command (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_dfree_command.sh"), '$SERVER', '$DOMAIN', '$USERNAME', '$PASSWORD', '$PREFIX', smbclient3])
     plantestsuite("samba3.blackbox.valid_users (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_valid_users.sh"), '$SERVER', '$SERVER_IP', '$DOMAIN', '$USERNAME', '$PASSWORD', '$PREFIX', smbclient3])
+    plantestsuite("samba3.blackbox.shadow_copy2 (%s)" % env, env, [os.path.join(samba3srcdir, "script/tests/test_shadow_copy.sh"), '$SERVER', '$SERVER_IP', '$DOMAIN', '$USERNAME', '$PASSWORD', smbclient3])
 
     #
     # tar command tests
-- 
2.4.3


From 10138fca969d0d6e21af0f5cbb4bf30c97333d5f Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Fri, 30 Oct 2015 00:10:17 +0200
Subject: [PATCH 2/3] vfs_shadow_copy2: fix case where snapshots are outside
 the share

Adjust the connect path to the root of the share in the snapshot,
in order to not-regard snapshot files as "wide links" if the
snapshots are located outside the share's root dir.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=11580

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/modules/vfs_shadow_copy2.c | 55 +++++++++++++++++++++++---------------
 1 file changed, 33 insertions(+), 22 deletions(-)

diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c
index 4d2ec54..bf3041a 100644
--- a/source3/modules/vfs_shadow_copy2.c
+++ b/source3/modules/vfs_shadow_copy2.c
@@ -1102,8 +1102,6 @@ static char *shadow_copy2_realpath(vfs_handle_struct *handle,
 	char *stripped = NULL;
 	char *tmp = NULL;
 	char *result = NULL;
-	char *inserted = NULL;
-	char *inserted_to, *inserted_end;
 	int saved_errno;
 
 	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
@@ -1120,29 +1118,9 @@ static char *shadow_copy2_realpath(vfs_handle_struct *handle,
 	}
 
 	result = SMB_VFS_NEXT_REALPATH(handle, tmp);
-	if (result == NULL) {
-		goto done;
-	}
-
-	/*
-	 * Take away what we've inserted. This removes the @GMT-thingy
-	 * completely, but will give a path under the share root.
-	 */
-	inserted = shadow_copy2_insert_string(talloc_tos(), handle, timestamp);
-	if (inserted == NULL) {
-		goto done;
-	}
-	inserted_to = strstr_m(result, inserted);
-	if (inserted_to == NULL) {
-		DEBUG(2, ("SMB_VFS_NEXT_REALPATH removed %s\n", inserted));
-		goto done;
-	}
-	inserted_end = inserted_to + talloc_get_size(inserted) - 1;
-	memmove(inserted_to, inserted_end, strlen(inserted_end)+1);
 
 done:
 	saved_errno = errno;
-	TALLOC_FREE(inserted);
 	TALLOC_FREE(tmp);
 	TALLOC_FREE(stripped);
 	errno = saved_errno;
@@ -1732,6 +1710,38 @@ static int shadow_copy2_get_real_filename(struct vfs_handle_struct *handle,
 	return ret;
 }
 
+static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle,
+					    const char *fname)
+{
+	time_t timestamp;
+	char *stripped = NULL;
+	char *tmp = NULL;
+	char *result = NULL;
+	int saved_errno;
+
+	if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
+					 &timestamp, &stripped)) {
+		goto done;
+	}
+	if (timestamp == 0) {
+		return SMB_VFS_NEXT_CONNECTPATH(handle, fname);
+	}
+
+	tmp = shadow_copy2_convert(talloc_tos(), handle, "", timestamp);
+	if (tmp == NULL) {
+		goto done;
+	}
+
+	result = SMB_VFS_NEXT_REALPATH(handle, tmp);
+
+done:
+	saved_errno = errno;
+	TALLOC_FREE(tmp);
+	TALLOC_FREE(stripped);
+	errno = saved_errno;
+	return result;
+}
+
 static uint64_t shadow_copy2_disk_free(vfs_handle_struct *handle,
 				       const char *path, uint64_t *bsize,
 				       uint64_t *dfree, uint64_t *dsize)
@@ -2033,6 +2043,7 @@ static struct vfs_fn_pointers vfs_shadow_copy2_fns = {
 	.chmod_acl_fn = shadow_copy2_chmod_acl,
 	.chflags_fn = shadow_copy2_chflags,
 	.get_real_filename_fn = shadow_copy2_get_real_filename,
+	.connectpath_fn = shadow_copy2_connectpath,
 };
 
 NTSTATUS vfs_shadow_copy2_init(void);
-- 
2.4.3


From f594891266e4374020c6d689b32fbeb8bea67a42 Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Thu, 29 Oct 2015 23:03:13 +0200
Subject: [PATCH 3/3] vfs_shadow_copy2: add a blackbox test with snapshots
 outside share

Add a blackbox test with snapshots located outside the share's root

BUG: https://bugzilla.samba.org/show_bug.cgi?id=11580

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 selftest/target/Samba3.pm                | 24 ++++++++++++++++++++++++
 source3/script/tests/test_shadow_copy.sh |  4 ++++
 2 files changed, 28 insertions(+)

diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index a6dec44..3e19d7f 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -1132,6 +1132,11 @@ sub provision($$$$$$$$)
 	my $intsnap_shrdir="$shrdir/intsnap";
 	push(@dirs,$intsnap_shrdir);
 
+	my $extsnap_shrdir="$shrdir/extsnap";
+	push(@dirs,$extsnap_shrdir);
+	my $extsnap_snapdir="$shrdir/extsnap_snap";
+	push(@dirs,$extsnap_snapdir);
+
 	# this gets autocreated by winbindd
 	my $wbsockdir="$prefix_abs/winbindd";
 	my $wbsockprivdir="$lockdir/winbindd_privileged";
@@ -1234,6 +1239,18 @@ sub provision($$$$$$$$)
 		return undef;
 	}
 
+	##
+	## create extsnap  directory layout
+	##
+        unless (open(SNAP_MAIN_FILE, ">$extsnap_shrdir/foo")) {
+                warn("Unable to open $extsnap_shrdir/foo");
+                return undef;
+        }
+        close(SNAP_MAIN_FILE);
+	if (not defined($self->create_snapshots("$extsnap_snapdir", "foo"))) {
+		return undef;
+	}
+
 	my $conffile="$libdir/server.conf";
 
 	my $nss_wrapper_pl = "$ENV{PERL} $self->{srcdir}/lib/nss_wrapper/nss_wrapper.pl";
@@ -1544,6 +1561,13 @@ sub provision($$$$$$$$)
 	comment = share with previous versions inside share root
 	vfs objects = shadow_copy2
 	shadow:mountpoint = $intsnap_shrdir
+
+[extsnap]
+	path = $extsnap_shrdir
+	comment = share with previous versions outside share root
+	vfs objects = shadow_copy2
+	shadow:mountpoint = $extsnap_shrdir
+	shadow:snapdir = $extsnap_snapdir
 	";
 	close(CONF);
 
diff --git a/source3/script/tests/test_shadow_copy.sh b/source3/script/tests/test_shadow_copy.sh
index cabd161..baf59c5 100755
--- a/source3/script/tests/test_shadow_copy.sh
+++ b/source3/script/tests/test_shadow_copy.sh
@@ -41,4 +41,8 @@ testit "counting previous versions inside share" \
    test_count_versions intsnap || \
    failed=`expr $failed + 1`
 
+testit "counting previous versions outside share" \
+   test_count_versions extsnap || \
+   failed=`expr $failed + 1`
+
 exit $failed
-- 
2.4.3



More information about the samba-technical mailing list