Added final Steve French patch for "required" attributes with old
[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 typedef struct _dptr_struct {
28         struct _dptr_struct *next, *prev;
29         int dnum;
30         uint16 spid;
31         connection_struct *conn;
32         void *ptr;
33         BOOL expect_close;
34         char *wcard; /* Field only used for trans2_ searches */
35         uint16 attr; /* Field only used for trans2_ searches */
36         char *path;
37 } dptr_struct;
38
39 static struct bitmap *dptr_bmap;
40 static dptr_struct *dirptrs;
41
42 static int dptrs_open = 0;
43
44 #define INVALID_DPTR_KEY (-3)
45
46 /****************************************************************************
47  Initialise the dir bitmap.
48 ****************************************************************************/
49
50 void init_dptrs(void)
51 {
52   static BOOL dptrs_init=False;
53
54   if (dptrs_init)
55     return;
56
57   dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES);
58
59   if (!dptr_bmap)
60     exit_server("out of memory in init_dptrs");
61
62   dptrs_init = True;
63 }
64
65 /****************************************************************************
66  Idle a dptr - the directory is closed but the control info is kept.
67 ****************************************************************************/
68
69 static void dptr_idle(dptr_struct *dptr)
70 {
71   if (dptr->ptr) {
72     DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
73     dptrs_open--;
74     CloseDir(dptr->ptr);
75     dptr->ptr = NULL;
76   }
77 }
78
79 /****************************************************************************
80  Idle the oldest dptr.
81 ****************************************************************************/
82
83 static void dptr_idleoldest(void)
84 {
85   dptr_struct *dptr;
86
87   /*
88    * Go to the end of the list.
89    */
90   for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
91     ;
92
93   if(!dptr) {
94     DEBUG(0,("No dptrs available to idle ?\n"));
95     return;
96   }
97
98   /*
99    * Idle the oldest pointer.
100    */
101
102   for(; dptr; dptr = dptr->prev) {
103     if (dptr->ptr) {
104       dptr_idle(dptr);
105       return;
106     }
107   }
108 }
109
110 /****************************************************************************
111  Get the dptr_struct for a dir index.
112 ****************************************************************************/
113
114 static dptr_struct *dptr_get(int key, BOOL forclose)
115 {
116   dptr_struct *dptr;
117
118   for(dptr = dirptrs; dptr; dptr = dptr->next) {
119     if(dptr->dnum == key) {
120       if (!forclose && !dptr->ptr) {
121         if (dptrs_open >= MAX_OPEN_DIRECTORIES)
122           dptr_idleoldest();
123         DEBUG(4,("Reopening dptr key %d\n",key));
124         if ((dptr->ptr = OpenDir(dptr->conn, dptr->path, True)))
125           dptrs_open++;
126       }
127       DLIST_PROMOTE(dirptrs,dptr);
128       return dptr;
129     }
130   }
131   return(NULL);
132 }
133
134 /****************************************************************************
135  Get the dptr ptr for a dir index.
136 ****************************************************************************/
137
138 static void *dptr_ptr(int key)
139 {
140   dptr_struct *dptr = dptr_get(key, False);
141
142   if (dptr)
143     return(dptr->ptr);
144   return(NULL);
145 }
146
147 /****************************************************************************
148  Get the dir path for a dir index.
149 ****************************************************************************/
150
151 char *dptr_path(int key)
152 {
153   dptr_struct *dptr = dptr_get(key, False);
154
155   if (dptr)
156     return(dptr->path);
157   return(NULL);
158 }
159
160 /****************************************************************************
161  Get the dir wcard for a dir index (lanman2 specific).
162 ****************************************************************************/
163
164 char *dptr_wcard(int key)
165 {
166   dptr_struct *dptr = dptr_get(key, False);
167
168   if (dptr)
169     return(dptr->wcard);
170   return(NULL);
171 }
172
173 /****************************************************************************
174  Set the dir wcard for a dir index (lanman2 specific).
175  Returns 0 on ok, 1 on fail.
176 ****************************************************************************/
177
178 BOOL dptr_set_wcard(int key, char *wcard)
179 {
180   dptr_struct *dptr = dptr_get(key, False);
181
182   if (dptr) {
183     dptr->wcard = wcard;
184     return True;
185   }
186   return False;
187 }
188
189 /****************************************************************************
190  Set the dir attrib for a dir index (lanman2 specific).
191  Returns 0 on ok, 1 on fail.
192 ****************************************************************************/
193
194 BOOL dptr_set_attr(int key, uint16 attr)
195 {
196   dptr_struct *dptr = dptr_get(key, False);
197
198   if (dptr) {
199     dptr->attr = attr;
200     return True;
201   }
202   return False;
203 }
204
205 /****************************************************************************
206  Get the dir attrib for a dir index (lanman2 specific)
207 ****************************************************************************/
208
209 uint16 dptr_attr(int key)
210 {
211   dptr_struct *dptr = dptr_get(key, False);
212
213   if (dptr)
214     return(dptr->attr);
215   return(0);
216 }
217
218 /****************************************************************************
219  Close a dptr (internal func).
220 ****************************************************************************/
221
222 static void dptr_close_internal(dptr_struct *dptr)
223 {
224   DEBUG(4,("closing dptr key %d\n",dptr->dnum));
225
226   DLIST_REMOVE(dirptrs, dptr);
227
228   /* 
229    * Free the dnum in the bitmap. Remember the dnum value is always 
230    * biased by one with respect to the bitmap.
231    */
232
233   if(bitmap_query( dptr_bmap, dptr->dnum - 1) != True) {
234     DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
235                         dptr->dnum ));
236   }
237
238   bitmap_clear(dptr_bmap, dptr->dnum - 1);
239
240   if (dptr->ptr) {
241     CloseDir(dptr->ptr);
242     dptrs_open--;
243   }
244
245   /* Lanman 2 specific code */
246   SAFE_FREE(dptr->wcard);
247   string_set(&dptr->path,"");
248   SAFE_FREE(dptr);
249 }
250
251 /****************************************************************************
252  Close a dptr given a key.
253 ****************************************************************************/
254
255 void dptr_close(int *key)
256 {
257   dptr_struct *dptr;
258
259   if(*key == INVALID_DPTR_KEY)
260     return;
261
262   /* OS/2 seems to use -1 to indicate "close all directories" */
263   if (*key == -1) {
264     dptr_struct *next;
265     for(dptr = dirptrs; dptr; dptr = next) {
266       next = dptr->next;
267       dptr_close_internal(dptr);
268     }
269     *key = INVALID_DPTR_KEY;
270     return;
271   }
272
273   dptr = dptr_get(*key, True);
274
275   if (!dptr) {
276     DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
277     return;
278   }
279
280   dptr_close_internal(dptr);
281
282   *key = INVALID_DPTR_KEY;
283 }
284
285 /****************************************************************************
286  Close all dptrs for a cnum.
287 ****************************************************************************/
288
289 void dptr_closecnum(connection_struct *conn)
290 {
291   dptr_struct *dptr, *next;
292   for(dptr = dirptrs; dptr; dptr = next) {
293     next = dptr->next;
294     if (dptr->conn == conn)
295       dptr_close_internal(dptr);
296   }
297 }
298
299 /****************************************************************************
300  Idle all dptrs for a cnum.
301 ****************************************************************************/
302
303 void dptr_idlecnum(connection_struct *conn)
304 {
305   dptr_struct *dptr;
306   for(dptr = dirptrs; dptr; dptr = dptr->next) {
307     if (dptr->conn == conn && dptr->ptr)
308       dptr_idle(dptr);
309   }
310 }
311
312 /****************************************************************************
313  Close a dptr that matches a given path, only if it matches the spid also.
314 ****************************************************************************/
315
316 void dptr_closepath(char *path,uint16 spid)
317 {
318   dptr_struct *dptr, *next;
319   for(dptr = dirptrs; dptr; dptr = next) {
320     next = dptr->next;
321     if (spid == dptr->spid && strequal(dptr->path,path))
322       dptr_close_internal(dptr);
323   }
324 }
325
326 /****************************************************************************
327  Start a directory listing.
328 ****************************************************************************/
329
330 static BOOL start_dir(connection_struct *conn,char *directory)
331 {
332   DEBUG(5,("start_dir dir=%s\n",directory));
333
334   if (!check_name(directory,conn))
335     return(False);
336   
337   if (! *directory)
338     directory = ".";
339
340   conn->dirptr = OpenDir(conn, directory, True);
341   if (conn->dirptr) {    
342     dptrs_open++;
343     string_set(&conn->dirpath,directory);
344     return(True);
345   }
346   
347   return(False);
348 }
349
350 /****************************************************************************
351  Try and close the oldest handle not marked for
352  expect close in the hope that the client has
353  finished with that one.
354 ****************************************************************************/
355
356 static void dptr_close_oldest(BOOL old)
357 {
358   dptr_struct *dptr;
359
360   /*
361    * Go to the end of the list.
362    */
363   for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
364     ;
365
366   if(!dptr) {
367     DEBUG(0,("No old dptrs available to close oldest ?\n"));
368     return;
369   }
370
371   /*
372    * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
373    * does not have expect_close set. If 'old' is false, close
374    * one of the new dnum handles.
375    */
376
377   for(; dptr; dptr = dptr->prev) {
378     if ((old && (dptr->dnum < 256) && !dptr->expect_close) ||
379         (!old && (dptr->dnum > 255))) {
380       dptr_close_internal(dptr);
381       return;
382     }
383   }
384 }
385
386 /****************************************************************************
387  Create a new dir ptr. If the flag old_handle is true then we must allocate
388  from the bitmap range 0 - 255 as old SMBsearch directory handles are only
389  one byte long. If old_handle is false we allocate from the range
390  256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
391  a directory handle is never zero. All the above is folklore taught to
392  me at Andrew's knee.... :-) :-). JRA.
393 ****************************************************************************/
394
395 int dptr_create(connection_struct *conn,char *path, BOOL old_handle, BOOL expect_close,uint16 spid)
396 {
397   dptr_struct *dptr;
398
399   if (!start_dir(conn,path))
400     return(-2); /* Code to say use a unix error return code. */
401
402   if (dptrs_open >= MAX_OPEN_DIRECTORIES)
403     dptr_idleoldest();
404
405   dptr = (dptr_struct *)malloc(sizeof(dptr_struct));
406   if(!dptr) {
407     DEBUG(0,("malloc fail in dptr_create.\n"));
408     return -1;
409   }
410
411   ZERO_STRUCTP(dptr);
412
413   if(old_handle) {
414
415     /*
416      * This is an old-style SMBsearch request. Ensure the
417      * value we return will fit in the range 1-255.
418      */
419
420     dptr->dnum = bitmap_find(dptr_bmap, 0);
421
422     if(dptr->dnum == -1 || dptr->dnum > 254) {
423
424       /*
425        * Try and close the oldest handle not marked for
426        * expect close in the hope that the client has
427        * finished with that one.
428        */
429
430       dptr_close_oldest(True);
431
432       /* Now try again... */
433       dptr->dnum = bitmap_find(dptr_bmap, 0);
434
435       if(dptr->dnum == -1 || dptr->dnum > 254) {
436         DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
437         SAFE_FREE(dptr);
438         return -1;
439       }
440     }
441   } else {
442
443     /*
444      * This is a new-style trans2 request. Allocate from
445      * a range that will return 256 - MAX_DIRECTORY_HANDLES.
446      */
447
448     dptr->dnum = bitmap_find(dptr_bmap, 255);
449
450     if(dptr->dnum == -1 || dptr->dnum < 255) {
451
452       /*
453        * Try and close the oldest handle close in the hope that
454        * the client has finished with that one. This will only
455        * happen in the case of the Win98 client bug where it leaks
456        * directory handles.
457        */
458
459       dptr_close_oldest(False);
460
461       /* Now try again... */
462       dptr->dnum = bitmap_find(dptr_bmap, 255);
463
464       if(dptr->dnum == -1 || dptr->dnum < 255) {
465         DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
466         SAFE_FREE(dptr);
467         return -1;
468       }
469     }
470   }
471
472   bitmap_set(dptr_bmap, dptr->dnum);
473
474   dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
475
476   dptr->ptr = conn->dirptr;
477   string_set(&dptr->path,path);
478   dptr->conn = conn;
479   dptr->spid = spid;
480   dptr->expect_close = expect_close;
481   dptr->wcard = NULL; /* Only used in lanman2 searches */
482   dptr->attr = 0; /* Only used in lanman2 searches */
483
484   DLIST_ADD(dirptrs, dptr);
485
486   DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
487            dptr->dnum,path,expect_close));  
488
489   return(dptr->dnum);
490 }
491
492 /****************************************************************************
493  Fill the 5 byte server reserved dptr field.
494 ****************************************************************************/
495
496 BOOL dptr_fill(char *buf1,unsigned int key)
497 {
498   unsigned char *buf = (unsigned char *)buf1;
499   void *p = dptr_ptr(key);
500   uint32 offset;
501   if (!p) {
502     DEBUG(1,("filling null dirptr %d\n",key));
503     return(False);
504   }
505   offset = TellDir(p);
506   DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
507            (long)p,(int)offset));
508   buf[0] = key;
509   SIVAL(buf,1,offset | DPTR_MASK);
510   return(True);
511 }
512
513 /****************************************************************************
514  Fetch the dir ptr and seek it given the 5 byte server field.
515 ****************************************************************************/
516
517 void *dptr_fetch(char *buf,int *num)
518 {
519   unsigned int key = *(unsigned char *)buf;
520   void *p = dptr_ptr(key);
521   uint32 offset;
522   if (!p) {
523     DEBUG(3,("fetched null dirptr %d\n",key));
524     return(NULL);
525   }
526   *num = key;
527   offset = IVAL(buf,1)&~DPTR_MASK;
528   SeekDir(p,offset);
529   DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
530            key,dptr_path(key),offset));
531   return(p);
532 }
533
534 /****************************************************************************
535  Fetch the dir ptr.
536 ****************************************************************************/
537
538 void *dptr_fetch_lanman2(int dptr_num)
539 {
540   void *p = dptr_ptr(dptr_num);
541
542   if (!p) {
543     DEBUG(3,("fetched null dirptr %d\n",dptr_num));
544     return(NULL);
545   }
546   DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
547   return(p);
548 }
549
550 /****************************************************************************
551  Check a filetype for being valid.
552 ****************************************************************************/
553
554 BOOL dir_check_ftype(connection_struct *conn,int mode,SMB_STRUCT_STAT *st,int dirtype)
555 {
556         int mask;
557
558         /* Check the "may have" search bits. */
559         if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
560                 return False;
561
562         /* Check the "must have" bits, which are the may have bits shifted eight */
563         /* If must have bit is set, the file/dir can not be returned in search unless the matching
564                 file attribute is set */
565         mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */
566         if(mask) {
567                 if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask)   /* check if matching attribute present */
568                         return True;
569                 else
570                         return False;
571         }
572
573         return True;
574 }
575
576 static BOOL mangle_mask_match(connection_struct *conn, char *filename, char *mask)
577 {
578         mangle_map(filename,True,False,SNUM(conn));
579         return mask_match(filename,mask,False);
580 }
581
582 /****************************************************************************
583  Get an 8.3 directory entry.
584 ****************************************************************************/
585
586 BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname,
587                    SMB_OFF_T *size,int *mode,time_t *date,BOOL check_descend)
588 {
589   char *dname;
590   BOOL found = False;
591   SMB_STRUCT_STAT sbuf;
592   pstring path;
593   pstring pathreal;
594   BOOL isrootdir;
595   pstring filename;
596   BOOL needslash;
597
598   *path = *pathreal = *filename = 0;
599
600   isrootdir = (strequal(conn->dirpath,"./") ||
601                strequal(conn->dirpath,".") ||
602                strequal(conn->dirpath,"/"));
603   
604   needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
605
606   if (!conn->dirptr)
607     return(False);
608
609   while (!found)
610   {
611     dname = ReadDirName(conn->dirptr);
612
613     DEBUG(6,("readdir on dirptr 0x%lx now at offset %d\n",
614           (long)conn->dirptr,TellDir(conn->dirptr)));
615       
616     if (dname == NULL) 
617       return(False);
618       
619     pstrcpy(filename,dname);      
620
621     /* notice the special *.* handling. This appears to be the only difference
622        between the wildcard handling in this routine and in the trans2 routines.
623        see masktest for a demo
624     */
625     if ((strcmp(mask,"*.*") == 0) ||
626         mask_match(filename,mask,False) ||
627         mangle_mask_match(conn,filename,mask))
628     {
629       if (isrootdir && (strequal(filename,"..") || strequal(filename,".")))
630         continue;
631
632       if (!mangle_is_8_3(filename, False)) {
633               mangle_map(filename,True,False,SNUM(conn));
634       }
635
636       pstrcpy(fname,filename);
637       *path = 0;
638       pstrcpy(path,conn->dirpath);
639       if(needslash)
640         pstrcat(path,"/");
641       pstrcpy(pathreal,path);
642       pstrcat(path,fname);
643       pstrcat(pathreal,dname);
644       if (conn->vfs_ops.stat(conn, pathreal, &sbuf) != 0)
645       {
646         DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) ));
647         continue;
648       }
649           
650       *mode = dos_mode(conn,pathreal,&sbuf);
651
652       if (!dir_check_ftype(conn,*mode,&sbuf,dirtype)) 
653       {
654         DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype));
655         continue;
656       }
657
658       *size = sbuf.st_size;
659       *date = sbuf.st_mtime;
660
661       DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
662           
663       found = True;
664     }
665   }
666
667   return(found);
668 }
669
670
671
672 typedef struct
673 {
674   int pos;
675   int numentries;
676   int mallocsize;
677   char *data;
678   char *current;
679 } Dir;
680
681 /*******************************************************************
682  Check to see if a user can read a file. This is only approximate,
683  it is used as part of the "hide unreadable" option. Don't
684  use it for anything security sensitive.
685 ********************************************************************/
686
687 static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
688 {
689         extern struct current_user current_user;
690         SEC_DESC *psd = NULL;
691         size_t sd_size;
692         files_struct *fsp;
693         int smb_action;
694         int access_mode;
695         NTSTATUS status;
696         uint32 access_granted;
697
698         /*
699          * If user is a member of the Admin group
700          * we never hide files from them.
701          */
702
703         if (conn->admin_user)
704                 return True;
705
706         /* If we can't stat it does not show it */
707         if (!VALID_STAT(*pst) && (vfs_stat(conn, name, pst) != 0))
708                 return False;
709
710         /* Pseudo-open the file (note - no fd's created). */
711
712         if(S_ISDIR(pst->st_mode))       
713                  fsp = open_directory(conn, name, pst, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
714                         unix_mode(conn,aRONLY|aDIR, name), &smb_action);
715         else
716                 fsp = open_file_shared1(conn, name, pst, FILE_READ_ATTRIBUTES, SET_DENY_MODE(DENY_NONE),
717                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
718
719         if (!fsp)
720                 return False;
721
722         /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
723         sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd);
724         close_file(fsp, False);
725
726         /* No access if SD get failed. */
727         if (!sd_size)
728                 return False;
729
730         return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA,
731                                  &access_granted, &status);
732 }
733
734 /*******************************************************************
735  Check to see if a user can write a file (and only files, we do not
736  check dirs on this one). This is only approximate,
737  it is used as part of the "hide unwriteable" option. Don't
738  use it for anything security sensitive.
739 ********************************************************************/
740
741 static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
742 {
743         extern struct current_user current_user;
744         SEC_DESC *psd = NULL;
745         size_t sd_size;
746         files_struct *fsp;
747         int smb_action;
748         int access_mode;
749         NTSTATUS status;
750         uint32 access_granted;
751
752         /*
753          * If user is a member of the Admin group
754          * we never hide files from them.
755          */
756
757         if (conn->admin_user)
758                 return True;
759
760         /* If we can't stat it does not show it */
761         if (!VALID_STAT(*pst) && (vfs_stat(conn, name, pst) != 0))
762                 return False;
763
764         /* Pseudo-open the file (note - no fd's created). */
765
766         if(S_ISDIR(pst->st_mode))       
767                 return True;
768         else
769                 fsp = open_file_shared1(conn, name, pst, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE),
770                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
771
772         if (!fsp)
773                 return False;
774
775         /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
776         sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd);
777         close_file(fsp, False);
778
779         /* No access if SD get failed. */
780         if (!sd_size)
781                 return False;
782
783         return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA,
784                                  &access_granted, &status);
785 }
786
787 /*******************************************************************
788   Is a file a "special" type ?
789 ********************************************************************/
790
791 static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
792 {
793         /*
794          * If user is a member of the Admin group
795          * we never hide files from them.
796          */
797
798         if (conn->admin_user)
799                 return True;
800
801         /* If we can't stat it does not show it */
802         if (!VALID_STAT(*pst) && (vfs_stat(conn, name, pst) != 0))
803                 return True;
804
805         if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
806                 return False;
807
808         return True;
809 }
810
811 /*******************************************************************
812  Open a directory.
813 ********************************************************************/
814
815 void *OpenDir(connection_struct *conn, char *name, BOOL use_veto)
816 {
817         Dir *dirp;
818         char *n;
819         DIR *p = conn->vfs_ops.opendir(conn,name);
820         int used=0;
821
822         if (!p)
823                 return(NULL);
824         dirp = (Dir *)malloc(sizeof(Dir));
825         if (!dirp) {
826                 DEBUG(0,("Out of memory in OpenDir\n"));
827                 conn->vfs_ops.closedir(conn,p);
828                 return(NULL);
829         }
830         dirp->pos = dirp->numentries = dirp->mallocsize = 0;
831         dirp->data = dirp->current = NULL;
832
833         while (True) {
834                 int l;
835                 BOOL normal_entry = True;
836                 SMB_STRUCT_STAT st;
837                 char *entry = NULL;
838
839                 if (used == 0) {
840                         n = ".";
841                         normal_entry = False;
842                 } else if (used == 2) {
843                         n = "..";
844                         normal_entry = False;
845                 } else {
846                         n = vfs_readdirname(conn, p);
847                         if (n == NULL)
848                                 break;
849                         if ((strcmp(".",n) == 0) ||(strcmp("..",n) == 0))
850                                 continue;
851                         normal_entry = True;
852                 }
853
854                 ZERO_STRUCT(st);
855                 l = strlen(n)+1;
856
857                 /* If it's a vetoed file, pretend it doesn't even exist */
858                 if (normal_entry && use_veto && conn && IS_VETO_PATH(conn, n))
859                         continue;
860
861                 /* Honour _hide unreadable_ option */
862                 if (normal_entry && conn && lp_hideunreadable(SNUM(conn))) {
863                         int ret=0;
864       
865                         if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) {
866                                 ret = user_can_read_file(conn, entry, &st);
867                         }
868                         if (!ret) {
869                                 SAFE_FREE(entry);
870                                 continue;
871                         }
872                 }
873
874                 /* Honour _hide unwriteable_ option */
875                 if (normal_entry && conn && lp_hideunwriteable_files(SNUM(conn))) {
876                         int ret=0;
877       
878                         if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) {
879                                 ret = user_can_write_file(conn, entry, &st);
880                         }
881                         if (!ret) {
882                                 SAFE_FREE(entry);
883                                 continue;
884                         }
885                 }
886
887                 /* Honour _hide_special_ option */
888                 if (normal_entry && conn && lp_hide_special_files(SNUM(conn))) {
889                         int ret=0;
890       
891                         if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) {
892                                 ret = file_is_special(conn, entry, &st);
893                         }
894                         if (ret) {
895                                 SAFE_FREE(entry);
896                                 continue;
897                         }
898                 }
899
900                 SAFE_FREE(entry);
901
902                 if (used + l > dirp->mallocsize) {
903                         int s = MAX(used+l,used+2000);
904                         char *r;
905                         r = (char *)Realloc(dirp->data,s);
906                         if (!r) {
907                                 DEBUG(0,("Out of memory in OpenDir\n"));
908                                         break;
909                         }
910                         dirp->data = r;
911                         dirp->mallocsize = s;
912                         dirp->current = dirp->data;
913                 }
914
915                 pstrcpy(dirp->data+used,n);
916                 used += l;
917                 dirp->numentries++;
918         }
919
920         conn->vfs_ops.closedir(conn,p);
921         return((void *)dirp);
922 }
923
924
925 /*******************************************************************
926  Close a directory.
927 ********************************************************************/
928
929 void CloseDir(void *p)
930 {
931   if (!p) return;    
932   SAFE_FREE(((Dir *)p)->data);
933   SAFE_FREE(p);
934 }
935
936 /*******************************************************************
937  Read from a directory.
938 ********************************************************************/
939
940 char *ReadDirName(void *p)
941 {
942   char *ret;
943   Dir *dirp = (Dir *)p;
944
945   if (!dirp || !dirp->current || dirp->pos >= dirp->numentries) return(NULL);
946
947   ret = dirp->current;
948   dirp->current = skip_string(dirp->current,1);
949   dirp->pos++;
950
951   return(ret);
952 }
953
954
955 /*******************************************************************
956  Seek a dir.
957 ********************************************************************/
958
959 BOOL SeekDir(void *p,int pos)
960 {
961   Dir *dirp = (Dir *)p;
962
963   if (!dirp) return(False);
964
965   if (pos < dirp->pos) {
966     dirp->current = dirp->data;
967     dirp->pos = 0;
968   }
969
970   while (dirp->pos < pos && ReadDirName(p)) ;
971
972   return(dirp->pos == pos);
973 }
974
975 /*******************************************************************
976  Tell a dir position.
977 ********************************************************************/
978
979 int TellDir(void *p)
980 {
981   Dir *dirp = (Dir *)p;
982
983   if (!dirp) return(-1);
984   
985   return(dirp->pos);
986 }
987
988 /*******************************************************************************
989  This section manages a global directory cache.
990  (It should probably be split into a separate module.  crh)
991 ********************************************************************************/
992
993 typedef struct {
994   ubi_dlNode  node;
995   char       *path;
996   char       *name;
997   char       *dname;
998   int         snum;
999 } dir_cache_entry;
1000
1001 static ubi_dlNewList( dir_cache );
1002
1003 /*****************************************************************************
1004  Add an entry to the directory cache.
1005  Input:  path  -
1006          name  -
1007          dname -
1008          snum  -
1009  Output: None.
1010 *****************************************************************************/
1011
1012 void DirCacheAdd( char *path, char *name, char *dname, int snum )
1013 {
1014   int               pathlen;
1015   int               namelen;
1016   dir_cache_entry  *entry;
1017
1018   /* Allocate the structure & string space in one go so that it can be freed
1019    * in one call to free().
1020    */
1021   pathlen = strlen( path ) +1;  /* Bytes required to store path (with nul). */
1022   namelen = strlen( name ) +1;  /* Bytes required to store name (with nul). */
1023   entry = (dir_cache_entry *)malloc( sizeof( dir_cache_entry )
1024                                    + pathlen
1025                                    + namelen
1026                                    + strlen( dname ) +1 );
1027   if( NULL == entry )   /* Not adding to the cache is not fatal,  */
1028     return;             /* so just return as if nothing happened. */
1029
1030   /* Set pointers correctly and load values. */
1031   entry->path  = pstrcpy( (char *)&entry[1],       path);
1032   entry->name  = pstrcpy( &(entry->path[pathlen]), name);
1033   entry->dname = pstrcpy( &(entry->name[namelen]), dname);
1034   entry->snum  = snum;
1035
1036   /* Add the new entry to the linked list. */
1037   (void)ubi_dlAddHead( dir_cache, entry );
1038   DEBUG( 4, ("Added dir cache entry %s %s -> %s\n", path, name, dname ) );
1039
1040   /* Free excess cache entries. */
1041   while( DIRCACHESIZE < dir_cache->count )
1042     safe_free( ubi_dlRemTail( dir_cache ) );
1043
1044 }
1045
1046 /*****************************************************************************
1047  Search for an entry to the directory cache.
1048  Input:  path  -
1049          name  -
1050          snum  -
1051  Output: The dname string of the located entry, or NULL if the entry was
1052          not found.
1053
1054  Notes:  This uses a linear search, which is is okay because of
1055          the small size of the cache.  Use a splay tree or hash
1056          for large caches.
1057 *****************************************************************************/
1058
1059 char *DirCacheCheck( char *path, char *name, int snum )
1060 {
1061   dir_cache_entry *entry;
1062
1063   for( entry = (dir_cache_entry *)ubi_dlFirst( dir_cache );
1064        NULL != entry;
1065        entry = (dir_cache_entry *)ubi_dlNext( entry ) )
1066     {
1067     if( entry->snum == snum
1068         && 0 == strcmp( name, entry->name )
1069         && 0 == strcmp( path, entry->path ) )
1070       {
1071       DEBUG(4, ("Got dir cache hit on %s %s -> %s\n",path,name,entry->dname));
1072       return( entry->dname );
1073       }
1074     }
1075
1076   return(NULL);
1077 }
1078
1079 /*****************************************************************************
1080  Remove all cache entries which have an snum that matches the input.
1081  Input:  snum  -
1082  Output: None.
1083 *****************************************************************************/
1084
1085 void DirCacheFlush(int snum)
1086 {
1087         dir_cache_entry *entry;
1088         ubi_dlNodePtr    next;
1089
1090         for(entry = (dir_cache_entry *)ubi_dlFirst( dir_cache ); 
1091             NULL != entry; )  {
1092                 next = ubi_dlNext( entry );
1093                 if( entry->snum == snum )
1094                         safe_free( ubi_dlRemThis( dir_cache, entry ) );
1095                 entry = (dir_cache_entry *)next;
1096         }
1097 }