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