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"
30 This module implements directory related functions for Samba.
33 /* "Special" directory offsets. */
34 #define END_OF_DIRECTORY_OFFSET ((long)-1)
35 #define START_OF_DIRECTORY_OFFSET ((long)0)
36 #define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000)
38 /* "Special" directory offsets in 32-bit wire format. */
39 #define WIRE_END_OF_DIRECTORY_OFFSET ((uint32_t)0xFFFFFFFF)
40 #define WIRE_START_OF_DIRECTORY_OFFSET ((uint32_t)0)
41 #define WIRE_DOT_DOT_DIRECTORY_OFFSET ((uint32_t)0x80000000)
43 /* Make directory handle internals available. */
45 struct name_cache_entry
{
51 connection_struct
*conn
;
55 size_t name_cache_size
;
56 struct name_cache_entry
*name_cache
;
57 unsigned int name_cache_index
;
58 unsigned int file_number
;
59 files_struct
*fsp
; /* Back pointer to containing fsp, only
60 set from OpenDir_fsp(). */
64 struct dptr_struct
*next
, *prev
;
67 struct connection_struct
*conn
;
68 struct smb_Dir
*dir_hnd
;
73 bool has_wild
; /* Set to true if the wcard entry has MS wildcard characters in it. */
74 bool did_stat
; /* Optimisation for non-wcard searches. */
75 bool priv
; /* Directory handle opened with privilege. */
77 struct memcache
*dptr_cache
;
80 static struct smb_Dir
*OpenDir_fsp(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
85 static void DirCacheAdd(struct smb_Dir
*dirp
, const char *name
, long offset
);
87 #define INVALID_DPTR_KEY (-3)
89 /****************************************************************************
91 ****************************************************************************/
93 bool make_dir_struct(TALLOC_CTX
*ctx
,
103 char *mask2
= talloc_strdup(ctx
, mask
);
109 if ((mode
& FILE_ATTRIBUTE_DIRECTORY
) != 0) {
113 memset(buf
+1,' ',11);
114 if ((p
= strchr_m(mask2
,'.')) != NULL
) {
116 push_ascii(buf
+1,mask2
,8, 0);
117 push_ascii(buf
+9,p
+1,3, 0);
120 push_ascii(buf
+1,mask2
,11, 0);
123 memset(buf
+21,'\0',DIR_STRUCT_SIZE
-21);
125 srv_put_dos_date(buf
,22,date
);
126 SSVAL(buf
,26,size
& 0xFFFF);
127 SSVAL(buf
,28,(size
>> 16)&0xFFFF);
128 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
129 Strange, but verified on W2K3. Needed for OS/2. JRA. */
130 push_ascii(buf
+30,fname
,12, uc
? STR_UPPER
: 0);
131 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf
+30, fname
));
135 /****************************************************************************
136 Initialise the dir bitmap.
137 ****************************************************************************/
139 bool init_dptrs(struct smbd_server_connection
*sconn
)
141 if (sconn
->searches
.dptr_bmap
) {
145 sconn
->searches
.dptr_bmap
= bitmap_talloc(
146 sconn
, MAX_DIRECTORY_HANDLES
);
148 if (sconn
->searches
.dptr_bmap
== NULL
) {
155 /****************************************************************************
156 Idle a dptr - the directory is closed but the control info is kept.
157 ****************************************************************************/
159 static void dptr_idle(struct dptr_struct
*dptr
)
162 DEBUG(4,("Idling dptr dnum %d\n",dptr
->dnum
));
163 TALLOC_FREE(dptr
->dir_hnd
);
164 TALLOC_FREE(dptr
->dptr_cache
);
169 /****************************************************************************
170 Idle the oldest dptr.
171 ****************************************************************************/
173 static void dptr_idleoldest(struct smbd_server_connection
*sconn
)
175 struct dptr_struct
*dptr
;
178 * Go to the end of the list.
180 dptr
= DLIST_TAIL(sconn
->searches
.dirptrs
);
183 DEBUG(0,("No dptrs available to idle ?\n"));
188 * Idle the oldest pointer.
191 for(; dptr
; dptr
= DLIST_PREV(dptr
)) {
199 /****************************************************************************
200 Get the struct dptr_struct for a dir index.
201 ****************************************************************************/
203 static struct dptr_struct
*dptr_get(struct smbd_server_connection
*sconn
,
204 int key
, bool forclose
)
206 struct dptr_struct
*dptr
;
208 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= dptr
->next
) {
209 if(dptr
->dnum
== key
) {
210 if (!forclose
&& !dptr
->dir_hnd
) {
211 if (sconn
->searches
.dirhandles_open
>= MAX_OPEN_DIRECTORIES
)
212 dptr_idleoldest(sconn
);
213 DEBUG(4,("dptr_get: Reopening dptr key %d\n",key
));
214 if (!(dptr
->dir_hnd
= OpenDir(
215 NULL
, dptr
->conn
, dptr
->path
,
216 dptr
->wcard
, dptr
->attr
))) {
217 DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr
->path
,
222 DLIST_PROMOTE(sconn
->searches
.dirptrs
,dptr
);
229 /****************************************************************************
230 Get the dir path for a dir index.
231 ****************************************************************************/
233 const char *dptr_path(struct smbd_server_connection
*sconn
, int key
)
235 struct dptr_struct
*dptr
= dptr_get(sconn
, key
, false);
241 /****************************************************************************
242 Get the dir wcard for a dir index.
243 ****************************************************************************/
245 const char *dptr_wcard(struct smbd_server_connection
*sconn
, int key
)
247 struct dptr_struct
*dptr
= dptr_get(sconn
, key
, false);
253 /****************************************************************************
254 Get the dir attrib for a dir index.
255 ****************************************************************************/
257 uint16
dptr_attr(struct smbd_server_connection
*sconn
, int key
)
259 struct dptr_struct
*dptr
= dptr_get(sconn
, key
, false);
265 /****************************************************************************
266 Close a dptr (internal func).
267 ****************************************************************************/
269 static void dptr_close_internal(struct dptr_struct
*dptr
)
271 struct smbd_server_connection
*sconn
= dptr
->conn
->sconn
;
273 DEBUG(4,("closing dptr key %d\n",dptr
->dnum
));
279 if (sconn
->using_smb2
) {
283 DLIST_REMOVE(sconn
->searches
.dirptrs
, dptr
);
286 * Free the dnum in the bitmap. Remember the dnum value is always
287 * biased by one with respect to the bitmap.
290 if (!bitmap_query(sconn
->searches
.dptr_bmap
, dptr
->dnum
- 1)) {
291 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
295 bitmap_clear(sconn
->searches
.dptr_bmap
, dptr
->dnum
- 1);
298 TALLOC_FREE(dptr
->dir_hnd
);
302 /****************************************************************************
303 Close a dptr given a key.
304 ****************************************************************************/
306 void dptr_close(struct smbd_server_connection
*sconn
, int *key
)
308 struct dptr_struct
*dptr
;
310 if(*key
== INVALID_DPTR_KEY
)
313 /* OS/2 seems to use -1 to indicate "close all directories" */
315 struct dptr_struct
*next
;
316 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= next
) {
318 dptr_close_internal(dptr
);
320 *key
= INVALID_DPTR_KEY
;
324 dptr
= dptr_get(sconn
, *key
, true);
327 DEBUG(0,("Invalid key %d given to dptr_close\n", *key
));
331 dptr_close_internal(dptr
);
333 *key
= INVALID_DPTR_KEY
;
336 /****************************************************************************
337 Close all dptrs for a cnum.
338 ****************************************************************************/
340 void dptr_closecnum(connection_struct
*conn
)
342 struct dptr_struct
*dptr
, *next
;
343 struct smbd_server_connection
*sconn
= conn
->sconn
;
349 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= next
) {
351 if (dptr
->conn
== conn
) {
352 dptr_close_internal(dptr
);
357 /****************************************************************************
358 Idle all dptrs for a cnum.
359 ****************************************************************************/
361 void dptr_idlecnum(connection_struct
*conn
)
363 struct dptr_struct
*dptr
;
364 struct smbd_server_connection
*sconn
= conn
->sconn
;
370 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= dptr
->next
) {
371 if (dptr
->conn
== conn
&& dptr
->dir_hnd
) {
377 /****************************************************************************
378 Close a dptr that matches a given path, only if it matches the spid also.
379 ****************************************************************************/
381 void dptr_closepath(struct smbd_server_connection
*sconn
,
382 char *path
,uint16 spid
)
384 struct dptr_struct
*dptr
, *next
;
385 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= next
) {
387 if (spid
== dptr
->spid
&& strequal(dptr
->path
,path
))
388 dptr_close_internal(dptr
);
392 /****************************************************************************
393 Try and close the oldest handle not marked for
394 expect close in the hope that the client has
395 finished with that one.
396 ****************************************************************************/
398 static void dptr_close_oldest(struct smbd_server_connection
*sconn
,
401 struct dptr_struct
*dptr
;
404 * Go to the end of the list.
406 for(dptr
= sconn
->searches
.dirptrs
; dptr
&& dptr
->next
; dptr
= dptr
->next
)
410 DEBUG(0,("No old dptrs available to close oldest ?\n"));
415 * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
416 * does not have expect_close set. If 'old' is false, close
417 * one of the new dnum handles.
420 for(; dptr
; dptr
= DLIST_PREV(dptr
)) {
421 if ((old
&& (dptr
->dnum
< 256) && !dptr
->expect_close
) ||
422 (!old
&& (dptr
->dnum
> 255))) {
423 dptr_close_internal(dptr
);
429 /****************************************************************************
430 Safely do an OpenDir as root, ensuring we're in the right place.
431 ****************************************************************************/
433 static struct smb_Dir
*open_dir_with_privilege(connection_struct
*conn
,
434 struct smb_request
*req
,
439 struct smb_Dir
*dir_hnd
= NULL
;
440 struct smb_filename
*smb_fname_cwd
;
441 char *saved_dir
= vfs_GetWd(talloc_tos(), conn
);
442 struct privilege_paths
*priv_paths
= req
->priv_paths
;
445 if (saved_dir
== NULL
) {
449 if (vfs_ChDir(conn
, path
) == -1) {
453 /* Now check the stat value is the same. */
454 smb_fname_cwd
= synthetic_smb_fname(talloc_tos(), ".", NULL
, NULL
);
456 if (smb_fname_cwd
== NULL
) {
459 ret
= SMB_VFS_STAT(conn
, smb_fname_cwd
);
464 if (!check_same_stat(&smb_fname_cwd
->st
, &priv_paths
->parent_name
.st
)) {
465 DEBUG(0,("open_dir_with_privilege: stat mismatch between %s "
468 smb_fname_str_dbg(&priv_paths
->parent_name
)));
472 dir_hnd
= OpenDir(NULL
, conn
, ".", wcard
, attr
);
476 vfs_ChDir(conn
, saved_dir
);
480 /****************************************************************************
481 Create a new dir ptr. If the flag old_handle is true then we must allocate
482 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
483 one byte long. If old_handle is false we allocate from the range
484 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
485 a directory handle is never zero.
486 wcard must not be zero.
487 ****************************************************************************/
489 NTSTATUS
dptr_create(connection_struct
*conn
,
490 struct smb_request
*req
,
492 const char *path
, bool old_handle
, bool expect_close
,uint16 spid
,
493 const char *wcard
, bool wcard_has_wild
, uint32 attr
, struct dptr_struct
**dptr_ret
)
495 struct smbd_server_connection
*sconn
= conn
->sconn
;
496 struct dptr_struct
*dptr
= NULL
;
497 struct smb_Dir
*dir_hnd
;
499 if (fsp
&& fsp
->is_directory
&& fsp
->fh
->fd
!= -1) {
500 path
= fsp
->fsp_name
->base_name
;
503 DEBUG(5,("dptr_create dir=%s\n", path
));
506 DEBUG(0,("dptr_create: called with fake connection_struct\n"));
507 return NT_STATUS_INTERNAL_ERROR
;
511 return NT_STATUS_INVALID_PARAMETER
;
515 if (!(fsp
->access_mask
& SEC_DIR_LIST
)) {
516 DEBUG(5,("dptr_create: directory %s "
517 "not open for LIST access\n",
519 return NT_STATUS_ACCESS_DENIED
;
521 dir_hnd
= OpenDir_fsp(NULL
, conn
, fsp
, wcard
, attr
);
524 bool backup_intent
= (req
&& req
->priv_paths
);
525 struct smb_filename
*smb_dname
;
528 smb_dname
= synthetic_smb_fname(talloc_tos(), path
,
530 if (smb_dname
== NULL
) {
531 return NT_STATUS_NO_MEMORY
;
533 if (lp_posix_pathnames()) {
534 ret
= SMB_VFS_LSTAT(conn
, smb_dname
);
536 ret
= SMB_VFS_STAT(conn
, smb_dname
);
539 return map_nt_error_from_unix(errno
);
541 if (!S_ISDIR(smb_dname
->st
.st_ex_mode
)) {
542 return NT_STATUS_NOT_A_DIRECTORY
;
544 status
= smbd_check_access_rights(conn
,
548 if (!NT_STATUS_IS_OK(status
)) {
552 dir_hnd
= open_dir_with_privilege(conn
,
558 dir_hnd
= OpenDir(NULL
, conn
, path
, wcard
, attr
);
563 return map_nt_error_from_unix(errno
);
566 if (sconn
->searches
.dirhandles_open
>= MAX_OPEN_DIRECTORIES
) {
567 dptr_idleoldest(sconn
);
570 dptr
= talloc(NULL
, struct dptr_struct
);
572 DEBUG(0,("talloc fail in dptr_create.\n"));
573 TALLOC_FREE(dir_hnd
);
574 return NT_STATUS_NO_MEMORY
;
579 dptr
->path
= talloc_strdup(dptr
, path
);
582 TALLOC_FREE(dir_hnd
);
583 return NT_STATUS_NO_MEMORY
;
586 dptr
->dir_hnd
= dir_hnd
;
588 dptr
->expect_close
= expect_close
;
589 dptr
->wcard
= talloc_strdup(dptr
, wcard
);
592 TALLOC_FREE(dir_hnd
);
593 return NT_STATUS_NO_MEMORY
;
595 if (lp_posix_pathnames() || (wcard
[0] == '.' && wcard
[1] == 0)) {
596 dptr
->has_wild
= True
;
598 dptr
->has_wild
= wcard_has_wild
;
603 if (sconn
->using_smb2
) {
610 * This is an old-style SMBsearch request. Ensure the
611 * value we return will fit in the range 1-255.
614 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 0);
616 if(dptr
->dnum
== -1 || dptr
->dnum
> 254) {
619 * Try and close the oldest handle not marked for
620 * expect close in the hope that the client has
621 * finished with that one.
624 dptr_close_oldest(sconn
, true);
626 /* Now try again... */
627 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 0);
628 if(dptr
->dnum
== -1 || dptr
->dnum
> 254) {
629 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr
->dnum
));
631 TALLOC_FREE(dir_hnd
);
632 return NT_STATUS_TOO_MANY_OPENED_FILES
;
638 * This is a new-style trans2 request. Allocate from
639 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
642 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 255);
644 if(dptr
->dnum
== -1 || dptr
->dnum
< 255) {
647 * Try and close the oldest handle close in the hope that
648 * the client has finished with that one. This will only
649 * happen in the case of the Win98 client bug where it leaks
653 dptr_close_oldest(sconn
, false);
655 /* Now try again... */
656 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 255);
658 if(dptr
->dnum
== -1 || dptr
->dnum
< 255) {
659 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr
->dnum
));
661 TALLOC_FREE(dir_hnd
);
662 return NT_STATUS_TOO_MANY_OPENED_FILES
;
667 bitmap_set(sconn
->searches
.dptr_bmap
, dptr
->dnum
);
669 dptr
->dnum
+= 1; /* Always bias the dnum by one - no zero dnums allowed. */
671 DLIST_ADD(sconn
->searches
.dirptrs
, dptr
);
674 DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
675 dptr
->dnum
,path
,expect_close
));
683 /****************************************************************************
684 Wrapper functions to access the lower level directory handles.
685 ****************************************************************************/
687 void dptr_CloseDir(files_struct
*fsp
)
691 * The destructor for the struct smb_Dir
692 * (fsp->dptr->dir_hnd) now handles
693 * all resource deallocation.
695 dptr_close_internal(fsp
->dptr
);
700 void dptr_SeekDir(struct dptr_struct
*dptr
, long offset
)
702 SeekDir(dptr
->dir_hnd
, offset
);
705 long dptr_TellDir(struct dptr_struct
*dptr
)
707 return TellDir(dptr
->dir_hnd
);
710 bool dptr_has_wild(struct dptr_struct
*dptr
)
712 return dptr
->has_wild
;
715 int dptr_dnum(struct dptr_struct
*dptr
)
720 bool dptr_get_priv(struct dptr_struct
*dptr
)
725 void dptr_set_priv(struct dptr_struct
*dptr
)
730 /****************************************************************************
731 Return the next visible file name, skipping veto'd and invisible files.
732 ****************************************************************************/
734 static const char *dptr_normal_ReadDirName(struct dptr_struct
*dptr
,
735 long *poffset
, SMB_STRUCT_STAT
*pst
,
738 /* Normal search for the next file. */
740 char *talloced
= NULL
;
742 while ((name
= ReadDirName(dptr
->dir_hnd
, poffset
, pst
, &talloced
))
744 if (is_visible_file(dptr
->conn
, dptr
->path
, name
, pst
, True
)) {
745 *ptalloced
= talloced
;
748 TALLOC_FREE(talloced
);
753 /****************************************************************************
754 Return the next visible file name, skipping veto'd and invisible files.
755 ****************************************************************************/
757 static char *dptr_ReadDirName(TALLOC_CTX
*ctx
,
758 struct dptr_struct
*dptr
,
760 SMB_STRUCT_STAT
*pst
)
762 struct smb_filename smb_fname_base
;
764 const char *name_temp
= NULL
;
765 char *talloced
= NULL
;
766 char *pathreal
= NULL
;
767 char *found_name
= NULL
;
770 SET_STAT_INVALID(*pst
);
772 if (dptr
->has_wild
|| dptr
->did_stat
) {
773 name_temp
= dptr_normal_ReadDirName(dptr
, poffset
, pst
,
775 if (name_temp
== NULL
) {
778 if (talloced
!= NULL
) {
779 return talloc_move(ctx
, &talloced
);
781 return talloc_strdup(ctx
, name_temp
);
784 /* If poffset is -1 then we know we returned this name before and we
785 * have no wildcards. We're at the end of the directory. */
786 if (*poffset
== END_OF_DIRECTORY_OFFSET
) {
790 /* We know the stored wcard contains no wildcard characters.
791 * See if we can match with a stat call. If we can't, then set
792 * did_stat to true to ensure we only do this once and keep
795 dptr
->did_stat
= true;
797 /* First check if it should be visible. */
798 if (!is_visible_file(dptr
->conn
, dptr
->path
, dptr
->wcard
,
801 /* This only returns false if the file was found, but
802 is explicitly not visible. Set us to end of
803 directory, but return NULL as we know we can't ever
808 if (VALID_STAT(*pst
)) {
809 name
= talloc_strdup(ctx
, dptr
->wcard
);
813 pathreal
= talloc_asprintf(ctx
,
820 /* Create an smb_filename with stream_name == NULL. */
821 ZERO_STRUCT(smb_fname_base
);
822 smb_fname_base
.base_name
= pathreal
;
824 if (SMB_VFS_STAT(dptr
->conn
, &smb_fname_base
) == 0) {
825 *pst
= smb_fname_base
.st
;
826 name
= talloc_strdup(ctx
, dptr
->wcard
);
829 /* If we get any other error than ENOENT or ENOTDIR
830 then the file exists we just can't stat it. */
831 if (errno
!= ENOENT
&& errno
!= ENOTDIR
) {
832 name
= talloc_strdup(ctx
, dptr
->wcard
);
837 /* Stat failed. We know this is authoratiative if we are
838 * providing case sensitive semantics or the underlying
839 * filesystem is case sensitive.
841 if (dptr
->conn
->case_sensitive
||
842 !(dptr
->conn
->fs_capabilities
& FILE_CASE_SENSITIVE_SEARCH
))
848 * Try case-insensitive stat if the fs has the ability. This avoids
849 * scanning the whole directory.
851 ret
= SMB_VFS_GET_REAL_FILENAME(dptr
->conn
, dptr
->path
, dptr
->wcard
,
856 } else if (errno
== ENOENT
) {
857 /* The case-insensitive lookup was authoritative. */
861 TALLOC_FREE(pathreal
);
863 name_temp
= dptr_normal_ReadDirName(dptr
, poffset
, pst
, &talloced
);
864 if (name_temp
== NULL
) {
867 if (talloced
!= NULL
) {
868 return talloc_move(ctx
, &talloced
);
870 return talloc_strdup(ctx
, name_temp
);
873 TALLOC_FREE(pathreal
);
875 /* We need to set the underlying dir_hnd offset to -1
876 * also as this function is usually called with the
877 * output from TellDir. */
878 dptr
->dir_hnd
->offset
= *poffset
= END_OF_DIRECTORY_OFFSET
;
882 /****************************************************************************
883 Search for a file by name, skipping veto'ed and not visible files.
884 ****************************************************************************/
886 bool dptr_SearchDir(struct dptr_struct
*dptr
, const char *name
, long *poffset
, SMB_STRUCT_STAT
*pst
)
888 SET_STAT_INVALID(*pst
);
890 if (!dptr
->has_wild
&& (dptr
->dir_hnd
->offset
== END_OF_DIRECTORY_OFFSET
)) {
891 /* This is a singleton directory and we're already at the end. */
892 *poffset
= END_OF_DIRECTORY_OFFSET
;
896 return SearchDir(dptr
->dir_hnd
, name
, poffset
);
899 /****************************************************************************
900 Initialize variables & state data at the beginning of all search SMB requests.
901 ****************************************************************************/
902 void dptr_init_search_op(struct dptr_struct
*dptr
)
904 SMB_VFS_INIT_SEARCH_OP(dptr
->conn
, dptr
->dir_hnd
->dir
);
907 /****************************************************************************
908 Map a native directory offset to a 32-bit cookie.
909 ****************************************************************************/
911 static uint32_t map_dir_offset_to_wire(struct dptr_struct
*dptr
, long offset
)
916 if (offset
== END_OF_DIRECTORY_OFFSET
) {
917 return WIRE_END_OF_DIRECTORY_OFFSET
;
918 } else if(offset
== START_OF_DIRECTORY_OFFSET
) {
919 return WIRE_START_OF_DIRECTORY_OFFSET
;
920 } else if (offset
== DOT_DOT_DIRECTORY_OFFSET
) {
921 return WIRE_DOT_DOT_DIRECTORY_OFFSET
;
923 if (sizeof(long) == 4) {
924 /* 32-bit machine. We can cheat... */
925 return (uint32_t)offset
;
927 if (dptr
->dptr_cache
== NULL
) {
928 /* Lazy initialize cache. */
929 dptr
->dptr_cache
= memcache_init(dptr
, 0);
930 if (dptr
->dptr_cache
== NULL
) {
931 return WIRE_END_OF_DIRECTORY_OFFSET
;
934 /* Have we seen this offset before ? */
935 key
.data
= (void *)&offset
;
936 key
.length
= sizeof(offset
);
937 if (memcache_lookup(dptr
->dptr_cache
,
938 SMB1_SEARCH_OFFSET_MAP
,
941 uint32_t wire_offset
;
942 SMB_ASSERT(val
.length
== sizeof(wire_offset
));
943 memcpy(&wire_offset
, val
.data
, sizeof(wire_offset
));
944 DEBUG(10,("found wire %u <-> offset %ld\n",
945 (unsigned int)wire_offset
,
950 /* Allocate a new wire cookie. */
953 } while (dptr
->counter
== WIRE_START_OF_DIRECTORY_OFFSET
||
954 dptr
->counter
== WIRE_END_OF_DIRECTORY_OFFSET
||
955 dptr
->counter
== WIRE_DOT_DOT_DIRECTORY_OFFSET
);
956 /* Store it in the cache. */
957 key
.data
= (void *)&offset
;
958 key
.length
= sizeof(offset
);
959 val
.data
= (void *)&dptr
->counter
;
960 val
.length
= sizeof(dptr
->counter
); /* MUST BE uint32_t ! */
961 memcache_add(dptr
->dptr_cache
,
962 SMB1_SEARCH_OFFSET_MAP
,
965 /* And the reverse mapping for lookup from
966 map_wire_to_dir_offset(). */
967 memcache_add(dptr
->dptr_cache
,
968 SMB1_SEARCH_OFFSET_MAP
,
971 DEBUG(10,("stored wire %u <-> offset %ld\n",
972 (unsigned int)dptr
->counter
,
974 return dptr
->counter
;
977 /****************************************************************************
978 Fill the 5 byte server reserved dptr field.
979 ****************************************************************************/
981 bool dptr_fill(struct smbd_server_connection
*sconn
,
982 char *buf1
,unsigned int key
)
984 unsigned char *buf
= (unsigned char *)buf1
;
985 struct dptr_struct
*dptr
= dptr_get(sconn
, key
, false);
986 uint32_t wire_offset
;
988 DEBUG(1,("filling null dirptr %d\n",key
));
991 wire_offset
= map_dir_offset_to_wire(dptr
,TellDir(dptr
->dir_hnd
));
992 DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key
,
993 (long)dptr
->dir_hnd
,(int)wire_offset
));
995 SIVAL(buf
,1,wire_offset
);
999 /****************************************************************************
1000 Map a 32-bit wire cookie to a native directory offset.
1001 ****************************************************************************/
1003 static long map_wire_to_dir_offset(struct dptr_struct
*dptr
, uint32_t wire_offset
)
1008 if (wire_offset
== WIRE_END_OF_DIRECTORY_OFFSET
) {
1009 return END_OF_DIRECTORY_OFFSET
;
1010 } else if(wire_offset
== WIRE_START_OF_DIRECTORY_OFFSET
) {
1011 return START_OF_DIRECTORY_OFFSET
;
1012 } else if (wire_offset
== WIRE_DOT_DOT_DIRECTORY_OFFSET
) {
1013 return DOT_DOT_DIRECTORY_OFFSET
;
1015 if (sizeof(long) == 4) {
1016 /* 32-bit machine. We can cheat... */
1017 return (long)wire_offset
;
1019 if (dptr
->dptr_cache
== NULL
) {
1020 /* Logic error, cache should be initialized. */
1021 return END_OF_DIRECTORY_OFFSET
;
1023 key
.data
= (void *)&wire_offset
;
1024 key
.length
= sizeof(wire_offset
);
1025 if (memcache_lookup(dptr
->dptr_cache
,
1026 SMB1_SEARCH_OFFSET_MAP
,
1029 /* Found mapping. */
1031 SMB_ASSERT(val
.length
== sizeof(offset
));
1032 memcpy(&offset
, val
.data
, sizeof(offset
));
1033 DEBUG(10,("lookup wire %u <-> offset %ld\n",
1034 (unsigned int)wire_offset
,
1038 return END_OF_DIRECTORY_OFFSET
;
1041 /****************************************************************************
1042 Fetch the dir ptr and seek it given the 5 byte server field.
1043 ****************************************************************************/
1045 struct dptr_struct
*dptr_fetch(struct smbd_server_connection
*sconn
,
1046 char *buf
, int *num
)
1048 unsigned int key
= *(unsigned char *)buf
;
1049 struct dptr_struct
*dptr
= dptr_get(sconn
, key
, false);
1050 uint32_t wire_offset
;
1054 DEBUG(3,("fetched null dirptr %d\n",key
));
1058 wire_offset
= IVAL(buf
,1);
1059 seekoff
= map_wire_to_dir_offset(dptr
, wire_offset
);
1060 SeekDir(dptr
->dir_hnd
,seekoff
);
1061 DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
1062 key
, dptr
->path
, (int)seekoff
));
1066 /****************************************************************************
1068 ****************************************************************************/
1070 struct dptr_struct
*dptr_fetch_lanman2(struct smbd_server_connection
*sconn
,
1073 struct dptr_struct
*dptr
= dptr_get(sconn
, dptr_num
, false);
1076 DEBUG(3,("fetched null dirptr %d\n",dptr_num
));
1079 DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num
,dptr
->path
));
1083 static bool mangle_mask_match(connection_struct
*conn
,
1084 const char *filename
,
1089 if (!name_to_8_3(filename
,mname
,False
,conn
->params
)) {
1092 return mask_match_search(mname
,mask
,False
);
1095 bool smbd_dirptr_get_entry(TALLOC_CTX
*ctx
,
1096 struct dptr_struct
*dirptr
,
1101 bool (*match_fn
)(TALLOC_CTX
*ctx
,
1106 bool (*mode_fn
)(TALLOC_CTX
*ctx
,
1108 struct smb_filename
*smb_fname
,
1112 struct smb_filename
**_smb_fname
,
1116 connection_struct
*conn
= dirptr
->conn
;
1123 pathlen
= strlen(dirptr
->path
);
1124 slashlen
= ( dirptr
->path
[pathlen
-1] != '/') ? 1 : 0;
1129 SMB_STRUCT_STAT sbuf
;
1133 char *pathreal
= NULL
;
1134 struct smb_filename smb_fname
;
1138 cur_offset
= dptr_TellDir(dirptr
);
1139 prev_offset
= cur_offset
;
1140 dname
= dptr_ReadDirName(ctx
, dirptr
, &cur_offset
, &sbuf
);
1142 DEBUG(6,("smbd_dirptr_get_entry: dirptr 0x%lx now at offset %ld\n",
1143 (long)dirptr
, cur_offset
));
1145 if (dname
== NULL
) {
1149 isdots
= (ISDOT(dname
) || ISDOTDOT(dname
));
1150 if (dont_descend
&& !isdots
) {
1156 * fname may get mangled, dname is never mangled.
1157 * Whenever we're accessing the filesystem we use
1158 * pathreal which is composed from dname.
1161 ok
= match_fn(ctx
, private_data
, dname
, mask
, &fname
);
1169 * pathreal = talloc_asprintf(ctx, "%s%s%s", dirptr->path,
1170 * needslash?"/":"", dname);
1171 * but this was measurably slower than doing the memcpy.
1174 pathreal
= talloc_array(
1176 pathlen
+ slashlen
+ talloc_get_size(dname
));
1183 memcpy(pathreal
, dirptr
->path
, pathlen
);
1184 pathreal
[pathlen
] = '/';
1185 memcpy(pathreal
+ slashlen
+ pathlen
, dname
,
1186 talloc_get_size(dname
));
1188 /* Create smb_fname with NULL stream_name. */
1189 ZERO_STRUCT(smb_fname
);
1190 smb_fname
.base_name
= pathreal
;
1191 smb_fname
.st
= sbuf
;
1193 ok
= mode_fn(ctx
, private_data
, &smb_fname
, &mode
);
1197 TALLOC_FREE(pathreal
);
1201 if (!dir_check_ftype(mode
, dirtype
)) {
1202 DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",
1203 fname
, (unsigned int)mode
, (unsigned int)dirtype
));
1206 TALLOC_FREE(pathreal
);
1210 if (ask_sharemode
) {
1211 struct timespec write_time_ts
;
1212 struct file_id fileid
;
1214 fileid
= vfs_file_id_from_sbuf(conn
,
1216 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1217 if (!null_timespec(write_time_ts
)) {
1218 update_stat_ex_mtime(&smb_fname
.st
,
1223 DEBUG(3,("smbd_dirptr_get_entry mask=[%s] found %s "
1225 mask
, smb_fname_str_dbg(&smb_fname
),
1228 DirCacheAdd(dirptr
->dir_hnd
, dname
, cur_offset
);
1232 *_smb_fname
= cp_smb_filename(ctx
, &smb_fname
);
1233 TALLOC_FREE(pathreal
);
1234 if (*_smb_fname
== NULL
) {
1239 *_prev_offset
= prev_offset
;
1247 /****************************************************************************
1248 Get an 8.3 directory entry.
1249 ****************************************************************************/
1251 static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX
*ctx
,
1257 connection_struct
*conn
= (connection_struct
*)private_data
;
1259 if ((strcmp(mask
,"*.*") == 0) ||
1260 mask_match_search(dname
, mask
, false) ||
1261 mangle_mask_match(conn
, dname
, mask
)) {
1265 if (!mangle_is_8_3(dname
, false, conn
->params
)) {
1266 bool ok
= name_to_8_3(dname
, mname
, false,
1276 *_fname
= talloc_strdup(ctx
, fname
);
1277 if (*_fname
== NULL
) {
1287 static bool smbd_dirptr_8_3_mode_fn(TALLOC_CTX
*ctx
,
1289 struct smb_filename
*smb_fname
,
1292 connection_struct
*conn
= (connection_struct
*)private_data
;
1294 if (!VALID_STAT(smb_fname
->st
)) {
1295 if ((SMB_VFS_STAT(conn
, smb_fname
)) != 0) {
1296 DEBUG(5,("smbd_dirptr_8_3_mode_fn: "
1297 "Couldn't stat [%s]. Error "
1299 smb_fname_str_dbg(smb_fname
),
1305 *_mode
= dos_mode(conn
, smb_fname
);
1309 bool get_dir_entry(TALLOC_CTX
*ctx
,
1310 struct dptr_struct
*dirptr
,
1316 struct timespec
*_date
,
1320 connection_struct
*conn
= dirptr
->conn
;
1322 struct smb_filename
*smb_fname
= NULL
;
1327 ok
= smbd_dirptr_get_entry(ctx
,
1333 smbd_dirptr_8_3_match_fn
,
1334 smbd_dirptr_8_3_mode_fn
,
1344 *_fname
= talloc_move(ctx
, &fname
);
1345 *_size
= smb_fname
->st
.st_ex_size
;
1347 *_date
= smb_fname
->st
.st_ex_mtime
;
1348 TALLOC_FREE(smb_fname
);
1352 /*******************************************************************
1353 Check to see if a user can read a file. This is only approximate,
1354 it is used as part of the "hide unreadable" option. Don't
1355 use it for anything security sensitive.
1356 ********************************************************************/
1358 static bool user_can_read_file(connection_struct
*conn
,
1359 struct smb_filename
*smb_fname
)
1362 * Never hide files from the root user.
1363 * We use (uid_t)0 here not sec_initial_uid()
1364 * as make test uses a single user context.
1367 if (get_current_uid(conn
) == (uid_t
)0) {
1371 return NT_STATUS_IS_OK(smbd_check_access_rights(conn
,
1377 /*******************************************************************
1378 Check to see if a user can write a file (and only files, we do not
1379 check dirs on this one). This is only approximate,
1380 it is used as part of the "hide unwriteable" option. Don't
1381 use it for anything security sensitive.
1382 ********************************************************************/
1384 static bool user_can_write_file(connection_struct
*conn
,
1385 const struct smb_filename
*smb_fname
)
1388 * Never hide files from the root user.
1389 * We use (uid_t)0 here not sec_initial_uid()
1390 * as make test uses a single user context.
1393 if (get_current_uid(conn
) == (uid_t
)0) {
1397 SMB_ASSERT(VALID_STAT(smb_fname
->st
));
1399 /* Pseudo-open the file */
1401 if(S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1405 return can_write_to_file(conn
, smb_fname
);
1408 /*******************************************************************
1409 Is a file a "special" type ?
1410 ********************************************************************/
1412 static bool file_is_special(connection_struct
*conn
,
1413 const struct smb_filename
*smb_fname
)
1416 * Never hide files from the root user.
1417 * We use (uid_t)0 here not sec_initial_uid()
1418 * as make test uses a single user context.
1421 if (get_current_uid(conn
) == (uid_t
)0) {
1425 SMB_ASSERT(VALID_STAT(smb_fname
->st
));
1427 if (S_ISREG(smb_fname
->st
.st_ex_mode
) ||
1428 S_ISDIR(smb_fname
->st
.st_ex_mode
) ||
1429 S_ISLNK(smb_fname
->st
.st_ex_mode
))
1435 /*******************************************************************
1436 Should the file be seen by the client?
1437 NOTE: A successful return is no guarantee of the file's existence.
1438 ********************************************************************/
1440 bool is_visible_file(connection_struct
*conn
, const char *dir_path
,
1441 const char *name
, SMB_STRUCT_STAT
*pst
, bool use_veto
)
1443 bool hide_unreadable
= lp_hide_unreadable(SNUM(conn
));
1444 bool hide_unwriteable
= lp_hide_unwriteable_files(SNUM(conn
));
1445 bool hide_special
= lp_hide_special_files(SNUM(conn
));
1447 struct smb_filename
*smb_fname_base
= NULL
;
1450 if ((strcmp(".",name
) == 0) || (strcmp("..",name
) == 0)) {
1451 return True
; /* . and .. are always visible. */
1454 /* If it's a vetoed file, pretend it doesn't even exist */
1455 if (use_veto
&& IS_VETO_PATH(conn
, name
)) {
1456 DEBUG(10,("is_visible_file: file %s is vetoed.\n", name
));
1460 if (hide_unreadable
|| hide_unwriteable
|| hide_special
) {
1461 entry
= talloc_asprintf(talloc_tos(), "%s/%s", dir_path
, name
);
1467 /* Create an smb_filename with stream_name == NULL. */
1468 smb_fname_base
= synthetic_smb_fname(talloc_tos(), entry
, NULL
,
1470 if (smb_fname_base
== NULL
) {
1475 /* If the file name does not exist, there's no point checking
1476 * the configuration options. We succeed, on the basis that the
1477 * checks *might* have passed if the file was present.
1479 if (!VALID_STAT(*pst
)) {
1480 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
1484 *pst
= smb_fname_base
->st
;
1488 /* Honour _hide unreadable_ option */
1489 if (hide_unreadable
&&
1490 !user_can_read_file(conn
, smb_fname_base
)) {
1491 DEBUG(10,("is_visible_file: file %s is unreadable.\n",
1496 /* Honour _hide unwriteable_ option */
1497 if (hide_unwriteable
&& !user_can_write_file(conn
,
1499 DEBUG(10,("is_visible_file: file %s is unwritable.\n",
1504 /* Honour _hide_special_ option */
1505 if (hide_special
&& file_is_special(conn
, smb_fname_base
)) {
1506 DEBUG(10,("is_visible_file: file %s is special.\n",
1515 TALLOC_FREE(smb_fname_base
);
1520 static int smb_Dir_destructor(struct smb_Dir
*dirp
)
1522 if (dirp
->dir
!= NULL
) {
1523 SMB_VFS_CLOSEDIR(dirp
->conn
,dirp
->dir
);
1524 if (dirp
->fsp
!= NULL
) {
1526 * The SMB_VFS_CLOSEDIR above
1527 * closes the underlying fd inside
1530 dirp
->fsp
->fh
->fd
= -1;
1531 if (dirp
->fsp
->dptr
!= NULL
) {
1532 SMB_ASSERT(dirp
->fsp
->dptr
->dir_hnd
== dirp
);
1533 dirp
->fsp
->dptr
->dir_hnd
= NULL
;
1538 if (dirp
->conn
->sconn
&& !dirp
->conn
->sconn
->using_smb2
) {
1539 dirp
->conn
->sconn
->searches
.dirhandles_open
--;
1544 /*******************************************************************
1546 ********************************************************************/
1548 struct smb_Dir
*OpenDir(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
1553 struct smb_Dir
*dirp
= talloc_zero(mem_ctx
, struct smb_Dir
);
1554 struct smbd_server_connection
*sconn
= conn
->sconn
;
1561 dirp
->name_cache_size
= lp_directory_name_cache_size(SNUM(conn
));
1563 dirp
->dir_path
= talloc_strdup(dirp
, name
);
1564 if (!dirp
->dir_path
) {
1569 if (sconn
&& !sconn
->using_smb2
) {
1570 sconn
->searches
.dirhandles_open
++;
1572 talloc_set_destructor(dirp
, smb_Dir_destructor
);
1574 dirp
->dir
= SMB_VFS_OPENDIR(conn
, dirp
->dir_path
, mask
, attr
);
1576 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp
->dir_path
,
1588 /*******************************************************************
1589 Open a directory from an fsp.
1590 ********************************************************************/
1592 static struct smb_Dir
*OpenDir_fsp(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
1597 struct smb_Dir
*dirp
= talloc_zero(mem_ctx
, struct smb_Dir
);
1598 struct smbd_server_connection
*sconn
= conn
->sconn
;
1605 dirp
->name_cache_size
= lp_directory_name_cache_size(SNUM(conn
));
1607 dirp
->dir_path
= talloc_strdup(dirp
, fsp
->fsp_name
->base_name
);
1608 if (!dirp
->dir_path
) {
1613 if (sconn
&& !sconn
->using_smb2
) {
1614 sconn
->searches
.dirhandles_open
++;
1616 talloc_set_destructor(dirp
, smb_Dir_destructor
);
1618 if (fsp
->is_directory
&& fsp
->fh
->fd
!= -1) {
1619 dirp
->dir
= SMB_VFS_FDOPENDIR(fsp
, mask
, attr
);
1620 if (dirp
->dir
!= NULL
) {
1623 DEBUG(10,("OpenDir_fsp: SMB_VFS_FDOPENDIR on %s returned "
1627 if (errno
!= ENOSYS
) {
1633 if (dirp
->dir
== NULL
) {
1634 /* FDOPENDIR didn't work. Use OPENDIR instead. */
1635 dirp
->dir
= SMB_VFS_OPENDIR(conn
, dirp
->dir_path
, mask
, attr
);
1639 DEBUG(5,("OpenDir_fsp: Can't open %s. %s\n", dirp
->dir_path
,
1652 /*******************************************************************
1653 Read from a directory.
1654 Return directory entry, current offset, and optional stat information.
1655 Don't check for veto or invisible files.
1656 ********************************************************************/
1658 const char *ReadDirName(struct smb_Dir
*dirp
, long *poffset
,
1659 SMB_STRUCT_STAT
*sbuf
, char **ptalloced
)
1662 char *talloced
= NULL
;
1663 connection_struct
*conn
= dirp
->conn
;
1665 /* Cheat to allow . and .. to be the first entries returned. */
1666 if (((*poffset
== START_OF_DIRECTORY_OFFSET
) ||
1667 (*poffset
== DOT_DOT_DIRECTORY_OFFSET
)) && (dirp
->file_number
< 2))
1669 if (dirp
->file_number
== 0) {
1671 *poffset
= dirp
->offset
= START_OF_DIRECTORY_OFFSET
;
1674 *poffset
= dirp
->offset
= DOT_DOT_DIRECTORY_OFFSET
;
1676 dirp
->file_number
++;
1679 } else if (*poffset
== END_OF_DIRECTORY_OFFSET
) {
1680 *poffset
= dirp
->offset
= END_OF_DIRECTORY_OFFSET
;
1683 /* A real offset, seek to it. */
1684 SeekDir(dirp
, *poffset
);
1687 while ((n
= vfs_readdirname(conn
, dirp
->dir
, sbuf
, &talloced
))) {
1688 /* Ignore . and .. - we've already returned them. */
1690 if ((n
[1] == '\0') || (n
[1] == '.' && n
[2] == '\0')) {
1691 TALLOC_FREE(talloced
);
1695 *poffset
= dirp
->offset
= SMB_VFS_TELLDIR(conn
, dirp
->dir
);
1696 *ptalloced
= talloced
;
1697 dirp
->file_number
++;
1700 *poffset
= dirp
->offset
= END_OF_DIRECTORY_OFFSET
;
1705 /*******************************************************************
1706 Rewind to the start.
1707 ********************************************************************/
1709 void RewindDir(struct smb_Dir
*dirp
, long *poffset
)
1711 SMB_VFS_REWINDDIR(dirp
->conn
, dirp
->dir
);
1712 dirp
->file_number
= 0;
1713 dirp
->offset
= START_OF_DIRECTORY_OFFSET
;
1714 *poffset
= START_OF_DIRECTORY_OFFSET
;
1717 /*******************************************************************
1719 ********************************************************************/
1721 void SeekDir(struct smb_Dir
*dirp
, long offset
)
1723 if (offset
!= dirp
->offset
) {
1724 if (offset
== START_OF_DIRECTORY_OFFSET
) {
1725 RewindDir(dirp
, &offset
);
1727 * Ok we should really set the file number here
1728 * to 1 to enable ".." to be returned next. Trouble
1729 * is I'm worried about callers using SeekDir(dirp,0)
1730 * as equivalent to RewindDir(). So leave this alone
1733 } else if (offset
== DOT_DOT_DIRECTORY_OFFSET
) {
1734 RewindDir(dirp
, &offset
);
1736 * Set the file number to 2 - we want to get the first
1737 * real file entry (the one we return after "..")
1738 * on the next ReadDir.
1740 dirp
->file_number
= 2;
1741 } else if (offset
== END_OF_DIRECTORY_OFFSET
) {
1742 ; /* Don't seek in this case. */
1744 SMB_VFS_SEEKDIR(dirp
->conn
, dirp
->dir
, offset
);
1746 dirp
->offset
= offset
;
1750 /*******************************************************************
1751 Tell a dir position.
1752 ********************************************************************/
1754 long TellDir(struct smb_Dir
*dirp
)
1756 return(dirp
->offset
);
1759 /*******************************************************************
1760 Add an entry into the dcache.
1761 ********************************************************************/
1763 static void DirCacheAdd(struct smb_Dir
*dirp
, const char *name
, long offset
)
1765 struct name_cache_entry
*e
;
1767 if (dirp
->name_cache_size
== 0) {
1771 if (dirp
->name_cache
== NULL
) {
1772 dirp
->name_cache
= talloc_zero_array(
1773 dirp
, struct name_cache_entry
, dirp
->name_cache_size
);
1775 if (dirp
->name_cache
== NULL
) {
1780 dirp
->name_cache_index
= (dirp
->name_cache_index
+1) %
1781 dirp
->name_cache_size
;
1782 e
= &dirp
->name_cache
[dirp
->name_cache_index
];
1783 TALLOC_FREE(e
->name
);
1784 e
->name
= talloc_strdup(dirp
, name
);
1788 /*******************************************************************
1789 Find an entry by name. Leave us at the offset after it.
1790 Don't check for veto or invisible files.
1791 ********************************************************************/
1793 bool SearchDir(struct smb_Dir
*dirp
, const char *name
, long *poffset
)
1796 const char *entry
= NULL
;
1797 char *talloced
= NULL
;
1798 connection_struct
*conn
= dirp
->conn
;
1800 /* Search back in the name cache. */
1801 if (dirp
->name_cache_size
&& dirp
->name_cache
) {
1802 for (i
= dirp
->name_cache_index
; i
>= 0; i
--) {
1803 struct name_cache_entry
*e
= &dirp
->name_cache
[i
];
1804 if (e
->name
&& (conn
->case_sensitive
? (strcmp(e
->name
, name
) == 0) : strequal(e
->name
, name
))) {
1805 *poffset
= e
->offset
;
1806 SeekDir(dirp
, e
->offset
);
1810 for (i
= dirp
->name_cache_size
- 1; i
> dirp
->name_cache_index
; i
--) {
1811 struct name_cache_entry
*e
= &dirp
->name_cache
[i
];
1812 if (e
->name
&& (conn
->case_sensitive
? (strcmp(e
->name
, name
) == 0) : strequal(e
->name
, name
))) {
1813 *poffset
= e
->offset
;
1814 SeekDir(dirp
, e
->offset
);
1820 /* Not found in the name cache. Rewind directory and start from scratch. */
1821 SMB_VFS_REWINDDIR(conn
, dirp
->dir
);
1822 dirp
->file_number
= 0;
1823 *poffset
= START_OF_DIRECTORY_OFFSET
;
1824 while ((entry
= ReadDirName(dirp
, poffset
, NULL
, &talloced
))) {
1825 if (conn
->case_sensitive
? (strcmp(entry
, name
) == 0) : strequal(entry
, name
)) {
1826 TALLOC_FREE(talloced
);
1829 TALLOC_FREE(talloced
);
1834 /*****************************************************************
1835 Is this directory empty ?
1836 *****************************************************************/
1838 NTSTATUS
can_delete_directory_fsp(files_struct
*fsp
)
1840 NTSTATUS status
= NT_STATUS_OK
;
1842 const char *dname
= NULL
;
1843 const char *dirname
= fsp
->fsp_name
->base_name
;
1844 char *talloced
= NULL
;
1846 struct connection_struct
*conn
= fsp
->conn
;
1847 struct smb_Dir
*dir_hnd
= OpenDir_fsp(talloc_tos(),
1854 return map_nt_error_from_unix(errno
);
1857 while ((dname
= ReadDirName(dir_hnd
, &dirpos
, &st
, &talloced
))) {
1858 /* Quick check for "." and ".." */
1859 if (dname
[0] == '.') {
1860 if (!dname
[1] || (dname
[1] == '.' && !dname
[2])) {
1861 TALLOC_FREE(talloced
);
1866 if (!is_visible_file(conn
, dirname
, dname
, &st
, True
)) {
1867 TALLOC_FREE(talloced
);
1871 DEBUG(10,("got name %s - can't delete\n",
1873 status
= NT_STATUS_DIRECTORY_NOT_EMPTY
;
1876 TALLOC_FREE(talloced
);
1877 TALLOC_FREE(dir_hnd
);