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"
35 This module implements directory related functions for Samba.
38 /* "Special" directory offsets. */
39 #define END_OF_DIRECTORY_OFFSET ((long)-1)
40 #define START_OF_DIRECTORY_OFFSET ((long)0)
41 #define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000)
43 /* Make directory handle internals available. */
46 connection_struct
*conn
;
48 struct smb_filename
*dir_smb_fname
;
49 unsigned int file_number
;
51 files_struct
*fsp
; /* Back pointer to containing fsp, only
52 set from OpenDir_fsp(). */
56 struct dptr_struct
*next
, *prev
;
58 struct smb_Dir
*dir_hnd
;
61 bool has_wild
; /* Set to true if the wcard entry has MS wildcard characters in it. */
62 bool did_stat
; /* Optimisation for non-wcard searches. */
63 bool priv
; /* Directory handle opened with privilege. */
66 char *last_name_sent
; /* for name-based trans2 resume */
70 struct smb_filename
*smb_fname
;
75 static NTSTATUS
OpenDir_fsp(
77 connection_struct
*conn
,
81 struct smb_Dir
**_dir_hnd
);
83 static int smb_Dir_destructor(struct smb_Dir
*dir_hnd
);
85 #define INVALID_DPTR_KEY (-3)
87 /****************************************************************************
88 Initialise the dir bitmap.
89 ****************************************************************************/
91 bool init_dptrs(struct smbd_server_connection
*sconn
)
93 if (sconn
->searches
.dptr_bmap
) {
97 sconn
->searches
.dptr_bmap
= bitmap_talloc(
98 sconn
, MAX_DIRECTORY_HANDLES
);
100 if (sconn
->searches
.dptr_bmap
== NULL
) {
107 /****************************************************************************
108 Get the struct dptr_struct for a dir index.
109 ****************************************************************************/
111 static struct dptr_struct
*dptr_get(struct smbd_server_connection
*sconn
,
114 struct dptr_struct
*dptr
;
116 for (dptr
= sconn
->searches
.dirptrs
; dptr
!= NULL
; dptr
= dptr
->next
) {
117 if(dptr
->dnum
!= key
) {
120 DLIST_PROMOTE(sconn
->searches
.dirptrs
, dptr
);
126 /****************************************************************************
127 Get the dir path for a dir index.
128 ****************************************************************************/
130 const char *dptr_path(struct smbd_server_connection
*sconn
, int key
)
132 struct dptr_struct
*dptr
= dptr_get(sconn
, key
);
134 return(dptr
->dir_hnd
->dir_smb_fname
->base_name
);
138 /****************************************************************************
139 Get the dir wcard for a dir index.
140 ****************************************************************************/
142 const char *dptr_wcard(struct smbd_server_connection
*sconn
, int key
)
144 struct dptr_struct
*dptr
= dptr_get(sconn
, key
);
150 /****************************************************************************
151 Get the dir attrib for a dir index.
152 ****************************************************************************/
154 uint16_t dptr_attr(struct smbd_server_connection
*sconn
, int key
)
156 struct dptr_struct
*dptr
= dptr_get(sconn
, key
);
162 /****************************************************************************
163 Close all dptrs for a cnum.
164 ****************************************************************************/
166 void dptr_closecnum(connection_struct
*conn
)
168 struct dptr_struct
*dptr
, *next
;
169 struct smbd_server_connection
*sconn
= conn
->sconn
;
175 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= next
) {
177 if (dptr
->dir_hnd
->conn
== conn
) {
179 * Need to make a copy, "dptr" will be gone
180 * after close_file_free() returns
182 struct files_struct
*fsp
= dptr
->dir_hnd
->fsp
;
183 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
188 /****************************************************************************
189 Create a new dir ptr. If the flag old_handle is true then we must allocate
190 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
191 one byte long. If old_handle is false we allocate from the range
192 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
193 a directory handle is never zero.
194 wcard must not be zero.
195 ****************************************************************************/
197 NTSTATUS
dptr_create(connection_struct
*conn
,
198 struct smb_request
*req
,
203 struct dptr_struct
**dptr_ret
)
205 struct smbd_server_connection
*sconn
= conn
->sconn
;
206 struct dptr_struct
*dptr
= NULL
;
207 struct smb_Dir
*dir_hnd
= NULL
;
210 DBG_INFO("dir=%s\n", fsp_str_dbg(fsp
));
213 DEBUG(0,("dptr_create: called with fake connection_struct\n"));
214 return NT_STATUS_INTERNAL_ERROR
;
218 return NT_STATUS_INVALID_PARAMETER
;
221 status
= check_any_access_fsp(fsp
, SEC_DIR_LIST
);
222 if (!NT_STATUS_IS_OK(status
)) {
223 DBG_INFO("dptr_create: directory %s "
224 "not open for LIST access\n",
228 status
= OpenDir_fsp(NULL
, conn
, fsp
, wcard
, attr
, &dir_hnd
);
229 if (!NT_STATUS_IS_OK(status
)) {
233 dptr
= talloc_zero(NULL
, struct dptr_struct
);
235 DEBUG(0,("talloc fail in dptr_create.\n"));
236 TALLOC_FREE(dir_hnd
);
237 return NT_STATUS_NO_MEMORY
;
240 dptr
->dir_hnd
= dir_hnd
;
241 dptr
->wcard
= talloc_strdup(dptr
, wcard
);
244 TALLOC_FREE(dir_hnd
);
245 return NT_STATUS_NO_MEMORY
;
247 if ((req
!= NULL
&& req
->posix_pathnames
) || ISDOT(wcard
)) {
248 dptr
->has_wild
= True
;
250 dptr
->has_wild
= ms_has_wild(dptr
->wcard
);
255 if (conn_using_smb2(sconn
)) {
262 * This is an old-style SMBsearch request. Ensure the
263 * value we return will fit in the range 1-255.
266 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 0);
268 if(dptr
->dnum
== -1 || dptr
->dnum
> 254) {
269 DBG_ERR("returned %d: Error - all old "
270 "dirptrs in use ?\n",
273 TALLOC_FREE(dir_hnd
);
274 return NT_STATUS_TOO_MANY_OPENED_FILES
;
279 * This is a new-style trans2 request. Allocate from
280 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
283 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 255);
285 if(dptr
->dnum
== -1 || dptr
->dnum
< 255) {
286 DBG_ERR("returned %d: Error - all new "
287 "dirptrs in use ?\n",
290 TALLOC_FREE(dir_hnd
);
291 return NT_STATUS_TOO_MANY_OPENED_FILES
;
295 bitmap_set(sconn
->searches
.dptr_bmap
, dptr
->dnum
);
297 dptr
->dnum
+= 1; /* Always bias the dnum by one - no zero dnums allowed. */
299 DLIST_ADD(sconn
->searches
.dirptrs
, dptr
);
302 DBG_INFO("creating new dirptr [%d] for path [%s]\n",
303 dptr
->dnum
, fsp_str_dbg(fsp
));
311 /****************************************************************************
312 Wrapper functions to access the lower level directory handles.
313 ****************************************************************************/
315 void dptr_CloseDir(files_struct
*fsp
)
317 struct smbd_server_connection
*sconn
= NULL
;
319 if (fsp
->dptr
== NULL
) {
322 sconn
= fsp
->conn
->sconn
;
325 * The destructor for the struct smb_Dir (fsp->dptr->dir_hnd)
326 * now handles all resource deallocation.
329 DBG_INFO("closing dptr key %d\n", fsp
->dptr
->dnum
);
331 if (sconn
!= NULL
&& !conn_using_smb2(sconn
)) {
332 DLIST_REMOVE(sconn
->searches
.dirptrs
, fsp
->dptr
);
335 * Free the dnum in the bitmap. Remember the dnum value is
336 * always biased by one with respect to the bitmap.
339 if (!bitmap_query(sconn
->searches
.dptr_bmap
,
340 fsp
->dptr
->dnum
- 1))
342 DBG_ERR("closing dnum = %d and bitmap not set !\n",
346 bitmap_clear(sconn
->searches
.dptr_bmap
, fsp
->dptr
->dnum
- 1);
349 TALLOC_FREE(fsp
->dptr
->dir_hnd
);
350 TALLOC_FREE(fsp
->dptr
);
353 void dptr_RewindDir(struct dptr_struct
*dptr
)
355 RewindDir(dptr
->dir_hnd
);
356 dptr
->did_stat
= false;
357 TALLOC_FREE(dptr
->overflow
.fname
);
358 TALLOC_FREE(dptr
->overflow
.smb_fname
);
361 unsigned int dptr_FileNumber(struct dptr_struct
*dptr
)
363 return dptr
->dir_hnd
->file_number
;
366 bool dptr_has_wild(struct dptr_struct
*dptr
)
368 return dptr
->has_wild
;
371 int dptr_dnum(struct dptr_struct
*dptr
)
376 bool dptr_get_priv(struct dptr_struct
*dptr
)
381 void dptr_set_priv(struct dptr_struct
*dptr
)
386 bool dptr_case_sensitive(struct dptr_struct
*dptr
)
388 return dptr
->dir_hnd
->case_sensitive
;
391 /****************************************************************************
392 Return the next visible file name, skipping veto'd and invisible files.
393 ****************************************************************************/
395 char *dptr_ReadDirName(TALLOC_CTX
*ctx
, struct dptr_struct
*dptr
)
397 struct stat_ex st
= {
400 struct smb_Dir
*dir_hnd
= dptr
->dir_hnd
;
401 struct files_struct
*dir_fsp
= dir_hnd
->fsp
;
402 struct smb_filename
*dir_name
= dir_fsp
->fsp_name
;
403 struct smb_filename smb_fname_base
;
404 bool retry_scanning
= false;
408 if (dptr
->has_wild
) {
409 const char *name_temp
= NULL
;
410 char *talloced
= NULL
;
411 name_temp
= ReadDirName(dir_hnd
, &talloced
);
412 if (name_temp
== NULL
) {
415 if (talloced
!= NULL
) {
416 return talloc_move(ctx
, &talloced
);
418 return talloc_strdup(ctx
, name_temp
);
421 if (dptr
->did_stat
) {
423 * No wildcard, this is not a real directory traverse
424 * but a "stat" call behind a query_directory. We've
425 * been here, nothing else to look at.
429 dptr
->did_stat
= true;
431 /* Create an smb_filename with stream_name == NULL. */
432 smb_fname_base
= (struct smb_filename
){
433 .base_name
= dptr
->wcard
,
434 .flags
= dir_name
->flags
,
435 .twrp
= dir_name
->twrp
,
438 if (dir_name
->flags
& SMB_FILENAME_POSIX_PATH
) {
439 flags
|= AT_SYMLINK_NOFOLLOW
;
442 ret
= SMB_VFS_FSTATAT(
443 dir_hnd
->conn
, dir_fsp
, &smb_fname_base
, &st
, flags
);
445 return talloc_strdup(ctx
, dptr
->wcard
);
449 * If we get any other error than ENOENT or ENOTDIR
450 * then the file exists, we just can't stat it.
452 if (errno
!= ENOENT
&& errno
!= ENOTDIR
) {
453 return talloc_strdup(ctx
, dptr
->wcard
);
457 * A scan will find the long version of a mangled name as
460 retry_scanning
|= mangle_is_mangled(dptr
->wcard
,
461 dir_hnd
->conn
->params
);
464 * Also retry scanning if the client requested case
465 * insensitive semantics and the file system does not provide
468 retry_scanning
|= (!dir_hnd
->case_sensitive
&&
469 (dir_hnd
->conn
->fs_capabilities
&
470 FILE_CASE_SENSITIVE_SEARCH
));
472 if (retry_scanning
) {
473 char *found_name
= NULL
;
476 status
= get_real_filename_at(dir_fsp
,
480 if (NT_STATUS_IS_OK(status
)) {
488 struct files_struct
*dir_hnd_fetch_fsp(struct smb_Dir
*dir_hnd
)
493 /****************************************************************************
494 Fetch the fsp associated with the dptr_num.
495 ****************************************************************************/
497 files_struct
*dptr_fetch_lanman2_fsp(struct smbd_server_connection
*sconn
,
500 struct dptr_struct
*dptr
= dptr_get(sconn
, dptr_num
);
504 DBG_NOTICE("fetching dirptr %d for path %s\n",
506 dptr
->dir_hnd
->dir_smb_fname
->base_name
);
507 return dptr
->dir_hnd
->fsp
;
510 bool smbd_dirptr_get_entry(TALLOC_CTX
*ctx
,
511 struct dptr_struct
*dirptr
,
517 bool (*match_fn
)(TALLOC_CTX
*ctx
,
524 struct smb_filename
**_smb_fname
,
527 struct smb_Dir
*dir_hnd
= dirptr
->dir_hnd
;
528 connection_struct
*conn
= dir_hnd
->conn
;
529 struct smb_filename
*dir_fname
= dir_hnd
->dir_smb_fname
;
530 bool posix
= (dir_fname
->flags
& SMB_FILENAME_POSIX_PATH
);
531 const bool toplevel
= ISDOT(dir_fname
->base_name
);
537 if (dirptr
->overflow
.smb_fname
!= NULL
) {
538 *_fname
= talloc_move(ctx
, &dirptr
->overflow
.fname
);
539 *_smb_fname
= talloc_move(ctx
, &dirptr
->overflow
.smb_fname
);
540 *_mode
= dirptr
->overflow
.mode
;
544 if (dont_descend
&& (dptr_FileNumber(dirptr
) >= 2)) {
546 * . and .. were returned first, we're done showing
547 * the directory as empty.
555 struct smb_filename
*smb_fname
= NULL
;
557 bool get_dosmode
= get_dosmode_in
;
558 bool toplevel_dotdot
;
562 dname
= dptr_ReadDirName(ctx
, dirptr
);
564 DBG_DEBUG("dir [%s] dirptr [%p] offset [%u] => "
566 smb_fname_str_dbg(dir_fname
),
568 dir_hnd
->file_number
,
569 dname
? dname
: "(finished)");
575 if (IS_VETO_PATH(conn
, dname
)) {
581 * fname may get mangled, dname is never mangled.
582 * Whenever we're accessing the filesystem we use
583 * pathreal which is composed from dname.
586 ok
= match_fn(ctx
, private_data
, dname
, mask
, &fname
);
592 toplevel_dotdot
= toplevel
&& ISDOTDOT(dname
);
594 smb_fname
= synthetic_smb_fname(talloc_tos(),
595 toplevel_dotdot
? "." : dname
,
600 if (smb_fname
== NULL
) {
606 * UCF_POSIX_PATHNAMES to avoid the readdir fallback
607 * if we get raced between readdir and unlink.
609 status
= openat_pathref_fsp_lcomp(dir_hnd
->fsp
,
611 UCF_POSIX_PATHNAMES
);
612 if (!NT_STATUS_IS_OK(status
)) {
613 DBG_DEBUG("Could not open %s: %s\n",
616 TALLOC_FREE(smb_fname
);
622 visible
= is_visible_fsp(smb_fname
->fsp
);
624 TALLOC_FREE(smb_fname
);
630 if (!S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
634 if (lp_host_msdfs() && lp_msdfs_root(SNUM(conn
)) &&
635 is_msdfs_link(dir_hnd
->fsp
, smb_fname
))
637 DBG_INFO("Masquerading msdfs link %s as a directory\n",
638 smb_fname
->base_name
);
640 smb_fname
->st
.st_ex_mode
= (smb_fname
->st
.st_ex_mode
&
644 mode
= dos_mode_msdfs(conn
, dname
, &smb_fname
->st
);
646 ask_sharemode
= false;
652 * Posix always wants to see symlinks.
654 ask_sharemode
= false;
658 if (!lp_follow_symlinks(SNUM(conn
))) {
660 * Hide symlinks not followed
662 TALLOC_FREE(smb_fname
);
669 * We have to find out if it's a dangling
670 * symlink. Use the fat logic behind
671 * openat_pathref_fsp().
675 struct files_struct
*fsp
= smb_fname
->fsp
;
676 smb_fname_fsp_unlink(smb_fname
);
678 file_free(NULL
, fsp
);
681 status
= openat_pathref_fsp(dir_hnd
->fsp
, smb_fname
);
683 if (!NT_STATUS_IS_OK(status
)) {
685 * Dangling symlink. Hide.
687 TALLOC_FREE(smb_fname
);
695 mode
= fdos_mode(smb_fname
->fsp
);
696 smb_fname
->st
= smb_fname
->fsp
->fsp_name
->st
;
699 if (!dir_check_ftype(mode
, dirtype
)) {
700 DBG_INFO("[%s] attribs 0x%" PRIx32
" didn't match "
705 TALLOC_FREE(smb_fname
);
711 if (ask_sharemode
&& !S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
712 struct timespec write_time_ts
;
713 struct file_id fileid
;
715 fileid
= vfs_file_id_from_sbuf(conn
,
717 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
718 if (!is_omit_timespec(&write_time_ts
)) {
719 update_stat_ex_mtime(&smb_fname
->st
,
724 if (toplevel_dotdot
) {
726 * Ensure posix fileid and sids are hidden
728 smb_fname
->st
.st_ex_ino
= 0;
729 smb_fname
->st
.st_ex_dev
= 0;
730 smb_fname
->st
.st_ex_uid
= -1;
731 smb_fname
->st
.st_ex_gid
= -1;
734 DBG_NOTICE("mask=[%s] found %s fname=%s (%s)\n",
736 smb_fname_str_dbg(smb_fname
),
742 *_smb_fname
= talloc_move(ctx
, &smb_fname
);
752 void smbd_dirptr_push_overflow(struct dptr_struct
*dirptr
,
754 struct smb_filename
**_smb_fname
,
757 SMB_ASSERT(dirptr
->overflow
.fname
== NULL
);
758 SMB_ASSERT(dirptr
->overflow
.smb_fname
== NULL
);
760 dirptr
->overflow
.fname
= talloc_move(dirptr
, _fname
);
761 dirptr
->overflow
.smb_fname
= talloc_move(dirptr
, _smb_fname
);
762 dirptr
->overflow
.mode
= mode
;
765 void smbd_dirptr_set_last_name_sent(struct dptr_struct
*dirptr
,
768 TALLOC_FREE(dirptr
->last_name_sent
);
769 dirptr
->last_name_sent
= talloc_move(dirptr
, _fname
);
772 char *smbd_dirptr_get_last_name_sent(struct dptr_struct
*dirptr
)
774 return dirptr
->last_name_sent
;
777 /*******************************************************************
778 Check to see if a user can read an fsp . This is only approximate,
779 it is used as part of the "hide unreadable" option. Don't
780 use it for anything security sensitive.
781 ********************************************************************/
783 static bool user_can_read_fsp(struct files_struct
*fsp
)
786 uint32_t rejected_share_access
= 0;
787 uint32_t rejected_mask
= 0;
788 struct security_descriptor
*sd
= NULL
;
789 uint32_t access_mask
= FILE_READ_DATA
|
791 FILE_READ_ATTRIBUTES
|
792 SEC_STD_READ_CONTROL
;
795 * Never hide files from the root user.
796 * We use (uid_t)0 here not sec_initial_uid()
797 * as make test uses a single user context.
800 if (get_current_uid(fsp
->conn
) == (uid_t
)0) {
805 * We can't directly use smbd_check_access_rights_fsp()
806 * here, as this implicitly grants FILE_READ_ATTRIBUTES
807 * which the Windows access-based-enumeration code
808 * explicitly checks for on the file security descriptor.
811 * https://bugzilla.samba.org/show_bug.cgi?id=10252
813 * and the smb2.acl2.ACCESSBASED test for details.
816 rejected_share_access
= access_mask
& ~(fsp
->conn
->share_access
);
817 if (rejected_share_access
) {
818 DBG_DEBUG("rejected share access 0x%x "
820 (unsigned int)access_mask
,
822 (unsigned int)rejected_share_access
);
826 status
= SMB_VFS_FGET_NT_ACL(metadata_fsp(fsp
),
833 if (!NT_STATUS_IS_OK(status
)) {
834 DBG_DEBUG("Could not get acl "
841 status
= se_file_access_check(sd
,
842 get_current_nttok(fsp
->conn
),
849 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
850 DBG_DEBUG("rejected bits 0x%x read access for %s\n",
851 (unsigned int)rejected_mask
,
858 /*******************************************************************
859 Check to see if a user can write to an fsp.
860 Always return true for directories.
861 This is only approximate,
862 it is used as part of the "hide unwriteable" option. Don't
863 use it for anything security sensitive.
864 ********************************************************************/
866 static bool user_can_write_fsp(struct files_struct
*fsp
)
869 * Never hide files from the root user.
870 * We use (uid_t)0 here not sec_initial_uid()
871 * as make test uses a single user context.
874 if (get_current_uid(fsp
->conn
) == (uid_t
)0) {
878 if (fsp
->fsp_flags
.is_directory
) {
882 return can_write_to_fsp(fsp
);
885 /*******************************************************************
886 Is a file a "special" type ?
887 ********************************************************************/
889 static bool file_is_special(connection_struct
*conn
,
890 const struct smb_filename
*smb_fname
)
893 * Never hide files from the root user.
894 * We use (uid_t)0 here not sec_initial_uid()
895 * as make test uses a single user context.
898 if (get_current_uid(conn
) == (uid_t
)0) {
902 SMB_ASSERT(VALID_STAT(smb_fname
->st
));
904 if (S_ISREG(smb_fname
->st
.st_ex_mode
) ||
905 S_ISDIR(smb_fname
->st
.st_ex_mode
) ||
906 S_ISLNK(smb_fname
->st
.st_ex_mode
))
912 /*******************************************************************
913 Should the file be seen by the client?
914 ********************************************************************/
916 bool is_visible_fsp(struct files_struct
*fsp
)
918 bool hide_unreadable
= false;
919 bool hide_unwriteable
= false;
920 bool hide_special
= false;
921 int hide_new_files_timeout
= 0;
922 const char *last_component
= NULL
;
925 * If the file does not exist, there's no point checking
926 * the configuration options. We succeed, on the basis that the
927 * checks *might* have passed if the file was present.
933 hide_unreadable
= lp_hide_unreadable(SNUM(fsp
->conn
));
934 hide_unwriteable
= lp_hide_unwriteable_files(SNUM(fsp
->conn
));
935 hide_special
= lp_hide_special_files(SNUM(fsp
->conn
));
936 hide_new_files_timeout
= lp_hide_new_files_timeout(SNUM(fsp
->conn
));
938 if (!hide_unreadable
&&
941 (hide_new_files_timeout
== 0))
946 fsp
= metadata_fsp(fsp
);
948 /* Get the last component of the base name. */
949 last_component
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
950 if (!last_component
) {
951 last_component
= fsp
->fsp_name
->base_name
;
953 last_component
++; /* Go past '/' */
956 if (ISDOT(last_component
) || ISDOTDOT(last_component
)) {
957 return true; /* . and .. are always visible. */
960 if (fsp_get_pathref_fd(fsp
) == -1) {
962 * Symlink in POSIX mode or MS-DFS.
963 * We've checked veto files so the
964 * only thing we can check is the
965 * hide_new_files_timeout.
967 if ((hide_new_files_timeout
!= 0) &&
968 !S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
969 double age
= timespec_elapsed(
970 &fsp
->fsp_name
->st
.st_ex_mtime
);
972 if (age
< (double)hide_new_files_timeout
) {
979 /* Honour _hide unreadable_ option */
980 if (hide_unreadable
&& !user_can_read_fsp(fsp
)) {
981 DBG_DEBUG("file %s is unreadable.\n", fsp_str_dbg(fsp
));
985 /* Honour _hide unwriteable_ option */
986 if (hide_unwriteable
&& !user_can_write_fsp(fsp
)) {
987 DBG_DEBUG("file %s is unwritable.\n", fsp_str_dbg(fsp
));
991 /* Honour _hide_special_ option */
992 if (hide_special
&& file_is_special(fsp
->conn
, fsp
->fsp_name
)) {
993 DBG_DEBUG("file %s is special.\n", fsp_str_dbg(fsp
));
997 if ((hide_new_files_timeout
!= 0) &&
998 !S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
999 double age
= timespec_elapsed(&fsp
->fsp_name
->st
.st_ex_mtime
);
1001 if (age
< (double)hide_new_files_timeout
) {
1009 static int smb_Dir_destructor(struct smb_Dir
*dir_hnd
)
1011 files_struct
*fsp
= dir_hnd
->fsp
;
1013 SMB_VFS_CLOSEDIR(dir_hnd
->conn
, dir_hnd
->dir
);
1014 fsp_set_fd(fsp
, -1);
1015 if (fsp
->dptr
!= NULL
) {
1016 SMB_ASSERT(fsp
->dptr
->dir_hnd
== dir_hnd
);
1017 fsp
->dptr
->dir_hnd
= NULL
;
1019 dir_hnd
->fsp
= NULL
;
1023 /*******************************************************************
1025 ********************************************************************/
1027 static int smb_Dir_OpenDir_destructor(struct smb_Dir
*dir_hnd
)
1029 files_struct
*fsp
= dir_hnd
->fsp
;
1031 smb_Dir_destructor(dir_hnd
);
1032 file_free(NULL
, fsp
);
1036 NTSTATUS
OpenDir(TALLOC_CTX
*mem_ctx
,
1037 connection_struct
*conn
,
1038 const struct smb_filename
*smb_dname
,
1041 struct smb_Dir
**_dir_hnd
)
1043 struct files_struct
*fsp
= NULL
;
1044 struct smb_Dir
*dir_hnd
= NULL
;
1047 status
= open_internal_dirfsp(conn
,
1051 if (!NT_STATUS_IS_OK(status
)) {
1055 status
= OpenDir_fsp(mem_ctx
, conn
, fsp
, mask
, attr
, &dir_hnd
);
1056 if (!NT_STATUS_IS_OK(status
)) {
1061 * This overwrites the destructor set by OpenDir_fsp() but
1062 * smb_Dir_OpenDir_destructor() calls the OpenDir_fsp()
1065 talloc_set_destructor(dir_hnd
, smb_Dir_OpenDir_destructor
);
1067 *_dir_hnd
= dir_hnd
;
1068 return NT_STATUS_OK
;
1071 NTSTATUS
OpenDir_from_pathref(TALLOC_CTX
*mem_ctx
,
1072 struct files_struct
*dirfsp
,
1075 struct smb_Dir
**_dir_hnd
)
1077 struct files_struct
*fsp
= NULL
;
1078 struct smb_Dir
*dir_hnd
= NULL
;
1081 status
= openat_internal_dir_from_pathref(dirfsp
, O_RDONLY
, &fsp
);
1082 if (!NT_STATUS_IS_OK(status
)) {
1086 status
= OpenDir_fsp(mem_ctx
, fsp
->conn
, fsp
, mask
, attr
, &dir_hnd
);
1087 if (!NT_STATUS_IS_OK(status
)) {
1092 * This overwrites the destructor set by OpenDir_fsp() but
1093 * smb_Dir_OpenDir_destructor() calls the OpenDir_fsp()
1096 talloc_set_destructor(dir_hnd
, smb_Dir_OpenDir_destructor
);
1098 *_dir_hnd
= dir_hnd
;
1099 return NT_STATUS_OK
;
1102 /*******************************************************************
1103 Open a directory from an fsp.
1104 ********************************************************************/
1106 static NTSTATUS
OpenDir_fsp(
1107 TALLOC_CTX
*mem_ctx
,
1108 connection_struct
*conn
,
1112 struct smb_Dir
**_dir_hnd
)
1114 struct smb_Dir
*dir_hnd
= talloc_zero(mem_ctx
, struct smb_Dir
);
1118 return NT_STATUS_NO_MEMORY
;
1121 if (!fsp
->fsp_flags
.is_directory
) {
1122 status
= NT_STATUS_INVALID_HANDLE
;
1126 if (fsp_get_io_fd(fsp
) == -1) {
1127 status
= NT_STATUS_INVALID_HANDLE
;
1131 dir_hnd
->conn
= conn
;
1133 dir_hnd
->dir_smb_fname
= cp_smb_filename(dir_hnd
, fsp
->fsp_name
);
1134 if (!dir_hnd
->dir_smb_fname
) {
1135 status
= NT_STATUS_NO_MEMORY
;
1139 dir_hnd
->dir
= SMB_VFS_FDOPENDIR(fsp
, mask
, attr
);
1140 if (dir_hnd
->dir
== NULL
) {
1141 status
= map_nt_error_from_unix(errno
);
1145 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_OPEN
) {
1146 dir_hnd
->case_sensitive
= true;
1148 dir_hnd
->case_sensitive
= conn
->case_sensitive
;
1151 talloc_set_destructor(dir_hnd
, smb_Dir_destructor
);
1153 *_dir_hnd
= dir_hnd
;
1154 return NT_STATUS_OK
;
1157 TALLOC_FREE(dir_hnd
);
1162 /*******************************************************************
1163 Read from a directory.
1164 Return directory entry, current offset, and optional stat information.
1165 Don't check for veto or invisible files.
1166 ********************************************************************/
1168 const char *ReadDirName(struct smb_Dir
*dir_hnd
, char **ptalloced
)
1171 char *talloced
= NULL
;
1172 connection_struct
*conn
= dir_hnd
->conn
;
1174 if (dir_hnd
->file_number
< 2) {
1175 if (dir_hnd
->file_number
== 0) {
1180 dir_hnd
->file_number
++;
1185 while ((n
= vfs_readdirname(conn
,
1189 int unlink_flags
= INT_MAX
;
1190 /* Ignore . and .. - we've already returned them. */
1191 if (ISDOT(n
) || ISDOTDOT(n
)) {
1192 TALLOC_FREE(talloced
);
1196 * ignore tmp directories, see mkdir_internals()
1198 if (IS_SMBD_TMPNAME(n
, &unlink_flags
)) {
1199 struct smb_filename
*atname
= NULL
;
1200 const char *fp
= NULL
;
1203 atname
= synthetic_smb_fname(talloc_tos(),
1209 if (atname
== NULL
) {
1210 TALLOC_FREE(talloced
);
1213 fp
= full_path_from_dirfsp_at_basename(atname
,
1217 TALLOC_FREE(atname
);
1218 TALLOC_FREE(talloced
);
1222 if (unlink_flags
== INT_MAX
) {
1223 DBG_NOTICE("ignoring %s\n", fp
);
1224 TALLOC_FREE(atname
);
1225 TALLOC_FREE(talloced
);
1230 * We remove the stale tmpname
1231 * as root and ignore any errors
1233 DBG_NOTICE("unlink stale %s\n", fp
);
1235 ret
= SMB_VFS_UNLINKAT(conn
,
1241 DBG_NOTICE("unlinked stale %s\n", fp
);
1243 DBG_WARNING("failed to unlink stale %s: %s\n",
1244 fp
, strerror(errno
));
1246 TALLOC_FREE(atname
);
1247 TALLOC_FREE(talloced
);
1250 *ptalloced
= talloced
;
1251 dir_hnd
->file_number
++;
1258 /*******************************************************************
1259 Rewind to the start.
1260 ********************************************************************/
1262 void RewindDir(struct smb_Dir
*dir_hnd
)
1264 SMB_VFS_REWINDDIR(dir_hnd
->conn
, dir_hnd
->dir
);
1265 dir_hnd
->file_number
= 0;
1268 struct files_below_forall_state
{
1270 ssize_t dirpath_len
;
1271 int (*fn
)(struct file_id fid
, const struct share_mode_data
*data
,
1272 void *private_data
);
1276 static int files_below_forall_fn(struct file_id fid
,
1277 const struct share_mode_data
*data
,
1280 struct files_below_forall_state
*state
= private_data
;
1281 char tmpbuf
[PATH_MAX
];
1282 char *fullpath
, *to_free
;
1285 len
= full_path_tos(data
->servicepath
, data
->base_name
,
1286 tmpbuf
, sizeof(tmpbuf
),
1287 &fullpath
, &to_free
);
1291 if (state
->dirpath_len
>= len
) {
1293 * Filter files above dirpath
1297 if (fullpath
[state
->dirpath_len
] != '/') {
1299 * Filter file that don't have a path separator at the end of
1305 if (memcmp(state
->dirpath
, fullpath
, state
->dirpath_len
) != 0) {
1312 TALLOC_FREE(to_free
);
1313 return state
->fn(fid
, data
, state
->private_data
);
1316 TALLOC_FREE(to_free
);
1320 static int files_below_forall(connection_struct
*conn
,
1321 const struct smb_filename
*dir_name
,
1322 int (*fn
)(struct file_id fid
,
1323 const struct share_mode_data
*data
,
1324 void *private_data
),
1327 struct files_below_forall_state state
= {
1329 .private_data
= private_data
,
1332 char tmpbuf
[PATH_MAX
];
1335 state
.dirpath_len
= full_path_tos(conn
->connectpath
,
1336 dir_name
->base_name
,
1337 tmpbuf
, sizeof(tmpbuf
),
1338 &state
.dirpath
, &to_free
);
1339 if (state
.dirpath_len
== -1) {
1343 ret
= share_mode_forall(files_below_forall_fn
, &state
);
1344 TALLOC_FREE(to_free
);
1348 struct have_file_open_below_state
{
1352 static int have_file_open_below_fn(struct file_id fid
,
1353 const struct share_mode_data
*data
,
1356 struct have_file_open_below_state
*state
= private_data
;
1357 state
->found_one
= true;
1361 bool have_file_open_below(connection_struct
*conn
,
1362 const struct smb_filename
*name
)
1364 struct have_file_open_below_state state
= {
1369 if (!VALID_STAT(name
->st
)) {
1372 if (!S_ISDIR(name
->st
.st_ex_mode
)) {
1376 ret
= files_below_forall(conn
, name
, have_file_open_below_fn
, &state
);
1381 return state
.found_one
;
1384 /*****************************************************************
1385 Is this directory empty ?
1386 *****************************************************************/
1388 NTSTATUS
can_delete_directory_fsp(files_struct
*fsp
)
1390 NTSTATUS status
= NT_STATUS_OK
;
1391 const char *dname
= NULL
;
1392 char *talloced
= NULL
;
1393 struct connection_struct
*conn
= fsp
->conn
;
1394 struct smb_Dir
*dir_hnd
= NULL
;
1397 talloc_tos(), conn
, fsp
->fsp_name
, NULL
, 0, &dir_hnd
);
1398 if (!NT_STATUS_IS_OK(status
)) {
1402 while ((dname
= ReadDirName(dir_hnd
, &talloced
))) {
1403 struct smb_filename
*smb_dname_full
= NULL
;
1404 struct smb_filename
*direntry_fname
= NULL
;
1405 char *fullname
= NULL
;
1408 if (ISDOT(dname
) || (ISDOTDOT(dname
))) {
1409 TALLOC_FREE(talloced
);
1412 if (IS_VETO_PATH(conn
, dname
)) {
1413 TALLOC_FREE(talloced
);
1417 fullname
= talloc_asprintf(talloc_tos(),
1419 fsp
->fsp_name
->base_name
,
1421 if (fullname
== NULL
) {
1422 status
= NT_STATUS_NO_MEMORY
;
1426 smb_dname_full
= synthetic_smb_fname(talloc_tos(),
1430 fsp
->fsp_name
->twrp
,
1431 fsp
->fsp_name
->flags
);
1432 if (smb_dname_full
== NULL
) {
1433 TALLOC_FREE(talloced
);
1434 TALLOC_FREE(fullname
);
1435 status
= NT_STATUS_NO_MEMORY
;
1439 ret
= SMB_VFS_LSTAT(conn
, smb_dname_full
);
1441 status
= map_nt_error_from_unix(errno
);
1442 TALLOC_FREE(talloced
);
1443 TALLOC_FREE(fullname
);
1444 TALLOC_FREE(smb_dname_full
);
1448 if (S_ISLNK(smb_dname_full
->st
.st_ex_mode
)) {
1449 /* Could it be an msdfs link ? */
1450 if (lp_host_msdfs() &&
1451 lp_msdfs_root(SNUM(conn
))) {
1452 struct smb_filename
*smb_dname
;
1453 smb_dname
= synthetic_smb_fname(talloc_tos(),
1456 &smb_dname_full
->st
,
1457 fsp
->fsp_name
->twrp
,
1458 fsp
->fsp_name
->flags
);
1459 if (smb_dname
== NULL
) {
1460 TALLOC_FREE(talloced
);
1461 TALLOC_FREE(fullname
);
1462 TALLOC_FREE(smb_dname_full
);
1463 status
= NT_STATUS_NO_MEMORY
;
1466 if (is_msdfs_link(fsp
, smb_dname
)) {
1467 TALLOC_FREE(talloced
);
1468 TALLOC_FREE(fullname
);
1469 TALLOC_FREE(smb_dname_full
);
1470 TALLOC_FREE(smb_dname
);
1471 DBG_DEBUG("got msdfs link name %s "
1472 "- can't delete directory %s\n",
1475 status
= NT_STATUS_DIRECTORY_NOT_EMPTY
;
1478 TALLOC_FREE(smb_dname
);
1480 /* Not a DFS link - could it be a dangling symlink ? */
1481 ret
= SMB_VFS_STAT(conn
, smb_dname_full
);
1482 if (ret
== -1 && (errno
== ENOENT
|| errno
== ELOOP
)) {
1485 * Allow if "delete veto files = yes"
1487 if (lp_delete_veto_files(SNUM(conn
))) {
1488 TALLOC_FREE(talloced
);
1489 TALLOC_FREE(fullname
);
1490 TALLOC_FREE(smb_dname_full
);
1494 DBG_DEBUG("got symlink name %s - "
1495 "can't delete directory %s\n",
1498 TALLOC_FREE(talloced
);
1499 TALLOC_FREE(fullname
);
1500 TALLOC_FREE(smb_dname_full
);
1501 status
= NT_STATUS_DIRECTORY_NOT_EMPTY
;
1505 /* Not a symlink, get a pathref. */
1506 status
= synthetic_pathref(talloc_tos(),
1510 &smb_dname_full
->st
,
1511 fsp
->fsp_name
->twrp
,
1512 fsp
->fsp_name
->flags
,
1514 if (!NT_STATUS_IS_OK(status
)) {
1515 status
= map_nt_error_from_unix(errno
);
1516 TALLOC_FREE(talloced
);
1517 TALLOC_FREE(fullname
);
1518 TALLOC_FREE(smb_dname_full
);
1522 if (!is_visible_fsp(direntry_fname
->fsp
)) {
1525 * Allow if "delete veto files = yes"
1527 if (lp_delete_veto_files(SNUM(conn
))) {
1528 TALLOC_FREE(talloced
);
1529 TALLOC_FREE(fullname
);
1530 TALLOC_FREE(smb_dname_full
);
1531 TALLOC_FREE(direntry_fname
);
1536 TALLOC_FREE(talloced
);
1537 TALLOC_FREE(fullname
);
1538 TALLOC_FREE(smb_dname_full
);
1539 TALLOC_FREE(direntry_fname
);
1541 DBG_DEBUG("got name %s - can't delete\n", dname
);
1542 status
= NT_STATUS_DIRECTORY_NOT_EMPTY
;
1545 TALLOC_FREE(talloced
);
1546 TALLOC_FREE(dir_hnd
);
1548 if (!NT_STATUS_IS_OK(status
)) {
1552 if (!(fsp
->posix_flags
& FSP_POSIX_FLAGS_RENAME
) &&
1553 lp_strict_rename(SNUM(conn
)) &&
1554 have_file_open_below(fsp
->conn
, fsp
->fsp_name
))
1556 return NT_STATUS_ACCESS_DENIED
;
1559 return NT_STATUS_OK
;