2 Unix SMB/CIFS implementation.
3 Directory handling routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/filesys.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "libcli/security/security.h"
26 #include "lib/util/bitmap.h"
29 This module implements directory related functions for Samba.
32 /* "Special" directory offsets. */
33 #define END_OF_DIRECTORY_OFFSET ((long)-1)
34 #define START_OF_DIRECTORY_OFFSET ((long)0)
35 #define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000)
37 /* "Special" directory offsets in 32-bit wire format. */
38 #define WIRE_END_OF_DIRECTORY_OFFSET ((uint32_t)0xFFFFFFFF)
39 #define WIRE_START_OF_DIRECTORY_OFFSET ((uint32_t)0)
40 #define WIRE_DOT_DOT_DIRECTORY_OFFSET ((uint32_t)0x80000000)
42 /* Make directory handle internals available. */
44 struct name_cache_entry
{
50 connection_struct
*conn
;
54 size_t name_cache_size
;
55 struct name_cache_entry
*name_cache
;
56 unsigned int name_cache_index
;
57 unsigned int file_number
;
58 files_struct
*fsp
; /* Back pointer to containing fsp, only
59 set from OpenDir_fsp(). */
63 struct dptr_struct
*next
, *prev
;
66 struct connection_struct
*conn
;
67 struct smb_Dir
*dir_hnd
;
72 bool has_wild
; /* Set to true if the wcard entry has MS wildcard characters in it. */
73 bool did_stat
; /* Optimisation for non-wcard searches. */
74 bool priv
; /* Directory handle opened with privilege. */
77 static struct smb_Dir
*OpenDir_fsp(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
82 #define INVALID_DPTR_KEY (-3)
84 /****************************************************************************
86 ****************************************************************************/
88 bool make_dir_struct(TALLOC_CTX
*ctx
,
98 char *mask2
= talloc_strdup(ctx
, mask
);
104 if ((mode
& FILE_ATTRIBUTE_DIRECTORY
) != 0) {
108 memset(buf
+1,' ',11);
109 if ((p
= strchr_m(mask2
,'.')) != NULL
) {
111 push_ascii(buf
+1,mask2
,8, 0);
112 push_ascii(buf
+9,p
+1,3, 0);
115 push_ascii(buf
+1,mask2
,11, 0);
118 memset(buf
+21,'\0',DIR_STRUCT_SIZE
-21);
120 srv_put_dos_date(buf
,22,date
);
121 SSVAL(buf
,26,size
& 0xFFFF);
122 SSVAL(buf
,28,(size
>> 16)&0xFFFF);
123 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
124 Strange, but verified on W2K3. Needed for OS/2. JRA. */
125 push_ascii(buf
+30,fname
,12, uc
? STR_UPPER
: 0);
126 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf
+30, fname
));
130 /****************************************************************************
131 Initialise the dir bitmap.
132 ****************************************************************************/
134 bool init_dptrs(struct smbd_server_connection
*sconn
)
136 if (sconn
->searches
.dptr_bmap
) {
140 sconn
->searches
.dptr_bmap
= bitmap_talloc(
141 sconn
, MAX_DIRECTORY_HANDLES
);
143 if (sconn
->searches
.dptr_bmap
== NULL
) {
150 /****************************************************************************
151 Idle a dptr - the directory is closed but the control info is kept.
152 ****************************************************************************/
154 static void dptr_idle(struct dptr_struct
*dptr
)
157 DEBUG(4,("Idling dptr dnum %d\n",dptr
->dnum
));
158 TALLOC_FREE(dptr
->dir_hnd
);
162 /****************************************************************************
163 Idle the oldest dptr.
164 ****************************************************************************/
166 static void dptr_idleoldest(struct smbd_server_connection
*sconn
)
168 struct dptr_struct
*dptr
;
171 * Go to the end of the list.
173 dptr
= DLIST_TAIL(sconn
->searches
.dirptrs
);
176 DEBUG(0,("No dptrs available to idle ?\n"));
181 * Idle the oldest pointer.
184 for(; dptr
; dptr
= DLIST_PREV(dptr
)) {
192 /****************************************************************************
193 Get the struct dptr_struct for a dir index.
194 ****************************************************************************/
196 static struct dptr_struct
*dptr_get(struct smbd_server_connection
*sconn
,
197 int key
, bool forclose
)
199 struct dptr_struct
*dptr
;
201 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= dptr
->next
) {
202 if(dptr
->dnum
== key
) {
203 if (!forclose
&& !dptr
->dir_hnd
) {
204 if (sconn
->searches
.dirhandles_open
>= MAX_OPEN_DIRECTORIES
)
205 dptr_idleoldest(sconn
);
206 DEBUG(4,("dptr_get: Reopening dptr key %d\n",key
));
207 if (!(dptr
->dir_hnd
= OpenDir(
208 NULL
, dptr
->conn
, dptr
->path
,
209 dptr
->wcard
, dptr
->attr
))) {
210 DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr
->path
,
215 DLIST_PROMOTE(sconn
->searches
.dirptrs
,dptr
);
222 /****************************************************************************
223 Get the dir path for a dir index.
224 ****************************************************************************/
226 const char *dptr_path(struct smbd_server_connection
*sconn
, int key
)
228 struct dptr_struct
*dptr
= dptr_get(sconn
, key
, false);
234 /****************************************************************************
235 Get the dir wcard for a dir index.
236 ****************************************************************************/
238 const char *dptr_wcard(struct smbd_server_connection
*sconn
, int key
)
240 struct dptr_struct
*dptr
= dptr_get(sconn
, key
, false);
246 /****************************************************************************
247 Get the dir attrib for a dir index.
248 ****************************************************************************/
250 uint16
dptr_attr(struct smbd_server_connection
*sconn
, int key
)
252 struct dptr_struct
*dptr
= dptr_get(sconn
, key
, false);
258 /****************************************************************************
259 Close a dptr (internal func).
260 ****************************************************************************/
262 static void dptr_close_internal(struct dptr_struct
*dptr
)
264 struct smbd_server_connection
*sconn
= dptr
->conn
->sconn
;
266 DEBUG(4,("closing dptr key %d\n",dptr
->dnum
));
272 if (sconn
->using_smb2
) {
276 DLIST_REMOVE(sconn
->searches
.dirptrs
, dptr
);
279 * Free the dnum in the bitmap. Remember the dnum value is always
280 * biased by one with respect to the bitmap.
283 if (!bitmap_query(sconn
->searches
.dptr_bmap
, dptr
->dnum
- 1)) {
284 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
288 bitmap_clear(sconn
->searches
.dptr_bmap
, dptr
->dnum
- 1);
291 TALLOC_FREE(dptr
->dir_hnd
);
295 /****************************************************************************
296 Close a dptr given a key.
297 ****************************************************************************/
299 void dptr_close(struct smbd_server_connection
*sconn
, int *key
)
301 struct dptr_struct
*dptr
;
303 if(*key
== INVALID_DPTR_KEY
)
306 /* OS/2 seems to use -1 to indicate "close all directories" */
308 struct dptr_struct
*next
;
309 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= next
) {
311 dptr_close_internal(dptr
);
313 *key
= INVALID_DPTR_KEY
;
317 dptr
= dptr_get(sconn
, *key
, true);
320 DEBUG(0,("Invalid key %d given to dptr_close\n", *key
));
324 dptr_close_internal(dptr
);
326 *key
= INVALID_DPTR_KEY
;
329 /****************************************************************************
330 Close all dptrs for a cnum.
331 ****************************************************************************/
333 void dptr_closecnum(connection_struct
*conn
)
335 struct dptr_struct
*dptr
, *next
;
336 struct smbd_server_connection
*sconn
= conn
->sconn
;
342 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= next
) {
344 if (dptr
->conn
== conn
) {
345 dptr_close_internal(dptr
);
350 /****************************************************************************
351 Idle all dptrs for a cnum.
352 ****************************************************************************/
354 void dptr_idlecnum(connection_struct
*conn
)
356 struct dptr_struct
*dptr
;
357 struct smbd_server_connection
*sconn
= conn
->sconn
;
363 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= dptr
->next
) {
364 if (dptr
->conn
== conn
&& dptr
->dir_hnd
) {
370 /****************************************************************************
371 Close a dptr that matches a given path, only if it matches the spid also.
372 ****************************************************************************/
374 void dptr_closepath(struct smbd_server_connection
*sconn
,
375 char *path
,uint16 spid
)
377 struct dptr_struct
*dptr
, *next
;
378 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= next
) {
380 if (spid
== dptr
->spid
&& strequal(dptr
->path
,path
))
381 dptr_close_internal(dptr
);
385 /****************************************************************************
386 Try and close the oldest handle not marked for
387 expect close in the hope that the client has
388 finished with that one.
389 ****************************************************************************/
391 static void dptr_close_oldest(struct smbd_server_connection
*sconn
,
394 struct dptr_struct
*dptr
;
397 * Go to the end of the list.
399 for(dptr
= sconn
->searches
.dirptrs
; dptr
&& dptr
->next
; dptr
= dptr
->next
)
403 DEBUG(0,("No old dptrs available to close oldest ?\n"));
408 * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
409 * does not have expect_close set. If 'old' is false, close
410 * one of the new dnum handles.
413 for(; dptr
; dptr
= DLIST_PREV(dptr
)) {
414 if ((old
&& (dptr
->dnum
< 256) && !dptr
->expect_close
) ||
415 (!old
&& (dptr
->dnum
> 255))) {
416 dptr_close_internal(dptr
);
422 /****************************************************************************
423 Safely do an OpenDir as root, ensuring we're in the right place.
424 ****************************************************************************/
426 static struct smb_Dir
*open_dir_with_privilege(connection_struct
*conn
,
427 struct smb_request
*req
,
433 struct smb_Dir
*dir_hnd
= NULL
;
434 struct smb_filename
*smb_fname_cwd
= NULL
;
435 char *saved_dir
= vfs_GetWd(talloc_tos(), conn
);
436 struct privilege_paths
*priv_paths
= req
->priv_paths
;
439 if (saved_dir
== NULL
) {
443 if (vfs_ChDir(conn
, path
) == -1) {
447 /* Now check the stat value is the same. */
448 status
= create_synthetic_smb_fname(talloc_tos(), ".",
452 if (!NT_STATUS_IS_OK(status
)) {
455 ret
= SMB_VFS_STAT(conn
, smb_fname_cwd
);
460 if (!check_same_stat(&smb_fname_cwd
->st
, &priv_paths
->parent_name
.st
)) {
461 DEBUG(0,("open_dir_with_privilege: stat mismatch between %s "
464 smb_fname_str_dbg(&priv_paths
->parent_name
)));
468 dir_hnd
= OpenDir(NULL
, conn
, ".", wcard
, attr
);
472 vfs_ChDir(conn
, saved_dir
);
476 /****************************************************************************
477 Create a new dir ptr. If the flag old_handle is true then we must allocate
478 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
479 one byte long. If old_handle is false we allocate from the range
480 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
481 a directory handle is never zero.
482 wcard must not be zero.
483 ****************************************************************************/
485 NTSTATUS
dptr_create(connection_struct
*conn
,
486 struct smb_request
*req
,
488 const char *path
, bool old_handle
, bool expect_close
,uint16 spid
,
489 const char *wcard
, bool wcard_has_wild
, uint32 attr
, struct dptr_struct
**dptr_ret
)
491 struct smbd_server_connection
*sconn
= conn
->sconn
;
492 struct dptr_struct
*dptr
= NULL
;
493 struct smb_Dir
*dir_hnd
;
495 if (fsp
&& fsp
->is_directory
&& fsp
->fh
->fd
!= -1) {
496 path
= fsp
->fsp_name
->base_name
;
499 DEBUG(5,("dptr_create dir=%s\n", path
));
502 DEBUG(0,("dptr_create: called with fake connection_struct\n"));
503 return NT_STATUS_INTERNAL_ERROR
;
507 return NT_STATUS_INVALID_PARAMETER
;
511 if (!(fsp
->access_mask
& SEC_DIR_LIST
)) {
512 DEBUG(5,("dptr_create: directory %s "
513 "not open for LIST access\n",
515 return NT_STATUS_ACCESS_DENIED
;
517 dir_hnd
= OpenDir_fsp(NULL
, conn
, fsp
, wcard
, attr
);
520 struct smb_filename
*smb_dname
= NULL
;
521 NTSTATUS status
= create_synthetic_smb_fname(talloc_tos(),
526 if (!NT_STATUS_IS_OK(status
)) {
529 if (lp_posix_pathnames()) {
530 ret
= SMB_VFS_LSTAT(conn
, smb_dname
);
532 ret
= SMB_VFS_STAT(conn
, smb_dname
);
535 return map_nt_error_from_unix(errno
);
537 if (!S_ISDIR(smb_dname
->st
.st_ex_mode
)) {
538 return NT_STATUS_NOT_A_DIRECTORY
;
540 status
= smbd_check_access_rights(conn
,
543 if (!NT_STATUS_IS_OK(status
)) {
546 if (req
&& req
->priv_paths
) {
547 dir_hnd
= open_dir_with_privilege(conn
,
553 dir_hnd
= OpenDir(NULL
, conn
, path
, wcard
, attr
);
558 return map_nt_error_from_unix(errno
);
561 if (sconn
->searches
.dirhandles_open
>= MAX_OPEN_DIRECTORIES
) {
562 dptr_idleoldest(sconn
);
565 dptr
= talloc(NULL
, struct dptr_struct
);
567 DEBUG(0,("talloc fail in dptr_create.\n"));
568 TALLOC_FREE(dir_hnd
);
569 return NT_STATUS_NO_MEMORY
;
574 dptr
->path
= talloc_strdup(dptr
, path
);
577 TALLOC_FREE(dir_hnd
);
578 return NT_STATUS_NO_MEMORY
;
581 dptr
->dir_hnd
= dir_hnd
;
583 dptr
->expect_close
= expect_close
;
584 dptr
->wcard
= talloc_strdup(dptr
, wcard
);
587 TALLOC_FREE(dir_hnd
);
588 return NT_STATUS_NO_MEMORY
;
590 if (lp_posix_pathnames() || (wcard
[0] == '.' && wcard
[1] == 0)) {
591 dptr
->has_wild
= True
;
593 dptr
->has_wild
= wcard_has_wild
;
598 if (sconn
->using_smb2
) {
605 * This is an old-style SMBsearch request. Ensure the
606 * value we return will fit in the range 1-255.
609 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 0);
611 if(dptr
->dnum
== -1 || dptr
->dnum
> 254) {
614 * Try and close the oldest handle not marked for
615 * expect close in the hope that the client has
616 * finished with that one.
619 dptr_close_oldest(sconn
, true);
621 /* Now try again... */
622 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 0);
623 if(dptr
->dnum
== -1 || dptr
->dnum
> 254) {
624 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr
->dnum
));
626 TALLOC_FREE(dir_hnd
);
627 return NT_STATUS_TOO_MANY_OPENED_FILES
;
633 * This is a new-style trans2 request. Allocate from
634 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
637 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 255);
639 if(dptr
->dnum
== -1 || dptr
->dnum
< 255) {
642 * Try and close the oldest handle close in the hope that
643 * the client has finished with that one. This will only
644 * happen in the case of the Win98 client bug where it leaks
648 dptr_close_oldest(sconn
, false);
650 /* Now try again... */
651 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 255);
653 if(dptr
->dnum
== -1 || dptr
->dnum
< 255) {
654 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr
->dnum
));
656 TALLOC_FREE(dir_hnd
);
657 return NT_STATUS_TOO_MANY_OPENED_FILES
;
662 bitmap_set(sconn
->searches
.dptr_bmap
, dptr
->dnum
);
664 dptr
->dnum
+= 1; /* Always bias the dnum by one - no zero dnums allowed. */
666 DLIST_ADD(sconn
->searches
.dirptrs
, dptr
);
669 DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
670 dptr
->dnum
,path
,expect_close
));
678 /****************************************************************************
679 Wrapper functions to access the lower level directory handles.
680 ****************************************************************************/
682 void dptr_CloseDir(files_struct
*fsp
)
686 * The destructor for the struct smb_Dir
687 * (fsp->dptr->dir_hnd) now handles
688 * all resource deallocation.
690 dptr_close_internal(fsp
->dptr
);
695 void dptr_SeekDir(struct dptr_struct
*dptr
, long offset
)
697 SeekDir(dptr
->dir_hnd
, offset
);
700 long dptr_TellDir(struct dptr_struct
*dptr
)
702 return TellDir(dptr
->dir_hnd
);
705 bool dptr_has_wild(struct dptr_struct
*dptr
)
707 return dptr
->has_wild
;
710 int dptr_dnum(struct dptr_struct
*dptr
)
715 bool dptr_get_priv(struct dptr_struct
*dptr
)
720 void dptr_set_priv(struct dptr_struct
*dptr
)
725 /****************************************************************************
726 Return the next visible file name, skipping veto'd and invisible files.
727 ****************************************************************************/
729 static const char *dptr_normal_ReadDirName(struct dptr_struct
*dptr
,
730 long *poffset
, SMB_STRUCT_STAT
*pst
,
733 /* Normal search for the next file. */
735 char *talloced
= NULL
;
737 while ((name
= ReadDirName(dptr
->dir_hnd
, poffset
, pst
, &talloced
))
739 if (is_visible_file(dptr
->conn
, dptr
->path
, name
, pst
, True
)) {
740 *ptalloced
= talloced
;
743 TALLOC_FREE(talloced
);
748 /****************************************************************************
749 Return the next visible file name, skipping veto'd and invisible files.
750 ****************************************************************************/
752 char *dptr_ReadDirName(TALLOC_CTX
*ctx
,
753 struct dptr_struct
*dptr
,
755 SMB_STRUCT_STAT
*pst
)
757 struct smb_filename smb_fname_base
;
759 const char *name_temp
= NULL
;
760 char *talloced
= NULL
;
761 char *pathreal
= NULL
;
762 char *found_name
= NULL
;
765 SET_STAT_INVALID(*pst
);
767 if (dptr
->has_wild
|| dptr
->did_stat
) {
768 name_temp
= dptr_normal_ReadDirName(dptr
, poffset
, pst
,
770 if (name_temp
== NULL
) {
773 if (talloced
!= NULL
) {
774 return talloc_move(ctx
, &talloced
);
776 return talloc_strdup(ctx
, name_temp
);
779 /* If poffset is -1 then we know we returned this name before and we
780 * have no wildcards. We're at the end of the directory. */
781 if (*poffset
== END_OF_DIRECTORY_OFFSET
) {
785 /* We know the stored wcard contains no wildcard characters.
786 * See if we can match with a stat call. If we can't, then set
787 * did_stat to true to ensure we only do this once and keep
790 dptr
->did_stat
= true;
792 /* First check if it should be visible. */
793 if (!is_visible_file(dptr
->conn
, dptr
->path
, dptr
->wcard
,
796 /* This only returns false if the file was found, but
797 is explicitly not visible. Set us to end of
798 directory, but return NULL as we know we can't ever
803 if (VALID_STAT(*pst
)) {
804 name
= talloc_strdup(ctx
, dptr
->wcard
);
808 pathreal
= talloc_asprintf(ctx
,
815 /* Create an smb_filename with stream_name == NULL. */
816 ZERO_STRUCT(smb_fname_base
);
817 smb_fname_base
.base_name
= pathreal
;
819 if (SMB_VFS_STAT(dptr
->conn
, &smb_fname_base
) == 0) {
820 *pst
= smb_fname_base
.st
;
821 name
= talloc_strdup(ctx
, dptr
->wcard
);
824 /* If we get any other error than ENOENT or ENOTDIR
825 then the file exists we just can't stat it. */
826 if (errno
!= ENOENT
&& errno
!= ENOTDIR
) {
827 name
= talloc_strdup(ctx
, dptr
->wcard
);
832 /* Stat failed. We know this is authoratiative if we are
833 * providing case sensitive semantics or the underlying
834 * filesystem is case sensitive.
836 if (dptr
->conn
->case_sensitive
||
837 !(dptr
->conn
->fs_capabilities
& FILE_CASE_SENSITIVE_SEARCH
))
843 * Try case-insensitive stat if the fs has the ability. This avoids
844 * scanning the whole directory.
846 ret
= SMB_VFS_GET_REAL_FILENAME(dptr
->conn
, dptr
->path
, dptr
->wcard
,
851 } else if (errno
== ENOENT
) {
852 /* The case-insensitive lookup was authoritative. */
856 TALLOC_FREE(pathreal
);
858 name_temp
= dptr_normal_ReadDirName(dptr
, poffset
, pst
, &talloced
);
859 if (name_temp
== NULL
) {
862 if (talloced
!= NULL
) {
863 return talloc_move(ctx
, &talloced
);
865 return talloc_strdup(ctx
, name_temp
);
868 TALLOC_FREE(pathreal
);
870 /* We need to set the underlying dir_hnd offset to -1
871 * also as this function is usually called with the
872 * output from TellDir. */
873 dptr
->dir_hnd
->offset
= *poffset
= END_OF_DIRECTORY_OFFSET
;
877 /****************************************************************************
878 Search for a file by name, skipping veto'ed and not visible files.
879 ****************************************************************************/
881 bool dptr_SearchDir(struct dptr_struct
*dptr
, const char *name
, long *poffset
, SMB_STRUCT_STAT
*pst
)
883 SET_STAT_INVALID(*pst
);
885 if (!dptr
->has_wild
&& (dptr
->dir_hnd
->offset
== END_OF_DIRECTORY_OFFSET
)) {
886 /* This is a singleton directory and we're already at the end. */
887 *poffset
= END_OF_DIRECTORY_OFFSET
;
891 return SearchDir(dptr
->dir_hnd
, name
, poffset
);
894 /****************************************************************************
895 Add the name we're returning into the underlying cache.
896 ****************************************************************************/
898 void dptr_DirCacheAdd(struct dptr_struct
*dptr
, const char *name
, long offset
)
900 DirCacheAdd(dptr
->dir_hnd
, name
, offset
);
903 /****************************************************************************
904 Initialize variables & state data at the beginning of all search SMB requests.
905 ****************************************************************************/
906 void dptr_init_search_op(struct dptr_struct
*dptr
)
908 SMB_VFS_INIT_SEARCH_OP(dptr
->conn
, dptr
->dir_hnd
->dir
);
911 /****************************************************************************
912 Map a native directory offset to a 32-bit cookie.
913 ****************************************************************************/
915 static uint32_t map_dir_offset_to_wire(struct dptr_struct
*dptr
, long offset
)
917 return (uint32_t)offset
;
920 /****************************************************************************
921 Fill the 5 byte server reserved dptr field.
922 ****************************************************************************/
924 bool dptr_fill(struct smbd_server_connection
*sconn
,
925 char *buf1
,unsigned int key
)
927 unsigned char *buf
= (unsigned char *)buf1
;
928 struct dptr_struct
*dptr
= dptr_get(sconn
, key
, false);
929 uint32_t wire_offset
;
931 DEBUG(1,("filling null dirptr %d\n",key
));
934 wire_offset
= map_dir_offset_to_wire(dptr
,TellDir(dptr
->dir_hnd
));
935 DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key
,
936 (long)dptr
->dir_hnd
,(int)wire_offset
));
938 SIVAL(buf
,1,wire_offset
);
942 /****************************************************************************
943 Fetch the dir ptr and seek it given the 5 byte server field.
944 ****************************************************************************/
946 struct dptr_struct
*dptr_fetch(struct smbd_server_connection
*sconn
,
949 unsigned int key
= *(unsigned char *)buf
;
950 struct dptr_struct
*dptr
= dptr_get(sconn
, key
, false);
951 uint32_t wire_offset
;
955 DEBUG(3,("fetched null dirptr %d\n",key
));
959 wire_offset
= IVAL(buf
,1);
960 if (wire_offset
== (uint32_t)-1) {
961 seekoff
= END_OF_DIRECTORY_OFFSET
;
963 seekoff
= (long)wire_offset
;
965 SeekDir(dptr
->dir_hnd
,seekoff
);
966 DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
967 key
, dptr
->path
, (int)seekoff
));
971 /****************************************************************************
973 ****************************************************************************/
975 struct dptr_struct
*dptr_fetch_lanman2(struct smbd_server_connection
*sconn
,
978 struct dptr_struct
*dptr
= dptr_get(sconn
, dptr_num
, false);
981 DEBUG(3,("fetched null dirptr %d\n",dptr_num
));
984 DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num
,dptr
->path
));
988 /****************************************************************************
989 Check that a file matches a particular file type.
990 ****************************************************************************/
992 bool dir_check_ftype(connection_struct
*conn
, uint32 mode
, uint32 dirtype
)
996 /* Check the "may have" search bits. */
997 if (((mode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_DIRECTORY
)) != 0)
1000 /* Check the "must have" bits, which are the may have bits shifted eight */
1001 /* If must have bit is set, the file/dir can not be returned in search unless the matching
1002 file attribute is set */
1003 mask
= ((dirtype
>> 8) & (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)); /* & 0x37 */
1005 if((mask
& (mode
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
))) == mask
) /* check if matching attribute present */
1014 static bool mangle_mask_match(connection_struct
*conn
,
1015 const char *filename
,
1020 if (!name_to_8_3(filename
,mname
,False
,conn
->params
)) {
1023 return mask_match_search(mname
,mask
,False
);
1026 bool smbd_dirptr_get_entry(TALLOC_CTX
*ctx
,
1027 struct dptr_struct
*dirptr
,
1032 bool (*match_fn
)(TALLOC_CTX
*ctx
,
1037 bool (*mode_fn
)(TALLOC_CTX
*ctx
,
1039 struct smb_filename
*smb_fname
,
1043 struct smb_filename
**_smb_fname
,
1047 connection_struct
*conn
= dirptr
->conn
;
1054 pathlen
= strlen(dirptr
->path
);
1055 slashlen
= ( dirptr
->path
[pathlen
-1] != '/') ? 1 : 0;
1060 SMB_STRUCT_STAT sbuf
;
1064 char *pathreal
= NULL
;
1065 struct smb_filename smb_fname
;
1070 cur_offset
= dptr_TellDir(dirptr
);
1071 prev_offset
= cur_offset
;
1072 dname
= dptr_ReadDirName(ctx
, dirptr
, &cur_offset
, &sbuf
);
1074 DEBUG(6,("smbd_dirptr_get_entry: dirptr 0x%lx now at offset %ld\n",
1075 (long)dirptr
, cur_offset
));
1077 if (dname
== NULL
) {
1081 isdots
= (ISDOT(dname
) || ISDOTDOT(dname
));
1082 if (dont_descend
&& !isdots
) {
1088 * fname may get mangled, dname is never mangled.
1089 * Whenever we're accessing the filesystem we use
1090 * pathreal which is composed from dname.
1093 ok
= match_fn(ctx
, private_data
, dname
, mask
, &fname
);
1101 * pathreal = talloc_asprintf(ctx, "%s%s%s", dirptr->path,
1102 * needslash?"/":"", dname);
1103 * but this was measurably slower than doing the memcpy.
1106 pathreal
= talloc_array(
1108 pathlen
+ slashlen
+ talloc_get_size(dname
));
1115 memcpy(pathreal
, dirptr
->path
, pathlen
);
1116 pathreal
[pathlen
] = '/';
1117 memcpy(pathreal
+ slashlen
+ pathlen
, dname
,
1118 talloc_get_size(dname
));
1120 /* Create smb_fname with NULL stream_name. */
1121 ZERO_STRUCT(smb_fname
);
1122 smb_fname
.base_name
= pathreal
;
1123 smb_fname
.st
= sbuf
;
1125 ok
= mode_fn(ctx
, private_data
, &smb_fname
, &mode
);
1129 TALLOC_FREE(pathreal
);
1133 if (!dir_check_ftype(conn
, mode
, dirtype
)) {
1134 DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",
1135 fname
, (unsigned int)mode
, (unsigned int)dirtype
));
1138 TALLOC_FREE(pathreal
);
1142 if (ask_sharemode
) {
1143 struct timespec write_time_ts
;
1144 struct file_id fileid
;
1146 fileid
= vfs_file_id_from_sbuf(conn
,
1148 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1149 if (!null_timespec(write_time_ts
)) {
1150 update_stat_ex_mtime(&smb_fname
.st
,
1155 DEBUG(3,("smbd_dirptr_get_entry mask=[%s] found %s "
1157 mask
, smb_fname_str_dbg(&smb_fname
),
1160 DirCacheAdd(dirptr
->dir_hnd
, dname
, cur_offset
);
1164 status
= copy_smb_filename(ctx
, &smb_fname
, _smb_fname
);
1165 TALLOC_FREE(pathreal
);
1166 if (!NT_STATUS_IS_OK(status
)) {
1171 *_prev_offset
= prev_offset
;
1179 /****************************************************************************
1180 Get an 8.3 directory entry.
1181 ****************************************************************************/
1183 static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX
*ctx
,
1189 connection_struct
*conn
= (connection_struct
*)private_data
;
1191 if ((strcmp(mask
,"*.*") == 0) ||
1192 mask_match_search(dname
, mask
, false) ||
1193 mangle_mask_match(conn
, dname
, mask
)) {
1197 if (!mangle_is_8_3(dname
, false, conn
->params
)) {
1198 bool ok
= name_to_8_3(dname
, mname
, false,
1208 *_fname
= talloc_strdup(ctx
, fname
);
1209 if (*_fname
== NULL
) {
1219 static bool smbd_dirptr_8_3_mode_fn(TALLOC_CTX
*ctx
,
1221 struct smb_filename
*smb_fname
,
1224 connection_struct
*conn
= (connection_struct
*)private_data
;
1226 if (!VALID_STAT(smb_fname
->st
)) {
1227 if ((SMB_VFS_STAT(conn
, smb_fname
)) != 0) {
1228 DEBUG(5,("smbd_dirptr_8_3_mode_fn: "
1229 "Couldn't stat [%s]. Error "
1231 smb_fname_str_dbg(smb_fname
),
1237 *_mode
= dos_mode(conn
, smb_fname
);
1241 bool get_dir_entry(TALLOC_CTX
*ctx
,
1242 struct dptr_struct
*dirptr
,
1248 struct timespec
*_date
,
1252 connection_struct
*conn
= dirptr
->conn
;
1254 struct smb_filename
*smb_fname
= NULL
;
1259 ok
= smbd_dirptr_get_entry(ctx
,
1265 smbd_dirptr_8_3_match_fn
,
1266 smbd_dirptr_8_3_mode_fn
,
1276 *_fname
= talloc_move(ctx
, &fname
);
1277 *_size
= smb_fname
->st
.st_ex_size
;
1279 *_date
= smb_fname
->st
.st_ex_mtime
;
1280 TALLOC_FREE(smb_fname
);
1284 /*******************************************************************
1285 Check to see if a user can read a file. This is only approximate,
1286 it is used as part of the "hide unreadable" option. Don't
1287 use it for anything security sensitive.
1288 ********************************************************************/
1290 static bool user_can_read_file(connection_struct
*conn
,
1291 struct smb_filename
*smb_fname
)
1294 * Never hide files from the root user.
1295 * We use (uid_t)0 here not sec_initial_uid()
1296 * as make test uses a single user context.
1299 if (get_current_uid(conn
) == (uid_t
)0) {
1303 return NT_STATUS_IS_OK(smbd_check_access_rights(conn
,
1308 /*******************************************************************
1309 Check to see if a user can write a file (and only files, we do not
1310 check dirs on this one). This is only approximate,
1311 it is used as part of the "hide unwriteable" option. Don't
1312 use it for anything security sensitive.
1313 ********************************************************************/
1315 static bool user_can_write_file(connection_struct
*conn
,
1316 const struct smb_filename
*smb_fname
)
1319 * Never hide files from the root user.
1320 * We use (uid_t)0 here not sec_initial_uid()
1321 * as make test uses a single user context.
1324 if (get_current_uid(conn
) == (uid_t
)0) {
1328 SMB_ASSERT(VALID_STAT(smb_fname
->st
));
1330 /* Pseudo-open the file */
1332 if(S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1336 return can_write_to_file(conn
, smb_fname
);
1339 /*******************************************************************
1340 Is a file a "special" type ?
1341 ********************************************************************/
1343 static bool file_is_special(connection_struct
*conn
,
1344 const struct smb_filename
*smb_fname
)
1347 * Never hide files from the root user.
1348 * We use (uid_t)0 here not sec_initial_uid()
1349 * as make test uses a single user context.
1352 if (get_current_uid(conn
) == (uid_t
)0) {
1356 SMB_ASSERT(VALID_STAT(smb_fname
->st
));
1358 if (S_ISREG(smb_fname
->st
.st_ex_mode
) ||
1359 S_ISDIR(smb_fname
->st
.st_ex_mode
) ||
1360 S_ISLNK(smb_fname
->st
.st_ex_mode
))
1366 /*******************************************************************
1367 Should the file be seen by the client?
1368 NOTE: A successful return is no guarantee of the file's existence.
1369 ********************************************************************/
1371 bool is_visible_file(connection_struct
*conn
, const char *dir_path
,
1372 const char *name
, SMB_STRUCT_STAT
*pst
, bool use_veto
)
1374 bool hide_unreadable
= lp_hideunreadable(SNUM(conn
));
1375 bool hide_unwriteable
= lp_hideunwriteable_files(SNUM(conn
));
1376 bool hide_special
= lp_hide_special_files(SNUM(conn
));
1378 struct smb_filename
*smb_fname_base
= NULL
;
1382 if ((strcmp(".",name
) == 0) || (strcmp("..",name
) == 0)) {
1383 return True
; /* . and .. are always visible. */
1386 /* If it's a vetoed file, pretend it doesn't even exist */
1387 if (use_veto
&& IS_VETO_PATH(conn
, name
)) {
1388 DEBUG(10,("is_visible_file: file %s is vetoed.\n", name
));
1392 if (hide_unreadable
|| hide_unwriteable
|| hide_special
) {
1393 entry
= talloc_asprintf(talloc_tos(), "%s/%s", dir_path
, name
);
1399 /* Create an smb_filename with stream_name == NULL. */
1400 status
= create_synthetic_smb_fname(talloc_tos(), entry
, NULL
,
1401 pst
, &smb_fname_base
);
1402 if (!NT_STATUS_IS_OK(status
)) {
1407 /* If the file name does not exist, there's no point checking
1408 * the configuration options. We succeed, on the basis that the
1409 * checks *might* have passed if the file was present.
1411 if (!VALID_STAT(*pst
)) {
1412 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
1416 *pst
= smb_fname_base
->st
;
1420 /* Honour _hide unreadable_ option */
1421 if (hide_unreadable
&&
1422 !user_can_read_file(conn
, smb_fname_base
)) {
1423 DEBUG(10,("is_visible_file: file %s is unreadable.\n",
1428 /* Honour _hide unwriteable_ option */
1429 if (hide_unwriteable
&& !user_can_write_file(conn
,
1431 DEBUG(10,("is_visible_file: file %s is unwritable.\n",
1436 /* Honour _hide_special_ option */
1437 if (hide_special
&& file_is_special(conn
, smb_fname_base
)) {
1438 DEBUG(10,("is_visible_file: file %s is special.\n",
1447 TALLOC_FREE(smb_fname_base
);
1452 static int smb_Dir_destructor(struct smb_Dir
*dirp
)
1454 if (dirp
->dir
!= NULL
) {
1455 SMB_VFS_CLOSEDIR(dirp
->conn
,dirp
->dir
);
1456 if (dirp
->fsp
!= NULL
) {
1458 * The SMB_VFS_CLOSEDIR above
1459 * closes the underlying fd inside
1462 dirp
->fsp
->fh
->fd
= -1;
1463 if (dirp
->fsp
->dptr
!= NULL
) {
1464 SMB_ASSERT(dirp
->fsp
->dptr
->dir_hnd
== dirp
);
1465 dirp
->fsp
->dptr
->dir_hnd
= NULL
;
1470 if (dirp
->conn
->sconn
&& !dirp
->conn
->sconn
->using_smb2
) {
1471 dirp
->conn
->sconn
->searches
.dirhandles_open
--;
1476 /*******************************************************************
1478 ********************************************************************/
1480 struct smb_Dir
*OpenDir(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
1485 struct smb_Dir
*dirp
= talloc_zero(mem_ctx
, struct smb_Dir
);
1486 struct smbd_server_connection
*sconn
= conn
->sconn
;
1493 dirp
->name_cache_size
= lp_directory_name_cache_size(SNUM(conn
));
1495 dirp
->dir_path
= talloc_strdup(dirp
, name
);
1496 if (!dirp
->dir_path
) {
1501 if (sconn
&& !sconn
->using_smb2
) {
1502 sconn
->searches
.dirhandles_open
++;
1504 talloc_set_destructor(dirp
, smb_Dir_destructor
);
1506 dirp
->dir
= SMB_VFS_OPENDIR(conn
, dirp
->dir_path
, mask
, attr
);
1508 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp
->dir_path
,
1520 /*******************************************************************
1521 Open a directory from an fsp.
1522 ********************************************************************/
1524 static struct smb_Dir
*OpenDir_fsp(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
1529 struct smb_Dir
*dirp
= talloc_zero(mem_ctx
, struct smb_Dir
);
1530 struct smbd_server_connection
*sconn
= conn
->sconn
;
1537 dirp
->name_cache_size
= lp_directory_name_cache_size(SNUM(conn
));
1539 dirp
->dir_path
= talloc_strdup(dirp
, fsp
->fsp_name
->base_name
);
1540 if (!dirp
->dir_path
) {
1545 if (sconn
&& !sconn
->using_smb2
) {
1546 sconn
->searches
.dirhandles_open
++;
1548 talloc_set_destructor(dirp
, smb_Dir_destructor
);
1550 if (fsp
->is_directory
&& fsp
->fh
->fd
!= -1) {
1551 dirp
->dir
= SMB_VFS_FDOPENDIR(fsp
, mask
, attr
);
1552 if (dirp
->dir
!= NULL
) {
1555 DEBUG(10,("OpenDir_fsp: SMB_VFS_FDOPENDIR on %s returned "
1559 if (errno
!= ENOSYS
) {
1565 if (dirp
->dir
== NULL
) {
1566 /* FDOPENDIR didn't work. Use OPENDIR instead. */
1567 dirp
->dir
= SMB_VFS_OPENDIR(conn
, dirp
->dir_path
, mask
, attr
);
1571 DEBUG(5,("OpenDir_fsp: Can't open %s. %s\n", dirp
->dir_path
,
1584 /*******************************************************************
1585 Read from a directory.
1586 Return directory entry, current offset, and optional stat information.
1587 Don't check for veto or invisible files.
1588 ********************************************************************/
1590 const char *ReadDirName(struct smb_Dir
*dirp
, long *poffset
,
1591 SMB_STRUCT_STAT
*sbuf
, char **ptalloced
)
1594 char *talloced
= NULL
;
1595 connection_struct
*conn
= dirp
->conn
;
1597 /* Cheat to allow . and .. to be the first entries returned. */
1598 if (((*poffset
== START_OF_DIRECTORY_OFFSET
) ||
1599 (*poffset
== DOT_DOT_DIRECTORY_OFFSET
)) && (dirp
->file_number
< 2))
1601 if (dirp
->file_number
== 0) {
1603 *poffset
= dirp
->offset
= START_OF_DIRECTORY_OFFSET
;
1606 *poffset
= dirp
->offset
= DOT_DOT_DIRECTORY_OFFSET
;
1608 dirp
->file_number
++;
1611 } else if (*poffset
== END_OF_DIRECTORY_OFFSET
) {
1612 *poffset
= dirp
->offset
= END_OF_DIRECTORY_OFFSET
;
1615 /* A real offset, seek to it. */
1616 SeekDir(dirp
, *poffset
);
1619 while ((n
= vfs_readdirname(conn
, dirp
->dir
, sbuf
, &talloced
))) {
1620 /* Ignore . and .. - we've already returned them. */
1622 if ((n
[1] == '\0') || (n
[1] == '.' && n
[2] == '\0')) {
1623 TALLOC_FREE(talloced
);
1627 *poffset
= dirp
->offset
= SMB_VFS_TELLDIR(conn
, dirp
->dir
);
1628 *ptalloced
= talloced
;
1629 dirp
->file_number
++;
1632 *poffset
= dirp
->offset
= END_OF_DIRECTORY_OFFSET
;
1637 /*******************************************************************
1638 Rewind to the start.
1639 ********************************************************************/
1641 void RewindDir(struct smb_Dir
*dirp
, long *poffset
)
1643 SMB_VFS_REWINDDIR(dirp
->conn
, dirp
->dir
);
1644 dirp
->file_number
= 0;
1645 dirp
->offset
= START_OF_DIRECTORY_OFFSET
;
1646 *poffset
= START_OF_DIRECTORY_OFFSET
;
1649 /*******************************************************************
1651 ********************************************************************/
1653 void SeekDir(struct smb_Dir
*dirp
, long offset
)
1655 if (offset
!= dirp
->offset
) {
1656 if (offset
== START_OF_DIRECTORY_OFFSET
) {
1657 RewindDir(dirp
, &offset
);
1659 * Ok we should really set the file number here
1660 * to 1 to enable ".." to be returned next. Trouble
1661 * is I'm worried about callers using SeekDir(dirp,0)
1662 * as equivalent to RewindDir(). So leave this alone
1665 } else if (offset
== DOT_DOT_DIRECTORY_OFFSET
) {
1666 RewindDir(dirp
, &offset
);
1668 * Set the file number to 2 - we want to get the first
1669 * real file entry (the one we return after "..")
1670 * on the next ReadDir.
1672 dirp
->file_number
= 2;
1673 } else if (offset
== END_OF_DIRECTORY_OFFSET
) {
1674 ; /* Don't seek in this case. */
1676 SMB_VFS_SEEKDIR(dirp
->conn
, dirp
->dir
, offset
);
1678 dirp
->offset
= offset
;
1682 /*******************************************************************
1683 Tell a dir position.
1684 ********************************************************************/
1686 long TellDir(struct smb_Dir
*dirp
)
1688 return(dirp
->offset
);
1691 /*******************************************************************
1692 Add an entry into the dcache.
1693 ********************************************************************/
1695 void DirCacheAdd(struct smb_Dir
*dirp
, const char *name
, long offset
)
1697 struct name_cache_entry
*e
;
1699 if (dirp
->name_cache_size
== 0) {
1703 if (dirp
->name_cache
== NULL
) {
1704 dirp
->name_cache
= talloc_zero_array(
1705 dirp
, struct name_cache_entry
, dirp
->name_cache_size
);
1707 if (dirp
->name_cache
== NULL
) {
1712 dirp
->name_cache_index
= (dirp
->name_cache_index
+1) %
1713 dirp
->name_cache_size
;
1714 e
= &dirp
->name_cache
[dirp
->name_cache_index
];
1715 TALLOC_FREE(e
->name
);
1716 e
->name
= talloc_strdup(dirp
, name
);
1720 /*******************************************************************
1721 Find an entry by name. Leave us at the offset after it.
1722 Don't check for veto or invisible files.
1723 ********************************************************************/
1725 bool SearchDir(struct smb_Dir
*dirp
, const char *name
, long *poffset
)
1728 const char *entry
= NULL
;
1729 char *talloced
= NULL
;
1730 connection_struct
*conn
= dirp
->conn
;
1732 /* Search back in the name cache. */
1733 if (dirp
->name_cache_size
&& dirp
->name_cache
) {
1734 for (i
= dirp
->name_cache_index
; i
>= 0; i
--) {
1735 struct name_cache_entry
*e
= &dirp
->name_cache
[i
];
1736 if (e
->name
&& (conn
->case_sensitive
? (strcmp(e
->name
, name
) == 0) : strequal(e
->name
, name
))) {
1737 *poffset
= e
->offset
;
1738 SeekDir(dirp
, e
->offset
);
1742 for (i
= dirp
->name_cache_size
- 1; i
> dirp
->name_cache_index
; i
--) {
1743 struct name_cache_entry
*e
= &dirp
->name_cache
[i
];
1744 if (e
->name
&& (conn
->case_sensitive
? (strcmp(e
->name
, name
) == 0) : strequal(e
->name
, name
))) {
1745 *poffset
= e
->offset
;
1746 SeekDir(dirp
, e
->offset
);
1752 /* Not found in the name cache. Rewind directory and start from scratch. */
1753 SMB_VFS_REWINDDIR(conn
, dirp
->dir
);
1754 dirp
->file_number
= 0;
1755 *poffset
= START_OF_DIRECTORY_OFFSET
;
1756 while ((entry
= ReadDirName(dirp
, poffset
, NULL
, &talloced
))) {
1757 if (conn
->case_sensitive
? (strcmp(entry
, name
) == 0) : strequal(entry
, name
)) {
1758 TALLOC_FREE(talloced
);
1761 TALLOC_FREE(talloced
);
1766 /*****************************************************************
1767 Is this directory empty ?
1768 *****************************************************************/
1770 NTSTATUS
can_delete_directory_fsp(files_struct
*fsp
)
1772 NTSTATUS status
= NT_STATUS_OK
;
1774 const char *dname
= NULL
;
1775 const char *dirname
= fsp
->fsp_name
->base_name
;
1776 char *talloced
= NULL
;
1778 struct connection_struct
*conn
= fsp
->conn
;
1779 struct smb_Dir
*dir_hnd
= OpenDir_fsp(talloc_tos(),
1786 return map_nt_error_from_unix(errno
);
1789 while ((dname
= ReadDirName(dir_hnd
, &dirpos
, &st
, &talloced
))) {
1790 /* Quick check for "." and ".." */
1791 if (dname
[0] == '.') {
1792 if (!dname
[1] || (dname
[1] == '.' && !dname
[2])) {
1793 TALLOC_FREE(talloced
);
1798 if (!is_visible_file(conn
, dirname
, dname
, &st
, True
)) {
1799 TALLOC_FREE(talloced
);
1803 DEBUG(10,("got name %s - can't delete\n",
1805 status
= NT_STATUS_DIRECTORY_NOT_EMPTY
;
1808 TALLOC_FREE(talloced
);
1809 TALLOC_FREE(dir_hnd
);