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