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 extern struct current_user current_user;
29 /* Make directory handle internals available. */
31 #define NAME_CACHE_SIZE 100
33 struct name_cache_entry {
39 connection_struct *conn;
43 struct name_cache_entry *name_cache;
44 unsigned int name_cache_index;
48 struct dptr_struct *next, *prev;
51 struct connection_struct *conn;
52 struct smb_Dir *dir_hnd;
57 BOOL has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
60 static struct bitmap *dptr_bmap;
61 static struct dptr_struct *dirptrs;
62 static int dirhandles_open = 0;
64 #define INVALID_DPTR_KEY (-3)
66 /****************************************************************************
67 Initialise the dir bitmap.
68 ****************************************************************************/
72 static BOOL dptrs_init=False;
77 dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES);
80 exit_server("out of memory in init_dptrs");
85 /****************************************************************************
86 Idle a dptr - the directory is closed but the control info is kept.
87 ****************************************************************************/
89 static void dptr_idle(struct dptr_struct *dptr)
92 DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
93 CloseDir(dptr->dir_hnd);
98 /****************************************************************************
100 ****************************************************************************/
102 static void dptr_idleoldest(void)
104 struct dptr_struct *dptr;
107 * Go to the end of the list.
109 for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
113 DEBUG(0,("No dptrs available to idle ?\n"));
118 * Idle the oldest pointer.
121 for(; dptr; dptr = dptr->prev) {
129 /****************************************************************************
130 Get the struct dptr_struct for a dir index.
131 ****************************************************************************/
133 static struct dptr_struct *dptr_get(int key, BOOL forclose)
135 struct dptr_struct *dptr;
137 for(dptr = dirptrs; dptr; dptr = dptr->next) {
138 if(dptr->dnum == key) {
139 if (!forclose && !dptr->dir_hnd) {
140 if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
142 DEBUG(4,("dptr_get: Reopening dptr key %d\n",key));
143 if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path))) {
144 DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path,
149 DLIST_PROMOTE(dirptrs,dptr);
156 /****************************************************************************
157 Get the dir path for a dir index.
158 ****************************************************************************/
160 char *dptr_path(int key)
162 struct dptr_struct *dptr = dptr_get(key, False);
168 /****************************************************************************
169 Get the dir wcard for a dir index.
170 ****************************************************************************/
172 char *dptr_wcard(int key)
174 struct dptr_struct *dptr = dptr_get(key, False);
180 /****************************************************************************
181 Get the dir attrib for a dir index.
182 ****************************************************************************/
184 uint16 dptr_attr(int key)
186 struct dptr_struct *dptr = dptr_get(key, False);
192 /****************************************************************************
193 Set the dir wcard for a dir index.
194 Returns 0 on ok, 1 on fail.
195 ****************************************************************************/
197 BOOL dptr_set_wcard_and_attributes(int key, const char *wcard, uint16 attr)
199 struct dptr_struct *dptr = dptr_get(key, False);
203 dptr->wcard = SMB_STRDUP(wcard);
206 if (wcard[0] == '.' && wcard[1] == 0) {
207 dptr->has_wild = True;
209 dptr->has_wild = ms_has_wild(wcard);
216 /****************************************************************************
217 Close a dptr (internal func).
218 ****************************************************************************/
220 static void dptr_close_internal(struct dptr_struct *dptr)
222 DEBUG(4,("closing dptr key %d\n",dptr->dnum));
224 DLIST_REMOVE(dirptrs, dptr);
227 * Free the dnum in the bitmap. Remember the dnum value is always
228 * biased by one with respect to the bitmap.
231 if(bitmap_query( dptr_bmap, dptr->dnum - 1) != True) {
232 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
236 bitmap_clear(dptr_bmap, dptr->dnum - 1);
239 CloseDir(dptr->dir_hnd);
242 /* Lanman 2 specific code */
243 SAFE_FREE(dptr->wcard);
244 string_set(&dptr->path,"");
248 /****************************************************************************
249 Close a dptr given a key.
250 ****************************************************************************/
252 void dptr_close(int *key)
254 struct dptr_struct *dptr;
256 if(*key == INVALID_DPTR_KEY)
259 /* OS/2 seems to use -1 to indicate "close all directories" */
261 struct dptr_struct *next;
262 for(dptr = dirptrs; dptr; dptr = next) {
264 dptr_close_internal(dptr);
266 *key = INVALID_DPTR_KEY;
270 dptr = dptr_get(*key, True);
273 DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
277 dptr_close_internal(dptr);
279 *key = INVALID_DPTR_KEY;
282 /****************************************************************************
283 Close all dptrs for a cnum.
284 ****************************************************************************/
286 void dptr_closecnum(connection_struct *conn)
288 struct dptr_struct *dptr, *next;
289 for(dptr = dirptrs; dptr; dptr = next) {
291 if (dptr->conn == conn)
292 dptr_close_internal(dptr);
296 /****************************************************************************
297 Idle all dptrs for a cnum.
298 ****************************************************************************/
300 void dptr_idlecnum(connection_struct *conn)
302 struct dptr_struct *dptr;
303 for(dptr = dirptrs; dptr; dptr = dptr->next) {
304 if (dptr->conn == conn && dptr->dir_hnd)
309 /****************************************************************************
310 Close a dptr that matches a given path, only if it matches the spid also.
311 ****************************************************************************/
313 void dptr_closepath(char *path,uint16 spid)
315 struct dptr_struct *dptr, *next;
316 for(dptr = dirptrs; dptr; dptr = next) {
318 if (spid == dptr->spid && strequal(dptr->path,path))
319 dptr_close_internal(dptr);
323 /****************************************************************************
324 Try and close the oldest handle not marked for
325 expect close in the hope that the client has
326 finished with that one.
327 ****************************************************************************/
329 static void dptr_close_oldest(BOOL old)
331 struct dptr_struct *dptr;
334 * Go to the end of the list.
336 for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
340 DEBUG(0,("No old dptrs available to close oldest ?\n"));
345 * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
346 * does not have expect_close set. If 'old' is false, close
347 * one of the new dnum handles.
350 for(; dptr; dptr = dptr->prev) {
351 if ((old && (dptr->dnum < 256) && !dptr->expect_close) ||
352 (!old && (dptr->dnum > 255))) {
353 dptr_close_internal(dptr);
359 /****************************************************************************
360 Create a new dir ptr. If the flag old_handle is true then we must allocate
361 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
362 one byte long. If old_handle is false we allocate from the range
363 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
364 a directory handle is never zero.
365 ****************************************************************************/
367 int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid)
369 struct dptr_struct *dptr = NULL;
370 struct smb_Dir *dir_hnd;
373 DEBUG(5,("dptr_create dir=%s\n", path));
375 if (!check_name(path,conn))
376 return(-2); /* Code to say use a unix error return code. */
378 /* use a const pointer from here on */
383 dir_hnd = OpenDir(conn, dir2);
388 string_set(&conn->dirpath,dir2);
390 if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
393 dptr = SMB_MALLOC_P(struct dptr_struct);
395 DEBUG(0,("malloc fail in dptr_create.\n"));
405 * This is an old-style SMBsearch request. Ensure the
406 * value we return will fit in the range 1-255.
409 dptr->dnum = bitmap_find(dptr_bmap, 0);
411 if(dptr->dnum == -1 || dptr->dnum > 254) {
414 * Try and close the oldest handle not marked for
415 * expect close in the hope that the client has
416 * finished with that one.
419 dptr_close_oldest(True);
421 /* Now try again... */
422 dptr->dnum = bitmap_find(dptr_bmap, 0);
423 if(dptr->dnum == -1 || dptr->dnum > 254) {
424 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
433 * This is a new-style trans2 request. Allocate from
434 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
437 dptr->dnum = bitmap_find(dptr_bmap, 255);
439 if(dptr->dnum == -1 || dptr->dnum < 255) {
442 * Try and close the oldest handle close in the hope that
443 * the client has finished with that one. This will only
444 * happen in the case of the Win98 client bug where it leaks
448 dptr_close_oldest(False);
450 /* Now try again... */
451 dptr->dnum = bitmap_find(dptr_bmap, 255);
453 if(dptr->dnum == -1 || dptr->dnum < 255) {
454 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
462 bitmap_set(dptr_bmap, dptr->dnum);
464 dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
466 string_set(&dptr->path,dir2);
468 dptr->dir_hnd = dir_hnd;
470 dptr->expect_close = expect_close;
471 dptr->wcard = NULL; /* Only used in lanman2 searches */
472 dptr->attr = 0; /* Only used in lanman2 searches */
473 dptr->has_wild = True; /* Only used in lanman2 searches */
475 DLIST_ADD(dirptrs, dptr);
477 DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
478 dptr->dnum,path,expect_close));
486 /****************************************************************************
487 Wrapper functions to access the lower level directory handles.
488 ****************************************************************************/
490 int dptr_CloseDir(struct dptr_struct *dptr)
492 return CloseDir(dptr->dir_hnd);
495 void dptr_SeekDir(struct dptr_struct *dptr, long offset)
497 SeekDir(dptr->dir_hnd, offset);
500 long dptr_TellDir(struct dptr_struct *dptr)
502 return TellDir(dptr->dir_hnd);
505 /****************************************************************************
506 Return the next visible file name, skipping veto'd and invisible files.
507 ****************************************************************************/
509 static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
511 /* Normal search for the next file. */
513 while ((name = ReadDirName(dptr->dir_hnd, poffset)) != NULL) {
514 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
521 /****************************************************************************
522 Return the next visible file name, skipping veto'd and invisible files.
523 ****************************************************************************/
525 const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
531 if (dptr->has_wild) {
532 return dptr_normal_ReadDirName(dptr, poffset, pst);
535 /* If poffset is -1 then we know we returned this name before and we have
536 no wildcards. We're at the end of the directory. */
537 if (*poffset == -1) {
541 /* We know the stored wcard contains no wildcard characters. See if we can match
542 with a stat call. If we can't, then set has_wild to true to
543 prevent us from doing this on every call. */
545 /* First check if it should be visible. */
546 if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard, pst, True)) {
547 dptr->has_wild = True;
548 return dptr_normal_ReadDirName(dptr, poffset, pst);
551 if (VALID_STAT(*pst)) {
552 /* We need to set the underlying dir_hdn offset to -1 also as
553 this function is usually called with the output from TellDir. */
554 dptr->dir_hnd->offset = *poffset = -1;
558 pstrcpy(pathreal,dptr->path);
559 pstrcat(pathreal,"/");
560 pstrcat(pathreal,dptr->wcard);
562 if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) {
563 /* We need to set the underlying dir_hdn offset to -1 also as
564 this function is usually called with the output from TellDir. */
565 dptr->dir_hnd->offset = *poffset = -1;
568 /* If we get any other error than ENOENT or ENOTDIR
569 then the file exists we just can't stat it. */
570 if (errno != ENOENT && errno != ENOTDIR) {
571 /* We need to set the underlying dir_hdn offset to -1 also as
572 this function is usually called with the output from TellDir. */
573 dptr->dir_hnd->offset = *poffset = -1;
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 dptr->has_wild = True;
588 return dptr_normal_ReadDirName(dptr, poffset, pst);
592 /****************************************************************************
593 Search for a file by name, skipping veto'ed and not visible files.
594 ****************************************************************************/
596 BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
600 if (!dptr->has_wild && (dptr->dir_hnd->offset == -1)) {
601 /* This is a singleton directory and we're already at the end. */
606 if (SearchDir(dptr->dir_hnd, name, poffset)) {
607 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
614 /****************************************************************************
615 Fill the 5 byte server reserved dptr field.
616 ****************************************************************************/
618 BOOL dptr_fill(char *buf1,unsigned int key)
620 unsigned char *buf = (unsigned char *)buf1;
621 struct dptr_struct *dptr = dptr_get(key, False);
624 DEBUG(1,("filling null dirptr %d\n",key));
627 offset = (uint32)TellDir(dptr->dir_hnd);
628 DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
629 (long)dptr->dir_hnd,(int)offset));
635 /****************************************************************************
636 Fetch the dir ptr and seek it given the 5 byte server field.
637 ****************************************************************************/
639 struct dptr_struct *dptr_fetch(char *buf,int *num)
641 unsigned int key = *(unsigned char *)buf;
642 struct dptr_struct *dptr = dptr_get(key, False);
647 DEBUG(3,("fetched null dirptr %d\n",key));
651 offset = IVAL(buf,1);
652 if (offset == (uint32)-1) {
655 seekoff = (long)offset;
657 SeekDir(dptr->dir_hnd,seekoff);
658 DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
659 key,dptr_path(key),(int)seekoff));
663 /****************************************************************************
665 ****************************************************************************/
667 struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
669 struct dptr_struct *dptr = dptr_get(dptr_num, False);
672 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
675 DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
679 /****************************************************************************
680 Check a filetype for being valid.
681 ****************************************************************************/
683 BOOL dir_check_ftype(connection_struct *conn,int mode,int dirtype)
687 /* Check the "may have" search bits. */
688 if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
691 /* Check the "must have" bits, which are the may have bits shifted eight */
692 /* If must have bit is set, the file/dir can not be returned in search unless the matching
693 file attribute is set */
694 mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */
696 if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask) /* check if matching attribute present */
705 static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask)
707 mangle_map(filename,True,False,SNUM(conn));
708 return mask_match_search(filename,mask,False);
711 /****************************************************************************
712 Get an 8.3 directory entry.
713 ****************************************************************************/
715 BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname,
716 SMB_OFF_T *size,int *mode,time_t *date,BOOL check_descend)
720 SMB_STRUCT_STAT sbuf;
726 *path = *pathreal = *filename = 0;
728 needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
734 long curoff = dptr_TellDir(conn->dirptr);
735 dname = dptr_ReadDirName(conn->dirptr, &curoff, &sbuf);
737 DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
738 (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
743 pstrcpy(filename,dname);
745 /* notice the special *.* handling. This appears to be the only difference
746 between the wildcard handling in this routine and in the trans2 routines.
747 see masktest for a demo
749 if ((strcmp(mask,"*.*") == 0) ||
750 mask_match_search(filename,mask,False) ||
751 mangle_mask_match(conn,filename,mask)) {
753 if (!mangle_is_8_3(filename, False))
754 mangle_map(filename,True,False,SNUM(conn));
756 pstrcpy(fname,filename);
758 pstrcpy(path,conn->dirpath);
761 pstrcpy(pathreal,path);
763 pstrcat(pathreal,dname);
764 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
765 DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) ));
769 *mode = dos_mode(conn,pathreal,&sbuf);
771 if (!dir_check_ftype(conn,*mode,dirtype)) {
772 DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype));
776 *size = sbuf.st_size;
777 *date = sbuf.st_mtime;
779 DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
788 /*******************************************************************
789 Check to see if a user can read a file. This is only approximate,
790 it is used as part of the "hide unreadable" option. Don't
791 use it for anything security sensitive.
792 ********************************************************************/
794 static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
796 SEC_DESC *psd = NULL;
801 uint32 access_granted;
804 * If user is a member of the Admin group
805 * we never hide files from them.
808 if (conn->admin_user)
811 /* If we can't stat it does not show it */
812 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
815 /* Pseudo-open the file (note - no fd's created). */
817 if(S_ISDIR(pst->st_mode))
818 fsp = open_directory(conn, name, pst, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
821 fsp = open_file_stat(conn, name, pst);
826 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
827 sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd,
828 (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
829 close_file(fsp, True);
831 /* No access if SD get failed. */
835 return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA,
836 &access_granted, &status);
839 /*******************************************************************
840 Check to see if a user can write a file (and only files, we do not
841 check dirs on this one). This is only approximate,
842 it is used as part of the "hide unwriteable" option. Don't
843 use it for anything security sensitive.
844 ********************************************************************/
846 static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
848 SEC_DESC *psd = NULL;
854 uint32 access_granted;
857 * If user is a member of the Admin group
858 * we never hide files from them.
861 if (conn->admin_user)
864 /* If we can't stat it does not show it */
865 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
868 /* Pseudo-open the file (note - no fd's created). */
870 if(S_ISDIR(pst->st_mode))
873 fsp = open_file_shared1(conn, name, pst, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE),
874 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY,
875 &access_mode, &smb_action);
880 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
881 sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd,
882 (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
883 close_file(fsp, False);
885 /* No access if SD get failed. */
889 return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA,
890 &access_granted, &status);
893 /*******************************************************************
894 Is a file a "special" type ?
895 ********************************************************************/
897 static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
900 * If user is a member of the Admin group
901 * we never hide files from them.
904 if (conn->admin_user)
907 /* If we can't stat it does not show it */
908 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
911 if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
917 /*******************************************************************
918 Should the file be seen by the client ?
919 ********************************************************************/
921 BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, BOOL use_veto)
923 BOOL hide_unreadable = lp_hideunreadable(SNUM(conn));
924 BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
925 BOOL hide_special = lp_hide_special_files(SNUM(conn));
929 if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
930 return True; /* . and .. are always visible. */
933 /* If it's a vetoed file, pretend it doesn't even exist */
934 if (use_veto && IS_VETO_PATH(conn, name)) {
938 if (hide_unreadable || hide_unwriteable || hide_special) {
941 if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
944 /* Honour _hide unreadable_ option */
945 if (hide_unreadable && !user_can_read_file(conn, entry, pst)) {
949 /* Honour _hide unwriteable_ option */
950 if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
954 /* Honour _hide_special_ option */
955 if (hide_special && file_is_special(conn, entry, pst)) {
964 /*******************************************************************
966 ********************************************************************/
968 struct smb_Dir *OpenDir(connection_struct *conn, const char *name)
970 struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir);
978 dirp->dir_path = SMB_STRDUP(name);
979 if (!dirp->dir_path) {
982 dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path);
984 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) ));
988 dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, NAME_CACHE_SIZE);
989 if (!dirp->name_cache) {
1000 SMB_VFS_CLOSEDIR(conn,dirp->dir);
1002 SAFE_FREE(dirp->dir_path);
1003 SAFE_FREE(dirp->name_cache);
1010 /*******************************************************************
1012 ********************************************************************/
1014 int CloseDir(struct smb_Dir *dirp)
1019 ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1021 SAFE_FREE(dirp->dir_path);
1022 if (dirp->name_cache) {
1023 for (i = 0; i < NAME_CACHE_SIZE; i++) {
1024 SAFE_FREE(dirp->name_cache[i].name);
1027 SAFE_FREE(dirp->name_cache);
1033 /*******************************************************************
1034 Read from a directory. Also return current offset.
1035 Don't check for veto or invisible files.
1036 ********************************************************************/
1038 const char *ReadDirName(struct smb_Dir *dirp, long *poffset)
1041 connection_struct *conn = dirp->conn;
1043 SeekDir(dirp, *poffset);
1044 while ((n = vfs_readdirname(conn, dirp->dir))) {
1045 struct name_cache_entry *e;
1046 dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1047 dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE;
1048 e = &dirp->name_cache[dirp->name_cache_index];
1050 e->name = SMB_STRDUP(n);
1051 *poffset = e->offset= dirp->offset;
1058 /*******************************************************************
1060 ********************************************************************/
1062 void SeekDir(struct smb_Dir *dirp, long offset)
1064 if (offset != dirp->offset) {
1065 SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1066 dirp->offset = offset;
1070 /*******************************************************************
1071 Tell a dir position.
1072 ********************************************************************/
1074 long TellDir(struct smb_Dir *dirp)
1076 return(dirp->offset);
1079 /*******************************************************************
1080 Find an entry by name. Leave us at the offset after it.
1081 Don't check for veto or invisible files.
1082 ********************************************************************/
1084 BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1088 connection_struct *conn = dirp->conn;
1090 /* Search back in the name cache. */
1091 for (i = dirp->name_cache_index; i >= 0; i--) {
1092 struct name_cache_entry *e = &dirp->name_cache[i];
1093 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1094 *poffset = e->offset;
1095 SeekDir(dirp, e->offset);
1099 for (i = NAME_CACHE_SIZE-1; i > dirp->name_cache_index; i--) {
1100 struct name_cache_entry *e = &dirp->name_cache[i];
1101 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1102 *poffset = e->offset;
1103 SeekDir(dirp, e->offset);
1108 /* Not found in the name cache. Rewind directory and start from scratch. */
1109 SMB_VFS_REWINDDIR(conn, dirp->dir);
1111 while ((entry = ReadDirName(dirp, poffset))) {
1112 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {