diff options
Diffstat (limited to 'source3/modules/vfs_shadow_copy2.c')
-rw-r--r-- | source3/modules/vfs_shadow_copy2.c | 91 |
1 files changed, 91 insertions, 0 deletions
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; |