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