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"
31 #include "libcli/smb/reparse.h"
32 #include "source3/smbd/dir.h"
33 #include "source3/include/serverid.h"
36 This module implements directory related functions for Samba.
39 /* "Special" directory offsets. */
40 #define END_OF_DIRECTORY_OFFSET ((long)-1)
41 #define START_OF_DIRECTORY_OFFSET ((long)0)
42 #define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000)
44 /* Make directory handle internals available. */
47 connection_struct
*conn
;
49 struct smb_filename
*dir_smb_fname
;
50 unsigned int file_number
;
52 files_struct
*fsp
; /* Back pointer to containing fsp, only
53 set from OpenDir_fsp(). */
57 struct dptr_struct
*next
, *prev
;
59 struct smb_Dir
*dir_hnd
;
62 bool has_wild
; /* Set to true if the wcard entry has MS wildcard characters in it. */
63 bool did_stat
; /* Optimisation for non-wcard searches. */
64 bool priv
; /* Directory handle opened with privilege. */
67 char *last_name_sent
; /* for name-based trans2 resume */
71 struct smb_filename
*smb_fname
;
76 static NTSTATUS
OpenDir_fsp(
78 connection_struct
*conn
,
82 struct smb_Dir
**_dir_hnd
);
84 static int smb_Dir_destructor(struct smb_Dir
*dir_hnd
);
86 #define INVALID_DPTR_KEY (-3)
88 /****************************************************************************
89 Initialise the dir bitmap.
90 ****************************************************************************/
92 bool init_dptrs(struct smbd_server_connection
*sconn
)
94 if (sconn
->searches
.dptr_bmap
) {
98 sconn
->searches
.dptr_bmap
= bitmap_talloc(
99 sconn
, MAX_DIRECTORY_HANDLES
);
101 if (sconn
->searches
.dptr_bmap
== NULL
) {
108 /****************************************************************************
109 Get the struct dptr_struct for a dir index.
110 ****************************************************************************/
112 static struct dptr_struct
*dptr_get(struct smbd_server_connection
*sconn
,
115 struct dptr_struct
*dptr
;
117 for (dptr
= sconn
->searches
.dirptrs
; dptr
!= NULL
; dptr
= dptr
->next
) {
118 if(dptr
->dnum
!= key
) {
121 DLIST_PROMOTE(sconn
->searches
.dirptrs
, dptr
);
127 /****************************************************************************
128 Get the dir path for a dir index.
129 ****************************************************************************/
131 const char *dptr_path(struct smbd_server_connection
*sconn
, int key
)
133 struct dptr_struct
*dptr
= dptr_get(sconn
, key
);
135 return(dptr
->dir_hnd
->dir_smb_fname
->base_name
);
139 /****************************************************************************
140 Get the dir wcard for a dir index.
141 ****************************************************************************/
143 const char *dptr_wcard(struct smbd_server_connection
*sconn
, int key
)
145 struct dptr_struct
*dptr
= dptr_get(sconn
, key
);
151 /****************************************************************************
152 Get the dir attrib for a dir index.
153 ****************************************************************************/
155 uint16_t dptr_attr(struct smbd_server_connection
*sconn
, int key
)
157 struct dptr_struct
*dptr
= dptr_get(sconn
, key
);
163 /****************************************************************************
164 Close all dptrs for a cnum.
165 ****************************************************************************/
167 void dptr_closecnum(connection_struct
*conn
)
169 struct dptr_struct
*dptr
, *next
;
170 struct smbd_server_connection
*sconn
= conn
->sconn
;
176 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= next
) {
178 if (dptr
->dir_hnd
->conn
== conn
) {
180 * Need to make a copy, "dptr" will be gone
181 * after close_file_free() returns
183 struct files_struct
*fsp
= dptr
->dir_hnd
->fsp
;
184 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
189 /****************************************************************************
190 Create a new dir ptr. If the flag old_handle is true then we must allocate
191 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
192 one byte long. If old_handle is false we allocate from the range
193 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
194 a directory handle is never zero.
195 wcard must not be zero.
196 ****************************************************************************/
198 NTSTATUS
dptr_create(connection_struct
*conn
,
199 struct smb_request
*req
,
204 struct dptr_struct
**dptr_ret
)
206 struct smbd_server_connection
*sconn
= conn
->sconn
;
207 struct dptr_struct
*dptr
= NULL
;
208 struct smb_Dir
*dir_hnd
= NULL
;
211 DBG_INFO("dir=%s\n", fsp_str_dbg(fsp
));
214 DEBUG(0,("dptr_create: called with fake connection_struct\n"));
215 return NT_STATUS_INTERNAL_ERROR
;
219 return NT_STATUS_INVALID_PARAMETER
;
222 status
= check_any_access_fsp(fsp
, SEC_DIR_LIST
);
223 if (!NT_STATUS_IS_OK(status
)) {
224 DBG_INFO("dptr_create: directory %s "
225 "not open for LIST access\n",
229 status
= OpenDir_fsp(NULL
, conn
, fsp
, wcard
, attr
, &dir_hnd
);
230 if (!NT_STATUS_IS_OK(status
)) {
234 dptr
= talloc_zero(NULL
, struct dptr_struct
);
236 DEBUG(0,("talloc fail in dptr_create.\n"));
237 TALLOC_FREE(dir_hnd
);
238 return NT_STATUS_NO_MEMORY
;
241 dptr
->dir_hnd
= dir_hnd
;
242 dptr
->wcard
= talloc_strdup(dptr
, wcard
);
245 TALLOC_FREE(dir_hnd
);
246 return NT_STATUS_NO_MEMORY
;
248 if ((req
!= NULL
&& req
->posix_pathnames
) || ISDOT(wcard
)) {
249 dptr
->has_wild
= True
;
251 dptr
->has_wild
= ms_has_wild(dptr
->wcard
);
256 if (conn_using_smb2(sconn
)) {
263 * This is an old-style SMBsearch request. Ensure the
264 * value we return will fit in the range 1-255.
267 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 0);
269 if(dptr
->dnum
== -1 || dptr
->dnum
> 254) {
270 DBG_ERR("returned %d: Error - all old "
271 "dirptrs in use ?\n",
274 TALLOC_FREE(dir_hnd
);
275 return NT_STATUS_TOO_MANY_OPENED_FILES
;
280 * This is a new-style trans2 request. Allocate from
281 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
284 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 255);
286 if(dptr
->dnum
== -1 || dptr
->dnum
< 255) {
287 DBG_ERR("returned %d: Error - all new "
288 "dirptrs in use ?\n",
291 TALLOC_FREE(dir_hnd
);
292 return NT_STATUS_TOO_MANY_OPENED_FILES
;
296 bitmap_set(sconn
->searches
.dptr_bmap
, dptr
->dnum
);
298 dptr
->dnum
+= 1; /* Always bias the dnum by one - no zero dnums allowed. */
300 DLIST_ADD(sconn
->searches
.dirptrs
, dptr
);
303 DBG_INFO("creating new dirptr [%d] for path [%s]\n",
304 dptr
->dnum
, fsp_str_dbg(fsp
));
312 /****************************************************************************
313 Wrapper functions to access the lower level directory handles.
314 ****************************************************************************/
316 void dptr_CloseDir(files_struct
*fsp
)
318 struct smbd_server_connection
*sconn
= NULL
;
320 if (fsp
->dptr
== NULL
) {
323 sconn
= fsp
->conn
->sconn
;
326 * The destructor for the struct smb_Dir (fsp->dptr->dir_hnd)
327 * now handles all resource deallocation.
330 DBG_INFO("closing dptr key %d\n", fsp
->dptr
->dnum
);
332 if (sconn
!= NULL
&& !conn_using_smb2(sconn
)) {
333 DLIST_REMOVE(sconn
->searches
.dirptrs
, fsp
->dptr
);
336 * Free the dnum in the bitmap. Remember the dnum value is
337 * always biased by one with respect to the bitmap.
340 if (!bitmap_query(sconn
->searches
.dptr_bmap
,
341 fsp
->dptr
->dnum
- 1))
343 DBG_ERR("closing dnum = %d and bitmap not set !\n",
347 bitmap_clear(sconn
->searches
.dptr_bmap
, fsp
->dptr
->dnum
- 1);
350 TALLOC_FREE(fsp
->dptr
->dir_hnd
);
351 TALLOC_FREE(fsp
->dptr
);
354 void dptr_RewindDir(struct dptr_struct
*dptr
)
356 RewindDir(dptr
->dir_hnd
);
357 dptr
->did_stat
= false;
358 TALLOC_FREE(dptr
->overflow
.fname
);
359 TALLOC_FREE(dptr
->overflow
.smb_fname
);
362 unsigned int dptr_FileNumber(struct dptr_struct
*dptr
)
364 return dptr
->dir_hnd
->file_number
;
367 bool dptr_has_wild(struct dptr_struct
*dptr
)
369 return dptr
->has_wild
;
372 int dptr_dnum(struct dptr_struct
*dptr
)
377 bool dptr_get_priv(struct dptr_struct
*dptr
)
382 void dptr_set_priv(struct dptr_struct
*dptr
)
387 bool dptr_case_sensitive(struct dptr_struct
*dptr
)
389 return dptr
->dir_hnd
->case_sensitive
;
392 /****************************************************************************
393 Return the next visible file name, skipping veto'd and invisible files.
394 ****************************************************************************/
396 char *dptr_ReadDirName(TALLOC_CTX
*ctx
, struct dptr_struct
*dptr
)
398 struct stat_ex st
= {
401 struct smb_Dir
*dir_hnd
= dptr
->dir_hnd
;
402 struct files_struct
*dir_fsp
= dir_hnd
->fsp
;
403 struct smb_filename
*dir_name
= dir_fsp
->fsp_name
;
404 struct smb_filename smb_fname_base
;
405 bool retry_scanning
= false;
409 if (dptr
->has_wild
) {
410 const char *name_temp
= NULL
;
411 char *talloced
= NULL
;
412 name_temp
= ReadDirName(dir_hnd
, &talloced
);
413 if (name_temp
== NULL
) {
416 if (talloced
!= NULL
) {
417 return talloc_move(ctx
, &talloced
);
419 return talloc_strdup(ctx
, name_temp
);
422 if (dptr
->did_stat
) {
424 * No wildcard, this is not a real directory traverse
425 * but a "stat" call behind a query_directory. We've
426 * been here, nothing else to look at.
430 dptr
->did_stat
= true;
432 /* Create an smb_filename with stream_name == NULL. */
433 smb_fname_base
= (struct smb_filename
){
434 .base_name
= dptr
->wcard
,
435 .flags
= dir_name
->flags
,
436 .twrp
= dir_name
->twrp
,
439 if (dir_name
->flags
& SMB_FILENAME_POSIX_PATH
) {
440 flags
|= AT_SYMLINK_NOFOLLOW
;
443 ret
= SMB_VFS_FSTATAT(
444 dir_hnd
->conn
, dir_fsp
, &smb_fname_base
, &st
, flags
);
446 return talloc_strdup(ctx
, dptr
->wcard
);
450 * If we get any other error than ENOENT or ENOTDIR
451 * then the file exists, we just can't stat it.
453 if (errno
!= ENOENT
&& errno
!= ENOTDIR
) {
454 return talloc_strdup(ctx
, dptr
->wcard
);
458 * A scan will find the long version of a mangled name as
461 retry_scanning
|= mangle_is_mangled(dptr
->wcard
,
462 dir_hnd
->conn
->params
);
465 * Also retry scanning if the client requested case
466 * insensitive semantics and the file system does not provide
469 retry_scanning
|= (!dir_hnd
->case_sensitive
&&
470 (dir_hnd
->conn
->fs_capabilities
&
471 FILE_CASE_SENSITIVE_SEARCH
));
473 if (retry_scanning
) {
474 char *found_name
= NULL
;
477 status
= get_real_filename_at(dir_fsp
,
481 if (NT_STATUS_IS_OK(status
)) {
489 struct files_struct
*dir_hnd_fetch_fsp(struct smb_Dir
*dir_hnd
)
494 /****************************************************************************
495 Fetch the fsp associated with the dptr_num.
496 ****************************************************************************/
498 files_struct
*dptr_fetch_lanman2_fsp(struct smbd_server_connection
*sconn
,
501 struct dptr_struct
*dptr
= dptr_get(sconn
, dptr_num
);
505 DBG_NOTICE("fetching dirptr %d for path %s\n",
507 dptr
->dir_hnd
->dir_smb_fname
->base_name
);
508 return dptr
->dir_hnd
->fsp
;
511 bool smbd_dirptr_get_entry(TALLOC_CTX
*ctx
,
512 struct dptr_struct
*dirptr
,
518 bool (*match_fn
)(TALLOC_CTX
*ctx
,
525 struct smb_filename
**_smb_fname
,
528 struct smb_Dir
*dir_hnd
= dirptr
->dir_hnd
;
529 connection_struct
*conn
= dir_hnd
->conn
;
530 struct smb_filename
*dir_fname
= dir_hnd
->dir_smb_fname
;
531 bool posix
= (dir_fname
->flags
& SMB_FILENAME_POSIX_PATH
);
532 const bool toplevel
= ISDOT(dir_fname
->base_name
);
538 if (dirptr
->overflow
.smb_fname
!= NULL
) {
539 *_fname
= talloc_move(ctx
, &dirptr
->overflow
.fname
);
540 *_smb_fname
= talloc_move(ctx
, &dirptr
->overflow
.smb_fname
);
541 *_mode
= dirptr
->overflow
.mode
;
545 if (dont_descend
&& (dptr_FileNumber(dirptr
) >= 2)) {
547 * . and .. were returned first, we're done showing
548 * the directory as empty.
556 struct smb_filename
*smb_fname
= NULL
;
558 bool get_dosmode
= get_dosmode_in
;
559 bool toplevel_dotdot
;
563 dname
= dptr_ReadDirName(ctx
, dirptr
);
565 DBG_DEBUG("dir [%s] dirptr [%p] offset [%u] => "
567 smb_fname_str_dbg(dir_fname
),
569 dir_hnd
->file_number
,
570 dname
? dname
: "(finished)");
576 if (IS_VETO_PATH(conn
, dname
)) {
582 * fname may get mangled, dname is never mangled.
583 * Whenever we're accessing the filesystem we use
584 * pathreal which is composed from dname.
587 ok
= match_fn(ctx
, private_data
, dname
, mask
, &fname
);
593 toplevel_dotdot
= toplevel
&& ISDOTDOT(dname
);
595 smb_fname
= synthetic_smb_fname(talloc_tos(),
596 toplevel_dotdot
? "." : dname
,
601 if (smb_fname
== NULL
) {
607 * UCF_POSIX_PATHNAMES to avoid the readdir fallback
608 * if we get raced between readdir and unlink.
610 status
= openat_pathref_fsp_lcomp(dir_hnd
->fsp
,
612 UCF_POSIX_PATHNAMES
);
613 if (!NT_STATUS_IS_OK(status
)) {
614 DBG_DEBUG("Could not open %s: %s\n",
617 TALLOC_FREE(smb_fname
);
623 visible
= is_visible_fsp(smb_fname
->fsp
);
625 TALLOC_FREE(smb_fname
);
631 if (!S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
635 if (lp_host_msdfs() && lp_msdfs_root(SNUM(conn
)) &&
636 is_msdfs_link(dir_hnd
->fsp
, smb_fname
))
638 DBG_INFO("Masquerading msdfs link %s as a directory\n",
639 smb_fname
->base_name
);
641 smb_fname
->st
.st_ex_mode
= (smb_fname
->st
.st_ex_mode
&
645 mode
= dos_mode_msdfs(conn
, dname
, &smb_fname
->st
);
647 ask_sharemode
= false;
653 * Posix always wants to see symlinks.
655 ask_sharemode
= false;
659 if (!lp_follow_symlinks(SNUM(conn
))) {
661 * Hide symlinks not followed
663 TALLOC_FREE(smb_fname
);
670 * We have to find out if it's a dangling
671 * symlink. Use the fat logic behind
672 * openat_pathref_fsp().
676 struct files_struct
*fsp
= smb_fname
->fsp
;
677 smb_fname_fsp_unlink(smb_fname
);
679 file_free(NULL
, fsp
);
682 status
= openat_pathref_fsp(dir_hnd
->fsp
, smb_fname
);
684 if (!NT_STATUS_IS_OK(status
)) {
686 * Dangling symlink. Hide.
688 TALLOC_FREE(smb_fname
);
696 mode
= fdos_mode(smb_fname
->fsp
);
697 smb_fname
->st
= smb_fname
->fsp
->fsp_name
->st
;
700 if (!dir_check_ftype(mode
, dirtype
)) {
701 DBG_INFO("[%s] attribs 0x%" PRIx32
" didn't match "
706 TALLOC_FREE(smb_fname
);
712 if (ask_sharemode
&& !S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
713 struct timespec write_time_ts
;
714 struct file_id fileid
;
716 fileid
= vfs_file_id_from_sbuf(conn
,
718 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
719 if (!is_omit_timespec(&write_time_ts
)) {
720 update_stat_ex_mtime(&smb_fname
->st
,
725 if (toplevel_dotdot
) {
727 * Ensure posix fileid and sids are hidden
729 smb_fname
->st
.st_ex_ino
= 0;
730 smb_fname
->st
.st_ex_dev
= 0;
731 smb_fname
->st
.st_ex_uid
= -1;
732 smb_fname
->st
.st_ex_gid
= -1;
735 DBG_NOTICE("mask=[%s] found %s fname=%s (%s)\n",
737 smb_fname_str_dbg(smb_fname
),
743 *_smb_fname
= talloc_move(ctx
, &smb_fname
);
753 void smbd_dirptr_push_overflow(struct dptr_struct
*dirptr
,
755 struct smb_filename
**_smb_fname
,
758 SMB_ASSERT(dirptr
->overflow
.fname
== NULL
);
759 SMB_ASSERT(dirptr
->overflow
.smb_fname
== NULL
);
761 dirptr
->overflow
.fname
= talloc_move(dirptr
, _fname
);
762 dirptr
->overflow
.smb_fname
= talloc_move(dirptr
, _smb_fname
);
763 dirptr
->overflow
.mode
= mode
;
766 void smbd_dirptr_set_last_name_sent(struct dptr_struct
*dirptr
,
769 TALLOC_FREE(dirptr
->last_name_sent
);
770 dirptr
->last_name_sent
= talloc_move(dirptr
, _fname
);
773 char *smbd_dirptr_get_last_name_sent(struct dptr_struct
*dirptr
)
775 return dirptr
->last_name_sent
;
778 /*******************************************************************
779 Check to see if a user can read an fsp . This is only approximate,
780 it is used as part of the "hide unreadable" option. Don't
781 use it for anything security sensitive.
782 ********************************************************************/
784 static bool user_can_read_fsp(struct files_struct
*fsp
)
787 uint32_t rejected_share_access
= 0;
788 uint32_t rejected_mask
= 0;
789 struct security_descriptor
*sd
= NULL
;
790 uint32_t access_mask
= FILE_READ_DATA
|
792 FILE_READ_ATTRIBUTES
|
793 SEC_STD_READ_CONTROL
;
796 * Never hide files from the root user.
797 * We use (uid_t)0 here not sec_initial_uid()
798 * as make test uses a single user context.
801 if (get_current_uid(fsp
->conn
) == (uid_t
)0) {
806 * We can't directly use smbd_check_access_rights_fsp()
807 * here, as this implicitly grants FILE_READ_ATTRIBUTES
808 * which the Windows access-based-enumeration code
809 * explicitly checks for on the file security descriptor.
812 * https://bugzilla.samba.org/show_bug.cgi?id=10252
814 * and the smb2.acl2.ACCESSBASED test for details.
817 rejected_share_access
= access_mask
& ~(fsp
->conn
->share_access
);
818 if (rejected_share_access
) {
819 DBG_DEBUG("rejected share access 0x%x "
821 (unsigned int)access_mask
,
823 (unsigned int)rejected_share_access
);
827 status
= SMB_VFS_FGET_NT_ACL(metadata_fsp(fsp
),
834 if (!NT_STATUS_IS_OK(status
)) {
835 DBG_DEBUG("Could not get acl "
842 status
= se_file_access_check(sd
,
843 get_current_nttok(fsp
->conn
),
850 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
851 DBG_DEBUG("rejected bits 0x%x read access for %s\n",
852 (unsigned int)rejected_mask
,
859 /*******************************************************************
860 Check to see if a user can write to an fsp.
861 Always return true for directories.
862 This is only approximate,
863 it is used as part of the "hide unwriteable" option. Don't
864 use it for anything security sensitive.
865 ********************************************************************/
867 static bool user_can_write_fsp(struct files_struct
*fsp
)
870 * Never hide files from the root user.
871 * We use (uid_t)0 here not sec_initial_uid()
872 * as make test uses a single user context.
875 if (get_current_uid(fsp
->conn
) == (uid_t
)0) {
879 if (fsp
->fsp_flags
.is_directory
) {
883 return can_write_to_fsp(fsp
);
886 /*******************************************************************
887 Is a file a "special" type ?
888 ********************************************************************/
890 static bool file_is_special(connection_struct
*conn
,
891 const struct smb_filename
*smb_fname
)
894 * Never hide files from the root user.
895 * We use (uid_t)0 here not sec_initial_uid()
896 * as make test uses a single user context.
899 if (get_current_uid(conn
) == (uid_t
)0) {
903 SMB_ASSERT(VALID_STAT(smb_fname
->st
));
905 if (S_ISREG(smb_fname
->st
.st_ex_mode
) ||
906 S_ISDIR(smb_fname
->st
.st_ex_mode
) ||
907 S_ISLNK(smb_fname
->st
.st_ex_mode
))
913 /*******************************************************************
914 Should the file be seen by the client?
915 ********************************************************************/
917 bool is_visible_fsp(struct files_struct
*fsp
)
919 bool hide_unreadable
= false;
920 bool hide_unwriteable
= false;
921 bool hide_special
= false;
922 int hide_new_files_timeout
= 0;
923 const char *last_component
= NULL
;
925 hide_unreadable
= lp_hide_unreadable(SNUM(fsp
->conn
));
926 hide_unwriteable
= lp_hide_unwriteable_files(SNUM(fsp
->conn
));
927 hide_special
= lp_hide_special_files(SNUM(fsp
->conn
));
928 hide_new_files_timeout
= lp_hide_new_files_timeout(SNUM(fsp
->conn
));
930 if (!hide_unreadable
&&
933 (hide_new_files_timeout
== 0))
938 fsp
= metadata_fsp(fsp
);
940 /* Get the last component of the base name. */
941 last_component
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
942 if (!last_component
) {
943 last_component
= fsp
->fsp_name
->base_name
;
945 last_component
++; /* Go past '/' */
948 if (ISDOT(last_component
) || ISDOTDOT(last_component
)) {
949 return true; /* . and .. are always visible. */
952 if (fsp_get_pathref_fd(fsp
) == -1) {
954 * Symlink in POSIX mode or MS-DFS.
955 * We've checked veto files so the
956 * only thing we can check is the
957 * hide_new_files_timeout.
959 if ((hide_new_files_timeout
!= 0) &&
960 !S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
961 double age
= timespec_elapsed(
962 &fsp
->fsp_name
->st
.st_ex_mtime
);
964 if (age
< (double)hide_new_files_timeout
) {
971 /* Honour _hide unreadable_ option */
972 if (hide_unreadable
&& !user_can_read_fsp(fsp
)) {
973 DBG_DEBUG("file %s is unreadable.\n", fsp_str_dbg(fsp
));
977 /* Honour _hide unwriteable_ option */
978 if (hide_unwriteable
&& !user_can_write_fsp(fsp
)) {
979 DBG_DEBUG("file %s is unwritable.\n", fsp_str_dbg(fsp
));
983 /* Honour _hide_special_ option */
984 if (hide_special
&& file_is_special(fsp
->conn
, fsp
->fsp_name
)) {
985 DBG_DEBUG("file %s is special.\n", fsp_str_dbg(fsp
));
989 if ((hide_new_files_timeout
!= 0) &&
990 !S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
991 double age
= timespec_elapsed(&fsp
->fsp_name
->st
.st_ex_mtime
);
993 if (age
< (double)hide_new_files_timeout
) {
1001 static int smb_Dir_destructor(struct smb_Dir
*dir_hnd
)
1003 files_struct
*fsp
= dir_hnd
->fsp
;
1005 SMB_VFS_CLOSEDIR(dir_hnd
->conn
, dir_hnd
->dir
);
1006 fsp_set_fd(fsp
, -1);
1007 if (fsp
->dptr
!= NULL
) {
1008 SMB_ASSERT(fsp
->dptr
->dir_hnd
== dir_hnd
);
1009 fsp
->dptr
->dir_hnd
= NULL
;
1011 dir_hnd
->fsp
= NULL
;
1015 /*******************************************************************
1017 ********************************************************************/
1019 static int smb_Dir_OpenDir_destructor(struct smb_Dir
*dir_hnd
)
1021 files_struct
*fsp
= dir_hnd
->fsp
;
1023 smb_Dir_destructor(dir_hnd
);
1024 file_free(NULL
, fsp
);
1028 NTSTATUS
OpenDir(TALLOC_CTX
*mem_ctx
,
1029 connection_struct
*conn
,
1030 const struct smb_filename
*smb_dname
,
1033 struct smb_Dir
**_dir_hnd
)
1035 struct files_struct
*fsp
= NULL
;
1036 struct smb_Dir
*dir_hnd
= NULL
;
1039 status
= open_internal_dirfsp(conn
,
1043 if (!NT_STATUS_IS_OK(status
)) {
1047 status
= OpenDir_fsp(mem_ctx
, conn
, fsp
, mask
, attr
, &dir_hnd
);
1048 if (!NT_STATUS_IS_OK(status
)) {
1053 * This overwrites the destructor set by OpenDir_fsp() but
1054 * smb_Dir_OpenDir_destructor() calls the OpenDir_fsp()
1057 talloc_set_destructor(dir_hnd
, smb_Dir_OpenDir_destructor
);
1059 *_dir_hnd
= dir_hnd
;
1060 return NT_STATUS_OK
;
1063 NTSTATUS
OpenDir_from_pathref(TALLOC_CTX
*mem_ctx
,
1064 struct files_struct
*dirfsp
,
1067 struct smb_Dir
**_dir_hnd
)
1069 struct files_struct
*fsp
= NULL
;
1070 struct smb_Dir
*dir_hnd
= NULL
;
1073 status
= openat_internal_dir_from_pathref(dirfsp
, O_RDONLY
, &fsp
);
1074 if (!NT_STATUS_IS_OK(status
)) {
1078 status
= OpenDir_fsp(mem_ctx
, fsp
->conn
, fsp
, mask
, attr
, &dir_hnd
);
1079 if (!NT_STATUS_IS_OK(status
)) {
1084 * This overwrites the destructor set by OpenDir_fsp() but
1085 * smb_Dir_OpenDir_destructor() calls the OpenDir_fsp()
1088 talloc_set_destructor(dir_hnd
, smb_Dir_OpenDir_destructor
);
1090 *_dir_hnd
= dir_hnd
;
1091 return NT_STATUS_OK
;
1094 /*******************************************************************
1095 Open a directory from an fsp.
1096 ********************************************************************/
1098 static NTSTATUS
OpenDir_fsp(
1099 TALLOC_CTX
*mem_ctx
,
1100 connection_struct
*conn
,
1104 struct smb_Dir
**_dir_hnd
)
1106 struct smb_Dir
*dir_hnd
= talloc_zero(mem_ctx
, struct smb_Dir
);
1110 return NT_STATUS_NO_MEMORY
;
1113 if (!fsp
->fsp_flags
.is_directory
) {
1114 status
= NT_STATUS_INVALID_HANDLE
;
1118 if (fsp_get_io_fd(fsp
) == -1) {
1119 status
= NT_STATUS_INVALID_HANDLE
;
1123 dir_hnd
->conn
= conn
;
1125 dir_hnd
->dir_smb_fname
= cp_smb_filename(dir_hnd
, fsp
->fsp_name
);
1126 if (!dir_hnd
->dir_smb_fname
) {
1127 status
= NT_STATUS_NO_MEMORY
;
1131 dir_hnd
->dir
= SMB_VFS_FDOPENDIR(fsp
, mask
, attr
);
1132 if (dir_hnd
->dir
== NULL
) {
1133 status
= map_nt_error_from_unix(errno
);
1137 if (fsp
->fsp_flags
.posix_open
) {
1138 dir_hnd
->case_sensitive
= true;
1140 dir_hnd
->case_sensitive
= conn
->case_sensitive
;
1143 talloc_set_destructor(dir_hnd
, smb_Dir_destructor
);
1145 *_dir_hnd
= dir_hnd
;
1146 return NT_STATUS_OK
;
1149 TALLOC_FREE(dir_hnd
);
1154 /*******************************************************************
1155 Read from a directory.
1156 Return directory entry, current offset, and optional stat information.
1157 Don't check for veto or invisible files.
1158 ********************************************************************/
1160 const char *ReadDirName(struct smb_Dir
*dir_hnd
, char **ptalloced
)
1163 char *talloced
= NULL
;
1164 connection_struct
*conn
= dir_hnd
->conn
;
1166 if (dir_hnd
->file_number
< 2) {
1167 if (dir_hnd
->file_number
== 0) {
1172 dir_hnd
->file_number
++;
1177 while ((n
= vfs_readdirname(conn
,
1181 int unlink_flags
= INT_MAX
;
1182 /* Ignore . and .. - we've already returned them. */
1183 if (ISDOT(n
) || ISDOTDOT(n
)) {
1184 TALLOC_FREE(talloced
);
1188 * ignore tmp directories, see mkdir_internals()
1190 if (IS_SMBD_TMPNAME(n
, &unlink_flags
)) {
1191 struct smb_filename
*atname
= NULL
;
1192 const char *fp
= NULL
;
1195 atname
= synthetic_smb_fname(talloc_tos(),
1201 if (atname
== NULL
) {
1202 TALLOC_FREE(talloced
);
1205 fp
= full_path_from_dirfsp_at_basename(atname
,
1209 TALLOC_FREE(atname
);
1210 TALLOC_FREE(talloced
);
1214 if (unlink_flags
== INT_MAX
) {
1215 DBG_NOTICE("ignoring %s\n", fp
);
1216 TALLOC_FREE(atname
);
1217 TALLOC_FREE(talloced
);
1222 * We remove the stale tmpname
1223 * as root and ignore any errors
1225 DBG_NOTICE("unlink stale %s\n", fp
);
1227 ret
= SMB_VFS_UNLINKAT(conn
,
1233 DBG_NOTICE("unlinked stale %s\n", fp
);
1235 DBG_WARNING("failed to unlink stale %s: %s\n",
1236 fp
, strerror(errno
));
1238 TALLOC_FREE(atname
);
1239 TALLOC_FREE(talloced
);
1242 *ptalloced
= talloced
;
1243 dir_hnd
->file_number
++;
1250 /*******************************************************************
1251 Rewind to the start.
1252 ********************************************************************/
1254 void RewindDir(struct smb_Dir
*dir_hnd
)
1256 SMB_VFS_REWINDDIR(dir_hnd
->conn
, dir_hnd
->dir
);
1257 dir_hnd
->file_number
= 0;
1260 struct have_file_open_below_state
{
1264 static int have_file_open_below_fn(const struct share_mode_data
*data
,
1265 const struct share_mode_entry
*e
,
1268 struct have_file_open_below_state
*state
= private_data
;
1275 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
1276 /* Ignore POSIX opens */
1280 exists
= serverid_exists(&e
->pid
);
1285 state
->found_one
= true;
1289 bool have_file_open_below(struct files_struct
*fsp
)
1291 struct have_file_open_below_state state
= {
1296 if (!lp_strict_rename(SNUM(fsp
->conn
))) {
1297 if (file_find_subpath(fsp
)) {
1303 if (!VALID_STAT(fsp
->fsp_name
->st
)) {
1306 if (!S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
1310 ret
= opens_below_forall_read(fsp
->conn
,
1312 have_file_open_below_fn
,
1318 return state
.found_one
;
1321 struct opens_below_forall_read_state
{
1323 ssize_t dirpath_len
;
1324 int (*fn
)(const struct share_mode_data
*data
,
1325 const struct share_mode_entry
*e
,
1326 void *private_data
);
1330 static int opens_below_forall_read_fn(struct file_id fid
,
1331 const struct share_mode_data
*data
,
1332 const struct share_mode_entry
*entry
,
1335 struct opens_below_forall_read_state
*state
= private_data
;
1336 char tmpbuf
[PATH_MAX
];
1337 char *fullpath
= NULL
;
1338 char *to_free
= NULL
;
1341 len
= full_path_tos(data
->servicepath
,
1350 if (state
->dirpath_len
>= len
) {
1352 * Filter files above dirpath
1356 if (fullpath
[state
->dirpath_len
] != '/') {
1358 * Filter file that don't have a path separator at the end of
1364 if (memcmp(state
->dirpath
, fullpath
, state
->dirpath_len
) != 0) {
1371 TALLOC_FREE(to_free
);
1372 return state
->fn(data
, entry
, state
->private_data
);
1375 TALLOC_FREE(to_free
);
1379 bool opens_below_forall_read(struct connection_struct
*conn
,
1380 const struct smb_filename
*dir_name
,
1381 int (*fn
)(const struct share_mode_data
*data
,
1382 const struct share_mode_entry
*e
,
1383 void *private_data
),
1386 struct opens_below_forall_read_state state
= {
1388 .private_data
= private_data
,
1391 char tmpbuf
[PATH_MAX
];
1392 char *to_free
= NULL
;
1394 state
.dirpath_len
= full_path_tos(conn
->connectpath
,
1395 dir_name
->base_name
,
1400 if (state
.dirpath_len
== -1) {
1404 ret
= share_entry_forall_read(opens_below_forall_read_fn
, &state
);
1405 TALLOC_FREE(to_free
);
1412 struct opens_below_forall_state
{
1414 ssize_t dirpath_len
;
1415 int (*fn
)(struct share_mode_data
*data
,
1416 struct share_mode_entry
*e
,
1417 void *private_data
);
1421 static int opens_below_forall_fn(struct file_id fid
,
1422 struct share_mode_data
*data
,
1423 struct share_mode_entry
*entry
,
1426 struct opens_below_forall_state
*state
= private_data
;
1427 char tmpbuf
[PATH_MAX
];
1428 char *fullpath
= NULL
;
1429 char *to_free
= NULL
;
1432 len
= full_path_tos(data
->servicepath
,
1441 if (state
->dirpath_len
>= len
) {
1443 * Filter files above dirpath
1447 if (fullpath
[state
->dirpath_len
] != '/') {
1449 * Filter file that don't have a path separator at the end of
1455 if (memcmp(state
->dirpath
, fullpath
, state
->dirpath_len
) != 0) {
1462 TALLOC_FREE(to_free
);
1463 return state
->fn(data
, entry
, state
->private_data
);
1466 TALLOC_FREE(to_free
);
1470 bool opens_below_forall(struct connection_struct
*conn
,
1471 const struct smb_filename
*dir_name
,
1472 int (*fn
)(struct share_mode_data
*data
,
1473 struct share_mode_entry
*e
,
1474 void *private_data
),
1477 struct opens_below_forall_state state
= {
1479 .private_data
= private_data
,
1482 char tmpbuf
[PATH_MAX
];
1483 char *to_free
= NULL
;
1485 state
.dirpath_len
= full_path_tos(conn
->connectpath
,
1486 dir_name
->base_name
,
1491 if (state
.dirpath_len
== -1) {
1495 ret
= share_entry_forall(opens_below_forall_fn
, &state
);
1496 TALLOC_FREE(to_free
);
1503 /*****************************************************************
1504 Is this directory empty ?
1505 *****************************************************************/
1507 NTSTATUS
can_delete_directory_fsp(files_struct
*fsp
)
1509 NTSTATUS status
= NT_STATUS_OK
;
1510 const char *dname
= NULL
;
1511 char *talloced
= NULL
;
1512 struct connection_struct
*conn
= fsp
->conn
;
1513 struct smb_Dir
*dir_hnd
= NULL
;
1516 talloc_tos(), conn
, fsp
->fsp_name
, NULL
, 0, &dir_hnd
);
1517 if (!NT_STATUS_IS_OK(status
)) {
1521 while ((dname
= ReadDirName(dir_hnd
, &talloced
))) {
1522 struct smb_filename
*smb_dname_full
= NULL
;
1523 struct smb_filename
*direntry_fname
= NULL
;
1524 char *fullname
= NULL
;
1527 if (ISDOT(dname
) || (ISDOTDOT(dname
))) {
1528 TALLOC_FREE(talloced
);
1531 if (IS_VETO_PATH(conn
, dname
)) {
1532 TALLOC_FREE(talloced
);
1536 fullname
= talloc_asprintf(talloc_tos(),
1538 fsp
->fsp_name
->base_name
,
1540 if (fullname
== NULL
) {
1541 status
= NT_STATUS_NO_MEMORY
;
1545 smb_dname_full
= synthetic_smb_fname(talloc_tos(),
1549 fsp
->fsp_name
->twrp
,
1550 fsp
->fsp_name
->flags
);
1551 if (smb_dname_full
== NULL
) {
1552 TALLOC_FREE(talloced
);
1553 TALLOC_FREE(fullname
);
1554 status
= NT_STATUS_NO_MEMORY
;
1558 ret
= SMB_VFS_LSTAT(conn
, smb_dname_full
);
1560 status
= map_nt_error_from_unix(errno
);
1561 TALLOC_FREE(talloced
);
1562 TALLOC_FREE(fullname
);
1563 TALLOC_FREE(smb_dname_full
);
1567 if (S_ISLNK(smb_dname_full
->st
.st_ex_mode
)) {
1568 /* Could it be an msdfs link ? */
1569 if (lp_host_msdfs() &&
1570 lp_msdfs_root(SNUM(conn
))) {
1571 struct smb_filename
*smb_dname
;
1572 smb_dname
= synthetic_smb_fname(talloc_tos(),
1575 &smb_dname_full
->st
,
1576 fsp
->fsp_name
->twrp
,
1577 fsp
->fsp_name
->flags
);
1578 if (smb_dname
== NULL
) {
1579 TALLOC_FREE(talloced
);
1580 TALLOC_FREE(fullname
);
1581 TALLOC_FREE(smb_dname_full
);
1582 status
= NT_STATUS_NO_MEMORY
;
1585 if (is_msdfs_link(fsp
, smb_dname
)) {
1586 TALLOC_FREE(talloced
);
1587 TALLOC_FREE(fullname
);
1588 TALLOC_FREE(smb_dname_full
);
1589 TALLOC_FREE(smb_dname
);
1590 DBG_DEBUG("got msdfs link name %s "
1591 "- can't delete directory %s\n",
1594 status
= NT_STATUS_DIRECTORY_NOT_EMPTY
;
1597 TALLOC_FREE(smb_dname
);
1599 /* Not a DFS link - could it be a dangling symlink ? */
1600 ret
= SMB_VFS_STAT(conn
, smb_dname_full
);
1601 if (ret
== -1 && (errno
== ENOENT
|| errno
== ELOOP
)) {
1604 * Allow if "delete veto files = yes"
1606 if (lp_delete_veto_files(SNUM(conn
))) {
1607 TALLOC_FREE(talloced
);
1608 TALLOC_FREE(fullname
);
1609 TALLOC_FREE(smb_dname_full
);
1613 DBG_DEBUG("got symlink name %s - "
1614 "can't delete directory %s\n",
1617 TALLOC_FREE(talloced
);
1618 TALLOC_FREE(fullname
);
1619 TALLOC_FREE(smb_dname_full
);
1620 status
= NT_STATUS_DIRECTORY_NOT_EMPTY
;
1624 /* Not a symlink, get a pathref. */
1625 status
= synthetic_pathref(talloc_tos(),
1629 &smb_dname_full
->st
,
1630 fsp
->fsp_name
->twrp
,
1631 fsp
->fsp_name
->flags
,
1633 if (!NT_STATUS_IS_OK(status
)) {
1634 status
= map_nt_error_from_unix(errno
);
1635 TALLOC_FREE(talloced
);
1636 TALLOC_FREE(fullname
);
1637 TALLOC_FREE(smb_dname_full
);
1641 if (!is_visible_fsp(direntry_fname
->fsp
)) {
1644 * Allow if "delete veto files = yes"
1646 if (lp_delete_veto_files(SNUM(conn
))) {
1647 TALLOC_FREE(talloced
);
1648 TALLOC_FREE(fullname
);
1649 TALLOC_FREE(smb_dname_full
);
1650 TALLOC_FREE(direntry_fname
);
1655 TALLOC_FREE(talloced
);
1656 TALLOC_FREE(fullname
);
1657 TALLOC_FREE(smb_dname_full
);
1658 TALLOC_FREE(direntry_fname
);
1660 DBG_DEBUG("got name %s - can't delete\n", dname
);
1661 status
= NT_STATUS_DIRECTORY_NOT_EMPTY
;
1664 TALLOC_FREE(talloced
);
1665 TALLOC_FREE(dir_hnd
);
1667 if (!NT_STATUS_IS_OK(status
)) {
1671 if (have_file_open_below(fsp
)) {
1672 return NT_STATUS_ACCESS_DENIED
;
1675 return NT_STATUS_OK
;