s3: smbd: Remove SMB1 idle unused directory handles code.
[gd/samba-autobuild/.git] / source3 / smbd / dir.c
1 /*
2    Unix SMB/CIFS implementation.
3    Directory handling routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison 2007
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "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 #include "../lib/util/memcache.h"
28 #include "../librpc/gen_ndr/open_files.h"
29
30 /*
31    This module implements directory related functions for Samba.
32 */
33
34 /* "Special" directory offsets. */
35 #define END_OF_DIRECTORY_OFFSET ((long)-1)
36 #define START_OF_DIRECTORY_OFFSET ((long)0)
37 #define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000)
38
39 /* "Special" directory offsets in 32-bit wire format. */
40 #define WIRE_END_OF_DIRECTORY_OFFSET ((uint32_t)0xFFFFFFFF)
41 #define WIRE_START_OF_DIRECTORY_OFFSET ((uint32_t)0)
42 #define WIRE_DOT_DOT_DIRECTORY_OFFSET ((uint32_t)0x80000000)
43
44 /* Make directory handle internals available. */
45
46 struct name_cache_entry {
47         char *name;
48         long offset;
49 };
50
51 struct smb_Dir {
52         connection_struct *conn;
53         DIR *dir;
54         long offset;
55         struct smb_filename *dir_smb_fname;
56         size_t name_cache_size;
57         struct name_cache_entry *name_cache;
58         unsigned int name_cache_index;
59         unsigned int file_number;
60         files_struct *fsp; /* Back pointer to containing fsp, only
61                               set from OpenDir_fsp(). */
62 };
63
64 struct dptr_struct {
65         struct dptr_struct *next, *prev;
66         int dnum;
67         uint16_t spid;
68         struct connection_struct *conn;
69         struct smb_Dir *dir_hnd;
70         bool expect_close;
71         char *wcard;
72         uint32_t attr;
73         struct smb_filename *smb_dname;
74         bool has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
75         bool did_stat; /* Optimisation for non-wcard searches. */
76         bool priv;     /* Directory handle opened with privilege. */
77         uint32_t counter;
78         struct memcache *dptr_cache;
79 };
80
81 static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
82                         files_struct *fsp,
83                         const char *mask,
84                         uint32_t attr);
85
86 static void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset);
87
88 #define INVALID_DPTR_KEY (-3)
89
90 /****************************************************************************
91  Initialise the dir bitmap.
92 ****************************************************************************/
93
94 bool init_dptrs(struct smbd_server_connection *sconn)
95 {
96         if (sconn->searches.dptr_bmap) {
97                 return true;
98         }
99
100         sconn->searches.dptr_bmap = bitmap_talloc(
101                 sconn, MAX_DIRECTORY_HANDLES);
102
103         if (sconn->searches.dptr_bmap == NULL) {
104                 return false;
105         }
106
107         return true;
108 }
109
110 #if 0
111 /****************************************************************************
112  Idle a dptr - the directory is closed but the control info is kept.
113 ****************************************************************************/
114
115 static void dptr_idle(struct dptr_struct *dptr)
116 {
117         if (dptr->dir_hnd) {
118                 DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
119                 TALLOC_FREE(dptr->dir_hnd);
120                 TALLOC_FREE(dptr->dptr_cache);
121                 dptr->counter = 0;
122         }
123 }
124
125 /****************************************************************************
126  Idle the oldest dptr.
127 ****************************************************************************/
128
129 static void dptr_idleoldest(struct smbd_server_connection *sconn)
130 {
131         struct dptr_struct *dptr;
132
133         /*
134          * Go to the end of the list.
135          */
136         dptr = DLIST_TAIL(sconn->searches.dirptrs);
137
138         if(!dptr) {
139                 DEBUG(0,("No dptrs available to idle ?\n"));
140                 return;
141         }
142
143         /*
144          * Idle the oldest pointer.
145          */
146
147         for(; dptr; dptr = DLIST_PREV(dptr)) {
148                 if (dptr->dir_hnd) {
149                         dptr_idle(dptr);
150                         return;
151                 }
152         }
153 }
154 #endif
155
156 /****************************************************************************
157  Get the struct dptr_struct for a dir index.
158 ****************************************************************************/
159
160 static struct dptr_struct *dptr_get(struct smbd_server_connection *sconn,
161                                     int key, bool forclose)
162 {
163         struct dptr_struct *dptr;
164
165         for (dptr = sconn->searches.dirptrs; dptr != NULL; dptr = dptr->next) {
166                 if(dptr->dnum != key) {
167                         continue;
168                 }
169                 DLIST_PROMOTE(sconn->searches.dirptrs, dptr);
170                 return dptr;
171         }
172         return(NULL);
173 }
174
175 /****************************************************************************
176  Get the dir path for a dir index.
177 ****************************************************************************/
178
179 const char *dptr_path(struct smbd_server_connection *sconn, int key)
180 {
181         struct dptr_struct *dptr = dptr_get(sconn, key, false);
182         if (dptr)
183                 return(dptr->smb_dname->base_name);
184         return(NULL);
185 }
186
187 /****************************************************************************
188  Get the dir wcard for a dir index.
189 ****************************************************************************/
190
191 const char *dptr_wcard(struct smbd_server_connection *sconn, int key)
192 {
193         struct dptr_struct *dptr = dptr_get(sconn, key, false);
194         if (dptr)
195                 return(dptr->wcard);
196         return(NULL);
197 }
198
199 /****************************************************************************
200  Get the dir attrib for a dir index.
201 ****************************************************************************/
202
203 uint16_t dptr_attr(struct smbd_server_connection *sconn, int key)
204 {
205         struct dptr_struct *dptr = dptr_get(sconn, key, false);
206         if (dptr)
207                 return(dptr->attr);
208         return(0);
209 }
210
211 /****************************************************************************
212  Close a dptr (internal func).
213 ****************************************************************************/
214
215 static void dptr_close_internal(struct dptr_struct *dptr)
216 {
217         struct smbd_server_connection *sconn = dptr->conn->sconn;
218
219         DEBUG(4,("closing dptr key %d\n",dptr->dnum));
220
221         if (sconn == NULL) {
222                 goto done;
223         }
224
225         if (sconn->using_smb2) {
226                 goto done;
227         }
228
229         DLIST_REMOVE(sconn->searches.dirptrs, dptr);
230
231         /*
232          * Free the dnum in the bitmap. Remember the dnum value is always 
233          * biased by one with respect to the bitmap.
234          */
235
236         if (!bitmap_query(sconn->searches.dptr_bmap, dptr->dnum - 1)) {
237                 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
238                         dptr->dnum ));
239         }
240
241         bitmap_clear(sconn->searches.dptr_bmap, dptr->dnum - 1);
242
243 done:
244         TALLOC_FREE(dptr->dir_hnd);
245         TALLOC_FREE(dptr);
246 }
247
248 /****************************************************************************
249  Close a dptr given a key.
250 ****************************************************************************/
251
252 void dptr_close(struct smbd_server_connection *sconn, int *key)
253 {
254         struct dptr_struct *dptr;
255
256         if(*key == INVALID_DPTR_KEY)
257                 return;
258
259         /* OS/2 seems to use -1 to indicate "close all directories" */
260         if (*key == -1) {
261                 struct dptr_struct *next;
262                 for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
263                         next = dptr->next;
264                         dptr_close_internal(dptr);
265                 }
266                 *key = INVALID_DPTR_KEY;
267                 return;
268         }
269
270         dptr = dptr_get(sconn, *key, true);
271
272         if (!dptr) {
273                 DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
274                 return;
275         }
276
277         dptr_close_internal(dptr);
278
279         *key = INVALID_DPTR_KEY;
280 }
281
282 /****************************************************************************
283  Close all dptrs for a cnum.
284 ****************************************************************************/
285
286 void dptr_closecnum(connection_struct *conn)
287 {
288         struct dptr_struct *dptr, *next;
289         struct smbd_server_connection *sconn = conn->sconn;
290
291         if (sconn == NULL) {
292                 return;
293         }
294
295         for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
296                 next = dptr->next;
297                 if (dptr->conn == conn) {
298                         dptr_close_internal(dptr);
299                 }
300         }
301 }
302
303 /****************************************************************************
304  Are there any SMB1 searches active on this connection struct ?
305 ****************************************************************************/
306
307 bool dptr_activecnum(const struct smbd_server_connection *sconn,
308                         const struct connection_struct *conn)
309 {
310         const struct dptr_struct *dptr;
311
312         for(dptr = sconn->searches.dirptrs; dptr; dptr = dptr->next) {
313                 if (dptr->conn == conn) {
314                         return true;
315                 }
316         }
317         return false;
318 }
319
320 /****************************************************************************
321  Close a dptr that matches a given path, only if it matches the spid also.
322 ****************************************************************************/
323
324 void dptr_closepath(struct smbd_server_connection *sconn,
325                     char *path,uint16_t spid)
326 {
327         struct dptr_struct *dptr, *next;
328         for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
329                 next = dptr->next;
330                 if (spid == dptr->spid &&
331                                 strequal(dptr->smb_dname->base_name,path)) {
332                         dptr_close_internal(dptr);
333                 }
334         }
335 }
336
337 /****************************************************************************
338  Try and close the oldest handle not marked for
339  expect close in the hope that the client has
340  finished with that one.
341 ****************************************************************************/
342
343 static void dptr_close_oldest(struct smbd_server_connection *sconn,
344                               bool old)
345 {
346         struct dptr_struct *dptr;
347
348         /*
349          * Go to the end of the list.
350          */
351         for(dptr = sconn->searches.dirptrs; dptr && dptr->next; dptr = dptr->next)
352                 ;
353
354         if(!dptr) {
355                 DEBUG(0,("No old dptrs available to close oldest ?\n"));
356                 return;
357         }
358
359         /*
360          * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
361          * does not have expect_close set. If 'old' is false, close
362          * one of the new dnum handles.
363          */
364
365         for(; dptr; dptr = DLIST_PREV(dptr)) {
366                 if ((old && (dptr->dnum < 256) && !dptr->expect_close) ||
367                         (!old && (dptr->dnum > 255))) {
368                                 dptr_close_internal(dptr);
369                                 return;
370                 }
371         }
372 }
373
374 /****************************************************************************
375  Safely do an OpenDir as root, ensuring we're in the right place.
376 ****************************************************************************/
377
378 static struct smb_Dir *open_dir_with_privilege(connection_struct *conn,
379                                         struct smb_request *req,
380                                         const struct smb_filename *smb_dname,
381                                         const char *wcard,
382                                         uint32_t attr)
383 {
384         struct smb_Dir *dir_hnd = NULL;
385         struct smb_filename *smb_fname_cwd = NULL;
386         struct smb_filename *saved_dir_fname = vfs_GetWd(talloc_tos(), conn);
387         struct privilege_paths *priv_paths = req->priv_paths;
388         int ret;
389
390         if (saved_dir_fname == NULL) {
391                 return NULL;
392         }
393
394         if (vfs_ChDir(conn, smb_dname) == -1) {
395                 return NULL;
396         }
397
398         /* Now check the stat value is the same. */
399         smb_fname_cwd = synthetic_smb_fname(talloc_tos(),
400                                         ".",
401                                         NULL,
402                                         NULL,
403                                         smb_dname->flags);
404         if (smb_fname_cwd == NULL) {
405                 goto out;
406         }
407         ret = SMB_VFS_STAT(conn, smb_fname_cwd);
408         if (ret != 0) {
409                 goto out;
410         }
411
412         if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
413                 DEBUG(0,("open_dir_with_privilege: stat mismatch between %s "
414                         "and %s\n",
415                         smb_dname->base_name,
416                         smb_fname_str_dbg(&priv_paths->parent_name)));
417                 goto out;
418         }
419
420         dir_hnd = OpenDir(NULL, conn, smb_fname_cwd, wcard, attr);
421
422   out:
423
424         vfs_ChDir(conn, saved_dir_fname);
425         TALLOC_FREE(saved_dir_fname);
426         return dir_hnd;
427 }
428
429 /****************************************************************************
430  Create a new dir ptr. If the flag old_handle is true then we must allocate
431  from the bitmap range 0 - 255 as old SMBsearch directory handles are only
432  one byte long. If old_handle is false we allocate from the range
433  256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
434  a directory handle is never zero.
435  wcard must not be zero.
436 ****************************************************************************/
437
438 NTSTATUS dptr_create(connection_struct *conn,
439                 struct smb_request *req,
440                 files_struct *fsp,
441                 const struct smb_filename *smb_dname,
442                 bool old_handle,
443                 bool expect_close,
444                 uint16_t spid,
445                 const char *wcard,
446                 bool wcard_has_wild,
447                 uint32_t attr,
448                 struct dptr_struct **dptr_ret)
449 {
450         struct smbd_server_connection *sconn = conn->sconn;
451         struct dptr_struct *dptr = NULL;
452         struct smb_Dir *dir_hnd;
453
454         if (fsp && fsp->is_directory && fsp->fh->fd != -1) {
455                 smb_dname = fsp->fsp_name;
456         }
457
458         DEBUG(5,("dptr_create dir=%s\n", smb_dname->base_name));
459
460         if (sconn == NULL) {
461                 DEBUG(0,("dptr_create: called with fake connection_struct\n"));
462                 return NT_STATUS_INTERNAL_ERROR;
463         }
464
465         if (!wcard) {
466                 return NT_STATUS_INVALID_PARAMETER;
467         }
468
469         if (fsp) {
470                 if (!(fsp->access_mask & SEC_DIR_LIST)) {
471                         DEBUG(5,("dptr_create: directory %s "
472                                 "not open for LIST access\n",
473                                 smb_dname->base_name));
474                         return NT_STATUS_ACCESS_DENIED;
475                 }
476                 dir_hnd = OpenDir_fsp(NULL, conn, fsp, wcard, attr);
477         } else {
478                 int ret;
479                 bool backup_intent = (req && req->priv_paths);
480                 NTSTATUS status;
481                 struct smb_filename *smb_dname_cp =
482                         cp_smb_filename(talloc_tos(), smb_dname);
483
484                 if (smb_dname_cp == NULL) {
485                         return NT_STATUS_NO_MEMORY;
486                 }
487
488                 if (req != NULL && req->posix_pathnames) {
489                         ret = SMB_VFS_LSTAT(conn, smb_dname_cp);
490                 } else {
491                         ret = SMB_VFS_STAT(conn, smb_dname_cp);
492                 }
493                 if (ret == -1) {
494                         status = map_nt_error_from_unix(errno);
495                         TALLOC_FREE(smb_dname_cp);
496                         return status;
497                 }
498                 if (!S_ISDIR(smb_dname_cp->st.st_ex_mode)) {
499                         TALLOC_FREE(smb_dname_cp);
500                         return NT_STATUS_NOT_A_DIRECTORY;
501                 }
502                 status = smbd_check_access_rights(conn,
503                                                 smb_dname_cp,
504                                                 backup_intent,
505                                                 SEC_DIR_LIST);
506                 if (!NT_STATUS_IS_OK(status)) {
507                         TALLOC_FREE(smb_dname_cp);
508                         return status;
509                 }
510                 if (backup_intent) {
511                         dir_hnd = open_dir_with_privilege(conn,
512                                                 req,
513                                                 smb_dname_cp,
514                                                 wcard,
515                                                 attr);
516                 } else {
517                         dir_hnd = OpenDir(NULL,
518                                         conn,
519                                         smb_dname_cp,
520                                         wcard,
521                                         attr);
522                 }
523                 TALLOC_FREE(smb_dname_cp);
524         }
525
526         if (!dir_hnd) {
527                 return map_nt_error_from_unix(errno);
528         }
529
530         dptr = talloc_zero(NULL, struct dptr_struct);
531         if(!dptr) {
532                 DEBUG(0,("talloc fail in dptr_create.\n"));
533                 TALLOC_FREE(dir_hnd);
534                 return NT_STATUS_NO_MEMORY;
535         }
536
537         dptr->smb_dname = cp_smb_filename(dptr, smb_dname);
538         if (!dptr->smb_dname) {
539                 TALLOC_FREE(dptr);
540                 TALLOC_FREE(dir_hnd);
541                 return NT_STATUS_NO_MEMORY;
542         }
543         dptr->conn = conn;
544         dptr->dir_hnd = dir_hnd;
545         dptr->spid = spid;
546         dptr->expect_close = expect_close;
547         dptr->wcard = talloc_strdup(dptr, wcard);
548         if (!dptr->wcard) {
549                 TALLOC_FREE(dptr);
550                 TALLOC_FREE(dir_hnd);
551                 return NT_STATUS_NO_MEMORY;
552         }
553         if ((req != NULL && req->posix_pathnames) ||
554                         (wcard[0] == '.' && wcard[1] == 0)) {
555                 dptr->has_wild = True;
556         } else {
557                 dptr->has_wild = wcard_has_wild;
558         }
559
560         dptr->attr = attr;
561
562         if (sconn->using_smb2) {
563                 goto done;
564         }
565
566         if(old_handle) {
567
568                 /*
569                  * This is an old-style SMBsearch request. Ensure the
570                  * value we return will fit in the range 1-255.
571                  */
572
573                 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 0);
574
575                 if(dptr->dnum == -1 || dptr->dnum > 254) {
576
577                         /*
578                          * Try and close the oldest handle not marked for
579                          * expect close in the hope that the client has
580                          * finished with that one.
581                          */
582
583                         dptr_close_oldest(sconn, true);
584
585                         /* Now try again... */
586                         dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 0);
587                         if(dptr->dnum == -1 || dptr->dnum > 254) {
588                                 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
589                                 TALLOC_FREE(dptr);
590                                 TALLOC_FREE(dir_hnd);
591                                 return NT_STATUS_TOO_MANY_OPENED_FILES;
592                         }
593                 }
594         } else {
595
596                 /*
597                  * This is a new-style trans2 request. Allocate from
598                  * a range that will return 256 - MAX_DIRECTORY_HANDLES.
599                  */
600
601                 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 255);
602
603                 if(dptr->dnum == -1 || dptr->dnum < 255) {
604
605                         /*
606                          * Try and close the oldest handle close in the hope that
607                          * the client has finished with that one. This will only
608                          * happen in the case of the Win98 client bug where it leaks
609                          * directory handles.
610                          */
611
612                         dptr_close_oldest(sconn, false);
613
614                         /* Now try again... */
615                         dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 255);
616
617                         if(dptr->dnum == -1 || dptr->dnum < 255) {
618                                 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
619                                 TALLOC_FREE(dptr);
620                                 TALLOC_FREE(dir_hnd);
621                                 return NT_STATUS_TOO_MANY_OPENED_FILES;
622                         }
623                 }
624         }
625
626         bitmap_set(sconn->searches.dptr_bmap, dptr->dnum);
627
628         dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
629
630         DLIST_ADD(sconn->searches.dirptrs, dptr);
631
632 done:
633         DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
634                 dptr->dnum,
635                 dptr->smb_dname->base_name,
636                 expect_close));
637
638         *dptr_ret = dptr;
639
640         return NT_STATUS_OK;
641 }
642
643
644 /****************************************************************************
645  Wrapper functions to access the lower level directory handles.
646 ****************************************************************************/
647
648 void dptr_CloseDir(files_struct *fsp)
649 {
650         if (fsp->dptr) {
651                 /*
652                  * The destructor for the struct smb_Dir
653                  * (fsp->dptr->dir_hnd) now handles
654                  * all resource deallocation.
655                  */
656                 dptr_close_internal(fsp->dptr);
657                 fsp->dptr = NULL;
658         }
659 }
660
661 void dptr_SeekDir(struct dptr_struct *dptr, long offset)
662 {
663         SeekDir(dptr->dir_hnd, offset);
664 }
665
666 long dptr_TellDir(struct dptr_struct *dptr)
667 {
668         return TellDir(dptr->dir_hnd);
669 }
670
671 bool dptr_has_wild(struct dptr_struct *dptr)
672 {
673         return dptr->has_wild;
674 }
675
676 int dptr_dnum(struct dptr_struct *dptr)
677 {
678         return dptr->dnum;
679 }
680
681 bool dptr_get_priv(struct dptr_struct *dptr)
682 {
683         return dptr->priv;
684 }
685
686 void dptr_set_priv(struct dptr_struct *dptr)
687 {
688         dptr->priv = true;
689 }
690
691 /****************************************************************************
692  Return the next visible file name, skipping veto'd and invisible files.
693 ****************************************************************************/
694
695 static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr,
696                                            long *poffset, SMB_STRUCT_STAT *pst,
697                                            char **ptalloced)
698 {
699         /* Normal search for the next file. */
700         const char *name;
701         char *talloced = NULL;
702
703         while ((name = ReadDirName(dptr->dir_hnd, poffset, pst, &talloced))
704                != NULL) {
705                 if (is_visible_file(dptr->conn,
706                                 dptr->smb_dname->base_name,
707                                 name,
708                                 pst,
709                                 true)) {
710                         *ptalloced = talloced;
711                         return name;
712                 }
713                 TALLOC_FREE(talloced);
714         }
715         return NULL;
716 }
717
718 /****************************************************************************
719  Return the next visible file name, skipping veto'd and invisible files.
720 ****************************************************************************/
721
722 static char *dptr_ReadDirName(TALLOC_CTX *ctx,
723                               struct dptr_struct *dptr,
724                               long *poffset,
725                               SMB_STRUCT_STAT *pst)
726 {
727         struct smb_filename smb_fname_base;
728         char *name = NULL;
729         const char *name_temp = NULL;
730         char *talloced = NULL;
731         char *pathreal = NULL;
732         char *found_name = NULL;
733         int ret;
734
735         SET_STAT_INVALID(*pst);
736
737         if (dptr->has_wild || dptr->did_stat) {
738                 name_temp = dptr_normal_ReadDirName(dptr, poffset, pst,
739                                                     &talloced);
740                 if (name_temp == NULL) {
741                         return NULL;
742                 }
743                 if (talloced != NULL) {
744                         return talloc_move(ctx, &talloced);
745                 }
746                 return talloc_strdup(ctx, name_temp);
747         }
748
749         /* If poffset is -1 then we know we returned this name before and we
750          * have no wildcards. We're at the end of the directory. */
751         if (*poffset == END_OF_DIRECTORY_OFFSET) {
752                 return NULL;
753         }
754
755         /* We know the stored wcard contains no wildcard characters.
756          * See if we can match with a stat call. If we can't, then set
757          * did_stat to true to ensure we only do this once and keep
758          * searching. */
759
760         dptr->did_stat = true;
761
762         /* First check if it should be visible. */
763         if (!is_visible_file(dptr->conn,
764                         dptr->smb_dname->base_name,
765                         dptr->wcard,
766                         pst,
767                         true)) {
768                 /* This only returns false if the file was found, but
769                    is explicitly not visible. Set us to end of
770                    directory, but return NULL as we know we can't ever
771                    find it. */
772                 goto ret;
773         }
774
775         if (VALID_STAT(*pst)) {
776                 name = talloc_strdup(ctx, dptr->wcard);
777                 goto ret;
778         }
779
780         pathreal = talloc_asprintf(ctx,
781                                 "%s/%s",
782                                 dptr->smb_dname->base_name,
783                                 dptr->wcard);
784         if (!pathreal)
785                 return NULL;
786
787         /* Create an smb_filename with stream_name == NULL. */
788         smb_fname_base = (struct smb_filename) { .base_name = pathreal };
789
790         if (SMB_VFS_STAT(dptr->conn, &smb_fname_base) == 0) {
791                 *pst = smb_fname_base.st;
792                 name = talloc_strdup(ctx, dptr->wcard);
793                 goto clean;
794         } else {
795                 /* If we get any other error than ENOENT or ENOTDIR
796                    then the file exists we just can't stat it. */
797                 if (errno != ENOENT && errno != ENOTDIR) {
798                         name = talloc_strdup(ctx, dptr->wcard);
799                         goto clean;
800                 }
801         }
802
803         /* Stat failed. We know this is authoratiative if we are
804          * providing case sensitive semantics or the underlying
805          * filesystem is case sensitive.
806          */
807         if (dptr->conn->case_sensitive ||
808             !(dptr->conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH))
809         {
810                 goto clean;
811         }
812
813         /*
814          * Try case-insensitive stat if the fs has the ability. This avoids
815          * scanning the whole directory.
816          */
817         ret = SMB_VFS_GET_REAL_FILENAME(dptr->conn,
818                                         dptr->smb_dname->base_name,
819                                         dptr->wcard,
820                                         ctx,
821                                         &found_name);
822         if (ret == 0) {
823                 name = found_name;
824                 goto clean;
825         } else if (errno == ENOENT) {
826                 /* The case-insensitive lookup was authoritative. */
827                 goto clean;
828         }
829
830         TALLOC_FREE(pathreal);
831
832         name_temp = dptr_normal_ReadDirName(dptr, poffset, pst, &talloced);
833         if (name_temp == NULL) {
834                 return NULL;
835         }
836         if (talloced != NULL) {
837                 return talloc_move(ctx, &talloced);
838         }
839         return talloc_strdup(ctx, name_temp);
840
841 clean:
842         TALLOC_FREE(pathreal);
843 ret:
844         /* We need to set the underlying dir_hnd offset to -1
845          * also as this function is usually called with the
846          * output from TellDir. */
847         dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
848         return name;
849 }
850
851 /****************************************************************************
852  Search for a file by name, skipping veto'ed and not visible files.
853 ****************************************************************************/
854
855 bool dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
856 {
857         SET_STAT_INVALID(*pst);
858
859         if (!dptr->has_wild && (dptr->dir_hnd->offset == END_OF_DIRECTORY_OFFSET)) {
860                 /* This is a singleton directory and we're already at the end. */
861                 *poffset = END_OF_DIRECTORY_OFFSET;
862                 return False;
863         }
864
865         return SearchDir(dptr->dir_hnd, name, poffset);
866 }
867
868 /****************************************************************************
869  Map a native directory offset to a 32-bit cookie.
870 ****************************************************************************/
871
872 static uint32_t map_dir_offset_to_wire(struct dptr_struct *dptr, long offset)
873 {
874         DATA_BLOB key;
875         DATA_BLOB val;
876
877         if (offset == END_OF_DIRECTORY_OFFSET) {
878                 return WIRE_END_OF_DIRECTORY_OFFSET;
879         } else if(offset == START_OF_DIRECTORY_OFFSET) {
880                 return WIRE_START_OF_DIRECTORY_OFFSET;
881         } else if (offset == DOT_DOT_DIRECTORY_OFFSET) {
882                 return WIRE_DOT_DOT_DIRECTORY_OFFSET;
883         }
884         if (sizeof(long) == 4) {
885                 /* 32-bit machine. We can cheat... */
886                 return (uint32_t)offset;
887         }
888         if (dptr->dptr_cache == NULL) {
889                 /* Lazy initialize cache. */
890                 dptr->dptr_cache = memcache_init(dptr, 0);
891                 if (dptr->dptr_cache == NULL) {
892                         return WIRE_END_OF_DIRECTORY_OFFSET;
893                 }
894         } else {
895                 /* Have we seen this offset before ? */
896                 key.data = (void *)&offset;
897                 key.length = sizeof(offset);
898                 if (memcache_lookup(dptr->dptr_cache,
899                                         SMB1_SEARCH_OFFSET_MAP,
900                                         key,
901                                         &val)) {
902                         uint32_t wire_offset;
903                         SMB_ASSERT(val.length == sizeof(wire_offset));
904                         memcpy(&wire_offset, val.data, sizeof(wire_offset));
905                         DEBUG(10,("found wire %u <-> offset %ld\n",
906                                 (unsigned int)wire_offset,
907                                 (long)offset));
908                         return wire_offset;
909                 }
910         }
911         /* Allocate a new wire cookie. */
912         do {
913                 dptr->counter++;
914         } while (dptr->counter == WIRE_START_OF_DIRECTORY_OFFSET ||
915                  dptr->counter == WIRE_END_OF_DIRECTORY_OFFSET ||
916                  dptr->counter == WIRE_DOT_DOT_DIRECTORY_OFFSET);
917         /* Store it in the cache. */
918         key.data = (void *)&offset;
919         key.length = sizeof(offset);
920         val.data = (void *)&dptr->counter;
921         val.length = sizeof(dptr->counter); /* MUST BE uint32_t ! */
922         memcache_add(dptr->dptr_cache,
923                         SMB1_SEARCH_OFFSET_MAP,
924                         key,
925                         val);
926         /* And the reverse mapping for lookup from
927            map_wire_to_dir_offset(). */
928         memcache_add(dptr->dptr_cache,
929                         SMB1_SEARCH_OFFSET_MAP,
930                         val,
931                         key);
932         DEBUG(10,("stored wire %u <-> offset %ld\n",
933                 (unsigned int)dptr->counter,
934                 (long)offset));
935         return dptr->counter;
936 }
937
938 /****************************************************************************
939  Fill the 5 byte server reserved dptr field.
940 ****************************************************************************/
941
942 bool dptr_fill(struct smbd_server_connection *sconn,
943                char *buf1,unsigned int key)
944 {
945         unsigned char *buf = (unsigned char *)buf1;
946         struct dptr_struct *dptr = dptr_get(sconn, key, false);
947         uint32_t wire_offset;
948         if (!dptr) {
949                 DEBUG(1,("filling null dirptr %d\n",key));
950                 return(False);
951         }
952         wire_offset = map_dir_offset_to_wire(dptr,TellDir(dptr->dir_hnd));
953         DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
954                 (long)dptr->dir_hnd,(int)wire_offset));
955         buf[0] = key;
956         SIVAL(buf,1,wire_offset);
957         return(True);
958 }
959
960 /****************************************************************************
961  Map a 32-bit wire cookie to a native directory offset.
962 ****************************************************************************/
963
964 static long map_wire_to_dir_offset(struct dptr_struct *dptr, uint32_t wire_offset)
965 {
966         DATA_BLOB key;
967         DATA_BLOB val;
968
969         if (wire_offset == WIRE_END_OF_DIRECTORY_OFFSET) {
970                 return END_OF_DIRECTORY_OFFSET;
971         } else if(wire_offset == WIRE_START_OF_DIRECTORY_OFFSET) {
972                 return START_OF_DIRECTORY_OFFSET;
973         } else if (wire_offset == WIRE_DOT_DOT_DIRECTORY_OFFSET) {
974                 return DOT_DOT_DIRECTORY_OFFSET;
975         }
976         if (sizeof(long) == 4) {
977                 /* 32-bit machine. We can cheat... */
978                 return (long)wire_offset;
979         }
980         if (dptr->dptr_cache == NULL) {
981                 /* Logic error, cache should be initialized. */
982                 return END_OF_DIRECTORY_OFFSET;
983         }
984         key.data = (void *)&wire_offset;
985         key.length = sizeof(wire_offset);
986         if (memcache_lookup(dptr->dptr_cache,
987                                 SMB1_SEARCH_OFFSET_MAP,
988                                 key,
989                                 &val)) {
990                 /* Found mapping. */
991                 long offset;
992                 SMB_ASSERT(val.length == sizeof(offset));
993                 memcpy(&offset, val.data, sizeof(offset));
994                 DEBUG(10,("lookup wire %u <-> offset %ld\n",
995                         (unsigned int)wire_offset,
996                         (long)offset));
997                 return offset;
998         }
999         return END_OF_DIRECTORY_OFFSET;
1000 }
1001
1002 /****************************************************************************
1003  Fetch the dir ptr and seek it given the 5 byte server field.
1004 ****************************************************************************/
1005
1006 struct dptr_struct *dptr_fetch(struct smbd_server_connection *sconn,
1007                                char *buf, int *num)
1008 {
1009         unsigned int key = *(unsigned char *)buf;
1010         struct dptr_struct *dptr = dptr_get(sconn, key, false);
1011         uint32_t wire_offset;
1012         long seekoff;
1013
1014         if (!dptr) {
1015                 DEBUG(3,("fetched null dirptr %d\n",key));
1016                 return(NULL);
1017         }
1018         *num = key;
1019         wire_offset = IVAL(buf,1);
1020         seekoff = map_wire_to_dir_offset(dptr, wire_offset);
1021         SeekDir(dptr->dir_hnd,seekoff);
1022         DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
1023                 key, dptr->smb_dname->base_name, (int)seekoff));
1024         return(dptr);
1025 }
1026
1027 /****************************************************************************
1028  Fetch the dir ptr.
1029 ****************************************************************************/
1030
1031 struct dptr_struct *dptr_fetch_lanman2(struct smbd_server_connection *sconn,
1032                                        int dptr_num)
1033 {
1034         struct dptr_struct *dptr  = dptr_get(sconn, dptr_num, false);
1035
1036         if (!dptr) {
1037                 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
1038                 return(NULL);
1039         }
1040         DEBUG(3,("fetching dirptr %d for path %s\n",
1041                 dptr_num,
1042                 dptr->smb_dname->base_name));
1043         return(dptr);
1044 }
1045
1046 static bool mangle_mask_match(connection_struct *conn,
1047                 const char *filename,
1048                 const char *mask)
1049 {
1050         char mname[13];
1051
1052         if (!name_to_8_3(filename,mname,False,conn->params)) {
1053                 return False;
1054         }
1055         return mask_match_search(mname,mask,False);
1056 }
1057
1058 bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
1059                            struct dptr_struct *dirptr,
1060                            const char *mask,
1061                            uint32_t dirtype,
1062                            bool dont_descend,
1063                            bool ask_sharemode,
1064                            bool get_dosmode,
1065                            bool (*match_fn)(TALLOC_CTX *ctx,
1066                                             void *private_data,
1067                                             const char *dname,
1068                                             const char *mask,
1069                                             char **_fname),
1070                            bool (*mode_fn)(TALLOC_CTX *ctx,
1071                                            void *private_data,
1072                                            struct smb_filename *smb_fname,
1073                                            bool get_dosmode,
1074                                            uint32_t *_mode),
1075                            void *private_data,
1076                            char **_fname,
1077                            struct smb_filename **_smb_fname,
1078                            uint32_t *_mode,
1079                            long *_prev_offset)
1080 {
1081         connection_struct *conn = dirptr->conn;
1082         size_t slashlen;
1083         size_t pathlen;
1084         const char *dpath = dirptr->smb_dname->base_name;
1085         bool dirptr_path_is_dot = ISDOT(dpath);
1086
1087         *_smb_fname = NULL;
1088         *_mode = 0;
1089
1090         pathlen = strlen(dpath);
1091         slashlen = ( dpath[pathlen-1] != '/') ? 1 : 0;
1092
1093         while (true) {
1094                 long cur_offset;
1095                 long prev_offset;
1096                 SMB_STRUCT_STAT sbuf = { 0 };
1097                 char *dname = NULL;
1098                 bool isdots;
1099                 char *fname = NULL;
1100                 char *pathreal = NULL;
1101                 struct smb_filename smb_fname;
1102                 uint32_t mode = 0;
1103                 bool ok;
1104
1105                 cur_offset = dptr_TellDir(dirptr);
1106                 prev_offset = cur_offset;
1107                 dname = dptr_ReadDirName(ctx, dirptr, &cur_offset, &sbuf);
1108
1109                 DEBUG(6,("smbd_dirptr_get_entry: dirptr 0x%lx now at offset %ld\n",
1110                         (long)dirptr, cur_offset));
1111
1112                 if (dname == NULL) {
1113                         return false;
1114                 }
1115
1116                 isdots = (ISDOT(dname) || ISDOTDOT(dname));
1117                 if (dont_descend && !isdots) {
1118                         TALLOC_FREE(dname);
1119                         continue;
1120                 }
1121
1122                 /*
1123                  * fname may get mangled, dname is never mangled.
1124                  * Whenever we're accessing the filesystem we use
1125                  * pathreal which is composed from dname.
1126                  */
1127
1128                 ok = match_fn(ctx, private_data, dname, mask, &fname);
1129                 if (!ok) {
1130                         TALLOC_FREE(dname);
1131                         continue;
1132                 }
1133
1134                 /*
1135                  * This used to be
1136                  * pathreal = talloc_asprintf(ctx, "%s%s%s", dirptr->path,
1137                  *                            needslash?"/":"", dname);
1138                  * but this was measurably slower than doing the memcpy.
1139                  */
1140
1141                 pathreal = talloc_array(
1142                         ctx, char,
1143                         pathlen + slashlen + talloc_get_size(dname));
1144                 if (!pathreal) {
1145                         TALLOC_FREE(dname);
1146                         TALLOC_FREE(fname);
1147                         return false;
1148                 }
1149
1150                 /*
1151                  * We don't want to pass ./xxx to modules below us so don't
1152                  * add the path if it is just . by itself.
1153                  */
1154                 if (dirptr_path_is_dot) {
1155                         memcpy(pathreal, dname, talloc_get_size(dname));
1156                 } else {
1157                         memcpy(pathreal, dpath, pathlen);
1158                         pathreal[pathlen] = '/';
1159                         memcpy(pathreal + slashlen + pathlen, dname,
1160                                talloc_get_size(dname));
1161                 }
1162
1163                 /* Create smb_fname with NULL stream_name. */
1164                 smb_fname = (struct smb_filename) {
1165                         .base_name = pathreal, .st = sbuf
1166                 };
1167
1168                 ok = mode_fn(ctx, private_data, &smb_fname, get_dosmode, &mode);
1169                 if (!ok) {
1170                         TALLOC_FREE(dname);
1171                         TALLOC_FREE(fname);
1172                         TALLOC_FREE(pathreal);
1173                         continue;
1174                 }
1175
1176                 if (!dir_check_ftype(mode, dirtype)) {
1177                         DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",
1178                                 fname, (unsigned int)mode, (unsigned int)dirtype));
1179                         TALLOC_FREE(dname);
1180                         TALLOC_FREE(fname);
1181                         TALLOC_FREE(pathreal);
1182                         continue;
1183                 }
1184
1185                 if (ask_sharemode) {
1186                         struct timespec write_time_ts;
1187                         struct file_id fileid;
1188
1189                         fileid = vfs_file_id_from_sbuf(conn,
1190                                                        &smb_fname.st);
1191                         get_file_infos(fileid, 0, NULL, &write_time_ts);
1192                         if (!null_timespec(write_time_ts)) {
1193                                 update_stat_ex_mtime(&smb_fname.st,
1194                                                      write_time_ts);
1195                         }
1196                 }
1197
1198                 DEBUG(3,("smbd_dirptr_get_entry mask=[%s] found %s "
1199                         "fname=%s (%s)\n",
1200                         mask, smb_fname_str_dbg(&smb_fname),
1201                         dname, fname));
1202
1203                 if (!conn->sconn->using_smb2) {
1204                         /*
1205                          * The dircache is only needed for SMB1 because SMB1
1206                          * uses a name for the resume wheras SMB2 always
1207                          * continues from the next position (unless it's told to
1208                          * restart or close-and-reopen the listing).
1209                          */
1210                         DirCacheAdd(dirptr->dir_hnd, dname, cur_offset);
1211                 }
1212
1213                 TALLOC_FREE(dname);
1214
1215                 *_smb_fname = cp_smb_filename(ctx, &smb_fname);
1216                 TALLOC_FREE(pathreal);
1217                 if (*_smb_fname == NULL) {
1218                         return false;
1219                 }
1220                 *_fname = fname;
1221                 *_mode = mode;
1222                 *_prev_offset = prev_offset;
1223
1224                 return true;
1225         }
1226
1227         return false;
1228 }
1229
1230 /****************************************************************************
1231  Get an 8.3 directory entry.
1232 ****************************************************************************/
1233
1234 static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX *ctx,
1235                                      void *private_data,
1236                                      const char *dname,
1237                                      const char *mask,
1238                                      char **_fname)
1239 {
1240         connection_struct *conn = (connection_struct *)private_data;
1241
1242         if ((strcmp(mask,"*.*") == 0) ||
1243             mask_match_search(dname, mask, false) ||
1244             mangle_mask_match(conn, dname, mask)) {
1245                 char mname[13];
1246                 const char *fname;
1247                 /*
1248                  * Ensure we can push the original name as UCS2. If
1249                  * not, then just don't return this name.
1250                  */
1251                 NTSTATUS status;
1252                 size_t ret_len = 0;
1253                 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1254                 uint8_t *tmp = talloc_array(talloc_tos(),
1255                                         uint8_t,
1256                                         len);
1257
1258                 status = srvstr_push(NULL,
1259                         FLAGS2_UNICODE_STRINGS,
1260                         tmp,
1261                         dname,
1262                         len,
1263                         STR_TERMINATE,
1264                         &ret_len);
1265
1266                 TALLOC_FREE(tmp);
1267
1268                 if (!NT_STATUS_IS_OK(status)) {
1269                         return false;
1270                 }
1271
1272                 if (!mangle_is_8_3(dname, false, conn->params)) {
1273                         bool ok = name_to_8_3(dname, mname, false,
1274                                               conn->params);
1275                         if (!ok) {
1276                                 return false;
1277                         }
1278                         fname = mname;
1279                 } else {
1280                         fname = dname;
1281                 }
1282
1283                 *_fname = talloc_strdup(ctx, fname);
1284                 if (*_fname == NULL) {
1285                         return false;
1286                 }
1287
1288                 return true;
1289         }
1290
1291         return false;
1292 }
1293
1294 static bool smbd_dirptr_8_3_mode_fn(TALLOC_CTX *ctx,
1295                                     void *private_data,
1296                                     struct smb_filename *smb_fname,
1297                                     bool get_dosmode,
1298                                     uint32_t *_mode)
1299 {
1300         connection_struct *conn = (connection_struct *)private_data;
1301
1302         if (!VALID_STAT(smb_fname->st)) {
1303                 if ((SMB_VFS_STAT(conn, smb_fname)) != 0) {
1304                         DEBUG(5,("smbd_dirptr_8_3_mode_fn: "
1305                                  "Couldn't stat [%s]. Error "
1306                                  "= %s\n",
1307                                  smb_fname_str_dbg(smb_fname),
1308                                  strerror(errno)));
1309                         return false;
1310                 }
1311         }
1312
1313         *_mode = dos_mode(conn, smb_fname);
1314         return true;
1315 }
1316
1317 bool get_dir_entry(TALLOC_CTX *ctx,
1318                 struct dptr_struct *dirptr,
1319                 const char *mask,
1320                 uint32_t dirtype,
1321                 char **_fname,
1322                 off_t *_size,
1323                 uint32_t *_mode,
1324                 struct timespec *_date,
1325                 bool check_descend,
1326                 bool ask_sharemode)
1327 {
1328         connection_struct *conn = dirptr->conn;
1329         char *fname = NULL;
1330         struct smb_filename *smb_fname = NULL;
1331         uint32_t mode = 0;
1332         long prev_offset;
1333         bool ok;
1334
1335         ok = smbd_dirptr_get_entry(ctx,
1336                                    dirptr,
1337                                    mask,
1338                                    dirtype,
1339                                    check_descend,
1340                                    ask_sharemode,
1341                                    true,
1342                                    smbd_dirptr_8_3_match_fn,
1343                                    smbd_dirptr_8_3_mode_fn,
1344                                    conn,
1345                                    &fname,
1346                                    &smb_fname,
1347                                    &mode,
1348                                    &prev_offset);
1349         if (!ok) {
1350                 return false;
1351         }
1352
1353         *_fname = talloc_move(ctx, &fname);
1354         *_size = smb_fname->st.st_ex_size;
1355         *_mode = mode;
1356         *_date = smb_fname->st.st_ex_mtime;
1357         TALLOC_FREE(smb_fname);
1358         return true;
1359 }
1360
1361 /*******************************************************************
1362  Check to see if a user can read a file. This is only approximate,
1363  it is used as part of the "hide unreadable" option. Don't
1364  use it for anything security sensitive.
1365 ********************************************************************/
1366
1367 static bool user_can_read_file(connection_struct *conn,
1368                                struct smb_filename *smb_fname)
1369 {
1370         NTSTATUS status;
1371         uint32_t rejected_share_access = 0;
1372         uint32_t rejected_mask = 0;
1373         struct security_descriptor *sd = NULL;
1374         uint32_t access_mask = FILE_READ_DATA|
1375                                 FILE_READ_EA|
1376                                 FILE_READ_ATTRIBUTES|
1377                                 SEC_STD_READ_CONTROL;
1378
1379         /*
1380          * Never hide files from the root user.
1381          * We use (uid_t)0 here not sec_initial_uid()
1382          * as make test uses a single user context.
1383          */
1384
1385         if (get_current_uid(conn) == (uid_t)0) {
1386                 return True;
1387         }
1388
1389         /*
1390          * We can't directly use smbd_check_access_rights()
1391          * here, as this implicitly grants FILE_READ_ATTRIBUTES
1392          * which the Windows access-based-enumeration code
1393          * explicitly checks for on the file security descriptor.
1394          * See bug:
1395          *
1396          * https://bugzilla.samba.org/show_bug.cgi?id=10252
1397          *
1398          * and the smb2.acl2.ACCESSBASED test for details.
1399          */
1400
1401         rejected_share_access = access_mask & ~(conn->share_access);
1402         if (rejected_share_access) {
1403                 DEBUG(10, ("rejected share access 0x%x "
1404                         "on %s (0x%x)\n",
1405                         (unsigned int)access_mask,
1406                         smb_fname_str_dbg(smb_fname),
1407                         (unsigned int)rejected_share_access ));
1408                 return false;
1409         }
1410
1411         status = SMB_VFS_GET_NT_ACL(conn,
1412                         smb_fname,
1413                         (SECINFO_OWNER |
1414                          SECINFO_GROUP |
1415                          SECINFO_DACL),
1416                         talloc_tos(),
1417                         &sd);
1418
1419         if (!NT_STATUS_IS_OK(status)) {
1420                 DEBUG(10, ("Could not get acl "
1421                         "on %s: %s\n",
1422                         smb_fname_str_dbg(smb_fname),
1423                         nt_errstr(status)));
1424                 return false;
1425         }
1426
1427         status = se_file_access_check(sd,
1428                                 get_current_nttok(conn),
1429                                 false,
1430                                 access_mask,
1431                                 &rejected_mask);
1432
1433         TALLOC_FREE(sd);
1434
1435         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1436                 DEBUG(10,("rejected bits 0x%x read access for %s\n",
1437                         (unsigned int)rejected_mask,
1438                         smb_fname_str_dbg(smb_fname) ));
1439                 return false;
1440         }
1441         return true;
1442 }
1443
1444 /*******************************************************************
1445  Check to see if a user can write a file (and only files, we do not
1446  check dirs on this one). This is only approximate,
1447  it is used as part of the "hide unwriteable" option. Don't
1448  use it for anything security sensitive.
1449 ********************************************************************/
1450
1451 static bool user_can_write_file(connection_struct *conn,
1452                                 const struct smb_filename *smb_fname)
1453 {
1454         /*
1455          * Never hide files from the root user.
1456          * We use (uid_t)0 here not sec_initial_uid()
1457          * as make test uses a single user context.
1458          */
1459
1460         if (get_current_uid(conn) == (uid_t)0) {
1461                 return True;
1462         }
1463
1464         SMB_ASSERT(VALID_STAT(smb_fname->st));
1465
1466         /* Pseudo-open the file */
1467
1468         if(S_ISDIR(smb_fname->st.st_ex_mode)) {
1469                 return True;
1470         }
1471
1472         return can_write_to_file(conn, smb_fname);
1473 }
1474
1475 /*******************************************************************
1476   Is a file a "special" type ?
1477 ********************************************************************/
1478
1479 static bool file_is_special(connection_struct *conn,
1480                             const struct smb_filename *smb_fname)
1481 {
1482         /*
1483          * Never hide files from the root user.
1484          * We use (uid_t)0 here not sec_initial_uid()
1485          * as make test uses a single user context.
1486          */
1487
1488         if (get_current_uid(conn) == (uid_t)0) {
1489                 return False;
1490         }
1491
1492         SMB_ASSERT(VALID_STAT(smb_fname->st));
1493
1494         if (S_ISREG(smb_fname->st.st_ex_mode) ||
1495             S_ISDIR(smb_fname->st.st_ex_mode) ||
1496             S_ISLNK(smb_fname->st.st_ex_mode))
1497                 return False;
1498
1499         return True;
1500 }
1501
1502 /*******************************************************************
1503  Should the file be seen by the client?
1504  NOTE: A successful return is no guarantee of the file's existence.
1505 ********************************************************************/
1506
1507 bool is_visible_file(connection_struct *conn, const char *dir_path,
1508                      const char *name, SMB_STRUCT_STAT *pst, bool use_veto)
1509 {
1510         bool hide_unreadable = lp_hide_unreadable(SNUM(conn));
1511         bool hide_unwriteable = lp_hide_unwriteable_files(SNUM(conn));
1512         bool hide_special = lp_hide_special_files(SNUM(conn));
1513         int hide_new_files_timeout = lp_hide_new_files_timeout(SNUM(conn));
1514         char *entry = NULL;
1515         struct smb_filename *smb_fname_base = NULL;
1516         bool ret = false;
1517
1518         if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
1519                 return True; /* . and .. are always visible. */
1520         }
1521
1522         /* If it's a vetoed file, pretend it doesn't even exist */
1523         if (use_veto && IS_VETO_PATH(conn, name)) {
1524                 DEBUG(10,("is_visible_file: file %s is vetoed.\n", name ));
1525                 return False;
1526         }
1527
1528         if (hide_unreadable ||
1529             hide_unwriteable ||
1530             hide_special ||
1531             (hide_new_files_timeout != 0))
1532         {
1533                 entry = talloc_asprintf(talloc_tos(), "%s/%s", dir_path, name);
1534                 if (!entry) {
1535                         ret = false;
1536                         goto out;
1537                 }
1538
1539                 /* Create an smb_filename with stream_name == NULL. */
1540                 smb_fname_base = synthetic_smb_fname(talloc_tos(),
1541                                                 entry,
1542                                                 NULL,
1543                                                 pst,
1544                                                 0);
1545                 if (smb_fname_base == NULL) {
1546                         ret = false;
1547                         goto out;
1548                 }
1549
1550                 /* If the file name does not exist, there's no point checking
1551                  * the configuration options. We succeed, on the basis that the
1552                  * checks *might* have passed if the file was present.
1553                  */
1554                 if (!VALID_STAT(*pst)) {
1555                         if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
1556                                 ret = true;
1557                                 goto out;
1558                         }
1559                         *pst = smb_fname_base->st;
1560                 }
1561
1562                 /* Honour _hide unreadable_ option */
1563                 if (hide_unreadable &&
1564                     !user_can_read_file(conn, smb_fname_base)) {
1565                         DEBUG(10,("is_visible_file: file %s is unreadable.\n",
1566                                  entry ));
1567                         ret = false;
1568                         goto out;
1569                 }
1570                 /* Honour _hide unwriteable_ option */
1571                 if (hide_unwriteable && !user_can_write_file(conn,
1572                                                              smb_fname_base)) {
1573                         DEBUG(10,("is_visible_file: file %s is unwritable.\n",
1574                                  entry ));
1575                         ret = false;
1576                         goto out;
1577                 }
1578                 /* Honour _hide_special_ option */
1579                 if (hide_special && file_is_special(conn, smb_fname_base)) {
1580                         DEBUG(10,("is_visible_file: file %s is special.\n",
1581                                  entry ));
1582                         ret = false;
1583                         goto out;
1584                 }
1585
1586                 if (hide_new_files_timeout != 0) {
1587
1588                         double age = timespec_elapsed(
1589                                 &smb_fname_base->st.st_ex_mtime);
1590
1591                         if (age < (double)hide_new_files_timeout) {
1592                                 ret = false;
1593                                 goto out;
1594                         }
1595                 }
1596         }
1597
1598         ret = true;
1599  out:
1600         TALLOC_FREE(smb_fname_base);
1601         TALLOC_FREE(entry);
1602         return ret;
1603 }
1604
1605 static int smb_Dir_destructor(struct smb_Dir *dirp)
1606 {
1607         if (dirp->dir != NULL) {
1608                 SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1609                 if (dirp->fsp != NULL) {
1610                         /*
1611                          * The SMB_VFS_CLOSEDIR above
1612                          * closes the underlying fd inside
1613                          * dirp->fsp.
1614                          */
1615                         dirp->fsp->fh->fd = -1;
1616                         if (dirp->fsp->dptr != NULL) {
1617                                 SMB_ASSERT(dirp->fsp->dptr->dir_hnd == dirp);
1618                                 dirp->fsp->dptr->dir_hnd = NULL;
1619                         }
1620                         dirp->fsp = NULL;
1621                 }
1622         }
1623         if (dirp->conn->sconn && !dirp->conn->sconn->using_smb2) {
1624                 dirp->conn->sconn->searches.dirhandles_open--;
1625         }
1626         return 0;
1627 }
1628
1629 /*******************************************************************
1630  Open a directory.
1631 ********************************************************************/
1632
1633 static struct smb_Dir *OpenDir_internal(TALLOC_CTX *mem_ctx,
1634                         connection_struct *conn,
1635                         const struct smb_filename *smb_dname,
1636                         const char *mask,
1637                         uint32_t attr)
1638 {
1639         struct smb_Dir *dirp = talloc_zero(mem_ctx, struct smb_Dir);
1640         struct smbd_server_connection *sconn = conn->sconn;
1641
1642         if (!dirp) {
1643                 return NULL;
1644         }
1645
1646         dirp->dir = SMB_VFS_OPENDIR(conn, smb_dname, mask, attr);
1647
1648         if (!dirp->dir) {
1649                 DEBUG(5,("OpenDir: Can't open %s. %s\n",
1650                         smb_dname->base_name,
1651                         strerror(errno) ));
1652                 goto fail;
1653         }
1654
1655         dirp->conn = conn;
1656
1657         if (!conn->sconn->using_smb2) {
1658                 /*
1659                  * The dircache is only needed for SMB1 because SMB1 uses a name
1660                  * for the resume wheras SMB2 always continues from the next
1661                  * position (unless it's told to restart or close-and-reopen the
1662                  * listing).
1663                  */
1664                 dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
1665         }
1666
1667         if (sconn && !sconn->using_smb2) {
1668                 sconn->searches.dirhandles_open++;
1669         }
1670         talloc_set_destructor(dirp, smb_Dir_destructor);
1671
1672         return dirp;
1673
1674   fail:
1675         TALLOC_FREE(dirp);
1676         return NULL;
1677 }
1678
1679 /****************************************************************************
1680  Open a directory handle by pathname, ensuring it's under the share path.
1681 ****************************************************************************/
1682
1683 static struct smb_Dir *open_dir_safely(TALLOC_CTX *ctx,
1684                                         connection_struct *conn,
1685                                         const struct smb_filename *smb_dname,
1686                                         const char *wcard,
1687                                         uint32_t attr)
1688 {
1689         struct smb_Dir *dir_hnd = NULL;
1690         struct smb_filename *smb_fname_cwd = NULL;
1691         struct smb_filename *saved_dir_fname = vfs_GetWd(ctx, conn);
1692         NTSTATUS status;
1693
1694         if (saved_dir_fname == NULL) {
1695                 return NULL;
1696         }
1697
1698         if (vfs_ChDir(conn, smb_dname) == -1) {
1699                 goto out;
1700         }
1701
1702         smb_fname_cwd = synthetic_smb_fname(talloc_tos(),
1703                                         ".",
1704                                         NULL,
1705                                         NULL,
1706                                         smb_dname->flags);
1707         if (smb_fname_cwd == NULL) {
1708                 goto out;
1709         }
1710
1711         /*
1712          * Now the directory is pinned, use
1713          * REALPATH to ensure we can access it.
1714          */
1715         status = check_name(conn, smb_fname_cwd);
1716         if (!NT_STATUS_IS_OK(status)) {
1717                 goto out;
1718         }
1719
1720         dir_hnd = OpenDir_internal(ctx,
1721                                 conn,
1722                                 smb_fname_cwd,
1723                                 wcard,
1724                                 attr);
1725
1726         if (dir_hnd == NULL) {
1727                 goto out;
1728         }
1729
1730         /*
1731          * OpenDir_internal only gets "." as the dir name.
1732          * Store the real dir name here.
1733          */
1734
1735         dir_hnd->dir_smb_fname = cp_smb_filename(dir_hnd, smb_dname);
1736         if (!dir_hnd->dir_smb_fname) {
1737                 TALLOC_FREE(dir_hnd);
1738                 errno = ENOMEM;
1739         }
1740
1741   out:
1742
1743         vfs_ChDir(conn, saved_dir_fname);
1744         TALLOC_FREE(saved_dir_fname);
1745         return dir_hnd;
1746 }
1747
1748 struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
1749                         const struct smb_filename *smb_dname,
1750                         const char *mask,
1751                         uint32_t attr)
1752 {
1753         return open_dir_safely(mem_ctx,
1754                                 conn,
1755                                 smb_dname,
1756                                 mask,
1757                                 attr);
1758 }
1759
1760 /*******************************************************************
1761  Open a directory from an fsp.
1762 ********************************************************************/
1763
1764 static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
1765                         files_struct *fsp,
1766                         const char *mask,
1767                         uint32_t attr)
1768 {
1769         struct smb_Dir *dirp = talloc_zero(mem_ctx, struct smb_Dir);
1770         struct smbd_server_connection *sconn = conn->sconn;
1771
1772         if (!dirp) {
1773                 goto fail;
1774         }
1775
1776         if (!fsp->is_directory) {
1777                 errno = EBADF;
1778                 goto fail;
1779         }
1780
1781         if (fsp->fh->fd == -1) {
1782                 errno = EBADF;
1783                 goto fail;
1784         }
1785
1786         dirp->conn = conn;
1787
1788         if (!conn->sconn->using_smb2) {
1789                 /*
1790                  * The dircache is only needed for SMB1 because SMB1 uses a name
1791                  * for the resume wheras SMB2 always continues from the next
1792                  * position (unless it's told to restart or close-and-reopen the
1793                  * listing).
1794                  */
1795                 dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
1796         }
1797
1798         dirp->dir_smb_fname = cp_smb_filename(dirp, fsp->fsp_name);
1799         if (!dirp->dir_smb_fname) {
1800                 errno = ENOMEM;
1801                 goto fail;
1802         }
1803
1804         dirp->dir = SMB_VFS_FDOPENDIR(fsp, mask, attr);
1805         if (dirp->dir != NULL) {
1806                 dirp->fsp = fsp;
1807         } else {
1808                 DEBUG(10,("OpenDir_fsp: SMB_VFS_FDOPENDIR on %s returned "
1809                         "NULL (%s)\n",
1810                         dirp->dir_smb_fname->base_name,
1811                         strerror(errno)));
1812                 if (errno != ENOSYS) {
1813                         goto fail;
1814                 }
1815         }
1816
1817         if (dirp->dir == NULL) {
1818                 /* FDOPENDIR is not supported. Use OPENDIR instead. */
1819                 TALLOC_FREE(dirp);
1820                 return open_dir_safely(mem_ctx,
1821                                         conn,
1822                                         fsp->fsp_name,
1823                                         mask,
1824                                         attr);
1825         }
1826
1827         if (sconn && !sconn->using_smb2) {
1828                 sconn->searches.dirhandles_open++;
1829         }
1830         talloc_set_destructor(dirp, smb_Dir_destructor);
1831
1832         return dirp;
1833
1834   fail:
1835         TALLOC_FREE(dirp);
1836         return NULL;
1837 }
1838
1839
1840 /*******************************************************************
1841  Read from a directory.
1842  Return directory entry, current offset, and optional stat information.
1843  Don't check for veto or invisible files.
1844 ********************************************************************/
1845
1846 const char *ReadDirName(struct smb_Dir *dirp, long *poffset,
1847                         SMB_STRUCT_STAT *sbuf, char **ptalloced)
1848 {
1849         const char *n;
1850         char *talloced = NULL;
1851         connection_struct *conn = dirp->conn;
1852
1853         /* Cheat to allow . and .. to be the first entries returned. */
1854         if (((*poffset == START_OF_DIRECTORY_OFFSET) ||
1855              (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2))
1856         {
1857                 if (dirp->file_number == 0) {
1858                         n = ".";
1859                         *poffset = dirp->offset = START_OF_DIRECTORY_OFFSET;
1860                 } else {
1861                         n = "..";
1862                         *poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET;
1863                 }
1864                 dirp->file_number++;
1865                 *ptalloced = NULL;
1866                 return n;
1867         }
1868
1869         if (*poffset == END_OF_DIRECTORY_OFFSET) {
1870                 *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1871                 return NULL;
1872         }
1873
1874         /* A real offset, seek to it. */
1875         SeekDir(dirp, *poffset);
1876
1877         while ((n = vfs_readdirname(conn, dirp->dir, sbuf, &talloced))) {
1878                 /* Ignore . and .. - we've already returned them. */
1879                 if (*n == '.') {
1880                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
1881                                 TALLOC_FREE(talloced);
1882                                 continue;
1883                         }
1884                 }
1885                 *poffset = dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1886                 *ptalloced = talloced;
1887                 dirp->file_number++;
1888                 return n;
1889         }
1890         *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1891         *ptalloced = NULL;
1892         return NULL;
1893 }
1894
1895 /*******************************************************************
1896  Rewind to the start.
1897 ********************************************************************/
1898
1899 void RewindDir(struct smb_Dir *dirp, long *poffset)
1900 {
1901         SMB_VFS_REWINDDIR(dirp->conn, dirp->dir);
1902         dirp->file_number = 0;
1903         dirp->offset = START_OF_DIRECTORY_OFFSET;
1904         *poffset = START_OF_DIRECTORY_OFFSET;
1905 }
1906
1907 /*******************************************************************
1908  Seek a dir.
1909 ********************************************************************/
1910
1911 void SeekDir(struct smb_Dir *dirp, long offset)
1912 {
1913         if (offset != dirp->offset) {
1914                 if (offset == START_OF_DIRECTORY_OFFSET) {
1915                         RewindDir(dirp, &offset);
1916                         /*
1917                          * Ok we should really set the file number here
1918                          * to 1 to enable ".." to be returned next. Trouble
1919                          * is I'm worried about callers using SeekDir(dirp,0)
1920                          * as equivalent to RewindDir(). So leave this alone
1921                          * for now.
1922                          */
1923                 } else if  (offset == DOT_DOT_DIRECTORY_OFFSET) {
1924                         RewindDir(dirp, &offset);
1925                         /*
1926                          * Set the file number to 2 - we want to get the first
1927                          * real file entry (the one we return after "..")
1928                          * on the next ReadDir.
1929                          */
1930                         dirp->file_number = 2;
1931                 } else if (offset == END_OF_DIRECTORY_OFFSET) {
1932                         ; /* Don't seek in this case. */
1933                 } else {
1934                         SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1935                 }
1936                 dirp->offset = offset;
1937         }
1938 }
1939
1940 /*******************************************************************
1941  Tell a dir position.
1942 ********************************************************************/
1943
1944 long TellDir(struct smb_Dir *dirp)
1945 {
1946         return(dirp->offset);
1947 }
1948
1949 /*******************************************************************
1950  Add an entry into the dcache.
1951 ********************************************************************/
1952
1953 static void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
1954 {
1955         struct name_cache_entry *e;
1956
1957         if (dirp->name_cache_size == 0) {
1958                 return;
1959         }
1960
1961         if (dirp->name_cache == NULL) {
1962                 dirp->name_cache = talloc_zero_array(
1963                         dirp, struct name_cache_entry, dirp->name_cache_size);
1964
1965                 if (dirp->name_cache == NULL) {
1966                         return;
1967                 }
1968         }
1969
1970         dirp->name_cache_index = (dirp->name_cache_index+1) %
1971                                         dirp->name_cache_size;
1972         e = &dirp->name_cache[dirp->name_cache_index];
1973         TALLOC_FREE(e->name);
1974         e->name = talloc_strdup(dirp, name);
1975         e->offset = offset;
1976 }
1977
1978 /*******************************************************************
1979  Find an entry by name. Leave us at the offset after it.
1980  Don't check for veto or invisible files.
1981 ********************************************************************/
1982
1983 bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1984 {
1985         int i;
1986         const char *entry = NULL;
1987         char *talloced = NULL;
1988         connection_struct *conn = dirp->conn;
1989
1990         /* Search back in the name cache. */
1991         if (dirp->name_cache_size && dirp->name_cache) {
1992                 for (i = dirp->name_cache_index; i >= 0; i--) {
1993                         struct name_cache_entry *e = &dirp->name_cache[i];
1994                         if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1995                                 *poffset = e->offset;
1996                                 SeekDir(dirp, e->offset);
1997                                 return True;
1998                         }
1999                 }
2000                 for (i = dirp->name_cache_size - 1; i > dirp->name_cache_index; i--) {
2001                         struct name_cache_entry *e = &dirp->name_cache[i];
2002                         if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
2003                                 *poffset = e->offset;
2004                                 SeekDir(dirp, e->offset);
2005                                 return True;
2006                         }
2007                 }
2008         }
2009
2010         /* Not found in the name cache. Rewind directory and start from scratch. */
2011         SMB_VFS_REWINDDIR(conn, dirp->dir);
2012         dirp->file_number = 0;
2013         *poffset = START_OF_DIRECTORY_OFFSET;
2014         while ((entry = ReadDirName(dirp, poffset, NULL, &talloced))) {
2015                 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
2016                         TALLOC_FREE(talloced);
2017                         return True;
2018                 }
2019                 TALLOC_FREE(talloced);
2020         }
2021         return False;
2022 }
2023
2024 struct files_below_forall_state {
2025         char *dirpath;
2026         size_t dirpath_len;
2027         int (*fn)(struct file_id fid, const struct share_mode_data *data,
2028                   void *private_data);
2029         void *private_data;
2030 };
2031
2032 static int files_below_forall_fn(struct file_id fid,
2033                                  const struct share_mode_data *data,
2034                                  void *private_data)
2035 {
2036         struct files_below_forall_state *state = private_data;
2037         char tmpbuf[PATH_MAX];
2038         char *fullpath, *to_free;
2039         size_t len;
2040
2041         len = full_path_tos(data->servicepath, data->base_name,
2042                             tmpbuf, sizeof(tmpbuf),
2043                             &fullpath, &to_free);
2044         if (len == -1) {
2045                 return 0;
2046         }
2047         if (state->dirpath_len >= len) {
2048                 /*
2049                  * Filter files above dirpath
2050                  */
2051                 goto out;
2052         }
2053         if (fullpath[state->dirpath_len] != '/') {
2054                 /*
2055                  * Filter file that don't have a path separator at the end of
2056                  * dirpath's length
2057                  */
2058                 goto out;
2059         }
2060
2061         if (memcmp(state->dirpath, fullpath, state->dirpath_len) != 0) {
2062                 /*
2063                  * Not a parent
2064                  */
2065                 goto out;
2066         }
2067
2068         TALLOC_FREE(to_free);
2069         return state->fn(fid, data, state->private_data);
2070
2071 out:
2072         TALLOC_FREE(to_free);
2073         return 0;
2074 }
2075
2076 static int files_below_forall(connection_struct *conn,
2077                               const struct smb_filename *dir_name,
2078                               int (*fn)(struct file_id fid,
2079                                         const struct share_mode_data *data,
2080                                         void *private_data),
2081                               void *private_data)
2082 {
2083         struct files_below_forall_state state = {
2084                         .fn = fn,
2085                         .private_data = private_data,
2086         };
2087         int ret;
2088         char tmpbuf[PATH_MAX];
2089         char *to_free;
2090
2091         state.dirpath_len = full_path_tos(conn->connectpath,
2092                                           dir_name->base_name,
2093                                           tmpbuf, sizeof(tmpbuf),
2094                                           &state.dirpath, &to_free);
2095         if (state.dirpath_len == -1) {
2096                 return -1;
2097         }
2098
2099         ret = share_mode_forall(files_below_forall_fn, &state);
2100         TALLOC_FREE(to_free);
2101         return ret;
2102 }
2103
2104 struct have_file_open_below_state {
2105         bool found_one;
2106 };
2107
2108 static int have_file_open_below_fn(struct file_id fid,
2109                                    const struct share_mode_data *data,
2110                                    void *private_data)
2111 {
2112         struct have_file_open_below_state *state = private_data;
2113         state->found_one = true;
2114         return 1;
2115 }
2116
2117 bool have_file_open_below(connection_struct *conn,
2118                                  const struct smb_filename *name)
2119 {
2120         struct have_file_open_below_state state = {
2121                 .found_one = false,
2122         };
2123         int ret;
2124
2125         if (!VALID_STAT(name->st)) {
2126                 return false;
2127         }
2128         if (!S_ISDIR(name->st.st_ex_mode)) {
2129                 return false;
2130         }
2131
2132         ret = files_below_forall(conn, name, have_file_open_below_fn, &state);
2133         if (ret == -1) {
2134                 return false;
2135         }
2136
2137         return state.found_one;
2138 }
2139
2140 /*****************************************************************
2141  Is this directory empty ?
2142 *****************************************************************/
2143
2144 NTSTATUS can_delete_directory_fsp(files_struct *fsp)
2145 {
2146         NTSTATUS status = NT_STATUS_OK;
2147         long dirpos = 0;
2148         const char *dname = NULL;
2149         const char *dirname = fsp->fsp_name->base_name;
2150         char *talloced = NULL;
2151         SMB_STRUCT_STAT st;
2152         struct connection_struct *conn = fsp->conn;
2153         struct smb_Dir *dir_hnd = OpenDir(talloc_tos(),
2154                                         conn,
2155                                         fsp->fsp_name,
2156                                         NULL,
2157                                         0);
2158
2159         if (!dir_hnd) {
2160                 return map_nt_error_from_unix(errno);
2161         }
2162
2163         while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced))) {
2164                 /* Quick check for "." and ".." */
2165                 if (dname[0] == '.') {
2166                         if (!dname[1] || (dname[1] == '.' && !dname[2])) {
2167                                 TALLOC_FREE(talloced);
2168                                 continue;
2169                         }
2170                 }
2171
2172                 if (!is_visible_file(conn, dirname, dname, &st, True)) {
2173                         TALLOC_FREE(talloced);
2174                         continue;
2175                 }
2176
2177                 DEBUG(10,("got name %s - can't delete\n",
2178                          dname ));
2179                 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
2180                 break;
2181         }
2182         TALLOC_FREE(talloced);
2183         TALLOC_FREE(dir_hnd);
2184
2185         if (!NT_STATUS_IS_OK(status)) {
2186                 return status;
2187         }
2188
2189         if (!(fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) &&
2190             lp_strict_rename(SNUM(conn)) &&
2191             have_file_open_below(fsp->conn, fsp->fsp_name))
2192         {
2193                 return NT_STATUS_ACCESS_DENIED;
2194         }
2195
2196         return NT_STATUS_OK;
2197 }