[SCM] Samba Shared Repository - branch master updated
Michael Adam
obnox at samba.org
Wed Jan 13 16:12:02 UTC 2016
The branch, master has been updated
via 7362c27 vfs_shadow_copy2: add a blackbox test suite
via 8a49a63 vfs_shadow_copy2: fix case where snapshots are outside the share
via 3703bca vfs_shadow_copy2: add shadow_copy2_do_convert()
from fba90fd s3:smbd_smb2_reauth_generic_return: make use of smb2req->xconn
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 7362c27a62e3802fc8df975ce50115b683811f4a
Author: Uri Simchoni <uri at samba.org>
Date: Thu Oct 29 22:24:30 2015 +0200
vfs_shadow_copy2: add a blackbox test suite
Add a blackbox test suite for vfs_shadow_copy2, testing
parameters mountpoint, basedir, snapdir, snapdirseverywhere,
and testing correct wide-link processing.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=11580
Signed-off-by: Uri Simchoni <uri at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
Autobuild-User(master): Michael Adam <obnox at samba.org>
Autobuild-Date(master): Wed Jan 13 17:11:38 CET 2016 on sn-devel-144
commit 8a49a63a5a5d8014d32179df1789186223443b35
Author: Uri Simchoni <uri at samba.org>
Date: Mon Nov 2 09:08:53 2015 +0200
vfs_shadow_copy2: fix case where snapshots are outside the share
Adjust the connect path to the root of the share in the snapshot,
or to the root of the snapshot if the snapshot is "inside" the
share.
This way snapshot symlink regarded as "wide links" if and only if
they point outside the snapshot or they were wide links when
the snapshot was taken.
This allows mounting the snapshots outside the share's root.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=11580
Signed-off-by: Uri Simchoni <uri at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
commit 3703bca4d9e494aec0b40243add3e076cf353601
Author: Uri Simchoni <uri at samba.org>
Date: Sun Nov 1 22:28:46 2015 +0200
vfs_shadow_copy2: add shadow_copy2_do_convert()
Add a new routine shadow_copy2_do_convert() which is
like shadow_copy2_convert(), but beside calculating the
path of the snapshot file, it also returns the minimum length
of the subpath which is both inside the share and inside the
same snapshot as the file in question, i.e. (at least in the
classical case) the subdirectory of the the snapshot file's
snapshot directory that corresponds to the file's share root.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=11580
Signed-off-by: Uri Simchoni <uri at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
-----------------------------------------------------------------------
Summary of changes:
selftest/target/Samba3.pm | 69 ++++++++
source3/modules/vfs_shadow_copy2.c | 107 +++++++++---
source3/script/tests/test_shadow_copy.sh | 290 +++++++++++++++++++++++++++++++
source3/selftest/tests.py | 1 +
4 files changed, 441 insertions(+), 26 deletions(-)
create mode 100755 source3/script/tests/test_shadow_copy.sh
Changeset truncated at 500 lines:
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 0906620..cd293a6 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -1126,6 +1126,15 @@ sub provision($$$$$$$$)
my $widelinks_linkdir="$shrdir/widelinks_foo";
push(@dirs,$widelinks_linkdir);
+ my $shadow_tstdir="$shrdir/shadow";
+ push(@dirs,$shadow_tstdir);
+ my $shadow_mntdir="$shadow_tstdir/mount";
+ push(@dirs,$shadow_mntdir);
+ my $shadow_basedir="$shadow_mntdir/base";
+ push(@dirs,$shadow_basedir);
+ my $shadow_shrdir="$shadow_basedir/share";
+ push(@dirs,$shadow_shrdir);
+
# this gets autocreated by winbindd
my $wbsockdir="$prefix_abs/winbindd";
my $wbsockprivdir="$lockdir/winbindd_privileged";
@@ -1392,6 +1401,10 @@ sub provision($$$$$$$$)
# fruit:copyfile is a global option
fruit:copyfile = yes
+ #this does not mean that we use non-secure test env,
+ #it just means we ALLOW one to be configured.
+ allow insecure wide links = yes
+
# Begin extra options
$extra_options
# End extra options
@@ -1553,6 +1566,62 @@ 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
+
+[shadow1]
+ path = $shadow_shrdir
+ comment = previous versions snapshots under mount point
+ vfs objects = shadow_copy2
+ shadow:mountpoint = $shadow_mntdir
+
+[shadow2]
+ path = $shadow_shrdir
+ comment = previous versions snapshots outside mount point
+ vfs objects = shadow_copy2
+ shadow:mountpoint = $shadow_mntdir
+ shadow:snapdir = $shadow_tstdir/.snapshots
+
+[shadow3]
+ path = $shadow_shrdir
+ comment = previous versions with subvolume snapshots, snapshots under base dir
+ vfs objects = shadow_copy2
+ shadow:mountpoint = $shadow_mntdir
+ shadow:basedir = $shadow_basedir
+ shadow:snapdir = $shadow_basedir/.snapshots
+
+[shadow4]
+ path = $shadow_shrdir
+ comment = previous versions with subvolume snapshots, snapshots outside mount point
+ vfs objects = shadow_copy2
+ shadow:mountpoint = $shadow_mntdir
+ shadow:basedir = $shadow_basedir
+ shadow:snapdir = $shadow_tstdir/.snapshots
+
+[shadow5]
+ path = $shadow_shrdir
+ comment = previous versions at volume root snapshots under mount point
+ vfs objects = shadow_copy2
+ shadow:mountpoint = $shadow_shrdir
+
+[shadow6]
+ path = $shadow_shrdir
+ comment = previous versions at volume root snapshots outside mount point
+ vfs objects = shadow_copy2
+ shadow:mountpoint = $shadow_shrdir
+ shadow:snapdir = $shadow_tstdir/.snapshots
+
+[shadow7]
+ path = $shadow_shrdir
+ comment = previous versions snapshots everywhere
+ vfs objects = shadow_copy2
+ shadow:mountpoint = $shadow_mntdir
+ shadow:snapdirseverywhere = yes
+
+[shadow_wl]
+ path = $shadow_shrdir
+ comment = previous versions with wide links allowed
+ vfs objects = shadow_copy2
+ shadow:mountpoint = $shadow_mntdir
+ wide links = yes
";
close(CONF);
diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c
index 93bca9c..018ec88 100644
--- a/source3/modules/vfs_shadow_copy2.c
+++ b/source3/modules/vfs_shadow_copy2.c
@@ -434,10 +434,13 @@ static char *shadow_copy2_find_mount_point(TALLOC_CTX *mem_ctx,
* Convert from a name as handed in via the SMB layer
* and a timestamp into the local path of the snapshot
* of the provided file at the provided time.
+ * Also return the path in the snapshot corresponding
+ * to the file's share root.
*/
-static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
- struct vfs_handle_struct *handle,
- const char *name, time_t timestamp)
+static char *shadow_copy2_do_convert(TALLOC_CTX *mem_ctx,
+ struct vfs_handle_struct *handle,
+ const char *name, time_t timestamp,
+ size_t *snaproot_len)
{
struct smb_filename converted_fname;
char *result = NULL;
@@ -447,10 +450,11 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
size_t pathlen;
char *insert = NULL;
char *converted = NULL;
- size_t insertlen;
+ size_t insertlen, connectlen = 0;
int i, saved_errno;
size_t min_offset;
struct shadow_copy2_config *config;
+ size_t in_share_offset = 0;
SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config,
return NULL);
@@ -492,6 +496,13 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
DEBUG(10, ("Found %s\n", converted));
result = converted;
converted = NULL;
+ if (snaproot_len != NULL) {
+ *snaproot_len = strlen(snapshot_path);
+ if (config->rel_connectpath != NULL) {
+ *snaproot_len +=
+ strlen(config->rel_connectpath) + 1;
+ }
+ }
goto fail;
} else {
errno = ENOENT;
@@ -500,6 +511,7 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
/* never reached ... */
}
+ connectlen = strlen(handle->conn->connectpath);
if (name[0] == 0) {
path = talloc_strdup(mem_ctx, handle->conn->connectpath);
} else {
@@ -575,6 +587,10 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
goto fail;
}
+ if (offset >= connectlen) {
+ in_share_offset = offset;
+ }
+
memcpy(converted+offset, insert, insertlen);
offset += insertlen;
@@ -588,6 +604,9 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
ret, ret == 0 ? "ok" : strerror(errno)));
if (ret == 0) {
/* success */
+ if (snaproot_len != NULL) {
+ *snaproot_len = in_share_offset + insertlen;
+ }
break;
}
if (errno == ENOTDIR) {
@@ -624,6 +643,18 @@ fail:
return result;
}
+/**
+ * Convert from a name as handed in via the SMB layer
+ * and a timestamp into the local path of the snapshot
+ * of the provided file at the provided time.
+ */
+static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx,
+ struct vfs_handle_struct *handle,
+ const char *name, time_t timestamp)
+{
+ return shadow_copy2_do_convert(mem_ctx, handle, name, timestamp, NULL);
+}
+
/*
modify a sbuf return to ensure that inodes in the shadow directory
are different from those in the main directory
@@ -1103,8 +1134,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,
@@ -1121,29 +1150,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;
@@ -1777,6 +1786,51 @@ 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;
+ size_t rootpath_len = 0;
+
+ DBG_DEBUG("Calc connect path for [%s]\n", fname);
+
+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
+ ×tamp, &stripped)) {
+ goto done;
+ }
+ if (timestamp == 0) {
+ return SMB_VFS_NEXT_CONNECTPATH(handle, fname);
+ }
+
+ tmp = shadow_copy2_do_convert(talloc_tos(), handle, stripped, timestamp,
+ &rootpath_len);
+ if (tmp == NULL) {
+ goto done;
+ }
+
+ DBG_DEBUG("converted path is [%s] root path is [%.*s]\n", tmp,
+ (int)rootpath_len, tmp);
+
+ tmp[rootpath_len] = '\0';
+ result = SMB_VFS_NEXT_REALPATH(handle, tmp);
+ if (result == NULL) {
+ goto done;
+ }
+
+ DBG_DEBUG("connect path is [%s]\n", result);
+
+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)
@@ -2079,6 +2133,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);
diff --git a/source3/script/tests/test_shadow_copy.sh b/source3/script/tests/test_shadow_copy.sh
new file mode 100755
index 0000000..eecd5b8
--- /dev/null
+++ b/source3/script/tests/test_shadow_copy.sh
@@ -0,0 +1,290 @@
+#!/bin/bash
+#
+# Blackbox test for shadow_copy2 VFS.
+#
+
+if [ $# -lt 7 ]; then
+cat <<EOF
+Usage: test_shadow_copy SERVER SERVER_IP DOMAIN USERNAME PASSWORD WORKDIR SMBCLIENT
+EOF
+exit 1;
+fi
+
+SERVER=${1}
+SERVER_IP=${2}
+DOMAIN=${3}
+USERNAME=${4}
+PASSWORD=${5}
+WORKDIR=${6}
+SMBCLIENT=${7}
+shift 7
+SMBCLIENT="$VALGRIND ${SMBCLIENT}"
+ADDARGS="$*"
+
+incdir=`dirname $0`/../../../testprogs/blackbox
+. $incdir/subunit.sh
+
+SNAPSHOTS[0]='@GMT-2015.10.31-19.40.30'
+SNAPSHOTS[1]='@GMT-2016.10.31-19.40.30'
+SNAPSHOTS[2]='@GMT-2017.10.31-19.40.30'
+SNAPSHOTS[3]='@GMT-2018.10.31-19.40.30'
+SNAPSHOTS[4]='@GMT-2019.10.31-19.40.30'
+SNAPSHOTS[5]='@GMT-2020.10.31-19.40.30'
+SNAPSHOTS[6]='@GMT-2021.10.31-19.40.30'
+SNAPSHOTS[7]='@GMT-2022.10.31-19.40.30'
+SNAPSHOTS[8]='@GMT-2023.10.31-19.40.30'
+SNAPSHOTS[9]='@GMT-2024.10.31-19.40.30'
+
+# build a hierarchy of files, symlinks, and directories
+build_files()
+{
+ local rootdir
+ local prefix
+ local version
+ local destdir
+ rootdir=$1
+ prefix=$2
+ version=$3
+ if [ -n "$prefix" ] ; then
+ destdir=$rootdir/$prefix
+ else
+ destdir=$rootdir
+ fi
+
+ mkdir -p $destdir
+ if [ "$version" = "latest" ] ; then
+ #non-snapshot files
+ # for non-snapshot version, create legit files
+ # so that wide-link checks focus on snapshot files
+ touch $destdir/foo
+ mkdir -p $destdir/bar
+ touch $destdir/bar/baz
+ touch $destdir/bar/lfoo
+ touch $destdir/bar/letcpasswd
+ touch $destdir/bar/loutside
+ elif [ "$version" = "fullsnap" ] ; then
+ #snapshot files
+ touch $destdir/foo
+ mkdir -p $destdir/bar
+ touch $destdir/bar/baz
+ ln -fs ../foo $destdir/bar/lfoo
+ ln -fs /etc/passwd $destdir/bar/letcpasswd
+ ln -fs ../../outside $destdir/bar/loutside
+ touch `dirname $destdir`/outside
+ else #subshare snapshot - at bar
+ touch $destdir/baz
+ ln -fs ../foo $destdir/lfoo
+ ln -fs /etc/passwd $destdir/letcpasswd
+ ln -fs ../../outside $destdir/loutside
+ touch `dirname $destdir`/../outside
+ fi
+
+}
+
+# build a snapshots directory
+build_snapshots()
+{
+ local where #where to build snapshots
+ local prefix #prefix from snapshot dir to share root
+ local start #timestamp index of first snapshot
+ local end #timestamp index of last snapshot
+ local sub #creat a snapshot of subtree of share
+ local snapdir
+ local snapname
+ local i
+ local version
+
+ where=$1
+ prefix=$2
+ start=$3
+ end=$4
+ sub=$5
+
+ snapdir=$where/.snapshots
+ mkdir -p $snapdir
+
+ version="fullsnap"
+ if [ "$sub" = "1" ] ; then
+ version="subsnap"
+ prefix=""
+
+ # a valid link target for an inner symlink -
+ # the link is not broken yet should be blocked
+ # by wide link checks
+ touch $snapdir/foo
+ fi
+
+ for i in `seq $start $end` ; do
+ snapname=${SNAPSHOTS[$i]}
+ mkdir $snapdir/$snapname
+ build_files $snapdir/$snapname "$prefix" $version
+ done
+}
+
+# Test listing previous versions of a file
+test_count_versions()
+{
+ local share
+ local path
+ local expected_count
+ local versions
+
+ share=$1
+ path=$2
+ expected_count=$3
+ versions=`$SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP -c "allinfo $path" | grep "^create_time:" | wc -l`
+ if [ "$versions" = "$expected_count" ] ; then
+ true
+ else
+ echo "expected $expected_count versions of $path, got $versions"
+ false
+ fi
+}
+
+# Test fetching a previous version of a file
+test_fetch_snap_file()
+{
+ local share
+ local path
+ local snapidx
+
+ share=$1
+ path=$2
+ snapidx=$3
+ $SMBCLIENT -U$USERNAME%$PASSWORD "//$SERVER/$share" -I $SERVER_IP \
+ -c "get ${SNAPSHOTS[$snapidx]}/$path $WORKDIR/foo"
+}
+
+test_shadow_copy_fixed()
+{
+ local share #share to contact
+ local where #where to place snapshots
+ local prefix #prefix to files inside snapshot
+ local msg
+ local allow_wl
+ local ncopies_allowd
+ local ncopies_blocked
+
+ share=$1
+ where=$2
+ prefix=$3
+ msg=$4
+ allow_wl=$5
+
+ ncopies_allowed=4
+ ncopies_blocked=1
+ if [ -n "$allow_wl" ] ; then
+ ncopies_blocked=4
+ fi
+
+ #delete snapshots from previous tests
+ find $WORKDIR -name ".snapshots" -exec rm -rf {} \; 1>/dev/null 2>&1
+ build_snapshots $WORKDIR/$where "$prefix" 0 2
+
+ testit "$msg - regular file" \
+ test_count_versions $share foo $ncopies_allowed || \
+ failed=`expr $failed + 1`
+
+ testit "$msg - regular file in subdir" \
+ test_count_versions $share bar/baz $ncopies_allowed || \
+ failed=`expr $failed + 1`
+
+ testit "$msg - local symlink" \
+ test_count_versions $share bar/lfoo $ncopies_allowed || \
+ failed=`expr $failed + 1`
+
+ testit "$msg - abs symlink outside" \
+ test_count_versions $share bar/letcpasswd $ncopies_blocked || \
+ failed=`expr $failed + 1`
+
+ testit "$msg - rel symlink outside" \
+ test_count_versions $share bar/loutside $ncopies_blocked || \
+ failed=`expr $failed + 1`
+}
+
+test_shadow_copy_everywhere()
--
Samba Shared Repository
More information about the samba-cvs
mailing list