r6169: Fix bug #2563. Infinite loop on non-existant file with findnext.
[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         /* In case sensitive mode we don't search - we know if it doesn't exist 
577            with a stat we will fail. */
578
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;
583                 return NULL;
584         } else {
585                 dptr->has_wild = True;
586                 return dptr_normal_ReadDirName(dptr, poffset, pst);
587         }
588 }
589
590 /****************************************************************************
591  Search for a file by name, skipping veto'ed and not visible files.
592 ****************************************************************************/
593
594 BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
595 {
596         ZERO_STRUCTP(pst);
597
598         if (!dptr->has_wild && (dptr->dir_hnd->offset == -1)) {
599                 /* This is a singleton directory and we're already at the end. */
600                 *poffset = -1;
601                 return False;
602         }
603
604         if (SearchDir(dptr->dir_hnd, name, poffset)) {
605                 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
606                         return True;
607                 }
608         }
609         return False;
610 }
611
612 /****************************************************************************
613  Fill the 5 byte server reserved dptr field.
614 ****************************************************************************/
615
616 BOOL dptr_fill(char *buf1,unsigned int key)
617 {
618         unsigned char *buf = (unsigned char *)buf1;
619         struct dptr_struct *dptr = dptr_get(key, False);
620         uint32 offset;
621         if (!dptr) {
622                 DEBUG(1,("filling null dirptr %d\n",key));
623                 return(False);
624         }
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));
628         buf[0] = key;
629         SIVAL(buf,1,offset | DPTR_MASK);
630         return(True);
631 }
632
633 /****************************************************************************
634  Fetch the dir ptr and seek it given the 5 byte server field.
635 ****************************************************************************/
636
637 struct dptr_struct *dptr_fetch(char *buf,int *num)
638 {
639         unsigned int key = *(unsigned char *)buf;
640         struct dptr_struct *dptr = dptr_get(key, False);
641         uint32 offset;
642
643         if (!dptr) {
644                 DEBUG(3,("fetched null dirptr %d\n",key));
645                 return(NULL);
646         }
647         *num = 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));
652         return(dptr);
653 }
654
655 /****************************************************************************
656  Fetch the dir ptr.
657 ****************************************************************************/
658
659 struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
660 {
661         struct dptr_struct *dptr  = dptr_get(dptr_num, False);
662
663         if (!dptr) {
664                 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
665                 return(NULL);
666         }
667         DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
668         return(dptr);
669 }
670
671 /****************************************************************************
672  Check a filetype for being valid.
673 ****************************************************************************/
674
675 BOOL dir_check_ftype(connection_struct *conn,int mode,int dirtype)
676 {
677         int mask;
678
679         /* Check the "may have" search bits. */
680         if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
681                 return False;
682
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 */
687         if(mask) {
688                 if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask)   /* check if matching attribute present */
689                         return True;
690                 else
691                         return False;
692         }
693
694         return True;
695 }
696
697 static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask)
698 {
699         mangle_map(filename,True,False,SNUM(conn));
700         return mask_match_search(filename,mask,False);
701 }
702
703 /****************************************************************************
704  Get an 8.3 directory entry.
705 ****************************************************************************/
706
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)
709 {
710         const char *dname;
711         BOOL found = False;
712         SMB_STRUCT_STAT sbuf;
713         pstring path;
714         pstring pathreal;
715         pstring filename;
716         BOOL needslash;
717
718         *path = *pathreal = *filename = 0;
719
720         needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
721
722         if (!conn->dirptr)
723                 return(False);
724
725         while (!found) {
726                 long curoff = dptr_TellDir(conn->dirptr);
727                 dname = dptr_ReadDirName(conn->dirptr, &curoff, &sbuf);
728
729                 DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
730                         (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
731       
732                 if (dname == NULL) 
733                         return(False);
734       
735                 pstrcpy(filename,dname);      
736
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
740                 */
741                 if ((strcmp(mask,"*.*") == 0) ||
742                     mask_match_search(filename,mask,False) ||
743                     mangle_mask_match(conn,filename,mask)) {
744
745                         if (!mangle_is_8_3(filename, False))
746                                 mangle_map(filename,True,False,SNUM(conn));
747
748                         pstrcpy(fname,filename);
749                         *path = 0;
750                         pstrcpy(path,conn->dirpath);
751                         if(needslash)
752                                 pstrcat(path,"/");
753                         pstrcpy(pathreal,path);
754                         pstrcat(path,fname);
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) ));
758                                 continue;
759                         }
760           
761                         *mode = dos_mode(conn,pathreal,&sbuf);
762
763                         if (!dir_check_ftype(conn,*mode,dirtype)) {
764                                 DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype));
765                                 continue;
766                         }
767
768                         *size = sbuf.st_size;
769                         *date = sbuf.st_mtime;
770
771                         DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
772
773                         found = True;
774                 }
775         }
776
777         return(found);
778 }
779
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 ********************************************************************/
785
786 static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
787 {
788         extern struct current_user current_user;
789         SEC_DESC *psd = NULL;
790         size_t sd_size;
791         files_struct *fsp;
792         int smb_action;
793         NTSTATUS status;
794         uint32 access_granted;
795
796         /*
797          * If user is a member of the Admin group
798          * we never hide files from them.
799          */
800
801         if (conn->admin_user)
802                 return True;
803
804         /* If we can't stat it does not show it */
805         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
806                 return False;
807
808         /* Pseudo-open the file (note - no fd's created). */
809
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),
812                         &smb_action);
813         else
814                 fsp = open_file_stat(conn, name, pst);
815
816         if (!fsp)
817                 return False;
818
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);
823
824         /* No access if SD get failed. */
825         if (!sd_size)
826                 return False;
827
828         return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA,
829                                  &access_granted, &status);
830 }
831
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 ********************************************************************/
838
839 static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
840 {
841         extern struct current_user current_user;
842         SEC_DESC *psd = NULL;
843         size_t sd_size;
844         files_struct *fsp;
845         int smb_action;
846         int access_mode;
847         NTSTATUS status;
848         uint32 access_granted;
849
850         /*
851          * If user is a member of the Admin group
852          * we never hide files from them.
853          */
854
855         if (conn->admin_user)
856                 return True;
857
858         /* If we can't stat it does not show it */
859         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
860                 return False;
861
862         /* Pseudo-open the file (note - no fd's created). */
863
864         if(S_ISDIR(pst->st_mode))       
865                 return True;
866         else
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);
870
871         if (!fsp)
872                 return False;
873
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);
878
879         /* No access if SD get failed. */
880         if (!sd_size)
881                 return False;
882
883         return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA,
884                                  &access_granted, &status);
885 }
886
887 /*******************************************************************
888   Is a file a "special" type ?
889 ********************************************************************/
890
891 static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
892 {
893         /*
894          * If user is a member of the Admin group
895          * we never hide files from them.
896          */
897
898         if (conn->admin_user)
899                 return False;
900
901         /* If we can't stat it does not show it */
902         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
903                 return True;
904
905         if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
906                 return False;
907
908         return True;
909 }
910
911 /*******************************************************************
912  Should the file be seen by the client ?
913 ********************************************************************/
914
915 BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, BOOL use_veto)
916 {
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));
920
921         ZERO_STRUCTP(pst);
922
923         if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
924                 return True; /* . and .. are always visible. */
925         }
926
927         /* If it's a vetoed file, pretend it doesn't even exist */
928         if (use_veto && IS_VETO_PATH(conn, name)) {
929                 return False;
930         }
931
932         if (hide_unreadable || hide_unwriteable || hide_special) {
933                 char *entry = NULL;
934
935                 if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
936                         return False;
937                 }
938                 /* Honour _hide unreadable_ option */
939                 if (hide_unreadable && !user_can_read_file(conn, entry, pst)) {
940                         SAFE_FREE(entry);
941                         return False;
942                 }
943                 /* Honour _hide unwriteable_ option */
944                 if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
945                         SAFE_FREE(entry);
946                         return False;
947                 }
948                 /* Honour _hide_special_ option */
949                 if (hide_special && !file_is_special(conn, entry, pst)) {
950                         SAFE_FREE(entry);
951                         return False;
952                 }
953                 SAFE_FREE(entry);
954         }
955         return True;
956 }
957
958 /*******************************************************************
959  Open a directory.
960 ********************************************************************/
961
962 struct smb_Dir *OpenDir(connection_struct *conn, const char *name)
963 {
964         struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir);
965         if (!dirp) {
966                 return NULL;
967         }
968         ZERO_STRUCTP(dirp);
969
970         dirp->conn = conn;
971
972         dirp->dir_path = SMB_STRDUP(name);
973         if (!dirp->dir_path) {
974                 goto fail;
975         }
976         dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path);
977         if (!dirp->dir) {
978                 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) ));
979                 goto fail;
980         }
981
982         dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, NAME_CACHE_SIZE);
983         if (!dirp->name_cache) {
984                 goto fail;
985         }
986
987         dirhandles_open++;
988         return dirp;
989
990   fail:
991
992         if (dirp) {
993                 if (dirp->dir) {
994                         SMB_VFS_CLOSEDIR(conn,dirp->dir);
995                 }
996                 SAFE_FREE(dirp->dir_path);
997                 SAFE_FREE(dirp->name_cache);
998                 SAFE_FREE(dirp);
999         }
1000         return NULL;
1001 }
1002
1003
1004 /*******************************************************************
1005  Close a directory.
1006 ********************************************************************/
1007
1008 int CloseDir(struct smb_Dir *dirp)
1009 {
1010         int i, ret = 0;
1011
1012         if (dirp->dir) {
1013                 ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1014         }
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);
1019                 }
1020         }
1021         SAFE_FREE(dirp->name_cache);
1022         SAFE_FREE(dirp);
1023         dirhandles_open--;
1024         return ret;
1025 }
1026
1027 /*******************************************************************
1028  Read from a directory. Also return current offset.
1029  Don't check for veto or invisible files.
1030 ********************************************************************/
1031
1032 const char *ReadDirName(struct smb_Dir *dirp, long *poffset)
1033 {
1034         const char *n;
1035         connection_struct *conn = dirp->conn;
1036
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) {
1042                         return NULL;
1043                 }
1044                 dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE;
1045
1046                 e = &dirp->name_cache[dirp->name_cache_index];
1047                 SAFE_FREE(e->name);
1048                 e->name = SMB_STRDUP(n);
1049                 *poffset = e->offset= dirp->offset;
1050                 return e->name;
1051         }
1052         dirp->offset = -1;
1053         return NULL;
1054 }
1055
1056 /*******************************************************************
1057  Seek a dir.
1058 ********************************************************************/
1059
1060 void SeekDir(struct smb_Dir *dirp, long offset)
1061 {
1062         if (offset != dirp->offset) {
1063                 SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1064                 dirp->offset = offset;
1065         }
1066 }
1067
1068 /*******************************************************************
1069  Tell a dir position.
1070 ********************************************************************/
1071
1072 long TellDir(struct smb_Dir *dirp)
1073 {
1074         return(dirp->offset);
1075 }
1076
1077 /*******************************************************************
1078  Find an entry by name. Leave us at the offset after it.
1079  Don't check for veto or invisible files.
1080 ********************************************************************/
1081
1082 BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1083 {
1084         int i;
1085         const char *entry;
1086         connection_struct *conn = dirp->conn;
1087
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);
1094                         return True;
1095                 }
1096         }
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);
1102                         return True;
1103                 }
1104         }
1105
1106         /* Not found in the name cache. Rewind directory and start from scratch. */
1107         SMB_VFS_REWINDDIR(conn, dirp->dir);
1108         *poffset = 0;
1109         while ((entry = ReadDirName(dirp, poffset))) {
1110                 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
1111                         return True;
1112                 }
1113         }
1114         return False;
1115 }