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 typedef struct _dptr_struct {
28 struct _dptr_struct *next, *prev;
31 connection_struct *conn;
34 char *wcard; /* Field only used for trans2_ searches */
35 uint16 attr; /* Field only used for trans2_ searches */
39 static struct bitmap *dptr_bmap;
40 static dptr_struct *dirptrs;
42 static int dptrs_open = 0;
44 #define INVALID_DPTR_KEY (-3)
46 /****************************************************************************
47 Initialise the dir bitmap.
48 ****************************************************************************/
52 static BOOL dptrs_init=False;
57 dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES);
60 exit_server("out of memory in init_dptrs");
65 /****************************************************************************
66 Idle a dptr - the directory is closed but the control info is kept.
67 ****************************************************************************/
69 static void dptr_idle(dptr_struct *dptr)
72 DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
79 /****************************************************************************
81 ****************************************************************************/
83 static void dptr_idleoldest(void)
88 * Go to the end of the list.
90 for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
94 DEBUG(0,("No dptrs available to idle ?\n"));
99 * Idle the oldest pointer.
102 for(; dptr; dptr = dptr->prev) {
110 /****************************************************************************
111 Get the dptr_struct for a dir index.
112 ****************************************************************************/
114 static dptr_struct *dptr_get(int key, BOOL forclose)
118 for(dptr = dirptrs; dptr; dptr = dptr->next) {
119 if(dptr->dnum == key) {
120 if (!forclose && !dptr->ptr) {
121 if (dptrs_open >= MAX_OPEN_DIRECTORIES)
123 DEBUG(4,("Reopening dptr key %d\n",key));
124 if ((dptr->ptr = OpenDir(dptr->conn, dptr->path, True)))
127 DLIST_PROMOTE(dirptrs,dptr);
134 /****************************************************************************
135 Get the dptr ptr for a dir index.
136 ****************************************************************************/
138 static void *dptr_ptr(int key)
140 dptr_struct *dptr = dptr_get(key, False);
147 /****************************************************************************
148 Get the dir path for a dir index.
149 ****************************************************************************/
151 char *dptr_path(int key)
153 dptr_struct *dptr = dptr_get(key, False);
160 /****************************************************************************
161 Get the dir wcard for a dir index (lanman2 specific).
162 ****************************************************************************/
164 char *dptr_wcard(int key)
166 dptr_struct *dptr = dptr_get(key, False);
173 /****************************************************************************
174 Set the dir wcard for a dir index (lanman2 specific).
175 Returns 0 on ok, 1 on fail.
176 ****************************************************************************/
178 BOOL dptr_set_wcard(int key, char *wcard)
180 dptr_struct *dptr = dptr_get(key, False);
189 /****************************************************************************
190 Set the dir attrib for a dir index (lanman2 specific).
191 Returns 0 on ok, 1 on fail.
192 ****************************************************************************/
194 BOOL dptr_set_attr(int key, uint16 attr)
196 dptr_struct *dptr = dptr_get(key, False);
205 /****************************************************************************
206 Get the dir attrib for a dir index (lanman2 specific)
207 ****************************************************************************/
209 uint16 dptr_attr(int key)
211 dptr_struct *dptr = dptr_get(key, False);
218 /****************************************************************************
219 Close a dptr (internal func).
220 ****************************************************************************/
222 static void dptr_close_internal(dptr_struct *dptr)
224 DEBUG(4,("closing dptr key %d\n",dptr->dnum));
226 DLIST_REMOVE(dirptrs, dptr);
229 * Free the dnum in the bitmap. Remember the dnum value is always
230 * biased by one with respect to the bitmap.
233 if(bitmap_query( dptr_bmap, dptr->dnum - 1) != True) {
234 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
238 bitmap_clear(dptr_bmap, dptr->dnum - 1);
245 /* Lanman 2 specific code */
246 SAFE_FREE(dptr->wcard);
247 string_set(&dptr->path,"");
251 /****************************************************************************
252 Close a dptr given a key.
253 ****************************************************************************/
255 void dptr_close(int *key)
259 if(*key == INVALID_DPTR_KEY)
262 /* OS/2 seems to use -1 to indicate "close all directories" */
265 for(dptr = dirptrs; dptr; dptr = next) {
267 dptr_close_internal(dptr);
269 *key = INVALID_DPTR_KEY;
273 dptr = dptr_get(*key, True);
276 DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
280 dptr_close_internal(dptr);
282 *key = INVALID_DPTR_KEY;
285 /****************************************************************************
286 Close all dptrs for a cnum.
287 ****************************************************************************/
289 void dptr_closecnum(connection_struct *conn)
291 dptr_struct *dptr, *next;
292 for(dptr = dirptrs; dptr; dptr = next) {
294 if (dptr->conn == conn)
295 dptr_close_internal(dptr);
299 /****************************************************************************
300 Idle all dptrs for a cnum.
301 ****************************************************************************/
303 void dptr_idlecnum(connection_struct *conn)
306 for(dptr = dirptrs; dptr; dptr = dptr->next) {
307 if (dptr->conn == conn && dptr->ptr)
312 /****************************************************************************
313 Close a dptr that matches a given path, only if it matches the spid also.
314 ****************************************************************************/
316 void dptr_closepath(char *path,uint16 spid)
318 dptr_struct *dptr, *next;
319 for(dptr = dirptrs; dptr; dptr = next) {
321 if (spid == dptr->spid && strequal(dptr->path,path))
322 dptr_close_internal(dptr);
326 /****************************************************************************
327 Start a directory listing.
328 ****************************************************************************/
330 static BOOL start_dir(connection_struct *conn,char *directory)
332 DEBUG(5,("start_dir dir=%s\n",directory));
334 if (!check_name(directory,conn))
340 conn->dirptr = OpenDir(conn, directory, True);
343 string_set(&conn->dirpath,directory);
350 /****************************************************************************
351 Try and close the oldest handle not marked for
352 expect close in the hope that the client has
353 finished with that one.
354 ****************************************************************************/
356 static void dptr_close_oldest(BOOL old)
361 * Go to the end of the list.
363 for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
367 DEBUG(0,("No old dptrs available to close oldest ?\n"));
372 * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
373 * does not have expect_close set. If 'old' is false, close
374 * one of the new dnum handles.
377 for(; dptr; dptr = dptr->prev) {
378 if ((old && (dptr->dnum < 256) && !dptr->expect_close) ||
379 (!old && (dptr->dnum > 255))) {
380 dptr_close_internal(dptr);
386 /****************************************************************************
387 Create a new dir ptr. If the flag old_handle is true then we must allocate
388 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
389 one byte long. If old_handle is false we allocate from the range
390 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
391 a directory handle is never zero. All the above is folklore taught to
392 me at Andrew's knee.... :-) :-). JRA.
393 ****************************************************************************/
395 int dptr_create(connection_struct *conn,char *path, BOOL old_handle, BOOL expect_close,uint16 spid)
399 if (!start_dir(conn,path))
400 return(-2); /* Code to say use a unix error return code. */
402 if (dptrs_open >= MAX_OPEN_DIRECTORIES)
405 dptr = (dptr_struct *)malloc(sizeof(dptr_struct));
407 DEBUG(0,("malloc fail in dptr_create.\n"));
416 * This is an old-style SMBsearch request. Ensure the
417 * value we return will fit in the range 1-255.
420 dptr->dnum = bitmap_find(dptr_bmap, 0);
422 if(dptr->dnum == -1 || dptr->dnum > 254) {
425 * Try and close the oldest handle not marked for
426 * expect close in the hope that the client has
427 * finished with that one.
430 dptr_close_oldest(True);
432 /* Now try again... */
433 dptr->dnum = bitmap_find(dptr_bmap, 0);
435 if(dptr->dnum == -1 || dptr->dnum > 254) {
436 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
444 * This is a new-style trans2 request. Allocate from
445 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
448 dptr->dnum = bitmap_find(dptr_bmap, 255);
450 if(dptr->dnum == -1 || dptr->dnum < 255) {
453 * Try and close the oldest handle close in the hope that
454 * the client has finished with that one. This will only
455 * happen in the case of the Win98 client bug where it leaks
459 dptr_close_oldest(False);
461 /* Now try again... */
462 dptr->dnum = bitmap_find(dptr_bmap, 255);
464 if(dptr->dnum == -1 || dptr->dnum < 255) {
465 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
472 bitmap_set(dptr_bmap, dptr->dnum);
474 dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
476 dptr->ptr = conn->dirptr;
477 string_set(&dptr->path,path);
480 dptr->expect_close = expect_close;
481 dptr->wcard = NULL; /* Only used in lanman2 searches */
482 dptr->attr = 0; /* Only used in lanman2 searches */
484 DLIST_ADD(dirptrs, dptr);
486 DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
487 dptr->dnum,path,expect_close));
492 /****************************************************************************
493 Fill the 5 byte server reserved dptr field.
494 ****************************************************************************/
496 BOOL dptr_fill(char *buf1,unsigned int key)
498 unsigned char *buf = (unsigned char *)buf1;
499 void *p = dptr_ptr(key);
502 DEBUG(1,("filling null dirptr %d\n",key));
506 DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
507 (long)p,(int)offset));
509 SIVAL(buf,1,offset | DPTR_MASK);
513 /****************************************************************************
514 Fetch the dir ptr and seek it given the 5 byte server field.
515 ****************************************************************************/
517 void *dptr_fetch(char *buf,int *num)
519 unsigned int key = *(unsigned char *)buf;
520 void *p = dptr_ptr(key);
523 DEBUG(3,("fetched null dirptr %d\n",key));
527 offset = IVAL(buf,1)&~DPTR_MASK;
529 DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
530 key,dptr_path(key),offset));
534 /****************************************************************************
536 ****************************************************************************/
538 void *dptr_fetch_lanman2(int dptr_num)
540 void *p = dptr_ptr(dptr_num);
543 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
546 DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
550 /****************************************************************************
551 Check a filetype for being valid.
552 ****************************************************************************/
554 BOOL dir_check_ftype(connection_struct *conn,int mode,SMB_STRUCT_STAT *st,int dirtype)
556 if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
561 static BOOL mangle_mask_match(connection_struct *conn, char *filename, char *mask)
563 mangle_map(filename,True,False,SNUM(conn));
564 return mask_match(filename,mask,False);
567 /****************************************************************************
568 Get an 8.3 directory entry.
569 ****************************************************************************/
571 BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname,
572 SMB_OFF_T *size,int *mode,time_t *date,BOOL check_descend)
576 SMB_STRUCT_STAT sbuf;
583 *path = *pathreal = *filename = 0;
585 isrootdir = (strequal(conn->dirpath,"./") ||
586 strequal(conn->dirpath,".") ||
587 strequal(conn->dirpath,"/"));
589 needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
596 dname = ReadDirName(conn->dirptr);
598 DEBUG(6,("readdir on dirptr 0x%lx now at offset %d\n",
599 (long)conn->dirptr,TellDir(conn->dirptr)));
604 pstrcpy(filename,dname);
606 /* notice the special *.* handling. This appears to be the only difference
607 between the wildcard handling in this routine and in the trans2 routines.
608 see masktest for a demo
610 if ((strcmp(mask,"*.*") == 0) ||
611 mask_match(filename,mask,False) ||
612 mangle_mask_match(conn,filename,mask))
614 if (isrootdir && (strequal(filename,"..") || strequal(filename,".")))
617 if (!mangle_is_8_3(filename, False)) {
618 mangle_map(filename,True,False,SNUM(conn));
621 pstrcpy(fname,filename);
623 pstrcpy(path,conn->dirpath);
626 pstrcpy(pathreal,path);
628 pstrcat(pathreal,dname);
629 if (conn->vfs_ops.stat(conn, pathreal, &sbuf) != 0)
631 DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) ));
635 *mode = dos_mode(conn,pathreal,&sbuf);
637 if (!dir_check_ftype(conn,*mode,&sbuf,dirtype))
639 DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype));
643 *size = sbuf.st_size;
644 *date = sbuf.st_mtime;
646 DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
666 /*******************************************************************
667 Check to see if a user can read a file. This is only approximate,
668 it is used as part of the "hide unreadable" option. Don't
669 use it for anything security sensitive.
670 ********************************************************************/
672 static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
674 extern struct current_user current_user;
675 SEC_DESC *psd = NULL;
681 uint32 access_granted;
684 * If user is a member of the Admin group
685 * we never hide files from them.
688 if (conn->admin_user)
691 /* If we can't stat it does not show it */
692 if (!VALID_STAT(*pst) && (vfs_stat(conn, name, pst) != 0))
695 /* Pseudo-open the file (note - no fd's created). */
697 if(S_ISDIR(pst->st_mode))
698 fsp = open_directory(conn, name, pst, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
699 unix_mode(conn,aRONLY|aDIR, name), &smb_action);
701 fsp = open_file_shared1(conn, name, pst, FILE_READ_ATTRIBUTES, SET_DENY_MODE(DENY_NONE),
702 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
707 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
708 sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd);
709 close_file(fsp, False);
711 /* No access if SD get failed. */
715 return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA,
716 &access_granted, &status);
719 /*******************************************************************
720 Check to see if a user can write a file (and only files, we do not
721 check dirs on this one). This is only approximate,
722 it is used as part of the "hide unwriteable" option. Don't
723 use it for anything security sensitive.
724 ********************************************************************/
726 static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
728 extern struct current_user current_user;
729 SEC_DESC *psd = NULL;
735 uint32 access_granted;
738 * If user is a member of the Admin group
739 * we never hide files from them.
742 if (conn->admin_user)
745 /* If we can't stat it does not show it */
746 if (!VALID_STAT(*pst) && (vfs_stat(conn, name, pst) != 0))
749 /* Pseudo-open the file (note - no fd's created). */
751 if(S_ISDIR(pst->st_mode))
754 fsp = open_file_shared1(conn, name, pst, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE),
755 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
760 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
761 sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd);
762 close_file(fsp, False);
764 /* No access if SD get failed. */
768 return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA,
769 &access_granted, &status);
772 /*******************************************************************
773 Is a file a "special" type ?
774 ********************************************************************/
776 static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
779 * If user is a member of the Admin group
780 * we never hide files from them.
783 if (conn->admin_user)
786 /* If we can't stat it does not show it */
787 if (!VALID_STAT(*pst) && (vfs_stat(conn, name, pst) != 0))
790 if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
796 /*******************************************************************
798 ********************************************************************/
800 void *OpenDir(connection_struct *conn, char *name, BOOL use_veto)
804 DIR *p = conn->vfs_ops.opendir(conn,name);
809 dirp = (Dir *)malloc(sizeof(Dir));
811 DEBUG(0,("Out of memory in OpenDir\n"));
812 conn->vfs_ops.closedir(conn,p);
815 dirp->pos = dirp->numentries = dirp->mallocsize = 0;
816 dirp->data = dirp->current = NULL;
820 BOOL normal_entry = True;
826 normal_entry = False;
827 } else if (used == 2) {
829 normal_entry = False;
831 n = vfs_readdirname(conn, p);
834 if ((strcmp(".",n) == 0) ||(strcmp("..",n) == 0))
842 /* If it's a vetoed file, pretend it doesn't even exist */
843 if (normal_entry && use_veto && conn && IS_VETO_PATH(conn, n))
846 /* Honour _hide unreadable_ option */
847 if (normal_entry && conn && lp_hideunreadable(SNUM(conn))) {
850 if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) {
851 ret = user_can_read_file(conn, entry, &st);
859 /* Honour _hide unwriteable_ option */
860 if (normal_entry && conn && lp_hideunwriteable_files(SNUM(conn))) {
863 if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) {
864 ret = user_can_write_file(conn, entry, &st);
872 /* Honour _hide_special_ option */
873 if (normal_entry && conn && lp_hide_special_files(SNUM(conn))) {
876 if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) {
877 ret = file_is_special(conn, entry, &st);
887 if (used + l > dirp->mallocsize) {
888 int s = MAX(used+l,used+2000);
890 r = (char *)Realloc(dirp->data,s);
892 DEBUG(0,("Out of memory in OpenDir\n"));
896 dirp->mallocsize = s;
897 dirp->current = dirp->data;
900 pstrcpy(dirp->data+used,n);
905 conn->vfs_ops.closedir(conn,p);
906 return((void *)dirp);
910 /*******************************************************************
912 ********************************************************************/
914 void CloseDir(void *p)
917 SAFE_FREE(((Dir *)p)->data);
921 /*******************************************************************
922 Read from a directory.
923 ********************************************************************/
925 char *ReadDirName(void *p)
928 Dir *dirp = (Dir *)p;
930 if (!dirp || !dirp->current || dirp->pos >= dirp->numentries) return(NULL);
933 dirp->current = skip_string(dirp->current,1);
940 /*******************************************************************
942 ********************************************************************/
944 BOOL SeekDir(void *p,int pos)
946 Dir *dirp = (Dir *)p;
948 if (!dirp) return(False);
950 if (pos < dirp->pos) {
951 dirp->current = dirp->data;
955 while (dirp->pos < pos && ReadDirName(p)) ;
957 return(dirp->pos == pos);
960 /*******************************************************************
962 ********************************************************************/
966 Dir *dirp = (Dir *)p;
968 if (!dirp) return(-1);
973 /*******************************************************************************
974 This section manages a global directory cache.
975 (It should probably be split into a separate module. crh)
976 ********************************************************************************/
986 static ubi_dlNewList( dir_cache );
988 /*****************************************************************************
989 Add an entry to the directory cache.
995 *****************************************************************************/
997 void DirCacheAdd( char *path, char *name, char *dname, int snum )
1001 dir_cache_entry *entry;
1003 /* Allocate the structure & string space in one go so that it can be freed
1004 * in one call to free().
1006 pathlen = strlen( path ) +1; /* Bytes required to store path (with nul). */
1007 namelen = strlen( name ) +1; /* Bytes required to store name (with nul). */
1008 entry = (dir_cache_entry *)malloc( sizeof( dir_cache_entry )
1011 + strlen( dname ) +1 );
1012 if( NULL == entry ) /* Not adding to the cache is not fatal, */
1013 return; /* so just return as if nothing happened. */
1015 /* Set pointers correctly and load values. */
1016 entry->path = pstrcpy( (char *)&entry[1], path);
1017 entry->name = pstrcpy( &(entry->path[pathlen]), name);
1018 entry->dname = pstrcpy( &(entry->name[namelen]), dname);
1021 /* Add the new entry to the linked list. */
1022 (void)ubi_dlAddHead( dir_cache, entry );
1023 DEBUG( 4, ("Added dir cache entry %s %s -> %s\n", path, name, dname ) );
1025 /* Free excess cache entries. */
1026 while( DIRCACHESIZE < dir_cache->count )
1027 safe_free( ubi_dlRemTail( dir_cache ) );
1031 /*****************************************************************************
1032 Search for an entry to the directory cache.
1036 Output: The dname string of the located entry, or NULL if the entry was
1039 Notes: This uses a linear search, which is is okay because of
1040 the small size of the cache. Use a splay tree or hash
1042 *****************************************************************************/
1044 char *DirCacheCheck( char *path, char *name, int snum )
1046 dir_cache_entry *entry;
1048 for( entry = (dir_cache_entry *)ubi_dlFirst( dir_cache );
1050 entry = (dir_cache_entry *)ubi_dlNext( entry ) )
1052 if( entry->snum == snum
1053 && 0 == strcmp( name, entry->name )
1054 && 0 == strcmp( path, entry->path ) )
1056 DEBUG(4, ("Got dir cache hit on %s %s -> %s\n",path,name,entry->dname));
1057 return( entry->dname );
1064 /*****************************************************************************
1065 Remove all cache entries which have an snum that matches the input.
1068 *****************************************************************************/
1070 void DirCacheFlush(int snum)
1072 dir_cache_entry *entry;
1075 for(entry = (dir_cache_entry *)ubi_dlFirst( dir_cache );
1077 next = ubi_dlNext( entry );
1078 if( entry->snum == snum )
1079 safe_free( ubi_dlRemThis( dir_cache, entry ) );
1080 entry = (dir_cache_entry *)next;