r6303: Setting up for 3.0.15pre1
[Samba.git] / source / smbd / dir.c
blob0f32dddd2d765a79c9b06db96a7892fc8cbc5be1
1 /*
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.
21 #include "includes.h"
24 This module implements directory related functions for Samba.
27 extern struct current_user current_user;
29 /* Make directory handle internals available. */
31 #define NAME_CACHE_SIZE 100
33 struct name_cache_entry {
34 char *name;
35 long offset;
38 struct smb_Dir {
39 connection_struct *conn;
40 DIR *dir;
41 long offset;
42 char *dir_path;
43 struct name_cache_entry *name_cache;
44 unsigned int name_cache_index;
47 struct dptr_struct {
48 struct dptr_struct *next, *prev;
49 int dnum;
50 uint16 spid;
51 struct connection_struct *conn;
52 struct smb_Dir *dir_hnd;
53 BOOL expect_close;
54 char *wcard;
55 uint16 attr;
56 char *path;
57 BOOL has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
60 static struct bitmap *dptr_bmap;
61 static struct dptr_struct *dirptrs;
62 static int dirhandles_open = 0;
64 #define INVALID_DPTR_KEY (-3)
66 /****************************************************************************
67 Initialise the dir bitmap.
68 ****************************************************************************/
70 void init_dptrs(void)
72 static BOOL dptrs_init=False;
74 if (dptrs_init)
75 return;
77 dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES);
79 if (!dptr_bmap)
80 exit_server("out of memory in init_dptrs");
82 dptrs_init = True;
85 /****************************************************************************
86 Idle a dptr - the directory is closed but the control info is kept.
87 ****************************************************************************/
89 static void dptr_idle(struct dptr_struct *dptr)
91 if (dptr->dir_hnd) {
92 DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
93 CloseDir(dptr->dir_hnd);
94 dptr->dir_hnd = NULL;
98 /****************************************************************************
99 Idle the oldest dptr.
100 ****************************************************************************/
102 static void dptr_idleoldest(void)
104 struct dptr_struct *dptr;
107 * Go to the end of the list.
109 for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
112 if(!dptr) {
113 DEBUG(0,("No dptrs available to idle ?\n"));
114 return;
118 * Idle the oldest pointer.
121 for(; dptr; dptr = dptr->prev) {
122 if (dptr->dir_hnd) {
123 dptr_idle(dptr);
124 return;
129 /****************************************************************************
130 Get the struct dptr_struct for a dir index.
131 ****************************************************************************/
133 static struct dptr_struct *dptr_get(int key, BOOL forclose)
135 struct dptr_struct *dptr;
137 for(dptr = dirptrs; dptr; dptr = dptr->next) {
138 if(dptr->dnum == key) {
139 if (!forclose && !dptr->dir_hnd) {
140 if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
141 dptr_idleoldest();
142 DEBUG(4,("dptr_get: Reopening dptr key %d\n",key));
143 if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path))) {
144 DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path,
145 strerror(errno)));
146 return False;
149 DLIST_PROMOTE(dirptrs,dptr);
150 return dptr;
153 return(NULL);
156 /****************************************************************************
157 Get the dir path for a dir index.
158 ****************************************************************************/
160 char *dptr_path(int key)
162 struct dptr_struct *dptr = dptr_get(key, False);
163 if (dptr)
164 return(dptr->path);
165 return(NULL);
168 /****************************************************************************
169 Get the dir wcard for a dir index.
170 ****************************************************************************/
172 char *dptr_wcard(int key)
174 struct dptr_struct *dptr = dptr_get(key, False);
175 if (dptr)
176 return(dptr->wcard);
177 return(NULL);
180 /****************************************************************************
181 Get the dir attrib for a dir index.
182 ****************************************************************************/
184 uint16 dptr_attr(int key)
186 struct dptr_struct *dptr = dptr_get(key, False);
187 if (dptr)
188 return(dptr->attr);
189 return(0);
192 /****************************************************************************
193 Set the dir wcard for a dir index.
194 Returns 0 on ok, 1 on fail.
195 ****************************************************************************/
197 BOOL dptr_set_wcard_and_attributes(int key, const char *wcard, uint16 attr)
199 struct dptr_struct *dptr = dptr_get(key, False);
201 if (dptr) {
202 dptr->attr = attr;
203 dptr->wcard = SMB_STRDUP(wcard);
204 if (!dptr->wcard)
205 return False;
206 if (wcard[0] == '.' && wcard[1] == 0) {
207 dptr->has_wild = True;
208 } else {
209 dptr->has_wild = ms_has_wild(wcard);
211 return True;
213 return False;
216 /****************************************************************************
217 Close a dptr (internal func).
218 ****************************************************************************/
220 static void dptr_close_internal(struct dptr_struct *dptr)
222 DEBUG(4,("closing dptr key %d\n",dptr->dnum));
224 DLIST_REMOVE(dirptrs, dptr);
227 * Free the dnum in the bitmap. Remember the dnum value is always
228 * biased by one with respect to the bitmap.
231 if(bitmap_query( dptr_bmap, dptr->dnum - 1) != True) {
232 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
233 dptr->dnum ));
236 bitmap_clear(dptr_bmap, dptr->dnum - 1);
238 if (dptr->dir_hnd) {
239 CloseDir(dptr->dir_hnd);
242 /* Lanman 2 specific code */
243 SAFE_FREE(dptr->wcard);
244 string_set(&dptr->path,"");
245 SAFE_FREE(dptr);
248 /****************************************************************************
249 Close a dptr given a key.
250 ****************************************************************************/
252 void dptr_close(int *key)
254 struct dptr_struct *dptr;
256 if(*key == INVALID_DPTR_KEY)
257 return;
259 /* OS/2 seems to use -1 to indicate "close all directories" */
260 if (*key == -1) {
261 struct dptr_struct *next;
262 for(dptr = dirptrs; dptr; dptr = next) {
263 next = dptr->next;
264 dptr_close_internal(dptr);
266 *key = INVALID_DPTR_KEY;
267 return;
270 dptr = dptr_get(*key, True);
272 if (!dptr) {
273 DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
274 return;
277 dptr_close_internal(dptr);
279 *key = INVALID_DPTR_KEY;
282 /****************************************************************************
283 Close all dptrs for a cnum.
284 ****************************************************************************/
286 void dptr_closecnum(connection_struct *conn)
288 struct dptr_struct *dptr, *next;
289 for(dptr = dirptrs; dptr; dptr = next) {
290 next = dptr->next;
291 if (dptr->conn == conn)
292 dptr_close_internal(dptr);
296 /****************************************************************************
297 Idle all dptrs for a cnum.
298 ****************************************************************************/
300 void dptr_idlecnum(connection_struct *conn)
302 struct dptr_struct *dptr;
303 for(dptr = dirptrs; dptr; dptr = dptr->next) {
304 if (dptr->conn == conn && dptr->dir_hnd)
305 dptr_idle(dptr);
309 /****************************************************************************
310 Close a dptr that matches a given path, only if it matches the spid also.
311 ****************************************************************************/
313 void dptr_closepath(char *path,uint16 spid)
315 struct dptr_struct *dptr, *next;
316 for(dptr = dirptrs; dptr; dptr = next) {
317 next = dptr->next;
318 if (spid == dptr->spid && strequal(dptr->path,path))
319 dptr_close_internal(dptr);
323 /****************************************************************************
324 Try and close the oldest handle not marked for
325 expect close in the hope that the client has
326 finished with that one.
327 ****************************************************************************/
329 static void dptr_close_oldest(BOOL old)
331 struct dptr_struct *dptr;
334 * Go to the end of the list.
336 for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
339 if(!dptr) {
340 DEBUG(0,("No old dptrs available to close oldest ?\n"));
341 return;
345 * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
346 * does not have expect_close set. If 'old' is false, close
347 * one of the new dnum handles.
350 for(; dptr; dptr = dptr->prev) {
351 if ((old && (dptr->dnum < 256) && !dptr->expect_close) ||
352 (!old && (dptr->dnum > 255))) {
353 dptr_close_internal(dptr);
354 return;
359 /****************************************************************************
360 Create a new dir ptr. If the flag old_handle is true then we must allocate
361 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
362 one byte long. If old_handle is false we allocate from the range
363 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
364 a directory handle is never zero.
365 ****************************************************************************/
367 int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid)
369 struct dptr_struct *dptr = NULL;
370 struct smb_Dir *dir_hnd;
371 const char *dir2;
373 DEBUG(5,("dptr_create dir=%s\n", path));
375 if (!check_name(path,conn))
376 return(-2); /* Code to say use a unix error return code. */
378 /* use a const pointer from here on */
379 dir2 = path;
380 if (!*dir2)
381 dir2 = ".";
383 dir_hnd = OpenDir(conn, dir2);
384 if (!dir_hnd) {
385 return (-2);
388 string_set(&conn->dirpath,dir2);
390 if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
391 dptr_idleoldest();
393 dptr = SMB_MALLOC_P(struct dptr_struct);
394 if(!dptr) {
395 DEBUG(0,("malloc fail in dptr_create.\n"));
396 CloseDir(dir_hnd);
397 return -1;
400 ZERO_STRUCTP(dptr);
402 if(old_handle) {
405 * This is an old-style SMBsearch request. Ensure the
406 * value we return will fit in the range 1-255.
409 dptr->dnum = bitmap_find(dptr_bmap, 0);
411 if(dptr->dnum == -1 || dptr->dnum > 254) {
414 * Try and close the oldest handle not marked for
415 * expect close in the hope that the client has
416 * finished with that one.
419 dptr_close_oldest(True);
421 /* Now try again... */
422 dptr->dnum = bitmap_find(dptr_bmap, 0);
423 if(dptr->dnum == -1 || dptr->dnum > 254) {
424 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
425 SAFE_FREE(dptr);
426 CloseDir(dir_hnd);
427 return -1;
430 } else {
433 * This is a new-style trans2 request. Allocate from
434 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
437 dptr->dnum = bitmap_find(dptr_bmap, 255);
439 if(dptr->dnum == -1 || dptr->dnum < 255) {
442 * Try and close the oldest handle close in the hope that
443 * the client has finished with that one. This will only
444 * happen in the case of the Win98 client bug where it leaks
445 * directory handles.
448 dptr_close_oldest(False);
450 /* Now try again... */
451 dptr->dnum = bitmap_find(dptr_bmap, 255);
453 if(dptr->dnum == -1 || dptr->dnum < 255) {
454 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
455 SAFE_FREE(dptr);
456 CloseDir(dir_hnd);
457 return -1;
462 bitmap_set(dptr_bmap, dptr->dnum);
464 dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
466 string_set(&dptr->path,dir2);
467 dptr->conn = conn;
468 dptr->dir_hnd = dir_hnd;
469 dptr->spid = spid;
470 dptr->expect_close = expect_close;
471 dptr->wcard = NULL; /* Only used in lanman2 searches */
472 dptr->attr = 0; /* Only used in lanman2 searches */
473 dptr->has_wild = True; /* Only used in lanman2 searches */
475 DLIST_ADD(dirptrs, dptr);
477 DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
478 dptr->dnum,path,expect_close));
480 conn->dirptr = dptr;
482 return(dptr->dnum);
486 /****************************************************************************
487 Wrapper functions to access the lower level directory handles.
488 ****************************************************************************/
490 int dptr_CloseDir(struct dptr_struct *dptr)
492 return CloseDir(dptr->dir_hnd);
495 void dptr_SeekDir(struct dptr_struct *dptr, long offset)
497 SeekDir(dptr->dir_hnd, offset);
500 long dptr_TellDir(struct dptr_struct *dptr)
502 return TellDir(dptr->dir_hnd);
505 /****************************************************************************
506 Return the next visible file name, skipping veto'd and invisible files.
507 ****************************************************************************/
509 static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
511 /* Normal search for the next file. */
512 const char *name;
513 while ((name = ReadDirName(dptr->dir_hnd, poffset)) != NULL) {
514 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
515 return name;
518 return NULL;
521 /****************************************************************************
522 Return the next visible file name, skipping veto'd and invisible files.
523 ****************************************************************************/
525 const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
527 pstring pathreal;
529 ZERO_STRUCTP(pst);
531 if (dptr->has_wild) {
532 return dptr_normal_ReadDirName(dptr, poffset, pst);
535 /* If poffset is -1 then we know we returned this name before and we have
536 no wildcards. We're at the end of the directory. */
537 if (*poffset == -1) {
538 return NULL;
541 /* We know the stored wcard contains no wildcard characters. See if we can match
542 with a stat call. If we can't, then set has_wild to true to
543 prevent us from doing this on every call. */
545 /* First check if it should be visible. */
546 if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard, pst, True)) {
547 dptr->has_wild = True;
548 return dptr_normal_ReadDirName(dptr, poffset, pst);
551 if (VALID_STAT(*pst)) {
552 /* We need to set the underlying dir_hdn offset to -1 also as
553 this function is usually called with the output from TellDir. */
554 dptr->dir_hnd->offset = *poffset = -1;
555 return dptr->wcard;
558 pstrcpy(pathreal,dptr->path);
559 pstrcat(pathreal,"/");
560 pstrcat(pathreal,dptr->wcard);
562 if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) {
563 /* We need to set the underlying dir_hdn offset to -1 also as
564 this function is usually called with the output from TellDir. */
565 dptr->dir_hnd->offset = *poffset = -1;
566 return dptr->wcard;
567 } else {
568 /* If we get any other error than ENOENT or ENOTDIR
569 then the file exists we just can't stat it. */
570 if (errno != ENOENT && errno != ENOTDIR) {
571 /* We need to set the underlying dir_hdn offset to -1 also as
572 this function is usually called with the output from TellDir. */
573 dptr->dir_hnd->offset = *poffset = -1;
574 return dptr->wcard;
578 /* In case sensitive mode we don't search - we know if it doesn't exist
579 with a stat we will fail. */
581 if (dptr->conn->case_sensitive) {
582 /* We need to set the underlying dir_hdn offset to -1 also as
583 this function is usually called with the output from TellDir. */
584 dptr->dir_hnd->offset = *poffset = -1;
585 return NULL;
586 } else {
587 dptr->has_wild = True;
588 return dptr_normal_ReadDirName(dptr, poffset, pst);
592 /****************************************************************************
593 Search for a file by name, skipping veto'ed and not visible files.
594 ****************************************************************************/
596 BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
598 ZERO_STRUCTP(pst);
600 if (!dptr->has_wild && (dptr->dir_hnd->offset == -1)) {
601 /* This is a singleton directory and we're already at the end. */
602 *poffset = -1;
603 return False;
606 if (SearchDir(dptr->dir_hnd, name, poffset)) {
607 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
608 return True;
611 return False;
614 /****************************************************************************
615 Fill the 5 byte server reserved dptr field.
616 ****************************************************************************/
618 BOOL dptr_fill(char *buf1,unsigned int key)
620 unsigned char *buf = (unsigned char *)buf1;
621 struct dptr_struct *dptr = dptr_get(key, False);
622 uint32 offset;
623 if (!dptr) {
624 DEBUG(1,("filling null dirptr %d\n",key));
625 return(False);
627 offset = TellDir(dptr->dir_hnd);
628 DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
629 (long)dptr->dir_hnd,(int)offset));
630 buf[0] = key;
631 SIVAL(buf,1,offset | DPTR_MASK);
632 return(True);
635 /****************************************************************************
636 Fetch the dir ptr and seek it given the 5 byte server field.
637 ****************************************************************************/
639 struct dptr_struct *dptr_fetch(char *buf,int *num)
641 unsigned int key = *(unsigned char *)buf;
642 struct dptr_struct *dptr = dptr_get(key, False);
643 uint32 offset;
645 if (!dptr) {
646 DEBUG(3,("fetched null dirptr %d\n",key));
647 return(NULL);
649 *num = key;
650 offset = IVAL(buf,1)&~DPTR_MASK;
651 SeekDir(dptr->dir_hnd,(long)offset);
652 DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
653 key,dptr_path(key),offset));
654 return(dptr);
657 /****************************************************************************
658 Fetch the dir ptr.
659 ****************************************************************************/
661 struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
663 struct dptr_struct *dptr = dptr_get(dptr_num, False);
665 if (!dptr) {
666 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
667 return(NULL);
669 DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
670 return(dptr);
673 /****************************************************************************
674 Check a filetype for being valid.
675 ****************************************************************************/
677 BOOL dir_check_ftype(connection_struct *conn,int mode,int dirtype)
679 int mask;
681 /* Check the "may have" search bits. */
682 if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
683 return False;
685 /* Check the "must have" bits, which are the may have bits shifted eight */
686 /* If must have bit is set, the file/dir can not be returned in search unless the matching
687 file attribute is set */
688 mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */
689 if(mask) {
690 if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask) /* check if matching attribute present */
691 return True;
692 else
693 return False;
696 return True;
699 static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask)
701 mangle_map(filename,True,False,SNUM(conn));
702 return mask_match_search(filename,mask,False);
705 /****************************************************************************
706 Get an 8.3 directory entry.
707 ****************************************************************************/
709 BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname,
710 SMB_OFF_T *size,int *mode,time_t *date,BOOL check_descend)
712 const char *dname;
713 BOOL found = False;
714 SMB_STRUCT_STAT sbuf;
715 pstring path;
716 pstring pathreal;
717 pstring filename;
718 BOOL needslash;
720 *path = *pathreal = *filename = 0;
722 needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
724 if (!conn->dirptr)
725 return(False);
727 while (!found) {
728 long curoff = dptr_TellDir(conn->dirptr);
729 dname = dptr_ReadDirName(conn->dirptr, &curoff, &sbuf);
731 DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
732 (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
734 if (dname == NULL)
735 return(False);
737 pstrcpy(filename,dname);
739 /* notice the special *.* handling. This appears to be the only difference
740 between the wildcard handling in this routine and in the trans2 routines.
741 see masktest for a demo
743 if ((strcmp(mask,"*.*") == 0) ||
744 mask_match_search(filename,mask,False) ||
745 mangle_mask_match(conn,filename,mask)) {
747 if (!mangle_is_8_3(filename, False))
748 mangle_map(filename,True,False,SNUM(conn));
750 pstrcpy(fname,filename);
751 *path = 0;
752 pstrcpy(path,conn->dirpath);
753 if(needslash)
754 pstrcat(path,"/");
755 pstrcpy(pathreal,path);
756 pstrcat(path,fname);
757 pstrcat(pathreal,dname);
758 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
759 DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) ));
760 continue;
763 *mode = dos_mode(conn,pathreal,&sbuf);
765 if (!dir_check_ftype(conn,*mode,dirtype)) {
766 DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype));
767 continue;
770 *size = sbuf.st_size;
771 *date = sbuf.st_mtime;
773 DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
775 found = True;
779 return(found);
782 /*******************************************************************
783 Check to see if a user can read a file. This is only approximate,
784 it is used as part of the "hide unreadable" option. Don't
785 use it for anything security sensitive.
786 ********************************************************************/
788 static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
790 SEC_DESC *psd = NULL;
791 size_t sd_size;
792 files_struct *fsp;
793 int smb_action;
794 NTSTATUS status;
795 uint32 access_granted;
798 * If user is a member of the Admin group
799 * we never hide files from them.
802 if (conn->admin_user)
803 return True;
805 /* If we can't stat it does not show it */
806 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
807 return False;
809 /* Pseudo-open the file (note - no fd's created). */
811 if(S_ISDIR(pst->st_mode))
812 fsp = open_directory(conn, name, pst, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
813 &smb_action);
814 else
815 fsp = open_file_stat(conn, name, pst);
817 if (!fsp)
818 return False;
820 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
821 sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd,
822 (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
823 close_file(fsp, True);
825 /* No access if SD get failed. */
826 if (!sd_size)
827 return False;
829 return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA,
830 &access_granted, &status);
833 /*******************************************************************
834 Check to see if a user can write a file (and only files, we do not
835 check dirs on this one). This is only approximate,
836 it is used as part of the "hide unwriteable" option. Don't
837 use it for anything security sensitive.
838 ********************************************************************/
840 static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
842 SEC_DESC *psd = NULL;
843 size_t sd_size;
844 files_struct *fsp;
845 int smb_action;
846 int access_mode;
847 NTSTATUS status;
848 uint32 access_granted;
851 * If user is a member of the Admin group
852 * we never hide files from them.
855 if (conn->admin_user)
856 return True;
858 /* If we can't stat it does not show it */
859 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
860 return False;
862 /* Pseudo-open the file (note - no fd's created). */
864 if(S_ISDIR(pst->st_mode))
865 return True;
866 else
867 fsp = open_file_shared1(conn, name, pst, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE),
868 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY,
869 &access_mode, &smb_action);
871 if (!fsp)
872 return False;
874 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
875 sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd,
876 (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
877 close_file(fsp, False);
879 /* No access if SD get failed. */
880 if (!sd_size)
881 return False;
883 return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA,
884 &access_granted, &status);
887 /*******************************************************************
888 Is a file a "special" type ?
889 ********************************************************************/
891 static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
894 * If user is a member of the Admin group
895 * we never hide files from them.
898 if (conn->admin_user)
899 return False;
901 /* If we can't stat it does not show it */
902 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
903 return True;
905 if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
906 return False;
908 return True;
911 /*******************************************************************
912 Should the file be seen by the client ?
913 ********************************************************************/
915 BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, BOOL use_veto)
917 BOOL hide_unreadable = lp_hideunreadable(SNUM(conn));
918 BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
919 BOOL hide_special = lp_hide_special_files(SNUM(conn));
921 ZERO_STRUCTP(pst);
923 if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
924 return True; /* . and .. are always visible. */
927 /* If it's a vetoed file, pretend it doesn't even exist */
928 if (use_veto && IS_VETO_PATH(conn, name)) {
929 return False;
932 if (hide_unreadable || hide_unwriteable || hide_special) {
933 char *entry = NULL;
935 if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
936 return False;
938 /* Honour _hide unreadable_ option */
939 if (hide_unreadable && !user_can_read_file(conn, entry, pst)) {
940 SAFE_FREE(entry);
941 return False;
943 /* Honour _hide unwriteable_ option */
944 if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
945 SAFE_FREE(entry);
946 return False;
948 /* Honour _hide_special_ option */
949 if (hide_special && !file_is_special(conn, entry, pst)) {
950 SAFE_FREE(entry);
951 return False;
953 SAFE_FREE(entry);
955 return True;
958 /*******************************************************************
959 Open a directory.
960 ********************************************************************/
962 struct smb_Dir *OpenDir(connection_struct *conn, const char *name)
964 struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir);
965 if (!dirp) {
966 return NULL;
968 ZERO_STRUCTP(dirp);
970 dirp->conn = conn;
972 dirp->dir_path = SMB_STRDUP(name);
973 if (!dirp->dir_path) {
974 goto fail;
976 dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path);
977 if (!dirp->dir) {
978 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) ));
979 goto fail;
982 dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, NAME_CACHE_SIZE);
983 if (!dirp->name_cache) {
984 goto fail;
987 dirhandles_open++;
988 return dirp;
990 fail:
992 if (dirp) {
993 if (dirp->dir) {
994 SMB_VFS_CLOSEDIR(conn,dirp->dir);
996 SAFE_FREE(dirp->dir_path);
997 SAFE_FREE(dirp->name_cache);
998 SAFE_FREE(dirp);
1000 return NULL;
1004 /*******************************************************************
1005 Close a directory.
1006 ********************************************************************/
1008 int CloseDir(struct smb_Dir *dirp)
1010 int i, ret = 0;
1012 if (dirp->dir) {
1013 ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1015 SAFE_FREE(dirp->dir_path);
1016 if (dirp->name_cache) {
1017 for (i = 0; i < NAME_CACHE_SIZE; i++) {
1018 SAFE_FREE(dirp->name_cache[i].name);
1021 SAFE_FREE(dirp->name_cache);
1022 SAFE_FREE(dirp);
1023 dirhandles_open--;
1024 return ret;
1027 /*******************************************************************
1028 Read from a directory. Also return current offset.
1029 Don't check for veto or invisible files.
1030 ********************************************************************/
1032 const char *ReadDirName(struct smb_Dir *dirp, long *poffset)
1034 const char *n;
1035 connection_struct *conn = dirp->conn;
1037 SeekDir(dirp, *poffset);
1038 while ((n = vfs_readdirname(conn, dirp->dir))) {
1039 struct name_cache_entry *e;
1040 dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1041 if (dirp->offset == -1) {
1042 return NULL;
1044 dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE;
1046 e = &dirp->name_cache[dirp->name_cache_index];
1047 SAFE_FREE(e->name);
1048 e->name = SMB_STRDUP(n);
1049 *poffset = e->offset= dirp->offset;
1050 return e->name;
1052 dirp->offset = -1;
1053 return NULL;
1056 /*******************************************************************
1057 Seek a dir.
1058 ********************************************************************/
1060 void SeekDir(struct smb_Dir *dirp, long offset)
1062 if (offset != dirp->offset) {
1063 SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1064 dirp->offset = offset;
1068 /*******************************************************************
1069 Tell a dir position.
1070 ********************************************************************/
1072 long TellDir(struct smb_Dir *dirp)
1074 return(dirp->offset);
1077 /*******************************************************************
1078 Find an entry by name. Leave us at the offset after it.
1079 Don't check for veto or invisible files.
1080 ********************************************************************/
1082 BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1084 int i;
1085 const char *entry;
1086 connection_struct *conn = dirp->conn;
1088 /* Search back in the name cache. */
1089 for (i = dirp->name_cache_index; i >= 0; i--) {
1090 struct name_cache_entry *e = &dirp->name_cache[i];
1091 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1092 *poffset = e->offset;
1093 SeekDir(dirp, e->offset);
1094 return True;
1097 for (i = NAME_CACHE_SIZE-1; i > dirp->name_cache_index; i--) {
1098 struct name_cache_entry *e = &dirp->name_cache[i];
1099 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1100 *poffset = e->offset;
1101 SeekDir(dirp, e->offset);
1102 return True;
1106 /* Not found in the name cache. Rewind directory and start from scratch. */
1107 SMB_VFS_REWINDDIR(conn, dirp->dir);
1108 *poffset = 0;
1109 while ((entry = ReadDirName(dirp, poffset))) {
1110 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
1111 return True;
1114 return False;