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"
28 This module implements directory related functions for Samba.
31 /* "Special" directory offsets. */
32 #define END_OF_DIRECTORY_OFFSET ((long)-1)
33 #define START_OF_DIRECTORY_OFFSET ((long)0)
34 #define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000)
36 /* Make directory handle internals available. */
38 struct name_cache_entry
{
44 connection_struct
*conn
;
48 size_t name_cache_size
;
49 struct name_cache_entry
*name_cache
;
50 unsigned int name_cache_index
;
51 unsigned int file_number
;
55 struct dptr_struct
*next
, *prev
;
58 struct connection_struct
*conn
;
59 struct smb_Dir
*dir_hnd
;
64 bool has_wild
; /* Set to true if the wcard entry has MS wildcard characters in it. */
65 bool did_stat
; /* Optimisation for non-wcard searches. */
68 static struct smb_Dir
*OpenDir_fsp(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
73 #define INVALID_DPTR_KEY (-3)
75 /****************************************************************************
77 ****************************************************************************/
79 bool make_dir_struct(TALLOC_CTX
*ctx
,
89 char *mask2
= talloc_strdup(ctx
, mask
);
95 if ((mode
& aDIR
) != 0) {
100 if ((p
= strchr_m(mask2
,'.')) != NULL
) {
102 push_ascii(buf
+1,mask2
,8, 0);
103 push_ascii(buf
+9,p
+1,3, 0);
106 push_ascii(buf
+1,mask2
,11, 0);
109 memset(buf
+21,'\0',DIR_STRUCT_SIZE
-21);
111 srv_put_dos_date(buf
,22,date
);
112 SSVAL(buf
,26,size
& 0xFFFF);
113 SSVAL(buf
,28,(size
>> 16)&0xFFFF);
114 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
115 Strange, but verified on W2K3. Needed for OS/2. JRA. */
116 push_ascii(buf
+30,fname
,12, uc
? STR_UPPER
: 0);
117 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf
+30, fname
));
121 /****************************************************************************
122 Initialise the dir bitmap.
123 ****************************************************************************/
125 bool init_dptrs(struct smbd_server_connection
*sconn
)
127 if (sconn
->searches
.dptr_bmap
) {
131 sconn
->searches
.dptr_bmap
= bitmap_talloc(
132 sconn
, MAX_DIRECTORY_HANDLES
);
134 if (sconn
->searches
.dptr_bmap
== NULL
) {
141 /****************************************************************************
142 Idle a dptr - the directory is closed but the control info is kept.
143 ****************************************************************************/
145 static void dptr_idle(struct dptr_struct
*dptr
)
148 DEBUG(4,("Idling dptr dnum %d\n",dptr
->dnum
));
149 TALLOC_FREE(dptr
->dir_hnd
);
153 /****************************************************************************
154 Idle the oldest dptr.
155 ****************************************************************************/
157 static void dptr_idleoldest(struct smbd_server_connection
*sconn
)
159 struct dptr_struct
*dptr
;
162 * Go to the end of the list.
164 dptr
= DLIST_TAIL(sconn
->searches
.dirptrs
);
167 DEBUG(0,("No dptrs available to idle ?\n"));
172 * Idle the oldest pointer.
175 for(; dptr
; dptr
= DLIST_PREV(dptr
)) {
183 /****************************************************************************
184 Get the struct dptr_struct for a dir index.
185 ****************************************************************************/
187 static struct dptr_struct
*dptr_get(struct smbd_server_connection
*sconn
,
188 int key
, bool forclose
)
190 struct dptr_struct
*dptr
;
192 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= dptr
->next
) {
193 if(dptr
->dnum
== key
) {
194 if (!forclose
&& !dptr
->dir_hnd
) {
195 if (sconn
->searches
.dirhandles_open
>= MAX_OPEN_DIRECTORIES
)
196 dptr_idleoldest(sconn
);
197 DEBUG(4,("dptr_get: Reopening dptr key %d\n",key
));
198 if (!(dptr
->dir_hnd
= OpenDir(
199 NULL
, dptr
->conn
, dptr
->path
,
200 dptr
->wcard
, dptr
->attr
))) {
201 DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr
->path
,
206 DLIST_PROMOTE(sconn
->searches
.dirptrs
,dptr
);
213 /****************************************************************************
214 Get the dir path for a dir index.
215 ****************************************************************************/
217 char *dptr_path(struct smbd_server_connection
*sconn
, int key
)
219 struct dptr_struct
*dptr
= dptr_get(sconn
, key
, false);
225 /****************************************************************************
226 Get the dir wcard for a dir index.
227 ****************************************************************************/
229 char *dptr_wcard(struct smbd_server_connection
*sconn
, int key
)
231 struct dptr_struct
*dptr
= dptr_get(sconn
, key
, false);
237 /****************************************************************************
238 Get the dir attrib for a dir index.
239 ****************************************************************************/
241 uint16
dptr_attr(struct smbd_server_connection
*sconn
, int key
)
243 struct dptr_struct
*dptr
= dptr_get(sconn
, key
, false);
249 /****************************************************************************
250 Close a dptr (internal func).
251 ****************************************************************************/
253 static void dptr_close_internal(struct dptr_struct
*dptr
)
255 struct smbd_server_connection
*sconn
= dptr
->conn
->sconn
;
257 DEBUG(4,("closing dptr key %d\n",dptr
->dnum
));
263 DLIST_REMOVE(sconn
->searches
.dirptrs
, dptr
);
266 * Free the dnum in the bitmap. Remember the dnum value is always
267 * biased by one with respect to the bitmap.
270 if (!bitmap_query(sconn
->searches
.dptr_bmap
, dptr
->dnum
- 1)) {
271 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
275 bitmap_clear(sconn
->searches
.dptr_bmap
, dptr
->dnum
- 1);
278 TALLOC_FREE(dptr
->dir_hnd
);
280 /* Lanman 2 specific code */
281 SAFE_FREE(dptr
->wcard
);
282 string_set(&dptr
->path
,"");
286 /****************************************************************************
287 Close a dptr given a key.
288 ****************************************************************************/
290 void dptr_close(struct smbd_server_connection
*sconn
, int *key
)
292 struct dptr_struct
*dptr
;
294 if(*key
== INVALID_DPTR_KEY
)
297 /* OS/2 seems to use -1 to indicate "close all directories" */
299 struct dptr_struct
*next
;
300 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= next
) {
302 dptr_close_internal(dptr
);
304 *key
= INVALID_DPTR_KEY
;
308 dptr
= dptr_get(sconn
, *key
, true);
311 DEBUG(0,("Invalid key %d given to dptr_close\n", *key
));
315 dptr_close_internal(dptr
);
317 *key
= INVALID_DPTR_KEY
;
320 /****************************************************************************
321 Close all dptrs for a cnum.
322 ****************************************************************************/
324 void dptr_closecnum(connection_struct
*conn
)
326 struct dptr_struct
*dptr
, *next
;
327 struct smbd_server_connection
*sconn
= conn
->sconn
;
333 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= next
) {
335 if (dptr
->conn
== conn
) {
336 dptr_close_internal(dptr
);
341 /****************************************************************************
342 Idle all dptrs for a cnum.
343 ****************************************************************************/
345 void dptr_idlecnum(connection_struct
*conn
)
347 struct dptr_struct
*dptr
;
348 struct smbd_server_connection
*sconn
= conn
->sconn
;
354 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= dptr
->next
) {
355 if (dptr
->conn
== conn
&& dptr
->dir_hnd
) {
361 /****************************************************************************
362 Close a dptr that matches a given path, only if it matches the spid also.
363 ****************************************************************************/
365 void dptr_closepath(struct smbd_server_connection
*sconn
,
366 char *path
,uint16 spid
)
368 struct dptr_struct
*dptr
, *next
;
369 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= next
) {
371 if (spid
== dptr
->spid
&& strequal(dptr
->path
,path
))
372 dptr_close_internal(dptr
);
376 /****************************************************************************
377 Try and close the oldest handle not marked for
378 expect close in the hope that the client has
379 finished with that one.
380 ****************************************************************************/
382 static void dptr_close_oldest(struct smbd_server_connection
*sconn
,
385 struct dptr_struct
*dptr
;
388 * Go to the end of the list.
390 for(dptr
= sconn
->searches
.dirptrs
; dptr
&& dptr
->next
; dptr
= dptr
->next
)
394 DEBUG(0,("No old dptrs available to close oldest ?\n"));
399 * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
400 * does not have expect_close set. If 'old' is false, close
401 * one of the new dnum handles.
404 for(; dptr
; dptr
= DLIST_PREV(dptr
)) {
405 if ((old
&& (dptr
->dnum
< 256) && !dptr
->expect_close
) ||
406 (!old
&& (dptr
->dnum
> 255))) {
407 dptr_close_internal(dptr
);
413 /****************************************************************************
414 Create a new dir ptr. If the flag old_handle is true then we must allocate
415 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
416 one byte long. If old_handle is false we allocate from the range
417 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
418 a directory handle is never zero.
419 wcard must not be zero.
420 ****************************************************************************/
422 NTSTATUS
dptr_create(connection_struct
*conn
, files_struct
*fsp
,
423 const char *path
, bool old_handle
, bool expect_close
,uint16 spid
,
424 const char *wcard
, bool wcard_has_wild
, uint32 attr
, struct dptr_struct
**dptr_ret
)
426 struct smbd_server_connection
*sconn
= conn
->sconn
;
427 struct dptr_struct
*dptr
= NULL
;
428 struct smb_Dir
*dir_hnd
;
431 if (fsp
&& fsp
->is_directory
&& fsp
->fh
->fd
!= -1) {
432 path
= fsp
->fsp_name
->base_name
;
435 DEBUG(5,("dptr_create dir=%s\n", path
));
438 DEBUG(0,("dptr_create: called with fake connection_struct\n"));
439 return NT_STATUS_INTERNAL_ERROR
;
443 return NT_STATUS_INVALID_PARAMETER
;
447 dir_hnd
= OpenDir_fsp(NULL
, conn
, fsp
, wcard
, attr
);
449 status
= check_name(conn
,path
);
450 if (!NT_STATUS_IS_OK(status
)) {
453 dir_hnd
= OpenDir(NULL
, conn
, path
, wcard
, attr
);
457 return map_nt_error_from_unix(errno
);
460 if (sconn
->searches
.dirhandles_open
>= MAX_OPEN_DIRECTORIES
) {
461 dptr_idleoldest(sconn
);
464 dptr
= SMB_MALLOC_P(struct dptr_struct
);
466 DEBUG(0,("malloc fail in dptr_create.\n"));
467 TALLOC_FREE(dir_hnd
);
468 return NT_STATUS_NO_MEMORY
;
476 * This is an old-style SMBsearch request. Ensure the
477 * value we return will fit in the range 1-255.
480 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 0);
482 if(dptr
->dnum
== -1 || dptr
->dnum
> 254) {
485 * Try and close the oldest handle not marked for
486 * expect close in the hope that the client has
487 * finished with that one.
490 dptr_close_oldest(sconn
, true);
492 /* Now try again... */
493 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 0);
494 if(dptr
->dnum
== -1 || dptr
->dnum
> 254) {
495 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr
->dnum
));
497 TALLOC_FREE(dir_hnd
);
498 return NT_STATUS_TOO_MANY_OPENED_FILES
;
504 * This is a new-style trans2 request. Allocate from
505 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
508 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 255);
510 if(dptr
->dnum
== -1 || dptr
->dnum
< 255) {
513 * Try and close the oldest handle close in the hope that
514 * the client has finished with that one. This will only
515 * happen in the case of the Win98 client bug where it leaks
519 dptr_close_oldest(sconn
, false);
521 /* Now try again... */
522 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 255);
524 if(dptr
->dnum
== -1 || dptr
->dnum
< 255) {
525 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr
->dnum
));
527 TALLOC_FREE(dir_hnd
);
528 return NT_STATUS_TOO_MANY_OPENED_FILES
;
533 bitmap_set(sconn
->searches
.dptr_bmap
, dptr
->dnum
);
535 dptr
->dnum
+= 1; /* Always bias the dnum by one - no zero dnums allowed. */
537 string_set(&dptr
->path
,path
);
539 dptr
->dir_hnd
= dir_hnd
;
541 dptr
->expect_close
= expect_close
;
542 dptr
->wcard
= SMB_STRDUP(wcard
);
544 bitmap_clear(sconn
->searches
.dptr_bmap
, dptr
->dnum
- 1);
546 TALLOC_FREE(dir_hnd
);
547 return NT_STATUS_NO_MEMORY
;
549 if (lp_posix_pathnames() || (wcard
[0] == '.' && wcard
[1] == 0)) {
550 dptr
->has_wild
= True
;
552 dptr
->has_wild
= wcard_has_wild
;
557 DLIST_ADD(sconn
->searches
.dirptrs
, dptr
);
559 DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
560 dptr
->dnum
,path
,expect_close
));
568 /****************************************************************************
569 Wrapper functions to access the lower level directory handles.
570 ****************************************************************************/
572 void dptr_CloseDir(files_struct
*fsp
)
576 * Ugly hack. We have defined fdopendir to return ENOSYS if dirfd also isn't
577 * present. I hate Solaris. JRA.
580 if (fsp
->fh
->fd
!= -1 &&
581 fsp
->dptr
->dir_hnd
&&
582 dirfd(fsp
->dptr
->dir_hnd
->dir
)) {
583 /* The call below closes the underlying fd. */
587 dptr_close_internal(fsp
->dptr
);
592 void dptr_SeekDir(struct dptr_struct
*dptr
, long offset
)
594 SeekDir(dptr
->dir_hnd
, offset
);
597 long dptr_TellDir(struct dptr_struct
*dptr
)
599 return TellDir(dptr
->dir_hnd
);
602 bool dptr_has_wild(struct dptr_struct
*dptr
)
604 return dptr
->has_wild
;
607 int dptr_dnum(struct dptr_struct
*dptr
)
612 /****************************************************************************
613 Return the next visible file name, skipping veto'd and invisible files.
614 ****************************************************************************/
616 static const char *dptr_normal_ReadDirName(struct dptr_struct
*dptr
,
617 long *poffset
, SMB_STRUCT_STAT
*pst
,
620 /* Normal search for the next file. */
622 char *talloced
= NULL
;
624 while ((name
= ReadDirName(dptr
->dir_hnd
, poffset
, pst
, &talloced
))
626 if (is_visible_file(dptr
->conn
, dptr
->path
, name
, pst
, True
)) {
627 *ptalloced
= talloced
;
630 TALLOC_FREE(talloced
);
635 /****************************************************************************
636 Return the next visible file name, skipping veto'd and invisible files.
637 ****************************************************************************/
639 char *dptr_ReadDirName(TALLOC_CTX
*ctx
,
640 struct dptr_struct
*dptr
,
642 SMB_STRUCT_STAT
*pst
)
644 struct smb_filename smb_fname_base
;
646 const char *name_temp
= NULL
;
647 char *talloced
= NULL
;
648 char *pathreal
= NULL
;
649 char *found_name
= NULL
;
652 SET_STAT_INVALID(*pst
);
654 if (dptr
->has_wild
|| dptr
->did_stat
) {
655 name_temp
= dptr_normal_ReadDirName(dptr
, poffset
, pst
,
657 if (name_temp
== NULL
) {
660 if (talloced
!= NULL
) {
661 return talloc_move(ctx
, &talloced
);
663 return talloc_strdup(ctx
, name_temp
);
666 /* If poffset is -1 then we know we returned this name before and we
667 * have no wildcards. We're at the end of the directory. */
668 if (*poffset
== END_OF_DIRECTORY_OFFSET
) {
672 /* We know the stored wcard contains no wildcard characters.
673 * See if we can match with a stat call. If we can't, then set
674 * did_stat to true to ensure we only do this once and keep
677 dptr
->did_stat
= true;
679 /* First check if it should be visible. */
680 if (!is_visible_file(dptr
->conn
, dptr
->path
, dptr
->wcard
,
683 /* This only returns false if the file was found, but
684 is explicitly not visible. Set us to end of
685 directory, but return NULL as we know we can't ever
690 if (VALID_STAT(*pst
)) {
691 name
= talloc_strdup(ctx
, dptr
->wcard
);
695 pathreal
= talloc_asprintf(ctx
,
702 /* Create an smb_filename with stream_name == NULL. */
703 ZERO_STRUCT(smb_fname_base
);
704 smb_fname_base
.base_name
= pathreal
;
706 if (SMB_VFS_STAT(dptr
->conn
, &smb_fname_base
) == 0) {
707 *pst
= smb_fname_base
.st
;
708 name
= talloc_strdup(ctx
, dptr
->wcard
);
711 /* If we get any other error than ENOENT or ENOTDIR
712 then the file exists we just can't stat it. */
713 if (errno
!= ENOENT
&& errno
!= ENOTDIR
) {
714 name
= talloc_strdup(ctx
, dptr
->wcard
);
719 /* Stat failed. We know this is authoratiative if we are
720 * providing case sensitive semantics or the underlying
721 * filesystem is case sensitive.
723 if (dptr
->conn
->case_sensitive
||
724 !(dptr
->conn
->fs_capabilities
& FILE_CASE_SENSITIVE_SEARCH
))
730 * Try case-insensitive stat if the fs has the ability. This avoids
731 * scanning the whole directory.
733 ret
= SMB_VFS_GET_REAL_FILENAME(dptr
->conn
, dptr
->path
, dptr
->wcard
,
738 } else if (errno
== ENOENT
) {
739 /* The case-insensitive lookup was authoritative. */
743 TALLOC_FREE(pathreal
);
745 name_temp
= dptr_normal_ReadDirName(dptr
, poffset
, pst
, &talloced
);
746 if (name_temp
== NULL
) {
749 if (talloced
!= NULL
) {
750 return talloc_move(ctx
, &talloced
);
752 return talloc_strdup(ctx
, name_temp
);
755 TALLOC_FREE(pathreal
);
757 /* We need to set the underlying dir_hnd offset to -1
758 * also as this function is usually called with the
759 * output from TellDir. */
760 dptr
->dir_hnd
->offset
= *poffset
= END_OF_DIRECTORY_OFFSET
;
764 /****************************************************************************
765 Search for a file by name, skipping veto'ed and not visible files.
766 ****************************************************************************/
768 bool dptr_SearchDir(struct dptr_struct
*dptr
, const char *name
, long *poffset
, SMB_STRUCT_STAT
*pst
)
770 SET_STAT_INVALID(*pst
);
772 if (!dptr
->has_wild
&& (dptr
->dir_hnd
->offset
== END_OF_DIRECTORY_OFFSET
)) {
773 /* This is a singleton directory and we're already at the end. */
774 *poffset
= END_OF_DIRECTORY_OFFSET
;
778 return SearchDir(dptr
->dir_hnd
, name
, poffset
);
781 /****************************************************************************
782 Add the name we're returning into the underlying cache.
783 ****************************************************************************/
785 void dptr_DirCacheAdd(struct dptr_struct
*dptr
, const char *name
, long offset
)
787 DirCacheAdd(dptr
->dir_hnd
, name
, offset
);
790 /****************************************************************************
791 Initialize variables & state data at the beginning of all search SMB requests.
792 ****************************************************************************/
793 void dptr_init_search_op(struct dptr_struct
*dptr
)
795 SMB_VFS_INIT_SEARCH_OP(dptr
->conn
, dptr
->dir_hnd
->dir
);
798 /****************************************************************************
799 Fill the 5 byte server reserved dptr field.
800 ****************************************************************************/
802 bool dptr_fill(struct smbd_server_connection
*sconn
,
803 char *buf1
,unsigned int key
)
805 unsigned char *buf
= (unsigned char *)buf1
;
806 struct dptr_struct
*dptr
= dptr_get(sconn
, key
, false);
809 DEBUG(1,("filling null dirptr %d\n",key
));
812 offset
= (uint32
)TellDir(dptr
->dir_hnd
);
813 DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key
,
814 (long)dptr
->dir_hnd
,(int)offset
));
820 /****************************************************************************
821 Fetch the dir ptr and seek it given the 5 byte server field.
822 ****************************************************************************/
824 struct dptr_struct
*dptr_fetch(struct smbd_server_connection
*sconn
,
827 unsigned int key
= *(unsigned char *)buf
;
828 struct dptr_struct
*dptr
= dptr_get(sconn
, key
, false);
833 DEBUG(3,("fetched null dirptr %d\n",key
));
837 offset
= IVAL(buf
,1);
838 if (offset
== (uint32
)-1) {
839 seekoff
= END_OF_DIRECTORY_OFFSET
;
841 seekoff
= (long)offset
;
843 SeekDir(dptr
->dir_hnd
,seekoff
);
844 DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
845 key
, dptr
->path
, (int)seekoff
));
849 /****************************************************************************
851 ****************************************************************************/
853 struct dptr_struct
*dptr_fetch_lanman2(struct smbd_server_connection
*sconn
,
856 struct dptr_struct
*dptr
= dptr_get(sconn
, dptr_num
, false);
859 DEBUG(3,("fetched null dirptr %d\n",dptr_num
));
862 DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num
,dptr
->path
));
866 /****************************************************************************
867 Check that a file matches a particular file type.
868 ****************************************************************************/
870 bool dir_check_ftype(connection_struct
*conn
, uint32 mode
, uint32 dirtype
)
874 /* Check the "may have" search bits. */
875 if (((mode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
| aDIR
)) != 0)
878 /* Check the "must have" bits, which are the may have bits shifted eight */
879 /* If must have bit is set, the file/dir can not be returned in search unless the matching
880 file attribute is set */
881 mask
= ((dirtype
>> 8) & (aDIR
|aARCH
|aRONLY
|aHIDDEN
|aSYSTEM
)); /* & 0x37 */
883 if((mask
& (mode
& (aDIR
|aARCH
|aRONLY
|aHIDDEN
|aSYSTEM
))) == mask
) /* check if matching attribute present */
892 static bool mangle_mask_match(connection_struct
*conn
,
893 const char *filename
,
898 if (!name_to_8_3(filename
,mname
,False
,conn
->params
)) {
901 return mask_match_search(mname
,mask
,False
);
904 bool smbd_dirptr_get_entry(TALLOC_CTX
*ctx
,
905 struct dptr_struct
*dirptr
,
910 bool (*match_fn
)(TALLOC_CTX
*ctx
,
915 bool (*mode_fn
)(TALLOC_CTX
*ctx
,
917 struct smb_filename
*smb_fname
,
921 struct smb_filename
**_smb_fname
,
925 connection_struct
*conn
= dirptr
->conn
;
931 needslash
= ( dirptr
->path
[strlen(dirptr
->path
) -1] != '/');
936 SMB_STRUCT_STAT sbuf
;
940 char *pathreal
= NULL
;
941 struct smb_filename smb_fname
;
946 cur_offset
= dptr_TellDir(dirptr
);
947 prev_offset
= cur_offset
;
948 dname
= dptr_ReadDirName(ctx
, dirptr
, &cur_offset
, &sbuf
);
950 DEBUG(6,("smbd_dirptr_get_entry: dirptr 0x%lx now at offset %ld\n",
951 (long)dirptr
, cur_offset
));
957 isdots
= (ISDOT(dname
) || ISDOTDOT(dname
));
958 if (dont_descend
&& !isdots
) {
964 * fname may get mangled, dname is never mangled.
965 * Whenever we're accessing the filesystem we use
966 * pathreal which is composed from dname.
969 ok
= match_fn(ctx
, private_data
, dname
, mask
, &fname
);
975 pathreal
= talloc_asprintf(ctx
, "%s%s%s",
985 /* Create smb_fname with NULL stream_name. */
986 ZERO_STRUCT(smb_fname
);
987 smb_fname
.base_name
= pathreal
;
990 ok
= mode_fn(ctx
, private_data
, &smb_fname
, &mode
);
994 TALLOC_FREE(pathreal
);
998 if (!dir_check_ftype(conn
, mode
, dirtype
)) {
999 DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",
1000 fname
, (unsigned int)mode
, (unsigned int)dirtype
));
1003 TALLOC_FREE(pathreal
);
1007 if (ask_sharemode
) {
1008 struct timespec write_time_ts
;
1009 struct file_id fileid
;
1011 fileid
= vfs_file_id_from_sbuf(conn
,
1013 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1014 if (!null_timespec(write_time_ts
)) {
1015 update_stat_ex_mtime(&smb_fname
.st
,
1020 DEBUG(3,("smbd_dirptr_get_entry mask=[%s] found %s "
1022 mask
, smb_fname_str_dbg(&smb_fname
),
1025 DirCacheAdd(dirptr
->dir_hnd
, dname
, cur_offset
);
1029 status
= copy_smb_filename(ctx
, &smb_fname
, _smb_fname
);
1030 TALLOC_FREE(pathreal
);
1031 if (!NT_STATUS_IS_OK(status
)) {
1036 *_prev_offset
= prev_offset
;
1044 /****************************************************************************
1045 Get an 8.3 directory entry.
1046 ****************************************************************************/
1048 static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX
*ctx
,
1054 connection_struct
*conn
= (connection_struct
*)private_data
;
1056 if ((strcmp(mask
,"*.*") == 0) ||
1057 mask_match_search(dname
, mask
, false) ||
1058 mangle_mask_match(conn
, dname
, mask
)) {
1062 if (!mangle_is_8_3(dname
, false, conn
->params
)) {
1063 bool ok
= name_to_8_3(dname
, mname
, false,
1073 *_fname
= talloc_strdup(ctx
, fname
);
1074 if (*_fname
== NULL
) {
1084 static bool smbd_dirptr_8_3_mode_fn(TALLOC_CTX
*ctx
,
1086 struct smb_filename
*smb_fname
,
1089 connection_struct
*conn
= (connection_struct
*)private_data
;
1091 if (!VALID_STAT(smb_fname
->st
)) {
1092 if ((SMB_VFS_STAT(conn
, smb_fname
)) != 0) {
1093 DEBUG(5,("smbd_dirptr_8_3_mode_fn: "
1094 "Couldn't stat [%s]. Error "
1096 smb_fname_str_dbg(smb_fname
),
1102 *_mode
= dos_mode(conn
, smb_fname
);
1106 bool get_dir_entry(TALLOC_CTX
*ctx
,
1107 struct dptr_struct
*dirptr
,
1113 struct timespec
*_date
,
1117 connection_struct
*conn
= dirptr
->conn
;
1119 struct smb_filename
*smb_fname
= NULL
;
1124 ok
= smbd_dirptr_get_entry(ctx
,
1130 smbd_dirptr_8_3_match_fn
,
1131 smbd_dirptr_8_3_mode_fn
,
1141 *_fname
= talloc_move(ctx
, &fname
);
1142 *_size
= smb_fname
->st
.st_ex_size
;
1144 *_date
= smb_fname
->st
.st_ex_mtime
;
1145 TALLOC_FREE(smb_fname
);
1149 /*******************************************************************
1150 Check to see if a user can read a file. This is only approximate,
1151 it is used as part of the "hide unreadable" option. Don't
1152 use it for anything security sensitive.
1153 ********************************************************************/
1155 static bool user_can_read_file(connection_struct
*conn
,
1156 struct smb_filename
*smb_fname
)
1159 * Never hide files from the root user.
1160 * We use (uid_t)0 here not sec_initial_uid()
1161 * as make test uses a single user context.
1164 if (get_current_uid(conn
) == (uid_t
)0) {
1168 return can_access_file_acl(conn
, smb_fname
, FILE_READ_DATA
);
1171 /*******************************************************************
1172 Check to see if a user can write a file (and only files, we do not
1173 check dirs on this one). This is only approximate,
1174 it is used as part of the "hide unwriteable" option. Don't
1175 use it for anything security sensitive.
1176 ********************************************************************/
1178 static bool user_can_write_file(connection_struct
*conn
,
1179 const struct smb_filename
*smb_fname
)
1182 * Never hide files from the root user.
1183 * We use (uid_t)0 here not sec_initial_uid()
1184 * as make test uses a single user context.
1187 if (get_current_uid(conn
) == (uid_t
)0) {
1191 SMB_ASSERT(VALID_STAT(smb_fname
->st
));
1193 /* Pseudo-open the file */
1195 if(S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1199 return can_write_to_file(conn
, smb_fname
);
1202 /*******************************************************************
1203 Is a file a "special" type ?
1204 ********************************************************************/
1206 static bool file_is_special(connection_struct
*conn
,
1207 const struct smb_filename
*smb_fname
)
1210 * Never hide files from the root user.
1211 * We use (uid_t)0 here not sec_initial_uid()
1212 * as make test uses a single user context.
1215 if (get_current_uid(conn
) == (uid_t
)0) {
1219 SMB_ASSERT(VALID_STAT(smb_fname
->st
));
1221 if (S_ISREG(smb_fname
->st
.st_ex_mode
) ||
1222 S_ISDIR(smb_fname
->st
.st_ex_mode
) ||
1223 S_ISLNK(smb_fname
->st
.st_ex_mode
))
1229 /*******************************************************************
1230 Should the file be seen by the client?
1231 NOTE: A successful return is no guarantee of the file's existence.
1232 ********************************************************************/
1234 bool is_visible_file(connection_struct
*conn
, const char *dir_path
,
1235 const char *name
, SMB_STRUCT_STAT
*pst
, bool use_veto
)
1237 bool hide_unreadable
= lp_hideunreadable(SNUM(conn
));
1238 bool hide_unwriteable
= lp_hideunwriteable_files(SNUM(conn
));
1239 bool hide_special
= lp_hide_special_files(SNUM(conn
));
1241 struct smb_filename
*smb_fname_base
= NULL
;
1245 if ((strcmp(".",name
) == 0) || (strcmp("..",name
) == 0)) {
1246 return True
; /* . and .. are always visible. */
1249 /* If it's a vetoed file, pretend it doesn't even exist */
1250 if (use_veto
&& IS_VETO_PATH(conn
, name
)) {
1251 DEBUG(10,("is_visible_file: file %s is vetoed.\n", name
));
1255 if (hide_unreadable
|| hide_unwriteable
|| hide_special
) {
1256 entry
= talloc_asprintf(talloc_tos(), "%s/%s", dir_path
, name
);
1262 /* Create an smb_filename with stream_name == NULL. */
1263 status
= create_synthetic_smb_fname(talloc_tos(), entry
, NULL
,
1264 pst
, &smb_fname_base
);
1265 if (!NT_STATUS_IS_OK(status
)) {
1270 /* If the file name does not exist, there's no point checking
1271 * the configuration options. We succeed, on the basis that the
1272 * checks *might* have passed if the file was present.
1274 if (!VALID_STAT(*pst
)) {
1275 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
1279 *pst
= smb_fname_base
->st
;
1283 /* Honour _hide unreadable_ option */
1284 if (hide_unreadable
&&
1285 !user_can_read_file(conn
, smb_fname_base
)) {
1286 DEBUG(10,("is_visible_file: file %s is unreadable.\n",
1291 /* Honour _hide unwriteable_ option */
1292 if (hide_unwriteable
&& !user_can_write_file(conn
,
1294 DEBUG(10,("is_visible_file: file %s is unwritable.\n",
1299 /* Honour _hide_special_ option */
1300 if (hide_special
&& file_is_special(conn
, smb_fname_base
)) {
1301 DEBUG(10,("is_visible_file: file %s is special.\n",
1310 TALLOC_FREE(smb_fname_base
);
1315 static int smb_Dir_destructor(struct smb_Dir
*dirp
)
1319 if (dirp
->conn
->sconn
) {
1320 files_struct
*fsp
= file_find_fd(dirp
->conn
->sconn
,
1323 /* The call below closes the underlying fd. */
1328 SMB_VFS_CLOSEDIR(dirp
->conn
,dirp
->dir
);
1330 if (dirp
->conn
->sconn
) {
1331 dirp
->conn
->sconn
->searches
.dirhandles_open
--;
1336 /*******************************************************************
1338 ********************************************************************/
1340 struct smb_Dir
*OpenDir(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
1345 struct smb_Dir
*dirp
= TALLOC_ZERO_P(mem_ctx
, struct smb_Dir
);
1346 struct smbd_server_connection
*sconn
= conn
->sconn
;
1353 dirp
->name_cache_size
= lp_directory_name_cache_size(SNUM(conn
));
1355 dirp
->dir_path
= talloc_strdup(dirp
, name
);
1356 if (!dirp
->dir_path
) {
1362 sconn
->searches
.dirhandles_open
++;
1364 talloc_set_destructor(dirp
, smb_Dir_destructor
);
1366 dirp
->dir
= SMB_VFS_OPENDIR(conn
, dirp
->dir_path
, mask
, attr
);
1368 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp
->dir_path
,
1380 /*******************************************************************
1381 Open a directory from an fsp.
1382 ********************************************************************/
1384 static struct smb_Dir
*OpenDir_fsp(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
1389 struct smb_Dir
*dirp
= TALLOC_ZERO_P(mem_ctx
, struct smb_Dir
);
1390 struct smbd_server_connection
*sconn
= conn
->sconn
;
1397 dirp
->name_cache_size
= lp_directory_name_cache_size(SNUM(conn
));
1399 dirp
->dir_path
= talloc_strdup(dirp
, fsp
->fsp_name
->base_name
);
1400 if (!dirp
->dir_path
) {
1406 sconn
->searches
.dirhandles_open
++;
1408 talloc_set_destructor(dirp
, smb_Dir_destructor
);
1410 if (fsp
->is_directory
&& fsp
->fh
->fd
!= -1) {
1411 dirp
->dir
= SMB_VFS_FDOPENDIR(fsp
, mask
, attr
);
1412 if (dirp
->dir
== NULL
) {
1413 DEBUG(10,("OpenDir_fsp: SMB_VFS_FDOPENDIR on %s returned "
1417 if (errno
!= ENOSYS
) {
1423 if (dirp
->dir
== NULL
) {
1424 /* FDOPENDIR didn't work. Use OPENDIR instead. */
1425 dirp
->dir
= SMB_VFS_OPENDIR(conn
, dirp
->dir_path
, mask
, attr
);
1429 DEBUG(5,("OpenDir_fsp: Can't open %s. %s\n", dirp
->dir_path
,
1442 /*******************************************************************
1443 Read from a directory.
1444 Return directory entry, current offset, and optional stat information.
1445 Don't check for veto or invisible files.
1446 ********************************************************************/
1448 const char *ReadDirName(struct smb_Dir
*dirp
, long *poffset
,
1449 SMB_STRUCT_STAT
*sbuf
, char **ptalloced
)
1452 char *talloced
= NULL
;
1453 connection_struct
*conn
= dirp
->conn
;
1455 /* Cheat to allow . and .. to be the first entries returned. */
1456 if (((*poffset
== START_OF_DIRECTORY_OFFSET
) ||
1457 (*poffset
== DOT_DOT_DIRECTORY_OFFSET
)) && (dirp
->file_number
< 2))
1459 if (dirp
->file_number
== 0) {
1461 *poffset
= dirp
->offset
= START_OF_DIRECTORY_OFFSET
;
1464 *poffset
= dirp
->offset
= DOT_DOT_DIRECTORY_OFFSET
;
1466 dirp
->file_number
++;
1469 } else if (*poffset
== END_OF_DIRECTORY_OFFSET
) {
1470 *poffset
= dirp
->offset
= END_OF_DIRECTORY_OFFSET
;
1473 /* A real offset, seek to it. */
1474 SeekDir(dirp
, *poffset
);
1477 while ((n
= vfs_readdirname(conn
, dirp
->dir
, sbuf
, &talloced
))) {
1478 /* Ignore . and .. - we've already returned them. */
1480 if ((n
[1] == '\0') || (n
[1] == '.' && n
[2] == '\0')) {
1481 TALLOC_FREE(talloced
);
1485 *poffset
= dirp
->offset
= SMB_VFS_TELLDIR(conn
, dirp
->dir
);
1486 *ptalloced
= talloced
;
1487 dirp
->file_number
++;
1490 *poffset
= dirp
->offset
= END_OF_DIRECTORY_OFFSET
;
1495 /*******************************************************************
1496 Rewind to the start.
1497 ********************************************************************/
1499 void RewindDir(struct smb_Dir
*dirp
, long *poffset
)
1501 SMB_VFS_REWINDDIR(dirp
->conn
, dirp
->dir
);
1502 dirp
->file_number
= 0;
1503 dirp
->offset
= START_OF_DIRECTORY_OFFSET
;
1504 *poffset
= START_OF_DIRECTORY_OFFSET
;
1507 /*******************************************************************
1509 ********************************************************************/
1511 void SeekDir(struct smb_Dir
*dirp
, long offset
)
1513 if (offset
!= dirp
->offset
) {
1514 if (offset
== START_OF_DIRECTORY_OFFSET
) {
1515 RewindDir(dirp
, &offset
);
1517 * Ok we should really set the file number here
1518 * to 1 to enable ".." to be returned next. Trouble
1519 * is I'm worried about callers using SeekDir(dirp,0)
1520 * as equivalent to RewindDir(). So leave this alone
1523 } else if (offset
== DOT_DOT_DIRECTORY_OFFSET
) {
1524 RewindDir(dirp
, &offset
);
1526 * Set the file number to 2 - we want to get the first
1527 * real file entry (the one we return after "..")
1528 * on the next ReadDir.
1530 dirp
->file_number
= 2;
1531 } else if (offset
== END_OF_DIRECTORY_OFFSET
) {
1532 ; /* Don't seek in this case. */
1534 SMB_VFS_SEEKDIR(dirp
->conn
, dirp
->dir
, offset
);
1536 dirp
->offset
= offset
;
1540 /*******************************************************************
1541 Tell a dir position.
1542 ********************************************************************/
1544 long TellDir(struct smb_Dir
*dirp
)
1546 return(dirp
->offset
);
1549 /*******************************************************************
1550 Add an entry into the dcache.
1551 ********************************************************************/
1553 void DirCacheAdd(struct smb_Dir
*dirp
, const char *name
, long offset
)
1555 struct name_cache_entry
*e
;
1557 if (dirp
->name_cache_size
== 0) {
1561 if (dirp
->name_cache
== NULL
) {
1562 dirp
->name_cache
= TALLOC_ZERO_ARRAY(
1563 dirp
, struct name_cache_entry
, dirp
->name_cache_size
);
1565 if (dirp
->name_cache
== NULL
) {
1570 dirp
->name_cache_index
= (dirp
->name_cache_index
+1) %
1571 dirp
->name_cache_size
;
1572 e
= &dirp
->name_cache
[dirp
->name_cache_index
];
1573 TALLOC_FREE(e
->name
);
1574 e
->name
= talloc_strdup(dirp
, name
);
1578 /*******************************************************************
1579 Find an entry by name. Leave us at the offset after it.
1580 Don't check for veto or invisible files.
1581 ********************************************************************/
1583 bool SearchDir(struct smb_Dir
*dirp
, const char *name
, long *poffset
)
1586 const char *entry
= NULL
;
1587 char *talloced
= NULL
;
1588 connection_struct
*conn
= dirp
->conn
;
1590 /* Search back in the name cache. */
1591 if (dirp
->name_cache_size
&& dirp
->name_cache
) {
1592 for (i
= dirp
->name_cache_index
; i
>= 0; i
--) {
1593 struct name_cache_entry
*e
= &dirp
->name_cache
[i
];
1594 if (e
->name
&& (conn
->case_sensitive
? (strcmp(e
->name
, name
) == 0) : strequal(e
->name
, name
))) {
1595 *poffset
= e
->offset
;
1596 SeekDir(dirp
, e
->offset
);
1600 for (i
= dirp
->name_cache_size
- 1; i
> dirp
->name_cache_index
; i
--) {
1601 struct name_cache_entry
*e
= &dirp
->name_cache
[i
];
1602 if (e
->name
&& (conn
->case_sensitive
? (strcmp(e
->name
, name
) == 0) : strequal(e
->name
, name
))) {
1603 *poffset
= e
->offset
;
1604 SeekDir(dirp
, e
->offset
);
1610 /* Not found in the name cache. Rewind directory and start from scratch. */
1611 SMB_VFS_REWINDDIR(conn
, dirp
->dir
);
1612 dirp
->file_number
= 0;
1613 *poffset
= START_OF_DIRECTORY_OFFSET
;
1614 while ((entry
= ReadDirName(dirp
, poffset
, NULL
, &talloced
))) {
1615 if (conn
->case_sensitive
? (strcmp(entry
, name
) == 0) : strequal(entry
, name
)) {
1616 TALLOC_FREE(talloced
);
1619 TALLOC_FREE(talloced
);
1624 /*****************************************************************
1625 Is this directory empty ?
1626 *****************************************************************/
1628 NTSTATUS
can_delete_directory(struct connection_struct
*conn
,
1629 const char *dirname
)
1631 NTSTATUS status
= NT_STATUS_OK
;
1633 const char *dname
= NULL
;
1634 char *talloced
= NULL
;
1636 struct smb_Dir
*dir_hnd
= OpenDir(talloc_tos(), conn
,
1640 return map_nt_error_from_unix(errno
);
1643 while ((dname
= ReadDirName(dir_hnd
, &dirpos
, &st
, &talloced
))) {
1644 /* Quick check for "." and ".." */
1645 if (dname
[0] == '.') {
1646 if (!dname
[1] || (dname
[1] == '.' && !dname
[2])) {
1647 TALLOC_FREE(talloced
);
1652 if (!is_visible_file(conn
, dirname
, dname
, &st
, True
)) {
1653 TALLOC_FREE(talloced
);
1657 DEBUG(10,("can_delete_directory: got name %s - can't delete\n",
1659 status
= NT_STATUS_DIRECTORY_NOT_EMPTY
;
1662 TALLOC_FREE(talloced
);
1663 TALLOC_FREE(dir_hnd
);