summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRalph Boehme <slow@samba.org>2022-03-24 16:25:22 +0100
committerJule Anger <janger@samba.org>2022-04-11 07:49:13 +0000
commitbf221a9b207dcd085171fbe8458e33a96a1d0869 (patch)
tree25672076feea565afea6560e0884d0e57fad4224
parentd6b48ec3795bf4bb6b7665be6ce9009932f59db6 (diff)
downloadsamba-bf221a9b207dcd085171fbe8458e33a96a1d0869.tar.gz
vfs_shadow_copy2: implement readdir()
RN: shadow_copy2 fails listing snapshotted dirs with shadow:fixinodes BUG: https://bugzilla.samba.org/show_bug.cgi?id=15035 Signed-off-by: Ralph Boehme <slow@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org> Autobuild-User(master): Jeremy Allison <jra@samba.org> Autobuild-Date(master): Thu Mar 31 18:47:42 UTC 2022 on sn-devel-184 (cherry picked from commit 9fa67ba8eeb6249d4b91b894e80eb1985c845314)
-rw-r--r--selftest/knownfail.d/samba3.blackbox.shadow_copy_torture1
-rw-r--r--source3/modules/vfs_shadow_copy2.c91
2 files changed, 91 insertions, 1 deletions
diff --git a/selftest/knownfail.d/samba3.blackbox.shadow_copy_torture b/selftest/knownfail.d/samba3.blackbox.shadow_copy_torture
deleted file mode 100644
index 36f2acb7f3b..00000000000
--- a/selftest/knownfail.d/samba3.blackbox.shadow_copy_torture
+++ /dev/null
@@ -1 +0,0 @@
-^samba3.blackbox.shadow_copy_torture.fix inodes when listing directory\(fileserver\)
diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c
index 769f8c7da87..05b12d4924c 100644
--- a/source3/modules/vfs_shadow_copy2.c
+++ b/source3/modules/vfs_shadow_copy2.c
@@ -3234,6 +3234,96 @@ static int shadow_copy2_connect(struct vfs_handle_struct *handle,
return 0;
}
+static struct dirent *shadow_copy2_readdir(vfs_handle_struct *handle,
+ struct files_struct *dirfsp,
+ DIR *dirp,
+ SMB_STRUCT_STAT *sbuf)
+{
+ struct shadow_copy2_private *priv = NULL;
+ struct dirent *ent = NULL;
+ struct smb_filename atname;
+ struct smb_filename *full_fname = NULL;
+ time_t timestamp = 0;
+ char *stripped = NULL;
+ char *conv = NULL;
+ char *abspath = NULL;
+ bool converted = false;
+
+ SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
+ return NULL);
+
+ ent = SMB_VFS_NEXT_READDIR(handle, dirfsp, dirp, sbuf);
+ if (ent == NULL) {
+ return NULL;
+ }
+ if (sbuf == NULL) {
+ return ent;
+ }
+ if (ISDOT(dirfsp->fsp_name->base_name) && ISDOTDOT(ent->d_name)) {
+ return ent;
+ }
+
+ atname = (struct smb_filename) {
+ .base_name = ent->d_name,
+ .twrp = dirfsp->fsp_name->twrp,
+ .flags = dirfsp->fsp_name->flags,
+ };
+
+ full_fname = full_path_from_dirfsp_atname(talloc_tos(),
+ dirfsp,
+ &atname);
+ if (full_fname == NULL) {
+ return NULL;
+ }
+
+ if (!shadow_copy2_strip_snapshot_converted(talloc_tos(),
+ handle,
+ full_fname,
+ &timestamp,
+ &stripped,
+ &converted)) {
+ TALLOC_FREE(full_fname);
+ return NULL;
+ }
+
+ if (timestamp == 0 && !converted) {
+ /* Not a snapshot path, no need for convert_sbuf() */
+ TALLOC_FREE(stripped);
+ TALLOC_FREE(full_fname);
+ return ent;
+ }
+
+ if (timestamp == 0) {
+ abspath = make_path_absolute(talloc_tos(),
+ priv,
+ full_fname->base_name);
+ TALLOC_FREE(full_fname);
+ if (abspath == NULL) {
+ return NULL;
+ }
+ } else {
+ conv = shadow_copy2_convert(talloc_tos(),
+ handle,
+ stripped,
+ timestamp);
+ TALLOC_FREE(stripped);
+ if (conv == NULL) {
+ return NULL;
+ }
+
+ abspath = make_path_absolute(talloc_tos(), priv, conv);
+ TALLOC_FREE(conv);
+ if (abspath == NULL) {
+ return NULL;
+ }
+ }
+
+ convert_sbuf(handle, abspath, sbuf);
+
+ TALLOC_FREE(abspath);
+ return ent;
+}
+
static struct vfs_fn_pointers vfs_shadow_copy2_fns = {
.connect_fn = shadow_copy2_connect,
.disk_free_fn = shadow_copy2_disk_free,
@@ -3264,6 +3354,7 @@ static struct vfs_fn_pointers vfs_shadow_copy2_fns = {
.pwrite_recv_fn = shadow_copy2_pwrite_recv,
.connectpath_fn = shadow_copy2_connectpath,
.parent_pathname_fn = shadow_copy2_parent_pathname,
+ .readdir_fn = shadow_copy2_readdir,
};
static_decl_vfs;