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
;
71 struct connection_struct
*conn
;
72 struct smb_Dir
*dir_hnd
;
76 struct smb_filename
*smb_dname
;
77 bool has_wild
; /* Set to true if the wcard entry has MS wildcard characters in it. */
78 bool did_stat
; /* Optimisation for non-wcard searches. */
79 bool priv
; /* Directory handle opened with privilege. */
81 struct memcache
*dptr_cache
;
84 static NTSTATUS
OpenDir_fsp(
86 connection_struct
*conn
,
90 struct smb_Dir
**_dir_hnd
);
92 static void DirCacheAdd(struct smb_Dir
*dir_hnd
, const char *name
, long offset
);
94 static int smb_Dir_destructor(struct smb_Dir
*dir_hnd
);
96 static bool SearchDir(struct smb_Dir
*dir_hnd
, const char *name
, long *poffset
);
98 #define INVALID_DPTR_KEY (-3)
100 /****************************************************************************
101 Initialise the dir bitmap.
102 ****************************************************************************/
104 bool init_dptrs(struct smbd_server_connection
*sconn
)
106 if (sconn
->searches
.dptr_bmap
) {
110 sconn
->searches
.dptr_bmap
= bitmap_talloc(
111 sconn
, MAX_DIRECTORY_HANDLES
);
113 if (sconn
->searches
.dptr_bmap
== NULL
) {
120 /****************************************************************************
121 Get the struct dptr_struct for a dir index.
122 ****************************************************************************/
124 static struct dptr_struct
*dptr_get(struct smbd_server_connection
*sconn
,
127 struct dptr_struct
*dptr
;
129 for (dptr
= sconn
->searches
.dirptrs
; dptr
!= NULL
; dptr
= dptr
->next
) {
130 if(dptr
->dnum
!= key
) {
133 DLIST_PROMOTE(sconn
->searches
.dirptrs
, dptr
);
139 /****************************************************************************
140 Get the dir path for a dir index.
141 ****************************************************************************/
143 const char *dptr_path(struct smbd_server_connection
*sconn
, int key
)
145 struct dptr_struct
*dptr
= dptr_get(sconn
, key
);
147 return(dptr
->smb_dname
->base_name
);
151 /****************************************************************************
152 Get the dir wcard for a dir index.
153 ****************************************************************************/
155 const char *dptr_wcard(struct smbd_server_connection
*sconn
, int key
)
157 struct dptr_struct
*dptr
= dptr_get(sconn
, key
);
163 /****************************************************************************
164 Get the dir attrib for a dir index.
165 ****************************************************************************/
167 uint16_t dptr_attr(struct smbd_server_connection
*sconn
, int key
)
169 struct dptr_struct
*dptr
= dptr_get(sconn
, key
);
175 /****************************************************************************
176 Close all dptrs for a cnum.
177 ****************************************************************************/
179 void dptr_closecnum(connection_struct
*conn
)
181 struct dptr_struct
*dptr
, *next
;
182 struct smbd_server_connection
*sconn
= conn
->sconn
;
188 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= next
) {
190 if (dptr
->conn
== conn
) {
192 * Need to make a copy, "dptr" will be gone
193 * after close_file_free() returns
195 struct files_struct
*fsp
= dptr
->dir_hnd
->fsp
;
196 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
201 /****************************************************************************
202 Create a new dir ptr. If the flag old_handle is true then we must allocate
203 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
204 one byte long. If old_handle is false we allocate from the range
205 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
206 a directory handle is never zero.
207 wcard must not be zero.
208 ****************************************************************************/
210 NTSTATUS
dptr_create(connection_struct
*conn
,
211 struct smb_request
*req
,
218 struct dptr_struct
**dptr_ret
)
220 struct smbd_server_connection
*sconn
= conn
->sconn
;
221 struct dptr_struct
*dptr
= NULL
;
222 struct smb_Dir
*dir_hnd
= NULL
;
225 DBG_INFO("dir=%s\n", fsp_str_dbg(fsp
));
228 DEBUG(0,("dptr_create: called with fake connection_struct\n"));
229 return NT_STATUS_INTERNAL_ERROR
;
233 return NT_STATUS_INVALID_PARAMETER
;
236 if (!(fsp
->access_mask
& SEC_DIR_LIST
)) {
237 DBG_INFO("dptr_create: directory %s "
238 "not open for LIST access\n",
240 return NT_STATUS_ACCESS_DENIED
;
242 status
= OpenDir_fsp(NULL
, conn
, fsp
, wcard
, attr
, &dir_hnd
);
243 if (!NT_STATUS_IS_OK(status
)) {
247 dptr
= talloc_zero(NULL
, struct dptr_struct
);
249 DEBUG(0,("talloc fail in dptr_create.\n"));
250 TALLOC_FREE(dir_hnd
);
251 return NT_STATUS_NO_MEMORY
;
254 dptr
->smb_dname
= cp_smb_filename(dptr
, fsp
->fsp_name
);
255 if (dptr
->smb_dname
== NULL
) {
257 TALLOC_FREE(dir_hnd
);
258 return NT_STATUS_NO_MEMORY
;
261 dptr
->dir_hnd
= dir_hnd
;
263 dptr
->expect_close
= expect_close
;
264 dptr
->wcard
= talloc_strdup(dptr
, wcard
);
267 TALLOC_FREE(dir_hnd
);
268 return NT_STATUS_NO_MEMORY
;
270 if ((req
!= NULL
&& req
->posix_pathnames
) ||
271 (wcard
[0] == '.' && wcard
[1] == 0)) {
272 dptr
->has_wild
= True
;
274 dptr
->has_wild
= ms_has_wild(dptr
->wcard
);
279 if (sconn
->using_smb2
) {
286 * This is an old-style SMBsearch request. Ensure the
287 * value we return will fit in the range 1-255.
290 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 0);
292 if(dptr
->dnum
== -1 || dptr
->dnum
> 254) {
293 DBG_ERR("returned %d: Error - all old "
294 "dirptrs in use ?\n",
297 TALLOC_FREE(dir_hnd
);
298 return NT_STATUS_TOO_MANY_OPENED_FILES
;
303 * This is a new-style trans2 request. Allocate from
304 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
307 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 255);
309 if(dptr
->dnum
== -1 || dptr
->dnum
< 255) {
310 DBG_ERR("returned %d: Error - all new "
311 "dirptrs in use ?\n",
314 TALLOC_FREE(dir_hnd
);
315 return NT_STATUS_TOO_MANY_OPENED_FILES
;
319 bitmap_set(sconn
->searches
.dptr_bmap
, dptr
->dnum
);
321 dptr
->dnum
+= 1; /* Always bias the dnum by one - no zero dnums allowed. */
323 DLIST_ADD(sconn
->searches
.dirptrs
, dptr
);
326 DBG_INFO("creating new dirptr [%d] for path [%s], expect_close = %d\n",
327 dptr
->dnum
, fsp_str_dbg(fsp
), expect_close
);
335 /****************************************************************************
336 Wrapper functions to access the lower level directory handles.
337 ****************************************************************************/
339 void dptr_CloseDir(files_struct
*fsp
)
341 struct smbd_server_connection
*sconn
= NULL
;
343 if (fsp
->dptr
== NULL
) {
346 sconn
= fsp
->dptr
->conn
->sconn
;
349 * The destructor for the struct smb_Dir (fsp->dptr->dir_hnd)
350 * now handles all resource deallocation.
353 DBG_INFO("closing dptr key %d\n", fsp
->dptr
->dnum
);
355 if (sconn
!= NULL
&& !sconn
->using_smb2
) {
356 DLIST_REMOVE(sconn
->searches
.dirptrs
, fsp
->dptr
);
359 * Free the dnum in the bitmap. Remember the dnum value is
360 * always biased by one with respect to the bitmap.
363 if (!bitmap_query(sconn
->searches
.dptr_bmap
,
364 fsp
->dptr
->dnum
- 1))
366 DBG_ERR("closing dnum = %d and bitmap not set !\n",
370 bitmap_clear(sconn
->searches
.dptr_bmap
, fsp
->dptr
->dnum
- 1);
373 TALLOC_FREE(fsp
->dptr
->dir_hnd
);
374 TALLOC_FREE(fsp
->dptr
);
377 void dptr_SeekDir(struct dptr_struct
*dptr
, long offset
)
379 SeekDir(dptr
->dir_hnd
, offset
);
382 long dptr_TellDir(struct dptr_struct
*dptr
)
384 return TellDir(dptr
->dir_hnd
);
387 bool dptr_has_wild(struct dptr_struct
*dptr
)
389 return dptr
->has_wild
;
392 int dptr_dnum(struct dptr_struct
*dptr
)
397 bool dptr_get_priv(struct dptr_struct
*dptr
)
402 void dptr_set_priv(struct dptr_struct
*dptr
)
407 bool dptr_case_sensitive(struct dptr_struct
*dptr
)
409 return dptr
->dir_hnd
->case_sensitive
;
412 /****************************************************************************
413 Return the next visible file name, skipping veto'd and invisible files.
414 ****************************************************************************/
416 static char *dptr_ReadDirName(TALLOC_CTX
*ctx
,
417 struct dptr_struct
*dptr
,
419 SMB_STRUCT_STAT
*pst
)
421 struct smb_filename smb_fname_base
;
423 const char *name_temp
= NULL
;
424 char *talloced
= NULL
;
425 char *pathreal
= NULL
;
426 char *found_name
= NULL
;
429 SET_STAT_INVALID(*pst
);
431 if (dptr
->has_wild
|| dptr
->did_stat
) {
432 name_temp
= ReadDirName(dptr
->dir_hnd
, poffset
, pst
,
434 if (name_temp
== NULL
) {
437 if (talloced
!= NULL
) {
438 return talloc_move(ctx
, &talloced
);
440 return talloc_strdup(ctx
, name_temp
);
443 /* If poffset is -1 then we know we returned this name before and we
444 * have no wildcards. We're at the end of the directory. */
445 if (*poffset
== END_OF_DIRECTORY_OFFSET
) {
449 /* We know the stored wcard contains no wildcard characters.
450 * See if we can match with a stat call. If we can't, then set
451 * did_stat to true to ensure we only do this once and keep
454 dptr
->did_stat
= true;
456 if (VALID_STAT(*pst
)) {
457 name
= talloc_strdup(ctx
, dptr
->wcard
);
461 pathreal
= talloc_asprintf(ctx
,
463 dptr
->smb_dname
->base_name
,
468 /* Create an smb_filename with stream_name == NULL. */
469 smb_fname_base
= (struct smb_filename
) {
470 .base_name
= pathreal
,
471 .flags
= dptr
->dir_hnd
->fsp
->fsp_name
->flags
,
472 .twrp
= dptr
->smb_dname
->twrp
,
475 if (vfs_stat(dptr
->conn
, &smb_fname_base
) == 0) {
476 *pst
= smb_fname_base
.st
;
477 name
= talloc_strdup(ctx
, dptr
->wcard
);
480 /* If we get any other error than ENOENT or ENOTDIR
481 then the file exists we just can't stat it. */
482 if (errno
!= ENOENT
&& errno
!= ENOTDIR
) {
483 name
= talloc_strdup(ctx
, dptr
->wcard
);
488 /* Stat failed. We know this is authoritative if we are
489 * providing case sensitive semantics or the underlying
490 * filesystem is case sensitive.
492 if (dptr
->dir_hnd
->case_sensitive
||
493 !(dptr
->conn
->fs_capabilities
& FILE_CASE_SENSITIVE_SEARCH
))
499 * Try case-insensitive stat if the fs has the ability. This avoids
500 * scanning the whole directory.
502 status
= SMB_VFS_GET_REAL_FILENAME_AT(dptr
->conn
,
507 if (NT_STATUS_IS_OK(status
)) {
511 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
512 /* The case-insensitive lookup was authoritative. */
516 TALLOC_FREE(pathreal
);
518 name_temp
= ReadDirName(dptr
->dir_hnd
, poffset
, pst
, &talloced
);
519 if (name_temp
== NULL
) {
522 if (talloced
!= NULL
) {
523 return talloc_move(ctx
, &talloced
);
525 return talloc_strdup(ctx
, name_temp
);
528 TALLOC_FREE(pathreal
);
530 /* We need to set the underlying dir_hnd offset to -1
531 * also as this function is usually called with the
532 * output from TellDir. */
533 dptr
->dir_hnd
->offset
= *poffset
= END_OF_DIRECTORY_OFFSET
;
537 /****************************************************************************
538 Search for a file by name.
539 ****************************************************************************/
541 bool dptr_SearchDir(struct dptr_struct
*dptr
, const char *name
, long *poffset
, SMB_STRUCT_STAT
*pst
)
543 SET_STAT_INVALID(*pst
);
545 if (!dptr
->has_wild
&& (dptr
->dir_hnd
->offset
== END_OF_DIRECTORY_OFFSET
)) {
546 /* This is a singleton directory and we're already at the end. */
547 *poffset
= END_OF_DIRECTORY_OFFSET
;
551 return SearchDir(dptr
->dir_hnd
, name
, poffset
);
554 /****************************************************************************
555 Map a native directory offset to a 32-bit cookie.
556 ****************************************************************************/
558 static uint32_t map_dir_offset_to_wire(struct dptr_struct
*dptr
, long offset
)
563 if (offset
== END_OF_DIRECTORY_OFFSET
) {
564 return WIRE_END_OF_DIRECTORY_OFFSET
;
566 if (offset
== START_OF_DIRECTORY_OFFSET
) {
567 return WIRE_START_OF_DIRECTORY_OFFSET
;
569 if (offset
== DOT_DOT_DIRECTORY_OFFSET
) {
570 return WIRE_DOT_DOT_DIRECTORY_OFFSET
;
572 if (sizeof(long) == 4) {
573 /* 32-bit machine. We can cheat... */
574 return (uint32_t)offset
;
576 if (dptr
->dptr_cache
== NULL
) {
577 /* Lazy initialize cache. */
578 dptr
->dptr_cache
= memcache_init(dptr
, 0);
579 if (dptr
->dptr_cache
== NULL
) {
580 return WIRE_END_OF_DIRECTORY_OFFSET
;
583 /* Have we seen this offset before ? */
584 key
.data
= (void *)&offset
;
585 key
.length
= sizeof(offset
);
586 if (memcache_lookup(dptr
->dptr_cache
,
587 SMB1_SEARCH_OFFSET_MAP
,
590 uint32_t wire_offset
;
591 SMB_ASSERT(val
.length
== sizeof(wire_offset
));
592 memcpy(&wire_offset
, val
.data
, sizeof(wire_offset
));
593 DEBUG(10,("found wire %u <-> offset %ld\n",
594 (unsigned int)wire_offset
,
599 /* Allocate a new wire cookie. */
602 } while (dptr
->counter
== WIRE_START_OF_DIRECTORY_OFFSET
||
603 dptr
->counter
== WIRE_END_OF_DIRECTORY_OFFSET
||
604 dptr
->counter
== WIRE_DOT_DOT_DIRECTORY_OFFSET
);
605 /* Store it in the cache. */
606 key
.data
= (void *)&offset
;
607 key
.length
= sizeof(offset
);
608 val
.data
= (void *)&dptr
->counter
;
609 val
.length
= sizeof(dptr
->counter
); /* MUST BE uint32_t ! */
610 memcache_add(dptr
->dptr_cache
,
611 SMB1_SEARCH_OFFSET_MAP
,
614 /* And the reverse mapping for lookup from
615 map_wire_to_dir_offset(). */
616 memcache_add(dptr
->dptr_cache
,
617 SMB1_SEARCH_OFFSET_MAP
,
620 DEBUG(10,("stored wire %u <-> offset %ld\n",
621 (unsigned int)dptr
->counter
,
623 return dptr
->counter
;
626 /****************************************************************************
627 Fill the 5 byte server reserved dptr field.
628 ****************************************************************************/
630 bool dptr_fill(struct smbd_server_connection
*sconn
,
631 char *buf1
,unsigned int key
)
633 unsigned char *buf
= (unsigned char *)buf1
;
634 struct dptr_struct
*dptr
= dptr_get(sconn
, key
);
635 uint32_t wire_offset
;
637 DEBUG(1,("filling null dirptr %d\n",key
));
640 wire_offset
= map_dir_offset_to_wire(dptr
,TellDir(dptr
->dir_hnd
));
641 DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key
,
642 (long)dptr
->dir_hnd
,(int)wire_offset
));
644 SIVAL(buf
,1,wire_offset
);
648 /****************************************************************************
649 Map a 32-bit wire cookie to a native directory offset.
650 ****************************************************************************/
652 static long map_wire_to_dir_offset(struct dptr_struct
*dptr
, uint32_t wire_offset
)
657 if (wire_offset
== WIRE_END_OF_DIRECTORY_OFFSET
) {
658 return END_OF_DIRECTORY_OFFSET
;
659 } else if(wire_offset
== WIRE_START_OF_DIRECTORY_OFFSET
) {
660 return START_OF_DIRECTORY_OFFSET
;
661 } else if (wire_offset
== WIRE_DOT_DOT_DIRECTORY_OFFSET
) {
662 return DOT_DOT_DIRECTORY_OFFSET
;
664 if (sizeof(long) == 4) {
665 /* 32-bit machine. We can cheat... */
666 return (long)wire_offset
;
668 if (dptr
->dptr_cache
== NULL
) {
669 /* Logic error, cache should be initialized. */
670 return END_OF_DIRECTORY_OFFSET
;
672 key
.data
= (void *)&wire_offset
;
673 key
.length
= sizeof(wire_offset
);
674 if (memcache_lookup(dptr
->dptr_cache
,
675 SMB1_SEARCH_OFFSET_MAP
,
680 SMB_ASSERT(val
.length
== sizeof(offset
));
681 memcpy(&offset
, val
.data
, sizeof(offset
));
682 DEBUG(10,("lookup wire %u <-> offset %ld\n",
683 (unsigned int)wire_offset
,
687 return END_OF_DIRECTORY_OFFSET
;
690 /****************************************************************************
691 Return the associated fsp and seek the dir_hnd on it it given the 5 byte
693 ****************************************************************************/
695 files_struct
*dptr_fetch_fsp(struct smbd_server_connection
*sconn
,
698 unsigned int key
= *(unsigned char *)buf
;
699 struct dptr_struct
*dptr
= dptr_get(sconn
, key
);
700 uint32_t wire_offset
;
704 DEBUG(3,("fetched null dirptr %d\n",key
));
708 wire_offset
= IVAL(buf
,1);
709 seekoff
= map_wire_to_dir_offset(dptr
, wire_offset
);
710 SeekDir(dptr
->dir_hnd
,seekoff
);
711 DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
712 key
, dptr
->smb_dname
->base_name
, (int)seekoff
));
713 return dptr
->dir_hnd
->fsp
;
716 struct files_struct
*dir_hnd_fetch_fsp(struct smb_Dir
*dir_hnd
)
721 /****************************************************************************
722 Fetch the fsp associated with the dptr_num.
723 ****************************************************************************/
725 files_struct
*dptr_fetch_lanman2_fsp(struct smbd_server_connection
*sconn
,
728 struct dptr_struct
*dptr
= dptr_get(sconn
, dptr_num
);
732 DBG_NOTICE("fetching dirptr %d for path %s\n",
734 dptr
->smb_dname
->base_name
);
735 return dptr
->dir_hnd
->fsp
;
738 static bool mangle_mask_match(connection_struct
*conn
,
739 const char *filename
,
744 if (!name_to_8_3(filename
,mname
,False
,conn
->params
)) {
747 return mask_match_search(mname
,mask
,False
);
750 bool smbd_dirptr_get_entry(TALLOC_CTX
*ctx
,
751 struct dptr_struct
*dirptr
,
757 bool (*match_fn
)(TALLOC_CTX
*ctx
,
762 bool (*mode_fn
)(TALLOC_CTX
*ctx
,
764 struct files_struct
*dirfsp
,
765 struct smb_filename
*atname
,
766 struct smb_filename
*smb_fname
,
771 struct smb_filename
**_smb_fname
,
775 connection_struct
*conn
= dirptr
->conn
;
778 const char *dpath
= dirptr
->smb_dname
->base_name
;
779 bool dirptr_path_is_dot
= ISDOT(dpath
);
786 pathlen
= strlen(dpath
);
787 slashlen
= ( dpath
[pathlen
-1] != '/') ? 1 : 0;
792 SMB_STRUCT_STAT sbuf
= { 0 };
796 char *pathreal
= NULL
;
797 struct smb_filename
*atname
= NULL
;
798 struct smb_filename
*smb_fname
= NULL
;
800 bool check_dfs_symlink
= false;
801 bool get_dosmode
= get_dosmode_in
;
804 cur_offset
= dptr_TellDir(dirptr
);
805 prev_offset
= cur_offset
;
806 dname
= dptr_ReadDirName(ctx
, dirptr
, &cur_offset
, &sbuf
);
808 DBG_DEBUG("dir [%s] dirptr [0x%lx] offset [%ld] => dname [%s]\n",
809 smb_fname_str_dbg(dirptr
->smb_dname
), (long)dirptr
,
810 cur_offset
, dname
? dname
: "(finished)");
816 isdots
= (ISDOT(dname
) || ISDOTDOT(dname
));
817 if (dont_descend
&& !isdots
) {
822 if (IS_VETO_PATH(conn
, dname
)) {
828 * fname may get mangled, dname is never mangled.
829 * Whenever we're accessing the filesystem we use
830 * pathreal which is composed from dname.
833 ok
= match_fn(ctx
, private_data
, dname
, mask
, &fname
);
841 * pathreal = talloc_asprintf(ctx, "%s%s%s", dirptr->path,
842 * needslash?"/":"", dname);
843 * but this was measurably slower than doing the memcpy.
846 pathreal
= talloc_array(
848 pathlen
+ slashlen
+ talloc_get_size(dname
));
856 * We don't want to pass ./xxx to modules below us so don't
857 * add the path if it is just . by itself.
859 if (dirptr_path_is_dot
) {
860 memcpy(pathreal
, dname
, talloc_get_size(dname
));
862 memcpy(pathreal
, dpath
, pathlen
);
863 pathreal
[pathlen
] = '/';
864 memcpy(pathreal
+ slashlen
+ pathlen
, dname
,
865 talloc_get_size(dname
));
868 /* Create smb_fname with NULL stream_name. */
869 smb_fname
= synthetic_smb_fname(talloc_tos(),
873 dirptr
->smb_dname
->twrp
,
874 dirptr
->smb_dname
->flags
);
875 TALLOC_FREE(pathreal
);
876 if (smb_fname
== NULL
) {
882 if (!VALID_STAT(smb_fname
->st
)) {
884 * If stat() fails with ENOENT it might be a
885 * msdfs-symlink in Windows context, this is checked
886 * below, for now we just want to fill stat info as good
889 ret
= vfs_stat(conn
, smb_fname
);
890 if (ret
!= 0 && errno
!= ENOENT
) {
891 TALLOC_FREE(smb_fname
);
898 /* Create smb_fname with NULL stream_name. */
899 atname
= synthetic_smb_fname(talloc_tos(),
903 dirptr
->smb_dname
->twrp
,
904 dirptr
->smb_dname
->flags
);
905 if (atname
== NULL
) {
908 TALLOC_FREE(smb_fname
);
913 * openat_pathref_fsp() will return
914 * NT_STATUS_OBJECT_NAME_NOT_FOUND in non-POSIX context when
915 * hitting a dangling symlink. It may be a DFS symlink, this is
916 * checked below by the mode_fn() call, so we have to allow this
919 * NT_STATUS_STOPPED_ON_SYMLINK is returned in POSIX context
920 * when hitting a symlink and ensures we always return directory
921 * entries that are symlinks in POSIX context.
923 status
= openat_pathref_fsp(dirptr
->dir_hnd
->fsp
, atname
);
924 if (!NT_STATUS_IS_OK(status
) &&
925 !NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
))
930 TALLOC_FREE(smb_fname
);
934 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
935 if (!(atname
->flags
& SMB_FILENAME_POSIX_PATH
)) {
936 check_dfs_symlink
= true;
939 * Check if it's a symlink. We only want to return this
940 * if it's a DFS symlink or in POSIX mode. Disable
941 * getting dosmode in the mode_fn() and prime the mode
942 * as FILE_ATTRIBUTE_NORMAL.
944 mode
= FILE_ATTRIBUTE_NORMAL
;
948 status
= move_smb_fname_fsp_link(smb_fname
, atname
);
949 if (!NT_STATUS_IS_OK(status
)) {
950 DBG_WARNING("Failed to move pathref for [%s]: %s\n",
951 smb_fname_str_dbg(smb_fname
),
954 TALLOC_FREE(smb_fname
);
960 if (!is_visible_fsp(smb_fname
->fsp
)) {
962 TALLOC_FREE(smb_fname
);
969 * Don't leak metadata about the containing
970 * directory of the share.
972 if (dirptr_path_is_dot
&& ISDOTDOT(dname
)) {
974 * Making a copy here, then freeing
975 * the original will close the smb_fname->fsp.
977 struct smb_filename
*tmp_smb_fname
=
978 cp_smb_filename(ctx
, smb_fname
);
980 if (tmp_smb_fname
== NULL
) {
982 TALLOC_FREE(smb_fname
);
987 TALLOC_FREE(smb_fname
);
988 smb_fname
= tmp_smb_fname
;
989 mode
= FILE_ATTRIBUTE_DIRECTORY
;
995 dirptr
->dir_hnd
->fsp
,
1001 TALLOC_FREE(atname
);
1002 TALLOC_FREE(smb_fname
);
1008 TALLOC_FREE(atname
);
1011 * The only valid cases where we return the directory entry if
1012 * it's a symlink are:
1014 * 1. POSIX context, always return it, or
1016 * 2. a DFS symlink where the mode_fn() call above has verified
1017 * this and set mode to FILE_ATTRIBUTE_REPARSE_POINT.
1019 if (check_dfs_symlink
&&
1020 !(mode
& FILE_ATTRIBUTE_REPARSE_POINT
))
1022 TALLOC_FREE(smb_fname
);
1028 if (!dir_check_ftype(mode
, dirtype
)) {
1029 DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",
1030 fname
, (unsigned int)mode
, (unsigned int)dirtype
));
1031 TALLOC_FREE(smb_fname
);
1037 if (ask_sharemode
&& !S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1038 struct timespec write_time_ts
;
1039 struct file_id fileid
;
1041 fileid
= vfs_file_id_from_sbuf(conn
,
1043 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1044 if (!is_omit_timespec(&write_time_ts
)) {
1045 update_stat_ex_mtime(&smb_fname
->st
,
1050 DEBUG(3,("smbd_dirptr_get_entry mask=[%s] found %s "
1052 mask
, smb_fname_str_dbg(smb_fname
),
1055 if (!conn
->sconn
->using_smb2
) {
1057 * The dircache is only needed for SMB1 because SMB1
1058 * uses a name for the resume wheras SMB2 always
1059 * continues from the next position (unless it's told to
1060 * restart or close-and-reopen the listing).
1062 DirCacheAdd(dirptr
->dir_hnd
, dname
, cur_offset
);
1067 *_smb_fname
= talloc_move(ctx
, &smb_fname
);
1068 if (*_smb_fname
== NULL
) {
1073 *_prev_offset
= prev_offset
;
1081 /****************************************************************************
1082 Get an 8.3 directory entry.
1083 ****************************************************************************/
1085 static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX
*ctx
,
1091 connection_struct
*conn
= (connection_struct
*)private_data
;
1093 if ((strcmp(mask
,"*.*") == 0) ||
1094 mask_match_search(dname
, mask
, false) ||
1095 mangle_mask_match(conn
, dname
, mask
)) {
1099 * Ensure we can push the original name as UCS2. If
1100 * not, then just don't return this name.
1104 size_t len
= (strlen(dname
) + 2) * 4; /* Allow enough space. */
1105 uint8_t *tmp
= talloc_array(talloc_tos(),
1109 status
= srvstr_push(NULL
,
1110 FLAGS2_UNICODE_STRINGS
,
1119 if (!NT_STATUS_IS_OK(status
)) {
1123 if (!mangle_is_8_3(dname
, false, conn
->params
)) {
1124 bool ok
= name_to_8_3(dname
, mname
, false,
1134 *_fname
= talloc_strdup(ctx
, fname
);
1135 if (*_fname
== NULL
) {
1145 static bool smbd_dirptr_8_3_mode_fn(TALLOC_CTX
*ctx
,
1147 struct files_struct
*dirfsp
,
1148 struct smb_filename
*atname
,
1149 struct smb_filename
*smb_fname
,
1153 connection_struct
*conn
= (connection_struct
*)private_data
;
1155 if (!VALID_STAT(smb_fname
->st
)) {
1156 if ((SMB_VFS_STAT(conn
, smb_fname
)) != 0) {
1157 DEBUG(5,("smbd_dirptr_8_3_mode_fn: "
1158 "Couldn't stat [%s]. Error "
1160 smb_fname_str_dbg(smb_fname
),
1167 *_mode
= fdos_mode(smb_fname
->fsp
);
1168 smb_fname
->st
= smb_fname
->fsp
->fsp_name
->st
;
1173 bool get_dir_entry(TALLOC_CTX
*ctx
,
1174 struct dptr_struct
*dirptr
,
1180 struct timespec
*_date
,
1184 connection_struct
*conn
= dirptr
->conn
;
1186 struct smb_filename
*smb_fname
= NULL
;
1191 ok
= smbd_dirptr_get_entry(ctx
,
1198 smbd_dirptr_8_3_match_fn
,
1199 smbd_dirptr_8_3_mode_fn
,
1209 *_fname
= talloc_move(ctx
, &fname
);
1210 *_size
= smb_fname
->st
.st_ex_size
;
1212 *_date
= smb_fname
->st
.st_ex_mtime
;
1213 TALLOC_FREE(smb_fname
);
1217 /*******************************************************************
1218 Check to see if a user can read an fsp . This is only approximate,
1219 it is used as part of the "hide unreadable" option. Don't
1220 use it for anything security sensitive.
1221 ********************************************************************/
1223 static bool user_can_read_fsp(struct files_struct
*fsp
)
1226 uint32_t rejected_share_access
= 0;
1227 uint32_t rejected_mask
= 0;
1228 struct security_descriptor
*sd
= NULL
;
1229 uint32_t access_mask
= FILE_READ_DATA
|
1231 FILE_READ_ATTRIBUTES
|
1232 SEC_STD_READ_CONTROL
;
1235 * Never hide files from the root user.
1236 * We use (uid_t)0 here not sec_initial_uid()
1237 * as make test uses a single user context.
1240 if (get_current_uid(fsp
->conn
) == (uid_t
)0) {
1245 * We can't directly use smbd_check_access_rights_fsp()
1246 * here, as this implicitly grants FILE_READ_ATTRIBUTES
1247 * which the Windows access-based-enumeration code
1248 * explicitly checks for on the file security descriptor.
1251 * https://bugzilla.samba.org/show_bug.cgi?id=10252
1253 * and the smb2.acl2.ACCESSBASED test for details.
1256 rejected_share_access
= access_mask
& ~(fsp
->conn
->share_access
);
1257 if (rejected_share_access
) {
1258 DBG_DEBUG("rejected share access 0x%x "
1260 (unsigned int)access_mask
,
1262 (unsigned int)rejected_share_access
);
1266 status
= SMB_VFS_FGET_NT_ACL(metadata_fsp(fsp
),
1273 if (!NT_STATUS_IS_OK(status
)) {
1274 DBG_DEBUG("Could not get acl "
1281 status
= se_file_access_check(sd
,
1282 get_current_nttok(fsp
->conn
),
1289 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
1290 DBG_DEBUG("rejected bits 0x%x read access for %s\n",
1291 (unsigned int)rejected_mask
,
1298 /*******************************************************************
1299 Check to see if a user can write to an fsp.
1300 Always return true for directories.
1301 This is only approximate,
1302 it is used as part of the "hide unwriteable" option. Don't
1303 use it for anything security sensitive.
1304 ********************************************************************/
1306 static bool user_can_write_fsp(struct files_struct
*fsp
)
1309 * Never hide files from the root user.
1310 * We use (uid_t)0 here not sec_initial_uid()
1311 * as make test uses a single user context.
1314 if (get_current_uid(fsp
->conn
) == (uid_t
)0) {
1318 if (fsp
->fsp_flags
.is_directory
) {
1322 return can_write_to_fsp(fsp
);
1325 /*******************************************************************
1326 Is a file a "special" type ?
1327 ********************************************************************/
1329 static bool file_is_special(connection_struct
*conn
,
1330 const struct smb_filename
*smb_fname
)
1333 * Never hide files from the root user.
1334 * We use (uid_t)0 here not sec_initial_uid()
1335 * as make test uses a single user context.
1338 if (get_current_uid(conn
) == (uid_t
)0) {
1342 SMB_ASSERT(VALID_STAT(smb_fname
->st
));
1344 if (S_ISREG(smb_fname
->st
.st_ex_mode
) ||
1345 S_ISDIR(smb_fname
->st
.st_ex_mode
) ||
1346 S_ISLNK(smb_fname
->st
.st_ex_mode
))
1352 /*******************************************************************
1353 Should the file be seen by the client?
1354 ********************************************************************/
1356 bool is_visible_fsp(struct files_struct
*fsp
)
1358 bool hide_unreadable
= false;
1359 bool hide_unwriteable
= false;
1360 bool hide_special
= false;
1361 int hide_new_files_timeout
= 0;
1362 const char *last_component
= NULL
;
1365 * If the file does not exist, there's no point checking
1366 * the configuration options. We succeed, on the basis that the
1367 * checks *might* have passed if the file was present.
1373 hide_unreadable
= lp_hide_unreadable(SNUM(fsp
->conn
));
1374 hide_unwriteable
= lp_hide_unwriteable_files(SNUM(fsp
->conn
));
1375 hide_special
= lp_hide_special_files(SNUM(fsp
->conn
));
1376 hide_new_files_timeout
= lp_hide_new_files_timeout(SNUM(fsp
->conn
));
1378 if (!hide_unreadable
&&
1379 !hide_unwriteable
&&
1381 (hide_new_files_timeout
== 0))
1386 fsp
= metadata_fsp(fsp
);
1388 /* Get the last component of the base name. */
1389 last_component
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
1390 if (!last_component
) {
1391 last_component
= fsp
->fsp_name
->base_name
;
1393 last_component
++; /* Go past '/' */
1396 if (ISDOT(last_component
) || ISDOTDOT(last_component
)) {
1397 return true; /* . and .. are always visible. */
1400 if (fsp_get_pathref_fd(fsp
) == -1) {
1402 * Symlink in POSIX mode or MS-DFS.
1403 * We've checked veto files so the
1404 * only thing we can check is the
1405 * hide_new_files_timeout.
1407 if ((hide_new_files_timeout
!= 0) &&
1408 !S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
1409 double age
= timespec_elapsed(
1410 &fsp
->fsp_name
->st
.st_ex_mtime
);
1412 if (age
< (double)hide_new_files_timeout
) {
1419 if (hide_unreadable
||
1422 (hide_new_files_timeout
!= 0))
1424 /* Honour _hide unreadable_ option */
1425 if (hide_unreadable
&&
1426 !user_can_read_fsp(fsp
))
1428 DBG_DEBUG("file %s is unreadable.\n",
1432 /* Honour _hide unwriteable_ option */
1433 if (hide_unwriteable
&&
1434 !user_can_write_fsp(fsp
))
1436 DBG_DEBUG("file %s is unwritable.\n",
1440 /* Honour _hide_special_ option */
1441 if (hide_special
&& file_is_special(fsp
->conn
, fsp
->fsp_name
)) {
1442 DBG_DEBUG("file %s is special.\n",
1447 if ((hide_new_files_timeout
!= 0) &&
1448 !S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
1449 double age
= timespec_elapsed(
1450 &fsp
->fsp_name
->st
.st_ex_mtime
);
1452 if (age
< (double)hide_new_files_timeout
) {
1461 static int smb_Dir_destructor(struct smb_Dir
*dir_hnd
)
1463 files_struct
*fsp
= dir_hnd
->fsp
;
1465 SMB_VFS_CLOSEDIR(dir_hnd
->conn
, dir_hnd
->dir
);
1466 fsp_set_fd(fsp
, -1);
1467 if (fsp
->dptr
!= NULL
) {
1468 SMB_ASSERT(fsp
->dptr
->dir_hnd
== dir_hnd
);
1469 fsp
->dptr
->dir_hnd
= NULL
;
1471 dir_hnd
->fsp
= NULL
;
1475 /*******************************************************************
1477 ********************************************************************/
1479 static int smb_Dir_OpenDir_destructor(struct smb_Dir
*dir_hnd
)
1481 files_struct
*fsp
= dir_hnd
->fsp
;
1483 smb_Dir_destructor(dir_hnd
);
1484 file_free(NULL
, fsp
);
1488 NTSTATUS
OpenDir(TALLOC_CTX
*mem_ctx
,
1489 connection_struct
*conn
,
1490 const struct smb_filename
*smb_dname
,
1493 struct smb_Dir
**_dir_hnd
)
1495 struct files_struct
*fsp
= NULL
;
1496 struct smb_Dir
*dir_hnd
= NULL
;
1499 status
= open_internal_dirfsp(conn
,
1503 if (!NT_STATUS_IS_OK(status
)) {
1507 status
= OpenDir_fsp(mem_ctx
, conn
, fsp
, mask
, attr
, &dir_hnd
);
1508 if (!NT_STATUS_IS_OK(status
)) {
1513 * This overwrites the destructor set by OpenDir_fsp() but
1514 * smb_Dir_OpenDir_destructor() calls the OpenDir_fsp()
1517 talloc_set_destructor(dir_hnd
, smb_Dir_OpenDir_destructor
);
1519 *_dir_hnd
= dir_hnd
;
1520 return NT_STATUS_OK
;
1523 NTSTATUS
OpenDir_from_pathref(TALLOC_CTX
*mem_ctx
,
1524 struct files_struct
*dirfsp
,
1527 struct smb_Dir
**_dir_hnd
)
1529 struct files_struct
*fsp
= NULL
;
1530 struct smb_Dir
*dir_hnd
= NULL
;
1533 status
= openat_internal_dir_from_pathref(dirfsp
, O_RDONLY
, &fsp
);
1534 if (!NT_STATUS_IS_OK(status
)) {
1538 status
= OpenDir_fsp(mem_ctx
, fsp
->conn
, fsp
, mask
, attr
, &dir_hnd
);
1539 if (!NT_STATUS_IS_OK(status
)) {
1544 * This overwrites the destructor set by OpenDir_fsp() but
1545 * smb_Dir_OpenDir_destructor() calls the OpenDir_fsp()
1548 talloc_set_destructor(dir_hnd
, smb_Dir_OpenDir_destructor
);
1550 *_dir_hnd
= dir_hnd
;
1551 return NT_STATUS_OK
;
1554 /*******************************************************************
1555 Open a directory from an fsp.
1556 ********************************************************************/
1558 static NTSTATUS
OpenDir_fsp(
1559 TALLOC_CTX
*mem_ctx
,
1560 connection_struct
*conn
,
1564 struct smb_Dir
**_dir_hnd
)
1566 struct smb_Dir
*dir_hnd
= talloc_zero(mem_ctx
, struct smb_Dir
);
1570 return NT_STATUS_NO_MEMORY
;
1573 if (!fsp
->fsp_flags
.is_directory
) {
1574 status
= NT_STATUS_INVALID_HANDLE
;
1578 if (fsp_get_io_fd(fsp
) == -1) {
1579 status
= NT_STATUS_INVALID_HANDLE
;
1583 dir_hnd
->conn
= conn
;
1585 if (!conn
->sconn
->using_smb2
) {
1587 * The dircache is only needed for SMB1 because SMB1 uses a name
1588 * for the resume wheras SMB2 always continues from the next
1589 * position (unless it's told to restart or close-and-reopen the
1592 dir_hnd
->name_cache_size
=
1593 lp_directory_name_cache_size(SNUM(conn
));
1596 dir_hnd
->dir_smb_fname
= cp_smb_filename(dir_hnd
, fsp
->fsp_name
);
1597 if (!dir_hnd
->dir_smb_fname
) {
1598 status
= NT_STATUS_NO_MEMORY
;
1602 dir_hnd
->dir
= SMB_VFS_FDOPENDIR(fsp
, mask
, attr
);
1603 if (dir_hnd
->dir
== NULL
) {
1604 status
= map_nt_error_from_unix(errno
);
1608 if (fsp
->posix_flags
& FSP_POSIX_FLAGS_OPEN
) {
1609 dir_hnd
->case_sensitive
= true;
1611 dir_hnd
->case_sensitive
= conn
->case_sensitive
;
1614 talloc_set_destructor(dir_hnd
, smb_Dir_destructor
);
1616 *_dir_hnd
= dir_hnd
;
1617 return NT_STATUS_OK
;
1620 TALLOC_FREE(dir_hnd
);
1625 /*******************************************************************
1626 Read from a directory.
1627 Return directory entry, current offset, and optional stat information.
1628 Don't check for veto or invisible files.
1629 ********************************************************************/
1631 const char *ReadDirName(struct smb_Dir
*dir_hnd
, long *poffset
,
1632 SMB_STRUCT_STAT
*sbuf
, char **ptalloced
)
1635 char *talloced
= NULL
;
1636 connection_struct
*conn
= dir_hnd
->conn
;
1638 /* Cheat to allow . and .. to be the first entries returned. */
1639 if (((*poffset
== START_OF_DIRECTORY_OFFSET
) ||
1640 (*poffset
== DOT_DOT_DIRECTORY_OFFSET
)) &&
1641 (dir_hnd
->file_number
< 2))
1643 if (dir_hnd
->file_number
== 0) {
1645 *poffset
= dir_hnd
->offset
= START_OF_DIRECTORY_OFFSET
;
1648 *poffset
= dir_hnd
->offset
= DOT_DOT_DIRECTORY_OFFSET
;
1650 dir_hnd
->file_number
++;
1655 if (*poffset
== END_OF_DIRECTORY_OFFSET
) {
1656 *poffset
= dir_hnd
->offset
= END_OF_DIRECTORY_OFFSET
;
1660 /* A real offset, seek to it. */
1661 SeekDir(dir_hnd
, *poffset
);
1663 while ((n
= vfs_readdirname(conn
, dir_hnd
->fsp
, dir_hnd
->dir
, sbuf
, &talloced
))) {
1664 /* Ignore . and .. - we've already returned them. */
1665 if (ISDOT(n
) || ISDOTDOT(n
)) {
1666 TALLOC_FREE(talloced
);
1669 *poffset
= dir_hnd
->offset
= SMB_VFS_TELLDIR(conn
, dir_hnd
->dir
);
1670 *ptalloced
= talloced
;
1671 dir_hnd
->file_number
++;
1674 *poffset
= dir_hnd
->offset
= END_OF_DIRECTORY_OFFSET
;
1679 /*******************************************************************
1680 Rewind to the start.
1681 ********************************************************************/
1683 void RewindDir(struct smb_Dir
*dir_hnd
, long *poffset
)
1685 SMB_VFS_REWINDDIR(dir_hnd
->conn
, dir_hnd
->dir
);
1686 dir_hnd
->file_number
= 0;
1687 dir_hnd
->offset
= START_OF_DIRECTORY_OFFSET
;
1688 *poffset
= START_OF_DIRECTORY_OFFSET
;
1691 /*******************************************************************
1693 ********************************************************************/
1695 void SeekDir(struct smb_Dir
*dirp
, long offset
)
1697 if (offset
!= dirp
->offset
) {
1698 if (offset
== START_OF_DIRECTORY_OFFSET
) {
1699 RewindDir(dirp
, &offset
);
1701 * Ok we should really set the file number here
1702 * to 1 to enable ".." to be returned next. Trouble
1703 * is I'm worried about callers using SeekDir(dirp,0)
1704 * as equivalent to RewindDir(). So leave this alone
1707 } else if (offset
== DOT_DOT_DIRECTORY_OFFSET
) {
1708 RewindDir(dirp
, &offset
);
1710 * Set the file number to 2 - we want to get the first
1711 * real file entry (the one we return after "..")
1712 * on the next ReadDir.
1714 dirp
->file_number
= 2;
1715 } else if (offset
== END_OF_DIRECTORY_OFFSET
) {
1716 ; /* Don't seek in this case. */
1718 SMB_VFS_SEEKDIR(dirp
->conn
, dirp
->dir
, offset
);
1720 dirp
->offset
= offset
;
1724 /*******************************************************************
1725 Tell a dir position.
1726 ********************************************************************/
1728 long TellDir(struct smb_Dir
*dir_hnd
)
1730 return(dir_hnd
->offset
);
1733 /*******************************************************************
1734 Add an entry into the dcache.
1735 ********************************************************************/
1737 static void DirCacheAdd(struct smb_Dir
*dir_hnd
, const char *name
, long offset
)
1739 struct name_cache_entry
*e
;
1741 if (dir_hnd
->name_cache_size
== 0) {
1745 if (dir_hnd
->name_cache
== NULL
) {
1746 dir_hnd
->name_cache
= talloc_zero_array(dir_hnd
,
1747 struct name_cache_entry
,
1748 dir_hnd
->name_cache_size
);
1750 if (dir_hnd
->name_cache
== NULL
) {
1755 dir_hnd
->name_cache_index
= (dir_hnd
->name_cache_index
+1) %
1756 dir_hnd
->name_cache_size
;
1757 e
= &dir_hnd
->name_cache
[dir_hnd
->name_cache_index
];
1758 TALLOC_FREE(e
->name
);
1759 e
->name
= talloc_strdup(dir_hnd
, name
);
1763 /*******************************************************************
1764 Find an entry by name. Leave us at the offset after it.
1765 Don't check for veto or invisible files.
1766 ********************************************************************/
1768 static bool SearchDir(struct smb_Dir
*dir_hnd
, const char *name
, long *poffset
)
1771 const char *entry
= NULL
;
1772 char *talloced
= NULL
;
1773 connection_struct
*conn
= dir_hnd
->conn
;
1775 /* Search back in the name cache. */
1776 if (dir_hnd
->name_cache_size
&& dir_hnd
->name_cache
) {
1777 for (i
= dir_hnd
->name_cache_index
; i
>= 0; 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
);
1785 for (i
= dir_hnd
->name_cache_size
- 1;
1786 i
> dir_hnd
->name_cache_index
; i
--) {
1787 struct name_cache_entry
*e
= &dir_hnd
->name_cache
[i
];
1788 if (e
->name
&& (dir_hnd
->case_sensitive
? (strcmp(e
->name
, name
) == 0) : strequal(e
->name
, name
))) {
1789 *poffset
= e
->offset
;
1790 SeekDir(dir_hnd
, e
->offset
);
1796 /* Not found in the name cache. Rewind directory and start from scratch. */
1797 SMB_VFS_REWINDDIR(conn
, dir_hnd
->dir
);
1798 dir_hnd
->file_number
= 0;
1799 *poffset
= START_OF_DIRECTORY_OFFSET
;
1800 while ((entry
= ReadDirName(dir_hnd
, poffset
, NULL
, &talloced
))) {
1801 if (dir_hnd
->case_sensitive
? (strcmp(entry
, name
) == 0) : strequal(entry
, name
)) {
1802 TALLOC_FREE(talloced
);
1805 TALLOC_FREE(talloced
);
1810 struct files_below_forall_state
{
1812 ssize_t dirpath_len
;
1813 int (*fn
)(struct file_id fid
, const struct share_mode_data
*data
,
1814 void *private_data
);
1818 static int files_below_forall_fn(struct file_id fid
,
1819 const struct share_mode_data
*data
,
1822 struct files_below_forall_state
*state
= private_data
;
1823 char tmpbuf
[PATH_MAX
];
1824 char *fullpath
, *to_free
;
1827 len
= full_path_tos(data
->servicepath
, data
->base_name
,
1828 tmpbuf
, sizeof(tmpbuf
),
1829 &fullpath
, &to_free
);
1833 if (state
->dirpath_len
>= len
) {
1835 * Filter files above dirpath
1839 if (fullpath
[state
->dirpath_len
] != '/') {
1841 * Filter file that don't have a path separator at the end of
1847 if (memcmp(state
->dirpath
, fullpath
, state
->dirpath_len
) != 0) {
1854 TALLOC_FREE(to_free
);
1855 return state
->fn(fid
, data
, state
->private_data
);
1858 TALLOC_FREE(to_free
);
1862 static int files_below_forall(connection_struct
*conn
,
1863 const struct smb_filename
*dir_name
,
1864 int (*fn
)(struct file_id fid
,
1865 const struct share_mode_data
*data
,
1866 void *private_data
),
1869 struct files_below_forall_state state
= {
1871 .private_data
= private_data
,
1874 char tmpbuf
[PATH_MAX
];
1877 state
.dirpath_len
= full_path_tos(conn
->connectpath
,
1878 dir_name
->base_name
,
1879 tmpbuf
, sizeof(tmpbuf
),
1880 &state
.dirpath
, &to_free
);
1881 if (state
.dirpath_len
== -1) {
1885 ret
= share_mode_forall(files_below_forall_fn
, &state
);
1886 TALLOC_FREE(to_free
);
1890 struct have_file_open_below_state
{
1894 static int have_file_open_below_fn(struct file_id fid
,
1895 const struct share_mode_data
*data
,
1898 struct have_file_open_below_state
*state
= private_data
;
1899 state
->found_one
= true;
1903 bool have_file_open_below(connection_struct
*conn
,
1904 const struct smb_filename
*name
)
1906 struct have_file_open_below_state state
= {
1911 if (!VALID_STAT(name
->st
)) {
1914 if (!S_ISDIR(name
->st
.st_ex_mode
)) {
1918 ret
= files_below_forall(conn
, name
, have_file_open_below_fn
, &state
);
1923 return state
.found_one
;
1926 /*****************************************************************
1927 Is this directory empty ?
1928 *****************************************************************/
1930 NTSTATUS
can_delete_directory_fsp(files_struct
*fsp
)
1932 NTSTATUS status
= NT_STATUS_OK
;
1934 const char *dname
= NULL
;
1935 char *talloced
= NULL
;
1936 struct connection_struct
*conn
= fsp
->conn
;
1937 struct smb_Dir
*dir_hnd
= NULL
;
1940 talloc_tos(), conn
, fsp
->fsp_name
, NULL
, 0, &dir_hnd
);
1941 if (!NT_STATUS_IS_OK(status
)) {
1945 while ((dname
= ReadDirName(dir_hnd
, &dirpos
, NULL
, &talloced
))) {
1946 struct smb_filename
*smb_dname_full
= NULL
;
1947 struct smb_filename
*direntry_fname
= NULL
;
1948 char *fullname
= NULL
;
1951 if (ISDOT(dname
) || (ISDOTDOT(dname
))) {
1952 TALLOC_FREE(talloced
);
1955 if (IS_VETO_PATH(conn
, dname
)) {
1956 TALLOC_FREE(talloced
);
1960 fullname
= talloc_asprintf(talloc_tos(),
1962 fsp
->fsp_name
->base_name
,
1964 if (fullname
== NULL
) {
1965 status
= NT_STATUS_NO_MEMORY
;
1969 smb_dname_full
= synthetic_smb_fname(talloc_tos(),
1973 fsp
->fsp_name
->twrp
,
1974 fsp
->fsp_name
->flags
);
1975 if (smb_dname_full
== NULL
) {
1976 TALLOC_FREE(talloced
);
1977 TALLOC_FREE(fullname
);
1978 status
= NT_STATUS_NO_MEMORY
;
1982 ret
= SMB_VFS_LSTAT(conn
, smb_dname_full
);
1984 status
= map_nt_error_from_unix(errno
);
1985 TALLOC_FREE(talloced
);
1986 TALLOC_FREE(fullname
);
1987 TALLOC_FREE(smb_dname_full
);
1991 if (S_ISLNK(smb_dname_full
->st
.st_ex_mode
)) {
1992 /* Could it be an msdfs link ? */
1993 if (lp_host_msdfs() &&
1994 lp_msdfs_root(SNUM(conn
))) {
1995 struct smb_filename
*smb_dname
;
1996 smb_dname
= synthetic_smb_fname(talloc_tos(),
1999 &smb_dname_full
->st
,
2000 fsp
->fsp_name
->twrp
,
2001 fsp
->fsp_name
->flags
);
2002 if (smb_dname
== NULL
) {
2003 TALLOC_FREE(talloced
);
2004 TALLOC_FREE(fullname
);
2005 TALLOC_FREE(smb_dname_full
);
2006 status
= NT_STATUS_NO_MEMORY
;
2009 if (is_msdfs_link(fsp
, smb_dname
)) {
2010 TALLOC_FREE(talloced
);
2011 TALLOC_FREE(fullname
);
2012 TALLOC_FREE(smb_dname_full
);
2013 TALLOC_FREE(smb_dname
);
2014 DBG_DEBUG("got msdfs link name %s "
2015 "- can't delete directory %s\n",
2018 status
= NT_STATUS_DIRECTORY_NOT_EMPTY
;
2021 TALLOC_FREE(smb_dname
);
2023 /* Not a DFS link - could it be a dangling symlink ? */
2024 ret
= SMB_VFS_STAT(conn
, smb_dname_full
);
2025 if (ret
== -1 && (errno
== ENOENT
|| errno
== ELOOP
)) {
2028 * Allow if "delete veto files = yes"
2030 if (lp_delete_veto_files(SNUM(conn
))) {
2031 TALLOC_FREE(talloced
);
2032 TALLOC_FREE(fullname
);
2033 TALLOC_FREE(smb_dname_full
);
2037 DBG_DEBUG("got symlink name %s - "
2038 "can't delete directory %s\n",
2041 TALLOC_FREE(talloced
);
2042 TALLOC_FREE(fullname
);
2043 TALLOC_FREE(smb_dname_full
);
2044 status
= NT_STATUS_DIRECTORY_NOT_EMPTY
;
2048 /* Not a symlink, get a pathref. */
2049 status
= synthetic_pathref(talloc_tos(),
2053 &smb_dname_full
->st
,
2054 fsp
->fsp_name
->twrp
,
2055 fsp
->fsp_name
->flags
,
2057 if (!NT_STATUS_IS_OK(status
)) {
2058 status
= map_nt_error_from_unix(errno
);
2059 TALLOC_FREE(talloced
);
2060 TALLOC_FREE(fullname
);
2061 TALLOC_FREE(smb_dname_full
);
2065 if (!is_visible_fsp(direntry_fname
->fsp
)) {
2068 * Allow if "delete veto files = yes"
2070 if (lp_delete_veto_files(SNUM(conn
))) {
2071 TALLOC_FREE(talloced
);
2072 TALLOC_FREE(fullname
);
2073 TALLOC_FREE(smb_dname_full
);
2074 TALLOC_FREE(direntry_fname
);
2079 TALLOC_FREE(talloced
);
2080 TALLOC_FREE(fullname
);
2081 TALLOC_FREE(smb_dname_full
);
2082 TALLOC_FREE(direntry_fname
);
2084 DBG_DEBUG("got name %s - can't delete\n", dname
);
2085 status
= NT_STATUS_DIRECTORY_NOT_EMPTY
;
2088 TALLOC_FREE(talloced
);
2089 TALLOC_FREE(dir_hnd
);
2091 if (!NT_STATUS_IS_OK(status
)) {
2095 if (!(fsp
->posix_flags
& FSP_POSIX_FLAGS_RENAME
) &&
2096 lp_strict_rename(SNUM(conn
)) &&
2097 have_file_open_below(fsp
->conn
, fsp
->fsp_name
))
2099 return NT_STATUS_ACCESS_DENIED
;
2102 return NT_STATUS_OK
;