r6225: get rid of warnings from my compiler about nested externs
[abartlet/samba.git/.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 extern struct current_user current_user;
28
29 /* Make directory handle internals available. */
30
31 #define NAME_CACHE_SIZE 100
32
33 struct name_cache_entry {
34         char *name;
35         long offset;
36 };
37
38 struct smb_Dir {
39         connection_struct *conn;
40         DIR *dir;
41         long offset;
42         char *dir_path;
43         struct name_cache_entry *name_cache;
44         unsigned int name_cache_index;
45 };
46
47 struct dptr_struct {
48         struct dptr_struct *next, *prev;
49         int dnum;
50         uint16 spid;
51         struct connection_struct *conn;
52         struct smb_Dir *dir_hnd;
53         BOOL expect_close;
54         char *wcard;
55         uint16 attr;
56         char *path;
57         BOOL has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
58 };
59
60 static struct bitmap *dptr_bmap;
61 static struct dptr_struct *dirptrs;
62 static int dirhandles_open = 0;
63
64 #define INVALID_DPTR_KEY (-3)
65
66 /****************************************************************************
67  Initialise the dir bitmap.
68 ****************************************************************************/
69
70 void init_dptrs(void)
71 {
72         static BOOL dptrs_init=False;
73
74         if (dptrs_init)
75                 return;
76
77         dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES);
78
79         if (!dptr_bmap)
80                 exit_server("out of memory in init_dptrs");
81
82         dptrs_init = True;
83 }
84
85 /****************************************************************************
86  Idle a dptr - the directory is closed but the control info is kept.
87 ****************************************************************************/
88
89 static void dptr_idle(struct dptr_struct *dptr)
90 {
91         if (dptr->dir_hnd) {
92                 DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
93                 CloseDir(dptr->dir_hnd);
94                 dptr->dir_hnd = NULL;
95         }
96 }
97
98 /****************************************************************************
99  Idle the oldest dptr.
100 ****************************************************************************/
101
102 static void dptr_idleoldest(void)
103 {
104         struct dptr_struct *dptr;
105
106         /*
107          * Go to the end of the list.
108          */
109         for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
110                 ;
111
112         if(!dptr) {
113                 DEBUG(0,("No dptrs available to idle ?\n"));
114                 return;
115         }
116
117         /*
118          * Idle the oldest pointer.
119          */
120
121         for(; dptr; dptr = dptr->prev) {
122                 if (dptr->dir_hnd) {
123                         dptr_idle(dptr);
124                         return;
125                 }
126         }
127 }
128
129 /****************************************************************************
130  Get the struct dptr_struct for a dir index.
131 ****************************************************************************/
132
133 static struct dptr_struct *dptr_get(int key, BOOL forclose)
134 {
135         struct dptr_struct *dptr;
136
137         for(dptr = dirptrs; dptr; dptr = dptr->next) {
138                 if(dptr->dnum == key) {
139                         if (!forclose && !dptr->dir_hnd) {
140                                 if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
141                                         dptr_idleoldest();
142                                 DEBUG(4,("dptr_get: Reopening dptr key %d\n",key));
143                                 if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path))) {
144                                         DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path,
145                                                 strerror(errno)));
146                                         return False;
147                                 }
148                         }
149                         DLIST_PROMOTE(dirptrs,dptr);
150                         return dptr;
151                 }
152         }
153         return(NULL);
154 }
155
156 /****************************************************************************
157  Get the dir path for a dir index.
158 ****************************************************************************/
159
160 char *dptr_path(int key)
161 {
162         struct dptr_struct *dptr = dptr_get(key, False);
163         if (dptr)
164                 return(dptr->path);
165         return(NULL);
166 }
167
168 /****************************************************************************
169  Get the dir wcard for a dir index.
170 ****************************************************************************/
171
172 char *dptr_wcard(int key)
173 {
174         struct dptr_struct *dptr = dptr_get(key, False);
175         if (dptr)
176                 return(dptr->wcard);
177         return(NULL);
178 }
179
180 /****************************************************************************
181  Get the dir attrib for a dir index.
182 ****************************************************************************/
183
184 uint16 dptr_attr(int key)
185 {
186         struct dptr_struct *dptr = dptr_get(key, False);
187         if (dptr)
188                 return(dptr->attr);
189         return(0);
190 }
191
192 /****************************************************************************
193  Set the dir wcard for a dir index.
194  Returns 0 on ok, 1 on fail.
195 ****************************************************************************/
196
197 BOOL dptr_set_wcard_and_attributes(int key, const char *wcard, uint16 attr)
198 {
199         struct dptr_struct *dptr = dptr_get(key, False);
200
201         if (dptr) {
202                 dptr->attr = attr;
203                 dptr->wcard = SMB_STRDUP(wcard);
204                 if (!dptr->wcard)
205                         return False;
206                 if (wcard[0] == '.' && wcard[1] == 0) {
207                         dptr->has_wild = True;
208                 } else {
209                         dptr->has_wild = ms_has_wild(wcard);
210                 }
211                 return True;
212         }
213         return False;
214 }
215
216 /****************************************************************************
217  Close a dptr (internal func).
218 ****************************************************************************/
219
220 static void dptr_close_internal(struct dptr_struct *dptr)
221 {
222         DEBUG(4,("closing dptr key %d\n",dptr->dnum));
223
224         DLIST_REMOVE(dirptrs, dptr);
225
226         /* 
227          * Free the dnum in the bitmap. Remember the dnum value is always 
228          * biased by one with respect to the bitmap.
229          */
230
231         if(bitmap_query( dptr_bmap, dptr->dnum - 1) != True) {
232                 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
233                         dptr->dnum ));
234         }
235
236         bitmap_clear(dptr_bmap, dptr->dnum - 1);
237
238         if (dptr->dir_hnd) {
239                 CloseDir(dptr->dir_hnd);
240         }
241
242         /* Lanman 2 specific code */
243         SAFE_FREE(dptr->wcard);
244         string_set(&dptr->path,"");
245         SAFE_FREE(dptr);
246 }
247
248 /****************************************************************************
249  Close a dptr given a key.
250 ****************************************************************************/
251
252 void dptr_close(int *key)
253 {
254         struct dptr_struct *dptr;
255
256         if(*key == INVALID_DPTR_KEY)
257                 return;
258
259         /* OS/2 seems to use -1 to indicate "close all directories" */
260         if (*key == -1) {
261                 struct dptr_struct *next;
262                 for(dptr = dirptrs; dptr; dptr = next) {
263                         next = dptr->next;
264                         dptr_close_internal(dptr);
265                 }
266                 *key = INVALID_DPTR_KEY;
267                 return;
268         }
269
270         dptr = dptr_get(*key, True);
271
272         if (!dptr) {
273                 DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
274                 return;
275         }
276
277         dptr_close_internal(dptr);
278
279         *key = INVALID_DPTR_KEY;
280 }
281
282 /****************************************************************************
283  Close all dptrs for a cnum.
284 ****************************************************************************/
285
286 void dptr_closecnum(connection_struct *conn)
287 {
288         struct dptr_struct *dptr, *next;
289         for(dptr = dirptrs; dptr; dptr = next) {
290                 next = dptr->next;
291                 if (dptr->conn == conn)
292                         dptr_close_internal(dptr);
293         }
294 }
295
296 /****************************************************************************
297  Idle all dptrs for a cnum.
298 ****************************************************************************/
299
300 void dptr_idlecnum(connection_struct *conn)
301 {
302         struct dptr_struct *dptr;
303         for(dptr = dirptrs; dptr; dptr = dptr->next) {
304                 if (dptr->conn == conn && dptr->dir_hnd)
305                         dptr_idle(dptr);
306         }
307 }
308
309 /****************************************************************************
310  Close a dptr that matches a given path, only if it matches the spid also.
311 ****************************************************************************/
312
313 void dptr_closepath(char *path,uint16 spid)
314 {
315         struct dptr_struct *dptr, *next;
316         for(dptr = dirptrs; dptr; dptr = next) {
317                 next = dptr->next;
318                 if (spid == dptr->spid && strequal(dptr->path,path))
319                         dptr_close_internal(dptr);
320         }
321 }
322
323 /****************************************************************************
324  Try and close the oldest handle not marked for
325  expect close in the hope that the client has
326  finished with that one.
327 ****************************************************************************/
328
329 static void dptr_close_oldest(BOOL old)
330 {
331         struct dptr_struct *dptr;
332
333         /*
334          * Go to the end of the list.
335          */
336         for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
337                 ;
338
339         if(!dptr) {
340                 DEBUG(0,("No old dptrs available to close oldest ?\n"));
341                 return;
342         }
343
344         /*
345          * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
346          * does not have expect_close set. If 'old' is false, close
347          * one of the new dnum handles.
348          */
349
350         for(; dptr; dptr = dptr->prev) {
351                 if ((old && (dptr->dnum < 256) && !dptr->expect_close) ||
352                         (!old && (dptr->dnum > 255))) {
353                                 dptr_close_internal(dptr);
354                                 return;
355                 }
356         }
357 }
358
359 /****************************************************************************
360  Create a new dir ptr. If the flag old_handle is true then we must allocate
361  from the bitmap range 0 - 255 as old SMBsearch directory handles are only
362  one byte long. If old_handle is false we allocate from the range
363  256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
364  a directory handle is never zero.
365 ****************************************************************************/
366
367 int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid)
368 {
369         struct dptr_struct *dptr = NULL;
370         struct smb_Dir *dir_hnd;
371         const char *dir2;
372
373         DEBUG(5,("dptr_create dir=%s\n", path));
374
375         if (!check_name(path,conn))
376                 return(-2); /* Code to say use a unix error return code. */
377
378         /* use a const pointer from here on */
379         dir2 = path;
380         if (!*dir2)
381                 dir2 = ".";
382
383         dir_hnd = OpenDir(conn, dir2);
384         if (!dir_hnd) {
385                 return (-2);
386         }
387
388         string_set(&conn->dirpath,dir2);
389
390         if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
391                 dptr_idleoldest();
392
393         dptr = SMB_MALLOC_P(struct dptr_struct);
394         if(!dptr) {
395                 DEBUG(0,("malloc fail in dptr_create.\n"));
396                 CloseDir(dir_hnd);
397                 return -1;
398         }
399
400         ZERO_STRUCTP(dptr);
401
402         if(old_handle) {
403
404                 /*
405                  * This is an old-style SMBsearch request. Ensure the
406                  * value we return will fit in the range 1-255.
407                  */
408
409                 dptr->dnum = bitmap_find(dptr_bmap, 0);
410
411                 if(dptr->dnum == -1 || dptr->dnum > 254) {
412
413                         /*
414                          * Try and close the oldest handle not marked for
415                          * expect close in the hope that the client has
416                          * finished with that one.
417                          */
418
419                         dptr_close_oldest(True);
420
421                         /* Now try again... */
422                         dptr->dnum = bitmap_find(dptr_bmap, 0);
423                         if(dptr->dnum == -1 || dptr->dnum > 254) {
424                                 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
425                                 SAFE_FREE(dptr);
426                                 CloseDir(dir_hnd);
427                                 return -1;
428                         }
429                 }
430         } else {
431
432                 /*
433                  * This is a new-style trans2 request. Allocate from
434                  * a range that will return 256 - MAX_DIRECTORY_HANDLES.
435                  */
436
437                 dptr->dnum = bitmap_find(dptr_bmap, 255);
438
439                 if(dptr->dnum == -1 || dptr->dnum < 255) {
440
441                         /*
442                          * Try and close the oldest handle close in the hope that
443                          * the client has finished with that one. This will only
444                          * happen in the case of the Win98 client bug where it leaks
445                          * directory handles.
446                          */
447
448                         dptr_close_oldest(False);
449
450                         /* Now try again... */
451                         dptr->dnum = bitmap_find(dptr_bmap, 255);
452
453                         if(dptr->dnum == -1 || dptr->dnum < 255) {
454                                 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
455                                 SAFE_FREE(dptr);
456                                 CloseDir(dir_hnd);
457                                 return -1;
458                         }
459                 }
460         }
461
462         bitmap_set(dptr_bmap, dptr->dnum);
463
464         dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
465
466         string_set(&dptr->path,dir2);
467         dptr->conn = conn;
468         dptr->dir_hnd = dir_hnd;
469         dptr->spid = spid;
470         dptr->expect_close = expect_close;
471         dptr->wcard = NULL; /* Only used in lanman2 searches */
472         dptr->attr = 0; /* Only used in lanman2 searches */
473         dptr->has_wild = True; /* Only used in lanman2 searches */
474
475         DLIST_ADD(dirptrs, dptr);
476
477         DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
478                 dptr->dnum,path,expect_close));  
479
480         conn->dirptr = dptr;
481
482         return(dptr->dnum);
483 }
484
485
486 /****************************************************************************
487  Wrapper functions to access the lower level directory handles.
488 ****************************************************************************/
489
490 int dptr_CloseDir(struct dptr_struct *dptr)
491 {
492         return CloseDir(dptr->dir_hnd);
493 }
494
495 void dptr_SeekDir(struct dptr_struct *dptr, long offset)
496 {
497         SeekDir(dptr->dir_hnd, offset);
498 }
499
500 long dptr_TellDir(struct dptr_struct *dptr)
501 {
502         return TellDir(dptr->dir_hnd);
503 }
504
505 /****************************************************************************
506  Return the next visible file name, skipping veto'd and invisible files.
507 ****************************************************************************/
508
509 static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
510 {
511         /* Normal search for the next file. */
512         const char *name;
513         while ((name = ReadDirName(dptr->dir_hnd, poffset)) != NULL) {
514                 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
515                         return name;
516                 }
517         }
518         return NULL;
519 }
520
521 /****************************************************************************
522  Return the next visible file name, skipping veto'd and invisible files.
523 ****************************************************************************/
524
525 const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
526 {
527         pstring pathreal;
528
529         ZERO_STRUCTP(pst);
530
531         if (dptr->has_wild) {
532                 return dptr_normal_ReadDirName(dptr, poffset, pst);
533         }
534
535         /* If poffset is -1 then we know we returned this name before and we have
536            no wildcards. We're at the end of the directory. */
537         if (*poffset == -1) {
538                 return NULL;
539         }
540
541         /* We know the stored wcard contains no wildcard characters. See if we can match
542            with a stat call. If we can't, then set has_wild to true to
543            prevent us from doing this on every call. */
544
545         /* First check if it should be visible. */
546         if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard, pst, True)) {
547                 dptr->has_wild = True;
548                 return dptr_normal_ReadDirName(dptr, poffset, pst);
549         }
550
551         if (VALID_STAT(*pst)) {
552                 /* We need to set the underlying dir_hdn offset to -1 also as
553                    this function is usually called with the output from TellDir. */
554                 dptr->dir_hnd->offset = *poffset = -1;
555                 return dptr->wcard;
556         }
557
558         pstrcpy(pathreal,dptr->path);
559         pstrcat(pathreal,"/");
560         pstrcat(pathreal,dptr->wcard);
561
562         if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) {
563                 /* We need to set the underlying dir_hdn offset to -1 also as
564                    this function is usually called with the output from TellDir. */
565                 dptr->dir_hnd->offset = *poffset = -1;
566                 return dptr->wcard;
567         } else {
568                 /* If we get any other error than ENOENT or ENOTDIR
569                    then the file exists we just can't stat it. */
570                 if (errno != ENOENT && errno != ENOTDIR) {
571                         /* We need to set the underlying dir_hdn offset to -1 also as
572                            this function is usually called with the output from TellDir. */
573                         dptr->dir_hnd->offset = *poffset = -1;
574                         return dptr->wcard;
575                 }
576         }
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                 dptr->has_wild = True;
588                 return dptr_normal_ReadDirName(dptr, poffset, pst);
589         }
590 }
591
592 /****************************************************************************
593  Search for a file by name, skipping veto'ed and not visible files.
594 ****************************************************************************/
595
596 BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
597 {
598         ZERO_STRUCTP(pst);
599
600         if (!dptr->has_wild && (dptr->dir_hnd->offset == -1)) {
601                 /* This is a singleton directory and we're already at the end. */
602                 *poffset = -1;
603                 return False;
604         }
605
606         if (SearchDir(dptr->dir_hnd, name, poffset)) {
607                 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
608                         return True;
609                 }
610         }
611         return False;
612 }
613
614 /****************************************************************************
615  Fill the 5 byte server reserved dptr field.
616 ****************************************************************************/
617
618 BOOL dptr_fill(char *buf1,unsigned int key)
619 {
620         unsigned char *buf = (unsigned char *)buf1;
621         struct dptr_struct *dptr = dptr_get(key, False);
622         uint32 offset;
623         if (!dptr) {
624                 DEBUG(1,("filling null dirptr %d\n",key));
625                 return(False);
626         }
627         offset = TellDir(dptr->dir_hnd);
628         DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
629                 (long)dptr->dir_hnd,(int)offset));
630         buf[0] = key;
631         SIVAL(buf,1,offset | DPTR_MASK);
632         return(True);
633 }
634
635 /****************************************************************************
636  Fetch the dir ptr and seek it given the 5 byte server field.
637 ****************************************************************************/
638
639 struct dptr_struct *dptr_fetch(char *buf,int *num)
640 {
641         unsigned int key = *(unsigned char *)buf;
642         struct dptr_struct *dptr = dptr_get(key, False);
643         uint32 offset;
644
645         if (!dptr) {
646                 DEBUG(3,("fetched null dirptr %d\n",key));
647                 return(NULL);
648         }
649         *num = key;
650         offset = IVAL(buf,1)&~DPTR_MASK;
651         SeekDir(dptr->dir_hnd,(long)offset);
652         DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
653                 key,dptr_path(key),offset));
654         return(dptr);
655 }
656
657 /****************************************************************************
658  Fetch the dir ptr.
659 ****************************************************************************/
660
661 struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
662 {
663         struct dptr_struct *dptr  = dptr_get(dptr_num, False);
664
665         if (!dptr) {
666                 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
667                 return(NULL);
668         }
669         DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
670         return(dptr);
671 }
672
673 /****************************************************************************
674  Check a filetype for being valid.
675 ****************************************************************************/
676
677 BOOL dir_check_ftype(connection_struct *conn,int mode,int dirtype)
678 {
679         int mask;
680
681         /* Check the "may have" search bits. */
682         if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
683                 return False;
684
685         /* Check the "must have" bits, which are the may have bits shifted eight */
686         /* If must have bit is set, the file/dir can not be returned in search unless the matching
687                 file attribute is set */
688         mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */
689         if(mask) {
690                 if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask)   /* check if matching attribute present */
691                         return True;
692                 else
693                         return False;
694         }
695
696         return True;
697 }
698
699 static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask)
700 {
701         mangle_map(filename,True,False,SNUM(conn));
702         return mask_match_search(filename,mask,False);
703 }
704
705 /****************************************************************************
706  Get an 8.3 directory entry.
707 ****************************************************************************/
708
709 BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname,
710                    SMB_OFF_T *size,int *mode,time_t *date,BOOL check_descend)
711 {
712         const char *dname;
713         BOOL found = False;
714         SMB_STRUCT_STAT sbuf;
715         pstring path;
716         pstring pathreal;
717         pstring filename;
718         BOOL needslash;
719
720         *path = *pathreal = *filename = 0;
721
722         needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
723
724         if (!conn->dirptr)
725                 return(False);
726
727         while (!found) {
728                 long curoff = dptr_TellDir(conn->dirptr);
729                 dname = dptr_ReadDirName(conn->dirptr, &curoff, &sbuf);
730
731                 DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
732                         (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
733       
734                 if (dname == NULL) 
735                         return(False);
736       
737                 pstrcpy(filename,dname);      
738
739                 /* notice the special *.* handling. This appears to be the only difference
740                         between the wildcard handling in this routine and in the trans2 routines.
741                         see masktest for a demo
742                 */
743                 if ((strcmp(mask,"*.*") == 0) ||
744                     mask_match_search(filename,mask,False) ||
745                     mangle_mask_match(conn,filename,mask)) {
746
747                         if (!mangle_is_8_3(filename, False))
748                                 mangle_map(filename,True,False,SNUM(conn));
749
750                         pstrcpy(fname,filename);
751                         *path = 0;
752                         pstrcpy(path,conn->dirpath);
753                         if(needslash)
754                                 pstrcat(path,"/");
755                         pstrcpy(pathreal,path);
756                         pstrcat(path,fname);
757                         pstrcat(pathreal,dname);
758                         if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
759                                 DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) ));
760                                 continue;
761                         }
762           
763                         *mode = dos_mode(conn,pathreal,&sbuf);
764
765                         if (!dir_check_ftype(conn,*mode,dirtype)) {
766                                 DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype));
767                                 continue;
768                         }
769
770                         *size = sbuf.st_size;
771                         *date = sbuf.st_mtime;
772
773                         DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
774
775                         found = True;
776                 }
777         }
778
779         return(found);
780 }
781
782 /*******************************************************************
783  Check to see if a user can read a file. This is only approximate,
784  it is used as part of the "hide unreadable" option. Don't
785  use it for anything security sensitive.
786 ********************************************************************/
787
788 static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
789 {
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         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 }