r25111: Move to talloced pathnames on most code paths.
[Samba/gebeck_regimport.git] / source3 / smbd / dir.c
blob7a6815b680633a5fd9b04d7bc751adf42f73d5fb
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 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/>.
20 #include "includes.h"
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 {
36 char *name;
37 long offset;
40 struct smb_Dir {
41 connection_struct *conn;
42 SMB_STRUCT_DIR *dir;
43 long offset;
44 char *dir_path;
45 size_t name_cache_size;
46 struct name_cache_entry *name_cache;
47 unsigned int name_cache_index;
48 unsigned int file_number;
51 struct dptr_struct {
52 struct dptr_struct *next, *prev;
53 int dnum;
54 uint16 spid;
55 struct connection_struct *conn;
56 struct smb_Dir *dir_hnd;
57 BOOL expect_close;
58 char *wcard;
59 uint32 attr;
60 char *path;
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 /****************************************************************************
72 Make a dir struct.
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)
77 char *p;
78 pstring mask2;
80 pstrcpy(mask2,mask);
82 if ((mode & aDIR) != 0)
83 size = 0;
85 memset(buf+1,' ',11);
86 if ((p = strchr_m(mask2,'.')) != NULL) {
87 *p = 0;
88 push_ascii(buf+1,mask2,8, 0);
89 push_ascii(buf+9,p+1,3, 0);
90 *p = '.';
91 } else
92 push_ascii(buf+1,mask2,11, 0);
94 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
95 SCVAL(buf,21,mode);
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;
113 if (dptrs_init)
114 return;
116 dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES);
118 if (!dptr_bmap)
119 exit_server("out of memory in init_dptrs");
121 dptrs_init = True;
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)
130 if (dptr->dir_hnd) {
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)
151 if(!dptr) {
152 DEBUG(0,("No dptrs available to idle ?\n"));
153 return;
157 * Idle the oldest pointer.
160 for(; dptr; dptr = dptr->prev) {
161 if (dptr->dir_hnd) {
162 dptr_idle(dptr);
163 return;
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)
180 dptr_idleoldest();
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,
184 strerror(errno)));
185 return False;
188 DLIST_PROMOTE(dirptrs,dptr);
189 return dptr;
192 return(NULL);
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);
202 if (dptr)
203 return(dptr->path);
204 return(NULL);
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);
214 if (dptr)
215 return(dptr->wcard);
216 return(NULL);
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);
226 if (dptr)
227 return(dptr->attr);
228 return(0);
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",
248 dptr->dnum ));
251 bitmap_clear(dptr_bmap, dptr->dnum - 1);
253 if (dptr->dir_hnd) {
254 CloseDir(dptr->dir_hnd);
257 /* Lanman 2 specific code */
258 SAFE_FREE(dptr->wcard);
259 string_set(&dptr->path,"");
260 SAFE_FREE(dptr);
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)
272 return;
274 /* OS/2 seems to use -1 to indicate "close all directories" */
275 if (*key == -1) {
276 struct dptr_struct *next;
277 for(dptr = dirptrs; dptr; dptr = next) {
278 next = dptr->next;
279 dptr_close_internal(dptr);
281 *key = INVALID_DPTR_KEY;
282 return;
285 dptr = dptr_get(*key, True);
287 if (!dptr) {
288 DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
289 return;
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) {
305 next = 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)
320 dptr_idle(dptr);
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) {
332 next = 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)
354 if(!dptr) {
355 DEBUG(0,("No old dptrs available to close oldest ?\n"));
356 return;
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);
369 return;
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;
388 NTSTATUS status;
390 DEBUG(5,("dptr_create dir=%s\n", path));
392 if (!wcard) {
393 return NT_STATUS_INVALID_PARAMETER;
396 status = check_name(conn,path);
397 if (!NT_STATUS_IS_OK(status)) {
398 return status;
401 dir_hnd = OpenDir(conn, path, wcard, attr);
402 if (!dir_hnd) {
403 return map_nt_error_from_unix(errno);
406 string_set(&conn->dirpath,path);
408 if (dirhandles_open >= MAX_OPEN_DIRECTORIES) {
409 dptr_idleoldest();
412 dptr = SMB_MALLOC_P(struct dptr_struct);
413 if(!dptr) {
414 DEBUG(0,("malloc fail in dptr_create.\n"));
415 CloseDir(dir_hnd);
416 return NT_STATUS_NO_MEMORY;
419 ZERO_STRUCTP(dptr);
421 if(old_handle) {
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));
444 SAFE_FREE(dptr);
445 CloseDir(dir_hnd);
446 return NT_STATUS_TOO_MANY_OPENED_FILES;
449 } else {
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
464 * directory handles.
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));
474 SAFE_FREE(dptr);
475 CloseDir(dir_hnd);
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);
486 dptr->conn = conn;
487 dptr->dir_hnd = dir_hnd;
488 dptr->spid = spid;
489 dptr->expect_close = expect_close;
490 dptr->wcard = SMB_STRDUP(wcard);
491 if (!dptr->wcard) {
492 bitmap_clear(dptr_bmap, dptr->dnum - 1);
493 SAFE_FREE(dptr);
494 CloseDir(dir_hnd);
495 return NT_STATUS_NO_MEMORY;
497 if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) {
498 dptr->has_wild = True;
499 } else {
500 dptr->has_wild = wcard_has_wild;
503 dptr->attr = attr;
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));
510 *dptr_ret = dptr;
512 return NT_STATUS_OK;
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)
543 return dptr->dnum;
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. */
553 const char *name;
554 while ((name = ReadDirName(dptr->dir_hnd, poffset)) != NULL) {
555 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
556 return name;
559 return NULL;
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) {
577 return NULL;
580 if (!dptr->did_stat) {
581 pstring pathreal;
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;
595 return NULL;
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;
602 return dptr->wcard;
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;
613 return dptr->wcard;
614 } else {
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;
621 return dptr->wcard;
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;
632 return NULL;
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;
649 return False;
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);
672 uint32 offset;
673 if (!dptr) {
674 DEBUG(1,("filling null dirptr %d\n",key));
675 return(False);
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));
680 buf[0] = key;
681 SIVAL(buf,1,offset);
682 return(True);
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);
693 uint32 offset;
694 long seekoff;
696 if (!dptr) {
697 DEBUG(3,("fetched null dirptr %d\n",key));
698 return(NULL);
700 *num = key;
701 offset = IVAL(buf,1);
702 if (offset == (uint32)-1) {
703 seekoff = END_OF_DIRECTORY_OFFSET;
704 } else {
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));
710 return(dptr);
713 /****************************************************************************
714 Fetch the dir ptr.
715 ****************************************************************************/
717 struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
719 struct dptr_struct *dptr = dptr_get(dptr_num, False);
721 if (!dptr) {
722 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
723 return(NULL);
725 DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
726 return(dptr);
729 /****************************************************************************
730 Check that a file matches a particular file type.
731 ****************************************************************************/
733 BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype)
735 uint32 mask;
737 /* Check the "may have" search bits. */
738 if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
739 return False;
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 */
745 if(mask) {
746 if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask) /* check if matching attribute present */
747 return True;
748 else
749 return False;
752 return True;
755 static BOOL mangle_mask_match(connection_struct *conn,
756 const char *filename,
757 const char *mask)
759 char mname[13];
761 if (!name_to_8_3(filename,mname,False,conn->params)) {
762 return False;
764 return mask_match_search(mname,mask,False);
767 /****************************************************************************
768 Get an 8.3 directory entry.
769 ****************************************************************************/
771 BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fname,
772 SMB_OFF_T *size,uint32 *mode,time_t *date,BOOL check_descend)
774 const char *dname;
775 BOOL found = False;
776 SMB_STRUCT_STAT sbuf;
777 pstring path;
778 pstring pathreal;
779 pstring filename;
780 BOOL needslash;
782 *path = *pathreal = *filename = 0;
784 needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
786 if (!conn->dirptr)
787 return(False);
789 while (!found) {
790 long curoff = dptr_TellDir(conn->dirptr);
791 dname = dptr_ReadDirName(conn->dirptr, &curoff, &sbuf);
793 DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
794 (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
796 if (dname == NULL)
797 return(False);
799 pstrcpy(filename,dname);
801 /* notice the special *.* handling. This appears to be the only difference
802 between the wildcard handling in this routine and in the trans2 routines.
803 see masktest for a demo
805 if ((strcmp(mask,"*.*") == 0) ||
806 mask_match_search(filename,mask,False) ||
807 mangle_mask_match(conn,filename,mask)) {
809 if (!mangle_is_8_3(filename, False, conn->params)) {
810 char mname[13];
811 if (!name_to_8_3(filename,mname,False,
812 conn->params)) {
813 continue;
815 pstrcpy(filename,mname);
818 pstrcpy(fname,filename);
819 *path = 0;
820 pstrcpy(path,conn->dirpath);
821 if(needslash)
822 pstrcat(path,"/");
823 pstrcpy(pathreal,path);
824 pstrcat(path,fname);
825 pstrcat(pathreal,dname);
826 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
827 DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) ));
828 continue;
831 *mode = dos_mode(conn,pathreal,&sbuf);
833 if (!dir_check_ftype(conn,*mode,dirtype)) {
834 DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",filename,(unsigned int)*mode,(unsigned int)dirtype));
835 continue;
838 *size = sbuf.st_size;
839 *date = sbuf.st_mtime;
841 DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
843 found = True;
845 DirCacheAdd(conn->dirptr->dir_hnd, dname, curoff);
849 return(found);
852 /*******************************************************************
853 Check to see if a user can read a file. This is only approximate,
854 it is used as part of the "hide unreadable" option. Don't
855 use it for anything security sensitive.
856 ********************************************************************/
858 static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
860 SEC_DESC *psd = NULL;
861 size_t sd_size;
862 files_struct *fsp;
863 NTSTATUS status;
864 uint32 access_granted;
867 * If user is a member of the Admin group
868 * we never hide files from them.
871 if (conn->admin_user) {
872 return True;
875 /* If we can't stat it does not show it */
876 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) {
877 DEBUG(10,("user_can_read_file: SMB_VFS_STAT failed for file %s with error %s\n",
878 name, strerror(errno) ));
879 return False;
882 /* Pseudo-open the file (note - no fd's created). */
884 if(S_ISDIR(pst->st_mode)) {
885 status = open_directory(conn, NULL, name, pst,
886 READ_CONTROL_ACCESS,
887 FILE_SHARE_READ|FILE_SHARE_WRITE,
888 FILE_OPEN,
889 0, /* no create options. */
890 FILE_ATTRIBUTE_DIRECTORY,
891 NULL, &fsp);
892 } else {
893 status = open_file_stat(conn, NULL, name, pst, &fsp);
896 if (!NT_STATUS_IS_OK(status)) {
897 return False;
900 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
901 sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd,
902 (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
903 close_file(fsp, NORMAL_CLOSE);
905 /* No access if SD get failed. */
906 if (!sd_size) {
907 return False;
910 return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA,
911 &access_granted, &status);
914 /*******************************************************************
915 Check to see if a user can write a file (and only files, we do not
916 check dirs on this one). This is only approximate,
917 it is used as part of the "hide unwriteable" option. Don't
918 use it for anything security sensitive.
919 ********************************************************************/
921 static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
923 SEC_DESC *psd = NULL;
924 size_t sd_size;
925 files_struct *fsp;
926 int info;
927 NTSTATUS status;
928 uint32 access_granted;
931 * If user is a member of the Admin group
932 * we never hide files from them.
935 if (conn->admin_user) {
936 return True;
939 /* If we can't stat it does not show it */
940 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) {
941 return False;
944 /* Pseudo-open the file */
946 if(S_ISDIR(pst->st_mode)) {
947 return True;
948 } else {
949 status = open_file_ntcreate(conn, NULL, name, pst,
950 FILE_WRITE_ATTRIBUTES,
951 FILE_SHARE_READ|FILE_SHARE_WRITE,
952 FILE_OPEN,
954 FILE_ATTRIBUTE_NORMAL,
955 INTERNAL_OPEN_ONLY,
956 &info, &fsp);
959 if (!NT_STATUS_IS_OK(status)) {
960 return False;
963 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
964 sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd,
965 (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
966 close_file(fsp, NORMAL_CLOSE);
968 /* No access if SD get failed. */
969 if (!sd_size)
970 return False;
972 return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA,
973 &access_granted, &status);
976 /*******************************************************************
977 Is a file a "special" type ?
978 ********************************************************************/
980 static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
983 * If user is a member of the Admin group
984 * we never hide files from them.
987 if (conn->admin_user)
988 return False;
990 /* If we can't stat it does not show it */
991 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
992 return True;
994 if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
995 return False;
997 return True;
1000 /*******************************************************************
1001 Should the file be seen by the client ?
1002 ********************************************************************/
1004 BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, BOOL use_veto)
1006 BOOL hide_unreadable = lp_hideunreadable(SNUM(conn));
1007 BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
1008 BOOL hide_special = lp_hide_special_files(SNUM(conn));
1010 SET_STAT_INVALID(*pst);
1012 if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
1013 return True; /* . and .. are always visible. */
1016 /* If it's a vetoed file, pretend it doesn't even exist */
1017 if (use_veto && IS_VETO_PATH(conn, name)) {
1018 DEBUG(10,("is_visible_file: file %s is vetoed.\n", name ));
1019 return False;
1022 if (hide_unreadable || hide_unwriteable || hide_special) {
1023 char *entry = NULL;
1025 if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
1026 return False;
1029 /* If it's a dfs symlink, ignore _hide xxxx_ options */
1030 if (lp_host_msdfs() &&
1031 lp_msdfs_root(SNUM(conn)) &&
1032 is_msdfs_link(conn, entry, NULL)) {
1033 SAFE_FREE(entry);
1034 return True;
1037 /* Honour _hide unreadable_ option */
1038 if (hide_unreadable && !user_can_read_file(conn, entry, pst)) {
1039 DEBUG(10,("is_visible_file: file %s is unreadable.\n", entry ));
1040 SAFE_FREE(entry);
1041 return False;
1043 /* Honour _hide unwriteable_ option */
1044 if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
1045 DEBUG(10,("is_visible_file: file %s is unwritable.\n", entry ));
1046 SAFE_FREE(entry);
1047 return False;
1049 /* Honour _hide_special_ option */
1050 if (hide_special && file_is_special(conn, entry, pst)) {
1051 DEBUG(10,("is_visible_file: file %s is special.\n", entry ));
1052 SAFE_FREE(entry);
1053 return False;
1055 SAFE_FREE(entry);
1057 return True;
1060 /*******************************************************************
1061 Open a directory.
1062 ********************************************************************/
1064 struct smb_Dir *OpenDir(connection_struct *conn, const char *name, const char *mask, uint32 attr)
1066 struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir);
1068 if (!dirp) {
1069 return NULL;
1071 ZERO_STRUCTP(dirp);
1073 dirp->conn = conn;
1074 dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
1076 dirp->dir_path = SMB_STRDUP(name);
1077 if (!dirp->dir_path) {
1078 goto fail;
1080 dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
1081 if (!dirp->dir) {
1082 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) ));
1083 goto fail;
1086 if (dirp->name_cache_size) {
1087 dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry,
1088 dirp->name_cache_size);
1089 if (!dirp->name_cache) {
1090 goto fail;
1092 } else {
1093 dirp->name_cache = NULL;
1096 dirhandles_open++;
1097 return dirp;
1099 fail:
1101 if (dirp) {
1102 if (dirp->dir) {
1103 SMB_VFS_CLOSEDIR(conn,dirp->dir);
1105 SAFE_FREE(dirp->dir_path);
1106 SAFE_FREE(dirp->name_cache);
1107 SAFE_FREE(dirp);
1109 return NULL;
1113 /*******************************************************************
1114 Close a directory.
1115 ********************************************************************/
1117 int CloseDir(struct smb_Dir *dirp)
1119 int i, ret = 0;
1121 if (dirp->dir) {
1122 ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1124 SAFE_FREE(dirp->dir_path);
1125 if (dirp->name_cache) {
1126 for (i = 0; i < dirp->name_cache_size; i++) {
1127 SAFE_FREE(dirp->name_cache[i].name);
1130 SAFE_FREE(dirp->name_cache);
1131 SAFE_FREE(dirp);
1132 dirhandles_open--;
1133 return ret;
1136 /*******************************************************************
1137 Read from a directory. Also return current offset.
1138 Don't check for veto or invisible files.
1139 ********************************************************************/
1141 const char *ReadDirName(struct smb_Dir *dirp, long *poffset)
1143 const char *n;
1144 connection_struct *conn = dirp->conn;
1146 /* Cheat to allow . and .. to be the first entries returned. */
1147 if (((*poffset == START_OF_DIRECTORY_OFFSET) || (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2)) {
1148 if (dirp->file_number == 0) {
1149 n = ".";
1150 *poffset = dirp->offset = START_OF_DIRECTORY_OFFSET;
1151 } else {
1152 *poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET;
1153 n = "..";
1155 dirp->file_number++;
1156 return n;
1157 } else if (*poffset == END_OF_DIRECTORY_OFFSET) {
1158 *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1159 return NULL;
1160 } else {
1161 /* A real offset, seek to it. */
1162 SeekDir(dirp, *poffset);
1165 while ((n = vfs_readdirname(conn, dirp->dir))) {
1166 /* Ignore . and .. - we've already returned them. */
1167 if (*n == '.') {
1168 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
1169 continue;
1172 *poffset = dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1173 dirp->file_number++;
1174 return n;
1176 *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1177 return NULL;
1180 /*******************************************************************
1181 Rewind to the start.
1182 ********************************************************************/
1184 void RewindDir(struct smb_Dir *dirp, long *poffset)
1186 SMB_VFS_REWINDDIR(dirp->conn, dirp->dir);
1187 dirp->file_number = 0;
1188 dirp->offset = START_OF_DIRECTORY_OFFSET;
1189 *poffset = START_OF_DIRECTORY_OFFSET;
1192 /*******************************************************************
1193 Seek a dir.
1194 ********************************************************************/
1196 void SeekDir(struct smb_Dir *dirp, long offset)
1198 if (offset != dirp->offset) {
1199 if (offset == START_OF_DIRECTORY_OFFSET) {
1200 RewindDir(dirp, &offset);
1202 * Ok we should really set the file number here
1203 * to 1 to enable ".." to be returned next. Trouble
1204 * is I'm worried about callers using SeekDir(dirp,0)
1205 * as equivalent to RewindDir(). So leave this alone
1206 * for now.
1208 } else if (offset == DOT_DOT_DIRECTORY_OFFSET) {
1209 RewindDir(dirp, &offset);
1211 * Set the file number to 2 - we want to get the first
1212 * real file entry (the one we return after "..")
1213 * on the next ReadDir.
1215 dirp->file_number = 2;
1216 } else if (offset == END_OF_DIRECTORY_OFFSET) {
1217 ; /* Don't seek in this case. */
1218 } else {
1219 SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1221 dirp->offset = offset;
1225 /*******************************************************************
1226 Tell a dir position.
1227 ********************************************************************/
1229 long TellDir(struct smb_Dir *dirp)
1231 return(dirp->offset);
1234 /*******************************************************************
1235 Add an entry into the dcache.
1236 ********************************************************************/
1238 void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
1240 struct name_cache_entry *e;
1242 if (!dirp->name_cache_size || !dirp->name_cache) {
1243 return;
1246 dirp->name_cache_index = (dirp->name_cache_index+1) %
1247 dirp->name_cache_size;
1248 e = &dirp->name_cache[dirp->name_cache_index];
1249 SAFE_FREE(e->name);
1250 e->name = SMB_STRDUP(name);
1251 e->offset = offset;
1254 /*******************************************************************
1255 Find an entry by name. Leave us at the offset after it.
1256 Don't check for veto or invisible files.
1257 ********************************************************************/
1259 BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1261 int i;
1262 const char *entry;
1263 connection_struct *conn = dirp->conn;
1265 /* Search back in the name cache. */
1266 if (dirp->name_cache_size && dirp->name_cache) {
1267 for (i = dirp->name_cache_index; i >= 0; i--) {
1268 struct name_cache_entry *e = &dirp->name_cache[i];
1269 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1270 *poffset = e->offset;
1271 SeekDir(dirp, e->offset);
1272 return True;
1275 for (i = dirp->name_cache_size - 1; i > dirp->name_cache_index; i--) {
1276 struct name_cache_entry *e = &dirp->name_cache[i];
1277 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1278 *poffset = e->offset;
1279 SeekDir(dirp, e->offset);
1280 return True;
1285 /* Not found in the name cache. Rewind directory and start from scratch. */
1286 SMB_VFS_REWINDDIR(conn, dirp->dir);
1287 dirp->file_number = 0;
1288 *poffset = START_OF_DIRECTORY_OFFSET;
1289 while ((entry = ReadDirName(dirp, poffset))) {
1290 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
1291 return True;
1294 return False;
1297 /*****************************************************************
1298 Is this directory empty ?
1299 *****************************************************************/
1301 NTSTATUS can_delete_directory(struct connection_struct *conn,
1302 const char *dirname)
1304 NTSTATUS status = NT_STATUS_OK;
1305 long dirpos = 0;
1306 const char *dname;
1307 struct smb_Dir *dir_hnd = OpenDir(conn, dirname, NULL, 0);
1309 if (!dir_hnd) {
1310 return map_nt_error_from_unix(errno);
1313 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
1314 SMB_STRUCT_STAT st;
1316 /* Quick check for "." and ".." */
1317 if (dname[0] == '.') {
1318 if (!dname[1] || (dname[1] == '.' && !dname[2])) {
1319 continue;
1323 if (!is_visible_file(conn, dirname, dname, &st, True)) {
1324 continue;
1327 DEBUG(10,("can_delete_directory: got name %s - can't delete\n", dname ));
1328 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1329 break;
1331 CloseDir(dir_hnd);
1333 return status;