From ff7e5c26733c933d0ed71616c39e2d931ad1e597 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 25 Jun 2005 03:03:44 +0000 Subject: r7893: Add in the extra parameters to opendir() to fix the large directory/insane app problem. Rev vfs version. Doesn't change the normal codepath. Jeremy. (This used to be commit 0f03a6bdcdbdf60da81e0aeffa84ac6e48fc6a04) --- source3/smbd/dir.c | 69 ++++++++++++++++++++-------------------------- source3/smbd/filename.c | 2 +- source3/smbd/msdfs.c | 2 +- source3/smbd/notify_hash.c | 2 +- source3/smbd/reply.c | 52 ++++++++++++++++------------------ source3/smbd/trans2.c | 24 ++++++---------- source3/smbd/vfs-wrap.c | 2 +- 7 files changed, 67 insertions(+), 86 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index ae21e16e31..fd0a303504 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -53,7 +53,7 @@ struct dptr_struct { struct smb_Dir *dir_hnd; BOOL expect_close; char *wcard; - uint16 attr; + uint32 attr; char *path; BOOL has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */ }; @@ -68,7 +68,7 @@ static int dirhandles_open = 0; Make a dir struct. ****************************************************************************/ -void make_dir_struct(char *buf, const char *mask, const char *fname,SMB_OFF_T size,int mode,time_t date, BOOL uc) +void make_dir_struct(char *buf, const char *mask, const char *fname,SMB_OFF_T size,uint32 mode,time_t date, BOOL uc) { char *p; pstring mask2; @@ -175,7 +175,7 @@ static struct dptr_struct *dptr_get(int key, BOOL forclose) if (dirhandles_open >= MAX_OPEN_DIRECTORIES) dptr_idleoldest(); DEBUG(4,("dptr_get: Reopening dptr key %d\n",key)); - if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path))) { + if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path, dptr->wcard, dptr->attr))) { DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path, strerror(errno))); return False; @@ -224,30 +224,6 @@ uint16 dptr_attr(int key) return(0); } -/**************************************************************************** - Set the dir wcard for a dir index. - Returns 0 on ok, 1 on fail. -****************************************************************************/ - -BOOL dptr_set_wcard_and_attributes(int key, const char *wcard, uint16 attr) -{ - struct dptr_struct *dptr = dptr_get(key, False); - - if (dptr) { - dptr->attr = attr; - dptr->wcard = SMB_STRDUP(wcard); - if (!dptr->wcard) - return False; - if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) { - dptr->has_wild = True; - } else { - dptr->has_wild = ms_has_wild(wcard); - } - return True; - } - return False; -} - /**************************************************************************** Close a dptr (internal func). ****************************************************************************/ @@ -399,7 +375,8 @@ static void dptr_close_oldest(BOOL old) a directory handle is never zero. ****************************************************************************/ -int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid) +int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid, + const char *wcard, uint32 attr) { struct dptr_struct *dptr = NULL; struct smb_Dir *dir_hnd; @@ -415,7 +392,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp if (!*dir2) dir2 = "."; - dir_hnd = OpenDir(conn, dir2); + dir_hnd = OpenDir(conn, dir2, wcard, attr); if (!dir_hnd) { return (-2); } @@ -503,9 +480,23 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp dptr->dir_hnd = dir_hnd; dptr->spid = spid; dptr->expect_close = expect_close; - dptr->wcard = NULL; /* Only used in lanman2 searches */ - dptr->attr = 0; /* Only used in lanman2 searches */ - dptr->has_wild = True; /* Only used in lanman2 searches */ + if (wcard) { + dptr->wcard = SMB_STRDUP(wcard); + if (!dptr->wcard) { + bitmap_clear(dptr_bmap, dptr->dnum - 1); + SAFE_FREE(dptr); + CloseDir(dir_hnd); + return -1; + } + } else { + dptr->wcard = NULL; + } + dptr->attr = attr; + if (lp_posix_pathnames() || (wcard && (wcard[0] == '.' && wcard[1] == 0))) { + dptr->has_wild = True; + } else { + dptr->has_wild = ms_has_wild(wcard); + } DLIST_ADD(dirptrs, dptr); @@ -715,9 +706,9 @@ struct dptr_struct *dptr_fetch_lanman2(int dptr_num) Check a filetype for being valid. ****************************************************************************/ -BOOL dir_check_ftype(connection_struct *conn,int mode,int dirtype) +BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype) { - int mask; + uint32 mask; /* Check the "may have" search bits. */ if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0) @@ -747,8 +738,8 @@ static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *m Get an 8.3 directory entry. ****************************************************************************/ -BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname, - SMB_OFF_T *size,int *mode,time_t *date,BOOL check_descend) +BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fname, + SMB_OFF_T *size,uint32 *mode,time_t *date,BOOL check_descend) { const char *dname; BOOL found = False; @@ -804,7 +795,7 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname *mode = dos_mode(conn,pathreal,&sbuf); if (!dir_check_ftype(conn,*mode,dirtype)) { - DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype)); + DEBUG(5,("[%s] attribs didn't match %x\n",filename,(unsigned int)dirtype)); continue; } @@ -1000,7 +991,7 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char * Open a directory. ********************************************************************/ -struct smb_Dir *OpenDir(connection_struct *conn, const char *name) +struct smb_Dir *OpenDir(connection_struct *conn, const char *name, const char *mask, uint32 attr) { struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir); if (!dirp) { @@ -1014,7 +1005,7 @@ struct smb_Dir *OpenDir(connection_struct *conn, const char *name) if (!dirp->dir_path) { goto fail; } - dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path); + dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr); if (!dirp->dir) { DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) )); goto fail; diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 3fb88974fe..f0a33e568e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -450,7 +450,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name mangled = !mangle_check_cache( name, maxlength, SNUM(conn)); /* open the directory */ - if (!(cur_dir = OpenDir(conn, path))) { + if (!(cur_dir = OpenDir(conn, path, NULL, 0))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); return(False); } diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index b61a328080..be88a92414 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -989,7 +989,7 @@ static BOOL form_junctions(int snum, struct junction_map* jucn, int* jn_count) cnt++; /* Now enumerate all dfs links */ - dirp = SMB_VFS_OPENDIR(conn, "."); + dirp = SMB_VFS_OPENDIR(conn, ".", NULL, 0); if(!dirp) goto out; diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index 0464eaa2eb..08eefab652 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -76,7 +76,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, * larger than the max time_t value). */ - dp = OpenDir(conn, path); + dp = OpenDir(conn, path, NULL, 0); if (dp == NULL) return False; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 99e0d5d9a1..9a7c22320c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1014,9 +1014,9 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size pstring directory; pstring fname; SMB_OFF_T size; - int mode; + uint32 mode; time_t date; - int dirtype; + uint32 dirtype; int outsize = 0; unsigned int numentries = 0; unsigned int maxentries = 0; @@ -1115,7 +1115,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size ok = True; if (status_len == 0) { - dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid)); + dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, dirtype); if (dptr_num < 0) { if(dptr_num == -2) { END_PROFILE(SMBsearch); @@ -1124,10 +1124,6 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size END_PROFILE(SMBsearch); return ERROR_DOS(ERRDOS,ERRnofids); } - if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) { - END_PROFILE(SMBsearch); - return ERROR_DOS(ERRDOS,ERRnomem); - } } else { dirtype = dptr_attr(dptr_num); } @@ -1743,10 +1739,10 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, Check if a user is allowed to delete a file. ********************************************************************/ -NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_path, BOOL check_is_at_open) +NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL bad_path, BOOL check_is_at_open) { SMB_STRUCT_STAT sbuf; - int fmode; + uint32 fmode; int smb_action; int access_mode; files_struct *fsp; @@ -1817,7 +1813,7 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_ code. ****************************************************************************/ -NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) +NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name) { pstring directory; pstring mask; @@ -1879,8 +1875,11 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) struct smb_Dir *dir_hnd = NULL; const char *dname; + if (strequal(mask,"????????.???")) + pstrcpy(mask,"*"); + if (check_name(directory,conn)) - dir_hnd = OpenDir(conn, directory); + dir_hnd = OpenDir(conn, directory, mask, dirtype); /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then the pattern matches against the long name, otherwise the short name @@ -1891,9 +1890,6 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) long offset = 0; error = NT_STATUS_NO_SUCH_FILE; - if (strequal(mask,"????????.???")) - pstrcpy(mask,"*"); - while ((dname = ReadDirName(dir_hnd, &offset))) { SMB_STRUCT_STAT st; pstring fname; @@ -1954,7 +1950,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size { int outsize = 0; pstring name; - int dirtype; + uint32 dirtype; NTSTATUS status; START_PROFILE(SMBunlink); @@ -3707,7 +3703,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) const char *dname = NULL; BOOL ret = False; long offset = 0; - struct smb_Dir *dir_hnd = OpenDir(conn, directory); + struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0); if(dir_hnd == NULL) return True; @@ -3775,7 +3771,7 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) */ BOOL all_veto_files = True; const char *dname; - struct smb_Dir *dir_hnd = OpenDir(conn, directory); + struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0); if(dir_hnd != NULL) { long dirpos = 0; @@ -3997,7 +3993,7 @@ static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T Rename an open file - given an fsp. ****************************************************************************/ -NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists) +NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint32 attrs, BOOL replace_if_exists) { SMB_STRUCT_STAT sbuf; BOOL bad_path = False; @@ -4111,7 +4107,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char * code. ****************************************************************************/ -NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists) +NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint32 attrs, BOOL replace_if_exists) { pstring directory; pstring mask; @@ -4333,17 +4329,17 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", const char *dname; pstring destname; + if (strequal(mask,"????????.???")) + pstrcpy(mask,"*"); + if (check_name(directory,conn)) - dir_hnd = OpenDir(conn, directory); + dir_hnd = OpenDir(conn, directory, mask, attrs); if (dir_hnd) { long offset = 0; error = NT_STATUS_NO_SUCH_FILE; /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */ - if (strequal(mask,"????????.???")) - pstrcpy(mask,"*"); - while ((dname = ReadDirName(dir_hnd, &offset))) { pstring fname; BOOL sysdir_entry = False; @@ -4444,7 +4440,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstring name; pstring newname; char *p; - uint16 attrs = SVAL(inbuf,smb_vwv0); + uint32 attrs = SVAL(inbuf,smb_vwv0); NTSTATUS status; START_PROFILE(SMBmv); @@ -4689,16 +4685,16 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, const char *dname; pstring destname; + if (strequal(mask,"????????.???")) + pstrcpy(mask,"*"); + if (check_name(directory,conn)) - dir_hnd = OpenDir(conn, directory); + dir_hnd = OpenDir(conn, directory, mask, 0); if (dir_hnd) { long offset = 0; error = ERRbadfile; - if (strequal(mask,"????????.???")) - pstrcpy(mask,"*"); - while ((dname = ReadDirName(dir_hnd, &offset))) { pstring fname; pstrcpy(fname,dname); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 978afa6d74..5bf53fca8a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -996,7 +996,7 @@ static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *ps static BOOL get_lanman2_dir_entry(connection_struct *conn, void *inbuf, void *outbuf, - char *path_mask,int dirtype,int info_level, + char *path_mask,uint32 dirtype,int info_level, int requires_resume_key, BOOL dont_descend,char **ppdata, char *base_data, int space_remaining, @@ -1012,7 +1012,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, char *p, *q, *pdata = *ppdata; uint32 reskey=0; long prev_dirpos=0; - int mode=0; + uint32 mode=0; SMB_OFF_T file_size = 0; SMB_BIG_UINT allocation_size = 0; uint32 len; @@ -1020,7 +1020,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, char *nameptr; char *last_entry_ptr; BOOL was_8_3; - int nt_extmode; /* Used for NT connections instead of mode */ + uint32 nt_extmode; /* Used for NT connections instead of mode */ BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); BOOL check_mangled_names = lp_manglednames(SNUM(conn)); @@ -1576,7 +1576,7 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb requested. */ char *params = *pparams; char *pdata = *ppdata; - int dirtype = SVAL(params,0); + uint32 dirtype = SVAL(params,0); int maxentries = SVAL(params,2); uint16 findfirst_flags = SVAL(params,4); BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE); @@ -1606,9 +1606,9 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb *directory = *mask = 0; - DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \ + DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", - dirtype, maxentries, close_after_first, close_if_end, requires_resume_key, + (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key, info_level, max_data_bytes)); if (!maxentries) { @@ -1711,19 +1711,13 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } *pparams = params; - dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid)); - if (dptr_num < 0) { - talloc_destroy(ea_ctx); - return(UNIXERROR(ERRDOS,ERRbadfile)); - } - /* Save the wildcard match and attribs we are using on this directory - needed as lanman2 assumes these are being saved between calls */ - if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) { - dptr_close(&dptr_num); + dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, dirtype); + if (dptr_num < 0) { talloc_destroy(ea_ctx); - return ERROR_NT(NT_STATUS_NO_MEMORY); + return(UNIXERROR(ERRDOS,ERRbadfile)); } DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype)); diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 57442edee6..3260cce9aa 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -88,7 +88,7 @@ int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_ /* Directory operations */ -DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname) +DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr) { DIR *result; -- cgit