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 "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"
33 This module implements directory related functions for Samba.
36 /* "Special" directory offsets. */
37 #define END_OF_DIRECTORY_OFFSET ((long)-1)
38 #define START_OF_DIRECTORY_OFFSET ((long)0)
39 #define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000)
41 /* "Special" directory offsets in 32-bit wire format. */
42 #define WIRE_END_OF_DIRECTORY_OFFSET ((uint32_t)0xFFFFFFFF)
43 #define WIRE_START_OF_DIRECTORY_OFFSET ((uint32_t)0)
44 #define WIRE_DOT_DOT_DIRECTORY_OFFSET ((uint32_t)0x80000000)
46 /* Make directory handle internals available. */
48 struct name_cache_entry {
54 connection_struct *conn;
57 struct smb_filename *dir_smb_fname;
58 size_t name_cache_size;
59 struct name_cache_entry *name_cache;
60 unsigned int name_cache_index;
61 unsigned int file_number;
63 files_struct *fsp; /* Back pointer to containing fsp, only
64 set from OpenDir_fsp(). */
68 struct dptr_struct *next, *prev;
70 struct connection_struct *conn;
71 struct smb_Dir *dir_hnd;
74 bool has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
75 bool did_stat; /* Optimisation for non-wcard searches. */
76 bool priv; /* Directory handle opened with privilege. */
78 struct memcache *dptr_cache;
81 static NTSTATUS OpenDir_fsp(
83 connection_struct *conn,
87 struct smb_Dir **_dir_hnd);
89 static void DirCacheAdd(struct smb_Dir *dir_hnd, const char *name, long offset);
91 static int smb_Dir_destructor(struct smb_Dir *dir_hnd);
93 static bool SearchDir(struct smb_Dir *dir_hnd, const char *name, long *poffset);
95 #define INVALID_DPTR_KEY (-3)
97 /****************************************************************************
98 Initialise the dir bitmap.
99 ****************************************************************************/
101 bool init_dptrs(struct smbd_server_connection *sconn)
103 if (sconn->searches.dptr_bmap) {
107 sconn->searches.dptr_bmap = bitmap_talloc(
108 sconn, MAX_DIRECTORY_HANDLES);
110 if (sconn->searches.dptr_bmap == NULL) {
117 /****************************************************************************
118 Get the struct dptr_struct for a dir index.
119 ****************************************************************************/
121 static struct dptr_struct *dptr_get(struct smbd_server_connection *sconn,
124 struct dptr_struct *dptr;
126 for (dptr = sconn->searches.dirptrs; dptr != NULL; dptr = dptr->next) {
127 if(dptr->dnum != key) {
130 DLIST_PROMOTE(sconn->searches.dirptrs, dptr);
136 /****************************************************************************
137 Get the dir path for a dir index.
138 ****************************************************************************/
140 const char *dptr_path(struct smbd_server_connection *sconn, int key)
142 struct dptr_struct *dptr = dptr_get(sconn, key);
144 return(dptr->dir_hnd->dir_smb_fname->base_name);
148 /****************************************************************************
149 Get the dir wcard for a dir index.
150 ****************************************************************************/
152 const char *dptr_wcard(struct smbd_server_connection *sconn, int key)
154 struct dptr_struct *dptr = dptr_get(sconn, key);
160 /****************************************************************************
161 Get the dir attrib for a dir index.
162 ****************************************************************************/
164 uint16_t dptr_attr(struct smbd_server_connection *sconn, int key)
166 struct dptr_struct *dptr = dptr_get(sconn, key);
172 /****************************************************************************
173 Close all dptrs for a cnum.
174 ****************************************************************************/
176 void dptr_closecnum(connection_struct *conn)
178 struct dptr_struct *dptr, *next;
179 struct smbd_server_connection *sconn = conn->sconn;
185 for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
187 if (dptr->conn == conn) {
189 * Need to make a copy, "dptr" will be gone
190 * after close_file_free() returns
192 struct files_struct *fsp = dptr->dir_hnd->fsp;
193 close_file_free(NULL, &fsp, NORMAL_CLOSE);
198 /****************************************************************************
199 Create a new dir ptr. If the flag old_handle is true then we must allocate
200 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
201 one byte long. If old_handle is false we allocate from the range
202 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
203 a directory handle is never zero.
204 wcard must not be zero.
205 ****************************************************************************/
207 NTSTATUS dptr_create(connection_struct *conn,
208 struct smb_request *req,
213 struct dptr_struct **dptr_ret)
215 struct smbd_server_connection *sconn = conn->sconn;
216 struct dptr_struct *dptr = NULL;
217 struct smb_Dir *dir_hnd = NULL;
220 DBG_INFO("dir=%s\n", fsp_str_dbg(fsp));
223 DEBUG(0,("dptr_create: called with fake connection_struct\n"));
224 return NT_STATUS_INTERNAL_ERROR;
228 return NT_STATUS_INVALID_PARAMETER;
231 if (!(fsp->access_mask & SEC_DIR_LIST)) {
232 DBG_INFO("dptr_create: directory %s "
233 "not open for LIST access\n",
235 return NT_STATUS_ACCESS_DENIED;
237 status = OpenDir_fsp(NULL, conn, fsp, wcard, attr, &dir_hnd);
238 if (!NT_STATUS_IS_OK(status)) {
242 dptr = talloc_zero(NULL, struct dptr_struct);
244 DEBUG(0,("talloc fail in dptr_create.\n"));
245 TALLOC_FREE(dir_hnd);
246 return NT_STATUS_NO_MEMORY;
250 dptr->dir_hnd = dir_hnd;
251 dptr->wcard = talloc_strdup(dptr, wcard);
254 TALLOC_FREE(dir_hnd);
255 return NT_STATUS_NO_MEMORY;
257 if ((req != NULL && req->posix_pathnames) || ISDOT(wcard)) {
258 dptr->has_wild = True;
260 dptr->has_wild = ms_has_wild(dptr->wcard);
265 if (sconn->using_smb2) {
272 * This is an old-style SMBsearch request. Ensure the
273 * value we return will fit in the range 1-255.
276 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 0);
278 if(dptr->dnum == -1 || dptr->dnum > 254) {
279 DBG_ERR("returned %d: Error - all old "
280 "dirptrs in use ?\n",
283 TALLOC_FREE(dir_hnd);
284 return NT_STATUS_TOO_MANY_OPENED_FILES;
289 * This is a new-style trans2 request. Allocate from
290 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
293 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 255);
295 if(dptr->dnum == -1 || dptr->dnum < 255) {
296 DBG_ERR("returned %d: Error - all new "
297 "dirptrs in use ?\n",
300 TALLOC_FREE(dir_hnd);
301 return NT_STATUS_TOO_MANY_OPENED_FILES;
305 bitmap_set(sconn->searches.dptr_bmap, dptr->dnum);
307 dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
309 DLIST_ADD(sconn->searches.dirptrs, dptr);
312 DBG_INFO("creating new dirptr [%d] for path [%s]\n",
313 dptr->dnum, fsp_str_dbg(fsp));
321 /****************************************************************************
322 Wrapper functions to access the lower level directory handles.
323 ****************************************************************************/
325 void dptr_CloseDir(files_struct *fsp)
327 struct smbd_server_connection *sconn = NULL;
329 if (fsp->dptr == NULL) {
332 sconn = fsp->dptr->conn->sconn;
335 * The destructor for the struct smb_Dir (fsp->dptr->dir_hnd)
336 * now handles all resource deallocation.
339 DBG_INFO("closing dptr key %d\n", fsp->dptr->dnum);
341 if (sconn != NULL && !sconn->using_smb2) {
342 DLIST_REMOVE(sconn->searches.dirptrs, fsp->dptr);
345 * Free the dnum in the bitmap. Remember the dnum value is
346 * always biased by one with respect to the bitmap.
349 if (!bitmap_query(sconn->searches.dptr_bmap,
350 fsp->dptr->dnum - 1))
352 DBG_ERR("closing dnum = %d and bitmap not set !\n",
356 bitmap_clear(sconn->searches.dptr_bmap, fsp->dptr->dnum - 1);
359 TALLOC_FREE(fsp->dptr->dir_hnd);
360 TALLOC_FREE(fsp->dptr);
363 void dptr_SeekDir(struct dptr_struct *dptr, long offset)
365 SeekDir(dptr->dir_hnd, offset);
368 long dptr_TellDir(struct dptr_struct *dptr)
370 return TellDir(dptr->dir_hnd);
373 bool dptr_has_wild(struct dptr_struct *dptr)
375 return dptr->has_wild;
378 int dptr_dnum(struct dptr_struct *dptr)
383 bool dptr_get_priv(struct dptr_struct *dptr)
388 void dptr_set_priv(struct dptr_struct *dptr)
393 bool dptr_case_sensitive(struct dptr_struct *dptr)
395 return dptr->dir_hnd->case_sensitive;
398 /****************************************************************************
399 Return the next visible file name, skipping veto'd and invisible files.
400 ****************************************************************************/
402 static char *dptr_ReadDirName(TALLOC_CTX *ctx,
403 struct dptr_struct *dptr,
405 SMB_STRUCT_STAT *pst)
407 struct smb_filename smb_fname_base;
409 const char *name_temp = NULL;
410 char *talloced = NULL;
411 char *pathreal = NULL;
412 char *found_name = NULL;
415 SET_STAT_INVALID(*pst);
417 if (dptr->has_wild || dptr->did_stat) {
418 name_temp = ReadDirName(dptr->dir_hnd, poffset, pst,
420 if (name_temp == NULL) {
423 if (talloced != NULL) {
424 return talloc_move(ctx, &talloced);
426 return talloc_strdup(ctx, name_temp);
429 /* If poffset is -1 then we know we returned this name before and we
430 * have no wildcards. We're at the end of the directory. */
431 if (*poffset == END_OF_DIRECTORY_OFFSET) {
435 /* We know the stored wcard contains no wildcard characters.
436 * See if we can match with a stat call. If we can't, then set
437 * did_stat to true to ensure we only do this once and keep
440 dptr->did_stat = true;
442 if (VALID_STAT(*pst)) {
443 name = talloc_strdup(ctx, dptr->wcard);
447 pathreal = talloc_asprintf(ctx,
449 dptr->dir_hnd->dir_smb_fname->base_name,
454 /* Create an smb_filename with stream_name == NULL. */
455 smb_fname_base = (struct smb_filename) {
456 .base_name = pathreal,
457 .flags = dptr->dir_hnd->fsp->fsp_name->flags,
458 .twrp = dptr->dir_hnd->fsp->fsp_name->twrp,
461 if (vfs_stat(dptr->conn, &smb_fname_base) == 0) {
462 *pst = smb_fname_base.st;
463 name = talloc_strdup(ctx, dptr->wcard);
466 /* If we get any other error than ENOENT or ENOTDIR
467 then the file exists we just can't stat it. */
468 if (errno != ENOENT && errno != ENOTDIR) {
469 name = talloc_strdup(ctx, dptr->wcard);
474 /* Stat failed. We know this is authoritative if we are
475 * providing case sensitive semantics or the underlying
476 * filesystem is case sensitive.
478 if (dptr->dir_hnd->case_sensitive ||
479 !(dptr->conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH))
485 * Try case-insensitive stat if the fs has the ability. This avoids
486 * scanning the whole directory.
488 status = SMB_VFS_GET_REAL_FILENAME_AT(dptr->conn,
493 if (NT_STATUS_IS_OK(status)) {
497 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
498 /* The case-insensitive lookup was authoritative. */
502 TALLOC_FREE(pathreal);
504 name_temp = ReadDirName(dptr->dir_hnd, poffset, pst, &talloced);
505 if (name_temp == NULL) {
508 if (talloced != NULL) {
509 return talloc_move(ctx, &talloced);
511 return talloc_strdup(ctx, name_temp);
514 TALLOC_FREE(pathreal);
516 /* We need to set the underlying dir_hnd offset to -1
517 * also as this function is usually called with the
518 * output from TellDir. */
519 dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
523 /****************************************************************************
524 Search for a file by name.
525 ****************************************************************************/
527 bool dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
529 SET_STAT_INVALID(*pst);
531 if (!dptr->has_wild && (dptr->dir_hnd->offset == END_OF_DIRECTORY_OFFSET)) {
532 /* This is a singleton directory and we're already at the end. */
533 *poffset = END_OF_DIRECTORY_OFFSET;
537 return SearchDir(dptr->dir_hnd, name, poffset);
540 /****************************************************************************
541 Map a native directory offset to a 32-bit cookie.
542 ****************************************************************************/
544 static uint32_t map_dir_offset_to_wire(struct dptr_struct *dptr, long offset)
549 if (offset == END_OF_DIRECTORY_OFFSET) {
550 return WIRE_END_OF_DIRECTORY_OFFSET;
552 if (offset == START_OF_DIRECTORY_OFFSET) {
553 return WIRE_START_OF_DIRECTORY_OFFSET;
555 if (offset == DOT_DOT_DIRECTORY_OFFSET) {
556 return WIRE_DOT_DOT_DIRECTORY_OFFSET;
558 if (sizeof(long) == 4) {
559 /* 32-bit machine. We can cheat... */
560 return (uint32_t)offset;
562 if (dptr->dptr_cache == NULL) {
563 /* Lazy initialize cache. */
564 dptr->dptr_cache = memcache_init(dptr, 0);
565 if (dptr->dptr_cache == NULL) {
566 return WIRE_END_OF_DIRECTORY_OFFSET;
569 /* Have we seen this offset before ? */
570 key.data = (void *)&offset;
571 key.length = sizeof(offset);
572 if (memcache_lookup(dptr->dptr_cache,
573 SMB1_SEARCH_OFFSET_MAP,
576 uint32_t wire_offset;
577 SMB_ASSERT(val.length == sizeof(wire_offset));
578 memcpy(&wire_offset, val.data, sizeof(wire_offset));
579 DEBUG(10,("found wire %u <-> offset %ld\n",
580 (unsigned int)wire_offset,
585 /* Allocate a new wire cookie. */
588 } while (dptr->counter == WIRE_START_OF_DIRECTORY_OFFSET ||
589 dptr->counter == WIRE_END_OF_DIRECTORY_OFFSET ||
590 dptr->counter == WIRE_DOT_DOT_DIRECTORY_OFFSET);
591 /* Store it in the cache. */
592 key.data = (void *)&offset;
593 key.length = sizeof(offset);
594 val.data = (void *)&dptr->counter;
595 val.length = sizeof(dptr->counter); /* MUST BE uint32_t ! */
596 memcache_add(dptr->dptr_cache,
597 SMB1_SEARCH_OFFSET_MAP,
600 /* And the reverse mapping for lookup from
601 map_wire_to_dir_offset(). */
602 memcache_add(dptr->dptr_cache,
603 SMB1_SEARCH_OFFSET_MAP,
606 DEBUG(10,("stored wire %u <-> offset %ld\n",
607 (unsigned int)dptr->counter,
609 return dptr->counter;
612 /****************************************************************************
613 Fill the 5 byte server reserved dptr field.
614 ****************************************************************************/
616 bool dptr_fill(struct smbd_server_connection *sconn,
617 char *buf1,unsigned int key)
619 unsigned char *buf = (unsigned char *)buf1;
620 struct dptr_struct *dptr = dptr_get(sconn, key);
621 uint32_t wire_offset;
623 DEBUG(1,("filling null dirptr %d\n",key));
626 wire_offset = map_dir_offset_to_wire(dptr,TellDir(dptr->dir_hnd));
627 DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
628 (long)dptr->dir_hnd,(int)wire_offset));
630 SIVAL(buf,1,wire_offset);
634 /****************************************************************************
635 Map a 32-bit wire cookie to a native directory offset.
636 ****************************************************************************/
638 static long map_wire_to_dir_offset(struct dptr_struct *dptr, uint32_t wire_offset)
643 if (wire_offset == WIRE_END_OF_DIRECTORY_OFFSET) {
644 return END_OF_DIRECTORY_OFFSET;
645 } else if(wire_offset == WIRE_START_OF_DIRECTORY_OFFSET) {
646 return START_OF_DIRECTORY_OFFSET;
647 } else if (wire_offset == WIRE_DOT_DOT_DIRECTORY_OFFSET) {
648 return DOT_DOT_DIRECTORY_OFFSET;
650 if (sizeof(long) == 4) {
651 /* 32-bit machine. We can cheat... */
652 return (long)wire_offset;
654 if (dptr->dptr_cache == NULL) {
655 /* Logic error, cache should be initialized. */
656 return END_OF_DIRECTORY_OFFSET;
658 key.data = (void *)&wire_offset;
659 key.length = sizeof(wire_offset);
660 if (memcache_lookup(dptr->dptr_cache,
661 SMB1_SEARCH_OFFSET_MAP,
666 SMB_ASSERT(val.length == sizeof(offset));
667 memcpy(&offset, val.data, sizeof(offset));
668 DEBUG(10,("lookup wire %u <-> offset %ld\n",
669 (unsigned int)wire_offset,
673 return END_OF_DIRECTORY_OFFSET;
676 /****************************************************************************
677 Return the associated fsp and seek the dir_hnd on it it given the 5 byte
679 ****************************************************************************/
681 files_struct *dptr_fetch_fsp(struct smbd_server_connection *sconn,
684 unsigned int key = *(unsigned char *)buf;
685 struct dptr_struct *dptr = dptr_get(sconn, key);
686 uint32_t wire_offset;
690 DEBUG(3,("fetched null dirptr %d\n",key));
694 wire_offset = IVAL(buf,1);
695 seekoff = map_wire_to_dir_offset(dptr, wire_offset);
696 SeekDir(dptr->dir_hnd,seekoff);
697 DBG_NOTICE("fetching dirptr %d for path %s at offset %ld\n",
699 dptr->dir_hnd->dir_smb_fname->base_name,
701 return dptr->dir_hnd->fsp;
704 struct files_struct *dir_hnd_fetch_fsp(struct smb_Dir *dir_hnd)
709 /****************************************************************************
710 Fetch the fsp associated with the dptr_num.
711 ****************************************************************************/
713 files_struct *dptr_fetch_lanman2_fsp(struct smbd_server_connection *sconn,
716 struct dptr_struct *dptr = dptr_get(sconn, dptr_num);
720 DBG_NOTICE("fetching dirptr %d for path %s\n",
722 dptr->dir_hnd->dir_smb_fname->base_name);
723 return dptr->dir_hnd->fsp;
726 static bool mangle_mask_match(connection_struct *conn,
727 const char *filename,
732 if (!name_to_8_3(filename,mname,False,conn->params)) {
735 return mask_match_search(mname,mask,False);
738 bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
739 struct dptr_struct *dirptr,
745 bool (*match_fn)(TALLOC_CTX *ctx,
750 bool (*mode_fn)(TALLOC_CTX *ctx,
752 struct files_struct *dirfsp,
753 struct smb_filename *atname,
754 struct smb_filename *smb_fname,
759 struct smb_filename **_smb_fname,
763 connection_struct *conn = dirptr->conn;
766 const char *dpath = dirptr->dir_hnd->dir_smb_fname->base_name;
767 bool dirptr_path_is_dot = ISDOT(dpath);
774 pathlen = strlen(dpath);
775 slashlen = ( dpath[pathlen-1] != '/') ? 1 : 0;
780 SMB_STRUCT_STAT sbuf = { 0 };
784 char *pathreal = NULL;
785 struct smb_filename *atname = NULL;
786 struct smb_filename *smb_fname = NULL;
788 bool check_dfs_symlink = false;
789 bool get_dosmode = get_dosmode_in;
792 cur_offset = dptr_TellDir(dirptr);
793 prev_offset = cur_offset;
794 dname = dptr_ReadDirName(ctx, dirptr, &cur_offset, &sbuf);
796 DBG_DEBUG("dir [%s] dirptr [0x%lx] offset [%ld] => dname [%s]\n",
797 smb_fname_str_dbg(dirptr->dir_hnd->dir_smb_fname),
799 cur_offset, dname ? dname : "(finished)");
805 isdots = (ISDOT(dname) || ISDOTDOT(dname));
806 if (dont_descend && !isdots) {
811 if (IS_VETO_PATH(conn, dname)) {
817 * fname may get mangled, dname is never mangled.
818 * Whenever we're accessing the filesystem we use
819 * pathreal which is composed from dname.
822 ok = match_fn(ctx, private_data, dname, mask, &fname);
830 * pathreal = talloc_asprintf(ctx, "%s%s%s", dirptr->path,
831 * needslash?"/":"", dname);
832 * but this was measurably slower than doing the memcpy.
835 pathreal = talloc_array(
837 pathlen + slashlen + talloc_get_size(dname));
845 * We don't want to pass ./xxx to modules below us so don't
846 * add the path if it is just . by itself.
848 if (dirptr_path_is_dot) {
849 memcpy(pathreal, dname, talloc_get_size(dname));
851 memcpy(pathreal, dpath, pathlen);
852 pathreal[pathlen] = '/';
853 memcpy(pathreal + slashlen + pathlen, dname,
854 talloc_get_size(dname));
857 /* Create smb_fname with NULL stream_name. */
858 smb_fname = synthetic_smb_fname(
863 dirptr->dir_hnd->dir_smb_fname->twrp,
864 dirptr->dir_hnd->dir_smb_fname->flags);
865 TALLOC_FREE(pathreal);
866 if (smb_fname == NULL) {
872 if (!VALID_STAT(smb_fname->st)) {
874 * If stat() fails with ENOENT it might be a
875 * msdfs-symlink in Windows context, this is checked
876 * below, for now we just want to fill stat info as good
879 ret = vfs_stat(conn, smb_fname);
880 if (ret != 0 && errno != ENOENT) {
881 TALLOC_FREE(smb_fname);
888 /* Create smb_fname with NULL stream_name. */
889 atname = synthetic_smb_fname(
894 dirptr->dir_hnd->dir_smb_fname->twrp,
895 dirptr->dir_hnd->dir_smb_fname->flags);
896 if (atname == NULL) {
899 TALLOC_FREE(smb_fname);
904 * openat_pathref_fsp() will return
905 * NT_STATUS_OBJECT_NAME_NOT_FOUND in non-POSIX context when
906 * hitting a dangling symlink. It may be a DFS symlink, this is
907 * checked below by the mode_fn() call, so we have to allow this
910 * NT_STATUS_STOPPED_ON_SYMLINK is returned in POSIX context
911 * when hitting a symlink and ensures we always return directory
912 * entries that are symlinks in POSIX context.
914 status = openat_pathref_fsp(dirptr->dir_hnd->fsp, atname);
915 if (!NT_STATUS_IS_OK(status) &&
916 !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND))
921 TALLOC_FREE(smb_fname);
925 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
926 if (!(atname->flags & SMB_FILENAME_POSIX_PATH)) {
927 check_dfs_symlink = true;
930 * Check if it's a symlink. We only want to return this
931 * if it's a DFS symlink or in POSIX mode. Disable
932 * getting dosmode in the mode_fn() and prime the mode
933 * as FILE_ATTRIBUTE_NORMAL.
935 mode = FILE_ATTRIBUTE_NORMAL;
939 status = move_smb_fname_fsp_link(smb_fname, atname);
940 if (!NT_STATUS_IS_OK(status)) {
941 DBG_WARNING("Failed to move pathref for [%s]: %s\n",
942 smb_fname_str_dbg(smb_fname),
945 TALLOC_FREE(smb_fname);
951 if (!is_visible_fsp(smb_fname->fsp)) {
953 TALLOC_FREE(smb_fname);
960 * Don't leak metadata about the containing
961 * directory of the share.
963 if (dirptr_path_is_dot && ISDOTDOT(dname)) {
965 * Making a copy here, then freeing
966 * the original will close the smb_fname->fsp.
968 struct smb_filename *tmp_smb_fname =
969 cp_smb_filename(ctx, smb_fname);
971 if (tmp_smb_fname == NULL) {
973 TALLOC_FREE(smb_fname);
978 TALLOC_FREE(smb_fname);
979 smb_fname = tmp_smb_fname;
980 mode = FILE_ATTRIBUTE_DIRECTORY;
983 /* Ensure posix fileid and sids are hidden
985 smb_fname->st.st_ex_ino = 0;
986 smb_fname->st.st_ex_dev = 0;
987 smb_fname->st.st_ex_uid = -1;
988 smb_fname->st.st_ex_gid = -1;
993 dirptr->dir_hnd->fsp,
1000 TALLOC_FREE(smb_fname);
1006 TALLOC_FREE(atname);
1009 * The only valid cases where we return the directory entry if
1010 * it's a symlink are:
1012 * 1. POSIX context, always return it, or
1014 * 2. a DFS symlink where the mode_fn() call above has verified
1015 * this and set mode to FILE_ATTRIBUTE_REPARSE_POINT.
1017 if (check_dfs_symlink &&
1018 !(mode & FILE_ATTRIBUTE_REPARSE_POINT))
1020 TALLOC_FREE(smb_fname);
1026 if (!dir_check_ftype(mode, dirtype)) {
1027 DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",
1028 fname, (unsigned int)mode, (unsigned int)dirtype));
1029 TALLOC_FREE(smb_fname);
1035 if (ask_sharemode && !S_ISDIR(smb_fname->st.st_ex_mode)) {
1036 struct timespec write_time_ts;
1037 struct file_id fileid;
1039 fileid = vfs_file_id_from_sbuf(conn,
1041 get_file_infos(fileid, 0, NULL, &write_time_ts);
1042 if (!is_omit_timespec(&write_time_ts)) {
1043 update_stat_ex_mtime(&smb_fname->st,
1048 DEBUG(3,("smbd_dirptr_get_entry mask=[%s] found %s "
1050 mask, smb_fname_str_dbg(smb_fname),
1053 if (!conn->sconn->using_smb2) {
1055 * The dircache is only needed for SMB1 because SMB1
1056 * uses a name for the resume wheras SMB2 always
1057 * continues from the next position (unless it's told to
1058 * restart or close-and-reopen the listing).
1060 DirCacheAdd(dirptr->dir_hnd, dname, cur_offset);
1065 *_smb_fname = talloc_move(ctx, &smb_fname);
1066 if (*_smb_fname == NULL) {
1071 *_prev_offset = prev_offset;
1079 /****************************************************************************
1080 Get an 8.3 directory entry.
1081 ****************************************************************************/
1083 static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX *ctx,
1089 connection_struct *conn = (connection_struct *)private_data;
1091 if ((strcmp(mask,"*.*") == 0) ||
1092 mask_match_search(dname, mask, false) ||
1093 mangle_mask_match(conn, dname, mask)) {
1097 * Ensure we can push the original name as UCS2. If
1098 * not, then just don't return this name.
1102 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1103 uint8_t *tmp = talloc_array(talloc_tos(),
1107 status = srvstr_push(NULL,
1108 FLAGS2_UNICODE_STRINGS,
1117 if (!NT_STATUS_IS_OK(status)) {
1121 if (!mangle_is_8_3(dname, false, conn->params)) {
1122 bool ok = name_to_8_3(dname, mname, false,
1132 *_fname = talloc_strdup(ctx, fname);
1133 if (*_fname == NULL) {
1143 static bool smbd_dirptr_8_3_mode_fn(TALLOC_CTX *ctx,
1145 struct files_struct *dirfsp,
1146 struct smb_filename *atname,
1147 struct smb_filename *smb_fname,
1151 connection_struct *conn = (connection_struct *)private_data;
1153 if (!VALID_STAT(smb_fname->st)) {
1154 if ((SMB_VFS_STAT(conn, smb_fname)) != 0) {
1155 DEBUG(5,("smbd_dirptr_8_3_mode_fn: "
1156 "Couldn't stat [%s]. Error "
1158 smb_fname_str_dbg(smb_fname),
1165 *_mode = fdos_mode(smb_fname->fsp);
1166 smb_fname->st = smb_fname->fsp->fsp_name->st;
1171 bool get_dir_entry(TALLOC_CTX *ctx,
1172 struct dptr_struct *dirptr,
1178 struct timespec *_date,
1182 connection_struct *conn = dirptr->conn;
1184 struct smb_filename *smb_fname = NULL;
1189 ok = smbd_dirptr_get_entry(ctx,
1196 smbd_dirptr_8_3_match_fn,
1197 smbd_dirptr_8_3_mode_fn,
1207 *_fname = talloc_move(ctx, &fname);
1208 *_size = smb_fname->st.st_ex_size;
1210 *_date = smb_fname->st.st_ex_mtime;
1211 TALLOC_FREE(smb_fname);
1215 /*******************************************************************
1216 Check to see if a user can read an fsp . This is only approximate,
1217 it is used as part of the "hide unreadable" option. Don't
1218 use it for anything security sensitive.
1219 ********************************************************************/
1221 static bool user_can_read_fsp(struct files_struct *fsp)
1224 uint32_t rejected_share_access = 0;
1225 uint32_t rejected_mask = 0;
1226 struct security_descriptor *sd = NULL;
1227 uint32_t access_mask = FILE_READ_DATA|
1229 FILE_READ_ATTRIBUTES|
1230 SEC_STD_READ_CONTROL;
1233 * Never hide files from the root user.
1234 * We use (uid_t)0 here not sec_initial_uid()
1235 * as make test uses a single user context.
1238 if (get_current_uid(fsp->conn) == (uid_t)0) {
1243 * We can't directly use smbd_check_access_rights_fsp()
1244 * here, as this implicitly grants FILE_READ_ATTRIBUTES
1245 * which the Windows access-based-enumeration code
1246 * explicitly checks for on the file security descriptor.
1249 * https://bugzilla.samba.org/show_bug.cgi?id=10252
1251 * and the smb2.acl2.ACCESSBASED test for details.
1254 rejected_share_access = access_mask & ~(fsp->conn->share_access);
1255 if (rejected_share_access) {
1256 DBG_DEBUG("rejected share access 0x%x "
1258 (unsigned int)access_mask,
1260 (unsigned int)rejected_share_access);
1264 status = SMB_VFS_FGET_NT_ACL(metadata_fsp(fsp),
1271 if (!NT_STATUS_IS_OK(status)) {
1272 DBG_DEBUG("Could not get acl "
1279 status = se_file_access_check(sd,
1280 get_current_nttok(fsp->conn),
1287 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1288 DBG_DEBUG("rejected bits 0x%x read access for %s\n",
1289 (unsigned int)rejected_mask,
1296 /*******************************************************************
1297 Check to see if a user can write to an fsp.
1298 Always return true for directories.
1299 This is only approximate,
1300 it is used as part of the "hide unwriteable" option. Don't
1301 use it for anything security sensitive.
1302 ********************************************************************/
1304 static bool user_can_write_fsp(struct files_struct *fsp)
1307 * Never hide files from the root user.
1308 * We use (uid_t)0 here not sec_initial_uid()
1309 * as make test uses a single user context.
1312 if (get_current_uid(fsp->conn) == (uid_t)0) {
1316 if (fsp->fsp_flags.is_directory) {
1320 return can_write_to_fsp(fsp);
1323 /*******************************************************************
1324 Is a file a "special" type ?
1325 ********************************************************************/
1327 static bool file_is_special(connection_struct *conn,
1328 const struct smb_filename *smb_fname)
1331 * Never hide files from the root user.
1332 * We use (uid_t)0 here not sec_initial_uid()
1333 * as make test uses a single user context.
1336 if (get_current_uid(conn) == (uid_t)0) {
1340 SMB_ASSERT(VALID_STAT(smb_fname->st));
1342 if (S_ISREG(smb_fname->st.st_ex_mode) ||
1343 S_ISDIR(smb_fname->st.st_ex_mode) ||
1344 S_ISLNK(smb_fname->st.st_ex_mode))
1350 /*******************************************************************
1351 Should the file be seen by the client?
1352 ********************************************************************/
1354 bool is_visible_fsp(struct files_struct *fsp)
1356 bool hide_unreadable = false;
1357 bool hide_unwriteable = false;
1358 bool hide_special = false;
1359 int hide_new_files_timeout = 0;
1360 const char *last_component = NULL;
1363 * If the file does not exist, there's no point checking
1364 * the configuration options. We succeed, on the basis that the
1365 * checks *might* have passed if the file was present.
1371 hide_unreadable = lp_hide_unreadable(SNUM(fsp->conn));
1372 hide_unwriteable = lp_hide_unwriteable_files(SNUM(fsp->conn));
1373 hide_special = lp_hide_special_files(SNUM(fsp->conn));
1374 hide_new_files_timeout = lp_hide_new_files_timeout(SNUM(fsp->conn));
1376 if (!hide_unreadable &&
1377 !hide_unwriteable &&
1379 (hide_new_files_timeout == 0))
1384 fsp = metadata_fsp(fsp);
1386 /* Get the last component of the base name. */
1387 last_component = strrchr_m(fsp->fsp_name->base_name, '/');
1388 if (!last_component) {
1389 last_component = fsp->fsp_name->base_name;
1391 last_component++; /* Go past '/' */
1394 if (ISDOT(last_component) || ISDOTDOT(last_component)) {
1395 return true; /* . and .. are always visible. */
1398 if (fsp_get_pathref_fd(fsp) == -1) {
1400 * Symlink in POSIX mode or MS-DFS.
1401 * We've checked veto files so the
1402 * only thing we can check is the
1403 * hide_new_files_timeout.
1405 if ((hide_new_files_timeout != 0) &&
1406 !S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
1407 double age = timespec_elapsed(
1408 &fsp->fsp_name->st.st_ex_mtime);
1410 if (age < (double)hide_new_files_timeout) {
1417 /* Honour _hide unreadable_ option */
1418 if (hide_unreadable && !user_can_read_fsp(fsp)) {
1419 DBG_DEBUG("file %s is unreadable.\n", fsp_str_dbg(fsp));
1423 /* Honour _hide unwriteable_ option */
1424 if (hide_unwriteable && !user_can_write_fsp(fsp)) {
1425 DBG_DEBUG("file %s is unwritable.\n", fsp_str_dbg(fsp));
1429 /* Honour _hide_special_ option */
1430 if (hide_special && file_is_special(fsp->conn, fsp->fsp_name)) {
1431 DBG_DEBUG("file %s is special.\n", fsp_str_dbg(fsp));
1435 if ((hide_new_files_timeout != 0) &&
1436 !S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
1437 double age = timespec_elapsed(&fsp->fsp_name->st.st_ex_mtime);
1439 if (age < (double)hide_new_files_timeout) {
1447 static int smb_Dir_destructor(struct smb_Dir *dir_hnd)
1449 files_struct *fsp = dir_hnd->fsp;
1451 SMB_VFS_CLOSEDIR(dir_hnd->conn, dir_hnd->dir);
1452 fsp_set_fd(fsp, -1);
1453 if (fsp->dptr != NULL) {
1454 SMB_ASSERT(fsp->dptr->dir_hnd == dir_hnd);
1455 fsp->dptr->dir_hnd = NULL;
1457 dir_hnd->fsp = NULL;
1461 /*******************************************************************
1463 ********************************************************************/
1465 static int smb_Dir_OpenDir_destructor(struct smb_Dir *dir_hnd)
1467 files_struct *fsp = dir_hnd->fsp;
1469 smb_Dir_destructor(dir_hnd);
1470 file_free(NULL, fsp);
1474 NTSTATUS OpenDir(TALLOC_CTX *mem_ctx,
1475 connection_struct *conn,
1476 const struct smb_filename *smb_dname,
1479 struct smb_Dir **_dir_hnd)
1481 struct files_struct *fsp = NULL;
1482 struct smb_Dir *dir_hnd = NULL;
1485 status = open_internal_dirfsp(conn,
1489 if (!NT_STATUS_IS_OK(status)) {
1493 status = OpenDir_fsp(mem_ctx, conn, fsp, mask, attr, &dir_hnd);
1494 if (!NT_STATUS_IS_OK(status)) {
1499 * This overwrites the destructor set by OpenDir_fsp() but
1500 * smb_Dir_OpenDir_destructor() calls the OpenDir_fsp()
1503 talloc_set_destructor(dir_hnd, smb_Dir_OpenDir_destructor);
1505 *_dir_hnd = dir_hnd;
1506 return NT_STATUS_OK;
1509 NTSTATUS OpenDir_from_pathref(TALLOC_CTX *mem_ctx,
1510 struct files_struct *dirfsp,
1513 struct smb_Dir **_dir_hnd)
1515 struct files_struct *fsp = NULL;
1516 struct smb_Dir *dir_hnd = NULL;
1519 status = openat_internal_dir_from_pathref(dirfsp, O_RDONLY, &fsp);
1520 if (!NT_STATUS_IS_OK(status)) {
1524 status = OpenDir_fsp(mem_ctx, fsp->conn, fsp, mask, attr, &dir_hnd);
1525 if (!NT_STATUS_IS_OK(status)) {
1530 * This overwrites the destructor set by OpenDir_fsp() but
1531 * smb_Dir_OpenDir_destructor() calls the OpenDir_fsp()
1534 talloc_set_destructor(dir_hnd, smb_Dir_OpenDir_destructor);
1536 *_dir_hnd = dir_hnd;
1537 return NT_STATUS_OK;
1540 /*******************************************************************
1541 Open a directory from an fsp.
1542 ********************************************************************/
1544 static NTSTATUS OpenDir_fsp(
1545 TALLOC_CTX *mem_ctx,
1546 connection_struct *conn,
1550 struct smb_Dir **_dir_hnd)
1552 struct smb_Dir *dir_hnd = talloc_zero(mem_ctx, struct smb_Dir);
1556 return NT_STATUS_NO_MEMORY;
1559 if (!fsp->fsp_flags.is_directory) {
1560 status = NT_STATUS_INVALID_HANDLE;
1564 if (fsp_get_io_fd(fsp) == -1) {
1565 status = NT_STATUS_INVALID_HANDLE;
1569 dir_hnd->conn = conn;
1571 if (!conn->sconn->using_smb2) {
1573 * The dircache is only needed for SMB1 because SMB1 uses a name
1574 * for the resume wheras SMB2 always continues from the next
1575 * position (unless it's told to restart or close-and-reopen the
1578 dir_hnd->name_cache_size =
1579 lp_directory_name_cache_size(SNUM(conn));
1582 dir_hnd->dir_smb_fname = cp_smb_filename(dir_hnd, fsp->fsp_name);
1583 if (!dir_hnd->dir_smb_fname) {
1584 status = NT_STATUS_NO_MEMORY;
1588 dir_hnd->dir = SMB_VFS_FDOPENDIR(fsp, mask, attr);
1589 if (dir_hnd->dir == NULL) {
1590 status = map_nt_error_from_unix(errno);
1594 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1595 dir_hnd->case_sensitive = true;
1597 dir_hnd->case_sensitive = conn->case_sensitive;
1600 talloc_set_destructor(dir_hnd, smb_Dir_destructor);
1602 *_dir_hnd = dir_hnd;
1603 return NT_STATUS_OK;
1606 TALLOC_FREE(dir_hnd);
1611 /*******************************************************************
1612 Read from a directory.
1613 Return directory entry, current offset, and optional stat information.
1614 Don't check for veto or invisible files.
1615 ********************************************************************/
1617 const char *ReadDirName(struct smb_Dir *dir_hnd, long *poffset,
1618 SMB_STRUCT_STAT *sbuf, char **ptalloced)
1621 char *talloced = NULL;
1622 connection_struct *conn = dir_hnd->conn;
1624 /* Cheat to allow . and .. to be the first entries returned. */
1625 if (((*poffset == START_OF_DIRECTORY_OFFSET) ||
1626 (*poffset == DOT_DOT_DIRECTORY_OFFSET)) &&
1627 (dir_hnd->file_number < 2))
1629 if (dir_hnd->file_number == 0) {
1631 *poffset = dir_hnd->offset = START_OF_DIRECTORY_OFFSET;
1634 *poffset = dir_hnd->offset = DOT_DOT_DIRECTORY_OFFSET;
1636 dir_hnd->file_number++;
1641 if (*poffset == END_OF_DIRECTORY_OFFSET) {
1642 *poffset = dir_hnd->offset = END_OF_DIRECTORY_OFFSET;
1646 /* A real offset, seek to it. */
1647 SeekDir(dir_hnd, *poffset);
1649 while ((n = vfs_readdirname(conn, dir_hnd->fsp, dir_hnd->dir, sbuf, &talloced))) {
1650 /* Ignore . and .. - we've already returned them. */
1651 if (ISDOT(n) || ISDOTDOT(n)) {
1652 TALLOC_FREE(talloced);
1655 *poffset = dir_hnd->offset = SMB_VFS_TELLDIR(conn, dir_hnd->dir);
1656 *ptalloced = talloced;
1657 dir_hnd->file_number++;
1660 *poffset = dir_hnd->offset = END_OF_DIRECTORY_OFFSET;
1665 /*******************************************************************
1666 Rewind to the start.
1667 ********************************************************************/
1669 void RewindDir(struct smb_Dir *dir_hnd, long *poffset)
1671 SMB_VFS_REWINDDIR(dir_hnd->conn, dir_hnd->dir);
1672 dir_hnd->file_number = 0;
1673 dir_hnd->offset = START_OF_DIRECTORY_OFFSET;
1674 *poffset = START_OF_DIRECTORY_OFFSET;
1677 /*******************************************************************
1679 ********************************************************************/
1681 void SeekDir(struct smb_Dir *dirp, long offset)
1683 if (offset == dirp->offset) {
1690 if (offset == START_OF_DIRECTORY_OFFSET) {
1691 RewindDir(dirp, &offset);
1693 * Ok we should really set the file number here
1694 * to 1 to enable ".." to be returned next. Trouble
1695 * is I'm worried about callers using SeekDir(dirp,0)
1696 * as equivalent to RewindDir(). So leave this alone
1699 } else if (offset == DOT_DOT_DIRECTORY_OFFSET) {
1700 RewindDir(dirp, &offset);
1702 * Set the file number to 2 - we want to get the first
1703 * real file entry (the one we return after "..")
1704 * on the next ReadDir.
1706 dirp->file_number = 2;
1707 } else if (offset == END_OF_DIRECTORY_OFFSET) {
1708 ; /* Don't seek in this case. */
1710 SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1712 dirp->offset = offset;
1715 /*******************************************************************
1716 Tell a dir position.
1717 ********************************************************************/
1719 long TellDir(struct smb_Dir *dir_hnd)
1721 return(dir_hnd->offset);
1724 /*******************************************************************
1725 Add an entry into the dcache.
1726 ********************************************************************/
1728 static void DirCacheAdd(struct smb_Dir *dir_hnd, const char *name, long offset)
1730 struct name_cache_entry *e;
1732 if (dir_hnd->name_cache_size == 0) {
1736 if (dir_hnd->name_cache == NULL) {
1737 dir_hnd->name_cache = talloc_zero_array(dir_hnd,
1738 struct name_cache_entry,
1739 dir_hnd->name_cache_size);
1741 if (dir_hnd->name_cache == NULL) {
1746 dir_hnd->name_cache_index = (dir_hnd->name_cache_index+1) %
1747 dir_hnd->name_cache_size;
1748 e = &dir_hnd->name_cache[dir_hnd->name_cache_index];
1749 TALLOC_FREE(e->name);
1750 e->name = talloc_strdup(dir_hnd, name);
1754 /*******************************************************************
1755 Find an entry by name. Leave us at the offset after it.
1756 Don't check for veto or invisible files.
1757 ********************************************************************/
1759 static bool SearchDir(struct smb_Dir *dir_hnd, const char *name, long *poffset)
1762 const char *entry = NULL;
1763 char *talloced = NULL;
1764 connection_struct *conn = dir_hnd->conn;
1766 /* Search back in the name cache. */
1767 if (dir_hnd->name_cache_size && dir_hnd->name_cache) {
1768 for (i = dir_hnd->name_cache_index; i >= 0; i--) {
1769 struct name_cache_entry *e = &dir_hnd->name_cache[i];
1770 if (e->name && (dir_hnd->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1771 *poffset = e->offset;
1772 SeekDir(dir_hnd, e->offset);
1776 for (i = dir_hnd->name_cache_size - 1;
1777 i > dir_hnd->name_cache_index; i--) {
1778 struct name_cache_entry *e = &dir_hnd->name_cache[i];
1779 if (e->name && (dir_hnd->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1780 *poffset = e->offset;
1781 SeekDir(dir_hnd, e->offset);
1787 /* Not found in the name cache. Rewind directory and start from scratch. */
1788 SMB_VFS_REWINDDIR(conn, dir_hnd->dir);
1789 dir_hnd->file_number = 0;
1790 *poffset = START_OF_DIRECTORY_OFFSET;
1791 while ((entry = ReadDirName(dir_hnd, poffset, NULL, &talloced))) {
1792 if (dir_hnd->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
1793 TALLOC_FREE(talloced);
1796 TALLOC_FREE(talloced);
1801 struct files_below_forall_state {
1803 ssize_t dirpath_len;
1804 int (*fn)(struct file_id fid, const struct share_mode_data *data,
1805 void *private_data);
1809 static int files_below_forall_fn(struct file_id fid,
1810 const struct share_mode_data *data,
1813 struct files_below_forall_state *state = private_data;
1814 char tmpbuf[PATH_MAX];
1815 char *fullpath, *to_free;
1818 len = full_path_tos(data->servicepath, data->base_name,
1819 tmpbuf, sizeof(tmpbuf),
1820 &fullpath, &to_free);
1824 if (state->dirpath_len >= len) {
1826 * Filter files above dirpath
1830 if (fullpath[state->dirpath_len] != '/') {
1832 * Filter file that don't have a path separator at the end of
1838 if (memcmp(state->dirpath, fullpath, state->dirpath_len) != 0) {
1845 TALLOC_FREE(to_free);
1846 return state->fn(fid, data, state->private_data);
1849 TALLOC_FREE(to_free);
1853 static int files_below_forall(connection_struct *conn,
1854 const struct smb_filename *dir_name,
1855 int (*fn)(struct file_id fid,
1856 const struct share_mode_data *data,
1857 void *private_data),
1860 struct files_below_forall_state state = {
1862 .private_data = private_data,
1865 char tmpbuf[PATH_MAX];
1868 state.dirpath_len = full_path_tos(conn->connectpath,
1869 dir_name->base_name,
1870 tmpbuf, sizeof(tmpbuf),
1871 &state.dirpath, &to_free);
1872 if (state.dirpath_len == -1) {
1876 ret = share_mode_forall(files_below_forall_fn, &state);
1877 TALLOC_FREE(to_free);
1881 struct have_file_open_below_state {
1885 static int have_file_open_below_fn(struct file_id fid,
1886 const struct share_mode_data *data,
1889 struct have_file_open_below_state *state = private_data;
1890 state->found_one = true;
1894 bool have_file_open_below(connection_struct *conn,
1895 const struct smb_filename *name)
1897 struct have_file_open_below_state state = {
1902 if (!VALID_STAT(name->st)) {
1905 if (!S_ISDIR(name->st.st_ex_mode)) {
1909 ret = files_below_forall(conn, name, have_file_open_below_fn, &state);
1914 return state.found_one;
1917 /*****************************************************************
1918 Is this directory empty ?
1919 *****************************************************************/
1921 NTSTATUS can_delete_directory_fsp(files_struct *fsp)
1923 NTSTATUS status = NT_STATUS_OK;
1925 const char *dname = NULL;
1926 char *talloced = NULL;
1927 struct connection_struct *conn = fsp->conn;
1928 struct smb_Dir *dir_hnd = NULL;
1931 talloc_tos(), conn, fsp->fsp_name, NULL, 0, &dir_hnd);
1932 if (!NT_STATUS_IS_OK(status)) {
1936 while ((dname = ReadDirName(dir_hnd, &dirpos, NULL, &talloced))) {
1937 struct smb_filename *smb_dname_full = NULL;
1938 struct smb_filename *direntry_fname = NULL;
1939 char *fullname = NULL;
1942 if (ISDOT(dname) || (ISDOTDOT(dname))) {
1943 TALLOC_FREE(talloced);
1946 if (IS_VETO_PATH(conn, dname)) {
1947 TALLOC_FREE(talloced);
1951 fullname = talloc_asprintf(talloc_tos(),
1953 fsp->fsp_name->base_name,
1955 if (fullname == NULL) {
1956 status = NT_STATUS_NO_MEMORY;
1960 smb_dname_full = synthetic_smb_fname(talloc_tos(),
1964 fsp->fsp_name->twrp,
1965 fsp->fsp_name->flags);
1966 if (smb_dname_full == NULL) {
1967 TALLOC_FREE(talloced);
1968 TALLOC_FREE(fullname);
1969 status = NT_STATUS_NO_MEMORY;
1973 ret = SMB_VFS_LSTAT(conn, smb_dname_full);
1975 status = map_nt_error_from_unix(errno);
1976 TALLOC_FREE(talloced);
1977 TALLOC_FREE(fullname);
1978 TALLOC_FREE(smb_dname_full);
1982 if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
1983 /* Could it be an msdfs link ? */
1984 if (lp_host_msdfs() &&
1985 lp_msdfs_root(SNUM(conn))) {
1986 struct smb_filename *smb_dname;
1987 smb_dname = synthetic_smb_fname(talloc_tos(),
1990 &smb_dname_full->st,
1991 fsp->fsp_name->twrp,
1992 fsp->fsp_name->flags);
1993 if (smb_dname == NULL) {
1994 TALLOC_FREE(talloced);
1995 TALLOC_FREE(fullname);
1996 TALLOC_FREE(smb_dname_full);
1997 status = NT_STATUS_NO_MEMORY;
2000 if (is_msdfs_link(fsp, smb_dname)) {
2001 TALLOC_FREE(talloced);
2002 TALLOC_FREE(fullname);
2003 TALLOC_FREE(smb_dname_full);
2004 TALLOC_FREE(smb_dname);
2005 DBG_DEBUG("got msdfs link name %s "
2006 "- can't delete directory %s\n",
2009 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
2012 TALLOC_FREE(smb_dname);
2014 /* Not a DFS link - could it be a dangling symlink ? */
2015 ret = SMB_VFS_STAT(conn, smb_dname_full);
2016 if (ret == -1 && (errno == ENOENT || errno == ELOOP)) {
2019 * Allow if "delete veto files = yes"
2021 if (lp_delete_veto_files(SNUM(conn))) {
2022 TALLOC_FREE(talloced);
2023 TALLOC_FREE(fullname);
2024 TALLOC_FREE(smb_dname_full);
2028 DBG_DEBUG("got symlink name %s - "
2029 "can't delete directory %s\n",
2032 TALLOC_FREE(talloced);
2033 TALLOC_FREE(fullname);
2034 TALLOC_FREE(smb_dname_full);
2035 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
2039 /* Not a symlink, get a pathref. */
2040 status = synthetic_pathref(talloc_tos(),
2044 &smb_dname_full->st,
2045 fsp->fsp_name->twrp,
2046 fsp->fsp_name->flags,
2048 if (!NT_STATUS_IS_OK(status)) {
2049 status = map_nt_error_from_unix(errno);
2050 TALLOC_FREE(talloced);
2051 TALLOC_FREE(fullname);
2052 TALLOC_FREE(smb_dname_full);
2056 if (!is_visible_fsp(direntry_fname->fsp)) {
2059 * Allow if "delete veto files = yes"
2061 if (lp_delete_veto_files(SNUM(conn))) {
2062 TALLOC_FREE(talloced);
2063 TALLOC_FREE(fullname);
2064 TALLOC_FREE(smb_dname_full);
2065 TALLOC_FREE(direntry_fname);
2070 TALLOC_FREE(talloced);
2071 TALLOC_FREE(fullname);
2072 TALLOC_FREE(smb_dname_full);
2073 TALLOC_FREE(direntry_fname);
2075 DBG_DEBUG("got name %s - can't delete\n", dname);
2076 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
2079 TALLOC_FREE(talloced);
2080 TALLOC_FREE(dir_hnd);
2082 if (!NT_STATUS_IS_OK(status)) {
2086 if (!(fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) &&
2087 lp_strict_rename(SNUM(conn)) &&
2088 have_file_open_below(fsp->conn, fsp->fsp_name))
2090 return NT_STATUS_ACCESS_DENIED;
2093 return NT_STATUS_OK;