r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text
[tprouty/samba.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 3 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, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21
22 /*
23    This module implements directory related functions for Samba.
24 */
25
26 extern struct current_user current_user;
27
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)
32
33 /* Make directory handle internals available. */
34
35 #define NAME_CACHE_SIZE 100
36
37 struct name_cache_entry {
38         char *name;
39         long offset;
40 };
41
42 struct smb_Dir {
43         connection_struct *conn;
44         SMB_STRUCT_DIR *dir;
45         long offset;
46         char *dir_path;
47         struct name_cache_entry *name_cache;
48         unsigned int name_cache_index;
49         unsigned int file_number;
50 };
51
52 struct dptr_struct {
53         struct dptr_struct *next, *prev;
54         int dnum;
55         uint16 spid;
56         struct connection_struct *conn;
57         struct smb_Dir *dir_hnd;
58         BOOL expect_close;
59         char *wcard;
60         uint32 attr;
61         char *path;
62         BOOL has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
63         BOOL did_stat; /* Optimisation for non-wcard searches. */
64 };
65
66 static struct bitmap *dptr_bmap;
67 static struct dptr_struct *dirptrs;
68 static int dirhandles_open = 0;
69
70 #define INVALID_DPTR_KEY (-3)
71
72 /****************************************************************************
73  Make a dir struct.
74 ****************************************************************************/
75
76 void make_dir_struct(char *buf, const char *mask, const char *fname,SMB_OFF_T size,uint32 mode,time_t date, BOOL uc)
77 {  
78         char *p;
79         pstring mask2;
80
81         pstrcpy(mask2,mask);
82
83         if ((mode & aDIR) != 0)
84                 size = 0;
85
86         memset(buf+1,' ',11);
87         if ((p = strchr_m(mask2,'.')) != NULL) {
88                 *p = 0;
89                 push_ascii(buf+1,mask2,8, 0);
90                 push_ascii(buf+9,p+1,3, 0);
91                 *p = '.';
92         } else
93                 push_ascii(buf+1,mask2,11, 0);
94
95         memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
96         SCVAL(buf,21,mode);
97         srv_put_dos_date(buf,22,date);
98         SSVAL(buf,26,size & 0xFFFF);
99         SSVAL(buf,28,(size >> 16)&0xFFFF);
100         /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
101            Strange, but verified on W2K3. Needed for OS/2. JRA. */
102         push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
103         DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
104 }
105
106 /****************************************************************************
107  Initialise the dir bitmap.
108 ****************************************************************************/
109
110 void init_dptrs(void)
111 {
112         static BOOL dptrs_init=False;
113
114         if (dptrs_init)
115                 return;
116
117         dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES);
118
119         if (!dptr_bmap)
120                 exit_server("out of memory in init_dptrs");
121
122         dptrs_init = True;
123 }
124
125 /****************************************************************************
126  Idle a dptr - the directory is closed but the control info is kept.
127 ****************************************************************************/
128
129 static void dptr_idle(struct dptr_struct *dptr)
130 {
131         if (dptr->dir_hnd) {
132                 DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
133                 CloseDir(dptr->dir_hnd);
134                 dptr->dir_hnd = NULL;
135         }
136 }
137
138 /****************************************************************************
139  Idle the oldest dptr.
140 ****************************************************************************/
141
142 static void dptr_idleoldest(void)
143 {
144         struct dptr_struct *dptr;
145
146         /*
147          * Go to the end of the list.
148          */
149         for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
150                 ;
151
152         if(!dptr) {
153                 DEBUG(0,("No dptrs available to idle ?\n"));
154                 return;
155         }
156
157         /*
158          * Idle the oldest pointer.
159          */
160
161         for(; dptr; dptr = dptr->prev) {
162                 if (dptr->dir_hnd) {
163                         dptr_idle(dptr);
164                         return;
165                 }
166         }
167 }
168
169 /****************************************************************************
170  Get the struct dptr_struct for a dir index.
171 ****************************************************************************/
172
173 static struct dptr_struct *dptr_get(int key, BOOL forclose)
174 {
175         struct dptr_struct *dptr;
176
177         for(dptr = dirptrs; dptr; dptr = dptr->next) {
178                 if(dptr->dnum == key) {
179                         if (!forclose && !dptr->dir_hnd) {
180                                 if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
181                                         dptr_idleoldest();
182                                 DEBUG(4,("dptr_get: Reopening dptr key %d\n",key));
183                                 if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path, dptr->wcard, dptr->attr))) {
184                                         DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path,
185                                                 strerror(errno)));
186                                         return False;
187                                 }
188                         }
189                         DLIST_PROMOTE(dirptrs,dptr);
190                         return dptr;
191                 }
192         }
193         return(NULL);
194 }
195
196 /****************************************************************************
197  Get the dir path for a dir index.
198 ****************************************************************************/
199
200 char *dptr_path(int key)
201 {
202         struct dptr_struct *dptr = dptr_get(key, False);
203         if (dptr)
204                 return(dptr->path);
205         return(NULL);
206 }
207
208 /****************************************************************************
209  Get the dir wcard for a dir index.
210 ****************************************************************************/
211
212 char *dptr_wcard(int key)
213 {
214         struct dptr_struct *dptr = dptr_get(key, False);
215         if (dptr)
216                 return(dptr->wcard);
217         return(NULL);
218 }
219
220 /****************************************************************************
221  Get the dir attrib for a dir index.
222 ****************************************************************************/
223
224 uint16 dptr_attr(int key)
225 {
226         struct dptr_struct *dptr = dptr_get(key, False);
227         if (dptr)
228                 return(dptr->attr);
229         return(0);
230 }
231
232 /****************************************************************************
233  Close a dptr (internal func).
234 ****************************************************************************/
235
236 static void dptr_close_internal(struct dptr_struct *dptr)
237 {
238         DEBUG(4,("closing dptr key %d\n",dptr->dnum));
239
240         DLIST_REMOVE(dirptrs, dptr);
241
242         /* 
243          * Free the dnum in the bitmap. Remember the dnum value is always 
244          * biased by one with respect to the bitmap.
245          */
246
247         if(bitmap_query( dptr_bmap, dptr->dnum - 1) != True) {
248                 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
249                         dptr->dnum ));
250         }
251
252         bitmap_clear(dptr_bmap, dptr->dnum - 1);
253
254         if (dptr->dir_hnd) {
255                 CloseDir(dptr->dir_hnd);
256         }
257
258         /* Lanman 2 specific code */
259         SAFE_FREE(dptr->wcard);
260         string_set(&dptr->path,"");
261         SAFE_FREE(dptr);
262 }
263
264 /****************************************************************************
265  Close a dptr given a key.
266 ****************************************************************************/
267
268 void dptr_close(int *key)
269 {
270         struct dptr_struct *dptr;
271
272         if(*key == INVALID_DPTR_KEY)
273                 return;
274
275         /* OS/2 seems to use -1 to indicate "close all directories" */
276         if (*key == -1) {
277                 struct dptr_struct *next;
278                 for(dptr = dirptrs; dptr; dptr = next) {
279                         next = dptr->next;
280                         dptr_close_internal(dptr);
281                 }
282                 *key = INVALID_DPTR_KEY;
283                 return;
284         }
285
286         dptr = dptr_get(*key, True);
287
288         if (!dptr) {
289                 DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
290                 return;
291         }
292
293         dptr_close_internal(dptr);
294
295         *key = INVALID_DPTR_KEY;
296 }
297
298 /****************************************************************************
299  Close all dptrs for a cnum.
300 ****************************************************************************/
301
302 void dptr_closecnum(connection_struct *conn)
303 {
304         struct dptr_struct *dptr, *next;
305         for(dptr = dirptrs; dptr; dptr = next) {
306                 next = dptr->next;
307                 if (dptr->conn == conn)
308                         dptr_close_internal(dptr);
309         }
310 }
311
312 /****************************************************************************
313  Idle all dptrs for a cnum.
314 ****************************************************************************/
315
316 void dptr_idlecnum(connection_struct *conn)
317 {
318         struct dptr_struct *dptr;
319         for(dptr = dirptrs; dptr; dptr = dptr->next) {
320                 if (dptr->conn == conn && dptr->dir_hnd)
321                         dptr_idle(dptr);
322         }
323 }
324
325 /****************************************************************************
326  Close a dptr that matches a given path, only if it matches the spid also.
327 ****************************************************************************/
328
329 void dptr_closepath(char *path,uint16 spid)
330 {
331         struct dptr_struct *dptr, *next;
332         for(dptr = dirptrs; dptr; dptr = next) {
333                 next = dptr->next;
334                 if (spid == dptr->spid && strequal(dptr->path,path))
335                         dptr_close_internal(dptr);
336         }
337 }
338
339 /****************************************************************************
340  Try and close the oldest handle not marked for
341  expect close in the hope that the client has
342  finished with that one.
343 ****************************************************************************/
344
345 static void dptr_close_oldest(BOOL old)
346 {
347         struct dptr_struct *dptr;
348
349         /*
350          * Go to the end of the list.
351          */
352         for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
353                 ;
354
355         if(!dptr) {
356                 DEBUG(0,("No old dptrs available to close oldest ?\n"));
357                 return;
358         }
359
360         /*
361          * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
362          * does not have expect_close set. If 'old' is false, close
363          * one of the new dnum handles.
364          */
365
366         for(; dptr; dptr = dptr->prev) {
367                 if ((old && (dptr->dnum < 256) && !dptr->expect_close) ||
368                         (!old && (dptr->dnum > 255))) {
369                                 dptr_close_internal(dptr);
370                                 return;
371                 }
372         }
373 }
374
375 /****************************************************************************
376  Create a new dir ptr. If the flag old_handle is true then we must allocate
377  from the bitmap range 0 - 255 as old SMBsearch directory handles are only
378  one byte long. If old_handle is false we allocate from the range
379  256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
380  a directory handle is never zero.
381  wcard must not be zero.
382 ****************************************************************************/
383
384 NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid,
385                 const char *wcard, BOOL wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret)
386 {
387         struct dptr_struct *dptr = NULL;
388         struct smb_Dir *dir_hnd;
389         const char *dir2;
390         NTSTATUS status;
391
392         DEBUG(5,("dptr_create dir=%s\n", path));
393
394         if (!wcard) {
395                 return NT_STATUS_INVALID_PARAMETER;
396         }
397
398         status = check_name(conn,path);
399         if (!NT_STATUS_IS_OK(status)) {
400                 return status;
401         }
402
403         /* use a const pointer from here on */
404         dir2 = path;
405         if (!*dir2)
406                 dir2 = ".";
407
408         dir_hnd = OpenDir(conn, dir2, wcard, attr);
409         if (!dir_hnd) {
410                 return map_nt_error_from_unix(errno);
411         }
412
413         string_set(&conn->dirpath,dir2);
414
415         if (dirhandles_open >= MAX_OPEN_DIRECTORIES) {
416                 dptr_idleoldest();
417         }
418
419         dptr = SMB_MALLOC_P(struct dptr_struct);
420         if(!dptr) {
421                 DEBUG(0,("malloc fail in dptr_create.\n"));
422                 CloseDir(dir_hnd);
423                 return NT_STATUS_NO_MEMORY;
424         }
425
426         ZERO_STRUCTP(dptr);
427
428         if(old_handle) {
429
430                 /*
431                  * This is an old-style SMBsearch request. Ensure the
432                  * value we return will fit in the range 1-255.
433                  */
434
435                 dptr->dnum = bitmap_find(dptr_bmap, 0);
436
437                 if(dptr->dnum == -1 || dptr->dnum > 254) {
438
439                         /*
440                          * Try and close the oldest handle not marked for
441                          * expect close in the hope that the client has
442                          * finished with that one.
443                          */
444
445                         dptr_close_oldest(True);
446
447                         /* Now try again... */
448                         dptr->dnum = bitmap_find(dptr_bmap, 0);
449                         if(dptr->dnum == -1 || dptr->dnum > 254) {
450                                 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
451                                 SAFE_FREE(dptr);
452                                 CloseDir(dir_hnd);
453                                 return NT_STATUS_TOO_MANY_OPENED_FILES;
454                         }
455                 }
456         } else {
457
458                 /*
459                  * This is a new-style trans2 request. Allocate from
460                  * a range that will return 256 - MAX_DIRECTORY_HANDLES.
461                  */
462
463                 dptr->dnum = bitmap_find(dptr_bmap, 255);
464
465                 if(dptr->dnum == -1 || dptr->dnum < 255) {
466
467                         /*
468                          * Try and close the oldest handle close in the hope that
469                          * the client has finished with that one. This will only
470                          * happen in the case of the Win98 client bug where it leaks
471                          * directory handles.
472                          */
473
474                         dptr_close_oldest(False);
475
476                         /* Now try again... */
477                         dptr->dnum = bitmap_find(dptr_bmap, 255);
478
479                         if(dptr->dnum == -1 || dptr->dnum < 255) {
480                                 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
481                                 SAFE_FREE(dptr);
482                                 CloseDir(dir_hnd);
483                                 return NT_STATUS_TOO_MANY_OPENED_FILES;
484                         }
485                 }
486         }
487
488         bitmap_set(dptr_bmap, dptr->dnum);
489
490         dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
491
492         string_set(&dptr->path,dir2);
493         dptr->conn = conn;
494         dptr->dir_hnd = dir_hnd;
495         dptr->spid = spid;
496         dptr->expect_close = expect_close;
497         dptr->wcard = SMB_STRDUP(wcard);
498         if (!dptr->wcard) {
499                 bitmap_clear(dptr_bmap, dptr->dnum - 1);
500                 SAFE_FREE(dptr);
501                 CloseDir(dir_hnd);
502                 return NT_STATUS_NO_MEMORY;
503         }
504         if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) {
505                 dptr->has_wild = True;
506         } else {
507                 dptr->has_wild = wcard_has_wild;
508         }
509
510         dptr->attr = attr;
511
512         DLIST_ADD(dirptrs, dptr);
513
514         DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
515                 dptr->dnum,path,expect_close));  
516
517         *dptr_ret = dptr;
518
519         return NT_STATUS_OK;
520 }
521
522
523 /****************************************************************************
524  Wrapper functions to access the lower level directory handles.
525 ****************************************************************************/
526
527 int dptr_CloseDir(struct dptr_struct *dptr)
528 {
529         DLIST_REMOVE(dirptrs, dptr);
530         return CloseDir(dptr->dir_hnd);
531 }
532
533 void dptr_SeekDir(struct dptr_struct *dptr, long offset)
534 {
535         SeekDir(dptr->dir_hnd, offset);
536 }
537
538 long dptr_TellDir(struct dptr_struct *dptr)
539 {
540         return TellDir(dptr->dir_hnd);
541 }
542
543 BOOL dptr_has_wild(struct dptr_struct *dptr)
544 {
545         return dptr->has_wild;
546 }
547
548 int dptr_dnum(struct dptr_struct *dptr)
549 {
550         return dptr->dnum;
551 }
552
553 /****************************************************************************
554  Return the next visible file name, skipping veto'd and invisible files.
555 ****************************************************************************/
556
557 static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
558 {
559         /* Normal search for the next file. */
560         const char *name;
561         while ((name = ReadDirName(dptr->dir_hnd, poffset)) != NULL) {
562                 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
563                         return name;
564                 }
565         }
566         return NULL;
567 }
568
569 /****************************************************************************
570  Return the next visible file name, skipping veto'd and invisible files.
571 ****************************************************************************/
572
573 const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
574 {
575         SET_STAT_INVALID(*pst);
576
577         if (dptr->has_wild) {
578                 return dptr_normal_ReadDirName(dptr, poffset, pst);
579         }
580
581         /* If poffset is -1 then we know we returned this name before and we have
582            no wildcards. We're at the end of the directory. */
583         if (*poffset == END_OF_DIRECTORY_OFFSET) {
584                 return NULL;
585         }
586
587         if (!dptr->did_stat) {
588                 pstring pathreal;
589
590                 /* We know the stored wcard contains no wildcard characters. See if we can match
591                    with a stat call. If we can't, then set did_stat to true to
592                    ensure we only do this once and keep searching. */
593
594                 dptr->did_stat = True;
595
596                 /* First check if it should be visible. */
597                 if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard, pst, True)) {
598                         /* This only returns False if the file was found, but
599                            is explicitly not visible. Set us to end of directory,
600                            but return NULL as we know we can't ever find it. */
601                         dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
602                         return NULL;
603                 }
604
605                 if (VALID_STAT(*pst)) {
606                         /* We need to set the underlying dir_hnd offset to -1 also as
607                            this function is usually called with the output from TellDir. */
608                         dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
609                         return dptr->wcard;
610                 }
611
612                 pstrcpy(pathreal,dptr->path);
613                 pstrcat(pathreal,"/");
614                 pstrcat(pathreal,dptr->wcard);
615
616                 if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) {
617                         /* We need to set the underlying dir_hnd offset to -1 also as
618                            this function is usually called with the output from TellDir. */
619                         dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
620                         return dptr->wcard;
621                 } else {
622                         /* If we get any other error than ENOENT or ENOTDIR
623                            then the file exists we just can't stat it. */
624                         if (errno != ENOENT && errno != ENOTDIR) {
625                                 /* We need to set the underlying dir_hdn offset to -1 also as
626                                    this function is usually called with the output from TellDir. */
627                                 dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
628                                 return dptr->wcard;
629                         }
630                 }
631
632                 /* In case sensitive mode we don't search - we know if it doesn't exist 
633                    with a stat we will fail. */
634
635                 if (dptr->conn->case_sensitive) {
636                         /* We need to set the underlying dir_hnd offset to -1 also as
637                            this function is usually called with the output from TellDir. */
638                         dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
639                         return NULL;
640                 }
641         }
642         return dptr_normal_ReadDirName(dptr, poffset, pst);
643 }
644
645 /****************************************************************************
646  Search for a file by name, skipping veto'ed and not visible files.
647 ****************************************************************************/
648
649 BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
650 {
651         SET_STAT_INVALID(*pst);
652
653         if (!dptr->has_wild && (dptr->dir_hnd->offset == END_OF_DIRECTORY_OFFSET)) {
654                 /* This is a singleton directory and we're already at the end. */
655                 *poffset = END_OF_DIRECTORY_OFFSET;
656                 return False;
657         }
658
659         return SearchDir(dptr->dir_hnd, name, poffset);
660 }
661
662 /****************************************************************************
663  Add the name we're returning into the underlying cache.
664 ****************************************************************************/
665
666 void dptr_DirCacheAdd(struct dptr_struct *dptr, const char *name, long offset)
667 {
668         DirCacheAdd(dptr->dir_hnd, name, offset);
669 }
670
671 /****************************************************************************
672  Fill the 5 byte server reserved dptr field.
673 ****************************************************************************/
674
675 BOOL dptr_fill(char *buf1,unsigned int key)
676 {
677         unsigned char *buf = (unsigned char *)buf1;
678         struct dptr_struct *dptr = dptr_get(key, False);
679         uint32 offset;
680         if (!dptr) {
681                 DEBUG(1,("filling null dirptr %d\n",key));
682                 return(False);
683         }
684         offset = (uint32)TellDir(dptr->dir_hnd);
685         DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
686                 (long)dptr->dir_hnd,(int)offset));
687         buf[0] = key;
688         SIVAL(buf,1,offset);
689         return(True);
690 }
691
692 /****************************************************************************
693  Fetch the dir ptr and seek it given the 5 byte server field.
694 ****************************************************************************/
695
696 struct dptr_struct *dptr_fetch(char *buf,int *num)
697 {
698         unsigned int key = *(unsigned char *)buf;
699         struct dptr_struct *dptr = dptr_get(key, False);
700         uint32 offset;
701         long seekoff;
702
703         if (!dptr) {
704                 DEBUG(3,("fetched null dirptr %d\n",key));
705                 return(NULL);
706         }
707         *num = key;
708         offset = IVAL(buf,1);
709         if (offset == (uint32)-1) {
710                 seekoff = END_OF_DIRECTORY_OFFSET;
711         } else {
712                 seekoff = (long)offset;
713         }
714         SeekDir(dptr->dir_hnd,seekoff);
715         DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
716                 key,dptr_path(key),(int)seekoff));
717         return(dptr);
718 }
719
720 /****************************************************************************
721  Fetch the dir ptr.
722 ****************************************************************************/
723
724 struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
725 {
726         struct dptr_struct *dptr  = dptr_get(dptr_num, False);
727
728         if (!dptr) {
729                 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
730                 return(NULL);
731         }
732         DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
733         return(dptr);
734 }
735
736 /****************************************************************************
737  Check that a file matches a particular file type.
738 ****************************************************************************/
739
740 BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype)
741 {
742         uint32 mask;
743
744         /* Check the "may have" search bits. */
745         if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
746                 return False;
747
748         /* Check the "must have" bits, which are the may have bits shifted eight */
749         /* If must have bit is set, the file/dir can not be returned in search unless the matching
750                 file attribute is set */
751         mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */
752         if(mask) {
753                 if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask)   /* check if matching attribute present */
754                         return True;
755                 else
756                         return False;
757         }
758
759         return True;
760 }
761
762 static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask)
763 {
764         mangle_map(filename,True,False,conn->params);
765         return mask_match_search(filename,mask,False);
766 }
767
768 /****************************************************************************
769  Get an 8.3 directory entry.
770 ****************************************************************************/
771
772 BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fname,
773                    SMB_OFF_T *size,uint32 *mode,time_t *date,BOOL check_descend)
774 {
775         const char *dname;
776         BOOL found = False;
777         SMB_STRUCT_STAT sbuf;
778         pstring path;
779         pstring pathreal;
780         pstring filename;
781         BOOL needslash;
782
783         *path = *pathreal = *filename = 0;
784
785         needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
786
787         if (!conn->dirptr)
788                 return(False);
789
790         while (!found) {
791                 long curoff = dptr_TellDir(conn->dirptr);
792                 dname = dptr_ReadDirName(conn->dirptr, &curoff, &sbuf);
793
794                 DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
795                         (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
796       
797                 if (dname == NULL) 
798                         return(False);
799       
800                 pstrcpy(filename,dname);      
801
802                 /* notice the special *.* handling. This appears to be the only difference
803                         between the wildcard handling in this routine and in the trans2 routines.
804                         see masktest for a demo
805                 */
806                 if ((strcmp(mask,"*.*") == 0) ||
807                     mask_match_search(filename,mask,False) ||
808                     mangle_mask_match(conn,filename,mask)) {
809
810                         if (!mangle_is_8_3(filename, False, conn->params))
811                                 mangle_map(filename,True,False,
812                                            conn->params);
813
814                         pstrcpy(fname,filename);
815                         *path = 0;
816                         pstrcpy(path,conn->dirpath);
817                         if(needslash)
818                                 pstrcat(path,"/");
819                         pstrcpy(pathreal,path);
820                         pstrcat(path,fname);
821                         pstrcat(pathreal,dname);
822                         if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
823                                 DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) ));
824                                 continue;
825                         }
826           
827                         *mode = dos_mode(conn,pathreal,&sbuf);
828
829                         if (!dir_check_ftype(conn,*mode,dirtype)) {
830                                 DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",filename,(unsigned int)*mode,(unsigned int)dirtype));
831                                 continue;
832                         }
833
834                         *size = sbuf.st_size;
835                         *date = sbuf.st_mtime;
836
837                         DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
838
839                         found = True;
840
841                         DirCacheAdd(conn->dirptr->dir_hnd, dname, curoff);
842                 }
843         }
844
845         return(found);
846 }
847
848 /*******************************************************************
849  Check to see if a user can read a file. This is only approximate,
850  it is used as part of the "hide unreadable" option. Don't
851  use it for anything security sensitive.
852 ********************************************************************/
853
854 static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
855 {
856         SEC_DESC *psd = NULL;
857         size_t sd_size;
858         files_struct *fsp;
859         NTSTATUS status;
860         uint32 access_granted;
861
862         /*
863          * If user is a member of the Admin group
864          * we never hide files from them.
865          */
866
867         if (conn->admin_user) {
868                 return True;
869         }
870
871         /* If we can't stat it does not show it */
872         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) {
873                 DEBUG(10,("user_can_read_file: SMB_VFS_STAT failed for file %s with error %s\n",
874                         name, strerror(errno) ));
875                 return False;
876         }
877
878         /* Pseudo-open the file (note - no fd's created). */
879
880         if(S_ISDIR(pst->st_mode)) {
881                  status = open_directory(conn, NULL, name, pst,
882                         READ_CONTROL_ACCESS,
883                         FILE_SHARE_READ|FILE_SHARE_WRITE,
884                         FILE_OPEN,
885                         0, /* no create options. */
886                         FILE_ATTRIBUTE_DIRECTORY,
887                         NULL, &fsp);
888         } else {
889                 status = open_file_stat(conn, NULL, name, pst, &fsp);
890         }
891
892         if (!NT_STATUS_IS_OK(status)) {
893                 return False;
894         }
895
896         /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
897         sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd,
898                         (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
899         close_file(fsp, NORMAL_CLOSE);
900
901         /* No access if SD get failed. */
902         if (!sd_size) {
903                 return False;
904         }
905
906         return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA,
907                                  &access_granted, &status);
908 }
909
910 /*******************************************************************
911  Check to see if a user can write a file (and only files, we do not
912  check dirs on this one). This is only approximate,
913  it is used as part of the "hide unwriteable" option. Don't
914  use it for anything security sensitive.
915 ********************************************************************/
916
917 static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
918 {
919         SEC_DESC *psd = NULL;
920         size_t sd_size;
921         files_struct *fsp;
922         int info;
923         NTSTATUS status;
924         uint32 access_granted;
925
926         /*
927          * If user is a member of the Admin group
928          * we never hide files from them.
929          */
930
931         if (conn->admin_user) {
932                 return True;
933         }
934
935         /* If we can't stat it does not show it */
936         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) {
937                 return False;
938         }
939
940         /* Pseudo-open the file */
941
942         if(S_ISDIR(pst->st_mode)) {
943                 return True;
944         } else {
945                 status = open_file_ntcreate(conn, NULL, name, pst,
946                         FILE_WRITE_ATTRIBUTES,
947                         FILE_SHARE_READ|FILE_SHARE_WRITE,
948                         FILE_OPEN,
949                         0,
950                         FILE_ATTRIBUTE_NORMAL,
951                         INTERNAL_OPEN_ONLY,
952                         &info, &fsp);
953         }
954
955         if (!NT_STATUS_IS_OK(status)) {
956                 return False;
957         }
958
959         /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
960         sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd,
961                         (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
962         close_file(fsp, NORMAL_CLOSE);
963
964         /* No access if SD get failed. */
965         if (!sd_size)
966                 return False;
967
968         return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA,
969                                  &access_granted, &status);
970 }
971
972 /*******************************************************************
973   Is a file a "special" type ?
974 ********************************************************************/
975
976 static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
977 {
978         /*
979          * If user is a member of the Admin group
980          * we never hide files from them.
981          */
982
983         if (conn->admin_user)
984                 return False;
985
986         /* If we can't stat it does not show it */
987         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
988                 return True;
989
990         if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
991                 return False;
992
993         return True;
994 }
995
996 /*******************************************************************
997  Should the file be seen by the client ?
998 ********************************************************************/
999
1000 BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, BOOL use_veto)
1001 {
1002         BOOL hide_unreadable = lp_hideunreadable(SNUM(conn));
1003         BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
1004         BOOL hide_special = lp_hide_special_files(SNUM(conn));
1005
1006         SET_STAT_INVALID(*pst);
1007
1008         if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
1009                 return True; /* . and .. are always visible. */
1010         }
1011
1012         /* If it's a vetoed file, pretend it doesn't even exist */
1013         if (use_veto && IS_VETO_PATH(conn, name)) {
1014                 DEBUG(10,("is_visible_file: file %s is vetoed.\n", name ));
1015                 return False;
1016         }
1017
1018         if (hide_unreadable || hide_unwriteable || hide_special) {
1019                 pstring link_target;
1020                 char *entry = NULL;
1021
1022                 if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
1023                         return False;
1024                 }
1025
1026                 /* If it's a dfs symlink, ignore _hide xxxx_ options */
1027                 if (lp_host_msdfs() &&
1028                                 lp_msdfs_root(SNUM(conn)) &&
1029                                 is_msdfs_link(conn, entry, link_target, NULL)) {
1030                         SAFE_FREE(entry);
1031                         return True;
1032                 }
1033
1034                 /* Honour _hide unreadable_ option */
1035                 if (hide_unreadable && !user_can_read_file(conn, entry, pst)) {
1036                         DEBUG(10,("is_visible_file: file %s is unreadable.\n", entry ));
1037                         SAFE_FREE(entry);
1038                         return False;
1039                 }
1040                 /* Honour _hide unwriteable_ option */
1041                 if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
1042                         DEBUG(10,("is_visible_file: file %s is unwritable.\n", entry ));
1043                         SAFE_FREE(entry);
1044                         return False;
1045                 }
1046                 /* Honour _hide_special_ option */
1047                 if (hide_special && file_is_special(conn, entry, pst)) {
1048                         DEBUG(10,("is_visible_file: file %s is special.\n", entry ));
1049                         SAFE_FREE(entry);
1050                         return False;
1051                 }
1052                 SAFE_FREE(entry);
1053         }
1054         return True;
1055 }
1056
1057 /*******************************************************************
1058  Open a directory.
1059 ********************************************************************/
1060
1061 struct smb_Dir *OpenDir(connection_struct *conn, const char *name, const char *mask, uint32 attr)
1062 {
1063         struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir);
1064         if (!dirp) {
1065                 return NULL;
1066         }
1067         ZERO_STRUCTP(dirp);
1068
1069         dirp->conn = conn;
1070
1071         dirp->dir_path = SMB_STRDUP(name);
1072         if (!dirp->dir_path) {
1073                 goto fail;
1074         }
1075         dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
1076         if (!dirp->dir) {
1077                 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) ));
1078                 goto fail;
1079         }
1080
1081         dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, NAME_CACHE_SIZE);
1082         if (!dirp->name_cache) {
1083                 goto fail;
1084         }
1085
1086         dirhandles_open++;
1087         return dirp;
1088
1089   fail:
1090
1091         if (dirp) {
1092                 if (dirp->dir) {
1093                         SMB_VFS_CLOSEDIR(conn,dirp->dir);
1094                 }
1095                 SAFE_FREE(dirp->dir_path);
1096                 SAFE_FREE(dirp->name_cache);
1097                 SAFE_FREE(dirp);
1098         }
1099         return NULL;
1100 }
1101
1102
1103 /*******************************************************************
1104  Close a directory.
1105 ********************************************************************/
1106
1107 int CloseDir(struct smb_Dir *dirp)
1108 {
1109         int i, ret = 0;
1110
1111         if (dirp->dir) {
1112                 ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1113         }
1114         SAFE_FREE(dirp->dir_path);
1115         if (dirp->name_cache) {
1116                 for (i = 0; i < NAME_CACHE_SIZE; i++) {
1117                         SAFE_FREE(dirp->name_cache[i].name);
1118                 }
1119         }
1120         SAFE_FREE(dirp->name_cache);
1121         SAFE_FREE(dirp);
1122         dirhandles_open--;
1123         return ret;
1124 }
1125
1126 /*******************************************************************
1127  Read from a directory. Also return current offset.
1128  Don't check for veto or invisible files.
1129 ********************************************************************/
1130
1131 const char *ReadDirName(struct smb_Dir *dirp, long *poffset)
1132 {
1133         const char *n;
1134         connection_struct *conn = dirp->conn;
1135
1136         /* Cheat to allow . and .. to be the first entries returned. */
1137         if (((*poffset == START_OF_DIRECTORY_OFFSET) || (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2)) {
1138                 if (dirp->file_number == 0) {
1139                         n = ".";
1140                         *poffset = dirp->offset = START_OF_DIRECTORY_OFFSET;
1141                 } else {
1142                         *poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET;
1143                         n = "..";
1144                 }
1145                 dirp->file_number++;
1146                 return n;
1147         } else if (*poffset == END_OF_DIRECTORY_OFFSET) {
1148                 *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1149                 return NULL;
1150         } else {
1151                 /* A real offset, seek to it. */
1152                 SeekDir(dirp, *poffset);
1153         }
1154
1155         while ((n = vfs_readdirname(conn, dirp->dir))) {
1156                 /* Ignore . and .. - we've already returned them. */
1157                 if (*n == '.') {
1158                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
1159                                 continue;
1160                         }
1161                 }
1162                 *poffset = dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1163                 dirp->file_number++;
1164                 return n;
1165         }
1166         *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1167         return NULL;
1168 }
1169
1170 /*******************************************************************
1171  Rewind to the start.
1172 ********************************************************************/
1173
1174 void RewindDir(struct smb_Dir *dirp, long *poffset)
1175 {
1176         SMB_VFS_REWINDDIR(dirp->conn, dirp->dir);
1177         dirp->file_number = 0;
1178         dirp->offset = START_OF_DIRECTORY_OFFSET;
1179         *poffset = START_OF_DIRECTORY_OFFSET;
1180 }
1181
1182 /*******************************************************************
1183  Seek a dir.
1184 ********************************************************************/
1185
1186 void SeekDir(struct smb_Dir *dirp, long offset)
1187 {
1188         if (offset != dirp->offset) {
1189                 if (offset == START_OF_DIRECTORY_OFFSET) {
1190                         RewindDir(dirp, &offset);
1191                         /* 
1192                          * Ok we should really set the file number here
1193                          * to 1 to enable ".." to be returned next. Trouble
1194                          * is I'm worried about callers using SeekDir(dirp,0)
1195                          * as equivalent to RewindDir(). So leave this alone
1196                          * for now.
1197                          */
1198                 } else if  (offset == DOT_DOT_DIRECTORY_OFFSET) {
1199                         RewindDir(dirp, &offset);
1200                         /*
1201                          * Set the file number to 2 - we want to get the first
1202                          * real file entry (the one we return after "..")
1203                          * on the next ReadDir.
1204                          */
1205                         dirp->file_number = 2;
1206                 } else if (offset == END_OF_DIRECTORY_OFFSET) {
1207                         ; /* Don't seek in this case. */
1208                 } else {
1209                         SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1210                 }
1211                 dirp->offset = offset;
1212         }
1213 }
1214
1215 /*******************************************************************
1216  Tell a dir position.
1217 ********************************************************************/
1218
1219 long TellDir(struct smb_Dir *dirp)
1220 {
1221         return(dirp->offset);
1222 }
1223
1224 /*******************************************************************
1225  Add an entry into the dcache.
1226 ********************************************************************/
1227
1228 void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
1229 {
1230         struct name_cache_entry *e;
1231
1232         dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE;
1233         e = &dirp->name_cache[dirp->name_cache_index];
1234         SAFE_FREE(e->name);
1235         e->name = SMB_STRDUP(name);
1236         e->offset = offset;
1237 }
1238
1239 /*******************************************************************
1240  Find an entry by name. Leave us at the offset after it.
1241  Don't check for veto or invisible files.
1242 ********************************************************************/
1243
1244 BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1245 {
1246         int i;
1247         const char *entry;
1248         connection_struct *conn = dirp->conn;
1249
1250         /* Search back in the name cache. */
1251         for (i = dirp->name_cache_index; i >= 0; i--) {
1252                 struct name_cache_entry *e = &dirp->name_cache[i];
1253                 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1254                         *poffset = e->offset;
1255                         SeekDir(dirp, e->offset);
1256                         return True;
1257                 }
1258         }
1259         for (i = NAME_CACHE_SIZE-1; i > dirp->name_cache_index; i--) {
1260                 struct name_cache_entry *e = &dirp->name_cache[i];
1261                 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1262                         *poffset = e->offset;
1263                         SeekDir(dirp, e->offset);
1264                         return True;
1265                 }
1266         }
1267
1268         /* Not found in the name cache. Rewind directory and start from scratch. */
1269         SMB_VFS_REWINDDIR(conn, dirp->dir);
1270         dirp->file_number = 0;
1271         *poffset = START_OF_DIRECTORY_OFFSET;
1272         while ((entry = ReadDirName(dirp, poffset))) {
1273                 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
1274                         return True;
1275                 }
1276         }
1277         return False;
1278 }
1279
1280 /*****************************************************************
1281  Is this directory empty ?
1282 *****************************************************************/
1283
1284 NTSTATUS can_delete_directory(struct connection_struct *conn,
1285                                 const char *dirname)
1286 {
1287         NTSTATUS status = NT_STATUS_OK;
1288         long dirpos = 0;
1289         const char *dname;
1290         struct smb_Dir *dir_hnd = OpenDir(conn, dirname, NULL, 0);
1291
1292         if (!dir_hnd) {
1293                 return map_nt_error_from_unix(errno);
1294         }
1295
1296         while ((dname = ReadDirName(dir_hnd,&dirpos))) {
1297                 SMB_STRUCT_STAT st;
1298
1299                 /* Quick check for "." and ".." */
1300                 if (dname[0] == '.') {
1301                         if (!dname[1] || (dname[1] == '.' && !dname[2])) {
1302                                 continue;
1303                         }
1304                 }
1305
1306                 if (!is_visible_file(conn, dirname, dname, &st, True)) {
1307                         continue;
1308                 }
1309
1310                 DEBUG(10,("can_delete_directory: got name %s - can't delete\n", dname ));
1311                 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1312                 break;
1313         }
1314         CloseDir(dir_hnd);
1315
1316         return status;
1317 }