From a8760778788330c6207485d1aa4e498d48d32778 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 9 Nov 2004 22:49:28 +0000 Subject: r3642: Extend vfs to add seekdir/telldir/rewinddir. Yes I know I have to fix the modules too... First step in fixing out large directories problem. Jeremy. --- source/include/smbprofile.h | 8 +++++- source/include/trans2.h | 7 +++++ source/include/vfs.h | 16 ++++++++--- source/include/vfs_macros.h | 10 +++++++ source/lib/system.c | 65 +++++++++++++++++++++++++++++++++++++++++++++ source/smbd/trans2.c | 16 ++++++----- source/smbd/vfs-wrap.c | 31 ++++++++++++++++++--- source/smbd/vfs.c | 7 +++-- 8 files changed, 143 insertions(+), 17 deletions(-) diff --git a/source/include/smbprofile.h b/source/include/smbprofile.h index e494faf7da6..ed6fce9a6d6 100644 --- a/source/include/smbprofile.h +++ b/source/include/smbprofile.h @@ -34,7 +34,7 @@ enum flush_reason_enum { SEEK_FLUSH, READ_FLUSH, WRITE_FLUSH, READRAW_FLUSH, #define PROF_SHMEM_KEY ((key_t)0x07021999) #define PROF_SHM_MAGIC 0x6349985 -#define PROF_SHM_VERSION 9 +#define PROF_SHM_VERSION 10 /* time values in the following structure are in microseconds */ @@ -47,6 +47,12 @@ struct profile_stats { unsigned syscall_opendir_time; unsigned syscall_readdir_count; unsigned syscall_readdir_time; + unsigned syscall_seekdir_count; + unsigned syscall_seekdir_time; + unsigned syscall_telldir_count; + unsigned syscall_telldir_time; + unsigned syscall_rewinddir_count; + unsigned syscall_rewinddir_time; unsigned syscall_mkdir_count; unsigned syscall_mkdir_time; unsigned syscall_rmdir_count; diff --git a/source/include/trans2.h b/source/include/trans2.h index 3106cd092ab..37b3cb24b14 100644 --- a/source/include/trans2.h +++ b/source/include/trans2.h @@ -329,6 +329,13 @@ Byte offset Type name description #define SMB_FS_FULL_SIZE_INFORMATION 1007 #define SMB_FS_OBJECTID_INFORMATION 1008 +/* flags on trans2 findfirst/findnext that control search */ +#define FLAG_TRANS2_FIND_CLOSE 0x1 +#define FLAG_TRANS2_FIND_CLOSE_IF_END 0x2 +#define FLAG_TRANS2_FIND_REQUIRE_RESUME 0x4 +#define FLAG_TRANS2_FIND_CONTINUE 0x8 +#define FLAG_TRANS2_FIND_BACKUP_INTENT 0x10 + /* UNIX CIFS Extensions - created by HP */ /* * UNIX CIFS Extensions have the range 0x200 - 0x2FF reserved. diff --git a/source/include/vfs.h b/source/include/vfs.h index db766b985d9..babf18ec81f 100644 --- a/source/include/vfs.h +++ b/source/include/vfs.h @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. VFS structures and parameters - Copyright (C) Jeremy Allison 1999-2003 + Copyright (C) Jeremy Allison 1999-2004 Copyright (C) Tim Potter 1999 Copyright (C) Alexander Bokovoy 2002 Copyright (C) Stefan (metze) Metzmacher 2003 @@ -55,7 +55,8 @@ /* Changed to version 8 includes EA calls. JRA. */ /* Changed to version 9 to include the get_shadow_data call. --metze */ /* Changed to version 10 to include pread/pwrite calls. */ -#define SMB_VFS_INTERFACE_VERSION 10 +/* Changed to version 11 to include seekdir/telldir/rewinddir calls. JRA */ +#define SMB_VFS_INTERFACE_VERSION 11 /* to bug old modules witch are trying to compile with the old functions */ @@ -102,6 +103,9 @@ typedef enum _vfs_op_type { SMB_VFS_OP_OPENDIR, SMB_VFS_OP_READDIR, + SMB_VFS_OP_SEEKDIR, + SMB_VFS_OP_TELLDIR, + SMB_VFS_OP_REWINDDIR, SMB_VFS_OP_MKDIR, SMB_VFS_OP_RMDIR, SMB_VFS_OP_CLOSEDIR, @@ -209,7 +213,10 @@ struct vfs_ops { /* Directory operations */ DIR *(*opendir)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *fname); - struct dirent *(*readdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, DIR *dirp); + SMB_STRUCT_DIRENT *(*readdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, DIR *dirp); + void (*seekdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, DIR *dirp, long offset); + long (*telldir)(struct vfs_handle_struct *handle, struct connection_struct *conn, DIR *dirp); + void (*rewinddir)(struct vfs_handle_struct *handle, struct connection_struct *conn, DIR *dirp); int (*mkdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, mode_t mode); int (*rmdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path); int (*closedir)(struct vfs_handle_struct *handle, struct connection_struct *conn, DIR *dir); @@ -310,6 +317,9 @@ struct vfs_ops { struct vfs_handle_struct *opendir; struct vfs_handle_struct *readdir; + struct vfs_handle_struct *seekdir; + struct vfs_handle_struct *telldir; + struct vfs_handle_struct *rewinddir; struct vfs_handle_struct *mkdir; struct vfs_handle_struct *rmdir; struct vfs_handle_struct *closedir; diff --git a/source/include/vfs_macros.h b/source/include/vfs_macros.h index 1ec1c5a7789..a149db53b1e 100644 --- a/source/include/vfs_macros.h +++ b/source/include/vfs_macros.h @@ -38,6 +38,9 @@ /* Directory operations */ #define SMB_VFS_OPENDIR(conn, fname) ((conn)->vfs.ops.opendir((conn)->vfs.handles.opendir, (conn), (fname))) #define SMB_VFS_READDIR(conn, dirp) ((conn)->vfs.ops.readdir((conn)->vfs.handles.readdir, (conn), (dirp))) +#define SMB_VFS_SEEKDIR(conn, dirp, offset) ((conn)->vfs.ops.seekdir((conn)->vfs.handles.seekdir, (conn), (dirp), (offset))) +#define SMB_VFS_TELLDIR(conn, dirp) ((conn)->vfs.ops.telldir((conn)->vfs.handles.telldir, (conn), (dirp))) +#define SMB_VFS_REWINDDIR(conn, dirp) ((conn)->vfs.ops.rewinddir((conn)->vfs.handles.rewinddir, (conn), (dirp))) #define SMB_VFS_MKDIR(conn, path, mode) ((conn)->vfs.ops.mkdir((conn)->vfs.handles.mkdir,(conn), (path), (mode))) #define SMB_VFS_RMDIR(conn, path) ((conn)->vfs.ops.rmdir((conn)->vfs.handles.rmdir, (conn), (path))) #define SMB_VFS_CLOSEDIR(conn, dir) ((conn)->vfs.ops.closedir((conn)->vfs.handles.closedir, (conn), dir)) @@ -136,6 +139,9 @@ /* Directory operations */ #define SMB_VFS_OPAQUE_OPENDIR(conn, fname) ((conn)->vfs_opaque.ops.opendir((conn)->vfs_opaque.handles.opendir, (conn), (fname))) #define SMB_VFS_OPAQUE_READDIR(conn, dirp) ((conn)->vfs_opaque.ops.readdir((conn)->vfs_opaque.handles.readdir, (conn), (dirp))) +#define SMB_VFS_OPAQUE_SEEKDIR(conn, dirp, offset) ((conn)->vfs_opaque.ops.seekdir((conn)->vfs_opaque.handles.seekdir, (conn), (dirp), (offset))) +#define SMB_VFS_OPAQUE_TELLDIR(conn, dirp) ((conn)->vfs_opaque.ops.telldir((conn)->vfs_opaque.handles.telldir, (conn), (dirp))) +#define SMB_VFS_OPAQUE_REWINDDIR(conn, dirp) ((conn)->vfs_opaque.ops.rewinddir((conn)->vfs_opaque.handles.rewinddir, (conn), (dirp))) #define SMB_VFS_OPAQUE_MKDIR(conn, path, mode) ((conn)->vfs_opaque.ops.mkdir((conn)->vfs_opaque.handles.mkdir,(conn), (path), (mode))) #define SMB_VFS_OPAQUE_RMDIR(conn, path) ((conn)->vfs_opaque.ops.rmdir((conn)->vfs_opaque.handles.rmdir, (conn), (path))) #define SMB_VFS_OPAQUE_CLOSEDIR(conn, dir) ((conn)->vfs_opaque.ops.closedir((conn)->vfs_opaque.handles.closedir, (conn), dir)) @@ -234,6 +240,10 @@ /* Directory operations */ #define SMB_VFS_NEXT_OPENDIR(handle, conn, fname) ((handle)->vfs_next.ops.opendir((handle)->vfs_next.handles.opendir, (conn), (fname))) #define SMB_VFS_NEXT_READDIR(handle, conn, dirp) ((handle)->vfs_next.ops.readdir((handle)->vfs_next.handles.readdir, (conn), (dirp))) +#define SMB_VFS_NEXT_SEEKDIR(handle, conn, dirp) ((handle)->vfs_next.ops.seekdir((handle)->vfs_next.handles.seekdir, (conn), (dirp), (offset))) +#define SMB_VFS_NEXT_TELLDIR(handle, conn, dirp) ((handle)->vfs_next.ops.telldir((handle)->vfs_next.handles.telldir, (conn), (dirp))) +#define SMB_VFS_NEXT_REWINDDIR(handle, conn, dirp) ((handle)->vfs_next.ops.rewinddir((handle)->vfs_next.handles.rewinddir, (conn), (dirp))) +#define SMB_VFS_NEXT_DIR(handle, conn, dirp) ((handle)->vfs_next.ops.readdir((handle)->vfs_next.handles.readdir, (conn), (dirp))) #define SMB_VFS_NEXT_MKDIR(handle, conn, path, mode) ((handle)->vfs_next.ops.mkdir((handle)->vfs_next.handles.mkdir,(conn), (path), (mode))) #define SMB_VFS_NEXT_RMDIR(handle, conn, path) ((handle)->vfs_next.ops.rmdir((handle)->vfs_next.handles.rmdir, (conn), (path))) #define SMB_VFS_NEXT_CLOSEDIR(handle, conn, dir) ((handle)->vfs_next.ops.closedir((handle)->vfs_next.handles.closedir, (conn), dir)) diff --git a/source/lib/system.c b/source/lib/system.c index b27ac5c00ad..f33d1ae7d57 100644 --- a/source/lib/system.c +++ b/source/lib/system.c @@ -361,6 +361,19 @@ FILE *sys_fopen(const char *path, const char *type) #endif } +/******************************************************************* + An opendir wrapper that will deal with 64 bit filesizes. +********************************************************************/ + +DIR *sys_opendir(const char *name) +{ +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64) + return opendir64(name); +#else + return opendir(name); +#endif +} + /******************************************************************* A readdir wrapper that will deal with 64 bit filesizes. ********************************************************************/ @@ -374,6 +387,58 @@ SMB_STRUCT_DIRENT *sys_readdir(DIR *dirp) #endif } +/******************************************************************* + A seekdir wrapper that will deal with 64 bit filesizes. +********************************************************************/ + +void sys_seekdir(DIR *dirp, long offset) +{ +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64) + seekdir64(dirp, offset); +#else + seekdir(dirp, offset); +#endif +} + +/******************************************************************* + A telldir wrapper that will deal with 64 bit filesizes. +********************************************************************/ + +long sys_telldir(DIR *dirp) +{ +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64) + return (long)telldir64(dirp); +#else + return (long)telldir(dirp); +#endif +} + +/******************************************************************* + A rewinddir wrapper that will deal with 64 bit filesizes. +********************************************************************/ + +void sys_rewinddir(DIR *dirp) +{ +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64) + rewinddir64(dirp); +#else + rewinddir(dirp); +#endif +} + +/******************************************************************* + A close wrapper that will deal with 64 bit filesizes. +********************************************************************/ + +int sys_closedir(DIR *dirp) +{ +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64) + return closedir64(dirp); +#else + return closedir(dirp); +#endif +} + /******************************************************************* An mknod() wrapper that will deal with 64 bit filesizes. ********************************************************************/ diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c index ac282ed95fc..4c0d5731eb8 100644 --- a/source/smbd/trans2.c +++ b/source/smbd/trans2.c @@ -1329,9 +1329,10 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb char *pdata = *ppdata; int dirtype = SVAL(params,0); int maxentries = SVAL(params,2); - BOOL close_after_first = BITSETW(params+4,0); - BOOL close_if_end = BITSETW(params+4,1); - BOOL requires_resume_key = BITSETW(params+4,2); + uint16 findfirst_flags = SVAL(params,4); + BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE); + BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END); + BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME); int info_level = SVAL(params,6); pstring directory; pstring mask; @@ -1555,10 +1556,11 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu int maxentries = SVAL(params,2); uint16 info_level = SVAL(params,4); uint32 resume_key = IVAL(params,6); - BOOL close_after_request = BITSETW(params+10,0); - BOOL close_if_end = BITSETW(params+10,1); - BOOL requires_resume_key = BITSETW(params+10,2); - BOOL continue_bit = BITSETW(params+10,3); + uint16 findnext_flags = SVAL(params,10); + BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE); + BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END); + BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME); + BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE); pstring resume_name; pstring mask; pstring directory; diff --git a/source/smbd/vfs-wrap.c b/source/smbd/vfs-wrap.c index 5393dfc7556..1444d0e875a 100644 --- a/source/smbd/vfs-wrap.c +++ b/source/smbd/vfs-wrap.c @@ -93,21 +93,44 @@ DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const c DIR *result; START_PROFILE(syscall_opendir); - result = opendir(fname); + result = sys_opendir(fname); END_PROFILE(syscall_opendir); return result; } -struct dirent *vfswrap_readdir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) +SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) { struct dirent *result; START_PROFILE(syscall_readdir); - result = readdir(dirp); + result = sys_readdir(dirp); END_PROFILE(syscall_readdir); return result; } +void vfswrap_seekdir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp, long offset) +{ + START_PROFILE(syscall_seekdir); + sys_seekdir(dirp, offset); + END_PROFILE(syscall_seekdir); +} + +long vfswrap_telldir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) +{ + long result; + START_PROFILE(syscall_telldir); + result = sys_telldir(dirp); + END_PROFILE(syscall_telldir); + return result; +} + +void vfswrap_rewinddir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) +{ + START_PROFILE(syscall_rewinddir); + sys_rewinddir(dirp); + END_PROFILE(syscall_rewinddir); +} + int vfswrap_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) { int result; @@ -152,7 +175,7 @@ int vfswrap_closedir(vfs_handle_struct *handle, connection_struct *conn, DIR *di int result; START_PROFILE(syscall_closedir); - result = closedir(dirp); + result = sys_closedir(dirp); END_PROFILE(syscall_closedir); return result; } diff --git a/source/smbd/vfs.c b/source/smbd/vfs.c index 0328558fe88..f30a5559006 100644 --- a/source/smbd/vfs.c +++ b/source/smbd/vfs.c @@ -62,6 +62,9 @@ static struct vfs_ops default_vfs = { vfswrap_opendir, vfswrap_readdir, + vfswrap_seekdir, + vfswrap_telldir, + vfswrap_rewinddir, vfswrap_mkdir, vfswrap_rmdir, vfswrap_closedir, @@ -611,13 +614,13 @@ SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n) char *vfs_readdirname(connection_struct *conn, void *p) { - struct dirent *ptr= NULL; + SMB_STRUCT_DIRENT *ptr= NULL; char *dname; if (!p) return(NULL); - ptr = (struct dirent *)SMB_VFS_READDIR(conn,p); + ptr = SMB_VFS_READDIR(conn,p); if (!ptr) return(NULL); -- cgit