7a6815b680633a5fd9b04d7bc751adf42f73d5fb
[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,
756                 const char *filename,
757                 const char *mask)
758 {
759         char mname[13];
760
761         if (!name_to_8_3(filename,mname,False,conn->params)) {
762                 return False;
763         }
764         return mask_match_search(mname,mask,False);
765 }
766
767 /****************************************************************************
768  Get an 8.3 directory entry.
769 ****************************************************************************/
770
771 BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fname,
772                    SMB_OFF_T *size,uint32 *mode,time_t *date,BOOL check_descend)
773 {
774         const char *dname;
775         BOOL found = False;
776         SMB_STRUCT_STAT sbuf;
777         pstring path;
778         pstring pathreal;
779         pstring filename;
780         BOOL needslash;
781
782         *path = *pathreal = *filename = 0;
783
784         needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
785
786         if (!conn->dirptr)
787                 return(False);
788
789         while (!found) {
790                 long curoff = dptr_TellDir(conn->dirptr);
791                 dname = dptr_ReadDirName(conn->dirptr, &curoff, &sbuf);
792
793                 DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
794                         (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
795
796                 if (dname == NULL)
797                         return(False);
798
799                 pstrcpy(filename,dname);
800
801                 /* notice the special *.* handling. This appears to be the only difference
802                         between the wildcard handling in this routine and in the trans2 routines.
803                         see masktest for a demo
804                 */
805                 if ((strcmp(mask,"*.*") == 0) ||
806                     mask_match_search(filename,mask,False) ||
807                     mangle_mask_match(conn,filename,mask)) {
808
809                         if (!mangle_is_8_3(filename, False, conn->params)) {
810                                 char mname[13];
811                                 if (!name_to_8_3(filename,mname,False,
812                                            conn->params)) {
813                                         continue;
814                                 }
815                                 pstrcpy(filename,mname);
816                         }
817
818                         pstrcpy(fname,filename);
819                         *path = 0;
820                         pstrcpy(path,conn->dirpath);
821                         if(needslash)
822                                 pstrcat(path,"/");
823                         pstrcpy(pathreal,path);
824                         pstrcat(path,fname);
825                         pstrcat(pathreal,dname);
826                         if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
827                                 DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) ));
828                                 continue;
829                         }
830           
831                         *mode = dos_mode(conn,pathreal,&sbuf);
832
833                         if (!dir_check_ftype(conn,*mode,dirtype)) {
834                                 DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",filename,(unsigned int)*mode,(unsigned int)dirtype));
835                                 continue;
836                         }
837
838                         *size = sbuf.st_size;
839                         *date = sbuf.st_mtime;
840
841                         DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
842
843                         found = True;
844
845                         DirCacheAdd(conn->dirptr->dir_hnd, dname, curoff);
846                 }
847         }
848
849         return(found);
850 }
851
852 /*******************************************************************
853  Check to see if a user can read a file. This is only approximate,
854  it is used as part of the "hide unreadable" option. Don't
855  use it for anything security sensitive.
856 ********************************************************************/
857
858 static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
859 {
860         SEC_DESC *psd = NULL;
861         size_t sd_size;
862         files_struct *fsp;
863         NTSTATUS status;
864         uint32 access_granted;
865
866         /*
867          * If user is a member of the Admin group
868          * we never hide files from them.
869          */
870
871         if (conn->admin_user) {
872                 return True;
873         }
874
875         /* If we can't stat it does not show it */
876         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) {
877                 DEBUG(10,("user_can_read_file: SMB_VFS_STAT failed for file %s with error %s\n",
878                         name, strerror(errno) ));
879                 return False;
880         }
881
882         /* Pseudo-open the file (note - no fd's created). */
883
884         if(S_ISDIR(pst->st_mode)) {
885                  status = open_directory(conn, NULL, name, pst,
886                         READ_CONTROL_ACCESS,
887                         FILE_SHARE_READ|FILE_SHARE_WRITE,
888                         FILE_OPEN,
889                         0, /* no create options. */
890                         FILE_ATTRIBUTE_DIRECTORY,
891                         NULL, &fsp);
892         } else {
893                 status = open_file_stat(conn, NULL, name, pst, &fsp);
894         }
895
896         if (!NT_STATUS_IS_OK(status)) {
897                 return False;
898         }
899
900         /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
901         sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd,
902                         (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
903         close_file(fsp, NORMAL_CLOSE);
904
905         /* No access if SD get failed. */
906         if (!sd_size) {
907                 return False;
908         }
909
910         return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA,
911                                  &access_granted, &status);
912 }
913
914 /*******************************************************************
915  Check to see if a user can write a file (and only files, we do not
916  check dirs on this one). This is only approximate,
917  it is used as part of the "hide unwriteable" option. Don't
918  use it for anything security sensitive.
919 ********************************************************************/
920
921 static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
922 {
923         SEC_DESC *psd = NULL;
924         size_t sd_size;
925         files_struct *fsp;
926         int info;
927         NTSTATUS status;
928         uint32 access_granted;
929
930         /*
931          * If user is a member of the Admin group
932          * we never hide files from them.
933          */
934
935         if (conn->admin_user) {
936                 return True;
937         }
938
939         /* If we can't stat it does not show it */
940         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) {
941                 return False;
942         }
943
944         /* Pseudo-open the file */
945
946         if(S_ISDIR(pst->st_mode)) {
947                 return True;
948         } else {
949                 status = open_file_ntcreate(conn, NULL, name, pst,
950                         FILE_WRITE_ATTRIBUTES,
951                         FILE_SHARE_READ|FILE_SHARE_WRITE,
952                         FILE_OPEN,
953                         0,
954                         FILE_ATTRIBUTE_NORMAL,
955                         INTERNAL_OPEN_ONLY,
956                         &info, &fsp);
957         }
958
959         if (!NT_STATUS_IS_OK(status)) {
960                 return False;
961         }
962
963         /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
964         sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd,
965                         (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
966         close_file(fsp, NORMAL_CLOSE);
967
968         /* No access if SD get failed. */
969         if (!sd_size)
970                 return False;
971
972         return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA,
973                                  &access_granted, &status);
974 }
975
976 /*******************************************************************
977   Is a file a "special" type ?
978 ********************************************************************/
979
980 static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
981 {
982         /*
983          * If user is a member of the Admin group
984          * we never hide files from them.
985          */
986
987         if (conn->admin_user)
988                 return False;
989
990         /* If we can't stat it does not show it */
991         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
992                 return True;
993
994         if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
995                 return False;
996
997         return True;
998 }
999
1000 /*******************************************************************
1001  Should the file be seen by the client ?
1002 ********************************************************************/
1003
1004 BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, BOOL use_veto)
1005 {
1006         BOOL hide_unreadable = lp_hideunreadable(SNUM(conn));
1007         BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
1008         BOOL hide_special = lp_hide_special_files(SNUM(conn));
1009
1010         SET_STAT_INVALID(*pst);
1011
1012         if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
1013                 return True; /* . and .. are always visible. */
1014         }
1015
1016         /* If it's a vetoed file, pretend it doesn't even exist */
1017         if (use_veto && IS_VETO_PATH(conn, name)) {
1018                 DEBUG(10,("is_visible_file: file %s is vetoed.\n", name ));
1019                 return False;
1020         }
1021
1022         if (hide_unreadable || hide_unwriteable || hide_special) {
1023                 char *entry = NULL;
1024
1025                 if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
1026                         return False;
1027                 }
1028
1029                 /* If it's a dfs symlink, ignore _hide xxxx_ options */
1030                 if (lp_host_msdfs() &&
1031                                 lp_msdfs_root(SNUM(conn)) &&
1032                                 is_msdfs_link(conn, entry, NULL)) {
1033                         SAFE_FREE(entry);
1034                         return True;
1035                 }
1036
1037                 /* Honour _hide unreadable_ option */
1038                 if (hide_unreadable && !user_can_read_file(conn, entry, pst)) {
1039                         DEBUG(10,("is_visible_file: file %s is unreadable.\n", entry ));
1040                         SAFE_FREE(entry);
1041                         return False;
1042                 }
1043                 /* Honour _hide unwriteable_ option */
1044                 if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
1045                         DEBUG(10,("is_visible_file: file %s is unwritable.\n", entry ));
1046                         SAFE_FREE(entry);
1047                         return False;
1048                 }
1049                 /* Honour _hide_special_ option */
1050                 if (hide_special && file_is_special(conn, entry, pst)) {
1051                         DEBUG(10,("is_visible_file: file %s is special.\n", entry ));
1052                         SAFE_FREE(entry);
1053                         return False;
1054                 }
1055                 SAFE_FREE(entry);
1056         }
1057         return True;
1058 }
1059
1060 /*******************************************************************
1061  Open a directory.
1062 ********************************************************************/
1063
1064 struct smb_Dir *OpenDir(connection_struct *conn, const char *name, const char *mask, uint32 attr)
1065 {
1066         struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir);
1067
1068         if (!dirp) {
1069                 return NULL;
1070         }
1071         ZERO_STRUCTP(dirp);
1072
1073         dirp->conn = conn;
1074         dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
1075
1076         dirp->dir_path = SMB_STRDUP(name);
1077         if (!dirp->dir_path) {
1078                 goto fail;
1079         }
1080         dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
1081         if (!dirp->dir) {
1082                 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) ));
1083                 goto fail;
1084         }
1085
1086         if (dirp->name_cache_size) {
1087                 dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry,
1088                                 dirp->name_cache_size);
1089                 if (!dirp->name_cache) {
1090                         goto fail;
1091                 }
1092         } else {
1093                 dirp->name_cache = NULL;
1094         }
1095
1096         dirhandles_open++;
1097         return dirp;
1098
1099   fail:
1100
1101         if (dirp) {
1102                 if (dirp->dir) {
1103                         SMB_VFS_CLOSEDIR(conn,dirp->dir);
1104                 }
1105                 SAFE_FREE(dirp->dir_path);
1106                 SAFE_FREE(dirp->name_cache);
1107                 SAFE_FREE(dirp);
1108         }
1109         return NULL;
1110 }
1111
1112
1113 /*******************************************************************
1114  Close a directory.
1115 ********************************************************************/
1116
1117 int CloseDir(struct smb_Dir *dirp)
1118 {
1119         int i, ret = 0;
1120
1121         if (dirp->dir) {
1122                 ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1123         }
1124         SAFE_FREE(dirp->dir_path);
1125         if (dirp->name_cache) {
1126                 for (i = 0; i < dirp->name_cache_size; i++) {
1127                         SAFE_FREE(dirp->name_cache[i].name);
1128                 }
1129         }
1130         SAFE_FREE(dirp->name_cache);
1131         SAFE_FREE(dirp);
1132         dirhandles_open--;
1133         return ret;
1134 }
1135
1136 /*******************************************************************
1137  Read from a directory. Also return current offset.
1138  Don't check for veto or invisible files.
1139 ********************************************************************/
1140
1141 const char *ReadDirName(struct smb_Dir *dirp, long *poffset)
1142 {
1143         const char *n;
1144         connection_struct *conn = dirp->conn;
1145
1146         /* Cheat to allow . and .. to be the first entries returned. */
1147         if (((*poffset == START_OF_DIRECTORY_OFFSET) || (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2)) {
1148                 if (dirp->file_number == 0) {
1149                         n = ".";
1150                         *poffset = dirp->offset = START_OF_DIRECTORY_OFFSET;
1151                 } else {
1152                         *poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET;
1153                         n = "..";
1154                 }
1155                 dirp->file_number++;
1156                 return n;
1157         } else if (*poffset == END_OF_DIRECTORY_OFFSET) {
1158                 *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1159                 return NULL;
1160         } else {
1161                 /* A real offset, seek to it. */
1162                 SeekDir(dirp, *poffset);
1163         }
1164
1165         while ((n = vfs_readdirname(conn, dirp->dir))) {
1166                 /* Ignore . and .. - we've already returned them. */
1167                 if (*n == '.') {
1168                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
1169                                 continue;
1170                         }
1171                 }
1172                 *poffset = dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1173                 dirp->file_number++;
1174                 return n;
1175         }
1176         *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1177         return NULL;
1178 }
1179
1180 /*******************************************************************
1181  Rewind to the start.
1182 ********************************************************************/
1183
1184 void RewindDir(struct smb_Dir *dirp, long *poffset)
1185 {
1186         SMB_VFS_REWINDDIR(dirp->conn, dirp->dir);
1187         dirp->file_number = 0;
1188         dirp->offset = START_OF_DIRECTORY_OFFSET;
1189         *poffset = START_OF_DIRECTORY_OFFSET;
1190 }
1191
1192 /*******************************************************************
1193  Seek a dir.
1194 ********************************************************************/
1195
1196 void SeekDir(struct smb_Dir *dirp, long offset)
1197 {
1198         if (offset != dirp->offset) {
1199                 if (offset == START_OF_DIRECTORY_OFFSET) {
1200                         RewindDir(dirp, &offset);
1201                         /* 
1202                          * Ok we should really set the file number here
1203                          * to 1 to enable ".." to be returned next. Trouble
1204                          * is I'm worried about callers using SeekDir(dirp,0)
1205                          * as equivalent to RewindDir(). So leave this alone
1206                          * for now.
1207                          */
1208                 } else if  (offset == DOT_DOT_DIRECTORY_OFFSET) {
1209                         RewindDir(dirp, &offset);
1210                         /*
1211                          * Set the file number to 2 - we want to get the first
1212                          * real file entry (the one we return after "..")
1213                          * on the next ReadDir.
1214                          */
1215                         dirp->file_number = 2;
1216                 } else if (offset == END_OF_DIRECTORY_OFFSET) {
1217                         ; /* Don't seek in this case. */
1218                 } else {
1219                         SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1220                 }
1221                 dirp->offset = offset;
1222         }
1223 }
1224
1225 /*******************************************************************
1226  Tell a dir position.
1227 ********************************************************************/
1228
1229 long TellDir(struct smb_Dir *dirp)
1230 {
1231         return(dirp->offset);
1232 }
1233
1234 /*******************************************************************
1235  Add an entry into the dcache.
1236 ********************************************************************/
1237
1238 void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
1239 {
1240         struct name_cache_entry *e;
1241
1242         if (!dirp->name_cache_size || !dirp->name_cache) {
1243                 return;
1244         }
1245
1246         dirp->name_cache_index = (dirp->name_cache_index+1) %
1247                                         dirp->name_cache_size;
1248         e = &dirp->name_cache[dirp->name_cache_index];
1249         SAFE_FREE(e->name);
1250         e->name = SMB_STRDUP(name);
1251         e->offset = offset;
1252 }
1253
1254 /*******************************************************************
1255  Find an entry by name. Leave us at the offset after it.
1256  Don't check for veto or invisible files.
1257 ********************************************************************/
1258
1259 BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1260 {
1261         int i;
1262         const char *entry;
1263         connection_struct *conn = dirp->conn;
1264
1265         /* Search back in the name cache. */
1266         if (dirp->name_cache_size && dirp->name_cache) {
1267                 for (i = dirp->name_cache_index; i >= 0; i--) {
1268                         struct name_cache_entry *e = &dirp->name_cache[i];
1269                         if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1270                                 *poffset = e->offset;
1271                                 SeekDir(dirp, e->offset);
1272                                 return True;
1273                         }
1274                 }
1275                 for (i = dirp->name_cache_size - 1; i > dirp->name_cache_index; i--) {
1276                         struct name_cache_entry *e = &dirp->name_cache[i];
1277                         if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1278                                 *poffset = e->offset;
1279                                 SeekDir(dirp, e->offset);
1280                                 return True;
1281                         }
1282                 }
1283         }
1284
1285         /* Not found in the name cache. Rewind directory and start from scratch. */
1286         SMB_VFS_REWINDDIR(conn, dirp->dir);
1287         dirp->file_number = 0;
1288         *poffset = START_OF_DIRECTORY_OFFSET;
1289         while ((entry = ReadDirName(dirp, poffset))) {
1290                 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
1291                         return True;
1292                 }
1293         }
1294         return False;
1295 }
1296
1297 /*****************************************************************
1298  Is this directory empty ?
1299 *****************************************************************/
1300
1301 NTSTATUS can_delete_directory(struct connection_struct *conn,
1302                                 const char *dirname)
1303 {
1304         NTSTATUS status = NT_STATUS_OK;
1305         long dirpos = 0;
1306         const char *dname;
1307         struct smb_Dir *dir_hnd = OpenDir(conn, dirname, NULL, 0);
1308
1309         if (!dir_hnd) {
1310                 return map_nt_error_from_unix(errno);
1311         }
1312
1313         while ((dname = ReadDirName(dir_hnd,&dirpos))) {
1314                 SMB_STRUCT_STAT st;
1315
1316                 /* Quick check for "." and ".." */
1317                 if (dname[0] == '.') {
1318                         if (!dname[1] || (dname[1] == '.' && !dname[2])) {
1319                                 continue;
1320                         }
1321                 }
1322
1323                 if (!is_visible_file(conn, dirname, dname, &st, True)) {
1324                         continue;
1325                 }
1326
1327                 DEBUG(10,("can_delete_directory: got name %s - can't delete\n", dname ));
1328                 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1329                 break;
1330         }
1331         CloseDir(dir_hnd);
1332
1333         return status;
1334 }