r8610: If I'm going to do a debug level zero, at least make it useful.
[vlendec/samba-autobuild/.git] / source3 / smbd / dir.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Directory handling routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 /*
24    This module implements directory related functions for Samba.
25 */
26
27 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         uint32 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,uint32 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, dptr->wcard, dptr->attr))) {
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  Close a dptr (internal func).
229 ****************************************************************************/
230
231 static void dptr_close_internal(struct dptr_struct *dptr)
232 {
233         DEBUG(4,("closing dptr key %d\n",dptr->dnum));
234
235         DLIST_REMOVE(dirptrs, dptr);
236
237         /* 
238          * Free the dnum in the bitmap. Remember the dnum value is always 
239          * biased by one with respect to the bitmap.
240          */
241
242         if(bitmap_query( dptr_bmap, dptr->dnum - 1) != True) {
243                 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
244                         dptr->dnum ));
245         }
246
247         bitmap_clear(dptr_bmap, dptr->dnum - 1);
248
249         if (dptr->dir_hnd) {
250                 CloseDir(dptr->dir_hnd);
251         }
252
253         /* Lanman 2 specific code */
254         SAFE_FREE(dptr->wcard);
255         string_set(&dptr->path,"");
256         SAFE_FREE(dptr);
257 }
258
259 /****************************************************************************
260  Close a dptr given a key.
261 ****************************************************************************/
262
263 void dptr_close(int *key)
264 {
265         struct dptr_struct *dptr;
266
267         if(*key == INVALID_DPTR_KEY)
268                 return;
269
270         /* OS/2 seems to use -1 to indicate "close all directories" */
271         if (*key == -1) {
272                 struct dptr_struct *next;
273                 for(dptr = dirptrs; dptr; dptr = next) {
274                         next = dptr->next;
275                         dptr_close_internal(dptr);
276                 }
277                 *key = INVALID_DPTR_KEY;
278                 return;
279         }
280
281         dptr = dptr_get(*key, True);
282
283         if (!dptr) {
284                 DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
285                 return;
286         }
287
288         dptr_close_internal(dptr);
289
290         *key = INVALID_DPTR_KEY;
291 }
292
293 /****************************************************************************
294  Close all dptrs for a cnum.
295 ****************************************************************************/
296
297 void dptr_closecnum(connection_struct *conn)
298 {
299         struct dptr_struct *dptr, *next;
300         for(dptr = dirptrs; dptr; dptr = next) {
301                 next = dptr->next;
302                 if (dptr->conn == conn)
303                         dptr_close_internal(dptr);
304         }
305 }
306
307 /****************************************************************************
308  Idle all dptrs for a cnum.
309 ****************************************************************************/
310
311 void dptr_idlecnum(connection_struct *conn)
312 {
313         struct dptr_struct *dptr;
314         for(dptr = dirptrs; dptr; dptr = dptr->next) {
315                 if (dptr->conn == conn && dptr->dir_hnd)
316                         dptr_idle(dptr);
317         }
318 }
319
320 /****************************************************************************
321  Close a dptr that matches a given path, only if it matches the spid also.
322 ****************************************************************************/
323
324 void dptr_closepath(char *path,uint16 spid)
325 {
326         struct dptr_struct *dptr, *next;
327         for(dptr = dirptrs; dptr; dptr = next) {
328                 next = dptr->next;
329                 if (spid == dptr->spid && strequal(dptr->path,path))
330                         dptr_close_internal(dptr);
331         }
332 }
333
334 /****************************************************************************
335  Try and close the oldest handle not marked for
336  expect close in the hope that the client has
337  finished with that one.
338 ****************************************************************************/
339
340 static void dptr_close_oldest(BOOL old)
341 {
342         struct dptr_struct *dptr;
343
344         /*
345          * Go to the end of the list.
346          */
347         for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
348                 ;
349
350         if(!dptr) {
351                 DEBUG(0,("No old dptrs available to close oldest ?\n"));
352                 return;
353         }
354
355         /*
356          * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
357          * does not have expect_close set. If 'old' is false, close
358          * one of the new dnum handles.
359          */
360
361         for(; dptr; dptr = dptr->prev) {
362                 if ((old && (dptr->dnum < 256) && !dptr->expect_close) ||
363                         (!old && (dptr->dnum > 255))) {
364                                 dptr_close_internal(dptr);
365                                 return;
366                 }
367         }
368 }
369
370 /****************************************************************************
371  Create a new dir ptr. If the flag old_handle is true then we must allocate
372  from the bitmap range 0 - 255 as old SMBsearch directory handles are only
373  one byte long. If old_handle is false we allocate from the range
374  256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
375  a directory handle is never zero.
376 ****************************************************************************/
377
378 int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid,
379                 const char *wcard, uint32 attr)
380 {
381         struct dptr_struct *dptr = NULL;
382         struct smb_Dir *dir_hnd;
383         const char *dir2;
384
385         DEBUG(5,("dptr_create dir=%s\n", path));
386
387         if (!check_name(path,conn))
388                 return(-2); /* Code to say use a unix error return code. */
389
390         /* use a const pointer from here on */
391         dir2 = path;
392         if (!*dir2)
393                 dir2 = ".";
394
395         dir_hnd = OpenDir(conn, dir2, wcard, attr);
396         if (!dir_hnd) {
397                 return (-2);
398         }
399
400         string_set(&conn->dirpath,dir2);
401
402         if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
403                 dptr_idleoldest();
404
405         dptr = SMB_MALLOC_P(struct dptr_struct);
406         if(!dptr) {
407                 DEBUG(0,("malloc fail in dptr_create.\n"));
408                 CloseDir(dir_hnd);
409                 return -1;
410         }
411
412         ZERO_STRUCTP(dptr);
413
414         if(old_handle) {
415
416                 /*
417                  * This is an old-style SMBsearch request. Ensure the
418                  * value we return will fit in the range 1-255.
419                  */
420
421                 dptr->dnum = bitmap_find(dptr_bmap, 0);
422
423                 if(dptr->dnum == -1 || dptr->dnum > 254) {
424
425                         /*
426                          * Try and close the oldest handle not marked for
427                          * expect close in the hope that the client has
428                          * finished with that one.
429                          */
430
431                         dptr_close_oldest(True);
432
433                         /* Now try again... */
434                         dptr->dnum = bitmap_find(dptr_bmap, 0);
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                                 CloseDir(dir_hnd);
439                                 return -1;
440                         }
441                 }
442         } else {
443
444                 /*
445                  * This is a new-style trans2 request. Allocate from
446                  * a range that will return 256 - MAX_DIRECTORY_HANDLES.
447                  */
448
449                 dptr->dnum = bitmap_find(dptr_bmap, 255);
450
451                 if(dptr->dnum == -1 || dptr->dnum < 255) {
452
453                         /*
454                          * Try and close the oldest handle close in the hope that
455                          * the client has finished with that one. This will only
456                          * happen in the case of the Win98 client bug where it leaks
457                          * directory handles.
458                          */
459
460                         dptr_close_oldest(False);
461
462                         /* Now try again... */
463                         dptr->dnum = bitmap_find(dptr_bmap, 255);
464
465                         if(dptr->dnum == -1 || dptr->dnum < 255) {
466                                 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
467                                 SAFE_FREE(dptr);
468                                 CloseDir(dir_hnd);
469                                 return -1;
470                         }
471                 }
472         }
473
474         bitmap_set(dptr_bmap, dptr->dnum);
475
476         dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
477
478         string_set(&dptr->path,dir2);
479         dptr->conn = conn;
480         dptr->dir_hnd = dir_hnd;
481         dptr->spid = spid;
482         dptr->expect_close = expect_close;
483         if (wcard) {
484                 dptr->wcard = SMB_STRDUP(wcard);
485                 if (!dptr->wcard) {
486                         bitmap_clear(dptr_bmap, dptr->dnum - 1);
487                         SAFE_FREE(dptr);
488                         CloseDir(dir_hnd);
489                         return -1;
490                 }
491         } else {
492                 dptr->wcard = NULL;
493         }
494         dptr->attr = attr;
495         if (lp_posix_pathnames() || (wcard && (wcard[0] == '.' && wcard[1] == 0))) {
496                 dptr->has_wild = True;
497         } else {
498                 dptr->has_wild = ms_has_wild(wcard);
499         }
500
501         DLIST_ADD(dirptrs, dptr);
502
503         DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
504                 dptr->dnum,path,expect_close));  
505
506         conn->dirptr = dptr;
507
508         return(dptr->dnum);
509 }
510
511
512 /****************************************************************************
513  Wrapper functions to access the lower level directory handles.
514 ****************************************************************************/
515
516 int dptr_CloseDir(struct dptr_struct *dptr)
517 {
518         return CloseDir(dptr->dir_hnd);
519 }
520
521 void dptr_SeekDir(struct dptr_struct *dptr, long offset)
522 {
523         SeekDir(dptr->dir_hnd, offset);
524 }
525
526 long dptr_TellDir(struct dptr_struct *dptr)
527 {
528         return TellDir(dptr->dir_hnd);
529 }
530
531 /****************************************************************************
532  Return the next visible file name, skipping veto'd and invisible files.
533 ****************************************************************************/
534
535 static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
536 {
537         /* Normal search for the next file. */
538         const char *name;
539         while ((name = ReadDirName(dptr->dir_hnd, poffset)) != NULL) {
540                 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
541                         return name;
542                 }
543         }
544         return NULL;
545 }
546
547 /****************************************************************************
548  Return the next visible file name, skipping veto'd and invisible files.
549 ****************************************************************************/
550
551 const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
552 {
553         pstring pathreal;
554
555         SET_STAT_INVALID(*pst);
556
557         if (dptr->has_wild) {
558                 return dptr_normal_ReadDirName(dptr, poffset, pst);
559         }
560
561         /* If poffset is -1 then we know we returned this name before and we have
562            no wildcards. We're at the end of the directory. */
563         if (*poffset == -1) {
564                 return NULL;
565         }
566
567         /* We know the stored wcard contains no wildcard characters. See if we can match
568            with a stat call. If we can't, then set has_wild to true to
569            prevent us from doing this on every call. */
570
571         /* First check if it should be visible. */
572         if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard, pst, True)) {
573                 dptr->has_wild = True;
574                 return dptr_normal_ReadDirName(dptr, poffset, pst);
575         }
576
577         if (VALID_STAT(*pst)) {
578                 /* We need to set the underlying dir_hdn offset to -1 also as
579                    this function is usually called with the output from TellDir. */
580                 dptr->dir_hnd->offset = *poffset = -1;
581                 return dptr->wcard;
582         }
583
584         pstrcpy(pathreal,dptr->path);
585         pstrcat(pathreal,"/");
586         pstrcat(pathreal,dptr->wcard);
587
588         if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) {
589                 /* We need to set the underlying dir_hdn offset to -1 also as
590                    this function is usually called with the output from TellDir. */
591                 dptr->dir_hnd->offset = *poffset = -1;
592                 return dptr->wcard;
593         } else {
594                 /* If we get any other error than ENOENT or ENOTDIR
595                    then the file exists we just can't stat it. */
596                 if (errno != ENOENT && errno != ENOTDIR) {
597                         /* We need to set the underlying dir_hdn offset to -1 also as
598                            this function is usually called with the output from TellDir. */
599                         dptr->dir_hnd->offset = *poffset = -1;
600                         return dptr->wcard;
601                 }
602         }
603
604         /* In case sensitive mode we don't search - we know if it doesn't exist 
605            with a stat we will fail. */
606
607         if (dptr->conn->case_sensitive) {
608                 /* We need to set the underlying dir_hdn offset to -1 also as
609                    this function is usually called with the output from TellDir. */
610                 dptr->dir_hnd->offset = *poffset = -1;
611                 return NULL;
612         } else {
613                 dptr->has_wild = True;
614                 return dptr_normal_ReadDirName(dptr, poffset, pst);
615         }
616 }
617
618 /****************************************************************************
619  Search for a file by name, skipping veto'ed and not visible files.
620 ****************************************************************************/
621
622 BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
623 {
624         SET_STAT_INVALID(*pst);
625
626         if (!dptr->has_wild && (dptr->dir_hnd->offset == -1)) {
627                 /* This is a singleton directory and we're already at the end. */
628                 *poffset = -1;
629                 return False;
630         }
631
632         if (SearchDir(dptr->dir_hnd, name, poffset)) {
633                 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
634                         return True;
635                 }
636         }
637         return False;
638 }
639
640 /****************************************************************************
641  Fill the 5 byte server reserved dptr field.
642 ****************************************************************************/
643
644 #define DPTR_MASK ((uint32)(((uint32)1)<<31))
645
646 BOOL dptr_fill(char *buf1,unsigned int key)
647 {
648         unsigned char *buf = (unsigned char *)buf1;
649         struct dptr_struct *dptr = dptr_get(key, False);
650         uint32 offset;
651         if (!dptr) {
652                 DEBUG(1,("filling null dirptr %d\n",key));
653                 return(False);
654         }
655         offset = (uint32)TellDir(dptr->dir_hnd);
656         DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
657                 (long)dptr->dir_hnd,(int)offset));
658         if (offset != (uint32)-1 && (offset & DPTR_MASK)) {
659                 DEBUG(0,("dptr_fill: Error - offset 0x%x has bit 32 set. Can't use in server state.\n",
660                         (unsigned int)offset ));
661                 return False;
662         }
663         buf[0] = key;
664         SIVAL(buf,1,offset | DPTR_MASK);
665         return(True);
666 }
667
668 /****************************************************************************
669  Fetch the dir ptr and seek it given the 5 byte server field.
670 ****************************************************************************/
671
672 struct dptr_struct *dptr_fetch(char *buf,int *num)
673 {
674         unsigned int key = *(unsigned char *)buf;
675         struct dptr_struct *dptr = dptr_get(key, False);
676         uint32 offset;
677         long seekoff;
678
679         if (!dptr) {
680                 DEBUG(3,("fetched null dirptr %d\n",key));
681                 return(NULL);
682         }
683         *num = key;
684         offset = IVAL(buf,1);
685         if (offset == (uint32)-1) {
686                 seekoff = -1;
687         } else {
688                 seekoff = (long)(offset & ~DPTR_MASK);
689         }
690         SeekDir(dptr->dir_hnd,seekoff);
691         DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
692                 key,dptr_path(key),(int)seekoff));
693         return(dptr);
694 }
695
696 /****************************************************************************
697  Fetch the dir ptr.
698 ****************************************************************************/
699
700 struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
701 {
702         struct dptr_struct *dptr  = dptr_get(dptr_num, False);
703
704         if (!dptr) {
705                 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
706                 return(NULL);
707         }
708         DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
709         return(dptr);
710 }
711
712 /****************************************************************************
713  Check a filetype for being valid.
714 ****************************************************************************/
715
716 BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype)
717 {
718         uint32 mask;
719
720         /* Check the "may have" search bits. */
721         if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
722                 return False;
723
724         /* Check the "must have" bits, which are the may have bits shifted eight */
725         /* If must have bit is set, the file/dir can not be returned in search unless the matching
726                 file attribute is set */
727         mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */
728         if(mask) {
729                 if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask)   /* check if matching attribute present */
730                         return True;
731                 else
732                         return False;
733         }
734
735         return True;
736 }
737
738 static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask)
739 {
740         mangle_map(filename,True,False,SNUM(conn));
741         return mask_match_search(filename,mask,False);
742 }
743
744 /****************************************************************************
745  Get an 8.3 directory entry.
746 ****************************************************************************/
747
748 BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fname,
749                    SMB_OFF_T *size,uint32 *mode,time_t *date,BOOL check_descend)
750 {
751         const char *dname;
752         BOOL found = False;
753         SMB_STRUCT_STAT sbuf;
754         pstring path;
755         pstring pathreal;
756         pstring filename;
757         BOOL needslash;
758
759         *path = *pathreal = *filename = 0;
760
761         needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
762
763         if (!conn->dirptr)
764                 return(False);
765
766         while (!found) {
767                 long curoff = dptr_TellDir(conn->dirptr);
768                 dname = dptr_ReadDirName(conn->dirptr, &curoff, &sbuf);
769
770                 DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
771                         (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
772       
773                 if (dname == NULL) 
774                         return(False);
775       
776                 pstrcpy(filename,dname);      
777
778                 /* notice the special *.* handling. This appears to be the only difference
779                         between the wildcard handling in this routine and in the trans2 routines.
780                         see masktest for a demo
781                 */
782                 if ((strcmp(mask,"*.*") == 0) ||
783                     mask_match_search(filename,mask,False) ||
784                     mangle_mask_match(conn,filename,mask)) {
785
786                         if (!mangle_is_8_3(filename, False, SNUM(conn)))
787                                 mangle_map(filename,True,False,SNUM(conn));
788
789                         pstrcpy(fname,filename);
790                         *path = 0;
791                         pstrcpy(path,conn->dirpath);
792                         if(needslash)
793                                 pstrcat(path,"/");
794                         pstrcpy(pathreal,path);
795                         pstrcat(path,fname);
796                         pstrcat(pathreal,dname);
797                         if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
798                                 DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) ));
799                                 continue;
800                         }
801           
802                         *mode = dos_mode(conn,pathreal,&sbuf);
803
804                         if (!dir_check_ftype(conn,*mode,dirtype)) {
805                                 DEBUG(5,("[%s] attribs didn't match %x\n",filename,(unsigned int)dirtype));
806                                 continue;
807                         }
808
809                         *size = sbuf.st_size;
810                         *date = sbuf.st_mtime;
811
812                         DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
813
814                         found = True;
815                 }
816         }
817
818         return(found);
819 }
820
821 /*******************************************************************
822  Check to see if a user can read a file. This is only approximate,
823  it is used as part of the "hide unreadable" option. Don't
824  use it for anything security sensitive.
825 ********************************************************************/
826
827 static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
828 {
829         SEC_DESC *psd = NULL;
830         size_t sd_size;
831         files_struct *fsp;
832         NTSTATUS status;
833         uint32 access_granted;
834
835         /*
836          * If user is a member of the Admin group
837          * we never hide files from them.
838          */
839
840         if (conn->admin_user) {
841                 return True;
842         }
843
844         /* If we can't stat it does not show it */
845         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) {
846                 return False;
847         }
848
849         /* Pseudo-open the file (note - no fd's created). */
850
851         if(S_ISDIR(pst->st_mode)) {
852                  fsp = open_directory(conn, name, pst,
853                         READ_CONTROL_ACCESS,
854                         FILE_SHARE_READ|FILE_SHARE_WRITE,
855                         FILE_OPEN,
856                         0, /* no create options. */
857                         NULL);
858         } else {
859                 fsp = open_file_stat(conn, name, pst);
860         }
861
862         if (!fsp) {
863                 return False;
864         }
865
866         /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
867         sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd,
868                         (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
869         close_file(fsp, True);
870
871         /* No access if SD get failed. */
872         if (!sd_size) {
873                 return False;
874         }
875
876         return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA,
877                                  &access_granted, &status);
878 }
879
880 /*******************************************************************
881  Check to see if a user can write a file (and only files, we do not
882  check dirs on this one). This is only approximate,
883  it is used as part of the "hide unwriteable" option. Don't
884  use it for anything security sensitive.
885 ********************************************************************/
886
887 static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
888 {
889         SEC_DESC *psd = NULL;
890         size_t sd_size;
891         files_struct *fsp;
892         int info;
893         NTSTATUS status;
894         uint32 access_granted;
895
896         /*
897          * If user is a member of the Admin group
898          * we never hide files from them.
899          */
900
901         if (conn->admin_user) {
902                 return True;
903         }
904
905         /* If we can't stat it does not show it */
906         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) {
907                 return False;
908         }
909
910         /* Pseudo-open the file */
911
912         if(S_ISDIR(pst->st_mode)) {
913                 return True;
914         } else {
915                 fsp = open_file_ntcreate(conn, name, pst,
916                         FILE_WRITE_ATTRIBUTES,
917                         FILE_SHARE_READ|FILE_SHARE_WRITE,
918                         FILE_OPEN,
919                         0,
920                         FILE_ATTRIBUTE_NORMAL,
921                         INTERNAL_OPEN_ONLY,
922                         &info);
923         }
924
925         if (!fsp) {
926                 return False;
927         }
928
929         /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
930         sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd,
931                         (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
932         close_file(fsp, False);
933
934         /* No access if SD get failed. */
935         if (!sd_size)
936                 return False;
937
938         return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA,
939                                  &access_granted, &status);
940 }
941
942 /*******************************************************************
943   Is a file a "special" type ?
944 ********************************************************************/
945
946 static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
947 {
948         /*
949          * If user is a member of the Admin group
950          * we never hide files from them.
951          */
952
953         if (conn->admin_user)
954                 return False;
955
956         /* If we can't stat it does not show it */
957         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
958                 return True;
959
960         if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
961                 return False;
962
963         return True;
964 }
965
966 /*******************************************************************
967  Should the file be seen by the client ?
968 ********************************************************************/
969
970 BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, BOOL use_veto)
971 {
972         BOOL hide_unreadable = lp_hideunreadable(SNUM(conn));
973         BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
974         BOOL hide_special = lp_hide_special_files(SNUM(conn));
975
976         SET_STAT_INVALID(*pst);
977
978         if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
979                 return True; /* . and .. are always visible. */
980         }
981
982         /* If it's a vetoed file, pretend it doesn't even exist */
983         if (use_veto && IS_VETO_PATH(conn, name)) {
984                 return False;
985         }
986
987         if (hide_unreadable || hide_unwriteable || hide_special) {
988                 char *entry = NULL;
989
990                 if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
991                         return False;
992                 }
993                 /* Honour _hide unreadable_ option */
994                 if (hide_unreadable && !user_can_read_file(conn, entry, pst)) {
995                         SAFE_FREE(entry);
996                         return False;
997                 }
998                 /* Honour _hide unwriteable_ option */
999                 if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
1000                         SAFE_FREE(entry);
1001                         return False;
1002                 }
1003                 /* Honour _hide_special_ option */
1004                 if (hide_special && file_is_special(conn, entry, pst)) {
1005                         SAFE_FREE(entry);
1006                         return False;
1007                 }
1008                 SAFE_FREE(entry);
1009         }
1010         return True;
1011 }
1012
1013 /*******************************************************************
1014  Open a directory.
1015 ********************************************************************/
1016
1017 struct smb_Dir *OpenDir(connection_struct *conn, const char *name, const char *mask, uint32 attr)
1018 {
1019         struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir);
1020         if (!dirp) {
1021                 return NULL;
1022         }
1023         ZERO_STRUCTP(dirp);
1024
1025         dirp->conn = conn;
1026
1027         dirp->dir_path = SMB_STRDUP(name);
1028         if (!dirp->dir_path) {
1029                 goto fail;
1030         }
1031         dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
1032         if (!dirp->dir) {
1033                 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) ));
1034                 goto fail;
1035         }
1036
1037         dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, NAME_CACHE_SIZE);
1038         if (!dirp->name_cache) {
1039                 goto fail;
1040         }
1041
1042         dirhandles_open++;
1043         return dirp;
1044
1045   fail:
1046
1047         if (dirp) {
1048                 if (dirp->dir) {
1049                         SMB_VFS_CLOSEDIR(conn,dirp->dir);
1050                 }
1051                 SAFE_FREE(dirp->dir_path);
1052                 SAFE_FREE(dirp->name_cache);
1053                 SAFE_FREE(dirp);
1054         }
1055         return NULL;
1056 }
1057
1058
1059 /*******************************************************************
1060  Close a directory.
1061 ********************************************************************/
1062
1063 int CloseDir(struct smb_Dir *dirp)
1064 {
1065         int i, ret = 0;
1066
1067         if (dirp->dir) {
1068                 ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1069         }
1070         SAFE_FREE(dirp->dir_path);
1071         if (dirp->name_cache) {
1072                 for (i = 0; i < NAME_CACHE_SIZE; i++) {
1073                         SAFE_FREE(dirp->name_cache[i].name);
1074                 }
1075         }
1076         SAFE_FREE(dirp->name_cache);
1077         SAFE_FREE(dirp);
1078         dirhandles_open--;
1079         return ret;
1080 }
1081
1082 /*******************************************************************
1083  Read from a directory. Also return current offset.
1084  Don't check for veto or invisible files.
1085 ********************************************************************/
1086
1087 const char *ReadDirName(struct smb_Dir *dirp, long *poffset)
1088 {
1089         const char *n;
1090         connection_struct *conn = dirp->conn;
1091
1092         /* Cheat to allow . and .. to be the first entries returned. */
1093         if ((*poffset == 0) && (dirp->file_number < 2)) {
1094                 if (dirp->file_number == 0) {
1095                         n = ".";
1096                 } else {
1097                         n = "..";
1098                 }
1099                 dirp->file_number++;
1100                 return n;
1101         } else {
1102                 /* A real offset, seek to it. */
1103                 SeekDir(dirp, *poffset);
1104         }
1105
1106         while ((n = vfs_readdirname(conn, dirp->dir))) {
1107                 struct name_cache_entry *e;
1108                 /* Ignore . and .. - we've already returned them. */
1109                 if (*n == '.') {
1110                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
1111                                 continue;
1112                         }
1113                 }
1114                 dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1115                 dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE;
1116                 e = &dirp->name_cache[dirp->name_cache_index];
1117                 SAFE_FREE(e->name);
1118                 e->name = SMB_STRDUP(n);
1119                 *poffset = e->offset= dirp->offset;
1120                 dirp->file_number++;
1121                 return e->name;
1122         }
1123         dirp->offset = -1;
1124         return NULL;
1125 }
1126
1127 /*******************************************************************
1128  Rewind to the start.
1129 ********************************************************************/
1130
1131 void RewindDir(struct smb_Dir *dirp, long *poffset)
1132 {
1133         SMB_VFS_REWINDDIR(dirp->conn, dirp->dir);
1134         dirp->file_number = 0;
1135         dirp->offset = 0;
1136         *poffset = 0;
1137 }
1138
1139 /*******************************************************************
1140  Seek a dir.
1141 ********************************************************************/
1142
1143 void SeekDir(struct smb_Dir *dirp, long offset)
1144 {
1145         if (offset != dirp->offset) {
1146                 if (offset == 0) {
1147                         RewindDir(dirp, &offset);
1148                 } else {
1149                         SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1150                 }
1151                 dirp->offset = offset;
1152         }
1153 }
1154
1155 /*******************************************************************
1156  Tell a dir position.
1157 ********************************************************************/
1158
1159 long TellDir(struct smb_Dir *dirp)
1160 {
1161         return(dirp->offset);
1162 }
1163
1164 /*******************************************************************
1165  Find an entry by name. Leave us at the offset after it.
1166  Don't check for veto or invisible files.
1167 ********************************************************************/
1168
1169 BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1170 {
1171         int i;
1172         const char *entry;
1173         connection_struct *conn = dirp->conn;
1174
1175         /* Search back in the name cache. */
1176         for (i = dirp->name_cache_index; i >= 0; i--) {
1177                 struct name_cache_entry *e = &dirp->name_cache[i];
1178                 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1179                         *poffset = e->offset;
1180                         SeekDir(dirp, e->offset);
1181                         return True;
1182                 }
1183         }
1184         for (i = NAME_CACHE_SIZE-1; i > dirp->name_cache_index; i--) {
1185                 struct name_cache_entry *e = &dirp->name_cache[i];
1186                 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1187                         *poffset = e->offset;
1188                         SeekDir(dirp, e->offset);
1189                         return True;
1190                 }
1191         }
1192
1193         /* Not found in the name cache. Rewind directory and start from scratch. */
1194         SMB_VFS_REWINDDIR(conn, dirp->dir);
1195         dirp->file_number = 0;
1196         *poffset = 0;
1197         while ((entry = ReadDirName(dirp, poffset))) {
1198                 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
1199                         return True;
1200                 }
1201         }
1202         return False;
1203 }