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@samba.org>
Reviewed-by: Michael Adam <obnox@samba.org>
* 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.
* 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;
{
struct smb_filename converted_fname;
char *result = NULL;
size_t pathlen;
char *insert = NULL;
char *converted = NULL;
size_t pathlen;
char *insert = NULL;
char *converted = NULL;
+ size_t insertlen, connectlen = 0;
int i, saved_errno;
size_t min_offset;
struct shadow_copy2_config *config;
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);
SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config,
return NULL);
DEBUG(10, ("Found %s\n", converted));
result = converted;
converted = NULL;
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;
goto fail;
} else {
errno = ENOENT;
/* never reached ... */
}
/* never reached ... */
}
+ connectlen = strlen(handle->conn->connectpath);
if (name[0] == 0) {
path = talloc_strdup(mem_ctx, handle->conn->connectpath);
} else {
if (name[0] == 0) {
path = talloc_strdup(mem_ctx, handle->conn->connectpath);
} else {
+ if (offset >= connectlen) {
+ in_share_offset = offset;
+ }
+
memcpy(converted+offset, insert, insertlen);
offset += insertlen;
memcpy(converted+offset, insert, insertlen);
offset += insertlen;
ret, ret == 0 ? "ok" : strerror(errno)));
if (ret == 0) {
/* success */
ret, ret == 0 ? "ok" : strerror(errno)));
if (ret == 0) {
/* success */
+ if (snaproot_len != NULL) {
+ *snaproot_len = in_share_offset + insertlen;
+ }
break;
}
if (errno == ENOTDIR) {
break;
}
if (errno == ENOTDIR) {
+/**
+ * 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
/*
modify a sbuf return to ensure that inodes in the shadow directory
are different from those in the main directory