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