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