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 3 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, see <http://www.gnu.org/licenses/>.
23 This module implements directory related functions for Samba.
26 extern struct current_user current_user;
28 /* "Special" directory offsets. */
29 #define END_OF_DIRECTORY_OFFSET ((long)-1)
30 #define START_OF_DIRECTORY_OFFSET ((long)0)
31 #define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000)
33 /* Make directory handle internals available. */
35 struct name_cache_entry {
41 connection_struct *conn;
45 size_t name_cache_size;
46 struct name_cache_entry *name_cache;
47 unsigned int name_cache_index;
48 unsigned int file_number;
52 struct dptr_struct *next, *prev;
55 struct connection_struct *conn;
56 struct smb_Dir *dir_hnd;
61 BOOL has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
62 BOOL did_stat; /* Optimisation for non-wcard searches. */
65 static struct bitmap *dptr_bmap;
66 static struct dptr_struct *dirptrs;
67 static int dirhandles_open = 0;
69 #define INVALID_DPTR_KEY (-3)
71 /****************************************************************************
73 ****************************************************************************/
75 void make_dir_struct(char *buf, const char *mask, const char *fname,SMB_OFF_T size,uint32 mode,time_t date, BOOL uc)
82 if ((mode & aDIR) != 0)
86 if ((p = strchr_m(mask2,'.')) != NULL) {
88 push_ascii(buf+1,mask2,8, 0);
89 push_ascii(buf+9,p+1,3, 0);
92 push_ascii(buf+1,mask2,11, 0);
94 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
96 srv_put_dos_date(buf,22,date);
97 SSVAL(buf,26,size & 0xFFFF);
98 SSVAL(buf,28,(size >> 16)&0xFFFF);
99 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
100 Strange, but verified on W2K3. Needed for OS/2. JRA. */
101 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
102 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
105 /****************************************************************************
106 Initialise the dir bitmap.
107 ****************************************************************************/
109 void init_dptrs(void)
111 static BOOL dptrs_init=False;
116 dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES);
119 exit_server("out of memory in init_dptrs");
124 /****************************************************************************
125 Idle a dptr - the directory is closed but the control info is kept.
126 ****************************************************************************/
128 static void dptr_idle(struct dptr_struct *dptr)
131 DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
132 CloseDir(dptr->dir_hnd);
133 dptr->dir_hnd = NULL;
137 /****************************************************************************
138 Idle the oldest dptr.
139 ****************************************************************************/
141 static void dptr_idleoldest(void)
143 struct dptr_struct *dptr;
146 * Go to the end of the list.
148 for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
152 DEBUG(0,("No dptrs available to idle ?\n"));
157 * Idle the oldest pointer.
160 for(; dptr; dptr = dptr->prev) {
168 /****************************************************************************
169 Get the struct dptr_struct for a dir index.
170 ****************************************************************************/
172 static struct dptr_struct *dptr_get(int key, BOOL forclose)
174 struct dptr_struct *dptr;
176 for(dptr = dirptrs; dptr; dptr = dptr->next) {
177 if(dptr->dnum == key) {
178 if (!forclose && !dptr->dir_hnd) {
179 if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
181 DEBUG(4,("dptr_get: Reopening dptr key %d\n",key));
182 if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path, dptr->wcard, dptr->attr))) {
183 DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path,
188 DLIST_PROMOTE(dirptrs,dptr);
195 /****************************************************************************
196 Get the dir path for a dir index.
197 ****************************************************************************/
199 char *dptr_path(int key)
201 struct dptr_struct *dptr = dptr_get(key, False);
207 /****************************************************************************
208 Get the dir wcard for a dir index.
209 ****************************************************************************/
211 char *dptr_wcard(int key)
213 struct dptr_struct *dptr = dptr_get(key, False);
219 /****************************************************************************
220 Get the dir attrib for a dir index.
221 ****************************************************************************/
223 uint16 dptr_attr(int key)
225 struct dptr_struct *dptr = dptr_get(key, False);
231 /****************************************************************************
232 Close a dptr (internal func).
233 ****************************************************************************/
235 static void dptr_close_internal(struct dptr_struct *dptr)
237 DEBUG(4,("closing dptr key %d\n",dptr->dnum));
239 DLIST_REMOVE(dirptrs, dptr);
242 * Free the dnum in the bitmap. Remember the dnum value is always
243 * biased by one with respect to the bitmap.
246 if(bitmap_query( dptr_bmap, dptr->dnum - 1) != True) {
247 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
251 bitmap_clear(dptr_bmap, dptr->dnum - 1);
254 CloseDir(dptr->dir_hnd);
257 /* Lanman 2 specific code */
258 SAFE_FREE(dptr->wcard);
259 string_set(&dptr->path,"");
263 /****************************************************************************
264 Close a dptr given a key.
265 ****************************************************************************/
267 void dptr_close(int *key)
269 struct dptr_struct *dptr;
271 if(*key == INVALID_DPTR_KEY)
274 /* OS/2 seems to use -1 to indicate "close all directories" */
276 struct dptr_struct *next;
277 for(dptr = dirptrs; dptr; dptr = next) {
279 dptr_close_internal(dptr);
281 *key = INVALID_DPTR_KEY;
285 dptr = dptr_get(*key, True);
288 DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
292 dptr_close_internal(dptr);
294 *key = INVALID_DPTR_KEY;
297 /****************************************************************************
298 Close all dptrs for a cnum.
299 ****************************************************************************/
301 void dptr_closecnum(connection_struct *conn)
303 struct dptr_struct *dptr, *next;
304 for(dptr = dirptrs; dptr; dptr = next) {
306 if (dptr->conn == conn)
307 dptr_close_internal(dptr);
311 /****************************************************************************
312 Idle all dptrs for a cnum.
313 ****************************************************************************/
315 void dptr_idlecnum(connection_struct *conn)
317 struct dptr_struct *dptr;
318 for(dptr = dirptrs; dptr; dptr = dptr->next) {
319 if (dptr->conn == conn && dptr->dir_hnd)
324 /****************************************************************************
325 Close a dptr that matches a given path, only if it matches the spid also.
326 ****************************************************************************/
328 void dptr_closepath(char *path,uint16 spid)
330 struct dptr_struct *dptr, *next;
331 for(dptr = dirptrs; dptr; dptr = next) {
333 if (spid == dptr->spid && strequal(dptr->path,path))
334 dptr_close_internal(dptr);
338 /****************************************************************************
339 Try and close the oldest handle not marked for
340 expect close in the hope that the client has
341 finished with that one.
342 ****************************************************************************/
344 static void dptr_close_oldest(BOOL old)
346 struct dptr_struct *dptr;
349 * Go to the end of the list.
351 for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
355 DEBUG(0,("No old dptrs available to close oldest ?\n"));
360 * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
361 * does not have expect_close set. If 'old' is false, close
362 * one of the new dnum handles.
365 for(; dptr; dptr = dptr->prev) {
366 if ((old && (dptr->dnum < 256) && !dptr->expect_close) ||
367 (!old && (dptr->dnum > 255))) {
368 dptr_close_internal(dptr);
374 /****************************************************************************
375 Create a new dir ptr. If the flag old_handle is true then we must allocate
376 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
377 one byte long. If old_handle is false we allocate from the range
378 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
379 a directory handle is never zero.
380 wcard must not be zero.
381 ****************************************************************************/
383 NTSTATUS dptr_create(connection_struct *conn, const char *path, BOOL old_handle, BOOL expect_close,uint16 spid,
384 const char *wcard, BOOL wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret)
386 struct dptr_struct *dptr = NULL;
387 struct smb_Dir *dir_hnd;
390 DEBUG(5,("dptr_create dir=%s\n", path));
393 return NT_STATUS_INVALID_PARAMETER;
396 status = check_name(conn,path);
397 if (!NT_STATUS_IS_OK(status)) {
401 dir_hnd = OpenDir(conn, path, wcard, attr);
403 return map_nt_error_from_unix(errno);
406 string_set(&conn->dirpath,path);
408 if (dirhandles_open >= MAX_OPEN_DIRECTORIES) {
412 dptr = SMB_MALLOC_P(struct dptr_struct);
414 DEBUG(0,("malloc fail in dptr_create.\n"));
416 return NT_STATUS_NO_MEMORY;
424 * This is an old-style SMBsearch request. Ensure the
425 * value we return will fit in the range 1-255.
428 dptr->dnum = bitmap_find(dptr_bmap, 0);
430 if(dptr->dnum == -1 || dptr->dnum > 254) {
433 * Try and close the oldest handle not marked for
434 * expect close in the hope that the client has
435 * finished with that one.
438 dptr_close_oldest(True);
440 /* Now try again... */
441 dptr->dnum = bitmap_find(dptr_bmap, 0);
442 if(dptr->dnum == -1 || dptr->dnum > 254) {
443 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
446 return NT_STATUS_TOO_MANY_OPENED_FILES;
452 * This is a new-style trans2 request. Allocate from
453 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
456 dptr->dnum = bitmap_find(dptr_bmap, 255);
458 if(dptr->dnum == -1 || dptr->dnum < 255) {
461 * Try and close the oldest handle close in the hope that
462 * the client has finished with that one. This will only
463 * happen in the case of the Win98 client bug where it leaks
467 dptr_close_oldest(False);
469 /* Now try again... */
470 dptr->dnum = bitmap_find(dptr_bmap, 255);
472 if(dptr->dnum == -1 || dptr->dnum < 255) {
473 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
476 return NT_STATUS_TOO_MANY_OPENED_FILES;
481 bitmap_set(dptr_bmap, dptr->dnum);
483 dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
485 string_set(&dptr->path,path);
487 dptr->dir_hnd = dir_hnd;
489 dptr->expect_close = expect_close;
490 dptr->wcard = SMB_STRDUP(wcard);
492 bitmap_clear(dptr_bmap, dptr->dnum - 1);
495 return NT_STATUS_NO_MEMORY;
497 if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) {
498 dptr->has_wild = True;
500 dptr->has_wild = wcard_has_wild;
505 DLIST_ADD(dirptrs, dptr);
507 DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
508 dptr->dnum,path,expect_close));
516 /****************************************************************************
517 Wrapper functions to access the lower level directory handles.
518 ****************************************************************************/
520 int dptr_CloseDir(struct dptr_struct *dptr)
522 DLIST_REMOVE(dirptrs, dptr);
523 return CloseDir(dptr->dir_hnd);
526 void dptr_SeekDir(struct dptr_struct *dptr, long offset)
528 SeekDir(dptr->dir_hnd, offset);
531 long dptr_TellDir(struct dptr_struct *dptr)
533 return TellDir(dptr->dir_hnd);
536 BOOL dptr_has_wild(struct dptr_struct *dptr)
538 return dptr->has_wild;
541 int dptr_dnum(struct dptr_struct *dptr)
546 /****************************************************************************
547 Return the next visible file name, skipping veto'd and invisible files.
548 ****************************************************************************/
550 static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
552 /* Normal search for the next file. */
554 while ((name = ReadDirName(dptr->dir_hnd, poffset)) != NULL) {
555 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
562 /****************************************************************************
563 Return the next visible file name, skipping veto'd and invisible files.
564 ****************************************************************************/
566 const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
568 SET_STAT_INVALID(*pst);
570 if (dptr->has_wild) {
571 return dptr_normal_ReadDirName(dptr, poffset, pst);
574 /* If poffset is -1 then we know we returned this name before and we have
575 no wildcards. We're at the end of the directory. */
576 if (*poffset == END_OF_DIRECTORY_OFFSET) {
580 if (!dptr->did_stat) {
583 /* We know the stored wcard contains no wildcard characters. See if we can match
584 with a stat call. If we can't, then set did_stat to true to
585 ensure we only do this once and keep searching. */
587 dptr->did_stat = True;
589 /* First check if it should be visible. */
590 if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard, pst, True)) {
591 /* This only returns False if the file was found, but
592 is explicitly not visible. Set us to end of directory,
593 but return NULL as we know we can't ever find it. */
594 dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
598 if (VALID_STAT(*pst)) {
599 /* We need to set the underlying dir_hnd offset to -1 also as
600 this function is usually called with the output from TellDir. */
601 dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
605 pstrcpy(pathreal,dptr->path);
606 pstrcat(pathreal,"/");
607 pstrcat(pathreal,dptr->wcard);
609 if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) {
610 /* We need to set the underlying dir_hnd offset to -1 also as
611 this function is usually called with the output from TellDir. */
612 dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
615 /* If we get any other error than ENOENT or ENOTDIR
616 then the file exists we just can't stat it. */
617 if (errno != ENOENT && errno != ENOTDIR) {
618 /* We need to set the underlying dir_hdn offset to -1 also as
619 this function is usually called with the output from TellDir. */
620 dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
625 /* In case sensitive mode we don't search - we know if it doesn't exist
626 with a stat we will fail. */
628 if (dptr->conn->case_sensitive) {
629 /* We need to set the underlying dir_hnd offset to -1 also as
630 this function is usually called with the output from TellDir. */
631 dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
635 return dptr_normal_ReadDirName(dptr, poffset, pst);
638 /****************************************************************************
639 Search for a file by name, skipping veto'ed and not visible files.
640 ****************************************************************************/
642 BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
644 SET_STAT_INVALID(*pst);
646 if (!dptr->has_wild && (dptr->dir_hnd->offset == END_OF_DIRECTORY_OFFSET)) {
647 /* This is a singleton directory and we're already at the end. */
648 *poffset = END_OF_DIRECTORY_OFFSET;
652 return SearchDir(dptr->dir_hnd, name, poffset);
655 /****************************************************************************
656 Add the name we're returning into the underlying cache.
657 ****************************************************************************/
659 void dptr_DirCacheAdd(struct dptr_struct *dptr, const char *name, long offset)
661 DirCacheAdd(dptr->dir_hnd, name, offset);
664 /****************************************************************************
665 Fill the 5 byte server reserved dptr field.
666 ****************************************************************************/
668 BOOL dptr_fill(char *buf1,unsigned int key)
670 unsigned char *buf = (unsigned char *)buf1;
671 struct dptr_struct *dptr = dptr_get(key, False);
674 DEBUG(1,("filling null dirptr %d\n",key));
677 offset = (uint32)TellDir(dptr->dir_hnd);
678 DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
679 (long)dptr->dir_hnd,(int)offset));
685 /****************************************************************************
686 Fetch the dir ptr and seek it given the 5 byte server field.
687 ****************************************************************************/
689 struct dptr_struct *dptr_fetch(char *buf,int *num)
691 unsigned int key = *(unsigned char *)buf;
692 struct dptr_struct *dptr = dptr_get(key, False);
697 DEBUG(3,("fetched null dirptr %d\n",key));
701 offset = IVAL(buf,1);
702 if (offset == (uint32)-1) {
703 seekoff = END_OF_DIRECTORY_OFFSET;
705 seekoff = (long)offset;
707 SeekDir(dptr->dir_hnd,seekoff);
708 DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
709 key,dptr_path(key),(int)seekoff));
713 /****************************************************************************
715 ****************************************************************************/
717 struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
719 struct dptr_struct *dptr = dptr_get(dptr_num, False);
722 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
725 DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
729 /****************************************************************************
730 Check that a file matches a particular file type.
731 ****************************************************************************/
733 BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype)
737 /* Check the "may have" search bits. */
738 if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
741 /* Check the "must have" bits, which are the may have bits shifted eight */
742 /* If must have bit is set, the file/dir can not be returned in search unless the matching
743 file attribute is set */
744 mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */
746 if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask) /* check if matching attribute present */
755 static BOOL mangle_mask_match(connection_struct *conn, const char *filename,
760 if (!name_to_8_3(filename,mname,False,conn->params)) {
763 return mask_match_search(mname,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)) {
810 if (!name_to_8_3(filename,mname,False,
814 pstrcpy(filename,mname);
817 pstrcpy(fname,filename);
819 pstrcpy(path,conn->dirpath);
822 pstrcpy(pathreal,path);
824 pstrcat(pathreal,dname);
825 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
826 DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) ));
830 *mode = dos_mode(conn,pathreal,&sbuf);
832 if (!dir_check_ftype(conn,*mode,dirtype)) {
833 DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",filename,(unsigned int)*mode,(unsigned int)dirtype));
837 *size = sbuf.st_size;
838 *date = sbuf.st_mtime;
840 DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
844 DirCacheAdd(conn->dirptr->dir_hnd, dname, curoff);
851 /*******************************************************************
852 Check to see if a user can read a file. This is only approximate,
853 it is used as part of the "hide unreadable" option. Don't
854 use it for anything security sensitive.
855 ********************************************************************/
857 static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
859 SEC_DESC *psd = NULL;
863 uint32 access_granted;
866 * If user is a member of the Admin group
867 * we never hide files from them.
870 if (conn->admin_user) {
874 /* If we can't stat it does not show it */
875 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) {
876 DEBUG(10,("user_can_read_file: SMB_VFS_STAT failed for file %s with error %s\n",
877 name, strerror(errno) ));
881 /* Pseudo-open the file (note - no fd's created). */
883 if(S_ISDIR(pst->st_mode)) {
884 status = open_directory(conn, NULL, name, pst,
886 FILE_SHARE_READ|FILE_SHARE_WRITE,
888 0, /* no create options. */
889 FILE_ATTRIBUTE_DIRECTORY,
892 status = open_file_stat(conn, NULL, name, pst, &fsp);
895 if (!NT_STATUS_IS_OK(status)) {
899 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
900 sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd,
901 (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
902 close_file(fsp, NORMAL_CLOSE);
904 /* No access if SD get failed. */
909 return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA,
910 &access_granted, &status);
913 /*******************************************************************
914 Check to see if a user can write a file (and only files, we do not
915 check dirs on this one). This is only approximate,
916 it is used as part of the "hide unwriteable" option. Don't
917 use it for anything security sensitive.
918 ********************************************************************/
920 static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
922 SEC_DESC *psd = NULL;
927 uint32 access_granted;
930 * If user is a member of the Admin group
931 * we never hide files from them.
934 if (conn->admin_user) {
938 /* If we can't stat it does not show it */
939 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) {
943 /* Pseudo-open the file */
945 if(S_ISDIR(pst->st_mode)) {
948 status = open_file_ntcreate(conn, NULL, name, pst,
949 FILE_WRITE_ATTRIBUTES,
950 FILE_SHARE_READ|FILE_SHARE_WRITE,
953 FILE_ATTRIBUTE_NORMAL,
958 if (!NT_STATUS_IS_OK(status)) {
962 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
963 sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd,
964 (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
965 close_file(fsp, NORMAL_CLOSE);
967 /* No access if SD get failed. */
971 return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA,
972 &access_granted, &status);
975 /*******************************************************************
976 Is a file a "special" type ?
977 ********************************************************************/
979 static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
982 * If user is a member of the Admin group
983 * we never hide files from them.
986 if (conn->admin_user)
989 /* If we can't stat it does not show it */
990 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
993 if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
999 /*******************************************************************
1000 Should the file be seen by the client ?
1001 ********************************************************************/
1003 BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, BOOL use_veto)
1005 BOOL hide_unreadable = lp_hideunreadable(SNUM(conn));
1006 BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
1007 BOOL hide_special = lp_hide_special_files(SNUM(conn));
1009 SET_STAT_INVALID(*pst);
1011 if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
1012 return True; /* . and .. are always visible. */
1015 /* If it's a vetoed file, pretend it doesn't even exist */
1016 if (use_veto && IS_VETO_PATH(conn, name)) {
1017 DEBUG(10,("is_visible_file: file %s is vetoed.\n", name ));
1021 if (hide_unreadable || hide_unwriteable || hide_special) {
1024 if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
1028 /* If it's a dfs symlink, ignore _hide xxxx_ options */
1029 if (lp_host_msdfs() &&
1030 lp_msdfs_root(SNUM(conn)) &&
1031 is_msdfs_link(conn, entry, NULL)) {
1036 /* Honour _hide unreadable_ option */
1037 if (hide_unreadable && !user_can_read_file(conn, entry, pst)) {
1038 DEBUG(10,("is_visible_file: file %s is unreadable.\n", entry ));
1042 /* Honour _hide unwriteable_ option */
1043 if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
1044 DEBUG(10,("is_visible_file: file %s is unwritable.\n", entry ));
1048 /* Honour _hide_special_ option */
1049 if (hide_special && file_is_special(conn, entry, pst)) {
1050 DEBUG(10,("is_visible_file: file %s is special.\n", entry ));
1059 /*******************************************************************
1061 ********************************************************************/
1063 struct smb_Dir *OpenDir(connection_struct *conn, const char *name, const char *mask, uint32 attr)
1065 struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir);
1073 dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
1075 dirp->dir_path = SMB_STRDUP(name);
1076 if (!dirp->dir_path) {
1079 dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
1081 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) ));
1085 if (dirp->name_cache_size) {
1086 dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry,
1087 dirp->name_cache_size);
1088 if (!dirp->name_cache) {
1092 dirp->name_cache = NULL;
1102 SMB_VFS_CLOSEDIR(conn,dirp->dir);
1104 SAFE_FREE(dirp->dir_path);
1105 SAFE_FREE(dirp->name_cache);
1112 /*******************************************************************
1114 ********************************************************************/
1116 int CloseDir(struct smb_Dir *dirp)
1121 ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1123 SAFE_FREE(dirp->dir_path);
1124 if (dirp->name_cache) {
1125 for (i = 0; i < dirp->name_cache_size; i++) {
1126 SAFE_FREE(dirp->name_cache[i].name);
1129 SAFE_FREE(dirp->name_cache);
1135 /*******************************************************************
1136 Read from a directory. Also return current offset.
1137 Don't check for veto or invisible files.
1138 ********************************************************************/
1140 const char *ReadDirName(struct smb_Dir *dirp, long *poffset)
1143 connection_struct *conn = dirp->conn;
1145 /* Cheat to allow . and .. to be the first entries returned. */
1146 if (((*poffset == START_OF_DIRECTORY_OFFSET) || (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2)) {
1147 if (dirp->file_number == 0) {
1149 *poffset = dirp->offset = START_OF_DIRECTORY_OFFSET;
1151 *poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET;
1154 dirp->file_number++;
1156 } else if (*poffset == END_OF_DIRECTORY_OFFSET) {
1157 *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1160 /* A real offset, seek to it. */
1161 SeekDir(dirp, *poffset);
1164 while ((n = vfs_readdirname(conn, dirp->dir))) {
1165 /* Ignore . and .. - we've already returned them. */
1167 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
1171 *poffset = dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1172 dirp->file_number++;
1175 *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1179 /*******************************************************************
1180 Rewind to the start.
1181 ********************************************************************/
1183 void RewindDir(struct smb_Dir *dirp, long *poffset)
1185 SMB_VFS_REWINDDIR(dirp->conn, dirp->dir);
1186 dirp->file_number = 0;
1187 dirp->offset = START_OF_DIRECTORY_OFFSET;
1188 *poffset = START_OF_DIRECTORY_OFFSET;
1191 /*******************************************************************
1193 ********************************************************************/
1195 void SeekDir(struct smb_Dir *dirp, long offset)
1197 if (offset != dirp->offset) {
1198 if (offset == START_OF_DIRECTORY_OFFSET) {
1199 RewindDir(dirp, &offset);
1201 * Ok we should really set the file number here
1202 * to 1 to enable ".." to be returned next. Trouble
1203 * is I'm worried about callers using SeekDir(dirp,0)
1204 * as equivalent to RewindDir(). So leave this alone
1207 } else if (offset == DOT_DOT_DIRECTORY_OFFSET) {
1208 RewindDir(dirp, &offset);
1210 * Set the file number to 2 - we want to get the first
1211 * real file entry (the one we return after "..")
1212 * on the next ReadDir.
1214 dirp->file_number = 2;
1215 } else if (offset == END_OF_DIRECTORY_OFFSET) {
1216 ; /* Don't seek in this case. */
1218 SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1220 dirp->offset = offset;
1224 /*******************************************************************
1225 Tell a dir position.
1226 ********************************************************************/
1228 long TellDir(struct smb_Dir *dirp)
1230 return(dirp->offset);
1233 /*******************************************************************
1234 Add an entry into the dcache.
1235 ********************************************************************/
1237 void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
1239 struct name_cache_entry *e;
1241 if (!dirp->name_cache_size || !dirp->name_cache) {
1245 dirp->name_cache_index = (dirp->name_cache_index+1) %
1246 dirp->name_cache_size;
1247 e = &dirp->name_cache[dirp->name_cache_index];
1249 e->name = SMB_STRDUP(name);
1253 /*******************************************************************
1254 Find an entry by name. Leave us at the offset after it.
1255 Don't check for veto or invisible files.
1256 ********************************************************************/
1258 BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1262 connection_struct *conn = dirp->conn;
1264 /* Search back in the name cache. */
1265 if (dirp->name_cache_size && dirp->name_cache) {
1266 for (i = dirp->name_cache_index; i >= 0; i--) {
1267 struct name_cache_entry *e = &dirp->name_cache[i];
1268 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1269 *poffset = e->offset;
1270 SeekDir(dirp, e->offset);
1274 for (i = dirp->name_cache_size - 1; i > dirp->name_cache_index; i--) {
1275 struct name_cache_entry *e = &dirp->name_cache[i];
1276 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1277 *poffset = e->offset;
1278 SeekDir(dirp, e->offset);
1284 /* Not found in the name cache. Rewind directory and start from scratch. */
1285 SMB_VFS_REWINDDIR(conn, dirp->dir);
1286 dirp->file_number = 0;
1287 *poffset = START_OF_DIRECTORY_OFFSET;
1288 while ((entry = ReadDirName(dirp, poffset))) {
1289 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
1296 /*****************************************************************
1297 Is this directory empty ?
1298 *****************************************************************/
1300 NTSTATUS can_delete_directory(struct connection_struct *conn,
1301 const char *dirname)
1303 NTSTATUS status = NT_STATUS_OK;
1306 struct smb_Dir *dir_hnd = OpenDir(conn, dirname, NULL, 0);
1309 return map_nt_error_from_unix(errno);
1312 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
1315 /* Quick check for "." and ".." */
1316 if (dname[0] == '.') {
1317 if (!dname[1] || (dname[1] == '.' && !dname[2])) {
1322 if (!is_visible_file(conn, dirname, dname, &st, True)) {
1326 DEBUG(10,("can_delete_directory: got name %s - can't delete\n", dname ));
1327 status = NT_STATUS_DIRECTORY_NOT_EMPTY;