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 /* Make directory handle internals available. */
39 struct name_cache_entry
{
45 connection_struct
*conn
;
49 size_t name_cache_size
;
50 struct name_cache_entry
*name_cache
;
51 unsigned int name_cache_index
;
52 unsigned int file_number
;
56 struct dptr_struct
*next
, *prev
;
59 struct connection_struct
*conn
;
60 struct smb_Dir
*dir_hnd
;
65 bool has_wild
; /* Set to true if the wcard entry has MS wildcard characters in it. */
66 bool did_stat
; /* Optimisation for non-wcard searches. */
69 static struct smb_Dir
*OpenDir_fsp(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
74 #define INVALID_DPTR_KEY (-3)
76 /****************************************************************************
78 ****************************************************************************/
80 bool make_dir_struct(TALLOC_CTX
*ctx
,
90 char *mask2
= talloc_strdup(ctx
, mask
);
96 if ((mode
& FILE_ATTRIBUTE_DIRECTORY
) != 0) {
100 memset(buf
+1,' ',11);
101 if ((p
= strchr_m(mask2
,'.')) != NULL
) {
103 push_ascii(buf
+1,mask2
,8, 0);
104 push_ascii(buf
+9,p
+1,3, 0);
107 push_ascii(buf
+1,mask2
,11, 0);
110 memset(buf
+21,'\0',DIR_STRUCT_SIZE
-21);
112 srv_put_dos_date(buf
,22,date
);
113 SSVAL(buf
,26,size
& 0xFFFF);
114 SSVAL(buf
,28,(size
>> 16)&0xFFFF);
115 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
116 Strange, but verified on W2K3. Needed for OS/2. JRA. */
117 push_ascii(buf
+30,fname
,12, uc
? STR_UPPER
: 0);
118 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf
+30, fname
));
122 /****************************************************************************
123 Initialise the dir bitmap.
124 ****************************************************************************/
126 bool init_dptrs(struct smbd_server_connection
*sconn
)
128 if (sconn
->searches
.dptr_bmap
) {
132 sconn
->searches
.dptr_bmap
= bitmap_talloc(
133 sconn
, MAX_DIRECTORY_HANDLES
);
135 if (sconn
->searches
.dptr_bmap
== NULL
) {
142 /****************************************************************************
143 Idle a dptr - the directory is closed but the control info is kept.
144 ****************************************************************************/
146 static void dptr_idle(struct dptr_struct
*dptr
)
149 DEBUG(4,("Idling dptr dnum %d\n",dptr
->dnum
));
150 TALLOC_FREE(dptr
->dir_hnd
);
154 /****************************************************************************
155 Idle the oldest dptr.
156 ****************************************************************************/
158 static void dptr_idleoldest(struct smbd_server_connection
*sconn
)
160 struct dptr_struct
*dptr
;
163 * Go to the end of the list.
165 dptr
= DLIST_TAIL(sconn
->searches
.dirptrs
);
168 DEBUG(0,("No dptrs available to idle ?\n"));
173 * Idle the oldest pointer.
176 for(; dptr
; dptr
= DLIST_PREV(dptr
)) {
184 /****************************************************************************
185 Get the struct dptr_struct for a dir index.
186 ****************************************************************************/
188 static struct dptr_struct
*dptr_get(struct smbd_server_connection
*sconn
,
189 int key
, bool forclose
)
191 struct dptr_struct
*dptr
;
193 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= dptr
->next
) {
194 if(dptr
->dnum
== key
) {
195 if (!forclose
&& !dptr
->dir_hnd
) {
196 if (sconn
->searches
.dirhandles_open
>= MAX_OPEN_DIRECTORIES
)
197 dptr_idleoldest(sconn
);
198 DEBUG(4,("dptr_get: Reopening dptr key %d\n",key
));
199 if (!(dptr
->dir_hnd
= OpenDir(
200 NULL
, dptr
->conn
, dptr
->path
,
201 dptr
->wcard
, dptr
->attr
))) {
202 DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr
->path
,
207 DLIST_PROMOTE(sconn
->searches
.dirptrs
,dptr
);
214 /****************************************************************************
215 Get the dir path for a dir index.
216 ****************************************************************************/
218 char *dptr_path(struct smbd_server_connection
*sconn
, int key
)
220 struct dptr_struct
*dptr
= dptr_get(sconn
, key
, false);
226 /****************************************************************************
227 Get the dir wcard for a dir index.
228 ****************************************************************************/
230 char *dptr_wcard(struct smbd_server_connection
*sconn
, int key
)
232 struct dptr_struct
*dptr
= dptr_get(sconn
, key
, false);
238 /****************************************************************************
239 Get the dir attrib for a dir index.
240 ****************************************************************************/
242 uint16
dptr_attr(struct smbd_server_connection
*sconn
, int key
)
244 struct dptr_struct
*dptr
= dptr_get(sconn
, key
, false);
250 /****************************************************************************
251 Close a dptr (internal func).
252 ****************************************************************************/
254 static void dptr_close_internal(struct dptr_struct
*dptr
)
256 struct smbd_server_connection
*sconn
= dptr
->conn
->sconn
;
258 DEBUG(4,("closing dptr key %d\n",dptr
->dnum
));
264 DLIST_REMOVE(sconn
->searches
.dirptrs
, dptr
);
267 * Free the dnum in the bitmap. Remember the dnum value is always
268 * biased by one with respect to the bitmap.
271 if (!bitmap_query(sconn
->searches
.dptr_bmap
, dptr
->dnum
- 1)) {
272 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
276 bitmap_clear(sconn
->searches
.dptr_bmap
, dptr
->dnum
- 1);
279 TALLOC_FREE(dptr
->dir_hnd
);
281 /* Lanman 2 specific code */
282 SAFE_FREE(dptr
->wcard
);
283 string_set(&dptr
->path
,"");
287 /****************************************************************************
288 Close a dptr given a key.
289 ****************************************************************************/
291 void dptr_close(struct smbd_server_connection
*sconn
, int *key
)
293 struct dptr_struct
*dptr
;
295 if(*key
== INVALID_DPTR_KEY
)
298 /* OS/2 seems to use -1 to indicate "close all directories" */
300 struct dptr_struct
*next
;
301 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= next
) {
303 dptr_close_internal(dptr
);
305 *key
= INVALID_DPTR_KEY
;
309 dptr
= dptr_get(sconn
, *key
, true);
312 DEBUG(0,("Invalid key %d given to dptr_close\n", *key
));
316 dptr_close_internal(dptr
);
318 *key
= INVALID_DPTR_KEY
;
321 /****************************************************************************
322 Close all dptrs for a cnum.
323 ****************************************************************************/
325 void dptr_closecnum(connection_struct
*conn
)
327 struct dptr_struct
*dptr
, *next
;
328 struct smbd_server_connection
*sconn
= conn
->sconn
;
334 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= next
) {
336 if (dptr
->conn
== conn
) {
337 dptr_close_internal(dptr
);
342 /****************************************************************************
343 Idle all dptrs for a cnum.
344 ****************************************************************************/
346 void dptr_idlecnum(connection_struct
*conn
)
348 struct dptr_struct
*dptr
;
349 struct smbd_server_connection
*sconn
= conn
->sconn
;
355 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= dptr
->next
) {
356 if (dptr
->conn
== conn
&& dptr
->dir_hnd
) {
362 /****************************************************************************
363 Close a dptr that matches a given path, only if it matches the spid also.
364 ****************************************************************************/
366 void dptr_closepath(struct smbd_server_connection
*sconn
,
367 char *path
,uint16 spid
)
369 struct dptr_struct
*dptr
, *next
;
370 for(dptr
= sconn
->searches
.dirptrs
; dptr
; dptr
= next
) {
372 if (spid
== dptr
->spid
&& strequal(dptr
->path
,path
))
373 dptr_close_internal(dptr
);
377 /****************************************************************************
378 Try and close the oldest handle not marked for
379 expect close in the hope that the client has
380 finished with that one.
381 ****************************************************************************/
383 static void dptr_close_oldest(struct smbd_server_connection
*sconn
,
386 struct dptr_struct
*dptr
;
389 * Go to the end of the list.
391 for(dptr
= sconn
->searches
.dirptrs
; dptr
&& dptr
->next
; dptr
= dptr
->next
)
395 DEBUG(0,("No old dptrs available to close oldest ?\n"));
400 * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
401 * does not have expect_close set. If 'old' is false, close
402 * one of the new dnum handles.
405 for(; dptr
; dptr
= DLIST_PREV(dptr
)) {
406 if ((old
&& (dptr
->dnum
< 256) && !dptr
->expect_close
) ||
407 (!old
&& (dptr
->dnum
> 255))) {
408 dptr_close_internal(dptr
);
414 /****************************************************************************
415 Create a new dir ptr. If the flag old_handle is true then we must allocate
416 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
417 one byte long. If old_handle is false we allocate from the range
418 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
419 a directory handle is never zero.
420 wcard must not be zero.
421 ****************************************************************************/
423 NTSTATUS
dptr_create(connection_struct
*conn
, files_struct
*fsp
,
424 const char *path
, bool old_handle
, bool expect_close
,uint16 spid
,
425 const char *wcard
, bool wcard_has_wild
, uint32 attr
, struct dptr_struct
**dptr_ret
)
427 struct smbd_server_connection
*sconn
= conn
->sconn
;
428 struct dptr_struct
*dptr
= NULL
;
429 struct smb_Dir
*dir_hnd
;
432 if (fsp
&& fsp
->is_directory
&& fsp
->fh
->fd
!= -1) {
433 path
= fsp
->fsp_name
->base_name
;
436 DEBUG(5,("dptr_create dir=%s\n", path
));
439 DEBUG(0,("dptr_create: called with fake connection_struct\n"));
440 return NT_STATUS_INTERNAL_ERROR
;
444 return NT_STATUS_INVALID_PARAMETER
;
448 dir_hnd
= OpenDir_fsp(NULL
, conn
, fsp
, wcard
, attr
);
450 status
= check_name(conn
,path
);
451 if (!NT_STATUS_IS_OK(status
)) {
454 dir_hnd
= OpenDir(NULL
, conn
, path
, wcard
, attr
);
458 return map_nt_error_from_unix(errno
);
461 if (sconn
->searches
.dirhandles_open
>= MAX_OPEN_DIRECTORIES
) {
462 dptr_idleoldest(sconn
);
465 dptr
= SMB_MALLOC_P(struct dptr_struct
);
467 DEBUG(0,("malloc fail in dptr_create.\n"));
468 TALLOC_FREE(dir_hnd
);
469 return NT_STATUS_NO_MEMORY
;
477 * This is an old-style SMBsearch request. Ensure the
478 * value we return will fit in the range 1-255.
481 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 0);
483 if(dptr
->dnum
== -1 || dptr
->dnum
> 254) {
486 * Try and close the oldest handle not marked for
487 * expect close in the hope that the client has
488 * finished with that one.
491 dptr_close_oldest(sconn
, true);
493 /* Now try again... */
494 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 0);
495 if(dptr
->dnum
== -1 || dptr
->dnum
> 254) {
496 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr
->dnum
));
498 TALLOC_FREE(dir_hnd
);
499 return NT_STATUS_TOO_MANY_OPENED_FILES
;
505 * This is a new-style trans2 request. Allocate from
506 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
509 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 255);
511 if(dptr
->dnum
== -1 || dptr
->dnum
< 255) {
514 * Try and close the oldest handle close in the hope that
515 * the client has finished with that one. This will only
516 * happen in the case of the Win98 client bug where it leaks
520 dptr_close_oldest(sconn
, false);
522 /* Now try again... */
523 dptr
->dnum
= bitmap_find(sconn
->searches
.dptr_bmap
, 255);
525 if(dptr
->dnum
== -1 || dptr
->dnum
< 255) {
526 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr
->dnum
));
528 TALLOC_FREE(dir_hnd
);
529 return NT_STATUS_TOO_MANY_OPENED_FILES
;
534 bitmap_set(sconn
->searches
.dptr_bmap
, dptr
->dnum
);
536 dptr
->dnum
+= 1; /* Always bias the dnum by one - no zero dnums allowed. */
538 string_set(&dptr
->path
,path
);
540 dptr
->dir_hnd
= dir_hnd
;
542 dptr
->expect_close
= expect_close
;
543 dptr
->wcard
= SMB_STRDUP(wcard
);
545 bitmap_clear(sconn
->searches
.dptr_bmap
, dptr
->dnum
- 1);
547 TALLOC_FREE(dir_hnd
);
548 return NT_STATUS_NO_MEMORY
;
550 if (lp_posix_pathnames() || (wcard
[0] == '.' && wcard
[1] == 0)) {
551 dptr
->has_wild
= True
;
553 dptr
->has_wild
= wcard_has_wild
;
558 DLIST_ADD(sconn
->searches
.dirptrs
, dptr
);
560 DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
561 dptr
->dnum
,path
,expect_close
));
569 /****************************************************************************
570 Wrapper functions to access the lower level directory handles.
571 ****************************************************************************/
573 void dptr_CloseDir(files_struct
*fsp
)
577 * Ugly hack. We have defined fdopendir to return ENOSYS if dirfd also isn't
578 * present. I hate Solaris. JRA.
581 if (fsp
->fh
->fd
!= -1 &&
582 fsp
->dptr
->dir_hnd
&&
583 dirfd(fsp
->dptr
->dir_hnd
->dir
)) {
584 /* The call below closes the underlying fd. */
588 dptr_close_internal(fsp
->dptr
);
593 void dptr_SeekDir(struct dptr_struct
*dptr
, long offset
)
595 SeekDir(dptr
->dir_hnd
, offset
);
598 long dptr_TellDir(struct dptr_struct
*dptr
)
600 return TellDir(dptr
->dir_hnd
);
603 bool dptr_has_wild(struct dptr_struct
*dptr
)
605 return dptr
->has_wild
;
608 int dptr_dnum(struct dptr_struct
*dptr
)
613 /****************************************************************************
614 Return the next visible file name, skipping veto'd and invisible files.
615 ****************************************************************************/
617 static const char *dptr_normal_ReadDirName(struct dptr_struct
*dptr
,
618 long *poffset
, SMB_STRUCT_STAT
*pst
,
621 /* Normal search for the next file. */
623 char *talloced
= NULL
;
625 while ((name
= ReadDirName(dptr
->dir_hnd
, poffset
, pst
, &talloced
))
627 if (is_visible_file(dptr
->conn
, dptr
->path
, name
, pst
, True
)) {
628 *ptalloced
= talloced
;
631 TALLOC_FREE(talloced
);
636 /****************************************************************************
637 Return the next visible file name, skipping veto'd and invisible files.
638 ****************************************************************************/
640 char *dptr_ReadDirName(TALLOC_CTX
*ctx
,
641 struct dptr_struct
*dptr
,
643 SMB_STRUCT_STAT
*pst
)
645 struct smb_filename smb_fname_base
;
647 const char *name_temp
= NULL
;
648 char *talloced
= NULL
;
649 char *pathreal
= NULL
;
650 char *found_name
= NULL
;
653 SET_STAT_INVALID(*pst
);
655 if (dptr
->has_wild
|| dptr
->did_stat
) {
656 name_temp
= dptr_normal_ReadDirName(dptr
, poffset
, pst
,
658 if (name_temp
== NULL
) {
661 if (talloced
!= NULL
) {
662 return talloc_move(ctx
, &talloced
);
664 return talloc_strdup(ctx
, name_temp
);
667 /* If poffset is -1 then we know we returned this name before and we
668 * have no wildcards. We're at the end of the directory. */
669 if (*poffset
== END_OF_DIRECTORY_OFFSET
) {
673 /* We know the stored wcard contains no wildcard characters.
674 * See if we can match with a stat call. If we can't, then set
675 * did_stat to true to ensure we only do this once and keep
678 dptr
->did_stat
= true;
680 /* First check if it should be visible. */
681 if (!is_visible_file(dptr
->conn
, dptr
->path
, dptr
->wcard
,
684 /* This only returns false if the file was found, but
685 is explicitly not visible. Set us to end of
686 directory, but return NULL as we know we can't ever
691 if (VALID_STAT(*pst
)) {
692 name
= talloc_strdup(ctx
, dptr
->wcard
);
696 pathreal
= talloc_asprintf(ctx
,
703 /* Create an smb_filename with stream_name == NULL. */
704 ZERO_STRUCT(smb_fname_base
);
705 smb_fname_base
.base_name
= pathreal
;
707 if (SMB_VFS_STAT(dptr
->conn
, &smb_fname_base
) == 0) {
708 *pst
= smb_fname_base
.st
;
709 name
= talloc_strdup(ctx
, dptr
->wcard
);
712 /* If we get any other error than ENOENT or ENOTDIR
713 then the file exists we just can't stat it. */
714 if (errno
!= ENOENT
&& errno
!= ENOTDIR
) {
715 name
= talloc_strdup(ctx
, dptr
->wcard
);
720 /* Stat failed. We know this is authoratiative if we are
721 * providing case sensitive semantics or the underlying
722 * filesystem is case sensitive.
724 if (dptr
->conn
->case_sensitive
||
725 !(dptr
->conn
->fs_capabilities
& FILE_CASE_SENSITIVE_SEARCH
))
731 * Try case-insensitive stat if the fs has the ability. This avoids
732 * scanning the whole directory.
734 ret
= SMB_VFS_GET_REAL_FILENAME(dptr
->conn
, dptr
->path
, dptr
->wcard
,
739 } else if (errno
== ENOENT
) {
740 /* The case-insensitive lookup was authoritative. */
744 TALLOC_FREE(pathreal
);
746 name_temp
= dptr_normal_ReadDirName(dptr
, poffset
, pst
, &talloced
);
747 if (name_temp
== NULL
) {
750 if (talloced
!= NULL
) {
751 return talloc_move(ctx
, &talloced
);
753 return talloc_strdup(ctx
, name_temp
);
756 TALLOC_FREE(pathreal
);
758 /* We need to set the underlying dir_hnd offset to -1
759 * also as this function is usually called with the
760 * output from TellDir. */
761 dptr
->dir_hnd
->offset
= *poffset
= END_OF_DIRECTORY_OFFSET
;
765 /****************************************************************************
766 Search for a file by name, skipping veto'ed and not visible files.
767 ****************************************************************************/
769 bool dptr_SearchDir(struct dptr_struct
*dptr
, const char *name
, long *poffset
, SMB_STRUCT_STAT
*pst
)
771 SET_STAT_INVALID(*pst
);
773 if (!dptr
->has_wild
&& (dptr
->dir_hnd
->offset
== END_OF_DIRECTORY_OFFSET
)) {
774 /* This is a singleton directory and we're already at the end. */
775 *poffset
= END_OF_DIRECTORY_OFFSET
;
779 return SearchDir(dptr
->dir_hnd
, name
, poffset
);
782 /****************************************************************************
783 Add the name we're returning into the underlying cache.
784 ****************************************************************************/
786 void dptr_DirCacheAdd(struct dptr_struct
*dptr
, const char *name
, long offset
)
788 DirCacheAdd(dptr
->dir_hnd
, name
, offset
);
791 /****************************************************************************
792 Initialize variables & state data at the beginning of all search SMB requests.
793 ****************************************************************************/
794 void dptr_init_search_op(struct dptr_struct
*dptr
)
796 SMB_VFS_INIT_SEARCH_OP(dptr
->conn
, dptr
->dir_hnd
->dir
);
799 /****************************************************************************
800 Fill the 5 byte server reserved dptr field.
801 ****************************************************************************/
803 bool dptr_fill(struct smbd_server_connection
*sconn
,
804 char *buf1
,unsigned int key
)
806 unsigned char *buf
= (unsigned char *)buf1
;
807 struct dptr_struct
*dptr
= dptr_get(sconn
, key
, false);
810 DEBUG(1,("filling null dirptr %d\n",key
));
813 offset
= (uint32
)TellDir(dptr
->dir_hnd
);
814 DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key
,
815 (long)dptr
->dir_hnd
,(int)offset
));
821 /****************************************************************************
822 Fetch the dir ptr and seek it given the 5 byte server field.
823 ****************************************************************************/
825 struct dptr_struct
*dptr_fetch(struct smbd_server_connection
*sconn
,
828 unsigned int key
= *(unsigned char *)buf
;
829 struct dptr_struct
*dptr
= dptr_get(sconn
, key
, false);
834 DEBUG(3,("fetched null dirptr %d\n",key
));
838 offset
= IVAL(buf
,1);
839 if (offset
== (uint32
)-1) {
840 seekoff
= END_OF_DIRECTORY_OFFSET
;
842 seekoff
= (long)offset
;
844 SeekDir(dptr
->dir_hnd
,seekoff
);
845 DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
846 key
, dptr
->path
, (int)seekoff
));
850 /****************************************************************************
852 ****************************************************************************/
854 struct dptr_struct
*dptr_fetch_lanman2(struct smbd_server_connection
*sconn
,
857 struct dptr_struct
*dptr
= dptr_get(sconn
, dptr_num
, false);
860 DEBUG(3,("fetched null dirptr %d\n",dptr_num
));
863 DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num
,dptr
->path
));
867 /****************************************************************************
868 Check that a file matches a particular file type.
869 ****************************************************************************/
871 bool dir_check_ftype(connection_struct
*conn
, uint32 mode
, uint32 dirtype
)
875 /* Check the "may have" search bits. */
876 if (((mode
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_DIRECTORY
)) != 0)
879 /* Check the "must have" bits, which are the may have bits shifted eight */
880 /* If must have bit is set, the file/dir can not be returned in search unless the matching
881 file attribute is set */
882 mask
= ((dirtype
>> 8) & (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)); /* & 0x37 */
884 if((mask
& (mode
& (FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
))) == mask
) /* check if matching attribute present */
893 static bool mangle_mask_match(connection_struct
*conn
,
894 const char *filename
,
899 if (!name_to_8_3(filename
,mname
,False
,conn
->params
)) {
902 return mask_match_search(mname
,mask
,False
);
905 bool smbd_dirptr_get_entry(TALLOC_CTX
*ctx
,
906 struct dptr_struct
*dirptr
,
911 bool (*match_fn
)(TALLOC_CTX
*ctx
,
916 bool (*mode_fn
)(TALLOC_CTX
*ctx
,
918 struct smb_filename
*smb_fname
,
922 struct smb_filename
**_smb_fname
,
926 connection_struct
*conn
= dirptr
->conn
;
932 needslash
= ( dirptr
->path
[strlen(dirptr
->path
) -1] != '/');
937 SMB_STRUCT_STAT sbuf
;
941 char *pathreal
= NULL
;
942 struct smb_filename smb_fname
;
947 cur_offset
= dptr_TellDir(dirptr
);
948 prev_offset
= cur_offset
;
949 dname
= dptr_ReadDirName(ctx
, dirptr
, &cur_offset
, &sbuf
);
951 DEBUG(6,("smbd_dirptr_get_entry: dirptr 0x%lx now at offset %ld\n",
952 (long)dirptr
, cur_offset
));
958 isdots
= (ISDOT(dname
) || ISDOTDOT(dname
));
959 if (dont_descend
&& !isdots
) {
965 * fname may get mangled, dname is never mangled.
966 * Whenever we're accessing the filesystem we use
967 * pathreal which is composed from dname.
970 ok
= match_fn(ctx
, private_data
, dname
, mask
, &fname
);
976 pathreal
= talloc_asprintf(ctx
, "%s%s%s",
986 /* Create smb_fname with NULL stream_name. */
987 ZERO_STRUCT(smb_fname
);
988 smb_fname
.base_name
= pathreal
;
991 ok
= mode_fn(ctx
, private_data
, &smb_fname
, &mode
);
995 TALLOC_FREE(pathreal
);
999 if (!dir_check_ftype(conn
, mode
, dirtype
)) {
1000 DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",
1001 fname
, (unsigned int)mode
, (unsigned int)dirtype
));
1004 TALLOC_FREE(pathreal
);
1008 if (ask_sharemode
) {
1009 struct timespec write_time_ts
;
1010 struct file_id fileid
;
1012 fileid
= vfs_file_id_from_sbuf(conn
,
1014 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
1015 if (!null_timespec(write_time_ts
)) {
1016 update_stat_ex_mtime(&smb_fname
.st
,
1021 DEBUG(3,("smbd_dirptr_get_entry mask=[%s] found %s "
1023 mask
, smb_fname_str_dbg(&smb_fname
),
1026 DirCacheAdd(dirptr
->dir_hnd
, dname
, cur_offset
);
1030 status
= copy_smb_filename(ctx
, &smb_fname
, _smb_fname
);
1031 TALLOC_FREE(pathreal
);
1032 if (!NT_STATUS_IS_OK(status
)) {
1037 *_prev_offset
= prev_offset
;
1045 /****************************************************************************
1046 Get an 8.3 directory entry.
1047 ****************************************************************************/
1049 static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX
*ctx
,
1055 connection_struct
*conn
= (connection_struct
*)private_data
;
1057 if ((strcmp(mask
,"*.*") == 0) ||
1058 mask_match_search(dname
, mask
, false) ||
1059 mangle_mask_match(conn
, dname
, mask
)) {
1063 if (!mangle_is_8_3(dname
, false, conn
->params
)) {
1064 bool ok
= name_to_8_3(dname
, mname
, false,
1074 *_fname
= talloc_strdup(ctx
, fname
);
1075 if (*_fname
== NULL
) {
1085 static bool smbd_dirptr_8_3_mode_fn(TALLOC_CTX
*ctx
,
1087 struct smb_filename
*smb_fname
,
1090 connection_struct
*conn
= (connection_struct
*)private_data
;
1092 if (!VALID_STAT(smb_fname
->st
)) {
1093 if ((SMB_VFS_STAT(conn
, smb_fname
)) != 0) {
1094 DEBUG(5,("smbd_dirptr_8_3_mode_fn: "
1095 "Couldn't stat [%s]. Error "
1097 smb_fname_str_dbg(smb_fname
),
1103 *_mode
= dos_mode(conn
, smb_fname
);
1107 bool get_dir_entry(TALLOC_CTX
*ctx
,
1108 struct dptr_struct
*dirptr
,
1114 struct timespec
*_date
,
1118 connection_struct
*conn
= dirptr
->conn
;
1120 struct smb_filename
*smb_fname
= NULL
;
1125 ok
= smbd_dirptr_get_entry(ctx
,
1131 smbd_dirptr_8_3_match_fn
,
1132 smbd_dirptr_8_3_mode_fn
,
1142 *_fname
= talloc_move(ctx
, &fname
);
1143 *_size
= smb_fname
->st
.st_ex_size
;
1145 *_date
= smb_fname
->st
.st_ex_mtime
;
1146 TALLOC_FREE(smb_fname
);
1150 /*******************************************************************
1151 Check to see if a user can read a file. This is only approximate,
1152 it is used as part of the "hide unreadable" option. Don't
1153 use it for anything security sensitive.
1154 ********************************************************************/
1156 static bool user_can_read_file(connection_struct
*conn
,
1157 struct smb_filename
*smb_fname
)
1160 * Never hide files from the root user.
1161 * We use (uid_t)0 here not sec_initial_uid()
1162 * as make test uses a single user context.
1165 if (get_current_uid(conn
) == (uid_t
)0) {
1169 return can_access_file_acl(conn
, smb_fname
, FILE_READ_DATA
);
1172 /*******************************************************************
1173 Check to see if a user can write a file (and only files, we do not
1174 check dirs on this one). This is only approximate,
1175 it is used as part of the "hide unwriteable" option. Don't
1176 use it for anything security sensitive.
1177 ********************************************************************/
1179 static bool user_can_write_file(connection_struct
*conn
,
1180 const struct smb_filename
*smb_fname
)
1183 * Never hide files from the root user.
1184 * We use (uid_t)0 here not sec_initial_uid()
1185 * as make test uses a single user context.
1188 if (get_current_uid(conn
) == (uid_t
)0) {
1192 SMB_ASSERT(VALID_STAT(smb_fname
->st
));
1194 /* Pseudo-open the file */
1196 if(S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1200 return can_write_to_file(conn
, smb_fname
);
1203 /*******************************************************************
1204 Is a file a "special" type ?
1205 ********************************************************************/
1207 static bool file_is_special(connection_struct
*conn
,
1208 const struct smb_filename
*smb_fname
)
1211 * Never hide files from the root user.
1212 * We use (uid_t)0 here not sec_initial_uid()
1213 * as make test uses a single user context.
1216 if (get_current_uid(conn
) == (uid_t
)0) {
1220 SMB_ASSERT(VALID_STAT(smb_fname
->st
));
1222 if (S_ISREG(smb_fname
->st
.st_ex_mode
) ||
1223 S_ISDIR(smb_fname
->st
.st_ex_mode
) ||
1224 S_ISLNK(smb_fname
->st
.st_ex_mode
))
1230 /*******************************************************************
1231 Should the file be seen by the client?
1232 NOTE: A successful return is no guarantee of the file's existence.
1233 ********************************************************************/
1235 bool is_visible_file(connection_struct
*conn
, const char *dir_path
,
1236 const char *name
, SMB_STRUCT_STAT
*pst
, bool use_veto
)
1238 bool hide_unreadable
= lp_hideunreadable(SNUM(conn
));
1239 bool hide_unwriteable
= lp_hideunwriteable_files(SNUM(conn
));
1240 bool hide_special
= lp_hide_special_files(SNUM(conn
));
1242 struct smb_filename
*smb_fname_base
= NULL
;
1246 if ((strcmp(".",name
) == 0) || (strcmp("..",name
) == 0)) {
1247 return True
; /* . and .. are always visible. */
1250 /* If it's a vetoed file, pretend it doesn't even exist */
1251 if (use_veto
&& IS_VETO_PATH(conn
, name
)) {
1252 DEBUG(10,("is_visible_file: file %s is vetoed.\n", name
));
1256 if (hide_unreadable
|| hide_unwriteable
|| hide_special
) {
1257 entry
= talloc_asprintf(talloc_tos(), "%s/%s", dir_path
, name
);
1263 /* Create an smb_filename with stream_name == NULL. */
1264 status
= create_synthetic_smb_fname(talloc_tos(), entry
, NULL
,
1265 pst
, &smb_fname_base
);
1266 if (!NT_STATUS_IS_OK(status
)) {
1271 /* If the file name does not exist, there's no point checking
1272 * the configuration options. We succeed, on the basis that the
1273 * checks *might* have passed if the file was present.
1275 if (!VALID_STAT(*pst
)) {
1276 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
1280 *pst
= smb_fname_base
->st
;
1284 /* Honour _hide unreadable_ option */
1285 if (hide_unreadable
&&
1286 !user_can_read_file(conn
, smb_fname_base
)) {
1287 DEBUG(10,("is_visible_file: file %s is unreadable.\n",
1292 /* Honour _hide unwriteable_ option */
1293 if (hide_unwriteable
&& !user_can_write_file(conn
,
1295 DEBUG(10,("is_visible_file: file %s is unwritable.\n",
1300 /* Honour _hide_special_ option */
1301 if (hide_special
&& file_is_special(conn
, smb_fname_base
)) {
1302 DEBUG(10,("is_visible_file: file %s is special.\n",
1311 TALLOC_FREE(smb_fname_base
);
1316 static int smb_Dir_destructor(struct smb_Dir
*dirp
)
1320 if (dirp
->conn
->sconn
) {
1321 files_struct
*fsp
= file_find_fd(dirp
->conn
->sconn
,
1324 /* The call below closes the underlying fd. */
1329 SMB_VFS_CLOSEDIR(dirp
->conn
,dirp
->dir
);
1331 if (dirp
->conn
->sconn
) {
1332 dirp
->conn
->sconn
->searches
.dirhandles_open
--;
1337 /*******************************************************************
1339 ********************************************************************/
1341 struct smb_Dir
*OpenDir(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
1346 struct smb_Dir
*dirp
= talloc_zero(mem_ctx
, struct smb_Dir
);
1347 struct smbd_server_connection
*sconn
= conn
->sconn
;
1354 dirp
->name_cache_size
= lp_directory_name_cache_size(SNUM(conn
));
1356 dirp
->dir_path
= talloc_strdup(dirp
, name
);
1357 if (!dirp
->dir_path
) {
1363 sconn
->searches
.dirhandles_open
++;
1365 talloc_set_destructor(dirp
, smb_Dir_destructor
);
1367 dirp
->dir
= SMB_VFS_OPENDIR(conn
, dirp
->dir_path
, mask
, attr
);
1369 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp
->dir_path
,
1381 /*******************************************************************
1382 Open a directory from an fsp.
1383 ********************************************************************/
1385 static struct smb_Dir
*OpenDir_fsp(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
1390 struct smb_Dir
*dirp
= talloc_zero(mem_ctx
, struct smb_Dir
);
1391 struct smbd_server_connection
*sconn
= conn
->sconn
;
1398 dirp
->name_cache_size
= lp_directory_name_cache_size(SNUM(conn
));
1400 dirp
->dir_path
= talloc_strdup(dirp
, fsp
->fsp_name
->base_name
);
1401 if (!dirp
->dir_path
) {
1407 sconn
->searches
.dirhandles_open
++;
1409 talloc_set_destructor(dirp
, smb_Dir_destructor
);
1411 if (fsp
->is_directory
&& fsp
->fh
->fd
!= -1) {
1412 dirp
->dir
= SMB_VFS_FDOPENDIR(fsp
, mask
, attr
);
1413 if (dirp
->dir
== NULL
) {
1414 DEBUG(10,("OpenDir_fsp: SMB_VFS_FDOPENDIR on %s returned "
1418 if (errno
!= ENOSYS
) {
1424 if (dirp
->dir
== NULL
) {
1425 /* FDOPENDIR didn't work. Use OPENDIR instead. */
1426 dirp
->dir
= SMB_VFS_OPENDIR(conn
, dirp
->dir_path
, mask
, attr
);
1430 DEBUG(5,("OpenDir_fsp: Can't open %s. %s\n", dirp
->dir_path
,
1443 /*******************************************************************
1444 Read from a directory.
1445 Return directory entry, current offset, and optional stat information.
1446 Don't check for veto or invisible files.
1447 ********************************************************************/
1449 const char *ReadDirName(struct smb_Dir
*dirp
, long *poffset
,
1450 SMB_STRUCT_STAT
*sbuf
, char **ptalloced
)
1453 char *talloced
= NULL
;
1454 connection_struct
*conn
= dirp
->conn
;
1456 /* Cheat to allow . and .. to be the first entries returned. */
1457 if (((*poffset
== START_OF_DIRECTORY_OFFSET
) ||
1458 (*poffset
== DOT_DOT_DIRECTORY_OFFSET
)) && (dirp
->file_number
< 2))
1460 if (dirp
->file_number
== 0) {
1462 *poffset
= dirp
->offset
= START_OF_DIRECTORY_OFFSET
;
1465 *poffset
= dirp
->offset
= DOT_DOT_DIRECTORY_OFFSET
;
1467 dirp
->file_number
++;
1470 } else if (*poffset
== END_OF_DIRECTORY_OFFSET
) {
1471 *poffset
= dirp
->offset
= END_OF_DIRECTORY_OFFSET
;
1474 /* A real offset, seek to it. */
1475 SeekDir(dirp
, *poffset
);
1478 while ((n
= vfs_readdirname(conn
, dirp
->dir
, sbuf
, &talloced
))) {
1479 /* Ignore . and .. - we've already returned them. */
1481 if ((n
[1] == '\0') || (n
[1] == '.' && n
[2] == '\0')) {
1482 TALLOC_FREE(talloced
);
1486 *poffset
= dirp
->offset
= SMB_VFS_TELLDIR(conn
, dirp
->dir
);
1487 *ptalloced
= talloced
;
1488 dirp
->file_number
++;
1491 *poffset
= dirp
->offset
= END_OF_DIRECTORY_OFFSET
;
1496 /*******************************************************************
1497 Rewind to the start.
1498 ********************************************************************/
1500 void RewindDir(struct smb_Dir
*dirp
, long *poffset
)
1502 SMB_VFS_REWINDDIR(dirp
->conn
, dirp
->dir
);
1503 dirp
->file_number
= 0;
1504 dirp
->offset
= START_OF_DIRECTORY_OFFSET
;
1505 *poffset
= START_OF_DIRECTORY_OFFSET
;
1508 /*******************************************************************
1510 ********************************************************************/
1512 void SeekDir(struct smb_Dir
*dirp
, long offset
)
1514 if (offset
!= dirp
->offset
) {
1515 if (offset
== START_OF_DIRECTORY_OFFSET
) {
1516 RewindDir(dirp
, &offset
);
1518 * Ok we should really set the file number here
1519 * to 1 to enable ".." to be returned next. Trouble
1520 * is I'm worried about callers using SeekDir(dirp,0)
1521 * as equivalent to RewindDir(). So leave this alone
1524 } else if (offset
== DOT_DOT_DIRECTORY_OFFSET
) {
1525 RewindDir(dirp
, &offset
);
1527 * Set the file number to 2 - we want to get the first
1528 * real file entry (the one we return after "..")
1529 * on the next ReadDir.
1531 dirp
->file_number
= 2;
1532 } else if (offset
== END_OF_DIRECTORY_OFFSET
) {
1533 ; /* Don't seek in this case. */
1535 SMB_VFS_SEEKDIR(dirp
->conn
, dirp
->dir
, offset
);
1537 dirp
->offset
= offset
;
1541 /*******************************************************************
1542 Tell a dir position.
1543 ********************************************************************/
1545 long TellDir(struct smb_Dir
*dirp
)
1547 return(dirp
->offset
);
1550 /*******************************************************************
1551 Add an entry into the dcache.
1552 ********************************************************************/
1554 void DirCacheAdd(struct smb_Dir
*dirp
, const char *name
, long offset
)
1556 struct name_cache_entry
*e
;
1558 if (dirp
->name_cache_size
== 0) {
1562 if (dirp
->name_cache
== NULL
) {
1563 dirp
->name_cache
= talloc_zero_array(
1564 dirp
, struct name_cache_entry
, dirp
->name_cache_size
);
1566 if (dirp
->name_cache
== NULL
) {
1571 dirp
->name_cache_index
= (dirp
->name_cache_index
+1) %
1572 dirp
->name_cache_size
;
1573 e
= &dirp
->name_cache
[dirp
->name_cache_index
];
1574 TALLOC_FREE(e
->name
);
1575 e
->name
= talloc_strdup(dirp
, name
);
1579 /*******************************************************************
1580 Find an entry by name. Leave us at the offset after it.
1581 Don't check for veto or invisible files.
1582 ********************************************************************/
1584 bool SearchDir(struct smb_Dir
*dirp
, const char *name
, long *poffset
)
1587 const char *entry
= NULL
;
1588 char *talloced
= NULL
;
1589 connection_struct
*conn
= dirp
->conn
;
1591 /* Search back in the name cache. */
1592 if (dirp
->name_cache_size
&& dirp
->name_cache
) {
1593 for (i
= dirp
->name_cache_index
; i
>= 0; i
--) {
1594 struct name_cache_entry
*e
= &dirp
->name_cache
[i
];
1595 if (e
->name
&& (conn
->case_sensitive
? (strcmp(e
->name
, name
) == 0) : strequal(e
->name
, name
))) {
1596 *poffset
= e
->offset
;
1597 SeekDir(dirp
, e
->offset
);
1601 for (i
= dirp
->name_cache_size
- 1; i
> dirp
->name_cache_index
; i
--) {
1602 struct name_cache_entry
*e
= &dirp
->name_cache
[i
];
1603 if (e
->name
&& (conn
->case_sensitive
? (strcmp(e
->name
, name
) == 0) : strequal(e
->name
, name
))) {
1604 *poffset
= e
->offset
;
1605 SeekDir(dirp
, e
->offset
);
1611 /* Not found in the name cache. Rewind directory and start from scratch. */
1612 SMB_VFS_REWINDDIR(conn
, dirp
->dir
);
1613 dirp
->file_number
= 0;
1614 *poffset
= START_OF_DIRECTORY_OFFSET
;
1615 while ((entry
= ReadDirName(dirp
, poffset
, NULL
, &talloced
))) {
1616 if (conn
->case_sensitive
? (strcmp(entry
, name
) == 0) : strequal(entry
, name
)) {
1617 TALLOC_FREE(talloced
);
1620 TALLOC_FREE(talloced
);
1625 /*****************************************************************
1626 Is this directory empty ?
1627 *****************************************************************/
1629 NTSTATUS
smbd_can_delete_directory(struct connection_struct
*conn
,
1630 const char *dirname
)
1632 NTSTATUS status
= NT_STATUS_OK
;
1634 const char *dname
= NULL
;
1635 char *talloced
= NULL
;
1637 struct smb_Dir
*dir_hnd
= OpenDir(talloc_tos(), conn
,
1641 return map_nt_error_from_unix(errno
);
1644 while ((dname
= ReadDirName(dir_hnd
, &dirpos
, &st
, &talloced
))) {
1645 /* Quick check for "." and ".." */
1646 if (dname
[0] == '.') {
1647 if (!dname
[1] || (dname
[1] == '.' && !dname
[2])) {
1648 TALLOC_FREE(talloced
);
1653 if (!is_visible_file(conn
, dirname
, dname
, &st
, True
)) {
1654 TALLOC_FREE(talloced
);
1658 DEBUG(10,("can_delete_directory: got name %s - can't delete\n",
1660 status
= NT_STATUS_DIRECTORY_NOT_EMPTY
;
1663 TALLOC_FREE(talloced
);
1664 TALLOC_FREE(dir_hnd
);