8af0dad8c3a6b92287719a7c1ee7abb07bbab9f0
[ddiss/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 NT_STATUS_IS_OK(smbd_check_access_rights(conn,
1165                                 smb_fname,
1166                                 FILE_READ_DATA));
1167 }
1168
1169 /*******************************************************************
1170  Check to see if a user can write a file (and only files, we do not
1171  check dirs on this one). This is only approximate,
1172  it is used as part of the "hide unwriteable" option. Don't
1173  use it for anything security sensitive.
1174 ********************************************************************/
1175
1176 static bool user_can_write_file(connection_struct *conn,
1177                                 const struct smb_filename *smb_fname)
1178 {
1179         /*
1180          * Never hide files from the root user.
1181          * We use (uid_t)0 here not sec_initial_uid()
1182          * as make test uses a single user context.
1183          */
1184
1185         if (get_current_uid(conn) == (uid_t)0) {
1186                 return True;
1187         }
1188
1189         SMB_ASSERT(VALID_STAT(smb_fname->st));
1190
1191         /* Pseudo-open the file */
1192
1193         if(S_ISDIR(smb_fname->st.st_ex_mode)) {
1194                 return True;
1195         }
1196
1197         return can_write_to_file(conn, smb_fname);
1198 }
1199
1200 /*******************************************************************
1201   Is a file a "special" type ?
1202 ********************************************************************/
1203
1204 static bool file_is_special(connection_struct *conn,
1205                             const struct smb_filename *smb_fname)
1206 {
1207         /*
1208          * Never hide files from the root user.
1209          * We use (uid_t)0 here not sec_initial_uid()
1210          * as make test uses a single user context.
1211          */
1212
1213         if (get_current_uid(conn) == (uid_t)0) {
1214                 return False;
1215         }
1216
1217         SMB_ASSERT(VALID_STAT(smb_fname->st));
1218
1219         if (S_ISREG(smb_fname->st.st_ex_mode) ||
1220             S_ISDIR(smb_fname->st.st_ex_mode) ||
1221             S_ISLNK(smb_fname->st.st_ex_mode))
1222                 return False;
1223
1224         return True;
1225 }
1226
1227 /*******************************************************************
1228  Should the file be seen by the client?
1229  NOTE: A successful return is no guarantee of the file's existence.
1230 ********************************************************************/
1231
1232 bool is_visible_file(connection_struct *conn, const char *dir_path,
1233                      const char *name, SMB_STRUCT_STAT *pst, bool use_veto)
1234 {
1235         bool hide_unreadable = lp_hideunreadable(SNUM(conn));
1236         bool hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
1237         bool hide_special = lp_hide_special_files(SNUM(conn));
1238         char *entry = NULL;
1239         struct smb_filename *smb_fname_base = NULL;
1240         NTSTATUS status;
1241         bool ret = false;
1242
1243         if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
1244                 return True; /* . and .. are always visible. */
1245         }
1246
1247         /* If it's a vetoed file, pretend it doesn't even exist */
1248         if (use_veto && IS_VETO_PATH(conn, name)) {
1249                 DEBUG(10,("is_visible_file: file %s is vetoed.\n", name ));
1250                 return False;
1251         }
1252
1253         if (hide_unreadable || hide_unwriteable || hide_special) {
1254                 entry = talloc_asprintf(talloc_tos(), "%s/%s", dir_path, name);
1255                 if (!entry) {
1256                         ret = false;
1257                         goto out;
1258                 }
1259
1260                 /* Create an smb_filename with stream_name == NULL. */
1261                 status = create_synthetic_smb_fname(talloc_tos(), entry, NULL,
1262                                                     pst, &smb_fname_base);
1263                 if (!NT_STATUS_IS_OK(status)) {
1264                         ret = false;
1265                         goto out;
1266                 }
1267
1268                 /* If the file name does not exist, there's no point checking
1269                  * the configuration options. We succeed, on the basis that the
1270                  * checks *might* have passed if the file was present.
1271                  */
1272                 if (!VALID_STAT(*pst)) {
1273                         if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
1274                                 ret = true;
1275                                 goto out;
1276                         } else {
1277                                 *pst = smb_fname_base->st;
1278                         }
1279                 }
1280
1281                 /* Honour _hide unreadable_ option */
1282                 if (hide_unreadable &&
1283                     !user_can_read_file(conn, smb_fname_base)) {
1284                         DEBUG(10,("is_visible_file: file %s is unreadable.\n",
1285                                  entry ));
1286                         ret = false;
1287                         goto out;
1288                 }
1289                 /* Honour _hide unwriteable_ option */
1290                 if (hide_unwriteable && !user_can_write_file(conn,
1291                                                              smb_fname_base)) {
1292                         DEBUG(10,("is_visible_file: file %s is unwritable.\n",
1293                                  entry ));
1294                         ret = false;
1295                         goto out;
1296                 }
1297                 /* Honour _hide_special_ option */
1298                 if (hide_special && file_is_special(conn, smb_fname_base)) {
1299                         DEBUG(10,("is_visible_file: file %s is special.\n",
1300                                  entry ));
1301                         ret = false;
1302                         goto out;
1303                 }
1304         }
1305
1306         ret = true;
1307  out:
1308         TALLOC_FREE(smb_fname_base);
1309         TALLOC_FREE(entry);
1310         return ret;
1311 }
1312
1313 static int smb_Dir_destructor(struct smb_Dir *dirp)
1314 {
1315         if (dirp->dir) {
1316 #ifdef HAVE_DIRFD
1317                 if (dirp->conn->sconn) {
1318                         files_struct *fsp = file_find_fd(dirp->conn->sconn,
1319                                                 dirfd(dirp->dir));
1320                         if (fsp) {
1321                                 /* The call below closes the underlying fd. */
1322                                 fsp->fh->fd = -1;
1323                         }
1324                 }
1325 #endif
1326                 SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1327         }
1328         if (dirp->conn->sconn) {
1329                 dirp->conn->sconn->searches.dirhandles_open--;
1330         }
1331         return 0;
1332 }
1333
1334 /*******************************************************************
1335  Open a directory.
1336 ********************************************************************/
1337
1338 struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
1339                         const char *name,
1340                         const char *mask,
1341                         uint32 attr)
1342 {
1343         struct smb_Dir *dirp = talloc_zero(mem_ctx, struct smb_Dir);
1344         struct smbd_server_connection *sconn = conn->sconn;
1345
1346         if (!dirp) {
1347                 return NULL;
1348         }
1349
1350         dirp->conn = conn;
1351         dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
1352
1353         dirp->dir_path = talloc_strdup(dirp, name);
1354         if (!dirp->dir_path) {
1355                 errno = ENOMEM;
1356                 goto fail;
1357         }
1358
1359         if (sconn) {
1360                 sconn->searches.dirhandles_open++;
1361         }
1362         talloc_set_destructor(dirp, smb_Dir_destructor);
1363
1364         dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
1365         if (!dirp->dir) {
1366                 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path,
1367                          strerror(errno) ));
1368                 goto fail;
1369         }
1370
1371         return dirp;
1372
1373   fail:
1374         TALLOC_FREE(dirp);
1375         return NULL;
1376 }
1377
1378 /*******************************************************************
1379  Open a directory from an fsp.
1380 ********************************************************************/
1381
1382 static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
1383                         files_struct *fsp,
1384                         const char *mask,
1385                         uint32 attr)
1386 {
1387         struct smb_Dir *dirp = talloc_zero(mem_ctx, struct smb_Dir);
1388         struct smbd_server_connection *sconn = conn->sconn;
1389
1390         if (!dirp) {
1391                 return NULL;
1392         }
1393
1394         dirp->conn = conn;
1395         dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
1396
1397         dirp->dir_path = talloc_strdup(dirp, fsp->fsp_name->base_name);
1398         if (!dirp->dir_path) {
1399                 errno = ENOMEM;
1400                 goto fail;
1401         }
1402
1403         if (sconn) {
1404                 sconn->searches.dirhandles_open++;
1405         }
1406         talloc_set_destructor(dirp, smb_Dir_destructor);
1407
1408         if (fsp->is_directory && fsp->fh->fd != -1) {
1409                 dirp->dir = SMB_VFS_FDOPENDIR(fsp, mask, attr);
1410                 if (dirp->dir == NULL) {
1411                         DEBUG(10,("OpenDir_fsp: SMB_VFS_FDOPENDIR on %s returned "
1412                                 "NULL (%s)\n",
1413                                 dirp->dir_path,
1414                                 strerror(errno)));
1415                         if (errno != ENOSYS) {
1416                                 return NULL;
1417                         }
1418                 }
1419         }
1420
1421         if (dirp->dir == NULL) {
1422                 /* FDOPENDIR didn't work. Use OPENDIR instead. */
1423                 dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
1424         }
1425
1426         if (!dirp->dir) {
1427                 DEBUG(5,("OpenDir_fsp: Can't open %s. %s\n", dirp->dir_path,
1428                          strerror(errno) ));
1429                 goto fail;
1430         }
1431
1432         return dirp;
1433
1434   fail:
1435         TALLOC_FREE(dirp);
1436         return NULL;
1437 }
1438
1439
1440 /*******************************************************************
1441  Read from a directory.
1442  Return directory entry, current offset, and optional stat information.
1443  Don't check for veto or invisible files.
1444 ********************************************************************/
1445
1446 const char *ReadDirName(struct smb_Dir *dirp, long *poffset,
1447                         SMB_STRUCT_STAT *sbuf, char **ptalloced)
1448 {
1449         const char *n;
1450         char *talloced = NULL;
1451         connection_struct *conn = dirp->conn;
1452
1453         /* Cheat to allow . and .. to be the first entries returned. */
1454         if (((*poffset == START_OF_DIRECTORY_OFFSET) ||
1455              (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2))
1456         {
1457                 if (dirp->file_number == 0) {
1458                         n = ".";
1459                         *poffset = dirp->offset = START_OF_DIRECTORY_OFFSET;
1460                 } else {
1461                         n = "..";
1462                         *poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET;
1463                 }
1464                 dirp->file_number++;
1465                 *ptalloced = NULL;
1466                 return n;
1467         } else if (*poffset == END_OF_DIRECTORY_OFFSET) {
1468                 *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1469                 return NULL;
1470         } else {
1471                 /* A real offset, seek to it. */
1472                 SeekDir(dirp, *poffset);
1473         }
1474
1475         while ((n = vfs_readdirname(conn, dirp->dir, sbuf, &talloced))) {
1476                 /* Ignore . and .. - we've already returned them. */
1477                 if (*n == '.') {
1478                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
1479                                 TALLOC_FREE(talloced);
1480                                 continue;
1481                         }
1482                 }
1483                 *poffset = dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1484                 *ptalloced = talloced;
1485                 dirp->file_number++;
1486                 return n;
1487         }
1488         *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1489         *ptalloced = NULL;
1490         return NULL;
1491 }
1492
1493 /*******************************************************************
1494  Rewind to the start.
1495 ********************************************************************/
1496
1497 void RewindDir(struct smb_Dir *dirp, long *poffset)
1498 {
1499         SMB_VFS_REWINDDIR(dirp->conn, dirp->dir);
1500         dirp->file_number = 0;
1501         dirp->offset = START_OF_DIRECTORY_OFFSET;
1502         *poffset = START_OF_DIRECTORY_OFFSET;
1503 }
1504
1505 /*******************************************************************
1506  Seek a dir.
1507 ********************************************************************/
1508
1509 void SeekDir(struct smb_Dir *dirp, long offset)
1510 {
1511         if (offset != dirp->offset) {
1512                 if (offset == START_OF_DIRECTORY_OFFSET) {
1513                         RewindDir(dirp, &offset);
1514                         /*
1515                          * Ok we should really set the file number here
1516                          * to 1 to enable ".." to be returned next. Trouble
1517                          * is I'm worried about callers using SeekDir(dirp,0)
1518                          * as equivalent to RewindDir(). So leave this alone
1519                          * for now.
1520                          */
1521                 } else if  (offset == DOT_DOT_DIRECTORY_OFFSET) {
1522                         RewindDir(dirp, &offset);
1523                         /*
1524                          * Set the file number to 2 - we want to get the first
1525                          * real file entry (the one we return after "..")
1526                          * on the next ReadDir.
1527                          */
1528                         dirp->file_number = 2;
1529                 } else if (offset == END_OF_DIRECTORY_OFFSET) {
1530                         ; /* Don't seek in this case. */
1531                 } else {
1532                         SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1533                 }
1534                 dirp->offset = offset;
1535         }
1536 }
1537
1538 /*******************************************************************
1539  Tell a dir position.
1540 ********************************************************************/
1541
1542 long TellDir(struct smb_Dir *dirp)
1543 {
1544         return(dirp->offset);
1545 }
1546
1547 /*******************************************************************
1548  Add an entry into the dcache.
1549 ********************************************************************/
1550
1551 void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
1552 {
1553         struct name_cache_entry *e;
1554
1555         if (dirp->name_cache_size == 0) {
1556                 return;
1557         }
1558
1559         if (dirp->name_cache == NULL) {
1560                 dirp->name_cache = talloc_zero_array(
1561                         dirp, struct name_cache_entry, dirp->name_cache_size);
1562
1563                 if (dirp->name_cache == NULL) {
1564                         return;
1565                 }
1566         }
1567
1568         dirp->name_cache_index = (dirp->name_cache_index+1) %
1569                                         dirp->name_cache_size;
1570         e = &dirp->name_cache[dirp->name_cache_index];
1571         TALLOC_FREE(e->name);
1572         e->name = talloc_strdup(dirp, name);
1573         e->offset = offset;
1574 }
1575
1576 /*******************************************************************
1577  Find an entry by name. Leave us at the offset after it.
1578  Don't check for veto or invisible files.
1579 ********************************************************************/
1580
1581 bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1582 {
1583         int i;
1584         const char *entry = NULL;
1585         char *talloced = NULL;
1586         connection_struct *conn = dirp->conn;
1587
1588         /* Search back in the name cache. */
1589         if (dirp->name_cache_size && dirp->name_cache) {
1590                 for (i = dirp->name_cache_index; i >= 0; i--) {
1591                         struct name_cache_entry *e = &dirp->name_cache[i];
1592                         if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1593                                 *poffset = e->offset;
1594                                 SeekDir(dirp, e->offset);
1595                                 return True;
1596                         }
1597                 }
1598                 for (i = dirp->name_cache_size - 1; i > dirp->name_cache_index; i--) {
1599                         struct name_cache_entry *e = &dirp->name_cache[i];
1600                         if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1601                                 *poffset = e->offset;
1602                                 SeekDir(dirp, e->offset);
1603                                 return True;
1604                         }
1605                 }
1606         }
1607
1608         /* Not found in the name cache. Rewind directory and start from scratch. */
1609         SMB_VFS_REWINDDIR(conn, dirp->dir);
1610         dirp->file_number = 0;
1611         *poffset = START_OF_DIRECTORY_OFFSET;
1612         while ((entry = ReadDirName(dirp, poffset, NULL, &talloced))) {
1613                 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
1614                         TALLOC_FREE(talloced);
1615                         return True;
1616                 }
1617                 TALLOC_FREE(talloced);
1618         }
1619         return False;
1620 }
1621
1622 /*****************************************************************
1623  Is this directory empty ?
1624 *****************************************************************/
1625
1626 NTSTATUS smbd_can_delete_directory(struct connection_struct *conn,
1627                                    const char *dirname)
1628 {
1629         NTSTATUS status = NT_STATUS_OK;
1630         long dirpos = 0;
1631         const char *dname = NULL;
1632         char *talloced = NULL;
1633         SMB_STRUCT_STAT st;
1634         struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
1635                                         dirname, NULL, 0);
1636
1637         if (!dir_hnd) {
1638                 return map_nt_error_from_unix(errno);
1639         }
1640
1641         while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced))) {
1642                 /* Quick check for "." and ".." */
1643                 if (dname[0] == '.') {
1644                         if (!dname[1] || (dname[1] == '.' && !dname[2])) {
1645                                 TALLOC_FREE(talloced);
1646                                 continue;
1647                         }
1648                 }
1649
1650                 if (!is_visible_file(conn, dirname, dname, &st, True)) {
1651                         TALLOC_FREE(talloced);
1652                         continue;
1653                 }
1654
1655                 DEBUG(10,("can_delete_directory: got name %s - can't delete\n",
1656                          dname ));
1657                 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1658                 break;
1659         }
1660         TALLOC_FREE(talloced);
1661         TALLOC_FREE(dir_hnd);
1662
1663         return status;
1664 }