r5152: Restructure the directory handling code, stop using void * pointers
[metze/samba/wip.git] / source3 / smbd / dir.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Directory handling routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    
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.
10    
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.
15    
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.
19 */
20
21 #include "includes.h"
22
23 /*
24    This module implements directory related functions for Samba.
25 */
26
27 /* Make directory handle internals available. */
28
29 #define NAME_CACHE_SIZE 100
30
31 struct name_cache_entry {
32         char *name;
33         long offset;
34 };
35
36 struct smb_Dir {
37         connection_struct *conn;
38         DIR *dir;
39         long offset;
40         char *dir_path;
41         struct name_cache_entry *name_cache;
42         unsigned int name_cache_index;
43         BOOL hide_unreadable;
44         BOOL hide_unwriteable;
45         BOOL hide_special;
46         BOOL use_veto;
47 };
48
49 struct dptr_struct {
50         struct dptr_struct *next, *prev;
51         int dnum;
52         uint16 spid;
53         struct connection_struct *conn;
54         struct smb_Dir *dir_hnd;
55         BOOL expect_close;
56         char *wcard;
57         uint16 attr;
58         char *path;
59         BOOL has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
60 };
61
62 static struct bitmap *dptr_bmap;
63 static struct dptr_struct *dirptrs;
64 static int dptrs_open = 0;
65
66 #define INVALID_DPTR_KEY (-3)
67
68 /****************************************************************************
69  Initialise the dir bitmap.
70 ****************************************************************************/
71
72 void init_dptrs(void)
73 {
74         static BOOL dptrs_init=False;
75
76         if (dptrs_init)
77                 return;
78
79         dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES);
80
81         if (!dptr_bmap)
82                 exit_server("out of memory in init_dptrs");
83
84         dptrs_init = True;
85 }
86
87 /****************************************************************************
88  Idle a dptr - the directory is closed but the control info is kept.
89 ****************************************************************************/
90
91 static void dptr_idle(struct dptr_struct *dptr)
92 {
93         if (dptr->dir_hnd) {
94                 DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
95                 CloseDir(dptr->dir_hnd);
96                 dptr->dir_hnd = NULL;
97         }
98 }
99
100 /****************************************************************************
101  Idle the oldest dptr.
102 ****************************************************************************/
103
104 static void dptr_idleoldest(void)
105 {
106         struct dptr_struct *dptr;
107
108         /*
109          * Go to the end of the list.
110          */
111         for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
112                 ;
113
114         if(!dptr) {
115                 DEBUG(0,("No dptrs available to idle ?\n"));
116                 return;
117         }
118
119         /*
120          * Idle the oldest pointer.
121          */
122
123         for(; dptr; dptr = dptr->prev) {
124                 if (dptr->dir_hnd) {
125                         dptr_idle(dptr);
126                         return;
127                 }
128         }
129 }
130
131 /****************************************************************************
132  Get the struct dptr_struct for a dir index.
133 ****************************************************************************/
134
135 static struct dptr_struct *dptr_get(int key, BOOL forclose)
136 {
137         struct dptr_struct *dptr;
138
139         for(dptr = dirptrs; dptr; dptr = dptr->next) {
140                 if(dptr->dnum == key) {
141                         if (!forclose && !dptr->dir_hnd) {
142                                 if (dptrs_open >= MAX_OPEN_DIRECTORIES)
143                                         dptr_idleoldest();
144                                 DEBUG(4,("dptr_get: Reopening dptr key %d\n",key));
145                                 if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path, True))) {
146                                         DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path,
147                                                 strerror(errno)));
148                                         return False;
149                                 }
150                         }
151                         DLIST_PROMOTE(dirptrs,dptr);
152                         return dptr;
153                 }
154         }
155         return(NULL);
156 }
157
158 /****************************************************************************
159  Get the dir path for a dir index.
160 ****************************************************************************/
161
162 char *dptr_path(int key)
163 {
164         struct dptr_struct *dptr = dptr_get(key, False);
165         if (dptr)
166                 return(dptr->path);
167         return(NULL);
168 }
169
170 /****************************************************************************
171  Get the dir wcard for a dir index.
172 ****************************************************************************/
173
174 char *dptr_wcard(int key)
175 {
176         struct dptr_struct *dptr = dptr_get(key, False);
177         if (dptr)
178                 return(dptr->wcard);
179         return(NULL);
180 }
181
182 /****************************************************************************
183  Get the dir attrib for a dir index.
184 ****************************************************************************/
185
186 uint16 dptr_attr(int key)
187 {
188         struct dptr_struct *dptr = dptr_get(key, False);
189         if (dptr)
190                 return(dptr->attr);
191         return(0);
192 }
193
194 /****************************************************************************
195  Set the dir wcard for a dir index.
196  Returns 0 on ok, 1 on fail.
197 ****************************************************************************/
198
199 BOOL dptr_set_wcard_and_attributes(int key, char *wcard, uint16 attr)
200 {
201         struct dptr_struct *dptr = dptr_get(key, False);
202
203         if (dptr) {
204                 dptr->attr = attr;
205                 dptr->wcard = wcard;
206                 dptr->has_wild = ms_has_wild(wcard);
207                 return True;
208         }
209         return False;
210 }
211
212 /****************************************************************************
213  Close a dptr (internal func).
214 ****************************************************************************/
215
216 static void dptr_close_internal(struct dptr_struct *dptr)
217 {
218         DEBUG(4,("closing dptr key %d\n",dptr->dnum));
219
220         DLIST_REMOVE(dirptrs, dptr);
221
222         /* 
223          * Free the dnum in the bitmap. Remember the dnum value is always 
224          * biased by one with respect to the bitmap.
225          */
226
227         if(bitmap_query( dptr_bmap, dptr->dnum - 1) != True) {
228                 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
229                         dptr->dnum ));
230         }
231
232         bitmap_clear(dptr_bmap, dptr->dnum - 1);
233
234         if (dptr->dir_hnd) {
235                 CloseDir(dptr->dir_hnd);
236         }
237
238         /* Lanman 2 specific code */
239         SAFE_FREE(dptr->wcard);
240         string_set(&dptr->path,"");
241         SAFE_FREE(dptr);
242 }
243
244 /****************************************************************************
245  Close a dptr given a key.
246 ****************************************************************************/
247
248 void dptr_close(int *key)
249 {
250         struct dptr_struct *dptr;
251
252         if(*key == INVALID_DPTR_KEY)
253                 return;
254
255         /* OS/2 seems to use -1 to indicate "close all directories" */
256         if (*key == -1) {
257                 struct dptr_struct *next;
258                 for(dptr = dirptrs; dptr; dptr = next) {
259                         next = dptr->next;
260                         dptr_close_internal(dptr);
261                 }
262                 *key = INVALID_DPTR_KEY;
263                 return;
264         }
265
266         dptr = dptr_get(*key, True);
267
268         if (!dptr) {
269                 DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
270                 return;
271         }
272
273         dptr_close_internal(dptr);
274
275         *key = INVALID_DPTR_KEY;
276 }
277
278 /****************************************************************************
279  Close all dptrs for a cnum.
280 ****************************************************************************/
281
282 void dptr_closecnum(connection_struct *conn)
283 {
284         struct dptr_struct *dptr, *next;
285         for(dptr = dirptrs; dptr; dptr = next) {
286                 next = dptr->next;
287                 if (dptr->conn == conn)
288                         dptr_close_internal(dptr);
289         }
290 }
291
292 /****************************************************************************
293  Idle all dptrs for a cnum.
294 ****************************************************************************/
295
296 void dptr_idlecnum(connection_struct *conn)
297 {
298         struct dptr_struct *dptr;
299         for(dptr = dirptrs; dptr; dptr = dptr->next) {
300                 if (dptr->conn == conn && dptr->dir_hnd)
301                         dptr_idle(dptr);
302         }
303 }
304
305 /****************************************************************************
306  Close a dptr that matches a given path, only if it matches the spid also.
307 ****************************************************************************/
308
309 void dptr_closepath(char *path,uint16 spid)
310 {
311         struct dptr_struct *dptr, *next;
312         for(dptr = dirptrs; dptr; dptr = next) {
313                 next = dptr->next;
314                 if (spid == dptr->spid && strequal(dptr->path,path))
315                         dptr_close_internal(dptr);
316         }
317 }
318
319 /****************************************************************************
320  Try and close the oldest handle not marked for
321  expect close in the hope that the client has
322  finished with that one.
323 ****************************************************************************/
324
325 static void dptr_close_oldest(BOOL old)
326 {
327         struct dptr_struct *dptr;
328
329         /*
330          * Go to the end of the list.
331          */
332         for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
333                 ;
334
335         if(!dptr) {
336                 DEBUG(0,("No old dptrs available to close oldest ?\n"));
337                 return;
338         }
339
340         /*
341          * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
342          * does not have expect_close set. If 'old' is false, close
343          * one of the new dnum handles.
344          */
345
346         for(; dptr; dptr = dptr->prev) {
347                 if ((old && (dptr->dnum < 256) && !dptr->expect_close) ||
348                         (!old && (dptr->dnum > 255))) {
349                                 dptr_close_internal(dptr);
350                                 return;
351                 }
352         }
353 }
354
355 /****************************************************************************
356  Create a new dir ptr. If the flag old_handle is true then we must allocate
357  from the bitmap range 0 - 255 as old SMBsearch directory handles are only
358  one byte long. If old_handle is false we allocate from the range
359  256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
360  a directory handle is never zero.
361 ****************************************************************************/
362
363 int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid)
364 {
365         struct dptr_struct *dptr = NULL;
366         struct smb_Dir *dir_hnd;
367         const char *dir2;
368
369         DEBUG(5,("dptr_create dir=%s\n", path));
370
371         if (!check_name(path,conn))
372                 return(-2); /* Code to say use a unix error return code. */
373
374         /* use a const pointer from here on */
375         dir2 = path;
376         if (!*dir2)
377                 dir2 = ".";
378
379         dir_hnd = OpenDir(conn, dir2, True);
380         if (!dir_hnd) {
381                 return (-2);
382         }
383
384         string_set(&conn->dirpath,dir2);
385
386         if (dptrs_open >= MAX_OPEN_DIRECTORIES)
387                 dptr_idleoldest();
388
389         dptr = SMB_MALLOC_P(struct dptr_struct);
390         if(!dptr) {
391                 DEBUG(0,("malloc fail in dptr_create.\n"));
392                 CloseDir(dir_hnd);
393                 return -1;
394         }
395
396         ZERO_STRUCTP(dptr);
397
398         if(old_handle) {
399
400                 /*
401                  * This is an old-style SMBsearch request. Ensure the
402                  * value we return will fit in the range 1-255.
403                  */
404
405                 dptr->dnum = bitmap_find(dptr_bmap, 0);
406
407                 if(dptr->dnum == -1 || dptr->dnum > 254) {
408
409                         /*
410                          * Try and close the oldest handle not marked for
411                          * expect close in the hope that the client has
412                          * finished with that one.
413                          */
414
415                         dptr_close_oldest(True);
416
417                         /* Now try again... */
418                         dptr->dnum = bitmap_find(dptr_bmap, 0);
419                         if(dptr->dnum == -1 || dptr->dnum > 254) {
420                                 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
421                                 SAFE_FREE(dptr);
422                                 CloseDir(dir_hnd);
423                                 return -1;
424                         }
425                 }
426         } else {
427
428                 /*
429                  * This is a new-style trans2 request. Allocate from
430                  * a range that will return 256 - MAX_DIRECTORY_HANDLES.
431                  */
432
433                 dptr->dnum = bitmap_find(dptr_bmap, 255);
434
435                 if(dptr->dnum == -1 || dptr->dnum < 255) {
436
437                         /*
438                          * Try and close the oldest handle close in the hope that
439                          * the client has finished with that one. This will only
440                          * happen in the case of the Win98 client bug where it leaks
441                          * directory handles.
442                          */
443
444                         dptr_close_oldest(False);
445
446                         /* Now try again... */
447                         dptr->dnum = bitmap_find(dptr_bmap, 255);
448
449                         if(dptr->dnum == -1 || dptr->dnum < 255) {
450                                 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
451                                 SAFE_FREE(dptr);
452                                 CloseDir(dir_hnd);
453                                 return -1;
454                         }
455                 }
456         }
457
458         bitmap_set(dptr_bmap, dptr->dnum);
459
460         dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
461
462         string_set(&dptr->path,dir2);
463         dptr->conn = conn;
464         dptr->dir_hnd = dir_hnd;
465         dptr->spid = spid;
466         dptr->expect_close = expect_close;
467         dptr->wcard = NULL; /* Only used in lanman2 searches */
468         dptr->attr = 0; /* Only used in lanman2 searches */
469         dptr->has_wild = True; /* Only used in lanman2 searches */
470
471         DLIST_ADD(dirptrs, dptr);
472
473         DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
474                 dptr->dnum,path,expect_close));  
475
476         conn->dirptr = dptr;
477
478         return(dptr->dnum);
479 }
480
481
482 /****************************************************************************
483  Wrapper functions to access the lower level directory handles.
484 ****************************************************************************/
485
486 int dptr_CloseDir(struct dptr_struct *dptr)
487 {
488         return CloseDir(dptr->dir_hnd);
489 }
490
491 const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset)
492 {
493         return ReadDirName(dptr->dir_hnd, poffset);
494 }
495
496 void dptr_SeekDir(struct dptr_struct *dptr, long offset)
497 {
498         SeekDir(dptr->dir_hnd, offset);
499 }
500
501 long dptr_TellDir(struct dptr_struct *dptr)
502 {
503         return TellDir(dptr->dir_hnd);
504 }
505
506 BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, BOOL case_sensitive)
507 {
508         return SearchDir(dptr->dir_hnd, name, poffset, case_sensitive);
509 }
510
511 /****************************************************************************
512  Fill the 5 byte server reserved dptr field.
513 ****************************************************************************/
514
515 BOOL dptr_fill(char *buf1,unsigned int key)
516 {
517         unsigned char *buf = (unsigned char *)buf1;
518         struct dptr_struct *dptr = dptr_get(key, False);
519         uint32 offset;
520         if (!dptr) {
521                 DEBUG(1,("filling null dirptr %d\n",key));
522                 return(False);
523         }
524         offset = TellDir(dptr->dir_hnd);
525         DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
526                 (long)dptr->dir_hnd,(int)offset));
527         buf[0] = key;
528         SIVAL(buf,1,offset | DPTR_MASK);
529         return(True);
530 }
531
532 /****************************************************************************
533  Fetch the dir ptr and seek it given the 5 byte server field.
534 ****************************************************************************/
535
536 struct dptr_struct *dptr_fetch(char *buf,int *num)
537 {
538         unsigned int key = *(unsigned char *)buf;
539         struct dptr_struct *dptr = dptr_get(key, False);
540         uint32 offset;
541
542         if (!dptr) {
543                 DEBUG(3,("fetched null dirptr %d\n",key));
544                 return(NULL);
545         }
546         *num = key;
547         offset = IVAL(buf,1)&~DPTR_MASK;
548         SeekDir(dptr->dir_hnd,(long)offset);
549         DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
550                 key,dptr_path(key),offset));
551         return(dptr);
552 }
553
554 /****************************************************************************
555  Fetch the dir ptr.
556 ****************************************************************************/
557
558 struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
559 {
560         struct dptr_struct *dptr  = dptr_get(dptr_num, False);
561
562         if (!dptr) {
563                 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
564                 return(NULL);
565         }
566         DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
567         return(dptr);
568 }
569
570 /****************************************************************************
571  Check a filetype for being valid.
572 ****************************************************************************/
573
574 BOOL dir_check_ftype(connection_struct *conn,int mode,SMB_STRUCT_STAT *st,int dirtype)
575 {
576         int mask;
577
578         /* Check the "may have" search bits. */
579         if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
580                 return False;
581
582         /* Check the "must have" bits, which are the may have bits shifted eight */
583         /* If must have bit is set, the file/dir can not be returned in search unless the matching
584                 file attribute is set */
585         mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */
586         if(mask) {
587                 if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask)   /* check if matching attribute present */
588                         return True;
589                 else
590                         return False;
591         }
592
593         return True;
594 }
595
596 static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask)
597 {
598         mangle_map(filename,True,False,SNUM(conn));
599         return mask_match(filename,mask,False);
600 }
601
602 /****************************************************************************
603  Get an 8.3 directory entry.
604 ****************************************************************************/
605
606 BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname,
607                    SMB_OFF_T *size,int *mode,time_t *date,BOOL check_descend)
608 {
609         const char *dname;
610         BOOL found = False;
611         SMB_STRUCT_STAT sbuf;
612         pstring path;
613         pstring pathreal;
614         BOOL isrootdir;
615         pstring filename;
616         BOOL needslash;
617
618         *path = *pathreal = *filename = 0;
619
620         isrootdir = (strequal(conn->dirpath,"./") ||
621                         strequal(conn->dirpath,".") ||
622                         strequal(conn->dirpath,"/"));
623   
624         needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
625
626         if (!conn->dirptr)
627                 return(False);
628
629         while (!found) {
630                 long curoff = TellDir(conn->dirptr->dir_hnd);
631                 dname = ReadDirName(conn->dirptr->dir_hnd, &curoff);
632
633                 DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
634                         (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
635       
636                 if (dname == NULL) 
637                         return(False);
638       
639                 pstrcpy(filename,dname);      
640
641                 /* notice the special *.* handling. This appears to be the only difference
642                         between the wildcard handling in this routine and in the trans2 routines.
643                         see masktest for a demo
644                 */
645                 if ((strcmp(mask,"*.*") == 0) ||
646                     mask_match(filename,mask,False) ||
647                     mangle_mask_match(conn,filename,mask)) {
648                         if (isrootdir && (strequal(filename,"..") || strequal(filename,".")))
649                                 continue;
650
651                         if (!mangle_is_8_3(filename, False))
652                                 mangle_map(filename,True,False,SNUM(conn));
653
654                         pstrcpy(fname,filename);
655                         *path = 0;
656                         pstrcpy(path,conn->dirpath);
657                         if(needslash)
658                                 pstrcat(path,"/");
659                         pstrcpy(pathreal,path);
660                         pstrcat(path,fname);
661                         pstrcat(pathreal,dname);
662                         if (SMB_VFS_STAT(conn, pathreal, &sbuf) != 0) {
663                                 DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) ));
664                                 continue;
665                         }
666           
667                         *mode = dos_mode(conn,pathreal,&sbuf);
668
669                         if (!dir_check_ftype(conn,*mode,&sbuf,dirtype)) {
670                                 DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype));
671                                 continue;
672                         }
673
674                         *size = sbuf.st_size;
675                         *date = sbuf.st_mtime;
676
677                         DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
678
679                         found = True;
680                 }
681         }
682
683         return(found);
684 }
685
686 /*******************************************************************
687  Check to see if a user can read a file. This is only approximate,
688  it is used as part of the "hide unreadable" option. Don't
689  use it for anything security sensitive.
690 ********************************************************************/
691
692 static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
693 {
694         extern struct current_user current_user;
695         SEC_DESC *psd = NULL;
696         size_t sd_size;
697         files_struct *fsp;
698         int smb_action;
699         NTSTATUS status;
700         uint32 access_granted;
701
702         /*
703          * If user is a member of the Admin group
704          * we never hide files from them.
705          */
706
707         if (conn->admin_user)
708                 return True;
709
710         /* If we can't stat it does not show it */
711         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
712                 return False;
713
714         /* Pseudo-open the file (note - no fd's created). */
715
716         if(S_ISDIR(pst->st_mode))       
717                  fsp = open_directory(conn, name, pst, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
718                         &smb_action);
719         else
720                 fsp = open_file_stat(conn, name, pst);
721
722         if (!fsp)
723                 return False;
724
725         /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
726         sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd,
727                         (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
728         close_file(fsp, True);
729
730         /* No access if SD get failed. */
731         if (!sd_size)
732                 return False;
733
734         return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA,
735                                  &access_granted, &status);
736 }
737
738 /*******************************************************************
739  Check to see if a user can write a file (and only files, we do not
740  check dirs on this one). This is only approximate,
741  it is used as part of the "hide unwriteable" option. Don't
742  use it for anything security sensitive.
743 ********************************************************************/
744
745 static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
746 {
747         extern struct current_user current_user;
748         SEC_DESC *psd = NULL;
749         size_t sd_size;
750         files_struct *fsp;
751         int smb_action;
752         int access_mode;
753         NTSTATUS status;
754         uint32 access_granted;
755
756         /*
757          * If user is a member of the Admin group
758          * we never hide files from them.
759          */
760
761         if (conn->admin_user)
762                 return True;
763
764         /* If we can't stat it does not show it */
765         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
766                 return False;
767
768         /* Pseudo-open the file (note - no fd's created). */
769
770         if(S_ISDIR(pst->st_mode))       
771                 return True;
772         else
773                 fsp = open_file_shared1(conn, name, pst, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE),
774                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY,
775                         &access_mode, &smb_action);
776
777         if (!fsp)
778                 return False;
779
780         /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
781         sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd,
782                         (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
783         close_file(fsp, False);
784
785         /* No access if SD get failed. */
786         if (!sd_size)
787                 return False;
788
789         return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA,
790                                  &access_granted, &status);
791 }
792
793 /*******************************************************************
794   Is a file a "special" type ?
795 ********************************************************************/
796
797 static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
798 {
799         /*
800          * If user is a member of the Admin group
801          * we never hide files from them.
802          */
803
804         if (conn->admin_user)
805                 return False;
806
807         /* If we can't stat it does not show it */
808         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
809                 return True;
810
811         if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
812                 return False;
813
814         return True;
815 }
816
817 /*******************************************************************
818  Open a directory.
819 ********************************************************************/
820
821 struct smb_Dir *OpenDir(connection_struct *conn, const char *name, BOOL use_veto)
822 {
823         struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir);
824         if (!dirp) {
825                 return NULL;
826         }
827         ZERO_STRUCTP(dirp);
828
829         dirp->conn = conn;
830         dirp->use_veto = use_veto;
831
832         dirp->dir_path = SMB_STRDUP(name);
833         if (!dirp->dir_path) {
834                 goto fail;
835         }
836         dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path);
837         if (!dirp->dir) {
838                 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) ));
839                 goto fail;
840         }
841
842         dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, NAME_CACHE_SIZE);
843         if (!dirp->name_cache) {
844                 goto fail;
845         }
846
847         dirp->hide_unreadable = lp_hideunreadable(SNUM(conn));
848         dirp->hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
849         dirp->hide_special = lp_hide_special_files(SNUM(conn));
850
851         dptrs_open++;
852         return dirp;
853
854   fail:
855
856         if (dirp) {
857                 if (dirp->dir) {
858                         SMB_VFS_CLOSEDIR(conn,dirp->dir);
859                 }
860                 SAFE_FREE(dirp->dir_path);
861                 SAFE_FREE(dirp->name_cache);
862                 SAFE_FREE(dirp);
863         }
864         return NULL;
865 }
866
867
868 /*******************************************************************
869  Close a directory.
870 ********************************************************************/
871
872 int CloseDir(struct smb_Dir *dirp)
873 {
874         int i, ret = 0;
875
876         if (dirp->dir) {
877                 ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
878         }
879         SAFE_FREE(dirp->dir_path);
880         if (dirp->name_cache) {
881                 for (i = 0; i < NAME_CACHE_SIZE; i++) {
882                         SAFE_FREE(dirp->name_cache[i].name);
883                 }
884         }
885         SAFE_FREE(dirp->name_cache);
886         SAFE_FREE(dirp);
887         dptrs_open--;
888         return ret;
889 }
890
891 /*******************************************************************
892  Read from a directory. Also return current offset.
893 ********************************************************************/
894
895 const char *ReadDirName(struct smb_Dir *dirp, long *poffset)
896 {
897         const char *n;
898         connection_struct *conn = dirp->conn;
899
900         SeekDir(dirp, *poffset);
901         while ((n = vfs_readdirname(conn, dirp->dir))) {
902                 struct name_cache_entry *e;
903
904                 if (!((strcmp(".",n) == 0) || (strcmp("..",n) == 0))) {
905                         /* If it's a vetoed file, pretend it doesn't even exist */
906                         if (dirp->use_veto && IS_VETO_PATH(conn, n)) {
907                                 continue;
908                         }
909
910                         if (dirp->hide_unreadable || dirp->hide_unwriteable || dirp->hide_special) {
911                                 SMB_STRUCT_STAT st;
912                                 char *entry = NULL;
913                                 ZERO_STRUCT(st);
914
915                                 if (asprintf(&entry, "%s/%s/%s", conn->origpath, dirp->dir_path, n) == -1) {
916                                         return NULL;
917                                 }
918                                 /* Honour _hide unreadable_ option */
919                                 if (dirp->hide_unreadable && !user_can_read_file(conn, entry, &st)) {
920                                         SAFE_FREE(entry);
921                                         continue;
922                                 }
923                                 /* Honour _hide unwriteable_ option */
924                                 if (dirp->hide_unwriteable && !user_can_write_file(conn, entry, &st)) {
925                                         SAFE_FREE(entry);
926                                         continue;
927                                 }
928                                 /* Honour _hide_special_ option */
929                                 if (dirp->hide_special && !file_is_special(conn, entry, &st)) {
930                                         SAFE_FREE(entry);
931                                         continue;
932                                 }
933                                 SAFE_FREE(entry);
934                         }
935                 }
936
937                 dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
938                 if (dirp->offset == -1) {
939                         return NULL;
940                 }
941                 dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE;
942
943                 e = &dirp->name_cache[dirp->name_cache_index];
944                 SAFE_FREE(e->name);
945                 e->name = SMB_STRDUP(n);
946                 *poffset = e->offset= dirp->offset;
947                 return e->name;
948         }
949         return NULL;
950 }
951
952 /*******************************************************************
953  Seek a dir.
954 ********************************************************************/
955
956 void SeekDir(struct smb_Dir *dirp, long offset)
957 {
958         if (offset != dirp->offset) {
959                 SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
960                 dirp->offset = offset;
961         }
962 }
963
964 /*******************************************************************
965  Tell a dir position.
966 ********************************************************************/
967
968 long TellDir(struct smb_Dir *dirp)
969 {
970         return(dirp->offset);
971 }
972
973 /*******************************************************************
974  Find an entry by name. Leave us at the offset after it.
975 ********************************************************************/
976
977 BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset, BOOL case_sensitive)
978 {
979         int i;
980         const char *entry;
981         connection_struct *conn = dirp->conn;
982
983         /* Search back in the name cache. */
984         for (i = dirp->name_cache_index; i >= 0; i--) {
985                 struct name_cache_entry *e = &dirp->name_cache[i];
986                 if (e->name && (case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
987                         *poffset = e->offset;
988                         SeekDir(dirp, e->offset);
989                         return True;
990                 }
991         }
992         for (i = NAME_CACHE_SIZE-1; i > dirp->name_cache_index; i--) {
993                 struct name_cache_entry *e = &dirp->name_cache[i];
994                 if (e->name && (case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
995                         *poffset = e->offset;
996                         SeekDir(dirp, e->offset);
997                         return True;
998                 }
999         }
1000
1001         /* Not found in the name cache. Rewind directory and start from scratch. */
1002         SMB_VFS_REWINDDIR(conn, dirp->dir);
1003         *poffset = 0;
1004         while ((entry = ReadDirName(dirp, poffset))) {
1005                 if (case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
1006                         return True;
1007                 }
1008         }
1009         return False;
1010 }