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 /* In case sensitive mode we don't search - we know if it doesn't exist
577 with a stat we will fail. */
579 if (dptr->conn->case_sensitive) {
580 /* We need to set the underlying dir_hdn offset to -1 also as
581 this function is usually called with the output from TellDir. */
582 dptr->dir_hnd->offset = *poffset = -1;
585 dptr->has_wild = True;
586 return dptr_normal_ReadDirName(dptr, poffset, pst);
590 /****************************************************************************
591 Search for a file by name, skipping veto'ed and not visible files.
592 ****************************************************************************/
594 BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
598 if (!dptr->has_wild && (dptr->dir_hnd->offset == -1)) {
599 /* This is a singleton directory and we're already at the end. */
604 if (SearchDir(dptr->dir_hnd, name, poffset)) {
605 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
612 /****************************************************************************
613 Fill the 5 byte server reserved dptr field.
614 ****************************************************************************/
616 BOOL dptr_fill(char *buf1,unsigned int key)
618 unsigned char *buf = (unsigned char *)buf1;
619 struct dptr_struct *dptr = dptr_get(key, False);
622 DEBUG(1,("filling null dirptr %d\n",key));
625 offset = TellDir(dptr->dir_hnd);
626 DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
627 (long)dptr->dir_hnd,(int)offset));
629 SIVAL(buf,1,offset | DPTR_MASK);
633 /****************************************************************************
634 Fetch the dir ptr and seek it given the 5 byte server field.
635 ****************************************************************************/
637 struct dptr_struct *dptr_fetch(char *buf,int *num)
639 unsigned int key = *(unsigned char *)buf;
640 struct dptr_struct *dptr = dptr_get(key, False);
644 DEBUG(3,("fetched null dirptr %d\n",key));
648 offset = IVAL(buf,1)&~DPTR_MASK;
649 SeekDir(dptr->dir_hnd,(long)offset);
650 DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
651 key,dptr_path(key),offset));
655 /****************************************************************************
657 ****************************************************************************/
659 struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
661 struct dptr_struct *dptr = dptr_get(dptr_num, False);
664 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
667 DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
671 /****************************************************************************
672 Check a filetype for being valid.
673 ****************************************************************************/
675 BOOL dir_check_ftype(connection_struct *conn,int mode,int dirtype)
679 /* Check the "may have" search bits. */
680 if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
683 /* Check the "must have" bits, which are the may have bits shifted eight */
684 /* If must have bit is set, the file/dir can not be returned in search unless the matching
685 file attribute is set */
686 mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */
688 if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask) /* check if matching attribute present */
697 static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask)
699 mangle_map(filename,True,False,SNUM(conn));
700 return mask_match_search(filename,mask,False);
703 /****************************************************************************
704 Get an 8.3 directory entry.
705 ****************************************************************************/
707 BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname,
708 SMB_OFF_T *size,int *mode,time_t *date,BOOL check_descend)
712 SMB_STRUCT_STAT sbuf;
718 *path = *pathreal = *filename = 0;
720 needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
726 long curoff = dptr_TellDir(conn->dirptr);
727 dname = dptr_ReadDirName(conn->dirptr, &curoff, &sbuf);
729 DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
730 (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
735 pstrcpy(filename,dname);
737 /* notice the special *.* handling. This appears to be the only difference
738 between the wildcard handling in this routine and in the trans2 routines.
739 see masktest for a demo
741 if ((strcmp(mask,"*.*") == 0) ||
742 mask_match_search(filename,mask,False) ||
743 mangle_mask_match(conn,filename,mask)) {
745 if (!mangle_is_8_3(filename, False))
746 mangle_map(filename,True,False,SNUM(conn));
748 pstrcpy(fname,filename);
750 pstrcpy(path,conn->dirpath);
753 pstrcpy(pathreal,path);
755 pstrcat(pathreal,dname);
756 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
757 DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) ));
761 *mode = dos_mode(conn,pathreal,&sbuf);
763 if (!dir_check_ftype(conn,*mode,dirtype)) {
764 DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype));
768 *size = sbuf.st_size;
769 *date = sbuf.st_mtime;
771 DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
780 /*******************************************************************
781 Check to see if a user can read a file. This is only approximate,
782 it is used as part of the "hide unreadable" option. Don't
783 use it for anything security sensitive.
784 ********************************************************************/
786 static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
788 extern struct current_user current_user;
789 SEC_DESC *psd = NULL;
794 uint32 access_granted;
797 * If user is a member of the Admin group
798 * we never hide files from them.
801 if (conn->admin_user)
804 /* If we can't stat it does not show it */
805 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
808 /* Pseudo-open the file (note - no fd's created). */
810 if(S_ISDIR(pst->st_mode))
811 fsp = open_directory(conn, name, pst, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
814 fsp = open_file_stat(conn, name, pst);
819 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
820 sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd,
821 (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
822 close_file(fsp, True);
824 /* No access if SD get failed. */
828 return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA,
829 &access_granted, &status);
832 /*******************************************************************
833 Check to see if a user can write a file (and only files, we do not
834 check dirs on this one). This is only approximate,
835 it is used as part of the "hide unwriteable" option. Don't
836 use it for anything security sensitive.
837 ********************************************************************/
839 static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
841 extern struct current_user current_user;
842 SEC_DESC *psd = NULL;
848 uint32 access_granted;
851 * If user is a member of the Admin group
852 * we never hide files from them.
855 if (conn->admin_user)
858 /* If we can't stat it does not show it */
859 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
862 /* Pseudo-open the file (note - no fd's created). */
864 if(S_ISDIR(pst->st_mode))
867 fsp = open_file_shared1(conn, name, pst, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE),
868 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY,
869 &access_mode, &smb_action);
874 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
875 sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd,
876 (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
877 close_file(fsp, False);
879 /* No access if SD get failed. */
883 return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA,
884 &access_granted, &status);
887 /*******************************************************************
888 Is a file a "special" type ?
889 ********************************************************************/
891 static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
894 * If user is a member of the Admin group
895 * we never hide files from them.
898 if (conn->admin_user)
901 /* If we can't stat it does not show it */
902 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
905 if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
911 /*******************************************************************
912 Should the file be seen by the client ?
913 ********************************************************************/
915 BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, BOOL use_veto)
917 BOOL hide_unreadable = lp_hideunreadable(SNUM(conn));
918 BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
919 BOOL hide_special = lp_hide_special_files(SNUM(conn));
923 if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
924 return True; /* . and .. are always visible. */
927 /* If it's a vetoed file, pretend it doesn't even exist */
928 if (use_veto && IS_VETO_PATH(conn, name)) {
932 if (hide_unreadable || hide_unwriteable || hide_special) {
935 if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
938 /* Honour _hide unreadable_ option */
939 if (hide_unreadable && !user_can_read_file(conn, entry, pst)) {
943 /* Honour _hide unwriteable_ option */
944 if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
948 /* Honour _hide_special_ option */
949 if (hide_special && !file_is_special(conn, entry, pst)) {
958 /*******************************************************************
960 ********************************************************************/
962 struct smb_Dir *OpenDir(connection_struct *conn, const char *name)
964 struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir);
972 dirp->dir_path = SMB_STRDUP(name);
973 if (!dirp->dir_path) {
976 dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path);
978 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) ));
982 dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, NAME_CACHE_SIZE);
983 if (!dirp->name_cache) {
994 SMB_VFS_CLOSEDIR(conn,dirp->dir);
996 SAFE_FREE(dirp->dir_path);
997 SAFE_FREE(dirp->name_cache);
1004 /*******************************************************************
1006 ********************************************************************/
1008 int CloseDir(struct smb_Dir *dirp)
1013 ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1015 SAFE_FREE(dirp->dir_path);
1016 if (dirp->name_cache) {
1017 for (i = 0; i < NAME_CACHE_SIZE; i++) {
1018 SAFE_FREE(dirp->name_cache[i].name);
1021 SAFE_FREE(dirp->name_cache);
1027 /*******************************************************************
1028 Read from a directory. Also return current offset.
1029 Don't check for veto or invisible files.
1030 ********************************************************************/
1032 const char *ReadDirName(struct smb_Dir *dirp, long *poffset)
1035 connection_struct *conn = dirp->conn;
1037 SeekDir(dirp, *poffset);
1038 while ((n = vfs_readdirname(conn, dirp->dir))) {
1039 struct name_cache_entry *e;
1040 dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1041 if (dirp->offset == -1) {
1044 dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE;
1046 e = &dirp->name_cache[dirp->name_cache_index];
1048 e->name = SMB_STRDUP(n);
1049 *poffset = e->offset= dirp->offset;
1056 /*******************************************************************
1058 ********************************************************************/
1060 void SeekDir(struct smb_Dir *dirp, long offset)
1062 if (offset != dirp->offset) {
1063 SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1064 dirp->offset = offset;
1068 /*******************************************************************
1069 Tell a dir position.
1070 ********************************************************************/
1072 long TellDir(struct smb_Dir *dirp)
1074 return(dirp->offset);
1077 /*******************************************************************
1078 Find an entry by name. Leave us at the offset after it.
1079 Don't check for veto or invisible files.
1080 ********************************************************************/
1082 BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1086 connection_struct *conn = dirp->conn;
1088 /* Search back in the name cache. */
1089 for (i = dirp->name_cache_index; i >= 0; i--) {
1090 struct name_cache_entry *e = &dirp->name_cache[i];
1091 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1092 *poffset = e->offset;
1093 SeekDir(dirp, e->offset);
1097 for (i = NAME_CACHE_SIZE-1; i > dirp->name_cache_index; i--) {
1098 struct name_cache_entry *e = &dirp->name_cache[i];
1099 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1100 *poffset = e->offset;
1101 SeekDir(dirp, e->offset);
1106 /* Not found in the name cache. Rewind directory and start from scratch. */
1107 SMB_VFS_REWINDDIR(conn, dirp->dir);
1109 while ((entry = ReadDirName(dirp, poffset))) {
1110 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {