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