[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Mon Jan 30 21:27:02 UTC 2017


The branch, master has been updated
       via  0e1deb7 s3: VFS: Don't allow symlink, link or rename on already converted paths.
       via  cda6764 s3: VFS: shadow_copy2: Fix usage of saved_errno to only set errno on error.
       via  4d339a8 s3: VFS: shadow_copy2: Fix a memory leak in the connectpath function.
       via  128d5f2 s3: VFS: shadow_copy2: Fix module to work with variable current working directory.
       via  b94dc85 s3: VFS: Add utility function check_for_converted_path().
       via  cd4f940 s3: VFS: Ensure shadow:format cannot contain a / path separator.
       via  42bd1ac s3: VFS: Allow shadow_copy2_connectpath() to return the cached path derived from $cwd.
       via  27340df s3: VFS: shadow_copy2: Fix chdir to store off the needed private variables.
       via  9d65107 s3: VFS: shadow_copy2: Add two currently unused functions to make pathnames absolute or relative to $cwd.
       via  2887465 s3: VFS: shadow_copy2: Change a parameter name.
       via  5aa1ea9 s3: VFS: shadow_copy2: Add a wrapper function to call the original shadow_copy2_strip_snapshot().
       via  72fe2b6 s3: VFS: shadow_copy2: Add two new variables to the private data. Not yet used.
       via  37ef8d3 s3: VFS: shadow_copy2: Fix length comparison to ensure we don't overstep a length.
       via  979e392 s3: VFS: shadow_copy2: Ensure pathnames for parameters are correctly relative and terminated.
       via  0a190f4 s3: VFS: shadow_copy2: Correctly initialize timestamp and stripped variables.
       via  d650d65 s3: smbd: Make set_conn_connectpath() call canonicalize_absolute_path().
       via  a513633 s3: smbtorture: Add new local test LOCAL-CANONICALIZE-PATH
       via  82979af s3: lib: Fix two old, old bugs in set_conn_connectpath(), now in canonicalize_absolute_path().
       via  02599c3 s3: lib: Add canonicalize_absolute_path().
       via  39678ed s3: smbd: Correctly canonicalize any incoming shadow copy path.
      from  26ffc20 build: vfs_posix_eadb is only built with the AD DC enabled

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 0e1deb77f2b310ad7e5dd784174207adacf1c981
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Jan 26 17:19:24 2017 -0800

    s3: VFS: Don't allow symlink, link or rename on already converted paths.
    
    Snapshot paths are a read-only filesystem.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Uri Simchoni <uri at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Mon Jan 30 22:26:29 CET 2017 on sn-devel-144

commit cda6764f1a8db96182bfd1855440bc6a1ba1abee
Author: Jeremy Allison <jra at samba.org>
Date:   Mon Jan 23 10:20:13 2017 -0800

    s3: VFS: shadow_copy2: Fix usage of saved_errno to only set errno on error.
    
    Rationale:
    
    VFS calls must act like their POSIX equivalents, and the POSIX versions
    *only* set errno on a failure. There is actually code in the upper smbd
    layers that depends on errno being correct on a fail return from a VFS call.
    
    For a compound VFS module like this, a common pattern is :
    
    SMB_VFS_CALL_X()
    {
          int ret;
    
          syscall1();
          ret = syscall2();
          syscall3();
    
          return ret;
    }
    
    Where if *any* of the contained syscallX()'s fail, they'll set errno.
    However, the actual errno we should return is *only* the one returned
    if syscall2() fails (the others are lstat's checking for existence etc.).
    
    So what we should do to correctly return only the errno from syscall2() is:
    
    SMB_VFS_CALL_X()
    {
          int ret;
          int saved_errno = 0;
    
          syscall1()
    
          ret = syscall2();
          if (ret == -1) {
                saved_errno = errno;
          }
          syscall3()
    
          if (saved_errno != 0) {
               errno = saved_errno;
          }
          return ret;
    }
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Uri Simchoni <uri at samba.org>

commit 4d339a88851f601fae195ac8ff0691cbd3504f41
Author: Jeremy Allison <jra at samba.org>
Date:   Mon Jan 23 10:06:44 2017 -0800

    s3: VFS: shadow_copy2: Fix a memory leak in the connectpath function.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Uri Simchoni <uri at samba.org>

commit 128d5f27cd42b0c7efcbe3d28fe3eee881e0734b
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Jan 26 10:49:51 2017 -0800

    s3: VFS: shadow_copy2: Fix module to work with variable current working directory.
    
    Completely cleans up the horrible shadow_copy2_strip_snapshot()
    and adds an explaination of what it's actually trying to do.
    
    * This function does two things.
    *
    * 1). Checks if an incoming filename is already a
    * snapshot converted pathname.
    *     If so, it returns the pathname truncated
    *     at the snapshot point which will be used
    *     as the connectpath, and then does an early return.
    *
    * 2). Checks if an incoming filename contains an
    * SMB-layer @GMT- style timestamp.
    *     If so, it strips the timestamp, and returns
    *     both the timestamp and the stripped path
    *     (making it cwd-relative).
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Uri Simchoni <uri at samba.org>

commit b94dc85d339c9a10496edd07b85bdd7808d2e332
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Jan 26 10:35:50 2017 -0800

    s3: VFS: Add utility function check_for_converted_path().
    
    Detects an already converted path. Not yet used.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Uri Simchoni <uri at samba.org>

commit cd4f940162b17e4f7345d392326a31ae478230fa
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Jan 26 10:24:52 2017 -0800

    s3: VFS: Ensure shadow:format cannot contain a / path separator.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Uri Simchoni <uri at samba.org>

commit 42bd1acad75a6b5ea81fe4b30c067dd82623c042
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Jan 20 12:09:08 2017 -0800

    s3: VFS: Allow shadow_copy2_connectpath() to return the cached path derived from $cwd.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Uri Simchoni <uri at samba.org>

commit 27340df4b52e4341f134667c59d71656a7a1fdae
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Jan 20 12:06:55 2017 -0800

    s3: VFS: shadow_copy2: Fix chdir to store off the needed private variables.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531
    
    This is not yet used, the users of this will be added later.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Uri Simchoni <uri at samba.org>

commit 9d65107b8f2864dba8d41b3316c483b3f36d0697
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Jan 20 12:00:08 2017 -0800

    s3: VFS: shadow_copy2: Add two currently unused functions to make pathnames absolute or relative to $cwd.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Uri Simchoni <uri at samba.org>

commit 2887465108aef5e2e7c64417437ecb86c7460e16
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Jan 20 11:56:21 2017 -0800

    s3: VFS: shadow_copy2: Change a parameter name.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531
    
    Allows easy substitution later.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Uri Simchoni <uri at samba.org>

commit 5aa1ea95157475dfd2d056f0158b14b2b90895a9
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Jan 20 11:54:56 2017 -0800

    s3: VFS: shadow_copy2: Add a wrapper function to call the original shadow_copy2_strip_snapshot().
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531
    
    Allows an extra (currently unused) parameter to be added.
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Uri Simchoni <uri at samba.org>

commit 72fe2b62e3ee7462e5be855b01943f28b26c36c1
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Jan 20 11:50:49 2017 -0800

    s3: VFS: shadow_copy2: Add two new variables to the private data. Not yet used.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Uri Simchoni <uri at samba.org>

commit 37ef8d3f65bd1215717eb51b2e1cdb84a7bed348
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Jan 20 11:48:40 2017 -0800

    s3: VFS: shadow_copy2: Fix length comparison to ensure we don't overstep a length.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Uri Simchoni <uri at samba.org>

commit 979e39252bcc88e8aacb543b8bf322dd6f17fe7f
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Jan 20 11:45:54 2017 -0800

    s3: VFS: shadow_copy2: Ensure pathnames for parameters are correctly relative and terminated.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Uri Simchoni <uri at samba.org>

commit 0a190f4dd950c947d47c42163d11ea4bd6e6e508
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Jan 20 11:42:39 2017 -0800

    s3: VFS: shadow_copy2: Correctly initialize timestamp and stripped variables.
    
    Allow the called functions to be fixed to not touch them on error.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Uri Simchoni <uri at samba.org>

commit d650d65488761b30fa34d42cb1ab400618a78c33
Author: Jeremy Allison <jra at samba.org>
Date:   Tue Jan 17 11:35:52 2017 -0800

    s3: smbd: Make set_conn_connectpath() call canonicalize_absolute_path().
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Uri Simchoni <uri at samba.org>

commit a51363309a4330b65e34ae941ec99d180bdbab56
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Jan 26 16:08:42 2017 -0800

    s3: smbtorture: Add new local test LOCAL-CANONICALIZE-PATH
    
    Tests new canonicalize_absolute_path() function.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Uri Simchoni <uri at samba.org>

commit 82979afc46cc5e466bdd999a94080e7a5df95518
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Jan 19 15:18:41 2017 -0800

    s3: lib: Fix two old, old bugs in set_conn_connectpath(), now in canonicalize_absolute_path().
    
    Canonicalizing a path of /foo/bar/../baz would return /foo/barbaz
    as moving forward 3 characters would delete the / character.
    
    Canonicalizing /foo/.. would end up as '\0'.
    
    Test to follow.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Uri Simchoni <uri at samba.org>

commit 02599c39337c3049762a6b0bd6290577817ee5a5
Author: Jeremy Allison <jra at samba.org>
Date:   Tue Jan 17 11:33:18 2017 -0800

    s3: lib: Add canonicalize_absolute_path().
    
    Resolves any invalid path components (.) (..)
    in an absolute POSIX path.
    
    We will be re-using this in several places.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Uri Simchoni <uri at samba.org>

commit 39678ed6af708fb6f2760bfb51051add11e3c498
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Jan 11 16:30:38 2017 -0800

    s3: smbd: Correctly canonicalize any incoming shadow copy path.
    
    Converts to:
    
    @GMT-token/path/last_component
    
    from all incoming path types. Allows shadow_copy modules
    to work when current directory is changed after removing
    last component.
    
    Ultimately when the VFS ABI is changed to add a timestamp
    to struct smb_filename, this is where the parsing will be
    done.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Uri Simchoni <uri at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 source3/lib/util_path.c            | 139 ++++++
 source3/lib/util_path.h            |   1 +
 source3/modules/vfs_shadow_copy2.c | 909 ++++++++++++++++++++++++++-----------
 source3/selftest/tests.py          |   1 +
 source3/smbd/filename.c            | 150 ++++++
 source3/smbd/service.c             | 103 +----
 source3/torture/torture.c          |  44 ++
 7 files changed, 994 insertions(+), 353 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/lib/util_path.c b/source3/lib/util_path.c
index 509ba5f..6f58a03 100644
--- a/source3/lib/util_path.c
+++ b/source3/lib/util_path.c
@@ -93,3 +93,142 @@ char *cache_path(const char *name)
 {
 	return xx_path(name, lp_cache_directory());
 }
