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