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