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 /****************************************************************************
68 ****************************************************************************/
70 void make_dir_struct(char *buf, const char *mask, const char *fname,SMB_OFF_T size,int mode,time_t date, BOOL uc)
77 if ((mode & aDIR) != 0)
81 if ((p = strchr_m(mask2,'.')) != NULL) {
83 push_ascii(buf+1,mask2,8, 0);
84 push_ascii(buf+9,p+1,3, 0);
87 push_ascii(buf+1,mask2,11, 0);
89 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
91 put_dos_date(buf,22,date);
92 SSVAL(buf,26,size & 0xFFFF);
93 SSVAL(buf,28,(size >> 16)&0xFFFF);
94 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
95 Strange, but verified on W2K3. Needed for OS/2. JRA. */
96 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
97 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
100 /****************************************************************************
101 Initialise the dir bitmap.
102 ****************************************************************************/
104 void init_dptrs(void)
106 static BOOL dptrs_init=False;
111 dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES);
114 exit_server("out of memory in init_dptrs");
119 /****************************************************************************
120 Idle a dptr - the directory is closed but the control info is kept.
121 ****************************************************************************/
123 static void dptr_idle(struct dptr_struct *dptr)
126 DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
127 CloseDir(dptr->dir_hnd);
128 dptr->dir_hnd = NULL;
132 /****************************************************************************
133 Idle the oldest dptr.
134 ****************************************************************************/
136 static void dptr_idleoldest(void)
138 struct dptr_struct *dptr;
141 * Go to the end of the list.
143 for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
147 DEBUG(0,("No dptrs available to idle ?\n"));
152 * Idle the oldest pointer.
155 for(; dptr; dptr = dptr->prev) {
163 /****************************************************************************
164 Get the struct dptr_struct for a dir index.
165 ****************************************************************************/
167 static struct dptr_struct *dptr_get(int key, BOOL forclose)
169 struct dptr_struct *dptr;
171 for(dptr = dirptrs; dptr; dptr = dptr->next) {
172 if(dptr->dnum == key) {
173 if (!forclose && !dptr->dir_hnd) {
174 if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
176 DEBUG(4,("dptr_get: Reopening dptr key %d\n",key));
177 if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path))) {
178 DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path,
183 DLIST_PROMOTE(dirptrs,dptr);
190 /****************************************************************************
191 Get the dir path for a dir index.
192 ****************************************************************************/
194 char *dptr_path(int key)
196 struct dptr_struct *dptr = dptr_get(key, False);
202 /****************************************************************************
203 Get the dir wcard for a dir index.
204 ****************************************************************************/
206 char *dptr_wcard(int key)
208 struct dptr_struct *dptr = dptr_get(key, False);
214 /****************************************************************************
215 Get the dir attrib for a dir index.
216 ****************************************************************************/
218 uint16 dptr_attr(int key)
220 struct dptr_struct *dptr = dptr_get(key, False);
226 /****************************************************************************
227 Set the dir wcard for a dir index.
228 Returns 0 on ok, 1 on fail.
229 ****************************************************************************/
231 BOOL dptr_set_wcard_and_attributes(int key, const char *wcard, uint16 attr)
233 struct dptr_struct *dptr = dptr_get(key, False);
237 dptr->wcard = SMB_STRDUP(wcard);
240 if (wcard[0] == '.' && wcard[1] == 0) {
241 dptr->has_wild = True;
243 dptr->has_wild = ms_has_wild(wcard);
250 /****************************************************************************
251 Close a dptr (internal func).
252 ****************************************************************************/
254 static void dptr_close_internal(struct dptr_struct *dptr)
256 DEBUG(4,("closing dptr key %d\n",dptr->dnum));
258 DLIST_REMOVE(dirptrs, dptr);
261 * Free the dnum in the bitmap. Remember the dnum value is always
262 * biased by one with respect to the bitmap.
265 if(bitmap_query( dptr_bmap, dptr->dnum - 1) != True) {
266 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
270 bitmap_clear(dptr_bmap, dptr->dnum - 1);
273 CloseDir(dptr->dir_hnd);
276 /* Lanman 2 specific code */
277 SAFE_FREE(dptr->wcard);
278 string_set(&dptr->path,"");
282 /****************************************************************************
283 Close a dptr given a key.
284 ****************************************************************************/
286 void dptr_close(int *key)
288 struct dptr_struct *dptr;
290 if(*key == INVALID_DPTR_KEY)
293 /* OS/2 seems to use -1 to indicate "close all directories" */
295 struct dptr_struct *next;
296 for(dptr = dirptrs; dptr; dptr = next) {
298 dptr_close_internal(dptr);
300 *key = INVALID_DPTR_KEY;
304 dptr = dptr_get(*key, True);
307 DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
311 dptr_close_internal(dptr);
313 *key = INVALID_DPTR_KEY;
316 /****************************************************************************
317 Close all dptrs for a cnum.
318 ****************************************************************************/
320 void dptr_closecnum(connection_struct *conn)
322 struct dptr_struct *dptr, *next;
323 for(dptr = dirptrs; dptr; dptr = next) {
325 if (dptr->conn == conn)
326 dptr_close_internal(dptr);
330 /****************************************************************************
331 Idle all dptrs for a cnum.
332 ****************************************************************************/
334 void dptr_idlecnum(connection_struct *conn)
336 struct dptr_struct *dptr;
337 for(dptr = dirptrs; dptr; dptr = dptr->next) {
338 if (dptr->conn == conn && dptr->dir_hnd)
343 /****************************************************************************
344 Close a dptr that matches a given path, only if it matches the spid also.
345 ****************************************************************************/
347 void dptr_closepath(char *path,uint16 spid)
349 struct dptr_struct *dptr, *next;
350 for(dptr = dirptrs; dptr; dptr = next) {
352 if (spid == dptr->spid && strequal(dptr->path,path))
353 dptr_close_internal(dptr);
357 /****************************************************************************
358 Try and close the oldest handle not marked for
359 expect close in the hope that the client has
360 finished with that one.
361 ****************************************************************************/
363 static void dptr_close_oldest(BOOL old)
365 struct dptr_struct *dptr;
368 * Go to the end of the list.
370 for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
374 DEBUG(0,("No old dptrs available to close oldest ?\n"));
379 * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
380 * does not have expect_close set. If 'old' is false, close
381 * one of the new dnum handles.
384 for(; dptr; dptr = dptr->prev) {
385 if ((old && (dptr->dnum < 256) && !dptr->expect_close) ||
386 (!old && (dptr->dnum > 255))) {
387 dptr_close_internal(dptr);
393 /****************************************************************************
394 Create a new dir ptr. If the flag old_handle is true then we must allocate
395 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
396 one byte long. If old_handle is false we allocate from the range
397 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
398 a directory handle is never zero.
399 ****************************************************************************/
401 int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid)
403 struct dptr_struct *dptr = NULL;
404 struct smb_Dir *dir_hnd;
407 DEBUG(5,("dptr_create dir=%s\n", path));
409 if (!check_name(path,conn))
410 return(-2); /* Code to say use a unix error return code. */
412 /* use a const pointer from here on */
417 dir_hnd = OpenDir(conn, dir2);
422 string_set(&conn->dirpath,dir2);
424 if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
427 dptr = SMB_MALLOC_P(struct dptr_struct);
429 DEBUG(0,("malloc fail in dptr_create.\n"));
439 * This is an old-style SMBsearch request. Ensure the
440 * value we return will fit in the range 1-255.
443 dptr->dnum = bitmap_find(dptr_bmap, 0);
445 if(dptr->dnum == -1 || dptr->dnum > 254) {
448 * Try and close the oldest handle not marked for
449 * expect close in the hope that the client has
450 * finished with that one.
453 dptr_close_oldest(True);
455 /* Now try again... */
456 dptr->dnum = bitmap_find(dptr_bmap, 0);
457 if(dptr->dnum == -1 || dptr->dnum > 254) {
458 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
467 * This is a new-style trans2 request. Allocate from
468 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
471 dptr->dnum = bitmap_find(dptr_bmap, 255);
473 if(dptr->dnum == -1 || dptr->dnum < 255) {
476 * Try and close the oldest handle close in the hope that
477 * the client has finished with that one. This will only
478 * happen in the case of the Win98 client bug where it leaks
482 dptr_close_oldest(False);
484 /* Now try again... */
485 dptr->dnum = bitmap_find(dptr_bmap, 255);
487 if(dptr->dnum == -1 || dptr->dnum < 255) {
488 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
496 bitmap_set(dptr_bmap, dptr->dnum);
498 dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
500 string_set(&dptr->path,dir2);
502 dptr->dir_hnd = dir_hnd;
504 dptr->expect_close = expect_close;
505 dptr->wcard = NULL; /* Only used in lanman2 searches */
506 dptr->attr = 0; /* Only used in lanman2 searches */
507 dptr->has_wild = True; /* Only used in lanman2 searches */
509 DLIST_ADD(dirptrs, dptr);
511 DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
512 dptr->dnum,path,expect_close));
520 /****************************************************************************
521 Wrapper functions to access the lower level directory handles.
522 ****************************************************************************/
524 int dptr_CloseDir(struct dptr_struct *dptr)
526 return CloseDir(dptr->dir_hnd);
529 void dptr_SeekDir(struct dptr_struct *dptr, long offset)
531 SeekDir(dptr->dir_hnd, offset);
534 long dptr_TellDir(struct dptr_struct *dptr)
536 return TellDir(dptr->dir_hnd);
539 /****************************************************************************
540 Return the next visible file name, skipping veto'd and invisible files.
541 ****************************************************************************/
543 static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
545 /* Normal search for the next file. */
547 while ((name = ReadDirName(dptr->dir_hnd, poffset)) != NULL) {
548 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
555 /****************************************************************************
556 Return the next visible file name, skipping veto'd and invisible files.
557 ****************************************************************************/
559 const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
563 SET_STAT_INVALID(*pst);
565 if (dptr->has_wild) {
566 return dptr_normal_ReadDirName(dptr, poffset, pst);
569 /* If poffset is -1 then we know we returned this name before and we have
570 no wildcards. We're at the end of the directory. */
571 if (*poffset == -1) {
575 /* We know the stored wcard contains no wildcard characters. See if we can match
576 with a stat call. If we can't, then set has_wild to true to
577 prevent us from doing this on every call. */
579 /* First check if it should be visible. */
580 if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard, pst, True)) {
581 dptr->has_wild = True;
582 return dptr_normal_ReadDirName(dptr, poffset, pst);
585 if (VALID_STAT(*pst)) {
586 /* We need to set the underlying dir_hdn offset to -1 also as
587 this function is usually called with the output from TellDir. */
588 dptr->dir_hnd->offset = *poffset = -1;
592 pstrcpy(pathreal,dptr->path);
593 pstrcat(pathreal,"/");
594 pstrcat(pathreal,dptr->wcard);
596 if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) {
597 /* We need to set the underlying dir_hdn offset to -1 also as
598 this function is usually called with the output from TellDir. */
599 dptr->dir_hnd->offset = *poffset = -1;
602 /* If we get any other error than ENOENT or ENOTDIR
603 then the file exists we just can't stat it. */
604 if (errno != ENOENT && errno != ENOTDIR) {
605 /* We need to set the underlying dir_hdn offset to -1 also as
606 this function is usually called with the output from TellDir. */
607 dptr->dir_hnd->offset = *poffset = -1;
612 /* In case sensitive mode we don't search - we know if it doesn't exist
613 with a stat we will fail. */
615 if (dptr->conn->case_sensitive) {
616 /* We need to set the underlying dir_hdn offset to -1 also as
617 this function is usually called with the output from TellDir. */
618 dptr->dir_hnd->offset = *poffset = -1;
621 dptr->has_wild = True;
622 return dptr_normal_ReadDirName(dptr, poffset, pst);
626 /****************************************************************************
627 Search for a file by name, skipping veto'ed and not visible files.
628 ****************************************************************************/
630 BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
632 SET_STAT_INVALID(*pst);
634 if (!dptr->has_wild && (dptr->dir_hnd->offset == -1)) {
635 /* This is a singleton directory and we're already at the end. */
640 if (SearchDir(dptr->dir_hnd, name, poffset)) {
641 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
648 /****************************************************************************
649 Fill the 5 byte server reserved dptr field.
650 ****************************************************************************/
652 BOOL dptr_fill(char *buf1,unsigned int key)
654 unsigned char *buf = (unsigned char *)buf1;
655 struct dptr_struct *dptr = dptr_get(key, False);
658 DEBUG(1,("filling null dirptr %d\n",key));
661 offset = (uint32)TellDir(dptr->dir_hnd);
662 DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
663 (long)dptr->dir_hnd,(int)offset));
669 /****************************************************************************
670 Fetch the dir ptr and seek it given the 5 byte server field.
671 ****************************************************************************/
673 struct dptr_struct *dptr_fetch(char *buf,int *num)
675 unsigned int key = *(unsigned char *)buf;
676 struct dptr_struct *dptr = dptr_get(key, False);
681 DEBUG(3,("fetched null dirptr %d\n",key));
685 offset = IVAL(buf,1);
686 if (offset == (uint32)-1) {
689 seekoff = (long)offset;
691 SeekDir(dptr->dir_hnd,seekoff);
692 DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
693 key,dptr_path(key),(int)seekoff));
697 /****************************************************************************
699 ****************************************************************************/
701 struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
703 struct dptr_struct *dptr = dptr_get(dptr_num, False);
706 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
709 DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
713 /****************************************************************************
714 Check a filetype for being valid.
715 ****************************************************************************/
717 BOOL dir_check_ftype(connection_struct *conn,int mode,int dirtype)
721 /* Check the "may have" search bits. */
722 if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
725 /* Check the "must have" bits, which are the may have bits shifted eight */
726 /* If must have bit is set, the file/dir can not be returned in search unless the matching
727 file attribute is set */
728 mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */
730 if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask) /* check if matching attribute present */
739 static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask)
741 mangle_map(filename,True,False,SNUM(conn));
742 return mask_match_search(filename,mask,False);
745 /****************************************************************************
746 Get an 8.3 directory entry.
747 ****************************************************************************/
749 BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname,
750 SMB_OFF_T *size,int *mode,time_t *date,BOOL check_descend)
754 SMB_STRUCT_STAT sbuf;
760 *path = *pathreal = *filename = 0;
762 needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
768 long curoff = dptr_TellDir(conn->dirptr);
769 dname = dptr_ReadDirName(conn->dirptr, &curoff, &sbuf);
771 DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
772 (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
777 pstrcpy(filename,dname);
779 /* notice the special *.* handling. This appears to be the only difference
780 between the wildcard handling in this routine and in the trans2 routines.
781 see masktest for a demo
783 if ((strcmp(mask,"*.*") == 0) ||
784 mask_match_search(filename,mask,False) ||
785 mangle_mask_match(conn,filename,mask)) {
787 if (!mangle_is_8_3(filename, False, SNUM(conn)))
788 mangle_map(filename,True,False,SNUM(conn));
790 pstrcpy(fname,filename);
792 pstrcpy(path,conn->dirpath);
795 pstrcpy(pathreal,path);
797 pstrcat(pathreal,dname);
798 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
799 DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) ));
803 *mode = dos_mode(conn,pathreal,&sbuf);
805 if (!dir_check_ftype(conn,*mode,dirtype)) {
806 DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype));
810 *size = sbuf.st_size;
811 *date = sbuf.st_mtime;
813 DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
822 /*******************************************************************
823 Check to see if a user can read a file. This is only approximate,
824 it is used as part of the "hide unreadable" option. Don't
825 use it for anything security sensitive.
826 ********************************************************************/
828 static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
830 SEC_DESC *psd = NULL;
835 uint32 access_granted;
838 * If user is a member of the Admin group
839 * we never hide files from them.
842 if (conn->admin_user)
845 /* If we can't stat it does not show it */
846 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
849 /* Pseudo-open the file (note - no fd's created). */
851 if(S_ISDIR(pst->st_mode))
852 fsp = open_directory(conn, name, pst, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
855 fsp = open_file_stat(conn, name, pst);
860 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
861 sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd,
862 (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
863 close_file(fsp, True);
865 /* No access if SD get failed. */
869 return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA,
870 &access_granted, &status);
873 /*******************************************************************
874 Check to see if a user can write a file (and only files, we do not
875 check dirs on this one). This is only approximate,
876 it is used as part of the "hide unwriteable" option. Don't
877 use it for anything security sensitive.
878 ********************************************************************/
880 static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
882 SEC_DESC *psd = NULL;
888 uint32 access_granted;
891 * If user is a member of the Admin group
892 * we never hide files from them.
895 if (conn->admin_user)
898 /* If we can't stat it does not show it */
899 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
902 /* Pseudo-open the file (note - no fd's created). */
904 if(S_ISDIR(pst->st_mode))
907 fsp = open_file_shared1(conn, name, pst, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE),
908 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY,
909 &access_mode, &smb_action);
914 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
915 sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd,
916 (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
917 close_file(fsp, False);
919 /* No access if SD get failed. */
923 return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA,
924 &access_granted, &status);
927 /*******************************************************************
928 Is a file a "special" type ?
929 ********************************************************************/
931 static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
934 * If user is a member of the Admin group
935 * we never hide files from them.
938 if (conn->admin_user)
941 /* If we can't stat it does not show it */
942 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
945 if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
951 /*******************************************************************
952 Should the file be seen by the client ?
953 ********************************************************************/
955 BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, BOOL use_veto)
957 BOOL hide_unreadable = lp_hideunreadable(SNUM(conn));
958 BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
959 BOOL hide_special = lp_hide_special_files(SNUM(conn));
961 SET_STAT_INVALID(*pst);
963 if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
964 return True; /* . and .. are always visible. */
967 /* If it's a vetoed file, pretend it doesn't even exist */
968 if (use_veto && IS_VETO_PATH(conn, name)) {
972 if (hide_unreadable || hide_unwriteable || hide_special) {
975 if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
978 /* Honour _hide unreadable_ option */
979 if (hide_unreadable && !user_can_read_file(conn, entry, pst)) {
983 /* Honour _hide unwriteable_ option */
984 if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
988 /* Honour _hide_special_ option */
989 if (hide_special && file_is_special(conn, entry, pst)) {
998 /*******************************************************************
1000 ********************************************************************/
1002 struct smb_Dir *OpenDir(connection_struct *conn, const char *name)
1004 struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir);
1012 dirp->dir_path = SMB_STRDUP(name);
1013 if (!dirp->dir_path) {
1016 dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path);
1018 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) ));
1022 dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, NAME_CACHE_SIZE);
1023 if (!dirp->name_cache) {
1034 SMB_VFS_CLOSEDIR(conn,dirp->dir);
1036 SAFE_FREE(dirp->dir_path);
1037 SAFE_FREE(dirp->name_cache);
1044 /*******************************************************************
1046 ********************************************************************/
1048 int CloseDir(struct smb_Dir *dirp)
1053 ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1055 SAFE_FREE(dirp->dir_path);
1056 if (dirp->name_cache) {
1057 for (i = 0; i < NAME_CACHE_SIZE; i++) {
1058 SAFE_FREE(dirp->name_cache[i].name);
1061 SAFE_FREE(dirp->name_cache);
1067 /*******************************************************************
1068 Read from a directory. Also return current offset.
1069 Don't check for veto or invisible files.
1070 ********************************************************************/
1072 const char *ReadDirName(struct smb_Dir *dirp, long *poffset)
1075 connection_struct *conn = dirp->conn;
1077 SeekDir(dirp, *poffset);
1078 while ((n = vfs_readdirname(conn, dirp->dir))) {
1079 struct name_cache_entry *e;
1080 dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1081 dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE;
1082 e = &dirp->name_cache[dirp->name_cache_index];
1084 e->name = SMB_STRDUP(n);
1085 *poffset = e->offset= dirp->offset;
1092 /*******************************************************************
1094 ********************************************************************/
1096 void SeekDir(struct smb_Dir *dirp, long offset)
1098 if (offset != dirp->offset) {
1099 SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1100 dirp->offset = offset;
1104 /*******************************************************************
1105 Tell a dir position.
1106 ********************************************************************/
1108 long TellDir(struct smb_Dir *dirp)
1110 return(dirp->offset);
1113 /*******************************************************************
1114 Find an entry by name. Leave us at the offset after it.
1115 Don't check for veto or invisible files.
1116 ********************************************************************/
1118 BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1122 connection_struct *conn = dirp->conn;
1124 /* Search back in the name cache. */
1125 for (i = dirp->name_cache_index; i >= 0; i--) {
1126 struct name_cache_entry *e = &dirp->name_cache[i];
1127 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1128 *poffset = e->offset;
1129 SeekDir(dirp, e->offset);
1133 for (i = NAME_CACHE_SIZE-1; i > dirp->name_cache_index; i--) {
1134 struct name_cache_entry *e = &dirp->name_cache[i];
1135 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1136 *poffset = e->offset;
1137 SeekDir(dirp, e->offset);
1142 /* Not found in the name cache. Rewind directory and start from scratch. */
1143 SMB_VFS_REWINDDIR(conn, dirp->dir);
1145 while ((entry = ReadDirName(dirp, poffset))) {
1146 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {