From: Jeremy Allison Date: Thu, 26 Jan 2017 18:49:51 +0000 (-0800) Subject: s3: VFS: shadow_copy2: Fix module to work with variable current working directory. X-Git-Url: http://git.samba.org/?p=metze%2Fsamba%2Fwip.git;a=commitdiff_plain;h=128d5f27cd42b0c7efcbe3d28fe3eee881e0734b 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 Reviewed-by: Uri Simchoni --- diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c index d6100ac5bb2b..f116c553ac4d 100644 --- a/source3/modules/vfs_shadow_copy2.c +++ b/source3/modules/vfs_shadow_copy2.c @@ -561,10 +561,21 @@ static int check_for_converted_path(TALLOC_CTX *mem_ctx, } /** - * 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_internal(TALLOC_CTX *mem_ctx, struct vfs_handle_struct *handle, const char *orig_name, @@ -579,62 +590,72 @@ static bool shadow_copy2_strip_snapshot_internal(TALLOC_CTX *mem_ctx, 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') { /* @@ -654,12 +675,24 @@ static bool shadow_copy2_strip_snapshot_internal(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] != '/') { /* @@ -667,75 +700,18 @@ static bool shadow_copy2_strip_snapshot_internal(TALLOC_CTX *mem_ctx, * component continues after the gmt-token. */ DEBUG(10, ("q[0] = %d\n", (int)q[0])); - goto no_snapshot; + goto out; } q += 1; rest_len = strlen(q); dst_len = len_before_gmt + rest_len; - if (priv->config->snapdirseverywhere) { - char *insert; - bool have_insert; - insert = shadow_copy2_insert_string(talloc_tos(), handle, - timestamp); - if (insert == NULL) { - errno = ENOMEM; - return false; - } - - DEBUG(10, (__location__ ": snapdirseverywhere mode.\n" - "path '%s'.\n" - "insert string '%s'\n", name, insert)); - - have_insert = (strstr(name, insert+1) != NULL); - DEBUG(10, ("have_insert=%d, name=%s, insert+1=%s\n", - (int)have_insert, name, insert+1)); - if (have_insert) { - DEBUG(10, (__location__ ": insert string '%s' found in " - "path '%s' found in snapdirseverywhere mode " - "==> already converted\n", insert, name)); - TALLOC_FREE(insert); - goto no_snapshot; - } - TALLOC_FREE(insert); - } else { - char *snapshot_path; - char *s; - - snapshot_path = shadow_copy2_snapshot_path(talloc_tos(), - handle, - timestamp); - if (snapshot_path == NULL) { - errno = ENOMEM; - return false; - } - - DEBUG(10, (__location__ " path: '%s'.\n" - "snapshot path: '%s'\n", name, snapshot_path)); - - s = strstr(name, snapshot_path); - if (s == name) { - /* - * this starts with "snapshot_basepath/GMT-Token" - * so it is already a converted absolute - * path. Don't process further. - */ - DEBUG(10, (__location__ ": path '%s' starts with " - "snapshot path '%s' (not in " - "snapdirseverywhere mode) ==> " - "already converted\n", name, snapshot_path)); - talloc_free(snapshot_path); - goto no_snapshot; - } - talloc_free(snapshot_path); - } - if (pstripped != NULL) { stripped = talloc_array(mem_ctx, char, dst_len+1); if (stripped == NULL) { - errno = ENOMEM; - return false; + ret = false; + goto out; } if (p > name) { memcpy(stripped, name, len_before_gmt); @@ -744,13 +720,25 @@ static bool shadow_copy2_strip_snapshot_internal(TALLOC_CTX *mem_ctx, memcpy(stripped + len_before_gmt, q, rest_len); } stripped[dst_len] = '\0'; + 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; -no_snapshot: - *ptimestamp = 0; - return true; + ret = true; + + out: + TALLOC_FREE(abs_path); + return ret; } static bool shadow_copy2_strip_snapshot(TALLOC_CTX *mem_ctx,