vfs_shadow_copy2: fix case where snapshots are outside the share
authorUri Simchoni <uri@samba.org>
Mon, 2 Nov 2015 07:08:53 +0000 (09:08 +0200)
committerMichael Adam <obnox@samba.org>
Wed, 13 Jan 2016 13:03:15 +0000 (14:03 +0100)
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@samba.org>
Reviewed-by: Michael Adam <obnox@samba.org>
source3/modules/vfs_shadow_copy2.c

index 19d71ecb0279980ba6edfada825e7d54a4125e9b..018ec88006fe280346071ce7d6fe56597b746fd9 100644 (file)
@@ -1134,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,
@@ -1152,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;
@@ -1808,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,
+                                        &timestamp, &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)
@@ -2110,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);