vfs_ceph: Implement SMB_VFS_FSET_DOS_ATTRIBUTES for precise btime
[samba.git] / source3 / smbd / dir.c
1 /*
2    Unix SMB/CIFS implementation.
3    Directory handling routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison 2007
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/filesys.h"
23 #include "locking/share_mode_lock.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "libcli/security/security.h"
27 #include "lib/util/bitmap.h"
28 #include "../lib/util/memcache.h"
29 #include "../librpc/gen_ndr/open_files.h"
30 #include "lib/util/string_wrappers.h"
31 #include "libcli/smb/reparse.h"
32 #include "source3/smbd/dir.h"
33
34 /*
35    This module implements directory related functions for Samba.
36 */
37
38 /* "Special" directory offsets. */
39 #define END_OF_DIRECTORY_OFFSET ((long)-1)
40 #define START_OF_DIRECTORY_OFFSET ((long)0)
41 #define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000)
42
43 /* Make directory handle internals available. */
44
45 struct smb_Dir {
46         connection_struct *conn;
47         DIR *dir;
48         struct smb_filename *dir_smb_fname;
49         unsigned int file_number;
50         bool case_sensitive;
51         files_struct *fsp; /* Back pointer to containing fsp, only
52                               set from OpenDir_fsp(). */
53 };
54
55 struct dptr_struct {
56         struct dptr_struct *next, *prev;
57         int dnum;
58         struct smb_Dir *dir_hnd;
59         char *wcard;
60         uint32_t attr;
61         bool has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
62         bool did_stat; /* Optimisation for non-wcard searches. */
63         bool priv;     /* Directory handle opened with privilege. */
64         uint32_t counter;
65
66         char *last_name_sent;   /* for name-based trans2 resume */
67
68         struct {
69                 char *fname;
70                 struct smb_filename *smb_fname;
71                 uint32_t mode;
72         } overflow;
73 };
74
75 static NTSTATUS OpenDir_fsp(
76         TALLOC_CTX *mem_ctx,
77         connection_struct *conn,
78         files_struct *fsp,
79         const char *mask,
80         uint32_t attr,
81         struct smb_Dir **_dir_hnd);
82
83 static int smb_Dir_destructor(struct smb_Dir *dir_hnd);
84
85 #define INVALID_DPTR_KEY (-3)
86
87 /****************************************************************************
88  Initialise the dir bitmap.
89 ****************************************************************************/
90
91 bool init_dptrs(struct smbd_server_connection *sconn)
92 {
93         if (sconn->searches.dptr_bmap) {
94                 return true;
95         }
96
97         sconn->searches.dptr_bmap = bitmap_talloc(
98                 sconn, MAX_DIRECTORY_HANDLES);
99
100         if (sconn->searches.dptr_bmap == NULL) {
101                 return false;
102         }
103
104         return true;
105 }
106
107 /****************************************************************************
108  Get the struct dptr_struct for a dir index.
109 ****************************************************************************/
110
111 static struct dptr_struct *dptr_get(struct smbd_server_connection *sconn,
112                                     int key)
113 {
114         struct dptr_struct *dptr;
115
116         for (dptr = sconn->searches.dirptrs; dptr != NULL; dptr = dptr->next) {
117                 if(dptr->dnum != key) {
118                         continue;
119                 }
120                 DLIST_PROMOTE(sconn->searches.dirptrs, dptr);
121                 return dptr;
122         }
123         return(NULL);
124 }
125
126 /****************************************************************************
127  Get the dir path for a dir index.
128 ****************************************************************************/
129
130 const char *dptr_path(struct smbd_server_connection *sconn, int key)
131 {
132         struct dptr_struct *dptr = dptr_get(sconn, key);
133         if (dptr)
134                 return(dptr->dir_hnd->dir_smb_fname->base_name);
135         return(NULL);
136 }
137
138 /****************************************************************************
139  Get the dir wcard for a dir index.
140 ****************************************************************************/
141
142 const char *dptr_wcard(struct smbd_server_connection *sconn, int key)
143 {
144         struct dptr_struct *dptr = dptr_get(sconn, key);
145         if (dptr)
146                 return(dptr->wcard);
147         return(NULL);
148 }
149
150 /****************************************************************************
151  Get the dir attrib for a dir index.
152 ****************************************************************************/
153
154 uint16_t dptr_attr(struct smbd_server_connection *sconn, int key)
155 {
156         struct dptr_struct *dptr = dptr_get(sconn, key);
157         if (dptr)
158                 return(dptr->attr);
159         return(0);
160 }
161
162 /****************************************************************************
163  Close all dptrs for a cnum.
164 ****************************************************************************/
165
166 void dptr_closecnum(connection_struct *conn)
167 {
168         struct dptr_struct *dptr, *next;
169         struct smbd_server_connection *sconn = conn->sconn;
170
171         if (sconn == NULL) {
172                 return;
173         }
174
175         for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
176                 next = dptr->next;
177                 if (dptr->dir_hnd->conn == conn) {
178                         /*
179                          * Need to make a copy, "dptr" will be gone
180                          * after close_file_free() returns
181                          */
182                         struct files_struct *fsp = dptr->dir_hnd->fsp;
183                         close_file_free(NULL, &fsp, NORMAL_CLOSE);
184                 }
185         }
186 }
187
188 /****************************************************************************
189  Create a new dir ptr. If the flag old_handle is true then we must allocate
190  from the bitmap range 0 - 255 as old SMBsearch directory handles are only
191  one byte long. If old_handle is false we allocate from the range
192  256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
193  a directory handle is never zero.
194  wcard must not be zero.
195 ****************************************************************************/
196
197 NTSTATUS dptr_create(connection_struct *conn,
198                 struct smb_request *req,
199                 files_struct *fsp,
200                 bool old_handle,
201                 const char *wcard,
202                 uint32_t attr,
203                 struct dptr_struct **dptr_ret)
204 {
205         struct smbd_server_connection *sconn = conn->sconn;
206         struct dptr_struct *dptr = NULL;
207         struct smb_Dir *dir_hnd = NULL;
208         NTSTATUS status;
209
210         DBG_INFO("dir=%s\n", fsp_str_dbg(fsp));
211
212         if (sconn == NULL) {
213                 DEBUG(0,("dptr_create: called with fake connection_struct\n"));
214                 return NT_STATUS_INTERNAL_ERROR;
215         }
216
217         if (!wcard) {
218                 return NT_STATUS_INVALID_PARAMETER;
219         }
220
221         status = check_any_access_fsp(fsp, SEC_DIR_LIST);
222         if (!NT_STATUS_IS_OK(status)) {
223                 DBG_INFO("dptr_create: directory %s "
224                         "not open for LIST access\n",
225                         fsp_str_dbg(fsp));
226                 return status;
227         }
228         status = OpenDir_fsp(NULL, conn, fsp, wcard, attr, &dir_hnd);
229         if (!NT_STATUS_IS_OK(status)) {
230                 return status;
231         }
232
233         dptr = talloc_zero(NULL, struct dptr_struct);
234         if(!dptr) {
235                 DEBUG(0,("talloc fail in dptr_create.\n"));
236                 TALLOC_FREE(dir_hnd);
237                 return NT_STATUS_NO_MEMORY;
238         }
239
240         dptr->dir_hnd = dir_hnd;
241         dptr->wcard = talloc_strdup(dptr, wcard);
242         if (!dptr->wcard) {
243                 TALLOC_FREE(dptr);
244                 TALLOC_FREE(dir_hnd);
245                 return NT_STATUS_NO_MEMORY;
246         }
247         if ((req != NULL && req->posix_pathnames) || ISDOT(wcard)) {
248                 dptr->has_wild = True;
249         } else {
250                 dptr->has_wild = ms_has_wild(dptr->wcard);
251         }
252
253         dptr->attr = attr;
254
255         if (conn_using_smb2(sconn)) {
256                 goto done;
257         }
258
259         if(old_handle) {
260
261                 /*
262                  * This is an old-style SMBsearch request. Ensure the
263                  * value we return will fit in the range 1-255.
264                  */
265
266                 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 0);
267
268                 if(dptr->dnum == -1 || dptr->dnum > 254) {
269                         DBG_ERR("returned %d: Error - all old "
270                                 "dirptrs in use ?\n",
271                                 dptr->dnum);
272                         TALLOC_FREE(dptr);
273                         TALLOC_FREE(dir_hnd);
274                         return NT_STATUS_TOO_MANY_OPENED_FILES;
275                 }
276         } else {
277
278                 /*
279                  * This is a new-style trans2 request. Allocate from
280                  * a range that will return 256 - MAX_DIRECTORY_HANDLES.
281                  */
282
283                 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 255);
284
285                 if(dptr->dnum == -1 || dptr->dnum < 255) {
286                         DBG_ERR("returned %d: Error - all new "
287                                 "dirptrs in use ?\n",
288                                 dptr->dnum);
289                         TALLOC_FREE(dptr);
290                         TALLOC_FREE(dir_hnd);
291                         return NT_STATUS_TOO_MANY_OPENED_FILES;
292                 }
293         }
294
295         bitmap_set(sconn->searches.dptr_bmap, dptr->dnum);
296
297         dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
298
299         DLIST_ADD(sconn->searches.dirptrs, dptr);
300
301 done:
302         DBG_INFO("creating new dirptr [%d] for path [%s]\n",
303                  dptr->dnum, fsp_str_dbg(fsp));
304
305         *dptr_ret = dptr;
306
307         return NT_STATUS_OK;
308 }
309
310
311 /****************************************************************************
312  Wrapper functions to access the lower level directory handles.
313 ****************************************************************************/
314
315 void dptr_CloseDir(files_struct *fsp)
316 {
317         struct smbd_server_connection *sconn = NULL;
318
319         if (fsp->dptr == NULL) {
320                 return;
321         }
322         sconn = fsp->conn->sconn;
323
324         /*
325          * The destructor for the struct smb_Dir (fsp->dptr->dir_hnd)
326          * now handles all resource deallocation.
327          */
328
329         DBG_INFO("closing dptr key %d\n", fsp->dptr->dnum);
330
331         if (sconn != NULL && !conn_using_smb2(sconn)) {
332                 DLIST_REMOVE(sconn->searches.dirptrs, fsp->dptr);
333
334                 /*
335                  * Free the dnum in the bitmap. Remember the dnum value is
336                  * always biased by one with respect to the bitmap.
337                  */
338
339                 if (!bitmap_query(sconn->searches.dptr_bmap,
340                                   fsp->dptr->dnum - 1))
341                 {
342                         DBG_ERR("closing dnum = %d and bitmap not set !\n",
343                                 fsp->dptr->dnum);
344                 }
345
346                 bitmap_clear(sconn->searches.dptr_bmap, fsp->dptr->dnum - 1);
347         }
348
349         TALLOC_FREE(fsp->dptr->dir_hnd);
350         TALLOC_FREE(fsp->dptr);
351 }
352
353 void dptr_RewindDir(struct dptr_struct *dptr)
354 {
355         RewindDir(dptr->dir_hnd);
356         dptr->did_stat = false;
357         TALLOC_FREE(dptr->overflow.fname);
358         TALLOC_FREE(dptr->overflow.smb_fname);
359 }
360
361 unsigned int dptr_FileNumber(struct dptr_struct *dptr)
362 {
363         return dptr->dir_hnd->file_number;
364 }
365
366 bool dptr_has_wild(struct dptr_struct *dptr)
367 {
368         return dptr->has_wild;
369 }
370
371 int dptr_dnum(struct dptr_struct *dptr)
372 {
373         return dptr->dnum;
374 }
375
376 bool dptr_get_priv(struct dptr_struct *dptr)
377 {
378         return dptr->priv;
379 }
380
381 void dptr_set_priv(struct dptr_struct *dptr)
382 {
383         dptr->priv = true;
384 }
385
386 bool dptr_case_sensitive(struct dptr_struct *dptr)
387 {
388         return dptr->dir_hnd->case_sensitive;
389 }
390
391 /****************************************************************************
392  Return the next visible file name, skipping veto'd and invisible files.
393 ****************************************************************************/
394
395 char *dptr_ReadDirName(TALLOC_CTX *ctx, struct dptr_struct *dptr)
396 {
397         struct stat_ex st = {
398                 .st_ex_nlink = 0,
399         };
400         struct smb_Dir *dir_hnd = dptr->dir_hnd;
401         struct files_struct *dir_fsp = dir_hnd->fsp;
402         struct smb_filename *dir_name = dir_fsp->fsp_name;
403         struct smb_filename smb_fname_base;
404         bool retry_scanning = false;
405         int ret;
406         int flags = 0;
407
408         if (dptr->has_wild) {
409                 const char *name_temp = NULL;
410                 char *talloced = NULL;
411                 name_temp = ReadDirName(dir_hnd, &talloced);
412                 if (name_temp == NULL) {
413                         return NULL;
414                 }
415                 if (talloced != NULL) {
416                         return talloc_move(ctx, &talloced);
417                 }
418                 return talloc_strdup(ctx, name_temp);
419         }
420
421         if (dptr->did_stat) {
422                 /*
423                  * No wildcard, this is not a real directory traverse
424                  * but a "stat" call behind a query_directory. We've
425                  * been here, nothing else to look at.
426                  */
427                 return NULL;
428         }
429         dptr->did_stat = true;
430
431         /* Create an smb_filename with stream_name == NULL. */
432         smb_fname_base = (struct smb_filename){
433                 .base_name = dptr->wcard,
434                 .flags = dir_name->flags,
435                 .twrp = dir_name->twrp,
436         };
437
438         if (dir_name->flags & SMB_FILENAME_POSIX_PATH) {
439                 flags |= AT_SYMLINK_NOFOLLOW;
440         }
441
442         ret = SMB_VFS_FSTATAT(
443                 dir_hnd->conn, dir_fsp, &smb_fname_base, &st, flags);
444         if (ret == 0) {
445                 return talloc_strdup(ctx, dptr->wcard);
446         }
447
448         /*
449          * If we get any other error than ENOENT or ENOTDIR
450          * then the file exists, we just can't stat it.
451          */
452         if (errno != ENOENT && errno != ENOTDIR) {
453                 return talloc_strdup(ctx, dptr->wcard);
454         }
455
456         /*
457          * A scan will find the long version of a mangled name as
458          * wildcard.
459          */
460         retry_scanning |= mangle_is_mangled(dptr->wcard,
461                                             dir_hnd->conn->params);
462
463         /*
464          * Also retry scanning if the client requested case
465          * insensitive semantics and the file system does not provide
466          * it.
467          */
468         retry_scanning |= (!dir_hnd->case_sensitive &&
469                            (dir_hnd->conn->fs_capabilities &
470                             FILE_CASE_SENSITIVE_SEARCH));
471
472         if (retry_scanning) {
473                 char *found_name = NULL;
474                 NTSTATUS status;
475
476                 status = get_real_filename_at(dir_fsp,
477                                               dptr->wcard,
478                                               ctx,
479                                               &found_name);
480                 if (NT_STATUS_IS_OK(status)) {
481                         return found_name;
482                 }
483         }
484
485         return NULL;
486 }
487
488 struct files_struct *dir_hnd_fetch_fsp(struct smb_Dir *dir_hnd)
489 {
490         return dir_hnd->fsp;
491 }
492
493 /****************************************************************************
494  Fetch the fsp associated with the dptr_num.
495 ****************************************************************************/
496
497 files_struct *dptr_fetch_lanman2_fsp(struct smbd_server_connection *sconn,
498                                        int dptr_num)
499 {
500         struct dptr_struct *dptr  = dptr_get(sconn, dptr_num);
501         if (dptr == NULL) {
502                 return NULL;
503         }
504         DBG_NOTICE("fetching dirptr %d for path %s\n",
505                    dptr_num,
506                    dptr->dir_hnd->dir_smb_fname->base_name);
507         return dptr->dir_hnd->fsp;
508 }
509
510 bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
511                            struct dptr_struct *dirptr,
512                            const char *mask,
513                            uint32_t dirtype,
514                            bool dont_descend,
515                            bool ask_sharemode,
516                            bool get_dosmode_in,
517                            bool (*match_fn)(TALLOC_CTX *ctx,
518                                             void *private_data,
519                                             const char *dname,
520                                             const char *mask,
521                                             char **_fname),
522                            void *private_data,
523                            char **_fname,
524                            struct smb_filename **_smb_fname,
525                            uint32_t *_mode)
526 {
527         struct smb_Dir *dir_hnd = dirptr->dir_hnd;
528         connection_struct *conn = dir_hnd->conn;
529         struct smb_filename *dir_fname = dir_hnd->dir_smb_fname;
530         bool posix = (dir_fname->flags & SMB_FILENAME_POSIX_PATH);
531         const bool toplevel = ISDOT(dir_fname->base_name);
532         NTSTATUS status;
533
534         *_smb_fname = NULL;
535         *_mode = 0;
536
537         if (dirptr->overflow.smb_fname != NULL) {
538                 *_fname = talloc_move(ctx, &dirptr->overflow.fname);
539                 *_smb_fname = talloc_move(ctx, &dirptr->overflow.smb_fname);
540                 *_mode = dirptr->overflow.mode;
541                 return true;
542         }
543
544         if (dont_descend && (dptr_FileNumber(dirptr) >= 2)) {
545                 /*
546                  * . and .. were returned first, we're done showing
547                  * the directory as empty.
548                  */
549                 return false;
550         }
551
552         while (true) {
553                 char *dname = NULL;
554                 char *fname = NULL;
555                 struct smb_filename *smb_fname = NULL;
556                 uint32_t mode = 0;
557                 bool get_dosmode = get_dosmode_in;
558                 bool toplevel_dotdot;
559                 bool visible;
560                 bool ok;
561
562                 dname = dptr_ReadDirName(ctx, dirptr);
563
564                 DBG_DEBUG("dir [%s] dirptr [%p] offset [%u] => "
565                           "dname [%s]\n",
566                           smb_fname_str_dbg(dir_fname),
567                           dirptr,
568                           dir_hnd->file_number,
569                           dname ? dname : "(finished)");
570
571                 if (dname == NULL) {
572                         return false;
573                 }
574
575                 if (IS_VETO_PATH(conn, dname)) {
576                         TALLOC_FREE(dname);
577                         continue;
578                 }
579
580                 /*
581                  * fname may get mangled, dname is never mangled.
582                  * Whenever we're accessing the filesystem we use
583                  * pathreal which is composed from dname.
584                  */
585
586                 ok = match_fn(ctx, private_data, dname, mask, &fname);
587                 if (!ok) {
588                         TALLOC_FREE(dname);
589                         continue;
590                 }
591
592                 toplevel_dotdot = toplevel && ISDOTDOT(dname);
593
594                 smb_fname = synthetic_smb_fname(talloc_tos(),
595                                                 toplevel_dotdot ? "." : dname,
596                                                 NULL,
597                                                 NULL,
598                                                 dir_fname->twrp,
599                                                 dir_fname->flags);
600                 if (smb_fname == NULL) {
601                         TALLOC_FREE(dname);
602                         return false;
603                 }
604
605                 /*
606                  * UCF_POSIX_PATHNAMES to avoid the readdir fallback
607                  * if we get raced between readdir and unlink.
608                  */
609                 status = openat_pathref_fsp_lcomp(dir_hnd->fsp,
610                                                   smb_fname,
611                                                   UCF_POSIX_PATHNAMES);
612                 if (!NT_STATUS_IS_OK(status)) {
613                         DBG_DEBUG("Could not open %s: %s\n",
614                                   dname,
615                                   nt_errstr(status));
616                         TALLOC_FREE(smb_fname);
617                         TALLOC_FREE(fname);
618                         TALLOC_FREE(dname);
619                         continue;
620                 }
621
622                 visible = is_visible_fsp(smb_fname->fsp);
623                 if (!visible) {
624                         TALLOC_FREE(smb_fname);
625                         TALLOC_FREE(fname);
626                         TALLOC_FREE(dname);
627                         continue;
628                 }
629
630                 if (!S_ISLNK(smb_fname->st.st_ex_mode)) {
631                         goto done;
632                 }
633
634                 if (lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) &&
635                     is_msdfs_link(dir_hnd->fsp, smb_fname))
636                 {
637                         DBG_INFO("Masquerading msdfs link %s as a directory\n",
638                                  smb_fname->base_name);
639
640                         smb_fname->st.st_ex_mode = (smb_fname->st.st_ex_mode &
641                                                     ~S_IFMT) |
642                                                    S_IFDIR;
643
644                         mode = dos_mode_msdfs(conn, dname, &smb_fname->st);
645                         get_dosmode = false;
646                         ask_sharemode = false;
647                         goto done;
648                 }
649
650                 if (posix) {
651                         /*
652                          * Posix always wants to see symlinks.
653                          */
654                         ask_sharemode = false;
655                         goto done;
656                 }
657
658                 if (!lp_follow_symlinks(SNUM(conn))) {
659                         /*
660                          * Hide symlinks not followed
661                          */
662                         TALLOC_FREE(smb_fname);
663                         TALLOC_FREE(fname);
664                         TALLOC_FREE(dname);
665                         continue;
666                 }
667
668                 /*
669                  * We have to find out if it's a dangling
670                  * symlink. Use the fat logic behind
671                  * openat_pathref_fsp().
672                  */
673
674                 {
675                         struct files_struct *fsp = smb_fname->fsp;
676                         smb_fname_fsp_unlink(smb_fname);
677                         fd_close(fsp);
678                         file_free(NULL, fsp);
679                 }
680
681                 status = openat_pathref_fsp(dir_hnd->fsp, smb_fname);
682
683                 if (!NT_STATUS_IS_OK(status)) {
684                         /*
685                          * Dangling symlink. Hide.
686                          */
687                         TALLOC_FREE(smb_fname);
688                         TALLOC_FREE(fname);
689                         TALLOC_FREE(dname);
690                         continue;
691                 }
692
693 done:
694                 if (get_dosmode) {
695                         mode = fdos_mode(smb_fname->fsp);
696                         smb_fname->st = smb_fname->fsp->fsp_name->st;
697                 }
698
699                 if (!dir_check_ftype(mode, dirtype)) {
700                         DBG_INFO("[%s] attribs 0x%" PRIx32 " didn't match "
701                                  "0x%" PRIx32 "\n",
702                                  fname,
703                                  mode,
704                                  dirtype);
705                         TALLOC_FREE(smb_fname);
706                         TALLOC_FREE(dname);
707                         TALLOC_FREE(fname);
708                         continue;
709                 }
710
711                 if (ask_sharemode && !S_ISDIR(smb_fname->st.st_ex_mode)) {
712                         struct timespec write_time_ts;
713                         struct file_id fileid;
714
715                         fileid = vfs_file_id_from_sbuf(conn,
716                                                        &smb_fname->st);
717                         get_file_infos(fileid, 0, NULL, &write_time_ts);
718                         if (!is_omit_timespec(&write_time_ts)) {
719                                 update_stat_ex_mtime(&smb_fname->st,
720                                                      write_time_ts);
721                         }
722                 }
723
724                 if (toplevel_dotdot) {
725                         /*
726                          * Ensure posix fileid and sids are hidden
727                          */
728                         smb_fname->st.st_ex_ino = 0;
729                         smb_fname->st.st_ex_dev = 0;
730                         smb_fname->st.st_ex_uid = -1;
731                         smb_fname->st.st_ex_gid = -1;
732                 }
733
734                 DBG_NOTICE("mask=[%s] found %s fname=%s (%s)\n",
735                            mask,
736                            smb_fname_str_dbg(smb_fname),
737                            dname,
738                            fname);
739
740                 TALLOC_FREE(dname);
741
742                 *_smb_fname = talloc_move(ctx, &smb_fname);
743                 *_fname = fname;
744                 *_mode = mode;
745
746                 return true;
747         }
748
749         return false;
750 }
751
752 void smbd_dirptr_push_overflow(struct dptr_struct *dirptr,
753                                char **_fname,
754                                struct smb_filename **_smb_fname,
755                                uint32_t mode)
756 {
757         SMB_ASSERT(dirptr->overflow.fname == NULL);
758         SMB_ASSERT(dirptr->overflow.smb_fname == NULL);
759
760         dirptr->overflow.fname = talloc_move(dirptr, _fname);
761         dirptr->overflow.smb_fname = talloc_move(dirptr, _smb_fname);
762         dirptr->overflow.mode = mode;
763 }
764
765 void smbd_dirptr_set_last_name_sent(struct dptr_struct *dirptr,
766                                     char **_fname)
767 {
768         TALLOC_FREE(dirptr->last_name_sent);
769         dirptr->last_name_sent = talloc_move(dirptr, _fname);
770 }
771
772 char *smbd_dirptr_get_last_name_sent(struct dptr_struct *dirptr)
773 {
774         return dirptr->last_name_sent;
775 }
776
777 /*******************************************************************
778  Check to see if a user can read an fsp . This is only approximate,
779  it is used as part of the "hide unreadable" option. Don't
780  use it for anything security sensitive.
781 ********************************************************************/
782
783 static bool user_can_read_fsp(struct files_struct *fsp)
784 {
785         NTSTATUS status;
786         uint32_t rejected_share_access = 0;
787         uint32_t rejected_mask = 0;
788         struct security_descriptor *sd = NULL;
789         uint32_t access_mask = FILE_READ_DATA|
790                                 FILE_READ_EA|
791                                 FILE_READ_ATTRIBUTES|
792                                 SEC_STD_READ_CONTROL;
793
794         /*
795          * Never hide files from the root user.
796          * We use (uid_t)0 here not sec_initial_uid()
797          * as make test uses a single user context.
798          */
799
800         if (get_current_uid(fsp->conn) == (uid_t)0) {
801                 return true;
802         }
803
804         /*
805          * We can't directly use smbd_check_access_rights_fsp()
806          * here, as this implicitly grants FILE_READ_ATTRIBUTES
807          * which the Windows access-based-enumeration code
808          * explicitly checks for on the file security descriptor.
809          * See bug:
810          *
811          * https://bugzilla.samba.org/show_bug.cgi?id=10252
812          *
813          * and the smb2.acl2.ACCESSBASED test for details.
814          */
815
816         rejected_share_access = access_mask & ~(fsp->conn->share_access);
817         if (rejected_share_access) {
818                 DBG_DEBUG("rejected share access 0x%x "
819                         "on %s (0x%x)\n",
820                         (unsigned int)access_mask,
821                         fsp_str_dbg(fsp),
822                         (unsigned int)rejected_share_access);
823                 return false;
824         }
825
826         status = SMB_VFS_FGET_NT_ACL(metadata_fsp(fsp),
827                         (SECINFO_OWNER |
828                          SECINFO_GROUP |
829                          SECINFO_DACL),
830                         talloc_tos(),
831                         &sd);
832
833         if (!NT_STATUS_IS_OK(status)) {
834                 DBG_DEBUG("Could not get acl "
835                         "on %s: %s\n",
836                         fsp_str_dbg(fsp),
837                         nt_errstr(status));
838                 return false;
839         }
840
841         status = se_file_access_check(sd,
842                                 get_current_nttok(fsp->conn),
843                                 false,
844                                 access_mask,
845                                 &rejected_mask);
846
847         TALLOC_FREE(sd);
848
849         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
850                 DBG_DEBUG("rejected bits 0x%x read access for %s\n",
851                         (unsigned int)rejected_mask,
852                         fsp_str_dbg(fsp));
853                 return false;
854         }
855         return true;
856 }
857
858 /*******************************************************************
859  Check to see if a user can write to an fsp.
860  Always return true for directories.
861  This is only approximate,
862  it is used as part of the "hide unwriteable" option. Don't
863  use it for anything security sensitive.
864 ********************************************************************/
865
866 static bool user_can_write_fsp(struct files_struct *fsp)
867 {
868         /*
869          * Never hide files from the root user.
870          * We use (uid_t)0 here not sec_initial_uid()
871          * as make test uses a single user context.
872          */
873
874         if (get_current_uid(fsp->conn) == (uid_t)0) {
875                 return true;
876         }
877
878         if (fsp->fsp_flags.is_directory) {
879                 return true;
880         }
881
882         return can_write_to_fsp(fsp);
883 }
884
885 /*******************************************************************
886   Is a file a "special" type ?
887 ********************************************************************/
888
889 static bool file_is_special(connection_struct *conn,
890                             const struct smb_filename *smb_fname)
891 {
892         /*
893          * Never hide files from the root user.
894          * We use (uid_t)0 here not sec_initial_uid()
895          * as make test uses a single user context.
896          */
897
898         if (get_current_uid(conn) == (uid_t)0) {
899                 return False;
900         }
901
902         SMB_ASSERT(VALID_STAT(smb_fname->st));
903
904         if (S_ISREG(smb_fname->st.st_ex_mode) ||
905             S_ISDIR(smb_fname->st.st_ex_mode) ||
906             S_ISLNK(smb_fname->st.st_ex_mode))
907                 return False;
908
909         return True;
910 }
911
912 /*******************************************************************
913  Should the file be seen by the client?
914 ********************************************************************/
915
916 bool is_visible_fsp(struct files_struct *fsp)
917 {
918         bool hide_unreadable = false;
919         bool hide_unwriteable = false;
920         bool hide_special = false;
921         int hide_new_files_timeout = 0;
922         const char *last_component = NULL;
923
924         /*
925          * If the file does not exist, there's no point checking
926          * the configuration options. We succeed, on the basis that the
927          * checks *might* have passed if the file was present.
928          */
929         if (fsp == NULL) {
930                 return true;
931         }
932
933         hide_unreadable = lp_hide_unreadable(SNUM(fsp->conn));
934         hide_unwriteable = lp_hide_unwriteable_files(SNUM(fsp->conn));
935         hide_special = lp_hide_special_files(SNUM(fsp->conn));
936         hide_new_files_timeout = lp_hide_new_files_timeout(SNUM(fsp->conn));
937
938         if (!hide_unreadable &&
939             !hide_unwriteable &&
940             !hide_special &&
941             (hide_new_files_timeout == 0))
942         {
943                 return true;
944         }
945
946         fsp = metadata_fsp(fsp);
947
948         /* Get the last component of the base name. */
949         last_component = strrchr_m(fsp->fsp_name->base_name, '/');
950         if (!last_component) {
951                 last_component = fsp->fsp_name->base_name;
952         } else {
953                 last_component++; /* Go past '/' */
954         }
955
956         if (ISDOT(last_component) || ISDOTDOT(last_component)) {
957                 return true; /* . and .. are always visible. */
958         }
959
960         if (fsp_get_pathref_fd(fsp) == -1) {
961                 /*
962                  * Symlink in POSIX mode or MS-DFS.
963                  * We've checked veto files so the
964                  * only thing we can check is the
965                  * hide_new_files_timeout.
966                  */
967                 if ((hide_new_files_timeout != 0) &&
968                     !S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
969                         double age = timespec_elapsed(
970                                 &fsp->fsp_name->st.st_ex_mtime);
971
972                         if (age < (double)hide_new_files_timeout) {
973                                 return false;
974                         }
975                 }
976                 return true;
977         }
978
979         /* Honour _hide unreadable_ option */
980         if (hide_unreadable && !user_can_read_fsp(fsp)) {
981                 DBG_DEBUG("file %s is unreadable.\n", fsp_str_dbg(fsp));
982                 return false;
983         }
984
985         /* Honour _hide unwriteable_ option */
986         if (hide_unwriteable && !user_can_write_fsp(fsp)) {
987                 DBG_DEBUG("file %s is unwritable.\n", fsp_str_dbg(fsp));
988                 return false;
989         }
990
991         /* Honour _hide_special_ option */
992         if (hide_special && file_is_special(fsp->conn, fsp->fsp_name)) {
993                 DBG_DEBUG("file %s is special.\n", fsp_str_dbg(fsp));
994                 return false;
995         }
996
997         if ((hide_new_files_timeout != 0) &&
998             !S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
999                 double age = timespec_elapsed(&fsp->fsp_name->st.st_ex_mtime);
1000
1001                 if (age < (double)hide_new_files_timeout) {
1002                         return false;
1003                 }
1004         }
1005
1006         return true;
1007 }
1008
1009 static int smb_Dir_destructor(struct smb_Dir *dir_hnd)
1010 {
1011         files_struct *fsp = dir_hnd->fsp;
1012
1013         SMB_VFS_CLOSEDIR(dir_hnd->conn, dir_hnd->dir);
1014         fsp_set_fd(fsp, -1);
1015         if (fsp->dptr != NULL) {
1016                 SMB_ASSERT(fsp->dptr->dir_hnd == dir_hnd);
1017                 fsp->dptr->dir_hnd = NULL;
1018         }
1019         dir_hnd->fsp = NULL;
1020         return 0;
1021 }
1022
1023 /*******************************************************************
1024  Open a directory.
1025 ********************************************************************/
1026
1027 static int smb_Dir_OpenDir_destructor(struct smb_Dir *dir_hnd)
1028 {
1029         files_struct *fsp = dir_hnd->fsp;
1030
1031         smb_Dir_destructor(dir_hnd);
1032         file_free(NULL, fsp);
1033         return 0;
1034 }
1035
1036 NTSTATUS OpenDir(TALLOC_CTX *mem_ctx,
1037                  connection_struct *conn,
1038                  const struct smb_filename *smb_dname,
1039                  const char *mask,
1040                  uint32_t attr,
1041                  struct smb_Dir **_dir_hnd)
1042 {
1043         struct files_struct *fsp = NULL;
1044         struct smb_Dir *dir_hnd = NULL;
1045         NTSTATUS status;
1046
1047         status = open_internal_dirfsp(conn,
1048                                       smb_dname,
1049                                       O_RDONLY,
1050                                       &fsp);
1051         if (!NT_STATUS_IS_OK(status)) {
1052                 return status;
1053         }
1054
1055         status = OpenDir_fsp(mem_ctx, conn, fsp, mask, attr, &dir_hnd);
1056         if (!NT_STATUS_IS_OK(status)) {
1057                 return status;
1058         }
1059
1060         /*
1061          * This overwrites the destructor set by OpenDir_fsp() but
1062          * smb_Dir_OpenDir_destructor() calls the OpenDir_fsp()
1063          * destructor.
1064          */
1065         talloc_set_destructor(dir_hnd, smb_Dir_OpenDir_destructor);
1066
1067         *_dir_hnd = dir_hnd;
1068         return NT_STATUS_OK;
1069 }
1070
1071 NTSTATUS OpenDir_from_pathref(TALLOC_CTX *mem_ctx,
1072                               struct files_struct *dirfsp,
1073                               const char *mask,
1074                               uint32_t attr,
1075                               struct smb_Dir **_dir_hnd)
1076 {
1077         struct files_struct *fsp = NULL;
1078         struct smb_Dir *dir_hnd = NULL;
1079         NTSTATUS status;
1080
1081         status = openat_internal_dir_from_pathref(dirfsp, O_RDONLY, &fsp);
1082         if (!NT_STATUS_IS_OK(status)) {
1083                 return status;
1084         }
1085
1086         status = OpenDir_fsp(mem_ctx, fsp->conn, fsp, mask, attr, &dir_hnd);
1087         if (!NT_STATUS_IS_OK(status)) {
1088                 return status;
1089         }
1090
1091         /*
1092          * This overwrites the destructor set by OpenDir_fsp() but
1093          * smb_Dir_OpenDir_destructor() calls the OpenDir_fsp()
1094          * destructor.
1095          */
1096         talloc_set_destructor(dir_hnd, smb_Dir_OpenDir_destructor);
1097
1098         *_dir_hnd = dir_hnd;
1099         return NT_STATUS_OK;
1100 }
1101
1102 /*******************************************************************
1103  Open a directory from an fsp.
1104 ********************************************************************/
1105
1106 static NTSTATUS OpenDir_fsp(
1107         TALLOC_CTX *mem_ctx,
1108         connection_struct *conn,
1109         files_struct *fsp,
1110         const char *mask,
1111         uint32_t attr,
1112         struct smb_Dir **_dir_hnd)
1113 {
1114         struct smb_Dir *dir_hnd = talloc_zero(mem_ctx, struct smb_Dir);
1115         NTSTATUS status;
1116
1117         if (!dir_hnd) {
1118                 return NT_STATUS_NO_MEMORY;
1119         }
1120
1121         if (!fsp->fsp_flags.is_directory) {
1122                 status = NT_STATUS_INVALID_HANDLE;
1123                 goto fail;
1124         }
1125
1126         if (fsp_get_io_fd(fsp) == -1) {
1127                 status = NT_STATUS_INVALID_HANDLE;
1128                 goto fail;
1129         }
1130
1131         dir_hnd->conn = conn;
1132
1133         dir_hnd->dir_smb_fname = cp_smb_filename(dir_hnd, fsp->fsp_name);
1134         if (!dir_hnd->dir_smb_fname) {
1135                 status = NT_STATUS_NO_MEMORY;
1136                 goto fail;
1137         }
1138
1139         dir_hnd->dir = SMB_VFS_FDOPENDIR(fsp, mask, attr);
1140         if (dir_hnd->dir == NULL) {
1141                 status = map_nt_error_from_unix(errno);
1142                 goto fail;
1143         }
1144         dir_hnd->fsp = fsp;
1145         if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1146                 dir_hnd->case_sensitive = true;
1147         } else {
1148                 dir_hnd->case_sensitive = conn->case_sensitive;
1149         }
1150
1151         talloc_set_destructor(dir_hnd, smb_Dir_destructor);
1152
1153         *_dir_hnd = dir_hnd;
1154         return NT_STATUS_OK;
1155
1156   fail:
1157         TALLOC_FREE(dir_hnd);
1158         return status;
1159 }
1160
1161
1162 /*******************************************************************
1163  Read from a directory.
1164  Return directory entry, current offset, and optional stat information.
1165  Don't check for veto or invisible files.
1166 ********************************************************************/
1167
1168 const char *ReadDirName(struct smb_Dir *dir_hnd, char **ptalloced)
1169 {
1170         const char *n;
1171         char *talloced = NULL;
1172         connection_struct *conn = dir_hnd->conn;
1173
1174         if (dir_hnd->file_number < 2) {
1175                 if (dir_hnd->file_number == 0) {
1176                         n = ".";
1177                 } else {
1178                         n = "..";
1179                 }
1180                 dir_hnd->file_number++;
1181                 *ptalloced = NULL;
1182                 return n;
1183         }
1184
1185         while ((n = vfs_readdirname(conn,
1186                                     dir_hnd->fsp,
1187                                     dir_hnd->dir,
1188                                     &talloced))) {
1189                 /* Ignore . and .. - we've already returned them. */
1190                 if (ISDOT(n) || ISDOTDOT(n)) {
1191                         TALLOC_FREE(talloced);
1192                         continue;
1193                 }
1194                 *ptalloced = talloced;
1195                 dir_hnd->file_number++;
1196                 return n;
1197         }
1198         *ptalloced = NULL;
1199         return NULL;
1200 }
1201
1202 /*******************************************************************
1203  Rewind to the start.
1204 ********************************************************************/
1205
1206 void RewindDir(struct smb_Dir *dir_hnd)
1207 {
1208         SMB_VFS_REWINDDIR(dir_hnd->conn, dir_hnd->dir);
1209         dir_hnd->file_number = 0;
1210 }
1211
1212 struct files_below_forall_state {
1213         char *dirpath;
1214         ssize_t dirpath_len;
1215         int (*fn)(struct file_id fid, const struct share_mode_data *data,
1216                   void *private_data);
1217         void *private_data;
1218 };
1219
1220 static int files_below_forall_fn(struct file_id fid,
1221                                  const struct share_mode_data *data,
1222                                  void *private_data)
1223 {
1224         struct files_below_forall_state *state = private_data;
1225         char tmpbuf[PATH_MAX];
1226         char *fullpath, *to_free;
1227         ssize_t len;
1228
1229         len = full_path_tos(data->servicepath, data->base_name,
1230                             tmpbuf, sizeof(tmpbuf),
1231                             &fullpath, &to_free);
1232         if (len == -1) {
1233                 return 0;
1234         }
1235         if (state->dirpath_len >= len) {
1236                 /*
1237                  * Filter files above dirpath
1238                  */
1239                 goto out;
1240         }
1241         if (fullpath[state->dirpath_len] != '/') {
1242                 /*
1243                  * Filter file that don't have a path separator at the end of
1244                  * dirpath's length
1245                  */
1246                 goto out;
1247         }
1248
1249         if (memcmp(state->dirpath, fullpath, state->dirpath_len) != 0) {
1250                 /*
1251                  * Not a parent
1252                  */
1253                 goto out;
1254         }
1255
1256         TALLOC_FREE(to_free);
1257         return state->fn(fid, data, state->private_data);
1258
1259 out:
1260         TALLOC_FREE(to_free);
1261         return 0;
1262 }
1263
1264 static int files_below_forall(connection_struct *conn,
1265                               const struct smb_filename *dir_name,
1266                               int (*fn)(struct file_id fid,
1267                                         const struct share_mode_data *data,
1268                                         void *private_data),
1269                               void *private_data)
1270 {
1271         struct files_below_forall_state state = {
1272                         .fn = fn,
1273                         .private_data = private_data,
1274         };
1275         int ret;
1276         char tmpbuf[PATH_MAX];
1277         char *to_free;
1278
1279         state.dirpath_len = full_path_tos(conn->connectpath,
1280                                           dir_name->base_name,
1281                                           tmpbuf, sizeof(tmpbuf),
1282                                           &state.dirpath, &to_free);
1283         if (state.dirpath_len == -1) {
1284                 return -1;
1285         }
1286
1287         ret = share_mode_forall(files_below_forall_fn, &state);
1288         TALLOC_FREE(to_free);
1289         return ret;
1290 }
1291
1292 struct have_file_open_below_state {
1293         bool found_one;
1294 };
1295
1296 static int have_file_open_below_fn(struct file_id fid,
1297                                    const struct share_mode_data *data,
1298                                    void *private_data)
1299 {
1300         struct have_file_open_below_state *state = private_data;
1301         state->found_one = true;
1302         return 1;
1303 }
1304
1305 bool have_file_open_below(connection_struct *conn,
1306                                  const struct smb_filename *name)
1307 {
1308         struct have_file_open_below_state state = {
1309                 .found_one = false,
1310         };
1311         int ret;
1312
1313         if (!VALID_STAT(name->st)) {
1314                 return false;
1315         }
1316         if (!S_ISDIR(name->st.st_ex_mode)) {
1317                 return false;
1318         }
1319
1320         ret = files_below_forall(conn, name, have_file_open_below_fn, &state);
1321         if (ret == -1) {
1322                 return false;
1323         }
1324
1325         return state.found_one;
1326 }
1327
1328 /*****************************************************************
1329  Is this directory empty ?
1330 *****************************************************************/
1331
1332 NTSTATUS can_delete_directory_fsp(files_struct *fsp)
1333 {
1334         NTSTATUS status = NT_STATUS_OK;
1335         const char *dname = NULL;
1336         char *talloced = NULL;
1337         struct connection_struct *conn = fsp->conn;
1338         struct smb_Dir *dir_hnd = NULL;
1339
1340         status = OpenDir(
1341                 talloc_tos(), conn, fsp->fsp_name, NULL, 0, &dir_hnd);
1342         if (!NT_STATUS_IS_OK(status)) {
1343                 return status;
1344         }
1345
1346         while ((dname = ReadDirName(dir_hnd, &talloced))) {
1347                 struct smb_filename *smb_dname_full = NULL;
1348                 struct smb_filename *direntry_fname = NULL;
1349                 char *fullname = NULL;
1350                 int ret;
1351
1352                 if (ISDOT(dname) || (ISDOTDOT(dname))) {
1353                         TALLOC_FREE(talloced);
1354                         continue;
1355                 }
1356                 if (IS_VETO_PATH(conn, dname)) {
1357                         TALLOC_FREE(talloced);
1358                         continue;
1359                 }
1360
1361                 fullname = talloc_asprintf(talloc_tos(),
1362                                            "%s/%s",
1363                                            fsp->fsp_name->base_name,
1364                                            dname);
1365                 if (fullname == NULL) {
1366                         status = NT_STATUS_NO_MEMORY;
1367                         break;
1368                 }
1369
1370                 smb_dname_full = synthetic_smb_fname(talloc_tos(),
1371                                                      fullname,
1372                                                      NULL,
1373                                                      NULL,
1374                                                      fsp->fsp_name->twrp,
1375                                                      fsp->fsp_name->flags);
1376                 if (smb_dname_full == NULL) {
1377                         TALLOC_FREE(talloced);
1378                         TALLOC_FREE(fullname);
1379                         status = NT_STATUS_NO_MEMORY;
1380                         break;
1381                 }
1382
1383                 ret = SMB_VFS_LSTAT(conn, smb_dname_full);
1384                 if (ret != 0) {
1385                         status = map_nt_error_from_unix(errno);
1386                         TALLOC_FREE(talloced);
1387                         TALLOC_FREE(fullname);
1388                         TALLOC_FREE(smb_dname_full);
1389                         break;
1390                 }
1391
1392                 if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
1393                         /* Could it be an msdfs link ? */
1394                         if (lp_host_msdfs() &&
1395                             lp_msdfs_root(SNUM(conn))) {
1396                                 struct smb_filename *smb_dname;
1397                                 smb_dname = synthetic_smb_fname(talloc_tos(),
1398                                                         dname,
1399                                                         NULL,
1400                                                         &smb_dname_full->st,
1401                                                         fsp->fsp_name->twrp,
1402                                                         fsp->fsp_name->flags);
1403                                 if (smb_dname == NULL) {
1404                                         TALLOC_FREE(talloced);
1405                                         TALLOC_FREE(fullname);
1406                                         TALLOC_FREE(smb_dname_full);
1407                                         status = NT_STATUS_NO_MEMORY;
1408                                         break;
1409                                 }
1410                                 if (is_msdfs_link(fsp, smb_dname)) {
1411                                         TALLOC_FREE(talloced);
1412                                         TALLOC_FREE(fullname);
1413                                         TALLOC_FREE(smb_dname_full);
1414                                         TALLOC_FREE(smb_dname);
1415                                         DBG_DEBUG("got msdfs link name %s "
1416                                                 "- can't delete directory %s\n",
1417                                                 dname,
1418                                                 fsp_str_dbg(fsp));
1419                                         status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1420                                         break;
1421                                 }
1422                                 TALLOC_FREE(smb_dname);
1423                         }
1424                         /* Not a DFS link - could it be a dangling symlink ? */
1425                         ret = SMB_VFS_STAT(conn, smb_dname_full);
1426                         if (ret == -1 && (errno == ENOENT || errno == ELOOP)) {
1427                                 /*
1428                                  * Dangling symlink.
1429                                  * Allow if "delete veto files = yes"
1430                                  */
1431                                 if (lp_delete_veto_files(SNUM(conn))) {
1432                                         TALLOC_FREE(talloced);
1433                                         TALLOC_FREE(fullname);
1434                                         TALLOC_FREE(smb_dname_full);
1435                                         continue;
1436                                 }
1437                         }
1438                         DBG_DEBUG("got symlink name %s - "
1439                                 "can't delete directory %s\n",
1440                                 dname,
1441                                 fsp_str_dbg(fsp));
1442                         TALLOC_FREE(talloced);
1443                         TALLOC_FREE(fullname);
1444                         TALLOC_FREE(smb_dname_full);
1445                         status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1446                         break;
1447                 }
1448
1449                 /* Not a symlink, get a pathref. */
1450                 status = synthetic_pathref(talloc_tos(),
1451                                            fsp,
1452                                            dname,
1453                                            NULL,
1454                                            &smb_dname_full->st,
1455                                            fsp->fsp_name->twrp,
1456                                            fsp->fsp_name->flags,
1457                                            &direntry_fname);
1458                 if (!NT_STATUS_IS_OK(status)) {
1459                         status = map_nt_error_from_unix(errno);
1460                         TALLOC_FREE(talloced);
1461                         TALLOC_FREE(fullname);
1462                         TALLOC_FREE(smb_dname_full);
1463                         break;
1464                 }
1465
1466                 if (!is_visible_fsp(direntry_fname->fsp)) {
1467                         /*
1468                          * Hidden file.
1469                          * Allow if "delete veto files = yes"
1470                          */
1471                         if (lp_delete_veto_files(SNUM(conn))) {
1472                                 TALLOC_FREE(talloced);
1473                                 TALLOC_FREE(fullname);
1474                                 TALLOC_FREE(smb_dname_full);
1475                                 TALLOC_FREE(direntry_fname);
1476                                 continue;
1477                         }
1478                 }
1479
1480                 TALLOC_FREE(talloced);
1481                 TALLOC_FREE(fullname);
1482                 TALLOC_FREE(smb_dname_full);
1483                 TALLOC_FREE(direntry_fname);
1484
1485                 DBG_DEBUG("got name %s - can't delete\n", dname);
1486                 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1487                 break;
1488         }
1489         TALLOC_FREE(talloced);
1490         TALLOC_FREE(dir_hnd);
1491
1492         if (!NT_STATUS_IS_OK(status)) {
1493                 return status;
1494         }
1495
1496         if (!(fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) &&
1497             lp_strict_rename(SNUM(conn)) &&
1498             have_file_open_below(fsp->conn, fsp->fsp_name))
1499         {
1500                 return NT_STATUS_ACCESS_DENIED;
1501         }
1502
1503         return NT_STATUS_OK;
1504 }