r6548: Fix bug #2622 - remove DPTR_MASK as it makes no sense.
[metze/samba/wip.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 = (uint32)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);
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         long seekoff;
645
646         if (!dptr) {
647                 DEBUG(3,("fetched null dirptr %d\n",key));
648                 return(NULL);
649         }
650         *num = key;
651         offset = IVAL(buf,1);
652         if (offset == (uint32)-1) {
653                 seekoff = -1;
654         } else {
655                 seekoff = (long)offset;
656         }
657         SeekDir(dptr->dir_hnd,seekoff);
658         DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
659                 key,dptr_path(key),(int)seekoff));
660         return(dptr);
661 }
662
663 /****************************************************************************
664  Fetch the dir ptr.
665 ****************************************************************************/
666
667 struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
668 {
669         struct dptr_struct *dptr  = dptr_get(dptr_num, False);
670
671         if (!dptr) {
672                 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
673                 return(NULL);
674         }
675         DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
676         return(dptr);
677 }
678
679 /****************************************************************************
680  Check a filetype for being valid.
681 ****************************************************************************/
682
683 BOOL dir_check_ftype(connection_struct *conn,int mode,int dirtype)
684 {
685         int mask;
686
687         /* Check the "may have" search bits. */
688         if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
689                 return False;
690
691         /* Check the "must have" bits, which are the may have bits shifted eight */
692         /* If must have bit is set, the file/dir can not be returned in search unless the matching
693                 file attribute is set */
694         mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */
695         if(mask) {
696                 if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask)   /* check if matching attribute present */
697                         return True;
698                 else
699                         return False;
700         }
701
702         return True;
703 }
704
705 static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask)
706 {
707         mangle_map(filename,True,False,SNUM(conn));
708         return mask_match_search(filename,mask,False);
709 }
710
711 /****************************************************************************
712  Get an 8.3 directory entry.
713 ****************************************************************************/
714
715 BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname,
716                    SMB_OFF_T *size,int *mode,time_t *date,BOOL check_descend)
717 {
718         const char *dname;
719         BOOL found = False;
720         SMB_STRUCT_STAT sbuf;
721         pstring path;
722         pstring pathreal;
723         pstring filename;
724         BOOL needslash;
725
726         *path = *pathreal = *filename = 0;
727
728         needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
729
730         if (!conn->dirptr)
731                 return(False);
732
733         while (!found) {
734                 long curoff = dptr_TellDir(conn->dirptr);
735                 dname = dptr_ReadDirName(conn->dirptr, &curoff, &sbuf);
736
737                 DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
738                         (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
739       
740                 if (dname == NULL) 
741                         return(False);
742       
743                 pstrcpy(filename,dname);      
744
745                 /* notice the special *.* handling. This appears to be the only difference
746                         between the wildcard handling in this routine and in the trans2 routines.
747                         see masktest for a demo
748                 */
749                 if ((strcmp(mask,"*.*") == 0) ||
750                     mask_match_search(filename,mask,False) ||
751                     mangle_mask_match(conn,filename,mask)) {
752
753                         if (!mangle_is_8_3(filename, False))
754                                 mangle_map(filename,True,False,SNUM(conn));
755
756                         pstrcpy(fname,filename);
757                         *path = 0;
758                         pstrcpy(path,conn->dirpath);
759                         if(needslash)
760                                 pstrcat(path,"/");
761                         pstrcpy(pathreal,path);
762                         pstrcat(path,fname);
763                         pstrcat(pathreal,dname);
764                         if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
765                                 DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) ));
766                                 continue;
767                         }
768           
769                         *mode = dos_mode(conn,pathreal,&sbuf);
770
771                         if (!dir_check_ftype(conn,*mode,dirtype)) {
772                                 DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype));
773                                 continue;
774                         }
775
776                         *size = sbuf.st_size;
777                         *date = sbuf.st_mtime;
778
779                         DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
780
781                         found = True;
782                 }
783         }
784
785         return(found);
786 }
787
788 /*******************************************************************
789  Check to see if a user can read a file. This is only approximate,
790  it is used as part of the "hide unreadable" option. Don't
791  use it for anything security sensitive.
792 ********************************************************************/
793
794 static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
795 {
796         SEC_DESC *psd = NULL;
797         size_t sd_size;
798         files_struct *fsp;
799         int smb_action;
800         NTSTATUS status;
801         uint32 access_granted;
802
803         /*
804          * If user is a member of the Admin group
805          * we never hide files from them.
806          */
807
808         if (conn->admin_user)
809                 return True;
810
811         /* If we can't stat it does not show it */
812         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
813                 return False;
814
815         /* Pseudo-open the file (note - no fd's created). */
816
817         if(S_ISDIR(pst->st_mode))       
818                  fsp = open_directory(conn, name, pst, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
819                         &smb_action);
820         else
821                 fsp = open_file_stat(conn, name, pst);
822
823         if (!fsp)
824                 return False;
825
826         /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
827         sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd,
828                         (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
829         close_file(fsp, True);
830
831         /* No access if SD get failed. */
832         if (!sd_size)
833                 return False;
834
835         return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA,
836                                  &access_granted, &status);
837 }
838
839 /*******************************************************************
840  Check to see if a user can write a file (and only files, we do not
841  check dirs on this one). This is only approximate,
842  it is used as part of the "hide unwriteable" option. Don't
843  use it for anything security sensitive.
844 ********************************************************************/
845
846 static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
847 {
848         SEC_DESC *psd = NULL;
849         size_t sd_size;
850         files_struct *fsp;
851         int smb_action;
852         int access_mode;
853         NTSTATUS status;
854         uint32 access_granted;
855
856         /*
857          * If user is a member of the Admin group
858          * we never hide files from them.
859          */
860
861         if (conn->admin_user)
862                 return True;
863
864         /* If we can't stat it does not show it */
865         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
866                 return False;
867
868         /* Pseudo-open the file (note - no fd's created). */
869
870         if(S_ISDIR(pst->st_mode))       
871                 return True;
872         else
873                 fsp = open_file_shared1(conn, name, pst, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE),
874                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY,
875                         &access_mode, &smb_action);
876
877         if (!fsp)
878                 return False;
879
880         /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
881         sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd,
882                         (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
883         close_file(fsp, False);
884
885         /* No access if SD get failed. */
886         if (!sd_size)
887                 return False;
888
889         return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA,
890                                  &access_granted, &status);
891 }
892
893 /*******************************************************************
894   Is a file a "special" type ?
895 ********************************************************************/
896
897 static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
898 {
899         /*
900          * If user is a member of the Admin group
901          * we never hide files from them.
902          */
903
904         if (conn->admin_user)
905                 return False;
906
907         /* If we can't stat it does not show it */
908         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
909                 return True;
910
911         if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
912                 return False;
913
914         return True;
915 }
916
917 /*******************************************************************
918  Should the file be seen by the client ?
919 ********************************************************************/
920
921 BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, BOOL use_veto)
922 {
923         BOOL hide_unreadable = lp_hideunreadable(SNUM(conn));
924         BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
925         BOOL hide_special = lp_hide_special_files(SNUM(conn));
926
927         ZERO_STRUCTP(pst);
928
929         if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
930                 return True; /* . and .. are always visible. */
931         }
932
933         /* If it's a vetoed file, pretend it doesn't even exist */
934         if (use_veto && IS_VETO_PATH(conn, name)) {
935                 return False;
936         }
937
938         if (hide_unreadable || hide_unwriteable || hide_special) {
939                 char *entry = NULL;
940
941                 if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
942                         return False;
943                 }
944                 /* Honour _hide unreadable_ option */
945                 if (hide_unreadable && !user_can_read_file(conn, entry, pst)) {
946                         SAFE_FREE(entry);
947                         return False;
948                 }
949                 /* Honour _hide unwriteable_ option */
950                 if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
951                         SAFE_FREE(entry);
952                         return False;
953                 }
954                 /* Honour _hide_special_ option */
955                 if (hide_special && file_is_special(conn, entry, pst)) {
956                         SAFE_FREE(entry);
957                         return False;
958                 }
959                 SAFE_FREE(entry);
960         }
961         return True;
962 }
963
964 /*******************************************************************
965  Open a directory.
966 ********************************************************************/
967
968 struct smb_Dir *OpenDir(connection_struct *conn, const char *name)
969 {
970         struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir);
971         if (!dirp) {
972                 return NULL;
973         }
974         ZERO_STRUCTP(dirp);
975
976         dirp->conn = conn;
977
978         dirp->dir_path = SMB_STRDUP(name);
979         if (!dirp->dir_path) {
980                 goto fail;
981         }
982         dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path);
983         if (!dirp->dir) {
984                 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) ));
985                 goto fail;
986         }
987
988         dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, NAME_CACHE_SIZE);
989         if (!dirp->name_cache) {
990                 goto fail;
991         }
992
993         dirhandles_open++;
994         return dirp;
995
996   fail:
997
998         if (dirp) {
999                 if (dirp->dir) {
1000                         SMB_VFS_CLOSEDIR(conn,dirp->dir);
1001                 }
1002                 SAFE_FREE(dirp->dir_path);
1003                 SAFE_FREE(dirp->name_cache);
1004                 SAFE_FREE(dirp);
1005         }
1006         return NULL;
1007 }
1008
1009
1010 /*******************************************************************
1011  Close a directory.
1012 ********************************************************************/
1013
1014 int CloseDir(struct smb_Dir *dirp)
1015 {
1016         int i, ret = 0;
1017
1018         if (dirp->dir) {
1019                 ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1020         }
1021         SAFE_FREE(dirp->dir_path);
1022         if (dirp->name_cache) {
1023                 for (i = 0; i < NAME_CACHE_SIZE; i++) {
1024                         SAFE_FREE(dirp->name_cache[i].name);
1025                 }
1026         }
1027         SAFE_FREE(dirp->name_cache);
1028         SAFE_FREE(dirp);
1029         dirhandles_open--;
1030         return ret;
1031 }
1032
1033 /*******************************************************************
1034  Read from a directory. Also return current offset.
1035  Don't check for veto or invisible files.
1036 ********************************************************************/
1037
1038 const char *ReadDirName(struct smb_Dir *dirp, long *poffset)
1039 {
1040         const char *n;
1041         connection_struct *conn = dirp->conn;
1042
1043         SeekDir(dirp, *poffset);
1044         while ((n = vfs_readdirname(conn, dirp->dir))) {
1045                 struct name_cache_entry *e;
1046                 dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1047                 dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE;
1048                 e = &dirp->name_cache[dirp->name_cache_index];
1049                 SAFE_FREE(e->name);
1050                 e->name = SMB_STRDUP(n);
1051                 *poffset = e->offset= dirp->offset;
1052                 return e->name;
1053         }
1054         dirp->offset = -1;
1055         return NULL;
1056 }
1057
1058 /*******************************************************************
1059  Seek a dir.
1060 ********************************************************************/
1061
1062 void SeekDir(struct smb_Dir *dirp, long offset)
1063 {
1064         if (offset != dirp->offset) {
1065                 SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1066                 dirp->offset = offset;
1067         }
1068 }
1069
1070 /*******************************************************************
1071  Tell a dir position.
1072 ********************************************************************/
1073
1074 long TellDir(struct smb_Dir *dirp)
1075 {
1076         return(dirp->offset);
1077 }
1078
1079 /*******************************************************************
1080  Find an entry by name. Leave us at the offset after it.
1081  Don't check for veto or invisible files.
1082 ********************************************************************/
1083
1084 BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1085 {
1086         int i;
1087         const char *entry;
1088         connection_struct *conn = dirp->conn;
1089
1090         /* Search back in the name cache. */
1091         for (i = dirp->name_cache_index; i >= 0; i--) {
1092                 struct name_cache_entry *e = &dirp->name_cache[i];
1093                 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1094                         *poffset = e->offset;
1095                         SeekDir(dirp, e->offset);
1096                         return True;
1097                 }
1098         }
1099         for (i = NAME_CACHE_SIZE-1; i > dirp->name_cache_index; i--) {
1100                 struct name_cache_entry *e = &dirp->name_cache[i];
1101                 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1102                         *poffset = e->offset;
1103                         SeekDir(dirp, e->offset);
1104                         return True;
1105                 }
1106         }
1107
1108         /* Not found in the name cache. Rewind directory and start from scratch. */
1109         SMB_VFS_REWINDDIR(conn, dirp->dir);
1110         *poffset = 0;
1111         while ((entry = ReadDirName(dirp, poffset))) {
1112                 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
1113                         return True;
1114                 }
1115         }
1116         return False;
1117 }