2 Unix SMB/CIFS implementation.
3 Directory handling routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 2007
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.
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.
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/>.
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"
31 This module implements directory related functions for Samba.
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)
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)
44 /* Make directory handle internals available. */
46 struct name_cache_entry {
52 connection_struct *conn;
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 bool fallback_opendir;
66 struct dptr_struct *next, *prev;
69 struct connection_struct *conn;
70 struct smb_Dir *dir_hnd;
74 struct smb_filename *smb_dname;
75 bool has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
76 bool did_stat; /* Optimisation for non-wcard searches. */
77 bool priv; /* Directory handle opened with privilege. */
79 struct memcache *dptr_cache;
82 static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
87 static void DirCacheAdd(struct smb_Dir *dir_hnd, const char *name, long offset);
89 static struct smb_Dir *open_dir_safely(TALLOC_CTX *ctx,
90 connection_struct *conn,
91 const struct smb_filename *smb_dname,
94 static int smb_Dir_destructor(struct smb_Dir *dir_hnd);
96 #define INVALID_DPTR_KEY (-3)
98 /****************************************************************************
99 Initialise the dir bitmap.
100 ****************************************************************************/
102 bool init_dptrs(struct smbd_server_connection *sconn)
104 if (sconn->searches.dptr_bmap) {
108 sconn->searches.dptr_bmap = bitmap_talloc(
109 sconn, MAX_DIRECTORY_HANDLES);
111 if (sconn->searches.dptr_bmap == NULL) {
118 /****************************************************************************
119 Get the struct dptr_struct for a dir index.
120 ****************************************************************************/
122 static struct dptr_struct *dptr_get(struct smbd_server_connection *sconn,
125 struct dptr_struct *dptr;
127 for (dptr = sconn->searches.dirptrs; dptr != NULL; dptr = dptr->next) {
128 if(dptr->dnum != key) {
131 DLIST_PROMOTE(sconn->searches.dirptrs, dptr);
137 /****************************************************************************
138 Get the dir path for a dir index.
139 ****************************************************************************/
141 const char *dptr_path(struct smbd_server_connection *sconn, int key)
143 struct dptr_struct *dptr = dptr_get(sconn, key);
145 return(dptr->smb_dname->base_name);
149 /****************************************************************************
150 Get the dir wcard for a dir index.
151 ****************************************************************************/
153 const char *dptr_wcard(struct smbd_server_connection *sconn, int key)
155 struct dptr_struct *dptr = dptr_get(sconn, key);
161 /****************************************************************************
162 Get the dir attrib for a dir index.
163 ****************************************************************************/
165 uint16_t dptr_attr(struct smbd_server_connection *sconn, int key)
167 struct dptr_struct *dptr = dptr_get(sconn, key);
173 /****************************************************************************
174 Close a dptr (internal func).
175 ****************************************************************************/
177 static void dptr_close_internal(struct dptr_struct *dptr)
179 struct smbd_server_connection *sconn = dptr->conn->sconn;
181 DEBUG(4,("closing dptr key %d\n",dptr->dnum));
187 if (sconn->using_smb2) {
191 DLIST_REMOVE(sconn->searches.dirptrs, dptr);
194 * Free the dnum in the bitmap. Remember the dnum value is always
195 * biased by one with respect to the bitmap.
198 if (!bitmap_query(sconn->searches.dptr_bmap, dptr->dnum - 1)) {
199 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
203 bitmap_clear(sconn->searches.dptr_bmap, dptr->dnum - 1);
206 TALLOC_FREE(dptr->dir_hnd);
210 /****************************************************************************
211 Close all dptrs for a cnum.
212 ****************************************************************************/
214 void dptr_closecnum(connection_struct *conn)
216 struct dptr_struct *dptr, *next;
217 struct smbd_server_connection *sconn = conn->sconn;
223 for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
225 if (dptr->conn == conn) {
226 files_struct *fsp = dptr->dir_hnd->fsp;
227 close_file(NULL, fsp, NORMAL_CLOSE);
233 /****************************************************************************
234 Create a new dir ptr. If the flag old_handle is true then we must allocate
235 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
236 one byte long. If old_handle is false we allocate from the range
237 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
238 a directory handle is never zero.
239 wcard must not be zero.
240 ****************************************************************************/
242 NTSTATUS dptr_create(connection_struct *conn,
243 struct smb_request *req,
245 const struct smb_filename *smb_dname,
252 struct dptr_struct **dptr_ret)
254 struct smbd_server_connection *sconn = conn->sconn;
255 struct dptr_struct *dptr = NULL;
256 struct smb_Dir *dir_hnd;
258 if (fsp && fsp->is_directory && fsp->fh->fd != -1) {
259 smb_dname = fsp->fsp_name;
262 DEBUG(5,("dptr_create dir=%s\n", smb_dname->base_name));
265 DEBUG(0,("dptr_create: called with fake connection_struct\n"));
266 return NT_STATUS_INTERNAL_ERROR;
270 return NT_STATUS_INVALID_PARAMETER;
273 if (!(fsp->access_mask & SEC_DIR_LIST)) {
274 DBG_INFO("dptr_create: directory %s "
275 "not open for LIST access\n",
276 smb_dname->base_name);
277 return NT_STATUS_ACCESS_DENIED;
279 dir_hnd = OpenDir_fsp(NULL, conn, fsp, wcard, attr);
281 return map_nt_error_from_unix(errno);
284 dptr = talloc_zero(NULL, struct dptr_struct);
286 DEBUG(0,("talloc fail in dptr_create.\n"));
287 TALLOC_FREE(dir_hnd);
288 return NT_STATUS_NO_MEMORY;
291 dptr->smb_dname = cp_smb_filename(dptr, smb_dname);
292 if (!dptr->smb_dname) {
294 TALLOC_FREE(dir_hnd);
295 return NT_STATUS_NO_MEMORY;
298 dptr->dir_hnd = dir_hnd;
300 dptr->expect_close = expect_close;
301 dptr->wcard = talloc_strdup(dptr, wcard);
304 TALLOC_FREE(dir_hnd);
305 return NT_STATUS_NO_MEMORY;
307 if ((req != NULL && req->posix_pathnames) ||
308 (wcard[0] == '.' && wcard[1] == 0)) {
309 dptr->has_wild = True;
311 dptr->has_wild = wcard_has_wild;
316 if (sconn->using_smb2) {
323 * This is an old-style SMBsearch request. Ensure the
324 * value we return will fit in the range 1-255.
327 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 0);
329 if(dptr->dnum == -1 || dptr->dnum > 254) {
330 DBG_ERR("returned %d: Error - all old "
331 "dirptrs in use ?\n",
334 TALLOC_FREE(dir_hnd);
335 return NT_STATUS_TOO_MANY_OPENED_FILES;
340 * This is a new-style trans2 request. Allocate from
341 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
344 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 255);
346 if(dptr->dnum == -1 || dptr->dnum < 255) {
347 DBG_ERR("returned %d: Error - all new "
348 "dirptrs in use ?\n",
351 TALLOC_FREE(dir_hnd);
352 return NT_STATUS_TOO_MANY_OPENED_FILES;
356 bitmap_set(sconn->searches.dptr_bmap, dptr->dnum);
358 dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
360 DLIST_ADD(sconn->searches.dirptrs, dptr);
363 DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
365 dptr->smb_dname->base_name,
374 /****************************************************************************
375 Wrapper functions to access the lower level directory handles.
376 ****************************************************************************/
378 void dptr_CloseDir(files_struct *fsp)
382 * The destructor for the struct smb_Dir
383 * (fsp->dptr->dir_hnd) now handles
384 * all resource deallocation.
386 dptr_close_internal(fsp->dptr);
391 void dptr_SeekDir(struct dptr_struct *dptr, long offset)
393 SeekDir(dptr->dir_hnd, offset);
396 long dptr_TellDir(struct dptr_struct *dptr)
398 return TellDir(dptr->dir_hnd);
401 bool dptr_has_wild(struct dptr_struct *dptr)
403 return dptr->has_wild;
406 int dptr_dnum(struct dptr_struct *dptr)
411 bool dptr_get_priv(struct dptr_struct *dptr)
416 void dptr_set_priv(struct dptr_struct *dptr)
421 /****************************************************************************
422 Return the next visible file name, skipping veto'd and invisible files.
423 ****************************************************************************/
425 static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr,
426 long *poffset, SMB_STRUCT_STAT *pst,
429 /* Normal search for the next file. */
431 char *talloced = NULL;
433 while ((name = ReadDirName(dptr->dir_hnd, poffset, pst, &talloced))
435 if (is_visible_file(dptr->conn,
436 dptr->smb_dname->base_name,
440 *ptalloced = talloced;
443 TALLOC_FREE(talloced);
448 /****************************************************************************
449 Return the next visible file name, skipping veto'd and invisible files.
450 ****************************************************************************/
452 static char *dptr_ReadDirName(TALLOC_CTX *ctx,
453 struct dptr_struct *dptr,
455 SMB_STRUCT_STAT *pst)
457 struct smb_filename smb_fname_base;
459 const char *name_temp = NULL;
460 char *talloced = NULL;
461 char *pathreal = NULL;
462 char *found_name = NULL;
465 SET_STAT_INVALID(*pst);
467 if (dptr->has_wild || dptr->did_stat) {
468 name_temp = dptr_normal_ReadDirName(dptr, poffset, pst,
470 if (name_temp == NULL) {
473 if (talloced != NULL) {
474 return talloc_move(ctx, &talloced);
476 return talloc_strdup(ctx, name_temp);
479 /* If poffset is -1 then we know we returned this name before and we
480 * have no wildcards. We're at the end of the directory. */
481 if (*poffset == END_OF_DIRECTORY_OFFSET) {
485 /* We know the stored wcard contains no wildcard characters.
486 * See if we can match with a stat call. If we can't, then set
487 * did_stat to true to ensure we only do this once and keep
490 dptr->did_stat = true;
492 /* First check if it should be visible. */
493 if (!is_visible_file(dptr->conn,
494 dptr->smb_dname->base_name,
498 /* This only returns false if the file was found, but
499 is explicitly not visible. Set us to end of
500 directory, but return NULL as we know we can't ever
505 if (VALID_STAT(*pst)) {
506 name = talloc_strdup(ctx, dptr->wcard);
510 pathreal = talloc_asprintf(ctx,
512 dptr->smb_dname->base_name,
517 /* Create an smb_filename with stream_name == NULL. */
518 smb_fname_base = (struct smb_filename) { .base_name = pathreal };
520 if (SMB_VFS_STAT(dptr->conn, &smb_fname_base) == 0) {
521 *pst = smb_fname_base.st;
522 name = talloc_strdup(ctx, dptr->wcard);
525 /* If we get any other error than ENOENT or ENOTDIR
526 then the file exists we just can't stat it. */
527 if (errno != ENOENT && errno != ENOTDIR) {
528 name = talloc_strdup(ctx, dptr->wcard);
533 /* Stat failed. We know this is authoratiative if we are
534 * providing case sensitive semantics or the underlying
535 * filesystem is case sensitive.
537 if (dptr->conn->case_sensitive ||
538 !(dptr->conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH))
544 * Try case-insensitive stat if the fs has the ability. This avoids
545 * scanning the whole directory.
547 ret = SMB_VFS_GET_REAL_FILENAME(dptr->conn,
548 dptr->smb_dname->base_name,
555 } else if (errno == ENOENT) {
556 /* The case-insensitive lookup was authoritative. */
560 TALLOC_FREE(pathreal);
562 name_temp = dptr_normal_ReadDirName(dptr, poffset, pst, &talloced);
563 if (name_temp == NULL) {
566 if (talloced != NULL) {
567 return talloc_move(ctx, &talloced);
569 return talloc_strdup(ctx, name_temp);
572 TALLOC_FREE(pathreal);
574 /* We need to set the underlying dir_hnd offset to -1
575 * also as this function is usually called with the
576 * output from TellDir. */
577 dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
581 /****************************************************************************
582 Search for a file by name, skipping veto'ed and not visible files.
583 ****************************************************************************/
585 bool dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
587 SET_STAT_INVALID(*pst);
589 if (!dptr->has_wild && (dptr->dir_hnd->offset == END_OF_DIRECTORY_OFFSET)) {
590 /* This is a singleton directory and we're already at the end. */
591 *poffset = END_OF_DIRECTORY_OFFSET;
595 return SearchDir(dptr->dir_hnd, name, poffset);
598 /****************************************************************************
599 Map a native directory offset to a 32-bit cookie.
600 ****************************************************************************/
602 static uint32_t map_dir_offset_to_wire(struct dptr_struct *dptr, long offset)
607 if (offset == END_OF_DIRECTORY_OFFSET) {
608 return WIRE_END_OF_DIRECTORY_OFFSET;
609 } else if(offset == START_OF_DIRECTORY_OFFSET) {
610 return WIRE_START_OF_DIRECTORY_OFFSET;
611 } else if (offset == DOT_DOT_DIRECTORY_OFFSET) {
612 return WIRE_DOT_DOT_DIRECTORY_OFFSET;
614 if (sizeof(long) == 4) {
615 /* 32-bit machine. We can cheat... */
616 return (uint32_t)offset;
618 if (dptr->dptr_cache == NULL) {
619 /* Lazy initialize cache. */
620 dptr->dptr_cache = memcache_init(dptr, 0);
621 if (dptr->dptr_cache == NULL) {
622 return WIRE_END_OF_DIRECTORY_OFFSET;
625 /* Have we seen this offset before ? */
626 key.data = (void *)&offset;
627 key.length = sizeof(offset);
628 if (memcache_lookup(dptr->dptr_cache,
629 SMB1_SEARCH_OFFSET_MAP,
632 uint32_t wire_offset;
633 SMB_ASSERT(val.length == sizeof(wire_offset));
634 memcpy(&wire_offset, val.data, sizeof(wire_offset));
635 DEBUG(10,("found wire %u <-> offset %ld\n",
636 (unsigned int)wire_offset,
641 /* Allocate a new wire cookie. */
644 } while (dptr->counter == WIRE_START_OF_DIRECTORY_OFFSET ||
645 dptr->counter == WIRE_END_OF_DIRECTORY_OFFSET ||
646 dptr->counter == WIRE_DOT_DOT_DIRECTORY_OFFSET);
647 /* Store it in the cache. */
648 key.data = (void *)&offset;
649 key.length = sizeof(offset);
650 val.data = (void *)&dptr->counter;
651 val.length = sizeof(dptr->counter); /* MUST BE uint32_t ! */
652 memcache_add(dptr->dptr_cache,
653 SMB1_SEARCH_OFFSET_MAP,
656 /* And the reverse mapping for lookup from
657 map_wire_to_dir_offset(). */
658 memcache_add(dptr->dptr_cache,
659 SMB1_SEARCH_OFFSET_MAP,
662 DEBUG(10,("stored wire %u <-> offset %ld\n",
663 (unsigned int)dptr->counter,
665 return dptr->counter;
668 /****************************************************************************
669 Fill the 5 byte server reserved dptr field.
670 ****************************************************************************/
672 bool dptr_fill(struct smbd_server_connection *sconn,
673 char *buf1,unsigned int key)
675 unsigned char *buf = (unsigned char *)buf1;
676 struct dptr_struct *dptr = dptr_get(sconn, key);
677 uint32_t wire_offset;
679 DEBUG(1,("filling null dirptr %d\n",key));
682 wire_offset = map_dir_offset_to_wire(dptr,TellDir(dptr->dir_hnd));
683 DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
684 (long)dptr->dir_hnd,(int)wire_offset));
686 SIVAL(buf,1,wire_offset);
690 /****************************************************************************
691 Map a 32-bit wire cookie to a native directory offset.
692 ****************************************************************************/
694 static long map_wire_to_dir_offset(struct dptr_struct *dptr, uint32_t wire_offset)
699 if (wire_offset == WIRE_END_OF_DIRECTORY_OFFSET) {
700 return END_OF_DIRECTORY_OFFSET;
701 } else if(wire_offset == WIRE_START_OF_DIRECTORY_OFFSET) {
702 return START_OF_DIRECTORY_OFFSET;
703 } else if (wire_offset == WIRE_DOT_DOT_DIRECTORY_OFFSET) {
704 return DOT_DOT_DIRECTORY_OFFSET;
706 if (sizeof(long) == 4) {
707 /* 32-bit machine. We can cheat... */
708 return (long)wire_offset;
710 if (dptr->dptr_cache == NULL) {
711 /* Logic error, cache should be initialized. */
712 return END_OF_DIRECTORY_OFFSET;
714 key.data = (void *)&wire_offset;
715 key.length = sizeof(wire_offset);
716 if (memcache_lookup(dptr->dptr_cache,
717 SMB1_SEARCH_OFFSET_MAP,
722 SMB_ASSERT(val.length == sizeof(offset));
723 memcpy(&offset, val.data, sizeof(offset));
724 DEBUG(10,("lookup wire %u <-> offset %ld\n",
725 (unsigned int)wire_offset,
729 return END_OF_DIRECTORY_OFFSET;
732 /****************************************************************************
733 Return the associated fsp and seek the dir_hnd on it it given the 5 byte
735 ****************************************************************************/
737 files_struct *dptr_fetch_fsp(struct smbd_server_connection *sconn,
740 unsigned int key = *(unsigned char *)buf;
741 struct dptr_struct *dptr = dptr_get(sconn, key);
742 uint32_t wire_offset;
746 DEBUG(3,("fetched null dirptr %d\n",key));
750 wire_offset = IVAL(buf,1);
751 seekoff = map_wire_to_dir_offset(dptr, wire_offset);
752 SeekDir(dptr->dir_hnd,seekoff);
753 DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
754 key, dptr->smb_dname->base_name, (int)seekoff));
755 return dptr->dir_hnd->fsp;
758 /****************************************************************************
759 Fetch the fsp associated with the dptr_num.
760 ****************************************************************************/
762 files_struct *dptr_fetch_lanman2_fsp(struct smbd_server_connection *sconn,
765 struct dptr_struct *dptr = dptr_get(sconn, dptr_num);
769 DBG_NOTICE("fetching dirptr %d for path %s\n",
771 dptr->smb_dname->base_name);
772 return dptr->dir_hnd->fsp;
775 static bool mangle_mask_match(connection_struct *conn,
776 const char *filename,
781 if (!name_to_8_3(filename,mname,False,conn->params)) {
784 return mask_match_search(mname,mask,False);
787 bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
788 struct dptr_struct *dirptr,
794 bool (*match_fn)(TALLOC_CTX *ctx,
799 bool (*mode_fn)(TALLOC_CTX *ctx,
801 struct smb_filename *smb_fname,
806 struct smb_filename **_smb_fname,
810 connection_struct *conn = dirptr->conn;
813 const char *dpath = dirptr->smb_dname->base_name;
814 bool dirptr_path_is_dot = ISDOT(dpath);
819 pathlen = strlen(dpath);
820 slashlen = ( dpath[pathlen-1] != '/') ? 1 : 0;
825 SMB_STRUCT_STAT sbuf = { 0 };
829 char *pathreal = NULL;
830 struct smb_filename smb_fname;
834 cur_offset = dptr_TellDir(dirptr);
835 prev_offset = cur_offset;
836 dname = dptr_ReadDirName(ctx, dirptr, &cur_offset, &sbuf);
838 DEBUG(6,("smbd_dirptr_get_entry: dirptr 0x%lx now at offset %ld\n",
839 (long)dirptr, cur_offset));
845 isdots = (ISDOT(dname) || ISDOTDOT(dname));
846 if (dont_descend && !isdots) {
852 * fname may get mangled, dname is never mangled.
853 * Whenever we're accessing the filesystem we use
854 * pathreal which is composed from dname.
857 ok = match_fn(ctx, private_data, dname, mask, &fname);
865 * pathreal = talloc_asprintf(ctx, "%s%s%s", dirptr->path,
866 * needslash?"/":"", dname);
867 * but this was measurably slower than doing the memcpy.
870 pathreal = talloc_array(
872 pathlen + slashlen + talloc_get_size(dname));
880 * We don't want to pass ./xxx to modules below us so don't
881 * add the path if it is just . by itself.
883 if (dirptr_path_is_dot) {
884 memcpy(pathreal, dname, talloc_get_size(dname));
886 memcpy(pathreal, dpath, pathlen);
887 pathreal[pathlen] = '/';
888 memcpy(pathreal + slashlen + pathlen, dname,
889 talloc_get_size(dname));
892 /* Create smb_fname with NULL stream_name. */
893 smb_fname = (struct smb_filename) {
894 .base_name = pathreal, .st = sbuf
897 ok = mode_fn(ctx, private_data, &smb_fname, get_dosmode, &mode);
901 TALLOC_FREE(pathreal);
905 if (!dir_check_ftype(mode, dirtype)) {
906 DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",
907 fname, (unsigned int)mode, (unsigned int)dirtype));
910 TALLOC_FREE(pathreal);
915 struct timespec write_time_ts;
916 struct file_id fileid;
918 fileid = vfs_file_id_from_sbuf(conn,
920 get_file_infos(fileid, 0, NULL, &write_time_ts);
921 if (!null_timespec(write_time_ts)) {
922 update_stat_ex_mtime(&smb_fname.st,
927 DEBUG(3,("smbd_dirptr_get_entry mask=[%s] found %s "
929 mask, smb_fname_str_dbg(&smb_fname),
932 if (!conn->sconn->using_smb2) {
934 * The dircache is only needed for SMB1 because SMB1
935 * uses a name for the resume wheras SMB2 always
936 * continues from the next position (unless it's told to
937 * restart or close-and-reopen the listing).
939 DirCacheAdd(dirptr->dir_hnd, dname, cur_offset);
944 *_smb_fname = cp_smb_filename(ctx, &smb_fname);
945 TALLOC_FREE(pathreal);
946 if (*_smb_fname == NULL) {
951 *_prev_offset = prev_offset;
959 /****************************************************************************
960 Get an 8.3 directory entry.
961 ****************************************************************************/
963 static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX *ctx,
969 connection_struct *conn = (connection_struct *)private_data;
971 if ((strcmp(mask,"*.*") == 0) ||
972 mask_match_search(dname, mask, false) ||
973 mangle_mask_match(conn, dname, mask)) {
977 * Ensure we can push the original name as UCS2. If
978 * not, then just don't return this name.
982 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
983 uint8_t *tmp = talloc_array(talloc_tos(),
987 status = srvstr_push(NULL,
988 FLAGS2_UNICODE_STRINGS,
997 if (!NT_STATUS_IS_OK(status)) {
1001 if (!mangle_is_8_3(dname, false, conn->params)) {
1002 bool ok = name_to_8_3(dname, mname, false,
1012 *_fname = talloc_strdup(ctx, fname);
1013 if (*_fname == NULL) {
1023 static bool smbd_dirptr_8_3_mode_fn(TALLOC_CTX *ctx,
1025 struct smb_filename *smb_fname,
1029 connection_struct *conn = (connection_struct *)private_data;
1031 if (!VALID_STAT(smb_fname->st)) {
1032 if ((SMB_VFS_STAT(conn, smb_fname)) != 0) {
1033 DEBUG(5,("smbd_dirptr_8_3_mode_fn: "
1034 "Couldn't stat [%s]. Error "
1036 smb_fname_str_dbg(smb_fname),
1042 *_mode = dos_mode(conn, smb_fname);
1046 bool get_dir_entry(TALLOC_CTX *ctx,
1047 struct dptr_struct *dirptr,
1053 struct timespec *_date,
1057 connection_struct *conn = dirptr->conn;
1059 struct smb_filename *smb_fname = NULL;
1064 ok = smbd_dirptr_get_entry(ctx,
1071 smbd_dirptr_8_3_match_fn,
1072 smbd_dirptr_8_3_mode_fn,
1082 *_fname = talloc_move(ctx, &fname);
1083 *_size = smb_fname->st.st_ex_size;
1085 *_date = smb_fname->st.st_ex_mtime;
1086 TALLOC_FREE(smb_fname);
1090 /*******************************************************************
1091 Check to see if a user can read a file. This is only approximate,
1092 it is used as part of the "hide unreadable" option. Don't
1093 use it for anything security sensitive.
1094 ********************************************************************/
1096 static bool user_can_read_file(connection_struct *conn,
1097 struct smb_filename *smb_fname)
1100 uint32_t rejected_share_access = 0;
1101 uint32_t rejected_mask = 0;
1102 struct security_descriptor *sd = NULL;
1103 uint32_t access_mask = FILE_READ_DATA|
1105 FILE_READ_ATTRIBUTES|
1106 SEC_STD_READ_CONTROL;
1109 * Never hide files from the root user.
1110 * We use (uid_t)0 here not sec_initial_uid()
1111 * as make test uses a single user context.
1114 if (get_current_uid(conn) == (uid_t)0) {
1119 * We can't directly use smbd_check_access_rights()
1120 * here, as this implicitly grants FILE_READ_ATTRIBUTES
1121 * which the Windows access-based-enumeration code
1122 * explicitly checks for on the file security descriptor.
1125 * https://bugzilla.samba.org/show_bug.cgi?id=10252
1127 * and the smb2.acl2.ACCESSBASED test for details.
1130 rejected_share_access = access_mask & ~(conn->share_access);
1131 if (rejected_share_access) {
1132 DEBUG(10, ("rejected share access 0x%x "
1134 (unsigned int)access_mask,
1135 smb_fname_str_dbg(smb_fname),
1136 (unsigned int)rejected_share_access ));
1140 status = SMB_VFS_GET_NT_ACL(conn,
1148 if (!NT_STATUS_IS_OK(status)) {
1149 DEBUG(10, ("Could not get acl "
1151 smb_fname_str_dbg(smb_fname),
1152 nt_errstr(status)));
1156 status = se_file_access_check(sd,
1157 get_current_nttok(conn),
1164 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1165 DEBUG(10,("rejected bits 0x%x read access for %s\n",
1166 (unsigned int)rejected_mask,
1167 smb_fname_str_dbg(smb_fname) ));
1173 /*******************************************************************
1174 Check to see if a user can write a file (and only files, we do not
1175 check dirs on this one). This is only approximate,
1176 it is used as part of the "hide unwriteable" option. Don't
1177 use it for anything security sensitive.
1178 ********************************************************************/
1180 static bool user_can_write_file(connection_struct *conn,
1181 const struct smb_filename *smb_fname)
1184 * Never hide files from the root user.
1185 * We use (uid_t)0 here not sec_initial_uid()
1186 * as make test uses a single user context.
1189 if (get_current_uid(conn) == (uid_t)0) {
1193 SMB_ASSERT(VALID_STAT(smb_fname->st));
1195 /* Pseudo-open the file */
1197 if(S_ISDIR(smb_fname->st.st_ex_mode)) {
1201 return can_write_to_file(conn, smb_fname);
1204 /*******************************************************************
1205 Is a file a "special" type ?
1206 ********************************************************************/
1208 static bool file_is_special(connection_struct *conn,
1209 const struct smb_filename *smb_fname)
1212 * Never hide files from the root user.
1213 * We use (uid_t)0 here not sec_initial_uid()
1214 * as make test uses a single user context.
1217 if (get_current_uid(conn) == (uid_t)0) {
1221 SMB_ASSERT(VALID_STAT(smb_fname->st));
1223 if (S_ISREG(smb_fname->st.st_ex_mode) ||
1224 S_ISDIR(smb_fname->st.st_ex_mode) ||
1225 S_ISLNK(smb_fname->st.st_ex_mode))
1231 /*******************************************************************
1232 Should the file be seen by the client?
1233 NOTE: A successful return is no guarantee of the file's existence.
1234 ********************************************************************/
1236 bool is_visible_file(connection_struct *conn, const char *dir_path,
1237 const char *name, SMB_STRUCT_STAT *pst, bool use_veto)
1239 bool hide_unreadable = lp_hide_unreadable(SNUM(conn));
1240 bool hide_unwriteable = lp_hide_unwriteable_files(SNUM(conn));
1241 bool hide_special = lp_hide_special_files(SNUM(conn));
1242 int hide_new_files_timeout = lp_hide_new_files_timeout(SNUM(conn));
1244 struct smb_filename *smb_fname_base = NULL;
1247 if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
1248 return True; /* . and .. are always visible. */
1251 /* If it's a vetoed file, pretend it doesn't even exist */
1252 if (use_veto && IS_VETO_PATH(conn, name)) {
1253 DEBUG(10,("is_visible_file: file %s is vetoed.\n", name ));
1257 if (hide_unreadable ||
1260 (hide_new_files_timeout != 0))
1262 entry = talloc_asprintf(talloc_tos(), "%s/%s", dir_path, name);
1268 /* Create an smb_filename with stream_name == NULL. */
1269 smb_fname_base = synthetic_smb_fname(talloc_tos(),
1274 if (smb_fname_base == NULL) {
1279 /* If the file name does not exist, there's no point checking
1280 * the configuration options. We succeed, on the basis that the
1281 * checks *might* have passed if the file was present.
1283 if (!VALID_STAT(*pst)) {
1284 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
1288 *pst = smb_fname_base->st;
1291 /* Honour _hide unreadable_ option */
1292 if (hide_unreadable &&
1293 !user_can_read_file(conn, smb_fname_base)) {
1294 DEBUG(10,("is_visible_file: file %s is unreadable.\n",
1299 /* Honour _hide unwriteable_ option */
1300 if (hide_unwriteable && !user_can_write_file(conn,
1302 DEBUG(10,("is_visible_file: file %s is unwritable.\n",
1307 /* Honour _hide_special_ option */
1308 if (hide_special && file_is_special(conn, smb_fname_base)) {
1309 DEBUG(10,("is_visible_file: file %s is special.\n",
1315 if (hide_new_files_timeout != 0) {
1317 double age = timespec_elapsed(
1318 &smb_fname_base->st.st_ex_mtime);
1320 if (age < (double)hide_new_files_timeout) {
1329 TALLOC_FREE(smb_fname_base);
1334 static int smb_Dir_destructor(struct smb_Dir *dir_hnd)
1336 files_struct *fsp = dir_hnd->fsp;
1338 SMB_VFS_CLOSEDIR(dir_hnd->conn, dir_hnd->dir);
1340 * The SMB_VFS_CLOSEDIR above
1341 * closes the underlying fd inside
1342 * dirp->fsp, unless fallback_opendir
1343 * was set in which case the fd
1344 * in dir_hnd->fsp->fh->fd isn't
1345 * the one being closed. Close
1348 if (dir_hnd->fallback_opendir) {
1352 SMB_ASSERT(fsp->dptr->dir_hnd == dir_hnd);
1353 fsp->dptr->dir_hnd = NULL;
1354 dir_hnd->fsp = NULL;
1358 /*******************************************************************
1360 ********************************************************************/
1362 static struct smb_Dir *OpenDir_internal(TALLOC_CTX *mem_ctx,
1363 connection_struct *conn,
1364 const struct smb_filename *smb_dname,
1368 struct smb_Dir *dir_hnd = talloc_zero(mem_ctx, struct smb_Dir);
1374 dir_hnd->dir = SMB_VFS_OPENDIR(conn, smb_dname, mask, attr);
1376 if (!dir_hnd->dir) {
1377 DEBUG(5,("OpenDir: Can't open %s. %s\n",
1378 smb_dname->base_name,
1383 dir_hnd->conn = conn;
1385 if (!conn->sconn->using_smb2) {
1387 * The dircache is only needed for SMB1 because SMB1 uses a name
1388 * for the resume wheras SMB2 always continues from the next
1389 * position (unless it's told to restart or close-and-reopen the
1392 dir_hnd->name_cache_size =
1393 lp_directory_name_cache_size(SNUM(conn));
1399 TALLOC_FREE(dir_hnd);
1404 * @brief Open a directory handle by pathname, ensuring it's under the share path.
1406 * First stores the $cwd, then changes directory to the passed in pathname
1407 * uses check_name() to ensure this is under the connection struct share path,
1408 * then operates on a pathname of "." to ensure we're in the same place.
1410 * The returned struct smb_Dir * should have a talloc destrctor added to
1411 * ensure that when the struct is freed the internal POSIX DIR * pointer
1416 * static int sample_smb_Dir_destructor(struct smb_Dir *dirp)
1418 * SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1421 * struct smb_Dir *dir_hnd = open_dir_safely(mem_ctx,
1426 * if (dir_hnd == NULL) {
1429 * talloc_set_destructor(dir_hnd, smb_Dir_destructor);
1434 static struct smb_Dir *open_dir_safely(TALLOC_CTX *ctx,
1435 connection_struct *conn,
1436 const struct smb_filename *smb_dname,
1440 struct smb_Dir *dir_hnd = NULL;
1441 struct smb_filename *smb_fname_cwd = NULL;
1442 struct smb_filename *saved_dir_fname = vfs_GetWd(ctx, conn);
1445 if (saved_dir_fname == NULL) {
1449 if (vfs_ChDir(conn, smb_dname) == -1) {
1453 smb_fname_cwd = synthetic_smb_fname(talloc_tos(),
1458 if (smb_fname_cwd == NULL) {
1463 * Now the directory is pinned, use
1464 * REALPATH to ensure we can access it.
1466 status = check_name(conn, smb_fname_cwd);
1467 if (!NT_STATUS_IS_OK(status)) {
1471 dir_hnd = OpenDir_internal(ctx,
1477 if (dir_hnd == NULL) {
1482 * OpenDir_internal only gets "." as the dir name.
1483 * Store the real dir name here.
1486 dir_hnd->dir_smb_fname = cp_smb_filename(dir_hnd, smb_dname);
1487 if (!dir_hnd->dir_smb_fname) {
1488 TALLOC_FREE(dir_hnd);
1489 SMB_VFS_CLOSEDIR(conn, dir_hnd->dir);
1495 vfs_ChDir(conn, saved_dir_fname);
1496 TALLOC_FREE(saved_dir_fname);
1501 * Simple destructor for OpenDir() use. Don't need to
1502 * care about fsp back pointer as we know we have never
1503 * set it in the OpenDir() code path.
1506 static int smb_Dir_OpenDir_destructor(struct smb_Dir *dir_hnd)
1508 SMB_VFS_CLOSEDIR(dir_hnd->conn, dir_hnd->dir);
1512 struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
1513 const struct smb_filename *smb_dname,
1517 struct smb_Dir *dir_hnd = open_dir_safely(mem_ctx,
1522 if (dir_hnd == NULL) {
1525 talloc_set_destructor(dir_hnd, smb_Dir_OpenDir_destructor);
1529 /*******************************************************************
1530 Open a directory from an fsp.
1531 ********************************************************************/
1533 static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
1538 struct smb_Dir *dir_hnd = talloc_zero(mem_ctx, struct smb_Dir);
1544 if (!fsp->is_directory) {
1549 if (fsp->fh->fd == -1) {
1554 dir_hnd->conn = conn;
1556 if (!conn->sconn->using_smb2) {
1558 * The dircache is only needed for SMB1 because SMB1 uses a name
1559 * for the resume wheras SMB2 always continues from the next
1560 * position (unless it's told to restart or close-and-reopen the
1563 dir_hnd->name_cache_size =
1564 lp_directory_name_cache_size(SNUM(conn));
1567 dir_hnd->dir_smb_fname = cp_smb_filename(dir_hnd, fsp->fsp_name);
1568 if (!dir_hnd->dir_smb_fname) {
1573 dir_hnd->dir = SMB_VFS_FDOPENDIR(fsp, mask, attr);
1574 if (dir_hnd->dir != NULL) {
1577 DEBUG(10,("OpenDir_fsp: SMB_VFS_FDOPENDIR on %s returned "
1579 dir_hnd->dir_smb_fname->base_name,
1581 if (errno != ENOSYS) {
1586 if (dir_hnd->dir == NULL) {
1587 /* FDOPENDIR is not supported. Use OPENDIR instead. */
1588 TALLOC_FREE(dir_hnd);
1589 dir_hnd = open_dir_safely(mem_ctx,
1594 if (dir_hnd == NULL) {
1599 * Remember if we used the fallback.
1600 * We need to change the destructor
1601 * to also close the fsp file descriptor
1602 * in this case as it isn't the same
1603 * one the directory handle uses.
1606 dir_hnd->fallback_opendir = true;
1609 talloc_set_destructor(dir_hnd, smb_Dir_destructor);
1614 TALLOC_FREE(dir_hnd);
1619 /*******************************************************************
1620 Read from a directory.
1621 Return directory entry, current offset, and optional stat information.
1622 Don't check for veto or invisible files.
1623 ********************************************************************/
1625 const char *ReadDirName(struct smb_Dir *dir_hnd, long *poffset,
1626 SMB_STRUCT_STAT *sbuf, char **ptalloced)
1629 char *talloced = NULL;
1630 connection_struct *conn = dir_hnd->conn;
1632 /* Cheat to allow . and .. to be the first entries returned. */
1633 if (((*poffset == START_OF_DIRECTORY_OFFSET) ||
1634 (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dir_hnd->file_number < 2))
1636 if (dir_hnd->file_number == 0) {
1638 *poffset = dir_hnd->offset = START_OF_DIRECTORY_OFFSET;
1641 *poffset = dir_hnd->offset = DOT_DOT_DIRECTORY_OFFSET;
1643 dir_hnd->file_number++;
1648 if (*poffset == END_OF_DIRECTORY_OFFSET) {
1649 *poffset = dir_hnd->offset = END_OF_DIRECTORY_OFFSET;
1653 /* A real offset, seek to it. */
1654 SeekDir(dir_hnd, *poffset);
1656 while ((n = vfs_readdirname(conn, dir_hnd->dir, sbuf, &talloced))) {
1657 /* Ignore . and .. - we've already returned them. */
1659 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
1660 TALLOC_FREE(talloced);
1664 *poffset = dir_hnd->offset = SMB_VFS_TELLDIR(conn, dir_hnd->dir);
1665 *ptalloced = talloced;
1666 dir_hnd->file_number++;
1669 *poffset = dir_hnd->offset = END_OF_DIRECTORY_OFFSET;
1674 /*******************************************************************
1675 Rewind to the start.
1676 ********************************************************************/
1678 void RewindDir(struct smb_Dir *dir_hnd, long *poffset)
1680 SMB_VFS_REWINDDIR(dir_hnd->conn, dir_hnd->dir);
1681 dir_hnd->file_number = 0;
1682 dir_hnd->offset = START_OF_DIRECTORY_OFFSET;
1683 *poffset = START_OF_DIRECTORY_OFFSET;
1686 /*******************************************************************
1688 ********************************************************************/
1690 void SeekDir(struct smb_Dir *dirp, long offset)
1692 if (offset != dirp->offset) {
1693 if (offset == START_OF_DIRECTORY_OFFSET) {
1694 RewindDir(dirp, &offset);
1696 * Ok we should really set the file number here
1697 * to 1 to enable ".." to be returned next. Trouble
1698 * is I'm worried about callers using SeekDir(dirp,0)
1699 * as equivalent to RewindDir(). So leave this alone
1702 } else if (offset == DOT_DOT_DIRECTORY_OFFSET) {
1703 RewindDir(dirp, &offset);
1705 * Set the file number to 2 - we want to get the first
1706 * real file entry (the one we return after "..")
1707 * on the next ReadDir.
1709 dirp->file_number = 2;
1710 } else if (offset == END_OF_DIRECTORY_OFFSET) {
1711 ; /* Don't seek in this case. */
1713 SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1715 dirp->offset = offset;
1719 /*******************************************************************
1720 Tell a dir position.
1721 ********************************************************************/
1723 long TellDir(struct smb_Dir *dir_hnd)
1725 return(dir_hnd->offset);
1728 /*******************************************************************
1729 Add an entry into the dcache.
1730 ********************************************************************/
1732 static void DirCacheAdd(struct smb_Dir *dir_hnd, const char *name, long offset)
1734 struct name_cache_entry *e;
1736 if (dir_hnd->name_cache_size == 0) {
1740 if (dir_hnd->name_cache == NULL) {
1741 dir_hnd->name_cache = talloc_zero_array(dir_hnd,
1742 struct name_cache_entry,
1743 dir_hnd->name_cache_size);
1745 if (dir_hnd->name_cache == NULL) {
1750 dir_hnd->name_cache_index = (dir_hnd->name_cache_index+1) %
1751 dir_hnd->name_cache_size;
1752 e = &dir_hnd->name_cache[dir_hnd->name_cache_index];
1753 TALLOC_FREE(e->name);
1754 e->name = talloc_strdup(dir_hnd, name);
1758 /*******************************************************************
1759 Find an entry by name. Leave us at the offset after it.
1760 Don't check for veto or invisible files.
1761 ********************************************************************/
1763 bool SearchDir(struct smb_Dir *dir_hnd, const char *name, long *poffset)
1766 const char *entry = NULL;
1767 char *talloced = NULL;
1768 connection_struct *conn = dir_hnd->conn;
1770 /* Search back in the name cache. */
1771 if (dir_hnd->name_cache_size && dir_hnd->name_cache) {
1772 for (i = dir_hnd->name_cache_index; i >= 0; i--) {
1773 struct name_cache_entry *e = &dir_hnd->name_cache[i];
1774 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1775 *poffset = e->offset;
1776 SeekDir(dir_hnd, e->offset);
1780 for (i = dir_hnd->name_cache_size - 1;
1781 i > dir_hnd->name_cache_index; i--) {
1782 struct name_cache_entry *e = &dir_hnd->name_cache[i];
1783 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1784 *poffset = e->offset;
1785 SeekDir(dir_hnd, e->offset);
1791 /* Not found in the name cache. Rewind directory and start from scratch. */
1792 SMB_VFS_REWINDDIR(conn, dir_hnd->dir);
1793 dir_hnd->file_number = 0;
1794 *poffset = START_OF_DIRECTORY_OFFSET;
1795 while ((entry = ReadDirName(dir_hnd, poffset, NULL, &talloced))) {
1796 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
1797 TALLOC_FREE(talloced);
1800 TALLOC_FREE(talloced);
1805 struct files_below_forall_state {
1808 int (*fn)(struct file_id fid, const struct share_mode_data *data,
1809 void *private_data);
1813 static int files_below_forall_fn(struct file_id fid,
1814 const struct share_mode_data *data,
1817 struct files_below_forall_state *state = private_data;
1818 char tmpbuf[PATH_MAX];
1819 char *fullpath, *to_free;
1822 len = full_path_tos(data->servicepath, data->base_name,
1823 tmpbuf, sizeof(tmpbuf),
1824 &fullpath, &to_free);
1828 if (state->dirpath_len >= len) {
1830 * Filter files above dirpath
1834 if (fullpath[state->dirpath_len] != '/') {
1836 * Filter file that don't have a path separator at the end of
1842 if (memcmp(state->dirpath, fullpath, state->dirpath_len) != 0) {
1849 TALLOC_FREE(to_free);
1850 return state->fn(fid, data, state->private_data);
1853 TALLOC_FREE(to_free);
1857 static int files_below_forall(connection_struct *conn,
1858 const struct smb_filename *dir_name,
1859 int (*fn)(struct file_id fid,
1860 const struct share_mode_data *data,
1861 void *private_data),
1864 struct files_below_forall_state state = {
1866 .private_data = private_data,
1869 char tmpbuf[PATH_MAX];
1872 state.dirpath_len = full_path_tos(conn->connectpath,
1873 dir_name->base_name,
1874 tmpbuf, sizeof(tmpbuf),
1875 &state.dirpath, &to_free);
1876 if (state.dirpath_len == -1) {
1880 ret = share_mode_forall(files_below_forall_fn, &state);
1881 TALLOC_FREE(to_free);
1885 struct have_file_open_below_state {
1889 static int have_file_open_below_fn(struct file_id fid,
1890 const struct share_mode_data *data,
1893 struct have_file_open_below_state *state = private_data;
1894 state->found_one = true;
1898 bool have_file_open_below(connection_struct *conn,
1899 const struct smb_filename *name)
1901 struct have_file_open_below_state state = {
1906 if (!VALID_STAT(name->st)) {
1909 if (!S_ISDIR(name->st.st_ex_mode)) {
1913 ret = files_below_forall(conn, name, have_file_open_below_fn, &state);
1918 return state.found_one;
1921 /*****************************************************************
1922 Is this directory empty ?
1923 *****************************************************************/
1925 NTSTATUS can_delete_directory_fsp(files_struct *fsp)
1927 NTSTATUS status = NT_STATUS_OK;
1929 const char *dname = NULL;
1930 const char *dirname = fsp->fsp_name->base_name;
1931 char *talloced = NULL;
1933 struct connection_struct *conn = fsp->conn;
1934 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(),
1941 return map_nt_error_from_unix(errno);
1944 while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced))) {
1945 /* Quick check for "." and ".." */
1946 if (dname[0] == '.') {
1947 if (!dname[1] || (dname[1] == '.' && !dname[2])) {
1948 TALLOC_FREE(talloced);
1953 if (!is_visible_file(conn, dirname, dname, &st, True)) {
1954 TALLOC_FREE(talloced);
1958 DEBUG(10,("got name %s - can't delete\n",
1960 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1963 TALLOC_FREE(talloced);
1964 TALLOC_FREE(dir_hnd);
1966 if (!NT_STATUS_IS_OK(status)) {
1970 if (!(fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) &&
1971 lp_strict_rename(SNUM(conn)) &&
1972 have_file_open_below(fsp->conn, fsp->fsp_name))
1974 return NT_STATUS_ACCESS_DENIED;
1977 return NT_STATUS_OK;