+
+/**
+ * @brief Removes any invalid path components in an absolute POSIX path.
+ *
+ * @param ctx Talloc context to return string.
+ *
+ * @param abs_path Absolute path string to process.
+ *
+ * @retval Pointer to a talloc'ed string containing the absolute full path.
+ **/
+
+char *canonicalize_absolute_path(TALLOC_CTX *ctx, const char *abs_path)
+{
+	char *destname;
+	char *d;
+	const char *s = abs_path;
+	bool start_of_name_component = true;
+
+	/* Allocate for strlen + '\0' + possible leading '/' */
+	destname = (char *)talloc_size(ctx, strlen(abs_path) + 2);
+	if (destname == NULL) {
+		return NULL;
+        }
+	d = destname;
+
+	*d++ = '/'; /* Always start with root. */
+
+	while (*s) {
+		if (*s == '/') {
+			/* Eat multiple '/' */
+			while (*s == '/') {
+				s++;
+			}
+			if ((d > destname + 1) && (*s != '\0')) {
+				*d++ = '/';
+			}
+			start_of_name_component = true;
+			continue;
+		}
+
+		if (start_of_name_component) {
+			if ((s[0] == '.') && (s[1] == '.') &&
+					(s[2] == '/' || s[2] == '\0')) {
+				/* Uh oh - "/../" or "/..\0" ! */
+
+				/* Go past the .. leaving us on the / or '\0' */
+				s += 2;
+
+				/* If  we just added a '/' - delete it */
+				if ((d > destname) && (*(d-1) == '/')) {
+					*(d-1) = '\0';
+					d--;
+				}
+
+				/*
+				 * Are we at the start ?
+				 * Can't go back further if so.
+				 */
+				if (d <= destname) {
+					*d++ = '/'; /* Can't delete root */
+					continue;
+				}
+				/* Go back one level... */
+				/*
+				 * Decrement d first as d points to
+				 * the *next* char to write into.
+				 */
+				for (d--; d > destname; d--) {
+					if (*d == '/') {
+						break;
+					}
+				}
+
+				/*
+				 * Are we at the start ?
+				 * Can't go back further if so.
+				 */
+				if (d <= destname) {
+					*d++ = '/'; /* Can't delete root */
+					continue;
+				}
+
+				/*
+				 * We're still at the start of a name
+				 * component, just the previous one.
+				 */
+				continue;
+			} else if ((s[0] == '.') &&
+					((s[1] == '\0') || s[1] == '/')) {
+				/*
+				 * Component of pathname can't be "." only.
+				 * Skip the '.' .
+				 */
+				if (s[1] == '/') {
+					s += 2;
+				} else {
+					s++;
+				}
+				continue;
+			}
+		}
+
+		if (!(*s & 0x80)) {
+			*d++ = *s++;
+		} else {
+			size_t siz;
+			/* Get the size of the next MB character. */
+			next_codepoint(s,&siz);
+			switch(siz) {
+				case 5:
+					*d++ = *s++;
+					/*fall through*/
+				case 4:
+					*d++ = *s++;
+					/*fall through*/
+				case 3:
+					*d++ = *s++;
+					/*fall through*/
+				case 2:
+					*d++ = *s++;
+					/*fall through*/
+				case 1:
+					*d++ = *s++;
+					break;
+				default:
+					break;
+			}
+		}
+		start_of_name_component = false;
+	}
+	*d = '\0';
+
+	/* And must not end in '/' */
+	if (d > destname + 1 && (*(d-1) == '/')) {
+		*(d-1) = '\0';
+	}
+
+	return destname;
+}
diff --git a/source3/lib/util_path.h b/source3/lib/util_path.h
index 118a4be..16e2792 100644
--- a/source3/lib/util_path.h
+++ b/source3/lib/util_path.h
@@ -27,5 +27,6 @@
 char *lock_path(const char *name);
 char *state_path(const char *name);
 char *cache_path(const char *name);
+char *canonicalize_absolute_path(TALLOC_CTX *ctx, const char *abs_path);
 
 #endif
diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c
index 6a25c87..402eb70 100644
--- a/source3/modules/vfs_shadow_copy2.c
+++ b/source3/modules/vfs_shadow_copy2.c
@@ -35,6 +35,7 @@
 #include "system/filesys.h"
 #include "include/ntioctl.h"
 #include "util_tdb.h"
