2 Unix SMB/CIFS implementation.
3 Directory handling routines
4 Copyright (C) Andrew Tridgell 1992-1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 This module implements directory related functions for Samba.
27 /* Make directory handle internals available. */
29 #define NAME_CACHE_SIZE 100
31 struct name_cache_entry {
37 connection_struct *conn;
41 struct name_cache_entry *name_cache;
42 unsigned int name_cache_index;
46 struct dptr_struct *next, *prev;
49 struct connection_struct *conn;
50 struct smb_Dir *dir_hnd;
55 BOOL has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
58 static struct bitmap *dptr_bmap;
59 static struct dptr_struct *dirptrs;
60 static int dirhandles_open = 0;
62 #define INVALID_DPTR_KEY (-3)
64 /****************************************************************************
65 Initialise the dir bitmap.
66 ****************************************************************************/
70 static BOOL dptrs_init=False;
75 dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES);
78 exit_server("out of memory in init_dptrs");
83 /****************************************************************************
84 Idle a dptr - the directory is closed but the control info is kept.
85 ****************************************************************************/
87 static void dptr_idle(struct dptr_struct *dptr)
90 DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
91 CloseDir(dptr->dir_hnd);
96 /****************************************************************************
98 ****************************************************************************/
100 static void dptr_idleoldest(void)
102 struct dptr_struct *dptr;
105 * Go to the end of the list.
107 for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
111 DEBUG(0,("No dptrs available to idle ?\n"));
116 * Idle the oldest pointer.
119 for(; dptr; dptr = dptr->prev) {
127 /****************************************************************************
128 Get the struct dptr_struct for a dir index.
129 ****************************************************************************/
131 static struct dptr_struct *dptr_get(int key, BOOL forclose)
133 struct dptr_struct *dptr;
135 for(dptr = dirptrs; dptr; dptr = dptr->next) {
136 if(dptr->dnum == key) {
137 if (!forclose && !dptr->dir_hnd) {
138 if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
140 DEBUG(4,("dptr_get: Reopening dptr key %d\n",key));
141 if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path))) {
142 DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path,
147 DLIST_PROMOTE(dirptrs,dptr);
154 /****************************************************************************
155 Get the dir path for a dir index.
156 ****************************************************************************/
158 char *dptr_path(int key)
160 struct dptr_struct *dptr = dptr_get(key, False);
166 /****************************************************************************
167 Get the dir wcard for a dir index.
168 ****************************************************************************/
170 char *dptr_wcard(int key)
172 struct dptr_struct *dptr = dptr_get(key, False);
178 /****************************************************************************
179 Get the dir attrib for a dir index.
180 ****************************************************************************/
182 uint16 dptr_attr(int key)
184 struct dptr_struct *dptr = dptr_get(key, False);
190 /****************************************************************************
191 Set the dir wcard for a dir index.
192 Returns 0 on ok, 1 on fail.
193 ****************************************************************************/
195 BOOL dptr_set_wcard_and_attributes(int key, const char *wcard, uint16 attr)
197 struct dptr_struct *dptr = dptr_get(key, False);
201 dptr->wcard = SMB_STRDUP(wcard);
204 if (wcard[0] == '.' && wcard[1] == 0) {
205 dptr->has_wild = True;
207 dptr->has_wild = ms_has_wild(wcard);
214 /****************************************************************************
215 Close a dptr (internal func).
216 ****************************************************************************/
218 static void dptr_close_internal(struct dptr_struct *dptr)
220 DEBUG(4,("closing dptr key %d\n",dptr->dnum));
222 DLIST_REMOVE(dirptrs, dptr);
225 * Free the dnum in the bitmap. Remember the dnum value is always
226 * biased by one with respect to the bitmap.
229 if(bitmap_query( dptr_bmap, dptr->dnum - 1) != True) {
230 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
234 bitmap_clear(dptr_bmap, dptr->dnum - 1);
237 CloseDir(dptr->dir_hnd);
240 /* Lanman 2 specific code */
241 SAFE_FREE(dptr->wcard);
242 string_set(&dptr->path,"");
246 /****************************************************************************
247 Close a dptr given a key.
248 ****************************************************************************/
250 void dptr_close(int *key)
252 struct dptr_struct *dptr;
254 if(*key == INVALID_DPTR_KEY)
257 /* OS/2 seems to use -1 to indicate "close all directories" */
259 struct dptr_struct *next;
260 for(dptr = dirptrs; dptr; dptr = next) {
262 dptr_close_internal(dptr);
264 *key = INVALID_DPTR_KEY;
268 dptr = dptr_get(*key, True);
271 DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
275 dptr_close_internal(dptr);
277 *key = INVALID_DPTR_KEY;
280 /****************************************************************************
281 Close all dptrs for a cnum.
282 ****************************************************************************/
284 void dptr_closecnum(connection_struct *conn)
286 struct dptr_struct *dptr, *next;
287 for(dptr = dirptrs; dptr; dptr = next) {
289 if (dptr->conn == conn)
290 dptr_close_internal(dptr);
294 /****************************************************************************
295 Idle all dptrs for a cnum.
296 ****************************************************************************/
298 void dptr_idlecnum(connection_struct *conn)
300 struct dptr_struct *dptr;
301 for(dptr = dirptrs; dptr; dptr = dptr->next) {
302 if (dptr->conn == conn && dptr->dir_hnd)
307 /****************************************************************************
308 Close a dptr that matches a given path, only if it matches the spid also.
309 ****************************************************************************/
311 void dptr_closepath(char *path,uint16 spid)
313 struct dptr_struct *dptr, *next;
314 for(dptr = dirptrs; dptr; dptr = next) {
316 if (spid == dptr->spid && strequal(dptr->path,path))
317 dptr_close_internal(dptr);
321 /****************************************************************************
322 Try and close the oldest handle not marked for
323 expect close in the hope that the client has
324 finished with that one.
325 ****************************************************************************/
327 static void dptr_close_oldest(BOOL old)
329 struct dptr_struct *dptr;
332 * Go to the end of the list.
334 for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
338 DEBUG(0,("No old dptrs available to close oldest ?\n"));
343 * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
344 * does not have expect_close set. If 'old' is false, close
345 * one of the new dnum handles.
348 for(; dptr; dptr = dptr->prev) {
349 if ((old && (dptr->dnum < 256) && !dptr->expect_close) ||
350 (!old && (dptr->dnum > 255))) {
351 dptr_close_internal(dptr);
357 /****************************************************************************
358 Create a new dir ptr. If the flag old_handle is true then we must allocate
359 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
360 one byte long. If old_handle is false we allocate from the range
361 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
362 a directory handle is never zero.
363 ****************************************************************************/
365 int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid)
367 struct dptr_struct *dptr = NULL;
368 struct smb_Dir *dir_hnd;
371 DEBUG(5,("dptr_create dir=%s\n", path));
373 if (!check_name(path,conn))
374 return(-2); /* Code to say use a unix error return code. */
376 /* use a const pointer from here on */
381 dir_hnd = OpenDir(conn, dir2);
386 string_set(&conn->dirpath,dir2);
388 if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
391 dptr = SMB_MALLOC_P(struct dptr_struct);
393 DEBUG(0,("malloc fail in dptr_create.\n"));
403 * This is an old-style SMBsearch request. Ensure the
404 * value we return will fit in the range 1-255.
407 dptr->dnum = bitmap_find(dptr_bmap, 0);
409 if(dptr->dnum == -1 || dptr->dnum > 254) {
412 * Try and close the oldest handle not marked for
413 * expect close in the hope that the client has
414 * finished with that one.
417 dptr_close_oldest(True);
419 /* Now try again... */
420 dptr->dnum = bitmap_find(dptr_bmap, 0);
421 if(dptr->dnum == -1 || dptr->dnum > 254) {
422 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
431 * This is a new-style trans2 request. Allocate from
432 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
435 dptr->dnum = bitmap_find(dptr_bmap, 255);
437 if(dptr->dnum == -1 || dptr->dnum < 255) {
440 * Try and close the oldest handle close in the hope that
441 * the client has finished with that one. This will only
442 * happen in the case of the Win98 client bug where it leaks
446 dptr_close_oldest(False);
448 /* Now try again... */
449 dptr->dnum = bitmap_find(dptr_bmap, 255);
451 if(dptr->dnum == -1 || dptr->dnum < 255) {
452 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
460 bitmap_set(dptr_bmap, dptr->dnum);
462 dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
464 string_set(&dptr->path,dir2);
466 dptr->dir_hnd = dir_hnd;
468 dptr->expect_close = expect_close;
469 dptr->wcard = NULL; /* Only used in lanman2 searches */
470 dptr->attr = 0; /* Only used in lanman2 searches */
471 dptr->has_wild = True; /* Only used in lanman2 searches */
473 DLIST_ADD(dirptrs, dptr);
475 DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
476 dptr->dnum,path,expect_close));
484 /****************************************************************************
485 Wrapper functions to access the lower level directory handles.
486 ****************************************************************************/
488 int dptr_CloseDir(struct dptr_struct *dptr)
490 return CloseDir(dptr->dir_hnd);
493 void dptr_SeekDir(struct dptr_struct *dptr, long offset)
495 SeekDir(dptr->dir_hnd, offset);
498 long dptr_TellDir(struct dptr_struct *dptr)
500 return TellDir(dptr->dir_hnd);
503 /****************************************************************************
504 Return the next visible file name, skipping veto'd and invisible files.
505 ****************************************************************************/
507 static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
509 /* Normal search for the next file. */
511 while ((name = ReadDirName(dptr->dir_hnd, poffset)) != NULL) {
512 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
519 /****************************************************************************
520 Return the next visible file name, skipping veto'd and invisible files.
521 ****************************************************************************/
523 const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
529 if (dptr->has_wild) {
530 return dptr_normal_ReadDirName(dptr, poffset, pst);
533 /* If poffset is -1 then we know we returned this name before and we have
534 no wildcards. We're at the end of the directory. */
535 if (*poffset == -1) {
539 /* We know the stored wcard contains no wildcard characters. See if we can match
540 with a stat call. If we can't, then set has_wild to true to
541 prevent us from doing this on every call. */
543 /* First check if it should be visible. */
544 if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard, pst, True)) {
545 dptr->has_wild = True;
546 return dptr_normal_ReadDirName(dptr, poffset, pst);
549 if (VALID_STAT(*pst)) {
550 /* We need to set the underlying dir_hdn offset to -1 also as
551 this function is usually called with the output from TellDir. */
552 dptr->dir_hnd->offset = *poffset = -1;
556 pstrcpy(pathreal,dptr->path);
557 pstrcat(pathreal,"/");
558 pstrcat(pathreal,dptr->wcard);
560 if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) {
561 /* We need to set the underlying dir_hdn offset to -1 also as
562 this function is usually called with the output from TellDir. */
563 dptr->dir_hnd->offset = *poffset = -1;
566 /* If we get any other error than ENOENT or ENOTDIR
567 then the file exists we just can't stat it. */
568 if (errno != ENOENT && errno != ENOTDIR) {
569 /* We need to set the underlying dir_hdn offset to -1 also as
570 this function is usually called with the output from TellDir. */
571 dptr->dir_hnd->offset = *poffset = -1;
576 dptr->has_wild = True;
578 /* In case sensitive mode we don't search - we know if it doesn't exist
579 with a stat we will fail. */
581 if (dptr->conn->case_sensitive) {
582 /* We need to set the underlying dir_hdn offset to -1 also as
583 this function is usually called with the output from TellDir. */
584 dptr->dir_hnd->offset = *poffset = -1;
587 return dptr_normal_ReadDirName(dptr, poffset, pst);
591 /****************************************************************************
592 Search for a file by name, skipping veto'ed and not visible files.
593 ****************************************************************************/
595 BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
600 while ((ret = SearchDir(dptr->dir_hnd, name, poffset)) == True) {
601 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
608 /****************************************************************************
609 Fill the 5 byte server reserved dptr field.
610 ****************************************************************************/
612 BOOL dptr_fill(char *buf1,unsigned int key)
614 unsigned char *buf = (unsigned char *)buf1;
615 struct dptr_struct *dptr = dptr_get(key, False);
618 DEBUG(1,("filling null dirptr %d\n",key));
621 offset = TellDir(dptr->dir_hnd);
622 DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
623 (long)dptr->dir_hnd,(int)offset));
625 SIVAL(buf,1,offset | DPTR_MASK);
629 /****************************************************************************
630 Fetch the dir ptr and seek it given the 5 byte server field.
631 ****************************************************************************/
633 struct dptr_struct *dptr_fetch(char *buf,int *num)
635 unsigned int key = *(unsigned char *)buf;
636 struct dptr_struct *dptr = dptr_get(key, False);
640 DEBUG(3,("fetched null dirptr %d\n",key));
644 offset = IVAL(buf,1)&~DPTR_MASK;
645 SeekDir(dptr->dir_hnd,(long)offset);
646 DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
647 key,dptr_path(key),offset));
651 /****************************************************************************
653 ****************************************************************************/
655 struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
657 struct dptr_struct *dptr = dptr_get(dptr_num, False);
660 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
663 DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
667 /****************************************************************************
668 Check a filetype for being valid.
669 ****************************************************************************/
671 BOOL dir_check_ftype(connection_struct *conn,int mode,int dirtype)
675 /* Check the "may have" search bits. */
676 if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
679 /* Check the "must have" bits, which are the may have bits shifted eight */
680 /* If must have bit is set, the file/dir can not be returned in search unless the matching
681 file attribute is set */
682 mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */
684 if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask) /* check if matching attribute present */
693 static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask)
695 mangle_map(filename,True,False,SNUM(conn));
696 return mask_match(filename,mask,False);
699 /****************************************************************************
700 Get an 8.3 directory entry.
701 ****************************************************************************/
703 BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname,
704 SMB_OFF_T *size,int *mode,time_t *date,BOOL check_descend)
708 SMB_STRUCT_STAT sbuf;
715 *path = *pathreal = *filename = 0;
717 isrootdir = (strequal(conn->dirpath,"./") ||
718 strequal(conn->dirpath,".") ||
719 strequal(conn->dirpath,"/"));
721 needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
727 long curoff = dptr_TellDir(conn->dirptr);
728 dname = dptr_ReadDirName(conn->dirptr, &curoff, &sbuf);
730 DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
731 (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
736 pstrcpy(filename,dname);
738 /* notice the special *.* handling. This appears to be the only difference
739 between the wildcard handling in this routine and in the trans2 routines.
740 see masktest for a demo
742 if ((strcmp(mask,"*.*") == 0) ||
743 mask_match(filename,mask,False) ||
744 mangle_mask_match(conn,filename,mask)) {
745 if (isrootdir && (strequal(filename,"..") || strequal(filename,".")))
748 if (!mangle_is_8_3(filename, False))
749 mangle_map(filename,True,False,SNUM(conn));
751 pstrcpy(fname,filename);
753 pstrcpy(path,conn->dirpath);
756 pstrcpy(pathreal,path);
758 pstrcat(pathreal,dname);
759 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
760 DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) ));
764 *mode = dos_mode(conn,pathreal,&sbuf);
766 if (!dir_check_ftype(conn,*mode,dirtype)) {
767 DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype));
771 *size = sbuf.st_size;
772 *date = sbuf.st_mtime;
774 DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
783 /*******************************************************************
784 Check to see if a user can read a file. This is only approximate,
785 it is used as part of the "hide unreadable" option. Don't
786 use it for anything security sensitive.
787 ********************************************************************/
789 static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
791 extern struct current_user current_user;
792 SEC_DESC *psd = NULL;
797 uint32 access_granted;
800 * If user is a member of the Admin group
801 * we never hide files from them.
804 if (conn->admin_user)
807 /* If we can't stat it does not show it */
808 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
811 /* Pseudo-open the file (note - no fd's created). */
813 if(S_ISDIR(pst->st_mode))
814 fsp = open_directory(conn, name, pst, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
817 fsp = open_file_stat(conn, name, pst);
822 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
823 sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd,
824 (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
825 close_file(fsp, True);
827 /* No access if SD get failed. */
831 return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA,
832 &access_granted, &status);
835 /*******************************************************************
836 Check to see if a user can write a file (and only files, we do not
837 check dirs on this one). This is only approximate,
838 it is used as part of the "hide unwriteable" option. Don't
839 use it for anything security sensitive.
840 ********************************************************************/
842 static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
844 extern struct current_user current_user;
845 SEC_DESC *psd = NULL;
851 uint32 access_granted;
854 * If user is a member of the Admin group
855 * we never hide files from them.
858 if (conn->admin_user)
861 /* If we can't stat it does not show it */
862 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
865 /* Pseudo-open the file (note - no fd's created). */
867 if(S_ISDIR(pst->st_mode))
870 fsp = open_file_shared1(conn, name, pst, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE),
871 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY,
872 &access_mode, &smb_action);
877 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
878 sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd,
879 (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
880 close_file(fsp, False);
882 /* No access if SD get failed. */
886 return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA,
887 &access_granted, &status);
890 /*******************************************************************
891 Is a file a "special" type ?
892 ********************************************************************/
894 static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
897 * If user is a member of the Admin group
898 * we never hide files from them.
901 if (conn->admin_user)
904 /* If we can't stat it does not show it */
905 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
908 if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
914 /*******************************************************************
915 Should the file be seen by the client ?
916 ********************************************************************/
918 BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, BOOL use_veto)
920 BOOL hide_unreadable = lp_hideunreadable(SNUM(conn));
921 BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
922 BOOL hide_special = lp_hide_special_files(SNUM(conn));
926 if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
927 return True; /* . and .. are always visible. */
930 /* If it's a vetoed file, pretend it doesn't even exist */
931 if (use_veto && IS_VETO_PATH(conn, name)) {
935 if (hide_unreadable || hide_unwriteable || hide_special) {
938 if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
941 /* Honour _hide unreadable_ option */
942 if (hide_unreadable && !user_can_read_file(conn, entry, pst)) {
946 /* Honour _hide unwriteable_ option */
947 if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
951 /* Honour _hide_special_ option */
952 if (hide_special && !file_is_special(conn, entry, pst)) {
961 /*******************************************************************
963 ********************************************************************/
965 struct smb_Dir *OpenDir(connection_struct *conn, const char *name)
967 struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir);
975 dirp->dir_path = SMB_STRDUP(name);
976 if (!dirp->dir_path) {
979 dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path);
981 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) ));
985 dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, NAME_CACHE_SIZE);
986 if (!dirp->name_cache) {
997 SMB_VFS_CLOSEDIR(conn,dirp->dir);
999 SAFE_FREE(dirp->dir_path);
1000 SAFE_FREE(dirp->name_cache);
1007 /*******************************************************************
1009 ********************************************************************/
1011 int CloseDir(struct smb_Dir *dirp)
1016 ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1018 SAFE_FREE(dirp->dir_path);
1019 if (dirp->name_cache) {
1020 for (i = 0; i < NAME_CACHE_SIZE; i++) {
1021 SAFE_FREE(dirp->name_cache[i].name);
1024 SAFE_FREE(dirp->name_cache);
1030 /*******************************************************************
1031 Read from a directory. Also return current offset.
1032 Don't check for veto or invisible files.
1033 ********************************************************************/
1035 const char *ReadDirName(struct smb_Dir *dirp, long *poffset)
1038 connection_struct *conn = dirp->conn;
1040 SeekDir(dirp, *poffset);
1041 while ((n = vfs_readdirname(conn, dirp->dir))) {
1042 struct name_cache_entry *e;
1043 dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1044 if (dirp->offset == -1) {
1047 dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE;
1049 e = &dirp->name_cache[dirp->name_cache_index];
1051 e->name = SMB_STRDUP(n);
1052 *poffset = e->offset= dirp->offset;
1059 /*******************************************************************
1061 ********************************************************************/
1063 void SeekDir(struct smb_Dir *dirp, long offset)
1065 if (offset != dirp->offset) {
1066 SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1067 dirp->offset = offset;
1071 /*******************************************************************
1072 Tell a dir position.
1073 ********************************************************************/
1075 long TellDir(struct smb_Dir *dirp)
1077 return(dirp->offset);
1080 /*******************************************************************
1081 Find an entry by name. Leave us at the offset after it.
1082 Don't check for veto or invisible files.
1083 ********************************************************************/
1085 BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1089 connection_struct *conn = dirp->conn;
1091 /* Search back in the name cache. */
1092 for (i = dirp->name_cache_index; i >= 0; i--) {
1093 struct name_cache_entry *e = &dirp->name_cache[i];
1094 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1095 *poffset = e->offset;
1096 SeekDir(dirp, e->offset);
1100 for (i = NAME_CACHE_SIZE-1; i > dirp->name_cache_index; i--) {
1101 struct name_cache_entry *e = &dirp->name_cache[i];
1102 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1103 *poffset = e->offset;
1104 SeekDir(dirp, e->offset);
1109 /* Not found in the name cache. Rewind directory and start from scratch. */
1110 SMB_VFS_REWINDDIR(conn, dirp->dir);
1112 while ((entry = ReadDirName(dirp, poffset))) {
1113 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {