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. */
64 BOOL did_stat; /* Optimisation for non-wcard searches. */
67 static struct bitmap *dptr_bmap;
68 static struct dptr_struct *dirptrs;
69 static int dirhandles_open = 0;
71 #define INVALID_DPTR_KEY (-3)
73 /****************************************************************************
75 ****************************************************************************/
77 void make_dir_struct(char *buf, const char *mask, const char *fname,SMB_OFF_T size,uint32 mode,time_t date, BOOL uc)
84 if ((mode & aDIR) != 0)
88 if ((p = strchr_m(mask2,'.')) != NULL) {
90 push_ascii(buf+1,mask2,8, 0);
91 push_ascii(buf+9,p+1,3, 0);
94 push_ascii(buf+1,mask2,11, 0);
96 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
98 srv_put_dos_date(buf,22,date);
99 SSVAL(buf,26,size & 0xFFFF);
100 SSVAL(buf,28,(size >> 16)&0xFFFF);
101 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
102 Strange, but verified on W2K3. Needed for OS/2. JRA. */
103 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
104 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
107 /****************************************************************************
108 Initialise the dir bitmap.
109 ****************************************************************************/
111 void init_dptrs(void)
113 static BOOL dptrs_init=False;
118 dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES);
121 exit_server("out of memory in init_dptrs");
126 /****************************************************************************
127 Idle a dptr - the directory is closed but the control info is kept.
128 ****************************************************************************/
130 static void dptr_idle(struct dptr_struct *dptr)
133 DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
134 CloseDir(dptr->dir_hnd);
135 dptr->dir_hnd = NULL;
139 /****************************************************************************
140 Idle the oldest dptr.
141 ****************************************************************************/
143 static void dptr_idleoldest(void)
145 struct dptr_struct *dptr;
148 * Go to the end of the list.
150 for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
154 DEBUG(0,("No dptrs available to idle ?\n"));
159 * Idle the oldest pointer.
162 for(; dptr; dptr = dptr->prev) {
170 /****************************************************************************
171 Get the struct dptr_struct for a dir index.
172 ****************************************************************************/
174 static struct dptr_struct *dptr_get(int key, BOOL forclose)
176 struct dptr_struct *dptr;
178 for(dptr = dirptrs; dptr; dptr = dptr->next) {
179 if(dptr->dnum == key) {
180 if (!forclose && !dptr->dir_hnd) {
181 if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
183 DEBUG(4,("dptr_get: Reopening dptr key %d\n",key));
184 if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path, dptr->wcard, dptr->attr))) {
185 DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path,
190 DLIST_PROMOTE(dirptrs,dptr);
197 /****************************************************************************
198 Get the dir path for a dir index.
199 ****************************************************************************/
201 char *dptr_path(int key)
203 struct dptr_struct *dptr = dptr_get(key, False);
209 /****************************************************************************
210 Get the dir wcard for a dir index.
211 ****************************************************************************/
213 char *dptr_wcard(int key)
215 struct dptr_struct *dptr = dptr_get(key, False);
221 /****************************************************************************
222 Get the dir attrib for a dir index.
223 ****************************************************************************/
225 uint16 dptr_attr(int key)
227 struct dptr_struct *dptr = dptr_get(key, False);
233 /****************************************************************************
234 Close a dptr (internal func).
235 ****************************************************************************/
237 static void dptr_close_internal(struct dptr_struct *dptr)
239 DEBUG(4,("closing dptr key %d\n",dptr->dnum));
241 DLIST_REMOVE(dirptrs, dptr);
244 * Free the dnum in the bitmap. Remember the dnum value is always
245 * biased by one with respect to the bitmap.
248 if(bitmap_query( dptr_bmap, dptr->dnum - 1) != True) {
249 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
253 bitmap_clear(dptr_bmap, dptr->dnum - 1);
256 CloseDir(dptr->dir_hnd);
259 /* Lanman 2 specific code */
260 SAFE_FREE(dptr->wcard);
261 string_set(&dptr->path,"");
265 /****************************************************************************
266 Close a dptr given a key.
267 ****************************************************************************/
269 void dptr_close(int *key)
271 struct dptr_struct *dptr;
273 if(*key == INVALID_DPTR_KEY)
276 /* OS/2 seems to use -1 to indicate "close all directories" */
278 struct dptr_struct *next;
279 for(dptr = dirptrs; dptr; dptr = next) {
281 dptr_close_internal(dptr);
283 *key = INVALID_DPTR_KEY;
287 dptr = dptr_get(*key, True);
290 DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
294 dptr_close_internal(dptr);
296 *key = INVALID_DPTR_KEY;
299 /****************************************************************************
300 Close all dptrs for a cnum.
301 ****************************************************************************/
303 void dptr_closecnum(connection_struct *conn)
305 struct dptr_struct *dptr, *next;
306 for(dptr = dirptrs; dptr; dptr = next) {
308 if (dptr->conn == conn)
309 dptr_close_internal(dptr);
313 /****************************************************************************
314 Idle all dptrs for a cnum.
315 ****************************************************************************/
317 void dptr_idlecnum(connection_struct *conn)
319 struct dptr_struct *dptr;
320 for(dptr = dirptrs; dptr; dptr = dptr->next) {
321 if (dptr->conn == conn && dptr->dir_hnd)
326 /****************************************************************************
327 Close a dptr that matches a given path, only if it matches the spid also.
328 ****************************************************************************/
330 void dptr_closepath(char *path,uint16 spid)
332 struct dptr_struct *dptr, *next;
333 for(dptr = dirptrs; dptr; dptr = next) {
335 if (spid == dptr->spid && strequal(dptr->path,path))
336 dptr_close_internal(dptr);
340 /****************************************************************************
341 Try and close the oldest handle not marked for
342 expect close in the hope that the client has
343 finished with that one.
344 ****************************************************************************/
346 static void dptr_close_oldest(BOOL old)
348 struct dptr_struct *dptr;
351 * Go to the end of the list.
353 for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
357 DEBUG(0,("No old dptrs available to close oldest ?\n"));
362 * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
363 * does not have expect_close set. If 'old' is false, close
364 * one of the new dnum handles.
367 for(; dptr; dptr = dptr->prev) {
368 if ((old && (dptr->dnum < 256) && !dptr->expect_close) ||
369 (!old && (dptr->dnum > 255))) {
370 dptr_close_internal(dptr);
376 /****************************************************************************
377 Create a new dir ptr. If the flag old_handle is true then we must allocate
378 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
379 one byte long. If old_handle is false we allocate from the range
380 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
381 a directory handle is never zero.
382 wcard must not be zero.
383 ****************************************************************************/
385 NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid,
386 const char *wcard, BOOL wcard_has_wild, uint32 attr, int *dptr_hnd_ret)
388 struct dptr_struct *dptr = NULL;
389 struct smb_Dir *dir_hnd;
393 DEBUG(5,("dptr_create dir=%s\n", path));
398 return NT_STATUS_INVALID_PARAMETER;
401 status = check_name(conn,path);
402 if (!NT_STATUS_IS_OK(status)) {
406 /* use a const pointer from here on */
411 dir_hnd = OpenDir(conn, dir2, wcard, attr);
413 return map_nt_error_from_unix(errno);
416 string_set(&conn->dirpath,dir2);
418 if (dirhandles_open >= MAX_OPEN_DIRECTORIES) {
422 dptr = SMB_MALLOC_P(struct dptr_struct);
424 DEBUG(0,("malloc fail in dptr_create.\n"));
426 return NT_STATUS_NO_MEMORY;
434 * This is an old-style SMBsearch request. Ensure the
435 * value we return will fit in the range 1-255.
438 dptr->dnum = bitmap_find(dptr_bmap, 0);
440 if(dptr->dnum == -1 || dptr->dnum > 254) {
443 * Try and close the oldest handle not marked for
444 * expect close in the hope that the client has
445 * finished with that one.
448 dptr_close_oldest(True);
450 /* Now try again... */
451 dptr->dnum = bitmap_find(dptr_bmap, 0);
452 if(dptr->dnum == -1 || dptr->dnum > 254) {
453 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
456 return NT_STATUS_TOO_MANY_OPENED_FILES;
462 * This is a new-style trans2 request. Allocate from
463 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
466 dptr->dnum = bitmap_find(dptr_bmap, 255);
468 if(dptr->dnum == -1 || dptr->dnum < 255) {
471 * Try and close the oldest handle close in the hope that
472 * the client has finished with that one. This will only
473 * happen in the case of the Win98 client bug where it leaks
477 dptr_close_oldest(False);
479 /* Now try again... */
480 dptr->dnum = bitmap_find(dptr_bmap, 255);
482 if(dptr->dnum == -1 || dptr->dnum < 255) {
483 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
486 return NT_STATUS_TOO_MANY_OPENED_FILES;
491 bitmap_set(dptr_bmap, dptr->dnum);
493 dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
495 string_set(&dptr->path,dir2);
497 dptr->dir_hnd = dir_hnd;
499 dptr->expect_close = expect_close;
500 dptr->wcard = SMB_STRDUP(wcard);
502 bitmap_clear(dptr_bmap, dptr->dnum - 1);
505 return NT_STATUS_NO_MEMORY;
507 if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) {
508 dptr->has_wild = True;
510 dptr->has_wild = wcard_has_wild;
515 DLIST_ADD(dirptrs, dptr);
517 DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
518 dptr->dnum,path,expect_close));
522 *dptr_hnd_ret = dptr->dnum;
527 /****************************************************************************
528 Wrapper functions to access the lower level directory handles.
529 ****************************************************************************/
531 int dptr_CloseDir(struct dptr_struct *dptr)
533 return CloseDir(dptr->dir_hnd);
536 void dptr_SeekDir(struct dptr_struct *dptr, long offset)
538 SeekDir(dptr->dir_hnd, offset);
541 long dptr_TellDir(struct dptr_struct *dptr)
543 return TellDir(dptr->dir_hnd);
546 BOOL dptr_has_wild(struct dptr_struct *dptr)
548 return dptr->has_wild;
551 /****************************************************************************
552 Return the next visible file name, skipping veto'd and invisible files.
553 ****************************************************************************/
555 static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
557 /* Normal search for the next file. */
559 while ((name = ReadDirName(dptr->dir_hnd, poffset)) != NULL) {
560 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
567 /****************************************************************************
568 Return the next visible file name, skipping veto'd and invisible files.
569 ****************************************************************************/
571 const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
573 SET_STAT_INVALID(*pst);
575 if (dptr->has_wild) {
576 return dptr_normal_ReadDirName(dptr, poffset, pst);
579 /* If poffset is -1 then we know we returned this name before and we have
580 no wildcards. We're at the end of the directory. */
581 if (*poffset == END_OF_DIRECTORY_OFFSET) {
585 if (!dptr->did_stat) {
588 /* We know the stored wcard contains no wildcard characters. See if we can match
589 with a stat call. If we can't, then set did_stat to true to
590 ensure we only do this once and keep searching. */
592 dptr->did_stat = True;
594 /* First check if it should be visible. */
595 if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard, pst, True)) {
596 /* This only returns False if the file was found, but
597 is explicitly not visible. Set us to end of directory,
598 but return NULL as we know we can't ever find it. */
599 dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
603 if (VALID_STAT(*pst)) {
604 /* We need to set the underlying dir_hnd 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;
610 pstrcpy(pathreal,dptr->path);
611 pstrcat(pathreal,"/");
612 pstrcat(pathreal,dptr->wcard);
614 if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) {
615 /* We need to set the underlying dir_hnd 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 /* If we get any other error than ENOENT or ENOTDIR
621 then the file exists we just can't stat it. */
622 if (errno != ENOENT && errno != ENOTDIR) {
623 /* We need to set the underlying dir_hdn offset to -1 also as
624 this function is usually called with the output from TellDir. */
625 dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
630 /* In case sensitive mode we don't search - we know if it doesn't exist
631 with a stat we will fail. */
633 if (dptr->conn->case_sensitive) {
634 /* We need to set the underlying dir_hnd offset to -1 also as
635 this function is usually called with the output from TellDir. */
636 dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
640 return dptr_normal_ReadDirName(dptr, poffset, pst);
643 /****************************************************************************
644 Search for a file by name, skipping veto'ed and not visible files.
645 ****************************************************************************/
647 BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
649 SET_STAT_INVALID(*pst);
651 if (!dptr->has_wild && (dptr->dir_hnd->offset == END_OF_DIRECTORY_OFFSET)) {
652 /* This is a singleton directory and we're already at the end. */
653 *poffset = END_OF_DIRECTORY_OFFSET;
657 return SearchDir(dptr->dir_hnd, name, poffset);
660 /****************************************************************************
661 Add the name we're returning into the underlying cache.
662 ****************************************************************************/
664 void dptr_DirCacheAdd(struct dptr_struct *dptr, const char *name, long offset)
666 DirCacheAdd(dptr->dir_hnd, name, offset);
669 /****************************************************************************
670 Fill the 5 byte server reserved dptr field.
671 ****************************************************************************/
673 BOOL dptr_fill(char *buf1,unsigned int key)
675 unsigned char *buf = (unsigned char *)buf1;
676 struct dptr_struct *dptr = dptr_get(key, False);
679 DEBUG(1,("filling null dirptr %d\n",key));
682 offset = (uint32)TellDir(dptr->dir_hnd);
683 DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
684 (long)dptr->dir_hnd,(int)offset));
690 /****************************************************************************
691 Fetch the dir ptr and seek it given the 5 byte server field.
692 ****************************************************************************/
694 struct dptr_struct *dptr_fetch(char *buf,int *num)
696 unsigned int key = *(unsigned char *)buf;
697 struct dptr_struct *dptr = dptr_get(key, False);
702 DEBUG(3,("fetched null dirptr %d\n",key));
706 offset = IVAL(buf,1);
707 if (offset == (uint32)-1) {
708 seekoff = END_OF_DIRECTORY_OFFSET;
710 seekoff = (long)offset;
712 SeekDir(dptr->dir_hnd,seekoff);
713 DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
714 key,dptr_path(key),(int)seekoff));
718 /****************************************************************************
720 ****************************************************************************/
722 struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
724 struct dptr_struct *dptr = dptr_get(dptr_num, False);
727 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
730 DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
734 /****************************************************************************
735 Check that a file matches a particular file type.
736 ****************************************************************************/
738 BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype)
742 /* Check the "may have" search bits. */
743 if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
746 /* Check the "must have" bits, which are the may have bits shifted eight */
747 /* If must have bit is set, the file/dir can not be returned in search unless the matching
748 file attribute is set */
749 mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */
751 if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask) /* check if matching attribute present */
760 static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask)
762 mangle_map(filename,True,False,conn->params);
763 return mask_match_search(filename,mask,False);
766 /****************************************************************************
767 Get an 8.3 directory entry.
768 ****************************************************************************/
770 BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fname,
771 SMB_OFF_T *size,uint32 *mode,time_t *date,BOOL check_descend)
775 SMB_STRUCT_STAT sbuf;
781 *path = *pathreal = *filename = 0;
783 needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
789 long curoff = dptr_TellDir(conn->dirptr);
790 dname = dptr_ReadDirName(conn->dirptr, &curoff, &sbuf);
792 DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
793 (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
798 pstrcpy(filename,dname);
800 /* notice the special *.* handling. This appears to be the only difference
801 between the wildcard handling in this routine and in the trans2 routines.
802 see masktest for a demo
804 if ((strcmp(mask,"*.*") == 0) ||
805 mask_match_search(filename,mask,False) ||
806 mangle_mask_match(conn,filename,mask)) {
808 if (!mangle_is_8_3(filename, False, conn->params))
809 mangle_map(filename,True,False,
812 pstrcpy(fname,filename);
814 pstrcpy(path,conn->dirpath);
817 pstrcpy(pathreal,path);
819 pstrcat(pathreal,dname);
820 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
821 DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) ));
825 *mode = dos_mode(conn,pathreal,&sbuf);
827 if (!dir_check_ftype(conn,*mode,dirtype)) {
828 DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",filename,(unsigned int)*mode,(unsigned int)dirtype));
832 *size = sbuf.st_size;
833 *date = sbuf.st_mtime;
835 DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
839 DirCacheAdd(conn->dirptr->dir_hnd, dname, curoff);
846 /*******************************************************************
847 Check to see if a user can read a file. This is only approximate,
848 it is used as part of the "hide unreadable" option. Don't
849 use it for anything security sensitive.
850 ********************************************************************/
852 static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
854 SEC_DESC *psd = NULL;
858 uint32 access_granted;
861 * If user is a member of the Admin group
862 * we never hide files from them.
865 if (conn->admin_user) {
869 /* If we can't stat it does not show it */
870 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) {
871 DEBUG(10,("user_can_read_file: SMB_VFS_STAT failed for file %s with error %s\n",
872 name, strerror(errno) ));
876 /* Pseudo-open the file (note - no fd's created). */
878 if(S_ISDIR(pst->st_mode)) {
879 status = open_directory(conn, name, pst,
881 FILE_SHARE_READ|FILE_SHARE_WRITE,
883 0, /* no create options. */
886 status = open_file_stat(conn, name, pst, &fsp);
889 if (!NT_STATUS_IS_OK(status)) {
893 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
894 sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd,
895 (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
896 close_file(fsp, NORMAL_CLOSE);
898 /* No access if SD get failed. */
903 return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA,
904 &access_granted, &status);
907 /*******************************************************************
908 Check to see if a user can write a file (and only files, we do not
909 check dirs on this one). This is only approximate,
910 it is used as part of the "hide unwriteable" option. Don't
911 use it for anything security sensitive.
912 ********************************************************************/
914 static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
916 SEC_DESC *psd = NULL;
921 uint32 access_granted;
924 * If user is a member of the Admin group
925 * we never hide files from them.
928 if (conn->admin_user) {
932 /* If we can't stat it does not show it */
933 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) {
937 /* Pseudo-open the file */
939 if(S_ISDIR(pst->st_mode)) {
942 status = open_file_ntcreate(conn, name, pst,
943 FILE_WRITE_ATTRIBUTES,
944 FILE_SHARE_READ|FILE_SHARE_WRITE,
947 FILE_ATTRIBUTE_NORMAL,
952 if (!NT_STATUS_IS_OK(status)) {
956 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
957 sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd,
958 (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
959 close_file(fsp, NORMAL_CLOSE);
961 /* No access if SD get failed. */
965 return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA,
966 &access_granted, &status);
969 /*******************************************************************
970 Is a file a "special" type ?
971 ********************************************************************/
973 static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
976 * If user is a member of the Admin group
977 * we never hide files from them.
980 if (conn->admin_user)
983 /* If we can't stat it does not show it */
984 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
987 if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
993 /*******************************************************************
994 Should the file be seen by the client ?
995 ********************************************************************/
997 BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, BOOL use_veto)
999 BOOL hide_unreadable = lp_hideunreadable(SNUM(conn));
1000 BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
1001 BOOL hide_special = lp_hide_special_files(SNUM(conn));
1003 SET_STAT_INVALID(*pst);
1005 if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
1006 return True; /* . and .. are always visible. */
1009 /* If it's a vetoed file, pretend it doesn't even exist */
1010 if (use_veto && IS_VETO_PATH(conn, name)) {
1011 DEBUG(10,("is_visible_file: file %s is vetoed.\n", name ));
1015 if (hide_unreadable || hide_unwriteable || hide_special) {
1018 if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
1022 /* If it's a dfs symlink, ignore _hide xxxx_ options */
1023 if (lp_host_msdfs() &&
1024 lp_msdfs_root(SNUM(conn)) &&
1025 /* We get away with NULL talloc ctx here as
1026 we're not interested in the link contents
1027 so we have nothing to free. */
1028 is_msdfs_link(NULL, conn, entry, NULL, NULL, NULL)) {
1033 /* Honour _hide unreadable_ option */
1034 if (hide_unreadable && !user_can_read_file(conn, entry, pst)) {
1035 DEBUG(10,("is_visible_file: file %s is unreadable.\n", entry ));
1039 /* Honour _hide unwriteable_ option */
1040 if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
1041 DEBUG(10,("is_visible_file: file %s is unwritable.\n", entry ));
1045 /* Honour _hide_special_ option */
1046 if (hide_special && file_is_special(conn, entry, pst)) {
1047 DEBUG(10,("is_visible_file: file %s is special.\n", entry ));
1056 /*******************************************************************
1058 ********************************************************************/
1060 struct smb_Dir *OpenDir(connection_struct *conn, const char *name, const char *mask, uint32 attr)
1062 struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir);
1070 dirp->dir_path = SMB_STRDUP(name);
1071 if (!dirp->dir_path) {
1074 dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
1076 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) ));
1080 dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, NAME_CACHE_SIZE);
1081 if (!dirp->name_cache) {
1092 SMB_VFS_CLOSEDIR(conn,dirp->dir);
1094 SAFE_FREE(dirp->dir_path);
1095 SAFE_FREE(dirp->name_cache);
1102 /*******************************************************************
1104 ********************************************************************/
1106 int CloseDir(struct smb_Dir *dirp)
1111 ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1113 SAFE_FREE(dirp->dir_path);
1114 if (dirp->name_cache) {
1115 for (i = 0; i < NAME_CACHE_SIZE; i++) {
1116 SAFE_FREE(dirp->name_cache[i].name);
1119 SAFE_FREE(dirp->name_cache);
1125 /*******************************************************************
1126 Read from a directory. Also return current offset.
1127 Don't check for veto or invisible files.
1128 ********************************************************************/
1130 const char *ReadDirName(struct smb_Dir *dirp, long *poffset)
1133 connection_struct *conn = dirp->conn;
1135 /* Cheat to allow . and .. to be the first entries returned. */
1136 if (((*poffset == START_OF_DIRECTORY_OFFSET) || (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2)) {
1137 if (dirp->file_number == 0) {
1139 *poffset = dirp->offset = START_OF_DIRECTORY_OFFSET;
1141 *poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET;
1144 dirp->file_number++;
1146 } else if (*poffset == END_OF_DIRECTORY_OFFSET) {
1147 *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1150 /* A real offset, seek to it. */
1151 SeekDir(dirp, *poffset);
1154 while ((n = vfs_readdirname(conn, dirp->dir))) {
1155 /* Ignore . and .. - we've already returned them. */
1157 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
1161 *poffset = dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1162 dirp->file_number++;
1165 *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1169 /*******************************************************************
1170 Rewind to the start.
1171 ********************************************************************/
1173 void RewindDir(struct smb_Dir *dirp, long *poffset)
1175 SMB_VFS_REWINDDIR(dirp->conn, dirp->dir);
1176 dirp->file_number = 0;
1177 dirp->offset = START_OF_DIRECTORY_OFFSET;
1178 *poffset = START_OF_DIRECTORY_OFFSET;
1181 /*******************************************************************
1183 ********************************************************************/
1185 void SeekDir(struct smb_Dir *dirp, long offset)
1187 if (offset != dirp->offset) {
1188 if (offset == START_OF_DIRECTORY_OFFSET) {
1189 RewindDir(dirp, &offset);
1191 * Ok we should really set the file number here
1192 * to 1 to enable ".." to be returned next. Trouble
1193 * is I'm worried about callers using SeekDir(dirp,0)
1194 * as equivalent to RewindDir(). So leave this alone
1197 } else if (offset == DOT_DOT_DIRECTORY_OFFSET) {
1198 RewindDir(dirp, &offset);
1200 * Set the file number to 2 - we want to get the first
1201 * real file entry (the one we return after "..")
1202 * on the next ReadDir.
1204 dirp->file_number = 2;
1205 } else if (offset == END_OF_DIRECTORY_OFFSET) {
1206 ; /* Don't seek in this case. */
1208 SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1210 dirp->offset = offset;
1214 /*******************************************************************
1215 Tell a dir position.
1216 ********************************************************************/
1218 long TellDir(struct smb_Dir *dirp)
1220 return(dirp->offset);
1223 /*******************************************************************
1224 Add an entry into the dcache.
1225 ********************************************************************/
1227 void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
1229 struct name_cache_entry *e;
1231 dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE;
1232 e = &dirp->name_cache[dirp->name_cache_index];
1234 e->name = SMB_STRDUP(name);
1238 /*******************************************************************
1239 Find an entry by name. Leave us at the offset after it.
1240 Don't check for veto or invisible files.
1241 ********************************************************************/
1243 BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1247 connection_struct *conn = dirp->conn;
1249 /* Search back in the name cache. */
1250 for (i = dirp->name_cache_index; i >= 0; i--) {
1251 struct name_cache_entry *e = &dirp->name_cache[i];
1252 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1253 *poffset = e->offset;
1254 SeekDir(dirp, e->offset);
1258 for (i = NAME_CACHE_SIZE-1; i > dirp->name_cache_index; i--) {
1259 struct name_cache_entry *e = &dirp->name_cache[i];
1260 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1261 *poffset = e->offset;
1262 SeekDir(dirp, e->offset);
1267 /* Not found in the name cache. Rewind directory and start from scratch. */
1268 SMB_VFS_REWINDDIR(conn, dirp->dir);
1269 dirp->file_number = 0;
1270 *poffset = START_OF_DIRECTORY_OFFSET;
1271 while ((entry = ReadDirName(dirp, poffset))) {
1272 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {