diff options
author | Ralph Boehme <slow@samba.org> | 2022-03-24 16:25:22 +0100 |
---|---|---|
committer | Jule Anger <janger@samba.org> | 2022-04-11 08:32:10 +0000 |
commit | a275f517628e86c4a9a1bcb1bb86921592f91b17 (patch) | |
tree | 7c96f4f8fb963747dd96225330d93bd05206ab7f | |
parent | fbcbe7b96c52e1d6e6c030d7fc311d03b22ec3e9 (diff) | |
download | samba-a275f517628e86c4a9a1bcb1bb86921592f91b17.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_torture | 1 | ||||
-rw-r--r-- | source3/modules/vfs_shadow_copy2.c | 91 |
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, + ×tamp, + &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; |