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