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