From dba8593c6f8c11d18ddc01e54f90c50c44070257 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Sun, 22 Nov 2020 13:57:27 +0100 Subject: [PATCH] vfs: Add dirfsp arg to SMB_VFS_READDIR() This allows for optimisations in VFS module: by passing the dirfsp as an additional arg, the function can check fsp->fsp_name->flags which may include eg SMB_FILENAME_POSIX_PATH to trigger POSIX pathname processing. Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- examples/VFS/skel_opaque.c | 4 +++- examples/VFS/skel_transparent.c | 6 ++++-- source3/include/vfs.h | 15 ++++++++++----- source3/include/vfs_macros.h | 8 ++++---- source3/modules/vfs_cap.c | 7 ++++--- source3/modules/vfs_ceph.c | 1 + source3/modules/vfs_default.c | 5 +++-- source3/modules/vfs_dirsort.c | 15 +++++++++++---- source3/modules/vfs_full_audit.c | 6 ++++-- source3/modules/vfs_glusterfs.c | 4 +++- source3/modules/vfs_media_harmony.c | 9 +++++---- source3/modules/vfs_not_implemented.c | 4 +++- source3/modules/vfs_shadow_copy.c | 7 ++++--- source3/modules/vfs_shadow_copy2.c | 2 +- source3/modules/vfs_time_audit.c | 7 ++++--- source3/modules/vfs_unityed_media.c | 5 +++-- source3/modules/vfs_widelinks.c | 10 ++++++---- source3/smbd/dir.c | 2 +- source3/smbd/proto.h | 7 +++++-- source3/smbd/vfs.c | 16 ++++++++++------ 20 files changed, 89 insertions(+), 51 deletions(-) diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c index 2a3a7301bdb..b74f7360dde 100644 --- a/examples/VFS/skel_opaque.c +++ b/examples/VFS/skel_opaque.c @@ -156,7 +156,9 @@ static DIR *skel_fdopendir(vfs_handle_struct *handle, files_struct *fsp, } static struct dirent *skel_readdir(vfs_handle_struct *handle, - DIR *dirp, SMB_STRUCT_STAT *sbuf) + struct files_struct *dirfsp, + DIR *dirp, + SMB_STRUCT_STAT *sbuf) { return NULL; } diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c index a86b3e7cd19..969f0572cf5 100644 --- a/examples/VFS/skel_transparent.c +++ b/examples/VFS/skel_transparent.c @@ -164,9 +164,11 @@ static DIR *skel_fdopendir(vfs_handle_struct *handle, files_struct *fsp, } static struct dirent *skel_readdir(vfs_handle_struct *handle, - DIR *dirp, SMB_STRUCT_STAT *sbuf) + struct files_struct *dirfsp, + DIR *dirp, + SMB_STRUCT_STAT *sbuf) { - return SMB_VFS_NEXT_READDIR(handle, dirp, sbuf); + return SMB_VFS_NEXT_READDIR(handle, dirfsp, dirp, sbuf); } static void skel_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset) diff --git a/source3/include/vfs.h b/source3/include/vfs.h index ce971de8627..3110cbd9fe8 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -337,6 +337,7 @@ * Version 44 - Add 'is_fsa' flag to struct files_struct. * Version 44 - Add 'have_proc_fds' flag to struct connection_struct. * Version 44 - Add 'have_proc_fds' flag to struct files_struct. + * Version 44 - Add dirfsp arg to SMB_VFS_READDIR() */ #define SMB_VFS_INTERFACE_VERSION 44 @@ -919,8 +920,9 @@ struct vfs_fn_pointers { DIR *(*fdopendir_fn)(struct vfs_handle_struct *handle, files_struct *fsp, const char *mask, uint32_t attributes); struct dirent *(*readdir_fn)(struct vfs_handle_struct *handle, - DIR *dirp, - SMB_STRUCT_STAT *sbuf); + struct files_struct *dirfsp, + DIR *dirp, + SMB_STRUCT_STAT *sbuf); void (*seekdir_fn)(struct vfs_handle_struct *handle, DIR *dirp, long offset); long (*telldir_fn)(struct vfs_handle_struct *handle, DIR *dirp); void (*rewind_dir_fn)(struct vfs_handle_struct *handle, DIR *dirp); @@ -1432,8 +1434,9 @@ DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle, const char *mask, uint32_t attributes); struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle, - DIR *dirp, - SMB_STRUCT_STAT *sbuf); + struct files_struct *dirfsp, + DIR *dirp, + SMB_STRUCT_STAT *sbuf); void smb_vfs_call_seekdir(struct vfs_handle_struct *handle, DIR *dirp, long offset); long smb_vfs_call_telldir(struct vfs_handle_struct *handle, @@ -1894,7 +1897,9 @@ NTSTATUS vfs_not_implemented_snap_delete(struct vfs_handle_struct *handle, DIR *vfs_not_implemented_fdopendir(vfs_handle_struct *handle, files_struct *fsp, const char *mask, uint32_t attr); struct dirent *vfs_not_implemented_readdir(vfs_handle_struct *handle, - DIR *dirp, SMB_STRUCT_STAT *sbuf); + struct files_struct *dirfsp, + DIR *dirp, + SMB_STRUCT_STAT *sbuf); void vfs_not_implemented_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset); long vfs_not_implemented_telldir(vfs_handle_struct *handle, DIR *dirp); void vfs_not_implemented_rewind_dir(vfs_handle_struct *handle, DIR *dirp); diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index 70d9ab6784c..f3ffe8566c7 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -111,10 +111,10 @@ #define SMB_VFS_NEXT_FDOPENDIR(handle, fsp, mask, attr) \ smb_vfs_call_fdopendir((handle)->next, (fsp), (mask), (attr)) -#define SMB_VFS_READDIR(conn, dirp, sbuf) \ - smb_vfs_call_readdir((conn)->vfs_handles, (dirp), (sbuf)) -#define SMB_VFS_NEXT_READDIR(handle, dirp, sbuf) \ - smb_vfs_call_readdir((handle)->next, (dirp), (sbuf)) +#define SMB_VFS_READDIR(conn, dirfsp, dirp, sbuf) \ + smb_vfs_call_readdir((conn)->vfs_handles, (dirfsp), (dirp), (sbuf)) +#define SMB_VFS_NEXT_READDIR(handle, dirfsp, dirp, sbuf) \ + smb_vfs_call_readdir((handle)->next, (dirfsp), (dirp), (sbuf)) #define SMB_VFS_SEEKDIR(conn, dirp, offset) \ smb_vfs_call_seekdir((conn)->vfs_handles, (dirp), (offset)) diff --git a/source3/modules/vfs_cap.c b/source3/modules/vfs_cap.c index 5deb7754f02..c40d2a25b76 100644 --- a/source3/modules/vfs_cap.c +++ b/source3/modules/vfs_cap.c @@ -85,8 +85,9 @@ static int cap_get_quota(vfs_handle_struct *handle, } static struct dirent *cap_readdir(vfs_handle_struct *handle, - DIR *dirp, - SMB_STRUCT_STAT *sbuf) + struct files_struct *dirfsp, + DIR *dirp, + SMB_STRUCT_STAT *sbuf) { struct dirent *result; struct dirent *newdirent; @@ -94,7 +95,7 @@ static struct dirent *cap_readdir(vfs_handle_struct *handle, size_t newnamelen; DEBUG(3,("cap: cap_readdir\n")); - result = SMB_VFS_NEXT_READDIR(handle, dirp, NULL); + result = SMB_VFS_NEXT_READDIR(handle, dirfsp, dirp, NULL); if (!result) { return NULL; } diff --git a/source3/modules/vfs_ceph.c b/source3/modules/vfs_ceph.c index 502b72359b3..4c380c3ad20 100644 --- a/source3/modules/vfs_ceph.c +++ b/source3/modules/vfs_ceph.c @@ -321,6 +321,7 @@ static DIR *cephwrap_fdopendir(struct vfs_handle_struct *handle, } static struct dirent *cephwrap_readdir(struct vfs_handle_struct *handle, + struct files_struct *dirfsp, DIR *dirp, SMB_STRUCT_STAT *sbuf) { diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 21075d725a9..929c4ce7d0e 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -571,8 +571,9 @@ static DIR *vfswrap_fdopendir(vfs_handle_struct *handle, static struct dirent *vfswrap_readdir(vfs_handle_struct *handle, - DIR *dirp, - SMB_STRUCT_STAT *sbuf) + struct files_struct *dirfsp, + DIR *dirp, + SMB_STRUCT_STAT *sbuf) { struct dirent *result; diff --git a/source3/modules/vfs_dirsort.c b/source3/modules/vfs_dirsort.c index 3b3d609563d..d9cfcadacf8 100644 --- a/source3/modules/vfs_dirsort.c +++ b/source3/modules/vfs_dirsort.c @@ -79,7 +79,10 @@ static bool open_and_sort_dir(vfs_handle_struct *handle, return false; } - dp = SMB_VFS_NEXT_READDIR(handle, data->source_directory, NULL); + dp = SMB_VFS_NEXT_READDIR(handle, + data->fsp, + data->source_directory, + NULL); if (dp == NULL) { return false; } @@ -120,7 +123,10 @@ static bool open_and_sort_dir(vfs_handle_struct *handle, data->directory_list[total_count] = *dp; total_count++; - dp = SMB_VFS_NEXT_READDIR(handle, data->source_directory, NULL); + dp = SMB_VFS_NEXT_READDIR(handle, + data->fsp, + data->source_directory, + NULL); } while (dp != NULL); data->number_of_entries = total_count; @@ -178,8 +184,9 @@ static DIR *dirsort_fdopendir(vfs_handle_struct *handle, } static struct dirent *dirsort_readdir(vfs_handle_struct *handle, - DIR *dirp, - SMB_STRUCT_STAT *sbuf) + struct files_struct *dirfsp, + DIR *dirp, + SMB_STRUCT_STAT *sbuf) { struct dirsort_privates *data = NULL; struct timespec current_mtime; diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index f1823e3b22e..5a73562a09a 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -1004,11 +1004,13 @@ static DIR *smb_full_audit_fdopendir(vfs_handle_struct *handle, } static struct dirent *smb_full_audit_readdir(vfs_handle_struct *handle, - DIR *dirp, SMB_STRUCT_STAT *sbuf) + struct files_struct *dirfsp, + DIR *dirp, + SMB_STRUCT_STAT *sbuf) { struct dirent *result; - result = SMB_VFS_NEXT_READDIR(handle, dirp, sbuf); + result = SMB_VFS_NEXT_READDIR(handle, dirfsp, dirp, sbuf); /* This operation has no reasonable error condition * (End of dir is also failure), so always succeed. diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c index e4c12931938..b5896feefbd 100644 --- a/source3/modules/vfs_glusterfs.c +++ b/source3/modules/vfs_glusterfs.c @@ -650,7 +650,9 @@ static int vfs_gluster_closedir(struct vfs_handle_struct *handle, DIR *dirp) } static struct dirent *vfs_gluster_readdir(struct vfs_handle_struct *handle, - DIR *dirp, SMB_STRUCT_STAT *sbuf) + struct files_struct *dirfsp, + DIR *dirp, + SMB_STRUCT_STAT *sbuf) { static char direntbuf[512]; int ret; diff --git a/source3/modules/vfs_media_harmony.c b/source3/modules/vfs_media_harmony.c index 12e7ad61806..79fc595339e 100644 --- a/source3/modules/vfs_media_harmony.c +++ b/source3/modules/vfs_media_harmony.c @@ -818,8 +818,9 @@ err: * Failure: set errno, return NULL */ static struct dirent *mh_readdir(vfs_handle_struct *handle, - DIR *dirp, - SMB_STRUCT_STAT *sbuf) + struct files_struct *dirfsp, + DIR *dirp, + SMB_STRUCT_STAT *sbuf) { mh_dirinfo_struct* dirInfo = (mh_dirinfo_struct*)dirp; struct dirent *d = NULL; @@ -842,7 +843,7 @@ static struct dirent *mh_readdir(vfs_handle_struct *handle, if (! dirInfo->isInMediaFiles) { - d = SMB_VFS_NEXT_READDIR(handle, dirInfo->dirstream, sbuf); + d = SMB_VFS_NEXT_READDIR(handle, dirfsp, dirInfo->dirstream, sbuf); goto out; } @@ -852,7 +853,7 @@ static struct dirent *mh_readdir(vfs_handle_struct *handle, bool isAppleDouble; skip = False; - d = SMB_VFS_NEXT_READDIR(handle, dirInfo->dirstream, sbuf); + d = SMB_VFS_NEXT_READDIR(handle, dirfsp, dirInfo->dirstream, sbuf); if (d == NULL) { diff --git a/source3/modules/vfs_not_implemented.c b/source3/modules/vfs_not_implemented.c index 59aaddb163a..d889dc417b5 100644 --- a/source3/modules/vfs_not_implemented.c +++ b/source3/modules/vfs_not_implemented.c @@ -151,7 +151,9 @@ DIR *vfs_not_implemented_fdopendir(vfs_handle_struct *handle, files_struct *fsp, } struct dirent *vfs_not_implemented_readdir(vfs_handle_struct *handle, - DIR *dirp, SMB_STRUCT_STAT *sbuf) + struct files_struct *dirfsp, + DIR *dirp, + SMB_STRUCT_STAT *sbuf) { errno = ENOSYS; return NULL; diff --git a/source3/modules/vfs_shadow_copy.c b/source3/modules/vfs_shadow_copy.c index 79f20979127..37c4657e79b 100644 --- a/source3/modules/vfs_shadow_copy.c +++ b/source3/modules/vfs_shadow_copy.c @@ -98,7 +98,7 @@ static DIR *shadow_copy_fdopendir(vfs_handle_struct *handle, files_struct *fsp, while (True) { struct dirent *d; - d = SMB_VFS_NEXT_READDIR(handle, p, NULL); + d = SMB_VFS_NEXT_READDIR(handle, fsp, p, NULL); if (d == NULL) { break; } @@ -126,8 +126,9 @@ static DIR *shadow_copy_fdopendir(vfs_handle_struct *handle, files_struct *fsp, } static struct dirent *shadow_copy_readdir(vfs_handle_struct *handle, - DIR *_dirp, - SMB_STRUCT_STAT *sbuf) + struct files_struct *dirfsp, + DIR *_dirp, + SMB_STRUCT_STAT *sbuf) { shadow_copy_Dir *dirp = (shadow_copy_Dir *)_dirp; diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c index 54577ca887d..6e4ed606309 100644 --- a/source3/modules/vfs_shadow_copy2.c +++ b/source3/modules/vfs_shadow_copy2.c @@ -2052,7 +2052,7 @@ static int shadow_copy2_get_shadow_copy_data( time(&(priv->snaps->fetch_time)); } - while ((d = SMB_VFS_NEXT_READDIR(handle, p, NULL))) { + while ((d = SMB_VFS_NEXT_READDIR(handle, dirfsp, p, NULL))) { char snapshot[GMT_NAME_LEN+1]; SHADOW_COPY_LABEL *tlabels; diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c index 7ff0b24cced..e18733b55c1 100644 --- a/source3/modules/vfs_time_audit.c +++ b/source3/modules/vfs_time_audit.c @@ -467,15 +467,16 @@ static DIR *smb_time_audit_fdopendir(vfs_handle_struct *handle, } static struct dirent *smb_time_audit_readdir(vfs_handle_struct *handle, - DIR *dirp, - SMB_STRUCT_STAT *sbuf) + struct files_struct *dirfsp, + DIR *dirp, + SMB_STRUCT_STAT *sbuf) { struct dirent *result; struct timespec ts1,ts2; double timediff; clock_gettime_mono(&ts1); - result = SMB_VFS_NEXT_READDIR(handle, dirp, sbuf); + result = SMB_VFS_NEXT_READDIR(handle, dirfsp, dirp, sbuf); clock_gettime_mono(&ts2); timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9; diff --git a/source3/modules/vfs_unityed_media.c b/source3/modules/vfs_unityed_media.c index 014420fd961..72c2e488dd6 100644 --- a/source3/modules/vfs_unityed_media.c +++ b/source3/modules/vfs_unityed_media.c @@ -614,6 +614,7 @@ err: * Failure: set errno, return NULL */ static struct dirent *um_readdir(vfs_handle_struct *handle, + struct files_struct *dirfsp, DIR *dirp, SMB_STRUCT_STAT *sbuf) { @@ -631,7 +632,7 @@ static struct dirent *um_readdir(vfs_handle_struct *handle, dirInfo->clientSubDirname)); if (!dirInfo->isInMediaFiles) { - return SMB_VFS_NEXT_READDIR(handle, dirInfo->dirstream, sbuf); + return SMB_VFS_NEXT_READDIR(handle, dirfsp, dirInfo->dirstream, sbuf); } do { @@ -642,7 +643,7 @@ static struct dirent *um_readdir(vfs_handle_struct *handle, uintmax_t number; skip = false; - d = SMB_VFS_NEXT_READDIR(handle, dirInfo->dirstream, sbuf); + d = SMB_VFS_NEXT_READDIR(handle, dirfsp, dirInfo->dirstream, sbuf); if (d == NULL) { break; diff --git a/source3/modules/vfs_widelinks.c b/source3/modules/vfs_widelinks.c index ea3b519eb85..1cbb0bf0ad0 100644 --- a/source3/modules/vfs_widelinks.c +++ b/source3/modules/vfs_widelinks.c @@ -372,8 +372,9 @@ static int widelinks_openat(vfs_handle_struct *handle, } static struct dirent *widelinks_readdir(vfs_handle_struct *handle, - DIR *dirp, - SMB_STRUCT_STAT *sbuf) + struct files_struct *dirfsp, + DIR *dirp, + SMB_STRUCT_STAT *sbuf) { struct widelinks_config *config = NULL; struct dirent *result; @@ -384,8 +385,9 @@ static struct dirent *widelinks_readdir(vfs_handle_struct *handle, return NULL); result = SMB_VFS_NEXT_READDIR(handle, - dirp, - sbuf); + dirfsp, + dirp, + sbuf); if (!config->active) { /* Module not active. */ diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 6f70e192dae..181a59aa61e 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1490,7 +1490,7 @@ const char *ReadDirName(struct smb_Dir *dir_hnd, long *poffset, /* A real offset, seek to it. */ SeekDir(dir_hnd, *poffset); - while ((n = vfs_readdirname(conn, dir_hnd->dir, sbuf, &talloced))) { + while ((n = vfs_readdirname(conn, dir_hnd->fsp, dir_hnd->dir, sbuf, &talloced))) { /* Ignore . and .. - we've already returned them. */ if (*n == '.') { if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) { diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index 6192e22fda6..ea81f7a7dd8 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -1287,8 +1287,11 @@ int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len); int vfs_fill_sparse(files_struct *fsp, off_t len); int vfs_set_blocking(files_struct *fsp, bool set); off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n); -const char *vfs_readdirname(connection_struct *conn, void *p, - SMB_STRUCT_STAT *sbuf, char **talloced); +const char *vfs_readdirname(connection_struct *conn, + struct files_struct *dirfsp, + void *p, + SMB_STRUCT_STAT *sbuf, + char **talloced); int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname); struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 45e1b9989bc..fd6b15f206c 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -842,8 +842,11 @@ off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n) A vfs_readdir wrapper which just returns the file name. ********************************************************************/ -const char *vfs_readdirname(connection_struct *conn, void *p, - SMB_STRUCT_STAT *sbuf, char **talloced) +const char *vfs_readdirname(connection_struct *conn, + struct files_struct *dirfsp, + void *p, + SMB_STRUCT_STAT *sbuf, + char **talloced) { struct dirent *ptr= NULL; const char *dname; @@ -853,7 +856,7 @@ const char *vfs_readdirname(connection_struct *conn, void *p, if (!p) return(NULL); - ptr = SMB_VFS_READDIR(conn, (DIR *)p, sbuf); + ptr = SMB_VFS_READDIR(conn, dirfsp, (DIR *)p, sbuf); if (!ptr) return(NULL); @@ -1759,11 +1762,12 @@ DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle, } struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle, - DIR *dirp, - SMB_STRUCT_STAT *sbuf) + struct files_struct *dirfsp, + DIR *dirp, + SMB_STRUCT_STAT *sbuf) { VFS_FIND(readdir); - return handle->fns->readdir_fn(handle, dirp, sbuf); + return handle->fns->readdir_fn(handle, dirfsp, dirp, sbuf); } void smb_vfs_call_seekdir(struct vfs_handle_struct *handle, -- 2.34.1