s3:smbd: fully construct the dptr before allocating a dnum in the bitmap
[metze/samba/wip.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 "system/filesys.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "libcli/security/security.h"
26
27 /*
28    This module implements directory related functions for Samba.
29 */
30
31 /* "Special" directory offsets. */
32 #define END_OF_DIRECTORY_OFFSET ((long)-1)
33 #define START_OF_DIRECTORY_OFFSET ((long)0)
34 #define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000)
35
36 /* Make directory handle internals available. */
37
38 struct name_cache_entry {
39         char *name;
40         long offset;
41 };
42
43 struct smb_Dir {
44         connection_struct *conn;
45         SMB_STRUCT_DIR *dir;
46         long offset;
47         char *dir_path;
48         size_t name_cache_size;
49         struct name_cache_entry *name_cache;
50         unsigned int name_cache_index;
51         unsigned int file_number;
52 };
53
54 struct dptr_struct {
55         struct dptr_struct *next, *prev;
56         int dnum;
57         uint16 spid;
58         struct connection_struct *conn;
59         struct smb_Dir *dir_hnd;
60         bool expect_close;
61         char *wcard;
62         uint32 attr;
63         char *path;
64         bool has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
65         bool did_stat; /* Optimisation for non-wcard searches. */
66 };
67
68 static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
69                         files_struct *fsp,
70                         const char *mask,
71                         uint32 attr);
72
73 #define INVALID_DPTR_KEY (-3)
74
75 /****************************************************************************
76  Make a dir struct.
77 ****************************************************************************/
78
79 bool make_dir_struct(TALLOC_CTX *ctx,
80                         char *buf,
81                         const char *mask,
82                         const char *fname,
83                         SMB_OFF_T size,
84                         uint32 mode,
85                         time_t date,
86                         bool uc)
87 {
88         char *p;
89         char *mask2 = talloc_strdup(ctx, mask);
90
91         if (!mask2) {
92                 return False;
93         }
94
95         if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
96                 size = 0;
97         }
98
99         memset(buf+1,' ',11);
100         if ((p = strchr_m(mask2,'.')) != NULL) {
101                 *p = 0;
102                 push_ascii(buf+1,mask2,8, 0);
103                 push_ascii(buf+9,p+1,3, 0);
104                 *p = '.';
105         } else {
106                 push_ascii(buf+1,mask2,11, 0);
107         }
108
109         memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
110         SCVAL(buf,21,mode);
111         srv_put_dos_date(buf,22,date);
112         SSVAL(buf,26,size & 0xFFFF);
113         SSVAL(buf,28,(size >> 16)&0xFFFF);
114         /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
115            Strange, but verified on W2K3. Needed for OS/2. JRA. */
116         push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
117         DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
118         return True;
119 }
120
121 /****************************************************************************
122  Initialise the dir bitmap.
123 ****************************************************************************/
124
125 bool init_dptrs(struct smbd_server_connection *sconn)
126 {
127         if (sconn->searches.dptr_bmap) {
128                 return true;
129         }
130
131         sconn->searches.dptr_bmap = bitmap_talloc(
132                 sconn, MAX_DIRECTORY_HANDLES);
133
134         if (sconn->searches.dptr_bmap == NULL) {
135                 return false;
136         }
137
138         return true;
139 }
140
141 /****************************************************************************
142  Idle a dptr - the directory is closed but the control info is kept.
143 ****************************************************************************/
144
145 static void dptr_idle(struct dptr_struct *dptr)
146 {
147         if (dptr->dir_hnd) {
148                 DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
149                 TALLOC_FREE(dptr->dir_hnd);
150         }
151 }
152
153 /****************************************************************************
154  Idle the oldest dptr.
155 ****************************************************************************/
156
157 static void dptr_idleoldest(struct smbd_server_connection *sconn)
158 {
159         struct dptr_struct *dptr;
160
161         /*
162          * Go to the end of the list.
163          */
164         dptr = DLIST_TAIL(sconn->searches.dirptrs);
165
166         if(!dptr) {
167                 DEBUG(0,("No dptrs available to idle ?\n"));
168                 return;
169         }
170
171         /*
172          * Idle the oldest pointer.
173          */
174
175         for(; dptr; dptr = DLIST_PREV(dptr)) {
176                 if (dptr->dir_hnd) {
177                         dptr_idle(dptr);
178                         return;
179                 }
180         }
181 }
182
183 /****************************************************************************
184  Get the struct dptr_struct for a dir index.
185 ****************************************************************************/
186
187 static struct dptr_struct *dptr_get(struct smbd_server_connection *sconn,
188                                     int key, bool forclose)
189 {
190         struct dptr_struct *dptr;
191
192         for(dptr = sconn->searches.dirptrs; dptr; dptr = dptr->next) {
193                 if(dptr->dnum == key) {
194                         if (!forclose && !dptr->dir_hnd) {
195                                 if (sconn->searches.dirhandles_open >= MAX_OPEN_DIRECTORIES)
196                                         dptr_idleoldest(sconn);
197                                 DEBUG(4,("dptr_get: Reopening dptr key %d\n",key));
198                                 if (!(dptr->dir_hnd = OpenDir(
199                                               NULL, dptr->conn, dptr->path,
200                                               dptr->wcard, dptr->attr))) {
201                                         DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path,
202                                                 strerror(errno)));
203                                         return False;
204                                 }
205                         }
206                         DLIST_PROMOTE(sconn->searches.dirptrs,dptr);
207                         return dptr;
208                 }
209         }
210         return(NULL);
211 }
212
213 /****************************************************************************
214  Get the dir path for a dir index.
215 ****************************************************************************/
216
217 char *dptr_path(struct smbd_server_connection *sconn, int key)
218 {
219         struct dptr_struct *dptr = dptr_get(sconn, key, false);
220         if (dptr)
221                 return(dptr->path);
222         return(NULL);
223 }
224
225 /****************************************************************************
226  Get the dir wcard for a dir index.
227 ****************************************************************************/
228
229 char *dptr_wcard(struct smbd_server_connection *sconn, int key)
230 {
231         struct dptr_struct *dptr = dptr_get(sconn, key, false);
232         if (dptr)
233                 return(dptr->wcard);
234         return(NULL);
235 }
236
237 /****************************************************************************
238  Get the dir attrib for a dir index.
239 ****************************************************************************/
240
241 uint16 dptr_attr(struct smbd_server_connection *sconn, int key)
242 {
243         struct dptr_struct *dptr = dptr_get(sconn, key, false);
244         if (dptr)
245                 return(dptr->attr);
246         return(0);
247 }
248
249 /****************************************************************************
250  Close a dptr (internal func).
251 ****************************************************************************/
252
253 static void dptr_close_internal(struct dptr_struct *dptr)
254 {
255         struct smbd_server_connection *sconn = dptr->conn->sconn;
256
257         DEBUG(4,("closing dptr key %d\n",dptr->dnum));
258
259         if (sconn == NULL) {
260                 goto done;
261         }
262
263         DLIST_REMOVE(sconn->searches.dirptrs, dptr);
264
265         /*
266          * Free the dnum in the bitmap. Remember the dnum value is always 
267          * biased by one with respect to the bitmap.
268          */
269
270         if (!bitmap_query(sconn->searches.dptr_bmap, dptr->dnum - 1)) {
271                 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
272                         dptr->dnum ));
273         }
274
275         bitmap_clear(sconn->searches.dptr_bmap, dptr->dnum - 1);
276
277 done:
278         TALLOC_FREE(dptr->dir_hnd);
279
280         /* Lanman 2 specific code */
281         SAFE_FREE(dptr->wcard);
282         SAFE_FREE(dptr->path);
283         SAFE_FREE(dptr);
284 }
285
286 /****************************************************************************
287  Close a dptr given a key.
288 ****************************************************************************/
289
290 void dptr_close(struct smbd_server_connection *sconn, int *key)
291 {
292         struct dptr_struct *dptr;
293
294         if(*key == INVALID_DPTR_KEY)
295                 return;
296
297         /* OS/2 seems to use -1 to indicate "close all directories" */
298         if (*key == -1) {
299                 struct dptr_struct *next;
300                 for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
301                         next = dptr->next;
302                         dptr_close_internal(dptr);
303                 }
304                 *key = INVALID_DPTR_KEY;
305                 return;
306         }
307
308         dptr = dptr_get(sconn, *key, true);
309
310         if (!dptr) {
311                 DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
312                 return;
313         }
314
315         dptr_close_internal(dptr);
316
317         *key = INVALID_DPTR_KEY;
318 }
319
320 /****************************************************************************
321  Close all dptrs for a cnum.
322 ****************************************************************************/
323
324 void dptr_closecnum(connection_struct *conn)
325 {
326         struct dptr_struct *dptr, *next;
327         struct smbd_server_connection *sconn = conn->sconn;
328
329         if (sconn == NULL) {
330                 return;
331         }
332
333         for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
334                 next = dptr->next;
335                 if (dptr->conn == conn) {
336                         dptr_close_internal(dptr);
337                 }
338         }
339 }
340
341 /****************************************************************************
342  Idle all dptrs for a cnum.
343 ****************************************************************************/
344
345 void dptr_idlecnum(connection_struct *conn)
346 {
347         struct dptr_struct *dptr;
348         struct smbd_server_connection *sconn = conn->sconn;
349
350         if (sconn == NULL) {
351                 return;
352         }
353
354         for(dptr = sconn->searches.dirptrs; dptr; dptr = dptr->next) {
355                 if (dptr->conn == conn && dptr->dir_hnd) {
356                         dptr_idle(dptr);
357                 }
358         }
359 }
360
361 /****************************************************************************
362  Close a dptr that matches a given path, only if it matches the spid also.
363 ****************************************************************************/
364
365 void dptr_closepath(struct smbd_server_connection *sconn,
366                     char *path,uint16 spid)
367 {
368         struct dptr_struct *dptr, *next;
369         for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
370                 next = dptr->next;
371                 if (spid == dptr->spid && strequal(dptr->path,path))
372                         dptr_close_internal(dptr);
373         }
374 }
375
376 /****************************************************************************
377  Try and close the oldest handle not marked for
378  expect close in the hope that the client has
379  finished with that one.
380 ****************************************************************************/
381
382 static void dptr_close_oldest(struct smbd_server_connection *sconn,
383                               bool old)
384 {
385         struct dptr_struct *dptr;
386
387         /*
388          * Go to the end of the list.
389          */
390         for(dptr = sconn->searches.dirptrs; dptr && dptr->next; dptr = dptr->next)
391                 ;
392
393         if(!dptr) {
394                 DEBUG(0,("No old dptrs available to close oldest ?\n"));
395                 return;
396         }
397
398         /*
399          * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
400          * does not have expect_close set. If 'old' is false, close
401          * one of the new dnum handles.
402          */
403
404         for(; dptr; dptr = DLIST_PREV(dptr)) {
405                 if ((old && (dptr->dnum < 256) && !dptr->expect_close) ||
406                         (!old && (dptr->dnum > 255))) {
407                                 dptr_close_internal(dptr);
408                                 return;
409                 }
410         }
411 }
412
413 /****************************************************************************
414  Create a new dir ptr. If the flag old_handle is true then we must allocate
415  from the bitmap range 0 - 255 as old SMBsearch directory handles are only
416  one byte long. If old_handle is false we allocate from the range
417  256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
418  a directory handle is never zero.
419  wcard must not be zero.
420 ****************************************************************************/
421
422 NTSTATUS dptr_create(connection_struct *conn, files_struct *fsp,
423                 const char *path, bool old_handle, bool expect_close,uint16 spid,
424                 const char *wcard, bool wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret)
425 {
426         struct smbd_server_connection *sconn = conn->sconn;
427         struct dptr_struct *dptr = NULL;
428         struct smb_Dir *dir_hnd;
429         NTSTATUS status;
430
431         if (fsp && fsp->is_directory && fsp->fh->fd != -1) {
432                 path = fsp->fsp_name->base_name;
433         }
434
435         DEBUG(5,("dptr_create dir=%s\n", path));
436
437         if (sconn == NULL) {
438                 DEBUG(0,("dptr_create: called with fake connection_struct\n"));
439                 return NT_STATUS_INTERNAL_ERROR;
440         }
441
442         if (!wcard) {
443                 return NT_STATUS_INVALID_PARAMETER;
444         }
445
446         if (fsp) {
447                 dir_hnd = OpenDir_fsp(NULL, conn, fsp, wcard, attr);
448         } else {
449                 status = check_name(conn,path);
450                 if (!NT_STATUS_IS_OK(status)) {
451                         return status;
452                 }
453                 dir_hnd = OpenDir(NULL, conn, path, wcard, attr);
454         }
455
456         if (!dir_hnd) {
457                 return map_nt_error_from_unix(errno);
458         }
459
460         if (sconn->searches.dirhandles_open >= MAX_OPEN_DIRECTORIES) {
461                 dptr_idleoldest(sconn);
462         }
463
464         dptr = SMB_MALLOC_P(struct dptr_struct);
465         if(!dptr) {
466                 DEBUG(0,("malloc fail in dptr_create.\n"));
467                 TALLOC_FREE(dir_hnd);
468                 return NT_STATUS_NO_MEMORY;
469         }
470
471         ZERO_STRUCTP(dptr);
472
473         dptr->path = SMB_STRDUP(path);
474         if (!dptr->path) {
475                 SAFE_FREE(dptr);
476                 TALLOC_FREE(dir_hnd);
477                 return NT_STATUS_NO_MEMORY;
478         }
479         dptr->conn = conn;
480         dptr->dir_hnd = dir_hnd;
481         dptr->spid = spid;
482         dptr->expect_close = expect_close;
483         dptr->wcard = SMB_STRDUP(wcard);
484         if (!dptr->wcard) {
485                 SAFE_FREE(dptr->path);
486                 SAFE_FREE(dptr);
487                 TALLOC_FREE(dir_hnd);
488                 return NT_STATUS_NO_MEMORY;
489         }
490         if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) {
491                 dptr->has_wild = True;
492         } else {
493                 dptr->has_wild = wcard_has_wild;
494         }
495
496         dptr->attr = attr;
497
498         if(old_handle) {
499
500                 /*
501                  * This is an old-style SMBsearch request. Ensure the
502                  * value we return will fit in the range 1-255.
503                  */
504
505                 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 0);
506
507                 if(dptr->dnum == -1 || dptr->dnum > 254) {
508
509                         /*
510                          * Try and close the oldest handle not marked for
511                          * expect close in the hope that the client has
512                          * finished with that one.
513                          */
514
515                         dptr_close_oldest(sconn, true);
516
517                         /* Now try again... */
518                         dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 0);
519                         if(dptr->dnum == -1 || dptr->dnum > 254) {
520                                 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
521                                 SAFE_FREE(dptr->path);
522                                 SAFE_FREE(dptr->wcard);
523                                 SAFE_FREE(dptr);
524                                 TALLOC_FREE(dir_hnd);
525                                 return NT_STATUS_TOO_MANY_OPENED_FILES;
526                         }
527                 }
528         } else {
529
530                 /*
531                  * This is a new-style trans2 request. Allocate from
532                  * a range that will return 256 - MAX_DIRECTORY_HANDLES.
533                  */
534
535                 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 255);
536
537                 if(dptr->dnum == -1 || dptr->dnum < 255) {
538
539                         /*
540                          * Try and close the oldest handle close in the hope that
541                          * the client has finished with that one. This will only
542                          * happen in the case of the Win98 client bug where it leaks
543                          * directory handles.
544                          */
545
546                         dptr_close_oldest(sconn, false);
547
548                         /* Now try again... */
549                         dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 255);
550
551                         if(dptr->dnum == -1 || dptr->dnum < 255) {
552                                 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
553                                 SAFE_FREE(dptr->path);
554                                 SAFE_FREE(dptr->wcard);
555                                 SAFE_FREE(dptr);
556                                 TALLOC_FREE(dir_hnd);
557                                 return NT_STATUS_TOO_MANY_OPENED_FILES;
558                         }
559                 }
560         }
561
562         bitmap_set(sconn->searches.dptr_bmap, dptr->dnum);
563
564         dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
565
566         DLIST_ADD(sconn->searches.dirptrs, dptr);
567
568         DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
569                 dptr->dnum,path,expect_close));  
570
571         *dptr_ret = dptr;
572
573         return NT_STATUS_OK;
574 }
575
576
577 /****************************************************************************
578  Wrapper functions to access the lower level directory handles.
579 ****************************************************************************/
580
581 void dptr_CloseDir(files_struct *fsp)
582 {
583         if (fsp->dptr) {
584 /*
585  * Ugly hack. We have defined fdopendir to return ENOSYS if dirfd also isn't
586  * present. I hate Solaris. JRA.
587  */
588 #ifdef HAVE_DIRFD
589                 if (fsp->fh->fd != -1 &&
590                                 fsp->dptr->dir_hnd &&
591                                 dirfd(fsp->dptr->dir_hnd->dir)) {
592                         /* The call below closes the underlying fd. */
593                         fsp->fh->fd = -1;
594                 }
595 #endif
596                 dptr_close_internal(fsp->dptr);
597                 fsp->dptr = NULL;
598         }
599 }
600
601 void dptr_SeekDir(struct dptr_struct *dptr, long offset)
602 {
603         SeekDir(dptr->dir_hnd, offset);
604 }
605
606 long dptr_TellDir(struct dptr_struct *dptr)
607 {
608         return TellDir(dptr->dir_hnd);
609 }
610
611 bool dptr_has_wild(struct dptr_struct *dptr)
612 {
613         return dptr->has_wild;
614 }
615
616 int dptr_dnum(struct dptr_struct *dptr)
617 {
618         return dptr->dnum;
619 }
620
621 /****************************************************************************
622  Return the next visible file name, skipping veto'd and invisible files.
623 ****************************************************************************/
624
625 static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr,
626                                            long *poffset, SMB_STRUCT_STAT *pst,
627                                            char **ptalloced)
628 {
629         /* Normal search for the next file. */
630         const char *name;
631         char *talloced = NULL;
632
633         while ((name = ReadDirName(dptr->dir_hnd, poffset, pst, &talloced))
634                != NULL) {
635                 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
636                         *ptalloced = talloced;
637                         return name;
638                 }
639                 TALLOC_FREE(talloced);
640         }
641         return NULL;
642 }
643
644 /****************************************************************************
645  Return the next visible file name, skipping veto'd and invisible files.
646 ****************************************************************************/
647
648 char *dptr_ReadDirName(TALLOC_CTX *ctx,
649                         struct dptr_struct *dptr,
650                         long *poffset,
651                         SMB_STRUCT_STAT *pst)
652 {
653         struct smb_filename smb_fname_base;
654         char *name = NULL;
655         const char *name_temp = NULL;
656         char *talloced = NULL;
657         char *pathreal = NULL;
658         char *found_name = NULL;
659         int ret;
660
661         SET_STAT_INVALID(*pst);
662
663         if (dptr->has_wild || dptr->did_stat) {
664                 name_temp = dptr_normal_ReadDirName(dptr, poffset, pst,
665                                                     &talloced);
666                 if (name_temp == NULL) {
667                         return NULL;
668                 }
669                 if (talloced != NULL) {
670                         return talloc_move(ctx, &talloced);
671                 }
672                 return talloc_strdup(ctx, name_temp);
673         }
674
675         /* If poffset is -1 then we know we returned this name before and we
676          * have no wildcards. We're at the end of the directory. */
677         if (*poffset == END_OF_DIRECTORY_OFFSET) {
678                 return NULL;
679         }
680
681         /* We know the stored wcard contains no wildcard characters.
682          * See if we can match with a stat call. If we can't, then set
683          * did_stat to true to ensure we only do this once and keep
684          * searching. */
685
686         dptr->did_stat = true;
687
688         /* First check if it should be visible. */
689         if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard,
690             pst, true))
691         {
692                 /* This only returns false if the file was found, but
693                    is explicitly not visible. Set us to end of
694                    directory, but return NULL as we know we can't ever
695                    find it. */
696                 goto ret;
697         }
698
699         if (VALID_STAT(*pst)) {
700                 name = talloc_strdup(ctx, dptr->wcard);
701                 goto ret;
702         }
703
704         pathreal = talloc_asprintf(ctx,
705                                 "%s/%s",
706                                 dptr->path,
707                                 dptr->wcard);
708         if (!pathreal)
709                 return NULL;
710
711         /* Create an smb_filename with stream_name == NULL. */
712         ZERO_STRUCT(smb_fname_base);
713         smb_fname_base.base_name = pathreal;
714
715         if (SMB_VFS_STAT(dptr->conn, &smb_fname_base) == 0) {
716                 *pst = smb_fname_base.st;
717                 name = talloc_strdup(ctx, dptr->wcard);
718                 goto clean;
719         } else {
720                 /* If we get any other error than ENOENT or ENOTDIR
721                    then the file exists we just can't stat it. */
722                 if (errno != ENOENT && errno != ENOTDIR) {
723                         name = talloc_strdup(ctx, dptr->wcard);
724                         goto clean;
725                 }
726         }
727
728         /* Stat failed. We know this is authoratiative if we are
729          * providing case sensitive semantics or the underlying
730          * filesystem is case sensitive.
731          */
732         if (dptr->conn->case_sensitive ||
733             !(dptr->conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH))
734         {
735                 goto clean;
736         }
737
738         /*
739          * Try case-insensitive stat if the fs has the ability. This avoids
740          * scanning the whole directory.
741          */
742         ret = SMB_VFS_GET_REAL_FILENAME(dptr->conn, dptr->path, dptr->wcard,
743                                         ctx, &found_name);
744         if (ret == 0) {
745                 name = found_name;
746                 goto clean;
747         } else if (errno == ENOENT) {
748                 /* The case-insensitive lookup was authoritative. */
749                 goto clean;
750         }
751
752         TALLOC_FREE(pathreal);
753
754         name_temp = dptr_normal_ReadDirName(dptr, poffset, pst, &talloced);
755         if (name_temp == NULL) {
756                 return NULL;
757         }
758         if (talloced != NULL) {
759                 return talloc_move(ctx, &talloced);
760         }
761         return talloc_strdup(ctx, name_temp);
762
763 clean:
764         TALLOC_FREE(pathreal);
765 ret:
766         /* We need to set the underlying dir_hnd offset to -1
767          * also as this function is usually called with the
768          * output from TellDir. */
769         dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
770         return name;
771 }
772
773 /****************************************************************************
774  Search for a file by name, skipping veto'ed and not visible files.
775 ****************************************************************************/
776
777 bool dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
778 {
779         SET_STAT_INVALID(*pst);
780
781         if (!dptr->has_wild && (dptr->dir_hnd->offset == END_OF_DIRECTORY_OFFSET)) {
782                 /* This is a singleton directory and we're already at the end. */
783                 *poffset = END_OF_DIRECTORY_OFFSET;
784                 return False;
785         }
786
787         return SearchDir(dptr->dir_hnd, name, poffset);
788 }
789
790 /****************************************************************************
791  Add the name we're returning into the underlying cache.
792 ****************************************************************************/
793
794 void dptr_DirCacheAdd(struct dptr_struct *dptr, const char *name, long offset)
795 {
796         DirCacheAdd(dptr->dir_hnd, name, offset);
797 }
798
799 /****************************************************************************
800  Initialize variables & state data at the beginning of all search SMB requests.
801 ****************************************************************************/
802 void dptr_init_search_op(struct dptr_struct *dptr)
803 {
804         SMB_VFS_INIT_SEARCH_OP(dptr->conn, dptr->dir_hnd->dir);
805 }
806
807 /****************************************************************************
808  Fill the 5 byte server reserved dptr field.
809 ****************************************************************************/
810
811 bool dptr_fill(struct smbd_server_connection *sconn,
812                char *buf1,unsigned int key)
813 {
814         unsigned char *buf = (unsigned char *)buf1;
815         struct dptr_struct *dptr = dptr_get(sconn, key, false);
816         uint32 offset;
817         if (!dptr) {
818                 DEBUG(1,("filling null dirptr %d\n",key));
819                 return(False);
820         }
821         offset = (uint32)TellDir(dptr->dir_hnd);
822         DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
823                 (long)dptr->dir_hnd,(int)offset));
824         buf[0] = key;
825         SIVAL(buf,1,offset);
826         return(True);
827 }
828
829 /****************************************************************************
830  Fetch the dir ptr and seek it given the 5 byte server field.
831 ****************************************************************************/
832
833 struct dptr_struct *dptr_fetch(struct smbd_server_connection *sconn,
834                                char *buf, int *num)
835 {
836         unsigned int key = *(unsigned char *)buf;
837         struct dptr_struct *dptr = dptr_get(sconn, key, false);
838         uint32 offset;
839         long seekoff;
840
841         if (!dptr) {
842                 DEBUG(3,("fetched null dirptr %d\n",key));
843                 return(NULL);
844         }
845         *num = key;
846         offset = IVAL(buf,1);
847         if (offset == (uint32)-1) {
848                 seekoff = END_OF_DIRECTORY_OFFSET;
849         } else {
850                 seekoff = (long)offset;
851         }
852         SeekDir(dptr->dir_hnd,seekoff);
853         DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
854                 key, dptr->path, (int)seekoff));
855         return(dptr);
856 }
857
858 /****************************************************************************
859  Fetch the dir ptr.
860 ****************************************************************************/
861
862 struct dptr_struct *dptr_fetch_lanman2(struct smbd_server_connection *sconn,
863                                        int dptr_num)
864 {
865         struct dptr_struct *dptr  = dptr_get(sconn, dptr_num, false);
866
867         if (!dptr) {
868                 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
869                 return(NULL);
870         }
871         DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr->path));
872         return(dptr);
873 }
874
875 /****************************************************************************
876  Check that a file matches a particular file type.
877 ****************************************************************************/
878
879 bool dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype)
880 {
881         uint32 mask;
882
883         /* Check the "may have" search bits. */
884         if (((mode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY)) != 0)
885                 return False;
886
887         /* Check the "must have" bits, which are the may have bits shifted eight */
888         /* If must have bit is set, the file/dir can not be returned in search unless the matching
889                 file attribute is set */
890         mask = ((dirtype >> 8) & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)); /* & 0x37 */
891         if(mask) {
892                 if((mask & (mode & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM))) == mask)   /* check if matching attribute present */
893                         return True;
894                 else
895                         return False;
896         }
897
898         return True;
899 }
900
901 static bool mangle_mask_match(connection_struct *conn,
902                 const char *filename,
903                 const char *mask)
904 {
905         char mname[13];
906
907         if (!name_to_8_3(filename,mname,False,conn->params)) {
908                 return False;
909         }
910         return mask_match_search(mname,mask,False);
911 }
912
913 bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
914                            struct dptr_struct *dirptr,
915                            const char *mask,
916                            uint32_t dirtype,
917                            bool dont_descend,
918                            bool ask_sharemode,
919                            bool (*match_fn)(TALLOC_CTX *ctx,
920                                             void *private_data,
921                                             const char *dname,
922                                             const char *mask,
923                                             char **_fname),
924                            bool (*mode_fn)(TALLOC_CTX *ctx,
925                                            void *private_data,
926                                            struct smb_filename *smb_fname,
927                                            uint32_t *_mode),
928                            void *private_data,
929                            char **_fname,
930                            struct smb_filename **_smb_fname,
931                            uint32_t *_mode,
932                            long *_prev_offset)
933 {
934         connection_struct *conn = dirptr->conn;
935         bool needslash;
936
937         *_smb_fname = NULL;
938         *_mode = 0;
939
940         needslash = ( dirptr->path[strlen(dirptr->path) -1] != '/');
941
942         while (true) {
943                 long cur_offset;
944                 long prev_offset;
945                 SMB_STRUCT_STAT sbuf;
946                 char *dname = NULL;
947                 bool isdots;
948                 char *fname = NULL;
949                 char *pathreal = NULL;
950                 struct smb_filename smb_fname;
951                 uint32_t mode = 0;
952                 bool ok;
953                 NTSTATUS status;
954
955                 cur_offset = dptr_TellDir(dirptr);
956                 prev_offset = cur_offset;
957                 dname = dptr_ReadDirName(ctx, dirptr, &cur_offset, &sbuf);
958
959                 DEBUG(6,("smbd_dirptr_get_entry: dirptr 0x%lx now at offset %ld\n",
960                         (long)dirptr, cur_offset));
961
962                 if (dname == NULL) {
963                         return false;
964                 }
965
966                 isdots = (ISDOT(dname) || ISDOTDOT(dname));
967                 if (dont_descend && !isdots) {
968                         TALLOC_FREE(dname);
969                         continue;
970                 }
971
972                 /*
973                  * fname may get mangled, dname is never mangled.
974                  * Whenever we're accessing the filesystem we use
975                  * pathreal which is composed from dname.
976                  */
977
978                 ok = match_fn(ctx, private_data, dname, mask, &fname);
979                 if (!ok) {
980                         TALLOC_FREE(dname);
981                         continue;
982                 }
983
984                 pathreal = talloc_asprintf(ctx, "%s%s%s",
985                                            dirptr->path,
986                                            needslash?"/":"",
987                                            dname);
988                 if (!pathreal) {
989                         TALLOC_FREE(dname);
990                         TALLOC_FREE(fname);
991                         return false;
992                 }
993
994                 /* Create smb_fname with NULL stream_name. */
995                 ZERO_STRUCT(smb_fname);
996                 smb_fname.base_name = pathreal;
997                 smb_fname.st = sbuf;
998
999                 ok = mode_fn(ctx, private_data, &smb_fname, &mode);
1000                 if (!ok) {
1001                         TALLOC_FREE(dname);
1002                         TALLOC_FREE(fname);
1003                         TALLOC_FREE(pathreal);
1004                         continue;
1005                 }
1006
1007                 if (!dir_check_ftype(conn, mode, dirtype)) {
1008                         DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",
1009                                 fname, (unsigned int)mode, (unsigned int)dirtype));
1010                         TALLOC_FREE(dname);
1011                         TALLOC_FREE(fname);
1012                         TALLOC_FREE(pathreal);
1013                         continue;
1014                 }
1015
1016                 if (ask_sharemode) {
1017                         struct timespec write_time_ts;
1018                         struct file_id fileid;
1019
1020                         fileid = vfs_file_id_from_sbuf(conn,
1021                                                        &smb_fname.st);
1022                         get_file_infos(fileid, 0, NULL, &write_time_ts);
1023                         if (!null_timespec(write_time_ts)) {
1024                                 update_stat_ex_mtime(&smb_fname.st,
1025                                                      write_time_ts);
1026                         }
1027                 }
1028
1029                 DEBUG(3,("smbd_dirptr_get_entry mask=[%s] found %s "
1030                         "fname=%s (%s)\n",
1031                         mask, smb_fname_str_dbg(&smb_fname),
1032                         dname, fname));
1033
1034                 DirCacheAdd(dirptr->dir_hnd, dname, cur_offset);
1035
1036                 TALLOC_FREE(dname);
1037
1038                 status = copy_smb_filename(ctx, &smb_fname, _smb_fname);
1039                 TALLOC_FREE(pathreal);
1040                 if (!NT_STATUS_IS_OK(status)) {
1041                         return false;
1042                 }
1043                 *_fname = fname;
1044                 *_mode = mode;
1045                 *_prev_offset = prev_offset;
1046
1047                 return true;
1048         }
1049
1050         return false;
1051 }
1052
1053 /****************************************************************************
1054  Get an 8.3 directory entry.
1055 ****************************************************************************/
1056
1057 static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX *ctx,
1058                                      void *private_data,
1059                                      const char *dname,
1060                                      const char *mask,
1061                                      char **_fname)
1062 {
1063         connection_struct *conn = (connection_struct *)private_data;
1064
1065         if ((strcmp(mask,"*.*") == 0) ||
1066             mask_match_search(dname, mask, false) ||
1067             mangle_mask_match(conn, dname, mask)) {
1068                 char mname[13];
1069                 const char *fname;
1070
1071                 if (!mangle_is_8_3(dname, false, conn->params)) {
1072                         bool ok = name_to_8_3(dname, mname, false,
1073                                               conn->params);
1074                         if (!ok) {
1075                                 return false;
1076                         }
1077                         fname = mname;
1078                 } else {
1079                         fname = dname;
1080                 }
1081
1082                 *_fname = talloc_strdup(ctx, fname);
1083                 if (*_fname == NULL) {
1084                         return false;
1085                 }
1086
1087                 return true;
1088         }
1089
1090         return false;
1091 }
1092
1093 static bool smbd_dirptr_8_3_mode_fn(TALLOC_CTX *ctx,
1094                                     void *private_data,
1095                                     struct smb_filename *smb_fname,
1096                                     uint32_t *_mode)
1097 {
1098         connection_struct *conn = (connection_struct *)private_data;
1099
1100         if (!VALID_STAT(smb_fname->st)) {
1101                 if ((SMB_VFS_STAT(conn, smb_fname)) != 0) {
1102                         DEBUG(5,("smbd_dirptr_8_3_mode_fn: "
1103                                  "Couldn't stat [%s]. Error "
1104                                  "= %s\n",
1105                                  smb_fname_str_dbg(smb_fname),
1106                                  strerror(errno)));
1107                         return false;
1108                 }
1109         }
1110
1111         *_mode = dos_mode(conn, smb_fname);
1112         return true;
1113 }
1114
1115 bool get_dir_entry(TALLOC_CTX *ctx,
1116                 struct dptr_struct *dirptr,
1117                 const char *mask,
1118                 uint32_t dirtype,
1119                 char **_fname,
1120                 SMB_OFF_T *_size,
1121                 uint32_t *_mode,
1122                 struct timespec *_date,
1123                 bool check_descend,
1124                 bool ask_sharemode)
1125 {
1126         connection_struct *conn = dirptr->conn;
1127         char *fname = NULL;
1128         struct smb_filename *smb_fname = NULL;
1129         uint32_t mode = 0;
1130         long prev_offset;
1131         bool ok;
1132
1133         ok = smbd_dirptr_get_entry(ctx,
1134                                    dirptr,
1135                                    mask,
1136                                    dirtype,
1137                                    check_descend,
1138                                    ask_sharemode,
1139                                    smbd_dirptr_8_3_match_fn,
1140                                    smbd_dirptr_8_3_mode_fn,
1141                                    conn,
1142                                    &fname,
1143                                    &smb_fname,
1144                                    &mode,
1145                                    &prev_offset);
1146         if (!ok) {
1147                 return false;
1148         }
1149
1150         *_fname = talloc_move(ctx, &fname);
1151         *_size = smb_fname->st.st_ex_size;
1152         *_mode = mode;
1153         *_date = smb_fname->st.st_ex_mtime;
1154         TALLOC_FREE(smb_fname);
1155         return true;
1156 }
1157
1158 /*******************************************************************
1159  Check to see if a user can read a file. This is only approximate,
1160  it is used as part of the "hide unreadable" option. Don't
1161  use it for anything security sensitive.
1162 ********************************************************************/
1163
1164 static bool user_can_read_file(connection_struct *conn,
1165                                struct smb_filename *smb_fname)
1166 {
1167         /*
1168          * Never hide files from the root user.
1169          * We use (uid_t)0 here not sec_initial_uid()
1170          * as make test uses a single user context.
1171          */
1172
1173         if (get_current_uid(conn) == (uid_t)0) {
1174                 return True;
1175         }
1176
1177         return can_access_file_acl(conn, smb_fname, FILE_READ_DATA);
1178 }
1179
1180 /*******************************************************************
1181  Check to see if a user can write a file (and only files, we do not
1182  check dirs on this one). This is only approximate,
1183  it is used as part of the "hide unwriteable" option. Don't
1184  use it for anything security sensitive.
1185 ********************************************************************/
1186
1187 static bool user_can_write_file(connection_struct *conn,
1188                                 const struct smb_filename *smb_fname)
1189 {
1190         /*
1191          * Never hide files from the root user.
1192          * We use (uid_t)0 here not sec_initial_uid()
1193          * as make test uses a single user context.
1194          */
1195
1196         if (get_current_uid(conn) == (uid_t)0) {
1197                 return True;
1198         }
1199
1200         SMB_ASSERT(VALID_STAT(smb_fname->st));
1201
1202         /* Pseudo-open the file */
1203
1204         if(S_ISDIR(smb_fname->st.st_ex_mode)) {
1205                 return True;
1206         }
1207
1208         return can_write_to_file(conn, smb_fname);
1209 }
1210
1211 /*******************************************************************
1212   Is a file a "special" type ?
1213 ********************************************************************/
1214
1215 static bool file_is_special(connection_struct *conn,
1216                             const struct smb_filename *smb_fname)
1217 {
1218         /*
1219          * Never hide files from the root user.
1220          * We use (uid_t)0 here not sec_initial_uid()
1221          * as make test uses a single user context.
1222          */
1223
1224         if (get_current_uid(conn) == (uid_t)0) {
1225                 return False;
1226         }
1227
1228         SMB_ASSERT(VALID_STAT(smb_fname->st));
1229
1230         if (S_ISREG(smb_fname->st.st_ex_mode) ||
1231             S_ISDIR(smb_fname->st.st_ex_mode) ||
1232             S_ISLNK(smb_fname->st.st_ex_mode))
1233                 return False;
1234
1235         return True;
1236 }
1237
1238 /*******************************************************************
1239  Should the file be seen by the client?
1240  NOTE: A successful return is no guarantee of the file's existence.
1241 ********************************************************************/
1242
1243 bool is_visible_file(connection_struct *conn, const char *dir_path,
1244                      const char *name, SMB_STRUCT_STAT *pst, bool use_veto)
1245 {
1246         bool hide_unreadable = lp_hideunreadable(SNUM(conn));
1247         bool hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
1248         bool hide_special = lp_hide_special_files(SNUM(conn));
1249         char *entry = NULL;
1250         struct smb_filename *smb_fname_base = NULL;
1251         NTSTATUS status;
1252         bool ret = false;
1253
1254         if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
1255                 return True; /* . and .. are always visible. */
1256         }
1257
1258         /* If it's a vetoed file, pretend it doesn't even exist */
1259         if (use_veto && IS_VETO_PATH(conn, name)) {
1260                 DEBUG(10,("is_visible_file: file %s is vetoed.\n", name ));
1261                 return False;
1262         }
1263
1264         if (hide_unreadable || hide_unwriteable || hide_special) {
1265                 entry = talloc_asprintf(talloc_tos(), "%s/%s", dir_path, name);
1266                 if (!entry) {
1267                         ret = false;
1268                         goto out;
1269                 }
1270
1271                 /* Create an smb_filename with stream_name == NULL. */
1272                 status = create_synthetic_smb_fname(talloc_tos(), entry, NULL,
1273                                                     pst, &smb_fname_base);
1274                 if (!NT_STATUS_IS_OK(status)) {
1275                         ret = false;
1276                         goto out;
1277                 }
1278
1279                 /* If the file name does not exist, there's no point checking
1280                  * the configuration options. We succeed, on the basis that the
1281                  * checks *might* have passed if the file was present.
1282                  */
1283                 if (!VALID_STAT(*pst)) {
1284                         if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
1285                                 ret = true;
1286                                 goto out;
1287                         } else {
1288                                 *pst = smb_fname_base->st;
1289                         }
1290                 }
1291
1292                 /* Honour _hide unreadable_ option */
1293                 if (hide_unreadable &&
1294                     !user_can_read_file(conn, smb_fname_base)) {
1295                         DEBUG(10,("is_visible_file: file %s is unreadable.\n",
1296                                  entry ));
1297                         ret = false;
1298                         goto out;
1299                 }
1300                 /* Honour _hide unwriteable_ option */
1301                 if (hide_unwriteable && !user_can_write_file(conn,
1302                                                              smb_fname_base)) {
1303                         DEBUG(10,("is_visible_file: file %s is unwritable.\n",
1304                                  entry ));
1305                         ret = false;
1306                         goto out;
1307                 }
1308                 /* Honour _hide_special_ option */
1309                 if (hide_special && file_is_special(conn, smb_fname_base)) {
1310                         DEBUG(10,("is_visible_file: file %s is special.\n",
1311                                  entry ));
1312                         ret = false;
1313                         goto out;
1314                 }
1315         }
1316
1317         ret = true;
1318  out:
1319         TALLOC_FREE(smb_fname_base);
1320         TALLOC_FREE(entry);
1321         return ret;
1322 }
1323
1324 static int smb_Dir_destructor(struct smb_Dir *dirp)
1325 {
1326         if (dirp->dir) {
1327 #ifdef HAVE_DIRFD
1328                 if (dirp->conn->sconn) {
1329                         files_struct *fsp = file_find_fd(dirp->conn->sconn,
1330                                                 dirfd(dirp->dir));
1331                         if (fsp) {
1332                                 /* The call below closes the underlying fd. */
1333                                 fsp->fh->fd = -1;
1334                         }
1335                 }
1336 #endif
1337                 SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1338         }
1339         if (dirp->conn->sconn) {
1340                 dirp->conn->sconn->searches.dirhandles_open--;
1341         }
1342         return 0;
1343 }
1344
1345 /*******************************************************************
1346  Open a directory.
1347 ********************************************************************/
1348
1349 struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
1350                         const char *name,
1351                         const char *mask,
1352                         uint32 attr)
1353 {
1354         struct smb_Dir *dirp = TALLOC_ZERO_P(mem_ctx, struct smb_Dir);
1355         struct smbd_server_connection *sconn = conn->sconn;
1356
1357         if (!dirp) {
1358                 return NULL;
1359         }
1360
1361         dirp->conn = conn;
1362         dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
1363
1364         dirp->dir_path = talloc_strdup(dirp, name);
1365         if (!dirp->dir_path) {
1366                 errno = ENOMEM;
1367                 goto fail;
1368         }
1369
1370         if (sconn) {
1371                 sconn->searches.dirhandles_open++;
1372         }
1373         talloc_set_destructor(dirp, smb_Dir_destructor);
1374
1375         dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
1376         if (!dirp->dir) {
1377                 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path,
1378                          strerror(errno) ));
1379                 goto fail;
1380         }
1381
1382         return dirp;
1383
1384   fail:
1385         TALLOC_FREE(dirp);
1386         return NULL;
1387 }
1388
1389 /*******************************************************************
1390  Open a directory from an fsp.
1391 ********************************************************************/
1392
1393 static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
1394                         files_struct *fsp,
1395                         const char *mask,
1396                         uint32 attr)
1397 {
1398         struct smb_Dir *dirp = TALLOC_ZERO_P(mem_ctx, struct smb_Dir);
1399         struct smbd_server_connection *sconn = conn->sconn;
1400
1401         if (!dirp) {
1402                 return NULL;
1403         }
1404
1405         dirp->conn = conn;
1406         dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
1407
1408         dirp->dir_path = talloc_strdup(dirp, fsp->fsp_name->base_name);
1409         if (!dirp->dir_path) {
1410                 errno = ENOMEM;
1411                 goto fail;
1412         }
1413
1414         if (sconn) {
1415                 sconn->searches.dirhandles_open++;
1416         }
1417         talloc_set_destructor(dirp, smb_Dir_destructor);
1418
1419         if (fsp->is_directory && fsp->fh->fd != -1) {
1420                 dirp->dir = SMB_VFS_FDOPENDIR(fsp, mask, attr);
1421                 if (dirp->dir == NULL) {
1422                         DEBUG(10,("OpenDir_fsp: SMB_VFS_FDOPENDIR on %s returned "
1423                                 "NULL (%s)\n",
1424                                 dirp->dir_path,
1425                                 strerror(errno)));
1426                         if (errno != ENOSYS) {
1427                                 return NULL;
1428                         }
1429                 }
1430         }
1431
1432         if (dirp->dir == NULL) {
1433                 /* FDOPENDIR didn't work. Use OPENDIR instead. */
1434                 dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
1435         }
1436
1437         if (!dirp->dir) {
1438                 DEBUG(5,("OpenDir_fsp: Can't open %s. %s\n", dirp->dir_path,
1439                          strerror(errno) ));
1440                 goto fail;
1441         }
1442
1443         return dirp;
1444
1445   fail:
1446         TALLOC_FREE(dirp);
1447         return NULL;
1448 }
1449
1450
1451 /*******************************************************************
1452  Read from a directory.
1453  Return directory entry, current offset, and optional stat information.
1454  Don't check for veto or invisible files.
1455 ********************************************************************/
1456
1457 const char *ReadDirName(struct smb_Dir *dirp, long *poffset,
1458                         SMB_STRUCT_STAT *sbuf, char **ptalloced)
1459 {
1460         const char *n;
1461         char *talloced = NULL;
1462         connection_struct *conn = dirp->conn;
1463
1464         /* Cheat to allow . and .. to be the first entries returned. */
1465         if (((*poffset == START_OF_DIRECTORY_OFFSET) ||
1466              (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2))
1467         {
1468                 if (dirp->file_number == 0) {
1469                         n = ".";
1470                         *poffset = dirp->offset = START_OF_DIRECTORY_OFFSET;
1471                 } else {
1472                         n = "..";
1473                         *poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET;
1474                 }
1475                 dirp->file_number++;
1476                 *ptalloced = NULL;
1477                 return n;
1478         } else if (*poffset == END_OF_DIRECTORY_OFFSET) {
1479                 *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1480                 return NULL;
1481         } else {
1482                 /* A real offset, seek to it. */
1483                 SeekDir(dirp, *poffset);
1484         }
1485
1486         while ((n = vfs_readdirname(conn, dirp->dir, sbuf, &talloced))) {
1487                 /* Ignore . and .. - we've already returned them. */
1488                 if (*n == '.') {
1489                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
1490                                 TALLOC_FREE(talloced);
1491                                 continue;
1492                         }
1493                 }
1494                 *poffset = dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1495                 *ptalloced = talloced;
1496                 dirp->file_number++;
1497                 return n;
1498         }
1499         *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1500         *ptalloced = NULL;
1501         return NULL;
1502 }
1503
1504 /*******************************************************************
1505  Rewind to the start.
1506 ********************************************************************/
1507
1508 void RewindDir(struct smb_Dir *dirp, long *poffset)
1509 {
1510         SMB_VFS_REWINDDIR(dirp->conn, dirp->dir);
1511         dirp->file_number = 0;
1512         dirp->offset = START_OF_DIRECTORY_OFFSET;
1513         *poffset = START_OF_DIRECTORY_OFFSET;
1514 }
1515
1516 /*******************************************************************
1517  Seek a dir.
1518 ********************************************************************/
1519
1520 void SeekDir(struct smb_Dir *dirp, long offset)
1521 {
1522         if (offset != dirp->offset) {
1523                 if (offset == START_OF_DIRECTORY_OFFSET) {
1524                         RewindDir(dirp, &offset);
1525                         /*
1526                          * Ok we should really set the file number here
1527                          * to 1 to enable ".." to be returned next. Trouble
1528                          * is I'm worried about callers using SeekDir(dirp,0)
1529                          * as equivalent to RewindDir(). So leave this alone
1530                          * for now.
1531                          */
1532                 } else if  (offset == DOT_DOT_DIRECTORY_OFFSET) {
1533                         RewindDir(dirp, &offset);
1534                         /*
1535                          * Set the file number to 2 - we want to get the first
1536                          * real file entry (the one we return after "..")
1537                          * on the next ReadDir.
1538                          */
1539                         dirp->file_number = 2;
1540                 } else if (offset == END_OF_DIRECTORY_OFFSET) {
1541                         ; /* Don't seek in this case. */
1542                 } else {
1543                         SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1544                 }
1545                 dirp->offset = offset;
1546         }
1547 }
1548
1549 /*******************************************************************
1550  Tell a dir position.
1551 ********************************************************************/
1552
1553 long TellDir(struct smb_Dir *dirp)
1554 {
1555         return(dirp->offset);
1556 }
1557
1558 /*******************************************************************
1559  Add an entry into the dcache.
1560 ********************************************************************/
1561
1562 void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
1563 {
1564         struct name_cache_entry *e;
1565
1566         if (dirp->name_cache_size == 0) {
1567                 return;
1568         }
1569
1570         if (dirp->name_cache == NULL) {
1571                 dirp->name_cache = TALLOC_ZERO_ARRAY(
1572                         dirp, struct name_cache_entry, dirp->name_cache_size);
1573
1574                 if (dirp->name_cache == NULL) {
1575                         return;
1576                 }
1577         }
1578
1579         dirp->name_cache_index = (dirp->name_cache_index+1) %
1580                                         dirp->name_cache_size;
1581         e = &dirp->name_cache[dirp->name_cache_index];
1582         TALLOC_FREE(e->name);
1583         e->name = talloc_strdup(dirp, name);
1584         e->offset = offset;
1585 }
1586
1587 /*******************************************************************
1588  Find an entry by name. Leave us at the offset after it.
1589  Don't check for veto or invisible files.
1590 ********************************************************************/
1591
1592 bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1593 {
1594         int i;
1595         const char *entry = NULL;
1596         char *talloced = NULL;
1597         connection_struct *conn = dirp->conn;
1598
1599         /* Search back in the name cache. */
1600         if (dirp->name_cache_size && dirp->name_cache) {
1601                 for (i = dirp->name_cache_index; i >= 0; i--) {
1602                         struct name_cache_entry *e = &dirp->name_cache[i];
1603                         if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1604                                 *poffset = e->offset;
1605                                 SeekDir(dirp, e->offset);
1606                                 return True;
1607                         }
1608                 }
1609                 for (i = dirp->name_cache_size - 1; i > dirp->name_cache_index; i--) {
1610                         struct name_cache_entry *e = &dirp->name_cache[i];
1611                         if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1612                                 *poffset = e->offset;
1613                                 SeekDir(dirp, e->offset);
1614                                 return True;
1615                         }
1616                 }
1617         }
1618
1619         /* Not found in the name cache. Rewind directory and start from scratch. */
1620         SMB_VFS_REWINDDIR(conn, dirp->dir);
1621         dirp->file_number = 0;
1622         *poffset = START_OF_DIRECTORY_OFFSET;
1623         while ((entry = ReadDirName(dirp, poffset, NULL, &talloced))) {
1624                 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
1625                         TALLOC_FREE(talloced);
1626                         return True;
1627                 }
1628                 TALLOC_FREE(talloced);
1629         }
1630         return False;
1631 }
1632
1633 /*****************************************************************
1634  Is this directory empty ?
1635 *****************************************************************/
1636
1637 NTSTATUS can_delete_directory(struct connection_struct *conn,
1638                                 const char *dirname)
1639 {
1640         NTSTATUS status = NT_STATUS_OK;
1641         long dirpos = 0;
1642         const char *dname = NULL;
1643         char *talloced = NULL;
1644         SMB_STRUCT_STAT st;
1645         struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
1646                                         dirname, NULL, 0);
1647
1648         if (!dir_hnd) {
1649                 return map_nt_error_from_unix(errno);
1650         }
1651
1652         while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced))) {
1653                 /* Quick check for "." and ".." */
1654                 if (dname[0] == '.') {
1655                         if (!dname[1] || (dname[1] == '.' && !dname[2])) {
1656                                 TALLOC_FREE(talloced);
1657                                 continue;
1658                         }
1659                 }
1660
1661                 if (!is_visible_file(conn, dirname, dname, &st, True)) {
1662                         TALLOC_FREE(talloced);
1663                         continue;
1664                 }
1665
1666                 DEBUG(10,("can_delete_directory: got name %s - can't delete\n",
1667                          dname ));
1668                 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1669                 break;
1670         }
1671         TALLOC_FREE(talloced);
1672         TALLOC_FREE(dir_hnd);
1673
1674         return status;
1675 }