vfs_shadow_copy2: fix case where snapshots are outside the share
[obnox/samba/samba-obnox.git] / 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);