+#include "lib/util_path.h"
 
 struct shadow_copy2_config {
 	char *gmt_format;
@@ -74,6 +75,11 @@ struct shadow_copy2_snaplist_info {
 struct shadow_copy2_private {
 	struct shadow_copy2_config *config;
 	struct shadow_copy2_snaplist_info *snaps;
+	char *shadow_cwd; /* Absolute $cwd path. */
+	/* Absolute connectpath - can vary depending on $cwd. */
+	char *shadow_connectpath;
+	/* malloc'ed realpath return. */
+	char *shadow_realpath;
 };
 
 static int shadow_copy2_get_shadow_copy_data(
@@ -404,79 +410,254 @@ static char *shadow_copy2_snapshot_path(TALLOC_CTX *mem_ctx,
 	return result;
 }
 
+static char *make_path_absolute(TALLOC_CTX *mem_ctx,
+				struct shadow_copy2_private *priv,
+				const char *name)
+{
+	char *newpath = NULL;
+	char *abs_path = NULL;
+
+	if (name[0] != '/') {
+		newpath = talloc_asprintf(mem_ctx,
+					"%s/%s",
+					priv->shadow_cwd,
+					name);
+		if (newpath == NULL) {
+			return NULL;
+		}
+		name = newpath;
+	}
+	abs_path = canonicalize_absolute_path(mem_ctx, name);
+	TALLOC_FREE(newpath);
+	return abs_path;
+}
+
+/* Return a $cwd-relative path. */
+static bool make_relative_path(const char *cwd, char *abs_path)
+{
+	size_t cwd_len = strlen(cwd);
+	size_t abs_len = strlen(abs_path);
+
+	if (abs_len < cwd_len) {
+		return false;
+	}
+	if (memcmp(abs_path, cwd, cwd_len) != 0) {
+		return false;
+	}
+	if (abs_path[cwd_len] != '/' && abs_path[cwd_len] != '\0') {
+		return false;
+	}
+	if (abs_path[cwd_len] == '/') {
+		cwd_len++;
+	}
+	memmove(abs_path, &abs_path[cwd_len], abs_len + 1 - cwd_len);
+	return true;
+}
+
+static bool shadow_copy2_snapshot_to_gmt(vfs_handle_struct *handle,
+					const char *name,
+					char *gmt, size_t gmt_len);
+
+/*
+ * Check if an incoming filename is already a snapshot converted pathname.
+ *
+ * If so, it returns the pathname truncated at the snapshot point which
+ * will be used as the connectpath.
+ */
+
+static int check_for_converted_path(TALLOC_CTX *mem_ctx,
+				struct vfs_handle_struct *handle,
+				struct shadow_copy2_private *priv,
+				char *abs_path,
+				bool *ppath_already_converted,
+				char **pconnectpath)
+{
+	size_t snapdirlen = 0;
+	char *p = strstr_m(abs_path, priv->config->snapdir);
+	char *q = NULL;
+	char *connect_path = NULL;
+	char snapshot[GMT_NAME_LEN+1];
+
+	*ppath_already_converted = false;
+
+	if (p == NULL) {
+		/* Must at least contain shadow:snapdir. */
+		return 0;
+	}
+
+	if (priv->config->snapdir[0] == '/' &&
+			p != abs_path) {
+		/* Absolute shadow:snapdir must be at the start. */
+		return 0;
+	}
+
+	snapdirlen = strlen(priv->config->snapdir);
+	if (p[snapdirlen] != '/') {
+		/* shadow:snapdir must end as a separate component. */
+		return 0;
+	}
+
+	if (p > abs_path && p[-1] != '/') {
+		/* shadow:snapdir must start as a separate component. */
+		return 0;
+	}
+
+	p += snapdirlen;
+	p++; /* Move past the / */
+
+	/*
+	 * Need to return up to the next path
+	 * component after the time.
+	 * This will be used as the connectpath.
+	 */
+	q = strchr(p, '/');
+	if (q == NULL) {
+		/*
+		 * No next path component.
+		 * Use entire string.
+		 */
+		connect_path = talloc_strdup(mem_ctx,
+					abs_path);
+	} else {
+		connect_path = talloc_strndup(mem_ctx,
+					abs_path,
+					q - abs_path);
+	}
+	if (connect_path == NULL) {
+		return ENOMEM;
+	}
+
+	/*
+	 * Point p at the same offset in connect_path as
+	 * it is in abs_path.
+	 */
+
+	p = &connect_path[p - abs_path];
+
+	/*
+	 * Now ensure there is a time string at p.
+	 * The SMB-format @GMT-token string is returned
+	 * in snapshot.
+	 */
+
+	if (!shadow_copy2_snapshot_to_gmt(handle,
+				p,
+				snapshot,
+				sizeof(snapshot))) {
+		TALLOC_FREE(connect_path);
+		return 0;
+	}
+
+	if (pconnectpath != NULL) {
+		*pconnectpath = connect_path;
+	}
+
+	*ppath_already_converted = true;
+
+	DBG_DEBUG("path |%s| is already converted. "
+		"connect path = |%s|\n",
+		abs_path,
+		connect_path);
+
+	return 0;
+}
+
 /**
- * Strip a snapshot component from a filename as
- * handed in via the smb layer.
- * Returns the parsed timestamp and the stripped filename.
+ * This function does two things.
+ *
+ * 1). Checks if an incoming filename is already a
+ * snapshot converted pathname.
+ *     If so, it returns the pathname truncated
+ *     at the snapshot point which will be used
+ *     as the connectpath, and then does an early return.
+ *
+ * 2). Checks if an incoming filename contains an
+ * SMB-layer @GMT- style timestamp.
+ *     If so, it strips the timestamp, and returns
+ *     both the timestamp and the stripped path
+ *     (making it cwd-relative).
  */
-static bool shadow_copy2_strip_snapshot(TALLOC_CTX *mem_ctx,
+
+static bool shadow_copy2_strip_snapshot_internal(TALLOC_CTX *mem_ctx,
 					struct vfs_handle_struct *handle,
-					const char *name,
+					const char *orig_name,
 					time_t *ptimestamp,
-					char **pstripped)
+					char **pstripped,
+					char **psnappath)
 {
 	struct tm tm;
-	time_t timestamp;
+	time_t timestamp = 0;
 	const char *p;
 	char *q;
-	char *stripped;
+	char *stripped = NULL;
 	size_t rest_len, dst_len;
 	struct shadow_copy2_private *priv;
-	const char *snapdir;
-	ssize_t snapdirlen;
 	ptrdiff_t len_before_gmt;
+	const char *name = orig_name;
+	char *abs_path = NULL;
+	bool ret = true;
+	bool already_converted = false;
+	int err = 0;
 
 	SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
 				return false);
 
 	DEBUG(10, (__location__ ": enter path '%s'\n", name));
 
+	abs_path = make_path_absolute(mem_ctx, priv, name);
+	if (abs_path == NULL) {
+		ret = false;
+		goto out;
+	}
+	name = abs_path;
+
+	DEBUG(10, (__location__ ": abs path '%s'\n", name));
+
+	err = check_for_converted_path(mem_ctx,
+					handle,
+					priv,
+					abs_path,
+					&already_converted,
+					psnappath);
+	if (err != 0) {
+		/* error in conversion. */
+		ret = false;
+		goto out;
+	}
+
+	if (already_converted) {
+		goto out;
+	}
+
+	/*
+	 * From here we're only looking to strip an
+	 * SMB-layer @GMT- token.
+	 */
+
 	p = strstr_m(name, "@GMT-");
 	if (p == NULL) {
 		DEBUG(11, ("@GMT not found\n"));
-		goto no_snapshot;
+		goto out;
 	}
 	if ((p > name) && (p[-1] != '/')) {
 		/* the GMT-token does not start a path-component */
 		DEBUG(10, ("not at start, p=%p, name=%p, p[-1]=%d\n",
 			   p, name, (int)p[-1]));
-		goto no_snapshot;
+		goto out;
 	}
 
-	/*
-	 * Figure out whether we got an already converted string. One
-	 * case where this happens is in a smb2 create call with the
-	 * mxac create blob set. We do the get_acl call on
-	 * fsp->fsp_name, which is already converted. We are converted
-	 * if we got a file name of the form ".snapshots/@GMT-",
-	 * i.e. ".snapshots/" precedes "p".
-	 */
-
-	snapdir = lp_parm_const_string(SNUM(handle->conn), "shadow", "snapdir",
-				       ".snapshots");
-	snapdirlen = strlen(snapdir);
 	len_before_gmt = p - name;
 
-	if ((len_before_gmt >= (snapdirlen + 1)) && (p[-1] == '/')) {
-		const char *parent_snapdir = p - (snapdirlen+1);
-
-		DEBUG(10, ("parent_snapdir = %s\n", parent_snapdir));
-
-		if (strncmp(parent_snapdir, snapdir, snapdirlen) == 0) {
-			DEBUG(10, ("name=%s is already converted\n", name));
-			goto no_snapshot;
-		}
-	}
 	q = strptime(p, GMT_FORMAT, &tm);
 	if (q == NULL) {
 		DEBUG(10, ("strptime failed\n"));
-		goto no_snapshot;
+		goto out;
 	}
 	tm.tm_isdst = -1;
 	timestamp = timegm(&tm);
 	if (timestamp == (time_t)-1) {
 		DEBUG(10, ("timestamp==-1\n"));
-		goto no_snapshot;
+		goto out;
 	}
 	if (q[0] == '\0') {
 		/*
@@ -496,12 +677,24 @@ static bool shadow_copy2_strip_snapshot(TALLOC_CTX *mem_ctx,
 			stripped = talloc_strndup(mem_ctx, name,
 					len_before_gmt);
 			if (stripped == NULL) {
-				return false;
+				ret = false;
+				goto out;
+			}
+			if (orig_name[0] != '/') {
+				if (make_relative_path(priv->shadow_cwd,
+						stripped) == false) {
+					DEBUG(10, (__location__ ": path '%s' "
+						"doesn't start with cwd '%s\n",
+						stripped, priv->shadow_cwd));
+						ret = false;
+					errno = ENOENT;
+					goto out;
+				}
 			}
 			*pstripped = stripped;
 		}
 		*ptimestamp = timestamp;
-		return true;
+		goto out;
 	}
 	if (q[0] != '/') {
 		/*


-- 
Samba Shared Repository



More information about the samba-cvs mailing list