r8689: Fixes bugid #2889 for sure. Turns out the OS/2 dos box doesn't like two offsets
[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 extern struct current_user current_user;
28
29 /* "Special" directory offsets. */
30 #define END_OF_DIRECTORY_OFFSET ((long)-1)
31 #define START_OF_DIRECTORY_OFFSET ((long)0)
32 #define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000)
33
34 /* Make directory handle internals available. */
35
36 #define NAME_CACHE_SIZE 100
37
38 struct name_cache_entry {
39         char *name;
40         long offset;
41 };
42
43 struct smb_Dir {
44         connection_struct *conn;
45         DIR *dir;
46         long offset;
47         char *dir_path;
48         struct name_cache_entry *name_cache;
49         unsigned int name_cache_index;
50         unsigned int file_number;
51 };
52
53 struct dptr_struct {
54         struct dptr_struct *next, *prev;
55         int dnum;
56         uint16 spid;
57         struct connection_struct *conn;
58         struct smb_Dir *dir_hnd;
59         BOOL expect_close;
60         char *wcard;
61         uint32 attr;
62         char *path;
63         BOOL has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
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         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 ****************************************************************************/
382
383 int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid,
384                 const char *wcard, uint32 attr)
385 {
386         struct dptr_struct *dptr = NULL;
387         struct smb_Dir *dir_hnd;
388         const char *dir2;
389
390         DEBUG(5,("dptr_create dir=%s\n", path));
391
392         if (!check_name(path,conn))
393                 return(-2); /* Code to say use a unix error return code. */
394
395         /* use a const pointer from here on */
396         dir2 = path;
397         if (!*dir2)
398                 dir2 = ".";
399
400         dir_hnd = OpenDir(conn, dir2, wcard, attr);
401         if (!dir_hnd) {
402                 return (-2);
403         }
404
405         string_set(&conn->dirpath,dir2);
406
407         if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
408                 dptr_idleoldest();
409
410         dptr = SMB_MALLOC_P(struct dptr_struct);
411         if(!dptr) {
412                 DEBUG(0,("malloc fail in dptr_create.\n"));
413                 CloseDir(dir_hnd);
414                 return -1;
415         }
416
417         ZERO_STRUCTP(dptr);
418
419         if(old_handle) {
420
421                 /*
422                  * This is an old-style SMBsearch request. Ensure the
423                  * value we return will fit in the range 1-255.
424                  */
425
426                 dptr->dnum = bitmap_find(dptr_bmap, 0);
427
428                 if(dptr->dnum == -1 || dptr->dnum > 254) {
429
430                         /*
431                          * Try and close the oldest handle not marked for
432                          * expect close in the hope that the client has
433                          * finished with that one.
434                          */
435
436                         dptr_close_oldest(True);
437
438                         /* Now try again... */
439                         dptr->dnum = bitmap_find(dptr_bmap, 0);
440                         if(dptr->dnum == -1 || dptr->dnum > 254) {
441                                 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
442                                 SAFE_FREE(dptr);
443                                 CloseDir(dir_hnd);
444                                 return -1;
445                         }
446                 }
447         } else {
448
449                 /*
450                  * This is a new-style trans2 request. Allocate from
451                  * a range that will return 256 - MAX_DIRECTORY_HANDLES.
452                  */
453
454                 dptr->dnum = bitmap_find(dptr_bmap, 255);
455
456                 if(dptr->dnum == -1 || dptr->dnum < 255) {
457
458                         /*
459                          * Try and close the oldest handle close in the hope that
460                          * the client has finished with that one. This will only
461                          * happen in the case of the Win98 client bug where it leaks
462                          * directory handles.
463                          */
464
465                         dptr_close_oldest(False);
466
467                         /* Now try again... */
468                         dptr->dnum = bitmap_find(dptr_bmap, 255);
469
470                         if(dptr->dnum == -1 || dptr->dnum < 255) {
471                                 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
472                                 SAFE_FREE(dptr);
473                                 CloseDir(dir_hnd);
474                                 return -1;
475                         }
476                 }
477         }
478
479         bitmap_set(dptr_bmap, dptr->dnum);
480
481         dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
482
483         string_set(&dptr->path,dir2);
484         dptr->conn = conn;
485         dptr->dir_hnd = dir_hnd;
486         dptr->spid = spid;
487         dptr->expect_close = expect_close;
488         if (wcard) {
489                 dptr->wcard = SMB_STRDUP(wcard);
490                 if (!dptr->wcard) {
491                         bitmap_clear(dptr_bmap, dptr->dnum - 1);
492                         SAFE_FREE(dptr);
493                         CloseDir(dir_hnd);
494                         return -1;
495                 }
496         } else {
497                 dptr->wcard = NULL;
498         }
499         dptr->attr = attr;
500         if (lp_posix_pathnames() || (wcard && (wcard[0] == '.' && wcard[1] == 0))) {
501                 dptr->has_wild = True;
502         } else {
503                 dptr->has_wild = ms_has_wild(wcard);
504         }
505
506         DLIST_ADD(dirptrs, dptr);
507
508         DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
509                 dptr->dnum,path,expect_close));  
510
511         conn->dirptr = dptr;
512
513         return(dptr->dnum);
514 }
515
516
517 /****************************************************************************
518  Wrapper functions to access the lower level directory handles.
519 ****************************************************************************/
520
521 int dptr_CloseDir(struct dptr_struct *dptr)
522 {
523         return CloseDir(dptr->dir_hnd);
524 }
525
526 void dptr_SeekDir(struct dptr_struct *dptr, long offset)
527 {
528         SeekDir(dptr->dir_hnd, offset);
529 }
530
531 long dptr_TellDir(struct dptr_struct *dptr)
532 {
533         return TellDir(dptr->dir_hnd);
534 }
535
536 /****************************************************************************
537  Return the next visible file name, skipping veto'd and invisible files.
538 ****************************************************************************/
539
540 static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
541 {
542         /* Normal search for the next file. */
543         const char *name;
544         while ((name = ReadDirName(dptr->dir_hnd, poffset)) != NULL) {
545                 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
546                         return name;
547                 }
548         }
549         return NULL;
550 }
551
552 /****************************************************************************
553  Return the next visible file name, skipping veto'd and invisible files.
554 ****************************************************************************/
555
556 const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
557 {
558         pstring pathreal;
559
560         SET_STAT_INVALID(*pst);
561
562         if (dptr->has_wild) {
563                 return dptr_normal_ReadDirName(dptr, poffset, pst);
564         }
565
566         /* If poffset is -1 then we know we returned this name before and we have
567            no wildcards. We're at the end of the directory. */
568         if (*poffset == END_OF_DIRECTORY_OFFSET) {
569                 return NULL;
570         }
571
572         /* We know the stored wcard contains no wildcard characters. See if we can match
573            with a stat call. If we can't, then set has_wild to true to
574            prevent us from doing this on every call. */
575
576         /* First check if it should be visible. */
577         if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard, pst, True)) {
578                 dptr->has_wild = True;
579                 return dptr_normal_ReadDirName(dptr, poffset, pst);
580         }
581
582         if (VALID_STAT(*pst)) {
583                 /* We need to set the underlying dir_hdn offset to -1 also as
584                    this function is usually called with the output from TellDir. */
585                 dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
586                 return dptr->wcard;
587         }
588
589         pstrcpy(pathreal,dptr->path);
590         pstrcat(pathreal,"/");
591         pstrcat(pathreal,dptr->wcard);
592
593         if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) {
594                 /* We need to set the underlying dir_hdn offset to -1 also as
595                    this function is usually called with the output from TellDir. */
596                 dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
597                 return dptr->wcard;
598         } else {
599                 /* If we get any other error than ENOENT or ENOTDIR
600                    then the file exists we just can't stat it. */
601                 if (errno != ENOENT && errno != ENOTDIR) {
602                         /* We need to set the underlying dir_hdn offset to -1 also as
603                            this function is usually called with the output from TellDir. */
604                         dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
605                         return dptr->wcard;
606                 }
607         }
608
609         /* In case sensitive mode we don't search - we know if it doesn't exist 
610            with a stat we will fail. */
611
612         if (dptr->conn->case_sensitive) {
613                 /* We need to set the underlying dir_hdn offset to -1 also as
614                    this function is usually called with the output from TellDir. */
615                 dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
616                 return NULL;
617         } else {
618                 dptr->has_wild = True;
619                 return dptr_normal_ReadDirName(dptr, poffset, pst);
620         }
621 }
622
623 /****************************************************************************
624  Search for a file by name, skipping veto'ed and not visible files.
625 ****************************************************************************/
626
627 BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
628 {
629         SET_STAT_INVALID(*pst);
630
631         if (!dptr->has_wild && (dptr->dir_hnd->offset == END_OF_DIRECTORY_OFFSET)) {
632                 /* This is a singleton directory and we're already at the end. */
633                 *poffset = END_OF_DIRECTORY_OFFSET;
634                 return False;
635         }
636
637         if (SearchDir(dptr->dir_hnd, name, poffset)) {
638                 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
639                         return True;
640                 }
641         }
642         return False;
643 }
644
645 /****************************************************************************
646  Fill the 5 byte server reserved dptr field.
647 ****************************************************************************/
648
649 BOOL dptr_fill(char *buf1,unsigned int key)
650 {
651         unsigned char *buf = (unsigned char *)buf1;
652         struct dptr_struct *dptr = dptr_get(key, False);
653         uint32 offset;
654         if (!dptr) {
655                 DEBUG(1,("filling null dirptr %d\n",key));
656                 return(False);
657         }
658         offset = (uint32)TellDir(dptr->dir_hnd);
659         DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
660                 (long)dptr->dir_hnd,(int)offset));
661         buf[0] = key;
662         SIVAL(buf,1,offset);
663         return(True);
664 }
665
666 /****************************************************************************
667  Fetch the dir ptr and seek it given the 5 byte server field.
668 ****************************************************************************/
669
670 struct dptr_struct *dptr_fetch(char *buf,int *num)
671 {
672         unsigned int key = *(unsigned char *)buf;
673         struct dptr_struct *dptr = dptr_get(key, False);
674         uint32 offset;
675         long seekoff;
676
677         if (!dptr) {
678                 DEBUG(3,("fetched null dirptr %d\n",key));
679                 return(NULL);
680         }
681         *num = key;
682         offset = IVAL(buf,1);
683         if (offset == (uint32)-1) {
684                 seekoff = END_OF_DIRECTORY_OFFSET;
685         } else {
686                 seekoff = (long)offset;
687         }
688         SeekDir(dptr->dir_hnd,seekoff);
689         DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
690                 key,dptr_path(key),(int)seekoff));
691         return(dptr);
692 }
693
694 /****************************************************************************
695  Fetch the dir ptr.
696 ****************************************************************************/
697
698 struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
699 {
700         struct dptr_struct *dptr  = dptr_get(dptr_num, False);
701
702         if (!dptr) {
703                 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
704                 return(NULL);
705         }
706         DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
707         return(dptr);
708 }
709
710 /****************************************************************************
711  Check a filetype for being valid.
712 ****************************************************************************/
713
714 BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype)
715 {
716         uint32 mask;
717
718         /* Check the "may have" search bits. */
719         if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
720                 return False;
721
722         /* Check the "must have" bits, which are the may have bits shifted eight */
723         /* If must have bit is set, the file/dir can not be returned in search unless the matching
724                 file attribute is set */
725         mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */
726         if(mask) {
727                 if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask)   /* check if matching attribute present */
728                         return True;
729                 else
730                         return False;
731         }
732
733         return True;
734 }
735
736 static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask)
737 {
738         mangle_map(filename,True,False,SNUM(conn));
739         return mask_match_search(filename,mask,False);
740 }
741
742 /****************************************************************************
743  Get an 8.3 directory entry.
744 ****************************************************************************/
745
746 BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fname,
747                    SMB_OFF_T *size,uint32 *mode,time_t *date,BOOL check_descend)
748 {
749         const char *dname;
750         BOOL found = False;
751         SMB_STRUCT_STAT sbuf;
752         pstring path;
753         pstring pathreal;
754         pstring filename;
755         BOOL needslash;
756
757         *path = *pathreal = *filename = 0;
758
759         needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
760
761         if (!conn->dirptr)
762                 return(False);
763
764         while (!found) {
765                 long curoff = dptr_TellDir(conn->dirptr);
766                 dname = dptr_ReadDirName(conn->dirptr, &curoff, &sbuf);
767
768                 DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
769                         (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
770       
771                 if (dname == NULL) 
772                         return(False);
773       
774                 pstrcpy(filename,dname);      
775
776                 /* notice the special *.* handling. This appears to be the only difference
777                         between the wildcard handling in this routine and in the trans2 routines.
778                         see masktest for a demo
779                 */
780                 if ((strcmp(mask,"*.*") == 0) ||
781                     mask_match_search(filename,mask,False) ||
782                     mangle_mask_match(conn,filename,mask)) {
783
784                         if (!mangle_is_8_3(filename, False, SNUM(conn)))
785                                 mangle_map(filename,True,False,SNUM(conn));
786
787                         pstrcpy(fname,filename);
788                         *path = 0;
789                         pstrcpy(path,conn->dirpath);
790                         if(needslash)
791                                 pstrcat(path,"/");
792                         pstrcpy(pathreal,path);
793                         pstrcat(path,fname);
794                         pstrcat(pathreal,dname);
795                         if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
796                                 DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) ));
797                                 continue;
798                         }
799           
800                         *mode = dos_mode(conn,pathreal,&sbuf);
801
802                         if (!dir_check_ftype(conn,*mode,dirtype)) {
803                                 DEBUG(5,("[%s] attribs didn't match %x\n",filename,(unsigned int)dirtype));
804                                 continue;
805                         }
806
807                         *size = sbuf.st_size;
808                         *date = sbuf.st_mtime;
809
810                         DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
811
812                         found = True;
813                 }
814         }
815
816         return(found);
817 }
818
819 /*******************************************************************
820  Check to see if a user can read a file. This is only approximate,
821  it is used as part of the "hide unreadable" option. Don't
822  use it for anything security sensitive.
823 ********************************************************************/
824
825 static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
826 {
827         SEC_DESC *psd = NULL;
828         size_t sd_size;
829         files_struct *fsp;
830         NTSTATUS status;
831         uint32 access_granted;
832
833         /*
834          * If user is a member of the Admin group
835          * we never hide files from them.
836          */
837
838         if (conn->admin_user) {
839                 return True;
840         }
841
842         /* If we can't stat it does not show it */
843         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) {
844                 return False;
845         }
846
847         /* Pseudo-open the file (note - no fd's created). */
848
849         if(S_ISDIR(pst->st_mode)) {
850                  fsp = open_directory(conn, name, pst,
851                         READ_CONTROL_ACCESS,
852                         FILE_SHARE_READ|FILE_SHARE_WRITE,
853                         FILE_OPEN,
854                         0, /* no create options. */
855                         NULL);
856         } else {
857                 fsp = open_file_stat(conn, name, pst);
858         }
859
860         if (!fsp) {
861                 return False;
862         }
863
864         /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
865         sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd,
866                         (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
867         close_file(fsp, True);
868
869         /* No access if SD get failed. */
870         if (!sd_size) {
871                 return False;
872         }
873
874         return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA,
875                                  &access_granted, &status);
876 }
877
878 /*******************************************************************
879  Check to see if a user can write a file (and only files, we do not
880  check dirs on this one). This is only approximate,
881  it is used as part of the "hide unwriteable" option. Don't
882  use it for anything security sensitive.
883 ********************************************************************/
884
885 static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
886 {
887         SEC_DESC *psd = NULL;
888         size_t sd_size;
889         files_struct *fsp;
890         int info;
891         NTSTATUS status;
892         uint32 access_granted;
893
894         /*
895          * If user is a member of the Admin group
896          * we never hide files from them.
897          */
898
899         if (conn->admin_user) {
900                 return True;
901         }
902
903         /* If we can't stat it does not show it */
904         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) {
905                 return False;
906         }
907
908         /* Pseudo-open the file */
909
910         if(S_ISDIR(pst->st_mode)) {
911                 return True;
912         } else {
913                 fsp = open_file_ntcreate(conn, name, pst,
914                         FILE_WRITE_ATTRIBUTES,
915                         FILE_SHARE_READ|FILE_SHARE_WRITE,
916                         FILE_OPEN,
917                         0,
918                         FILE_ATTRIBUTE_NORMAL,
919                         INTERNAL_OPEN_ONLY,
920                         &info);
921         }
922
923         if (!fsp) {
924                 return False;
925         }
926
927         /* Get NT ACL -allocated in main loop talloc context. No free needed here. */
928         sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd,
929                         (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
930         close_file(fsp, False);
931
932         /* No access if SD get failed. */
933         if (!sd_size)
934                 return False;
935
936         return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA,
937                                  &access_granted, &status);
938 }
939
940 /*******************************************************************
941   Is a file a "special" type ?
942 ********************************************************************/
943
944 static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
945 {
946         /*
947          * If user is a member of the Admin group
948          * we never hide files from them.
949          */
950
951         if (conn->admin_user)
952                 return False;
953
954         /* If we can't stat it does not show it */
955         if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
956                 return True;
957
958         if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
959                 return False;
960
961         return True;
962 }
963
964 /*******************************************************************
965  Should the file be seen by the client ?
966 ********************************************************************/
967
968 BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, BOOL use_veto)
969 {
970         BOOL hide_unreadable = lp_hideunreadable(SNUM(conn));
971         BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
972         BOOL hide_special = lp_hide_special_files(SNUM(conn));
973
974         SET_STAT_INVALID(*pst);
975
976         if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
977                 return True; /* . and .. are always visible. */
978         }
979
980         /* If it's a vetoed file, pretend it doesn't even exist */
981         if (use_veto && IS_VETO_PATH(conn, name)) {
982                 return False;
983         }
984
985         if (hide_unreadable || hide_unwriteable || hide_special) {
986                 char *entry = NULL;
987
988                 if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
989                         return False;
990                 }
991                 /* Honour _hide unreadable_ option */
992                 if (hide_unreadable && !user_can_read_file(conn, entry, pst)) {
993                         SAFE_FREE(entry);
994                         return False;
995                 }
996                 /* Honour _hide unwriteable_ option */
997                 if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
998                         SAFE_FREE(entry);
999                         return False;
1000                 }
1001                 /* Honour _hide_special_ option */
1002                 if (hide_special && file_is_special(conn, entry, pst)) {
1003                         SAFE_FREE(entry);
1004                         return False;
1005                 }
1006                 SAFE_FREE(entry);
1007         }
1008         return True;
1009 }
1010
1011 /*******************************************************************
1012  Open a directory.
1013 ********************************************************************/
1014
1015 struct smb_Dir *OpenDir(connection_struct *conn, const char *name, const char *mask, uint32 attr)
1016 {
1017         struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir);
1018         if (!dirp) {
1019                 return NULL;
1020         }
1021         ZERO_STRUCTP(dirp);
1022
1023         dirp->conn = conn;
1024
1025         dirp->dir_path = SMB_STRDUP(name);
1026         if (!dirp->dir_path) {
1027                 goto fail;
1028         }
1029         dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
1030         if (!dirp->dir) {
1031                 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) ));
1032                 goto fail;
1033         }
1034
1035         dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, NAME_CACHE_SIZE);
1036         if (!dirp->name_cache) {
1037                 goto fail;
1038         }
1039
1040         dirhandles_open++;
1041         return dirp;
1042
1043   fail:
1044
1045         if (dirp) {
1046                 if (dirp->dir) {
1047                         SMB_VFS_CLOSEDIR(conn,dirp->dir);
1048                 }
1049                 SAFE_FREE(dirp->dir_path);
1050                 SAFE_FREE(dirp->name_cache);
1051                 SAFE_FREE(dirp);
1052         }
1053         return NULL;
1054 }
1055
1056
1057 /*******************************************************************
1058  Close a directory.
1059 ********************************************************************/
1060
1061 int CloseDir(struct smb_Dir *dirp)
1062 {
1063         int i, ret = 0;
1064
1065         if (dirp->dir) {
1066                 ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1067         }
1068         SAFE_FREE(dirp->dir_path);
1069         if (dirp->name_cache) {
1070                 for (i = 0; i < NAME_CACHE_SIZE; i++) {
1071                         SAFE_FREE(dirp->name_cache[i].name);
1072                 }
1073         }
1074         SAFE_FREE(dirp->name_cache);
1075         SAFE_FREE(dirp);
1076         dirhandles_open--;
1077         return ret;
1078 }
1079
1080 /*******************************************************************
1081  Read from a directory. Also return current offset.
1082  Don't check for veto or invisible files.
1083 ********************************************************************/
1084
1085 const char *ReadDirName(struct smb_Dir *dirp, long *poffset)
1086 {
1087         const char *n;
1088         connection_struct *conn = dirp->conn;
1089
1090         /* Cheat to allow . and .. to be the first entries returned. */
1091         if (((*poffset == START_OF_DIRECTORY_OFFSET) || (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2)) {
1092                 if (dirp->file_number == 0) {
1093                         n = ".";
1094                         *poffset = dirp->offset = START_OF_DIRECTORY_OFFSET;
1095                 } else {
1096                         *poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET;
1097                         n = "..";
1098                 }
1099                 dirp->file_number++;
1100                 return n;
1101         } else {
1102                 /* A real offset, seek to it. */
1103                 SeekDir(dirp, *poffset);
1104         }
1105
1106         while ((n = vfs_readdirname(conn, dirp->dir))) {
1107                 struct name_cache_entry *e;
1108                 /* Ignore . and .. - we've already returned them. */
1109                 if (*n == '.') {
1110                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
1111                                 continue;
1112                         }
1113                 }
1114                 dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1115                 dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE;
1116                 e = &dirp->name_cache[dirp->name_cache_index];
1117                 SAFE_FREE(e->name);
1118                 e->name = SMB_STRDUP(n);
1119                 *poffset = e->offset= dirp->offset;
1120                 dirp->file_number++;
1121                 return e->name;
1122         }
1123         dirp->offset = END_OF_DIRECTORY_OFFSET;
1124         return NULL;
1125 }
1126
1127 /*******************************************************************
1128  Rewind to the start.
1129 ********************************************************************/
1130
1131 void RewindDir(struct smb_Dir *dirp, long *poffset)
1132 {
1133         SMB_VFS_REWINDDIR(dirp->conn, dirp->dir);
1134         dirp->file_number = 0;
1135         dirp->offset = START_OF_DIRECTORY_OFFSET;
1136         *poffset = START_OF_DIRECTORY_OFFSET;
1137 }
1138
1139 /*******************************************************************
1140  Seek a dir.
1141 ********************************************************************/
1142
1143 void SeekDir(struct smb_Dir *dirp, long offset)
1144 {
1145         if (offset != dirp->offset) {
1146                 if (offset == START_OF_DIRECTORY_OFFSET || offset == DOT_DOT_DIRECTORY_OFFSET) {
1147                         RewindDir(dirp, &offset);
1148                 } else {
1149                         SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1150                 }
1151                 dirp->offset = offset;
1152         }
1153 }
1154
1155 /*******************************************************************
1156  Tell a dir position.
1157 ********************************************************************/
1158
1159 long TellDir(struct smb_Dir *dirp)
1160 {
1161         return(dirp->offset);
1162 }
1163
1164 /*******************************************************************
1165  Find an entry by name. Leave us at the offset after it.
1166  Don't check for veto or invisible files.
1167 ********************************************************************/
1168
1169 BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1170 {
1171         int i;
1172         const char *entry;
1173         connection_struct *conn = dirp->conn;
1174
1175         /* Search back in the name cache. */
1176         for (i = dirp->name_cache_index; i >= 0; i--) {
1177                 struct name_cache_entry *e = &dirp->name_cache[i];
1178                 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1179                         *poffset = e->offset;
1180                         SeekDir(dirp, e->offset);
1181                         return True;
1182                 }
1183         }
1184         for (i = NAME_CACHE_SIZE-1; i > dirp->name_cache_index; i--) {
1185                 struct name_cache_entry *e = &dirp->name_cache[i];
1186                 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1187                         *poffset = e->offset;
1188                         SeekDir(dirp, e->offset);
1189                         return True;
1190                 }
1191         }
1192
1193         /* Not found in the name cache. Rewind directory and start from scratch. */
1194         SMB_VFS_REWINDDIR(conn, dirp->dir);
1195         dirp->file_number = 0;
1196         *poffset = START_OF_DIRECTORY_OFFSET;
1197         while ((entry = ReadDirName(dirp, poffset))) {
1198                 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
1199                         return True;
1200                 }
1201         }
1202         return False;
1203 }