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