2 Unix SMB/CIFS implementation.
3 Directory handling routines
4 Copyright (C) Andrew Tridgell 1992-1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 This module implements directory related functions for Samba.
27 extern struct current_user current_user
;
29 /* "Special" directory offsets. */
30 #define END_OF_DIRECTORY_OFFSET ((long)-1)
31 #define START_OF_DIRECTORY_OFFSET ((long)0)
32 #define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000)
34 /* Make directory handle internals available. */
36 #define NAME_CACHE_SIZE 100
38 struct name_cache_entry
{
44 connection_struct
*conn
;
48 struct name_cache_entry
*name_cache
;
49 unsigned int name_cache_index
;
50 unsigned int file_number
;
54 struct dptr_struct
*next
, *prev
;
57 struct connection_struct
*conn
;
58 struct smb_Dir
*dir_hnd
;
63 BOOL has_wild
; /* Set to true if the wcard entry has MS wildcard characters in it. */
66 static struct bitmap
*dptr_bmap
;
67 static struct dptr_struct
*dirptrs
;
68 static int dirhandles_open
= 0;
70 #define INVALID_DPTR_KEY (-3)
72 /****************************************************************************
74 ****************************************************************************/
76 void make_dir_struct(char *buf
, const char *mask
, const char *fname
,SMB_OFF_T size
,uint32 mode
,time_t date
, BOOL uc
)
83 if ((mode
& aDIR
) != 0)
87 if ((p
= strchr_m(mask2
,'.')) != NULL
) {
89 push_ascii(buf
+1,mask2
,8, 0);
90 push_ascii(buf
+9,p
+1,3, 0);
93 push_ascii(buf
+1,mask2
,11, 0);
95 memset(buf
+21,'\0',DIR_STRUCT_SIZE
-21);
97 srv_put_dos_date(buf
,22,date
);
98 SSVAL(buf
,26,size
& 0xFFFF);
99 SSVAL(buf
,28,(size
>> 16)&0xFFFF);
100 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
101 Strange, but verified on W2K3. Needed for OS/2. JRA. */
102 push_ascii(buf
+30,fname
,12, uc
? STR_UPPER
: 0);
103 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf
+30, fname
));
106 /****************************************************************************
107 Initialise the dir bitmap.
108 ****************************************************************************/
110 void init_dptrs(void)
112 static BOOL dptrs_init
=False
;
117 dptr_bmap
= bitmap_allocate(MAX_DIRECTORY_HANDLES
);
120 exit_server("out of memory in init_dptrs");
125 /****************************************************************************
126 Idle a dptr - the directory is closed but the control info is kept.
127 ****************************************************************************/
129 static void dptr_idle(struct dptr_struct
*dptr
)
132 DEBUG(4,("Idling dptr dnum %d\n",dptr
->dnum
));
133 CloseDir(dptr
->dir_hnd
);
134 dptr
->dir_hnd
= NULL
;
138 /****************************************************************************
139 Idle the oldest dptr.
140 ****************************************************************************/
142 static void dptr_idleoldest(void)
144 struct dptr_struct
*dptr
;
147 * Go to the end of the list.
149 for(dptr
= dirptrs
; dptr
&& dptr
->next
; dptr
= dptr
->next
)
153 DEBUG(0,("No dptrs available to idle ?\n"));
158 * Idle the oldest pointer.
161 for(; dptr
; dptr
= dptr
->prev
) {
169 /****************************************************************************
170 Get the struct dptr_struct for a dir index.
171 ****************************************************************************/
173 static struct dptr_struct
*dptr_get(int key
, BOOL forclose
)
175 struct dptr_struct
*dptr
;
177 for(dptr
= dirptrs
; dptr
; dptr
= dptr
->next
) {
178 if(dptr
->dnum
== key
) {
179 if (!forclose
&& !dptr
->dir_hnd
) {
180 if (dirhandles_open
>= MAX_OPEN_DIRECTORIES
)
182 DEBUG(4,("dptr_get: Reopening dptr key %d\n",key
));
183 if (!(dptr
->dir_hnd
= OpenDir(dptr
->conn
, dptr
->path
, dptr
->wcard
, dptr
->attr
))) {
184 DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr
->path
,
189 DLIST_PROMOTE(dirptrs
,dptr
);
196 /****************************************************************************
197 Get the dir path for a dir index.
198 ****************************************************************************/
200 char *dptr_path(int key
)
202 struct dptr_struct
*dptr
= dptr_get(key
, False
);
208 /****************************************************************************
209 Get the dir wcard for a dir index.
210 ****************************************************************************/
212 char *dptr_wcard(int key
)
214 struct dptr_struct
*dptr
= dptr_get(key
, False
);
220 /****************************************************************************
221 Get the dir attrib for a dir index.
222 ****************************************************************************/
224 uint16
dptr_attr(int key
)
226 struct dptr_struct
*dptr
= dptr_get(key
, False
);
232 /****************************************************************************
233 Close a dptr (internal func).
234 ****************************************************************************/
236 static void dptr_close_internal(struct dptr_struct
*dptr
)
238 DEBUG(4,("closing dptr key %d\n",dptr
->dnum
));
240 DLIST_REMOVE(dirptrs
, dptr
);
243 * Free the dnum in the bitmap. Remember the dnum value is always
244 * biased by one with respect to the bitmap.
247 if(bitmap_query( dptr_bmap
, dptr
->dnum
- 1) != True
) {
248 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
252 bitmap_clear(dptr_bmap
, dptr
->dnum
- 1);
255 CloseDir(dptr
->dir_hnd
);
258 /* Lanman 2 specific code */
259 SAFE_FREE(dptr
->wcard
);
260 string_set(&dptr
->path
,"");
264 /****************************************************************************
265 Close a dptr given a key.
266 ****************************************************************************/
268 void dptr_close(int *key
)
270 struct dptr_struct
*dptr
;
272 if(*key
== INVALID_DPTR_KEY
)
275 /* OS/2 seems to use -1 to indicate "close all directories" */
277 struct dptr_struct
*next
;
278 for(dptr
= dirptrs
; dptr
; dptr
= next
) {
280 dptr_close_internal(dptr
);
282 *key
= INVALID_DPTR_KEY
;
286 dptr
= dptr_get(*key
, True
);
289 DEBUG(0,("Invalid key %d given to dptr_close\n", *key
));
293 dptr_close_internal(dptr
);
295 *key
= INVALID_DPTR_KEY
;
298 /****************************************************************************
299 Close all dptrs for a cnum.
300 ****************************************************************************/
302 void dptr_closecnum(connection_struct
*conn
)
304 struct dptr_struct
*dptr
, *next
;
305 for(dptr
= dirptrs
; dptr
; dptr
= next
) {
307 if (dptr
->conn
== conn
)
308 dptr_close_internal(dptr
);
312 /****************************************************************************
313 Idle all dptrs for a cnum.
314 ****************************************************************************/
316 void dptr_idlecnum(connection_struct
*conn
)
318 struct dptr_struct
*dptr
;
319 for(dptr
= dirptrs
; dptr
; dptr
= dptr
->next
) {
320 if (dptr
->conn
== conn
&& dptr
->dir_hnd
)
325 /****************************************************************************
326 Close a dptr that matches a given path, only if it matches the spid also.
327 ****************************************************************************/
329 void dptr_closepath(char *path
,uint16 spid
)
331 struct dptr_struct
*dptr
, *next
;
332 for(dptr
= dirptrs
; dptr
; dptr
= next
) {
334 if (spid
== dptr
->spid
&& strequal(dptr
->path
,path
))
335 dptr_close_internal(dptr
);
339 /****************************************************************************
340 Try and close the oldest handle not marked for
341 expect close in the hope that the client has
342 finished with that one.
343 ****************************************************************************/
345 static void dptr_close_oldest(BOOL old
)
347 struct dptr_struct
*dptr
;
350 * Go to the end of the list.
352 for(dptr
= dirptrs
; dptr
&& dptr
->next
; dptr
= dptr
->next
)
356 DEBUG(0,("No old dptrs available to close oldest ?\n"));
361 * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
362 * does not have expect_close set. If 'old' is false, close
363 * one of the new dnum handles.
366 for(; dptr
; dptr
= dptr
->prev
) {
367 if ((old
&& (dptr
->dnum
< 256) && !dptr
->expect_close
) ||
368 (!old
&& (dptr
->dnum
> 255))) {
369 dptr_close_internal(dptr
);
375 /****************************************************************************
376 Create a new dir ptr. If the flag old_handle is true then we must allocate
377 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
378 one byte long. If old_handle is false we allocate from the range
379 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
380 a directory handle is never zero.
381 wcard must not be zero.
382 ****************************************************************************/
384 int dptr_create(connection_struct
*conn
, pstring path
, BOOL old_handle
, BOOL expect_close
,uint16 spid
,
385 const char *wcard
, BOOL wcard_has_wild
, uint32 attr
)
387 struct dptr_struct
*dptr
= NULL
;
388 struct smb_Dir
*dir_hnd
;
391 DEBUG(5,("dptr_create dir=%s\n", path
));
397 if (!check_name(path
,conn
))
398 return(-2); /* Code to say use a unix error return code. */
400 /* use a const pointer from here on */
405 dir_hnd
= OpenDir(conn
, dir2
, wcard
, attr
);
410 string_set(&conn
->dirpath
,dir2
);
412 if (dirhandles_open
>= MAX_OPEN_DIRECTORIES
)
415 dptr
= SMB_MALLOC_P(struct dptr_struct
);
417 DEBUG(0,("malloc fail in dptr_create.\n"));
427 * This is an old-style SMBsearch request. Ensure the
428 * value we return will fit in the range 1-255.
431 dptr
->dnum
= bitmap_find(dptr_bmap
, 0);
433 if(dptr
->dnum
== -1 || dptr
->dnum
> 254) {
436 * Try and close the oldest handle not marked for
437 * expect close in the hope that the client has
438 * finished with that one.
441 dptr_close_oldest(True
);
443 /* Now try again... */
444 dptr
->dnum
= bitmap_find(dptr_bmap
, 0);
445 if(dptr
->dnum
== -1 || dptr
->dnum
> 254) {
446 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr
->dnum
));
455 * This is a new-style trans2 request. Allocate from
456 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
459 dptr
->dnum
= bitmap_find(dptr_bmap
, 255);
461 if(dptr
->dnum
== -1 || dptr
->dnum
< 255) {
464 * Try and close the oldest handle close in the hope that
465 * the client has finished with that one. This will only
466 * happen in the case of the Win98 client bug where it leaks
470 dptr_close_oldest(False
);
472 /* Now try again... */
473 dptr
->dnum
= bitmap_find(dptr_bmap
, 255);
475 if(dptr
->dnum
== -1 || dptr
->dnum
< 255) {
476 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr
->dnum
));
484 bitmap_set(dptr_bmap
, dptr
->dnum
);
486 dptr
->dnum
+= 1; /* Always bias the dnum by one - no zero dnums allowed. */
488 string_set(&dptr
->path
,dir2
);
490 dptr
->dir_hnd
= dir_hnd
;
492 dptr
->expect_close
= expect_close
;
493 dptr
->wcard
= SMB_STRDUP(wcard
);
495 bitmap_clear(dptr_bmap
, dptr
->dnum
- 1);
500 if (lp_posix_pathnames() || (wcard
[0] == '.' && wcard
[1] == 0)) {
501 dptr
->has_wild
= True
;
503 dptr
->has_wild
= wcard_has_wild
;
508 DLIST_ADD(dirptrs
, dptr
);
510 DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
511 dptr
->dnum
,path
,expect_close
));
519 /****************************************************************************
520 Wrapper functions to access the lower level directory handles.
521 ****************************************************************************/
523 int dptr_CloseDir(struct dptr_struct
*dptr
)
525 return CloseDir(dptr
->dir_hnd
);
528 void dptr_SeekDir(struct dptr_struct
*dptr
, long offset
)
530 SeekDir(dptr
->dir_hnd
, offset
);
533 long dptr_TellDir(struct dptr_struct
*dptr
)
535 return TellDir(dptr
->dir_hnd
);
538 /****************************************************************************
539 Return the next visible file name, skipping veto'd and invisible files.
540 ****************************************************************************/
542 static const char *dptr_normal_ReadDirName(struct dptr_struct
*dptr
, long *poffset
, SMB_STRUCT_STAT
*pst
)
544 /* Normal search for the next file. */
546 while ((name
= ReadDirName(dptr
->dir_hnd
, poffset
)) != NULL
) {
547 if (is_visible_file(dptr
->conn
, dptr
->path
, name
, pst
, True
)) {
554 /****************************************************************************
555 Return the next visible file name, skipping veto'd and invisible files.
556 ****************************************************************************/
558 const char *dptr_ReadDirName(struct dptr_struct
*dptr
, long *poffset
, SMB_STRUCT_STAT
*pst
)
562 SET_STAT_INVALID(*pst
);
564 if (dptr
->has_wild
) {
565 return dptr_normal_ReadDirName(dptr
, poffset
, pst
);
568 /* If poffset is -1 then we know we returned this name before and we have
569 no wildcards. We're at the end of the directory. */
570 if (*poffset
== END_OF_DIRECTORY_OFFSET
) {
574 /* We know the stored wcard contains no wildcard characters. See if we can match
575 with a stat call. If we can't, then set has_wild to true to
576 prevent us from doing this on every call. */
578 /* First check if it should be visible. */
579 if (!is_visible_file(dptr
->conn
, dptr
->path
, dptr
->wcard
, pst
, True
)) {
580 dptr
->has_wild
= True
;
581 return dptr_normal_ReadDirName(dptr
, poffset
, pst
);
584 if (VALID_STAT(*pst
)) {
585 /* We need to set the underlying dir_hdn offset to -1 also as
586 this function is usually called with the output from TellDir. */
587 dptr
->dir_hnd
->offset
= *poffset
= END_OF_DIRECTORY_OFFSET
;
591 pstrcpy(pathreal
,dptr
->path
);
592 pstrcat(pathreal
,"/");
593 pstrcat(pathreal
,dptr
->wcard
);
595 if (SMB_VFS_STAT(dptr
->conn
,pathreal
,pst
) == 0) {
596 /* We need to set the underlying dir_hdn offset to -1 also as
597 this function is usually called with the output from TellDir. */
598 dptr
->dir_hnd
->offset
= *poffset
= END_OF_DIRECTORY_OFFSET
;
601 /* If we get any other error than ENOENT or ENOTDIR
602 then the file exists we just can't stat it. */
603 if (errno
!= ENOENT
&& errno
!= ENOTDIR
) {
604 /* We need to set the underlying dir_hdn offset to -1 also as
605 this function is usually called with the output from TellDir. */
606 dptr
->dir_hnd
->offset
= *poffset
= END_OF_DIRECTORY_OFFSET
;
611 /* In case sensitive mode we don't search - we know if it doesn't exist
612 with a stat we will fail. */
614 if (dptr
->conn
->case_sensitive
) {
615 /* We need to set the underlying dir_hdn offset to -1 also as
616 this function is usually called with the output from TellDir. */
617 dptr
->dir_hnd
->offset
= *poffset
= END_OF_DIRECTORY_OFFSET
;
620 dptr
->has_wild
= True
;
621 return dptr_normal_ReadDirName(dptr
, poffset
, pst
);
625 /****************************************************************************
626 Search for a file by name, skipping veto'ed and not visible files.
627 ****************************************************************************/
629 BOOL
dptr_SearchDir(struct dptr_struct
*dptr
, const char *name
, long *poffset
, SMB_STRUCT_STAT
*pst
)
631 SET_STAT_INVALID(*pst
);
633 if (!dptr
->has_wild
&& (dptr
->dir_hnd
->offset
== END_OF_DIRECTORY_OFFSET
)) {
634 /* This is a singleton directory and we're already at the end. */
635 *poffset
= END_OF_DIRECTORY_OFFSET
;
639 if (SearchDir(dptr
->dir_hnd
, name
, poffset
)) {
640 if (is_visible_file(dptr
->conn
, dptr
->path
, name
, pst
, True
)) {
647 /****************************************************************************
648 Add the name we're returning into the underlying cache.
649 ****************************************************************************/
651 void dptr_DirCacheAdd(struct dptr_struct
*dptr
, const char *name
, long offset
)
653 DirCacheAdd(dptr
->dir_hnd
, name
, offset
);
656 /****************************************************************************
657 Fill the 5 byte server reserved dptr field.
658 ****************************************************************************/
660 BOOL
dptr_fill(char *buf1
,unsigned int key
)
662 unsigned char *buf
= (unsigned char *)buf1
;
663 struct dptr_struct
*dptr
= dptr_get(key
, False
);
666 DEBUG(1,("filling null dirptr %d\n",key
));
669 offset
= (uint32
)TellDir(dptr
->dir_hnd
);
670 DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key
,
671 (long)dptr
->dir_hnd
,(int)offset
));
677 /****************************************************************************
678 Fetch the dir ptr and seek it given the 5 byte server field.
679 ****************************************************************************/
681 struct dptr_struct
*dptr_fetch(char *buf
,int *num
)
683 unsigned int key
= *(unsigned char *)buf
;
684 struct dptr_struct
*dptr
= dptr_get(key
, False
);
689 DEBUG(3,("fetched null dirptr %d\n",key
));
693 offset
= IVAL(buf
,1);
694 if (offset
== (uint32
)-1) {
695 seekoff
= END_OF_DIRECTORY_OFFSET
;
697 seekoff
= (long)offset
;
699 SeekDir(dptr
->dir_hnd
,seekoff
);
700 DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
701 key
,dptr_path(key
),(int)seekoff
));
705 /****************************************************************************
707 ****************************************************************************/
709 struct dptr_struct
*dptr_fetch_lanman2(int dptr_num
)
711 struct dptr_struct
*dptr
= dptr_get(dptr_num
, False
);
714 DEBUG(3,("fetched null dirptr %d\n",dptr_num
));
717 DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num
,dptr_path(dptr_num
)));
721 /****************************************************************************
722 Check that a file matches a particular file type.
723 ****************************************************************************/
725 BOOL
dir_check_ftype(connection_struct
*conn
, uint32 mode
, uint32 dirtype
)
729 /* Check the "may have" search bits. */
730 if (((mode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
| aDIR
)) != 0)
733 /* Check the "must have" bits, which are the may have bits shifted eight */
734 /* If must have bit is set, the file/dir can not be returned in search unless the matching
735 file attribute is set */
736 mask
= ((dirtype
>> 8) & (aDIR
|aARCH
|aRONLY
|aHIDDEN
|aSYSTEM
)); /* & 0x37 */
738 if((mask
& (mode
& (aDIR
|aARCH
|aRONLY
|aHIDDEN
|aSYSTEM
))) == mask
) /* check if matching attribute present */
747 static BOOL
mangle_mask_match(connection_struct
*conn
, fstring filename
, char *mask
)
749 mangle_map(filename
,True
,False
,SNUM(conn
));
750 return mask_match_search(filename
,mask
,False
);
753 /****************************************************************************
754 Get an 8.3 directory entry.
755 ****************************************************************************/
757 BOOL
get_dir_entry(connection_struct
*conn
,char *mask
,uint32 dirtype
, pstring fname
,
758 SMB_OFF_T
*size
,uint32
*mode
,time_t *date
,BOOL check_descend
)
762 SMB_STRUCT_STAT sbuf
;
768 *path
= *pathreal
= *filename
= 0;
770 needslash
= ( conn
->dirpath
[strlen(conn
->dirpath
) -1] != '/');
776 long curoff
= dptr_TellDir(conn
->dirptr
);
777 dname
= dptr_ReadDirName(conn
->dirptr
, &curoff
, &sbuf
);
779 DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
780 (long)conn
->dirptr
,TellDir(conn
->dirptr
->dir_hnd
)));
785 pstrcpy(filename
,dname
);
787 /* notice the special *.* handling. This appears to be the only difference
788 between the wildcard handling in this routine and in the trans2 routines.
789 see masktest for a demo
791 if ((strcmp(mask
,"*.*") == 0) ||
792 mask_match_search(filename
,mask
,False
) ||
793 mangle_mask_match(conn
,filename
,mask
)) {
795 if (!mangle_is_8_3(filename
, False
, SNUM(conn
)))
796 mangle_map(filename
,True
,False
,SNUM(conn
));
798 pstrcpy(fname
,filename
);
800 pstrcpy(path
,conn
->dirpath
);
803 pstrcpy(pathreal
,path
);
805 pstrcat(pathreal
,dname
);
806 if (!VALID_STAT(sbuf
) && (SMB_VFS_STAT(conn
, pathreal
, &sbuf
)) != 0) {
807 DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path
, strerror(errno
) ));
811 *mode
= dos_mode(conn
,pathreal
,&sbuf
);
813 if (!dir_check_ftype(conn
,*mode
,dirtype
)) {
814 DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",filename
,(unsigned int)*mode
,(unsigned int)dirtype
));
818 *size
= sbuf
.st_size
;
819 *date
= sbuf
.st_mtime
;
821 DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask
, pathreal
,fname
));
825 DirCacheAdd(conn
->dirptr
->dir_hnd
, dname
, curoff
);
832 /*******************************************************************
833 Check to see if a user can read a file. This is only approximate,
834 it is used as part of the "hide unreadable" option. Don't
835 use it for anything security sensitive.
836 ********************************************************************/
838 static BOOL
user_can_read_file(connection_struct
*conn
, char *name
, SMB_STRUCT_STAT
*pst
)
840 SEC_DESC
*psd
= NULL
;
844 uint32 access_granted
;
847 * If user is a member of the Admin group
848 * we never hide files from them.
851 if (conn
->admin_user
) {
855 /* If we can't stat it does not show it */
856 if (!VALID_STAT(*pst
) && (SMB_VFS_STAT(conn
, name
, pst
) != 0)) {
860 /* Pseudo-open the file (note - no fd's created). */
862 if(S_ISDIR(pst
->st_mode
)) {
863 fsp
= open_directory(conn
, name
, pst
,
865 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
867 0, /* no create options. */
870 fsp
= open_file_stat(conn
, name
, pst
);
877 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
878 sd_size
= SMB_VFS_FGET_NT_ACL(fsp
, fsp
->fh
->fd
,
879 (OWNER_SECURITY_INFORMATION
|GROUP_SECURITY_INFORMATION
|DACL_SECURITY_INFORMATION
), &psd
);
880 close_file(fsp
, NORMAL_CLOSE
);
882 /* No access if SD get failed. */
887 return se_access_check(psd
, current_user
.nt_user_token
, FILE_READ_DATA
,
888 &access_granted
, &status
);
891 /*******************************************************************
892 Check to see if a user can write a file (and only files, we do not
893 check dirs on this one). This is only approximate,
894 it is used as part of the "hide unwriteable" option. Don't
895 use it for anything security sensitive.
896 ********************************************************************/
898 static BOOL
user_can_write_file(connection_struct
*conn
, char *name
, SMB_STRUCT_STAT
*pst
)
900 SEC_DESC
*psd
= NULL
;
905 uint32 access_granted
;
908 * If user is a member of the Admin group
909 * we never hide files from them.
912 if (conn
->admin_user
) {
916 /* If we can't stat it does not show it */
917 if (!VALID_STAT(*pst
) && (SMB_VFS_STAT(conn
, name
, pst
) != 0)) {
921 /* Pseudo-open the file */
923 if(S_ISDIR(pst
->st_mode
)) {
926 fsp
= open_file_ntcreate(conn
, name
, pst
,
927 FILE_WRITE_ATTRIBUTES
,
928 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
931 FILE_ATTRIBUTE_NORMAL
,
940 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
941 sd_size
= SMB_VFS_FGET_NT_ACL(fsp
, fsp
->fh
->fd
,
942 (OWNER_SECURITY_INFORMATION
|GROUP_SECURITY_INFORMATION
|DACL_SECURITY_INFORMATION
), &psd
);
943 close_file(fsp
, NORMAL_CLOSE
);
945 /* No access if SD get failed. */
949 return se_access_check(psd
, current_user
.nt_user_token
, FILE_WRITE_DATA
,
950 &access_granted
, &status
);
953 /*******************************************************************
954 Is a file a "special" type ?
955 ********************************************************************/
957 static BOOL
file_is_special(connection_struct
*conn
, char *name
, SMB_STRUCT_STAT
*pst
)
960 * If user is a member of the Admin group
961 * we never hide files from them.
964 if (conn
->admin_user
)
967 /* If we can't stat it does not show it */
968 if (!VALID_STAT(*pst
) && (SMB_VFS_STAT(conn
, name
, pst
) != 0))
971 if (S_ISREG(pst
->st_mode
) || S_ISDIR(pst
->st_mode
) || S_ISLNK(pst
->st_mode
))
977 /*******************************************************************
978 Should the file be seen by the client ?
979 ********************************************************************/
981 BOOL
is_visible_file(connection_struct
*conn
, const char *dir_path
, const char *name
, SMB_STRUCT_STAT
*pst
, BOOL use_veto
)
983 BOOL hide_unreadable
= lp_hideunreadable(SNUM(conn
));
984 BOOL hide_unwriteable
= lp_hideunwriteable_files(SNUM(conn
));
985 BOOL hide_special
= lp_hide_special_files(SNUM(conn
));
987 SET_STAT_INVALID(*pst
);
989 if ((strcmp(".",name
) == 0) || (strcmp("..",name
) == 0)) {
990 return True
; /* . and .. are always visible. */
993 /* If it's a vetoed file, pretend it doesn't even exist */
994 if (use_veto
&& IS_VETO_PATH(conn
, name
)) {
998 if (hide_unreadable
|| hide_unwriteable
|| hide_special
) {
1001 if (asprintf(&entry
, "%s/%s", dir_path
, name
) == -1) {
1004 /* Honour _hide unreadable_ option */
1005 if (hide_unreadable
&& !user_can_read_file(conn
, entry
, pst
)) {
1009 /* Honour _hide unwriteable_ option */
1010 if (hide_unwriteable
&& !user_can_write_file(conn
, entry
, pst
)) {
1014 /* Honour _hide_special_ option */
1015 if (hide_special
&& file_is_special(conn
, entry
, pst
)) {
1024 /*******************************************************************
1026 ********************************************************************/
1028 struct smb_Dir
*OpenDir(connection_struct
*conn
, const char *name
, const char *mask
, uint32 attr
)
1030 struct smb_Dir
*dirp
= SMB_MALLOC_P(struct smb_Dir
);
1038 dirp
->dir_path
= SMB_STRDUP(name
);
1039 if (!dirp
->dir_path
) {
1042 dirp
->dir
= SMB_VFS_OPENDIR(conn
, dirp
->dir_path
, mask
, attr
);
1044 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp
->dir_path
, strerror(errno
) ));
1048 dirp
->name_cache
= SMB_CALLOC_ARRAY(struct name_cache_entry
, NAME_CACHE_SIZE
);
1049 if (!dirp
->name_cache
) {
1060 SMB_VFS_CLOSEDIR(conn
,dirp
->dir
);
1062 SAFE_FREE(dirp
->dir_path
);
1063 SAFE_FREE(dirp
->name_cache
);
1070 /*******************************************************************
1072 ********************************************************************/
1074 int CloseDir(struct smb_Dir
*dirp
)
1079 ret
= SMB_VFS_CLOSEDIR(dirp
->conn
,dirp
->dir
);
1081 SAFE_FREE(dirp
->dir_path
);
1082 if (dirp
->name_cache
) {
1083 for (i
= 0; i
< NAME_CACHE_SIZE
; i
++) {
1084 SAFE_FREE(dirp
->name_cache
[i
].name
);
1087 SAFE_FREE(dirp
->name_cache
);
1093 /*******************************************************************
1094 Read from a directory. Also return current offset.
1095 Don't check for veto or invisible files.
1096 ********************************************************************/
1098 const char *ReadDirName(struct smb_Dir
*dirp
, long *poffset
)
1101 connection_struct
*conn
= dirp
->conn
;
1103 /* Cheat to allow . and .. to be the first entries returned. */
1104 if (((*poffset
== START_OF_DIRECTORY_OFFSET
) || (*poffset
== DOT_DOT_DIRECTORY_OFFSET
)) && (dirp
->file_number
< 2)) {
1105 if (dirp
->file_number
== 0) {
1107 *poffset
= dirp
->offset
= START_OF_DIRECTORY_OFFSET
;
1109 *poffset
= dirp
->offset
= DOT_DOT_DIRECTORY_OFFSET
;
1112 dirp
->file_number
++;
1114 } else if (*poffset
== END_OF_DIRECTORY_OFFSET
) {
1115 *poffset
= dirp
->offset
= END_OF_DIRECTORY_OFFSET
;
1118 /* A real offset, seek to it. */
1119 SeekDir(dirp
, *poffset
);
1122 while ((n
= vfs_readdirname(conn
, dirp
->dir
))) {
1123 /* Ignore . and .. - we've already returned them. */
1125 if ((n
[1] == '\0') || (n
[1] == '.' && n
[2] == '\0')) {
1129 *poffset
= dirp
->offset
= SMB_VFS_TELLDIR(conn
, dirp
->dir
);
1130 dirp
->file_number
++;
1133 *poffset
= dirp
->offset
= END_OF_DIRECTORY_OFFSET
;
1137 /*******************************************************************
1138 Rewind to the start.
1139 ********************************************************************/
1141 void RewindDir(struct smb_Dir
*dirp
, long *poffset
)
1143 SMB_VFS_REWINDDIR(dirp
->conn
, dirp
->dir
);
1144 dirp
->file_number
= 0;
1145 dirp
->offset
= START_OF_DIRECTORY_OFFSET
;
1146 *poffset
= START_OF_DIRECTORY_OFFSET
;
1149 /*******************************************************************
1151 ********************************************************************/
1153 void SeekDir(struct smb_Dir
*dirp
, long offset
)
1155 if (offset
!= dirp
->offset
) {
1156 if (offset
== START_OF_DIRECTORY_OFFSET
) {
1157 RewindDir(dirp
, &offset
);
1159 * Ok we should really set the file number here
1160 * to 1 to enable ".." to be returned next. Trouble
1161 * is I'm worried about callers using SeekDir(dirp,0)
1162 * as equivalent to RewindDir(). So leave this alone
1165 } else if (offset
== DOT_DOT_DIRECTORY_OFFSET
) {
1166 RewindDir(dirp
, &offset
);
1168 * Set the file number to 2 - we want to get the first
1169 * real file entry (the one we return after "..")
1170 * on the next ReadDir.
1172 dirp
->file_number
= 2;
1173 } else if (offset
== END_OF_DIRECTORY_OFFSET
) {
1174 ; /* Don't seek in this case. */
1176 SMB_VFS_SEEKDIR(dirp
->conn
, dirp
->dir
, offset
);
1178 dirp
->offset
= offset
;
1182 /*******************************************************************
1183 Tell a dir position.
1184 ********************************************************************/
1186 long TellDir(struct smb_Dir
*dirp
)
1188 return(dirp
->offset
);
1191 /*******************************************************************
1192 Add an entry into the dcache.
1193 ********************************************************************/
1195 void DirCacheAdd(struct smb_Dir
*dirp
, const char *name
, long offset
)
1197 struct name_cache_entry
*e
;
1199 dirp
->name_cache_index
= (dirp
->name_cache_index
+1) % NAME_CACHE_SIZE
;
1200 e
= &dirp
->name_cache
[dirp
->name_cache_index
];
1202 e
->name
= SMB_STRDUP(name
);
1206 /*******************************************************************
1207 Find an entry by name. Leave us at the offset after it.
1208 Don't check for veto or invisible files.
1209 ********************************************************************/
1211 BOOL
SearchDir(struct smb_Dir
*dirp
, const char *name
, long *poffset
)
1215 connection_struct
*conn
= dirp
->conn
;
1217 /* Search back in the name cache. */
1218 for (i
= dirp
->name_cache_index
; i
>= 0; i
--) {
1219 struct name_cache_entry
*e
= &dirp
->name_cache
[i
];
1220 if (e
->name
&& (conn
->case_sensitive
? (strcmp(e
->name
, name
) == 0) : strequal(e
->name
, name
))) {
1221 *poffset
= e
->offset
;
1222 SeekDir(dirp
, e
->offset
);
1226 for (i
= NAME_CACHE_SIZE
-1; i
> dirp
->name_cache_index
; i
--) {
1227 struct name_cache_entry
*e
= &dirp
->name_cache
[i
];
1228 if (e
->name
&& (conn
->case_sensitive
? (strcmp(e
->name
, name
) == 0) : strequal(e
->name
, name
))) {
1229 *poffset
= e
->offset
;
1230 SeekDir(dirp
, e
->offset
);
1235 /* Not found in the name cache. Rewind directory and start from scratch. */
1236 SMB_VFS_REWINDDIR(conn
, dirp
->dir
);
1237 dirp
->file_number
= 0;
1238 *poffset
= START_OF_DIRECTORY_OFFSET
;
1239 while ((entry
= ReadDirName(dirp
, poffset
))) {
1240 if (conn
->case_sensitive
? (strcmp(entry
, name
) == 0) : strequal(entry
, name
)) {