r6044: Ensure the old search calls always ask mask_match to translate
[vlendec/samba-autobuild/.git] / source3 / smbd / dir.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Directory handling routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    
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.
10    
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.
15    
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.
19 */
20
21 #include "includes.h"
22
23 /*
24    This module implements directory related functions for Samba.
25 */
26
27 /* Make directory handle internals available. */
28
29 #define NAME_CACHE_SIZE 100
30
31 struct name_cache_entry {
32         char *name;
33         long offset;
34 };
35
36 struct smb_Dir {
37         connection_struct *conn;
38         DIR *dir;
39         long offset;
40         char *dir_path;
41         struct name_cache_entry *name_cache;
42         unsigned int name_cache_index;
43 };
44
45 struct dptr_struct {
46         struct dptr_struct *next, *prev;
47         int dnum;
48         uint16 spid;
49         struct connection_struct *conn;
50         struct smb_Dir *dir_hnd;
51         BOOL expect_close;
52         char *wcard;
53         uint16 attr;
54         char *path;
55         BOOL has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
56 };
57
58 static struct bitmap *dptr_bmap;
59 static struct dptr_struct *dirptrs;
60 static int dirhandles_open = 0;
61
62 #define INVALID_DPTR_KEY (-3)
63
64 /****************************************************************************
65  Initialise the dir bitmap.
66 ****************************************************************************/
67
68 void init_dptrs(void)
69 {
70         static BOOL dptrs_init=False;
71
72         if (dptrs_init)
73                 return;
74
75         dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES);
76
77         if (!dptr_bmap)
78                 exit_server("out of memory in init_dptrs");
79
80         dptrs_init = True;
81 }
82
83 /****************************************************************************
84  Idle a dptr - the directory is closed but the control info is kept.
85 ****************************************************************************/
86
87 static void dptr_idle(struct dptr_struct *dptr)
88 {
89         if (dptr->dir_hnd) {
90                 DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
91                 CloseDir(dptr->dir_hnd);
92                 dptr->dir_hnd = NULL;
93         }
94 }
95
96 /****************************************************************************
97  Idle the oldest dptr.
98 ****************************************************************************/
99
100 static void dptr_idleoldest(void)
101 {
102         struct dptr_struct *dptr;
103
104         /*
105          * Go to the end of the list.
106          */
107         for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
108                 ;
109
110         if(!dptr) {
111                 DEBUG(0,("No dptrs available to idle ?\n"));
112                 return;
113         }
114
115         /*
116          * Idle the oldest pointer.
117          */
118
119         for(; dptr; dptr = dptr->prev) {
120                 if (dptr->dir_hnd) {
121                         dptr_idle(dptr);
122                         return;
123                 }
124         }
125 }
126
127 /****************************************************************************
128  Get the struct dptr_struct for a dir index.
129 ****************************************************************************/
130
131 static struct dptr_struct *dptr_get(int key, BOOL forclose)
132 {
133         struct dptr_struct *dptr;
134
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)
139                                         dptr_idleoldest();
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,
143                                                 strerror(errno)));
144                                         return False;
145                                 }
146                         }
147                         DLIST_PROMOTE(dirptrs,dptr);
148                         return dptr;
149                 }
150         }
151         return(NULL);
152 }
153
154 /****************************************************************************
155  Get the dir path for a dir index.
156 ****************************************************************************/
157
158 char *dptr_path(int key)
159 {
160         struct dptr_struct *dptr = dptr_get(key, False);
161         if (dptr)
162                 return(dptr->path);
163         return(NULL);
164 }
165
166 /****************************************************************************
167  Get the dir wcard for a dir index.
168 ****************************************************************************/
169
170 char *dptr_wcard(int key)
171 {
172         struct dptr_struct *dptr = dptr_get(key, False);
173         if (dptr)
174                 return(dptr->wcard);
175         return(NULL);
176 }
177
178 /****************************************************************************
179  Get the dir attrib for a dir index.
180 ****************************************************************************/
181
182 uint16 dptr_attr(int key)
183 {
184         struct dptr_struct *dptr = dptr_get(key, False);
185         if (dptr)
186                 return(dptr->attr);
187         return(0);
188 }
189
190 /****************************************************************************
191  Set the dir wcard for a dir index.
192  Returns 0 on ok, 1 on fail.
193 ****************************************************************************/
194
195 BOOL dptr_set_wcard_and_attributes(int key, const char *wcard, uint16 attr)
196 {
197         struct dptr_struct *dptr = dptr_get(key, False);
198
199         if (dptr) {
200                 dptr->attr = attr;
201                 dptr->wcard = SMB_STRDUP(wcard);
202                 if (!dptr->wcard)
203                         return False;
204                 if (wcard[0] == '.' && wcard[1] == 0) {
205                         dptr->has_wild = True;
206                 } else {
207                         dptr->has_wild = ms_has_wild(wcard);
208                 }
209                 return True;
210         }
211         return False;
212 }
213
214 /****************************************************************************
215  Close a dptr (internal func).
216 ****************************************************************************/
217
218 static void dptr_close_internal(struct dptr_struct *dptr)
219 {
220         DEBUG(4,("closing dptr key %d\n",dptr->dnum));
221
222         DLIST_REMOVE(dirptrs, dptr);
223
224         /* 
225          * Free the dnum in the bitmap. Remember the dnum value is always 
226          * biased by one with respect to the bitmap.
227          */
228
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",
231                         dptr->dnum ));
232         }
233
234         bitmap_clear(dptr_bmap, dptr->dnum - 1);
235
236         if (dptr->dir_hnd) {
237                 CloseDir(dptr->dir_hnd);
238         }
239
240         /* Lanman 2 specific code */
241         SAFE_FREE(dptr->wcard);
242         string_set(&dptr->path,"");
243         SAFE_FREE(dptr);
244 }
245
246 /****************************************************************************
247  Close a dptr given a key.
248 ****************************************************************************/
249
250 void dptr_close(int *key)
251 {
252         struct dptr_struct *dptr;
253
254         if(*key == INVALID_DPTR_KEY)
255                 return;
256
257         /* OS/2 seems to use -1 to indicate "close all directories" */
258         if (*key == -1) {
259                 struct dptr_struct *next;
260                 for(dptr = dirptrs; dptr; dptr = next) {
261                         next = dptr->next;
262                         dptr_close_internal(dptr);
263                 }
264                 *key = INVALID_DPTR_KEY;
265                 return;
266         }
267
268         dptr = dptr_get(*key, True);
269
270         if (!dptr) {
271                 DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
272                 return;
273         }
274
275         dptr_close_internal(dptr);
276
277         *key = INVALID_DPTR_KEY;
278 }
279
280 /****************************************************************************
281  Close all dptrs for a cnum.
282 ****************************************************************************/
283
284 void dptr_closecnum(connection_struct *conn)
285 {
286         struct dptr_struct *dptr, *next;
287         for(dptr = dirptrs; dptr; dptr = next) {
288                 next = dptr->next;
289                 if (dptr->conn == conn)
290                         dptr_close_internal(dptr);
291         }
292 }
293
294 /****************************************************************************
295  Idle all dptrs for a cnum.
296 ****************************************************************************/
297
298 void dptr_idlecnum(connection_struct *conn)
299 {
300         struct dptr_struct *dptr;
301         for(dptr = dirptrs; dptr; dptr = dptr->next) {
302                 if (dptr->conn == conn && dptr->dir_hnd)
303                         dptr_idle(dptr);
304         }
305 }
306
307 /****************************************************************************
308  Close a dptr that matches a given path, only if it matches the spid also.
309 ****************************************************************************/
310
311 void dptr_closepath(char *path,uint16 spid)
312 {
313         struct dptr_struct *dptr, *next;
314         for(dptr = dirptrs; dptr; dptr = next) {
315                 next = dptr->next;
316                 if (spid == dptr->spid && strequal(dptr->path,path))
317                         dptr_close_internal(dptr);
318         }
319 }
320
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 ****************************************************************************/
326
327 static void dptr_close_oldest(BOOL old)
328 {
329         struct dptr_struct *dptr;
330
331         /*
332          * Go to the end of the list.
333          */
334         for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
335                 ;
336
337         if(!dptr) {
338                 DEBUG(0,("No old dptrs available to close oldest ?\n"));
339                 return;
340         }
341
342         /*
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.
346          */
347
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);
352                                 return;
353                 }
354         }
355 }
356
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 ****************************************************************************/
364
365 int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid)
366 {
367         struct dptr_struct *dptr = NULL;
368         struct smb_Dir *dir_hnd;
369         const char *dir2;
370
371         DEBUG(5,("dptr_create dir=%s\n", path));
372
373         if (!check_name(path,conn))
374                 return(-2); /* Code to say use a unix error return code. */
375
376         /* use a const pointer from here on */
377         dir2 = path;
378         if (!*dir2)
379                 dir2 = ".";
380
381         dir_hnd = OpenDir(conn, dir2);
382         if (!dir_hnd) {
383                 return (-2);
384         }
385
386         string_set(&conn->dirpath,dir2);
387
388         if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
389                 dptr_idleoldest();
390
391         dptr = SMB_MALLOC_P(struct dptr_struct);
392         if(!dptr) {
393                 DEBUG(0,("malloc fail in dptr_create.\n"));
394                 CloseDir(dir_hnd);
395                 return -1;
396         }
397
398         ZERO_STRUCTP(dptr);
399
400         if(old_handle) {
401
402                 /*
403                  * This is an old-style SMBsearch request. Ensure the
404                  * value we return will fit in the range 1-255.
405                  */
406
407                 dptr->dnum = bitmap_find(dptr_bmap, 0);
408
409                 if(dptr->dnum == -1 || dptr->dnum > 254) {
410
411                         /*
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.
415                          */
416
417                         dptr_close_oldest(True);
418
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));
423                                 SAFE_FREE(dptr);
424                                 CloseDir(dir_hnd);
425                                 return -1;
426                         }
427                 }
428         } else {
429
430                 /*
431                  * This is a new-style trans2 request. Allocate from
432                  * a range that will return 256 - MAX_DIRECTORY_HANDLES.
433                  */
434
435                 dptr->dnum = bitmap_find(dptr_bmap, 255);
436
437                 if(dptr->dnum == -1 || dptr->dnum < 255) {
438
439                         /*
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
443                          * directory handles.
444                          */
445
446                         dptr_close_oldest(False);
447
448                         /* Now try again... */
449                         dptr->dnum = bitmap_find(dptr_bmap, 255);
450
451                         if(dptr->dnum == -1 || dptr->dnum < 255) {
452                                 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
453                                 SAFE_FREE(dptr);
454                                 CloseDir(dir_hnd);
455                                 return -1;
456                         }
457                 }
458         }
459
460         bitmap_set(dptr_bmap, dptr->dnum);
461
462         dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
463
464         string_set(&dptr->path,dir2);
465         dptr->conn = conn;
466         dptr->dir_hnd = dir_hnd;
467         dptr->spid = spid;
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 */
472
473         DLIST_ADD(dirptrs, dptr);
474
475         DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
476                 dptr->dnum,path,expect_close));  
477
478         conn->dirptr = dptr;
479
480         return(dptr->dnum);
481 }
482
483
484 /****************************************************************************
485  Wrapper functions to access the lower level directory handles.
486 ****************************************************************************/
487
488 int dptr_CloseDir(struct dptr_struct *dptr)
489 {
490         return CloseDir(dptr->dir_hnd);
491 }
492
493 void dptr_SeekDir(struct dptr_struct *dptr, long offset)
494 {
495         SeekDir(dptr->dir_hnd, offset);
496 }
497
498 long dptr_TellDir(struct dptr_struct *dptr)
499 {
500         return TellDir(dptr->dir_hnd);
501 }
502
503 /****************************************************************************
504  Return the next visible file name, skipping veto'd and invisible files.
505 ****************************************************************************/
506
507 static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
508 {
509         /* Normal search for the next file. */
510         const char *name;
511         while ((name = ReadDirName(dptr->dir_hnd, poffset)) != NULL) {
512                 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
513                         return name;
514                 }
515         }
516         return NULL;
517 }
518
519 /****************************************************************************
520  Return the next visible file name, skipping veto'd and invisible files.
521 ****************************************************************************/
522
523 const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
524 {
525         pstring pathreal;
526
527         ZERO_STRUCTP(pst);
528
529         if (dptr->has_wild) {
530                 return dptr_normal_ReadDirName(dptr, poffset, pst);
531         }
532
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) {
536                 return NULL;
537         }
538
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. */
542
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);
547         }
548
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;
553                 return dptr->wcard;
554         }
555
556         pstrcpy(pathreal,dptr->path);
557         pstrcat(pathreal,"/");
558         pstrcat(pathreal,dptr->wcard);
559
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;
564                 return dptr->wcard;
565         } else {
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;
572                         return dptr->wcard;
573                 }
574         }
575
576         dptr->has_wild = True;
577
578         /* In case sensitive mode we don't search - we know if it doesn't exist 
579            with a stat we will fail. */
580
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;
585                 return NULL;
586         } else {
587                 return dptr_normal_ReadDirName(dptr, poffset, pst);
588         }
589 }
590
591 /****************************************************************************
592  Search for a file by name, skipping veto'ed and not visible files.
593 ****************************************************************************/
594
595 BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
596 {
597         ZERO_STRUCTP(pst);
598
599         if (!dptr->has_wild && (dptr->dir_hnd->offset == -1)) {
600                 /* This is a singleton directory and we're already at the end. */
601                 *poffset = -1;
602                 return False;
603         }
604
605         while (SearchDir(dptr->dir_hnd, name, poffset) == True) {
606                 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
607                         return True;
608                 }
609         }
610         return False;
611 }
612
613 /****************************************************************************
614  Fill the 5 byte server reserved dptr field.
615 ****************************************************************************/
616
617 BOOL dptr_fill(char *buf1,unsigned int key)
618 {
619         unsigned char *buf = (unsigned char *)buf1;
620         struct dptr_struct *dptr = dptr_get(key, False);
621         uint32 offset;
622         if (!dptr) {
623                 DEBUG(1,("filling null dirptr %d\n",key));
624                 return(False);
625         }
626         offset = TellDir(dptr->dir_hnd);
627         DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
628                 (long)dptr->dir_hnd,(int)offset));
629         buf[0] = key;
630         SIVAL(buf,1,offset | DPTR_MASK);
631         return(True);
632 }
633
634 /****************************************************************************
635  Fetch the dir ptr and seek it given the 5 byte server field.
636 ****************************************************************************/
637
638 struct dptr_struct *dptr_fetch(char *buf,int *num)
639 {
640         unsigned int key = *(unsigned char *)buf;
641         struct dptr_struct *dptr = dptr_get(key, False);
642         uint32 offset;
643
644         if (!dptr) {
645                 DEBUG(3,("fetched null dirptr %d\n",key));
646                 return(NULL);
647         }
648         *num = key;
649         offset = IVAL(buf,1)&~DPTR_MASK;
650         SeekDir(dptr->dir_hnd,(long)offset);
651         DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
652                 key,dptr_path(key),offset));
653         return(dptr);
654 }
655
656 /****************************************************************************
657  Fetch the dir ptr.
658 ****************************************************************************/
659
660 struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
661 {
662         struct dptr_struct *dptr  = dptr_get(dptr_num, False);
663
664         if (!dptr) {
665                 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
666                 return(NULL);
667         }
668         DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
669         return(dptr);
670 }
671
672 /****************************************************************************
673  Check a filetype for being valid.
674 ****************************************************************************/
675
676 BOOL dir_check_ftype(connection_struct *conn,int mode,int dirtype)
677 {
678         int mask;
679
680         /* Check the "may have" search bits. */
681         if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
682                 return False;
683
684         /* Check the "must have" bits, which are the may have bits shifted eight */
685         /* If must have bit is set, the file/dir can not be returned in search unless the matching
686                 file attribute is set */
687         mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */
688         if(mask) {
689                 if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask)   /* check if matching attribute present */
690                         return True;
691                 else
692                         return False;
693         }
694
695         return True;
696 }
697
698 static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask)
699 {
700         mangle_map(filename,True,False,SNUM(conn));
701         return mask_match_search(filename,mask,False);
702 }
703
704 /****************************************************************************
705  Get an 8.3 directory entry.
706 ****************************************************************************/
707
708 BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname,
709                    SMB_OFF_T *size,int *mode,time_t *date,BOOL check_descend)
710 {
711         const char *dname;
712         BOOL found = False;
713         SMB_STRUCT_STAT sbuf;
714         pstring path;
715         pstring pathreal;
716         pstring filename;
717         BOOL needslash;
718
719         *path = *pathreal = *filename = 0;
720
721         needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
722
723         if (!conn->dirptr)
724                 return(False);
725
726         while (!found) {
727                 long curoff = dptr_TellDir(conn->dirptr);
728                 dname = dptr_ReadDirName(conn->dirptr, &curoff, &sbuf);
729
730                 DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
731                         (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
732       
733                 if (dname == NULL) 
734                         return(False);
735       
736                 pstrcpy(filename,dname);      
737
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
741                 */
742                 if ((strcmp(mask,"*.*") == 0) ||
743                     mask_match_search(filename,mask,False) ||
744                     mangle_mask_match(conn,filename,mask)) {
745
746                         if (!mangle_is_8_3(filename, False))
747                                 mangle_map(filename,True,False,SNUM(conn));
748
749                         pstrcpy(fname,filename);
750                         *path = 0;
751                         pstrcpy(path,conn->dirpath);
752                         if(needslash)
753                                 pstrcat(path,"/");
754                         pstrcpy(pathreal,path);
755                         pstrcat(path,fname);
756                         pstrcat(pathreal,dname);
757                         if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
758                                 DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) ));
759                                 continue;
760                         }
761           
762                         *mode = dos_mode(conn,pathreal,&sbuf);
763
764                         if (!dir_check_ftype(conn,*mode,dirtype)) {
765                                 DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype));
766                                 continue;
767                         }
768
769                         *size = sbuf.st_size;
770                         *date = sbuf.st_mtime;
771
772                         DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
773
774                         found = True;
775                 }
776         }
777
778         return(found);
779 }
780
781 /*******************************************************************
782  Check to see if a user can read a file. This is only approximate,
783  it is used as part of the "hide unreadable" option. Don't
784  use it for anything security sensitive.
785 ********************************************************************/
786
787 static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
788 {
789         extern struct current_user current_user;
790         SEC_DESC *psd = NULL;
791         size_t sd_size;
792         files_struct *fsp;
793         int smb_action;
794         NTSTATUS status;
795         uint32 access_granted;
796
797         /*
798          * If user is a member of the Admin group
799          * we never hide files from them.
800          */
801
802         if (conn->admin_user)
803                 return True;
804
805         /* If we can't stat it does not show it */
806         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
807                 return False;
808
809         /* Pseudo-open the file (note - no fd's created). */
810
811         if(S_ISDIR(pst->st_mode))       
812                  fsp = open_directory(conn, name, pst, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
813                         &smb_action);
814         else
815                 fsp = open_file_stat(conn, name, pst);
816
817         if (!fsp)
818                 return False;
819
820         /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
821         sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd,
822                         (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
823         close_file(fsp, True);
824
825         /* No access if SD get failed. */
826         if (!sd_size)
827                 return False;
828
829         return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA,
830                                  &access_granted, &status);
831 }
832
833 /*******************************************************************
834  Check to see if a user can write a file (and only files, we do not
835  check dirs on this one). This is only approximate,
836  it is used as part of the "hide unwriteable" option. Don't
837  use it for anything security sensitive.
838 ********************************************************************/
839
840 static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
841 {
842         extern struct current_user current_user;
843         SEC_DESC *psd = NULL;
844         size_t sd_size;
845         files_struct *fsp;
846         int smb_action;
847         int access_mode;
848         NTSTATUS status;
849         uint32 access_granted;
850
851         /*
852          * If user is a member of the Admin group
853          * we never hide files from them.
854          */
855
856         if (conn->admin_user)
857                 return True;
858
859         /* If we can't stat it does not show it */
860         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
861                 return False;
862
863         /* Pseudo-open the file (note - no fd's created). */
864
865         if(S_ISDIR(pst->st_mode))       
866                 return True;
867         else
868                 fsp = open_file_shared1(conn, name, pst, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE),
869                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY,
870                         &access_mode, &smb_action);
871
872         if (!fsp)
873                 return False;
874
875         /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
876         sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd,
877                         (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
878         close_file(fsp, False);
879
880         /* No access if SD get failed. */
881         if (!sd_size)
882                 return False;
883
884         return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA,
885                                  &access_granted, &status);
886 }
887
888 /*******************************************************************
889   Is a file a "special" type ?
890 ********************************************************************/
891
892 static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
893 {
894         /*
895          * If user is a member of the Admin group
896          * we never hide files from them.
897          */
898
899         if (conn->admin_user)
900                 return False;
901
902         /* If we can't stat it does not show it */
903         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
904                 return True;
905
906         if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
907                 return False;
908
909         return True;
910 }
911
912 /*******************************************************************
913  Should the file be seen by the client ?
914 ********************************************************************/
915
916 BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, BOOL use_veto)
917 {
918         BOOL hide_unreadable = lp_hideunreadable(SNUM(conn));
919         BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
920         BOOL hide_special = lp_hide_special_files(SNUM(conn));
921
922         ZERO_STRUCTP(pst);
923
924         if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
925                 return True; /* . and .. are always visible. */
926         }
927
928         /* If it's a vetoed file, pretend it doesn't even exist */
929         if (use_veto && IS_VETO_PATH(conn, name)) {
930                 return False;
931         }
932
933         if (hide_unreadable || hide_unwriteable || hide_special) {
934                 char *entry = NULL;
935
936                 if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
937                         return False;
938                 }
939                 /* Honour _hide unreadable_ option */
940                 if (hide_unreadable && !user_can_read_file(conn, entry, pst)) {
941                         SAFE_FREE(entry);
942                         return False;
943                 }
944                 /* Honour _hide unwriteable_ option */
945                 if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
946                         SAFE_FREE(entry);
947                         return False;
948                 }
949                 /* Honour _hide_special_ option */
950                 if (hide_special && !file_is_special(conn, entry, pst)) {
951                         SAFE_FREE(entry);
952                         return False;
953                 }
954                 SAFE_FREE(entry);
955         }
956         return True;
957 }
958
959 /*******************************************************************
960  Open a directory.
961 ********************************************************************/
962
963 struct smb_Dir *OpenDir(connection_struct *conn, const char *name)
964 {
965         struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir);
966         if (!dirp) {
967                 return NULL;
968         }
969         ZERO_STRUCTP(dirp);
970
971         dirp->conn = conn;
972
973         dirp->dir_path = SMB_STRDUP(name);
974         if (!dirp->dir_path) {
975                 goto fail;
976         }
977         dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path);
978         if (!dirp->dir) {
979                 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) ));
980                 goto fail;
981         }
982
983         dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, NAME_CACHE_SIZE);
984         if (!dirp->name_cache) {
985                 goto fail;
986         }
987
988         dirhandles_open++;
989         return dirp;
990
991   fail:
992
993         if (dirp) {
994                 if (dirp->dir) {
995                         SMB_VFS_CLOSEDIR(conn,dirp->dir);
996                 }
997                 SAFE_FREE(dirp->dir_path);
998                 SAFE_FREE(dirp->name_cache);
999                 SAFE_FREE(dirp);
1000         }
1001         return NULL;
1002 }
1003
1004
1005 /*******************************************************************
1006  Close a directory.
1007 ********************************************************************/
1008
1009 int CloseDir(struct smb_Dir *dirp)
1010 {
1011         int i, ret = 0;
1012
1013         if (dirp->dir) {
1014                 ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1015         }
1016         SAFE_FREE(dirp->dir_path);
1017         if (dirp->name_cache) {
1018                 for (i = 0; i < NAME_CACHE_SIZE; i++) {
1019                         SAFE_FREE(dirp->name_cache[i].name);
1020                 }
1021         }
1022         SAFE_FREE(dirp->name_cache);
1023         SAFE_FREE(dirp);
1024         dirhandles_open--;
1025         return ret;
1026 }
1027
1028 /*******************************************************************
1029  Read from a directory. Also return current offset.
1030  Don't check for veto or invisible files.
1031 ********************************************************************/
1032
1033 const char *ReadDirName(struct smb_Dir *dirp, long *poffset)
1034 {
1035         const char *n;
1036         connection_struct *conn = dirp->conn;
1037
1038         SeekDir(dirp, *poffset);
1039         while ((n = vfs_readdirname(conn, dirp->dir))) {
1040                 struct name_cache_entry *e;
1041                 dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1042                 if (dirp->offset == -1) {
1043                         return NULL;
1044                 }
1045                 dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE;
1046
1047                 e = &dirp->name_cache[dirp->name_cache_index];
1048                 SAFE_FREE(e->name);
1049                 e->name = SMB_STRDUP(n);
1050                 *poffset = e->offset= dirp->offset;
1051                 return e->name;
1052         }
1053         dirp->offset = -1;
1054         return NULL;
1055 }
1056
1057 /*******************************************************************
1058  Seek a dir.
1059 ********************************************************************/
1060
1061 void SeekDir(struct smb_Dir *dirp, long offset)
1062 {
1063         if (offset != dirp->offset) {
1064                 SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1065                 dirp->offset = offset;
1066         }
1067 }
1068
1069 /*******************************************************************
1070  Tell a dir position.
1071 ********************************************************************/
1072
1073 long TellDir(struct smb_Dir *dirp)
1074 {
1075         return(dirp->offset);
1076 }
1077
1078 /*******************************************************************
1079  Find an entry by name. Leave us at the offset after it.
1080  Don't check for veto or invisible files.
1081 ********************************************************************/
1082
1083 BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1084 {
1085         int i;
1086         const char *entry;
1087         connection_struct *conn = dirp->conn;
1088
1089         /* Search back in the name cache. */
1090         for (i = dirp->name_cache_index; i >= 0; i--) {
1091                 struct name_cache_entry *e = &dirp->name_cache[i];
1092                 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1093                         *poffset = e->offset;
1094                         SeekDir(dirp, e->offset);
1095                         return True;
1096                 }
1097         }
1098         for (i = NAME_CACHE_SIZE-1; i > dirp->name_cache_index; i--) {
1099                 struct name_cache_entry *e = &dirp->name_cache[i];
1100                 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1101                         *poffset = e->offset;
1102                         SeekDir(dirp, e->offset);
1103                         return True;
1104                 }
1105         }
1106
1107         /* Not found in the name cache. Rewind directory and start from scratch. */
1108         SMB_VFS_REWINDDIR(conn, dirp->dir);
1109         *poffset = 0;
1110         while ((entry = ReadDirName(dirp, poffset))) {
1111                 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
1112                         return True;
1113                 }
1114         }
1115         return False;
1116 }