Use VFS I/O for stat_cache_lookup()
[samba.git] / source3 / smbd / filename.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    filename handling routines
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 extern int DEBUGLEVEL;
25 extern BOOL case_sensitive;
26 extern BOOL case_preserve;
27 extern BOOL short_case_preserve;
28 extern fstring remote_machine;
29 extern BOOL use_mangled_map;
30
31 static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache);
32
33 /****************************************************************************
34  Check if two filenames are equal.
35  This needs to be careful about whether we are case sensitive.
36 ****************************************************************************/
37 static BOOL fname_equal(char *name1, char *name2)
38 {
39   int l1 = strlen(name1);
40   int l2 = strlen(name2);
41
42   /* handle filenames ending in a single dot */
43   if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
44     {
45       BOOL ret;
46       name1[l1-1] = 0;
47       ret = fname_equal(name1,name2);
48       name1[l1-1] = '.';
49       return(ret);
50     }
51
52   if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
53     {
54       BOOL ret;
55       name2[l2-1] = 0;
56       ret = fname_equal(name1,name2);
57       name2[l2-1] = '.';
58       return(ret);
59     }
60
61   /* now normal filename handling */
62   if (case_sensitive)
63     return(strcmp(name1,name2) == 0);
64
65   return(strequal(name1,name2));
66 }
67
68
69 /****************************************************************************
70  Mangle the 2nd name and check if it is then equal to the first name.
71 ****************************************************************************/
72 static BOOL mangled_equal(char *name1, char *name2)
73 {
74   pstring tmpname;
75
76   if (is_8_3(name2, True))
77     return(False);
78
79   pstrcpy(tmpname,name2);
80   mangle_name_83(tmpname);
81
82   return(strequal(name1,tmpname));
83 }
84
85 /****************************************************************************
86  Stat cache code used in unix_convert.
87 *****************************************************************************/
88
89 static int global_stat_cache_lookups;
90 static int global_stat_cache_misses;
91 static int global_stat_cache_hits;
92
93 /****************************************************************************
94  Stat cache statistics code.
95 *****************************************************************************/
96
97 void print_stat_cache_statistics(void)
98 {
99   double eff = (100.0* (double)global_stat_cache_hits)/(double)global_stat_cache_lookups;
100
101   DEBUG(0,("stat cache stats: lookups = %d, hits = %d, misses = %d, \
102 stat cache was %f%% effective.\n", global_stat_cache_lookups,
103        global_stat_cache_hits, global_stat_cache_misses, eff ));
104 }
105
106 typedef struct {
107   ubi_dlNode link;
108   int name_len;
109   pstring orig_name;
110   pstring translated_name;
111 } stat_cache_entry;
112
113 #define MAX_STAT_CACHE_SIZE 50
114
115 static ubi_dlList stat_cache = { NULL, (ubi_dlNodePtr)&stat_cache, 0};
116
117 /****************************************************************************
118  Compare a pathname to a name in the stat cache - of a given length.
119  Note - this code always checks that the next character in the pathname
120  is either a '/' character, or a '\0' character - to ensure we only
121  match *full* pathname components. Note we don't need to handle case
122  here, if we're case insensitive the stat cache orig names are all upper
123  case.
124 *****************************************************************************/
125
126 static BOOL stat_name_equal_len( char *stat_name, char *orig_name, int len)
127 {
128   BOOL matched = (memcmp( stat_name, orig_name, len) == 0);
129   if(orig_name[len] != '/' && orig_name[len] != '\0')
130     return False;
131
132   return matched;
133 }
134
135 /****************************************************************************
136  Add an entry into the stat cache.
137 *****************************************************************************/
138
139 static void stat_cache_add( char *full_orig_name, char *orig_translated_path)
140 {
141   stat_cache_entry *scp;
142   pstring orig_name;
143   pstring translated_path;
144   int namelen;
145
146   if (!lp_stat_cache()) return;
147
148   namelen = strlen(orig_translated_path);
149
150   /*
151    * Don't cache trivial valid directory entries.
152    */
153   if((*full_orig_name == '\0') || (strcmp(full_orig_name, ".") == 0) ||
154      (strcmp(full_orig_name, "..") == 0))
155     return;
156
157   /*
158    * If we are in case insentive mode, we need to
159    * store names that need no translation - else, it
160    * would be a waste.
161    */
162
163   if(case_sensitive && (strcmp(full_orig_name, orig_translated_path) == 0))
164     return;
165
166   /*
167    * Remove any trailing '/' characters from the
168    * translated path.
169    */
170
171   pstrcpy(translated_path, orig_translated_path);
172   if(translated_path[namelen-1] == '/') {
173     translated_path[namelen-1] = '\0';
174     namelen--;
175   }
176
177   /*
178    * We will only replace namelen characters 
179    * of full_orig_name.
180    * StrnCpy always null terminates.
181    */
182
183   StrnCpy(orig_name, full_orig_name, namelen);
184   if(!case_sensitive)
185     strupper( orig_name );
186
187   /*
188    * Check this name doesn't exist in the cache before we 
189    * add it.
190    */
191
192   for( scp = (stat_cache_entry *)ubi_dlFirst( &stat_cache); scp; 
193                         scp = (stat_cache_entry *)ubi_dlNext( scp )) {
194     if((strcmp( scp->orig_name, orig_name) == 0) &&
195        (strcmp( scp->translated_name, translated_path) == 0)) {
196       /*
197        * Name does exist - promote it.
198        */
199       if( (stat_cache_entry *)ubi_dlFirst( &stat_cache) != scp ) {
200         ubi_dlRemThis( &stat_cache, scp);
201         ubi_dlAddHead( &stat_cache, scp);
202       }
203       return;
204     }
205   }
206
207   if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry))) == NULL) {
208     DEBUG(0,("stat_cache_add: Out of memory !\n"));
209     return;
210   }
211
212   pstrcpy(scp->orig_name, orig_name);
213   pstrcpy(scp->translated_name, translated_path);
214   scp->name_len = namelen;
215
216   ubi_dlAddHead( &stat_cache, scp);
217
218   DEBUG(10,("stat_cache_add: Added entry %s -> %s\n", scp->orig_name, scp->translated_name ));
219
220   if(ubi_dlCount(&stat_cache) > lp_stat_cache_size()) {
221     scp = (stat_cache_entry *)ubi_dlRemTail( &stat_cache );
222     free((char *)scp);
223     return;
224   }
225 }
226
227 /****************************************************************************
228  Look through the stat cache for an entry - promote it to the top if found.
229  Return True if we translated (and did a scuccessful stat on) the entire name.
230 *****************************************************************************/
231
232 static BOOL stat_cache_lookup(struct connection_struct *conn, char *name, 
233                               char *dirpath, char **start, 
234                               SMB_STRUCT_STAT *pst)
235 {
236   stat_cache_entry *scp;
237   stat_cache_entry *longest_hit = NULL;
238   pstring chk_name;
239   int namelen;
240
241   if (!lp_stat_cache()) return False;
242  
243   namelen = strlen(name);
244
245   *start = name;
246   global_stat_cache_lookups++;
247
248   /*
249    * Don't lookup trivial valid directory entries.
250    */
251   if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) {
252     global_stat_cache_misses++;
253     return False;
254   }
255
256   pstrcpy(chk_name, name);
257   if(!case_sensitive)
258     strupper( chk_name );
259
260   for( scp = (stat_cache_entry *)ubi_dlFirst( &stat_cache); scp; 
261                         scp = (stat_cache_entry *)ubi_dlNext( scp )) {
262     if(scp->name_len <= namelen) {
263       if(stat_name_equal_len(scp->orig_name, chk_name, scp->name_len)) {
264         if((longest_hit == NULL) || (longest_hit->name_len <= scp->name_len))
265           longest_hit = scp;
266       }
267     }
268   }
269
270   if(longest_hit == NULL) {
271     DEBUG(10,("stat_cache_lookup: cache miss on %s\n", name));
272     global_stat_cache_misses++;
273     return False;
274   }
275
276   global_stat_cache_hits++;
277
278   DEBUG(10,("stat_cache_lookup: cache hit for name %s. %s -> %s\n",
279         name, longest_hit->orig_name, longest_hit->translated_name ));
280
281   /*
282    * longest_hit is the longest match we got in the list.
283    * Check it exists - if so, overwrite the original name
284    * and then promote it to the top.
285    */
286
287   if(conn->vfs_ops.stat(longest_hit->translated_name, pst) != 0) {
288     /*
289      * Discard this entry.
290      */
291     ubi_dlRemThis( &stat_cache, longest_hit);
292     free((char *)longest_hit);
293     return False;
294   }
295
296   memcpy(name, longest_hit->translated_name, longest_hit->name_len);
297   if( (stat_cache_entry *)ubi_dlFirst( &stat_cache) != longest_hit ) {
298     ubi_dlRemThis( &stat_cache, longest_hit);
299     ubi_dlAddHead( &stat_cache, longest_hit);
300   }
301
302   *start = &name[longest_hit->name_len];
303   if(**start == '/')
304     ++*start;
305
306   StrnCpy( dirpath, longest_hit->translated_name, name - (*start));
307
308   return (namelen == longest_hit->name_len);
309 }
310
311 /****************************************************************************
312 This routine is called to convert names from the dos namespace to unix
313 namespace. It needs to handle any case conversions, mangling, format
314 changes etc.
315
316 We assume that we have already done a chdir() to the right "root" directory
317 for this service.
318
319 The function will return False if some part of the name except for the last
320 part cannot be resolved
321
322 If the saved_last_component != 0, then the unmodified last component
323 of the pathname is returned there. This is used in an exceptional
324 case in reply_mv (so far). If saved_last_component == 0 then nothing
325 is returned there.
326
327 The bad_path arg is set to True if the filename walk failed. This is
328 used to pick the correct error code to return between ENOENT and ENOTDIR
329 as Windows applications depend on ERRbadpath being returned if a component
330 of a pathname does not exist.
331 ****************************************************************************/
332
333 BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, 
334                   BOOL *bad_path, SMB_STRUCT_STAT *pst)
335 {
336   SMB_STRUCT_STAT st;
337   char *start, *end;
338   pstring dirpath;
339   pstring orig_path;
340   int saved_errno;
341   BOOL component_was_mangled = False;
342   BOOL name_has_wildcard = False;
343 #if 0
344   /* Andrew's conservative code... JRA. */
345   extern char magic_char;
346 #endif
347
348   DEBUG(5, ("unix_convert called on file \"%s\"\n", name));
349
350   *dirpath = 0;
351   *bad_path = False;
352   if(pst) {
353           ZERO_STRUCTP(pst);
354   }
355
356   if(saved_last_component)
357     *saved_last_component = 0;
358
359   /* 
360    * Convert to basic unix format - removing \ chars and cleaning it up.
361    */
362
363   unix_format(name);
364   unix_clean_name(name);
365
366   /* 
367    * Names must be relative to the root of the service - trim any leading /.
368    * also trim trailing /'s.
369    */
370
371   trim_string(name,"/","/");
372
373   /*
374    * If we trimmed down to a single '\0' character
375    * then we should use the "." directory to avoid
376    * searching the cache, but not if we are in a
377    * printing share.
378    */
379
380   if (!*name && (!conn -> printer)) {
381     name[0] = '.';
382     name[1] = '\0';
383   }
384
385   /*
386    * Ensure saved_last_component is valid even if file exists.
387    */
388
389   if(saved_last_component) {
390     end = strrchr(name, '/');
391     if(end)
392       pstrcpy(saved_last_component, end + 1);
393     else
394       pstrcpy(saved_last_component, name);
395   }
396
397   if (!case_sensitive && 
398       (!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
399     strnorm(name);
400
401   /* 
402    * Check if it's a printer file.
403    */
404   if (conn->printer) {
405     if ((! *name) || strchr(name,'/') || !is_8_3(name, True)) {
406       char *s;
407       fstring name2;
408       slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine);
409
410       /* 
411        * Sanitise the name.
412        */
413
414       for (s=name2 ; *s ; s++)
415         if (!issafe(*s)) *s = '_';
416       pstrcpy(name,(char *)mktemp(name2));        
417     }      
418     return(True);
419   }
420
421   /*
422    * If we trimmed down to a single '\0' character
423    * then we will be using the "." directory.
424    * As we know this is valid we can return true here.
425    */
426
427   if(!*name)
428     return(True);
429
430   start = name;
431   while (strncmp(start,"./",2) == 0)
432     start += 2;
433
434   pstrcpy(orig_path, name);
435
436   if(stat_cache_lookup(conn, name, dirpath, &start, &st)) {
437     if(pst)
438       *pst = st;
439     return True;
440   }
441
442   /* 
443    * stat the name - if it exists then we are all done!
444    */
445
446   if (conn->vfs_ops.stat(name,&st) == 0) {
447     stat_cache_add(orig_path, name);
448     DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
449     if(pst)
450       *pst = st;
451     return(True);
452   }
453
454   saved_errno = errno;
455
456   DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n",
457         name, dirpath, start));
458
459   /* 
460    * A special case - if we don't have any mangling chars and are case
461    * sensitive then searching won't help.
462    */
463
464   if (case_sensitive && !is_mangled(name) && 
465       !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT))
466     return(False);
467
468   if(strchr(start,'?') || strchr(start,'*'))
469     name_has_wildcard = True;
470
471   /* 
472    * is_mangled() was changed to look at an entire pathname, not 
473    * just a component. JRA.
474    */
475
476   if(is_mangled(start))
477     component_was_mangled = True;
478
479 #if 0
480   /* Keep Andrew's conservative code around, just in case. JRA. */
481   /* this is an extremely conservative test for mangled names. */
482   if (strchr(start,magic_char))
483     component_was_mangled = True;
484 #endif
485
486   /* 
487    * Now we need to recursively match the name against the real 
488    * directory structure.
489    */
490
491   /* 
492    * Match each part of the path name separately, trying the names
493    * as is first, then trying to scan the directory for matching names.
494    */
495
496   for (; start ; start = (end?end+1:(char *)NULL)) {
497       /* 
498        * Pinpoint the end of this section of the filename.
499        */
500       end = strchr(start, '/');
501
502       /* 
503        * Chop the name at this point.
504        */
505       if (end) 
506         *end = 0;
507
508       if(saved_last_component != 0)
509         pstrcpy(saved_last_component, end ? end + 1 : start);
510
511       /* 
512        * Check if the name exists up to this point.
513        */
514
515       if (conn->vfs_ops.stat(name, &st) == 0) {
516         /*
517          * It exists. it must either be a directory or this must be
518          * the last part of the path for it to be OK.
519          */
520         if (end && !(st.st_mode & S_IFDIR)) {
521           /*
522            * An intermediate part of the name isn't a directory.
523             */
524           DEBUG(5,("Not a dir %s\n",start));
525           *end = '/';
526           return(False);
527         }
528
529       } else {
530         pstring rest;
531
532         *rest = 0;
533
534         /*
535          * Remember the rest of the pathname so it can be restored
536          * later.
537          */
538
539         if (end)
540           pstrcpy(rest,end+1);
541
542         /*
543          * Try to find this part of the path in the directory.
544          */
545
546         if (strchr(start,'?') || strchr(start,'*') ||
547             !scan_directory(dirpath, start, conn, end?True:False)) {
548           if (end) {
549             /*
550              * An intermediate part of the name can't be found.
551              */
552             DEBUG(5,("Intermediate not found %s\n",start));
553             *end = '/';
554
555             /* 
556              * We need to return the fact that the intermediate
557              * name resolution failed. This is used to return an
558              * error of ERRbadpath rather than ERRbadfile. Some
559              * Windows applications depend on the difference between
560              * these two errors.
561              */
562             *bad_path = True;
563             return(False);
564           }
565               
566           /* 
567            * Just the last part of the name doesn't exist.
568                * We may need to strupper() or strlower() it in case
569            * this conversion is being used for file creation 
570            * purposes. If the filename is of mixed case then 
571            * don't normalise it.
572            */
573
574           if (!case_preserve && (!strhasupper(start) || !strhaslower(start)))           
575             strnorm(start);
576
577           /*
578            * check on the mangled stack to see if we can recover the 
579            * base of the filename.
580            */
581
582           if (is_mangled(start)) {
583             check_mangled_cache( start );
584           }
585
586           DEBUG(5,("New file %s\n",start));
587           return(True); 
588         }
589
590       /* 
591        * Restore the rest of the string.
592        */
593       if (end) {
594         pstrcpy(start+strlen(start)+1,rest);
595         end = start + strlen(start);
596       }
597     } /* end else */
598
599     /* 
600      * Add to the dirpath that we have resolved so far.
601      */
602     if (*dirpath)
603       pstrcat(dirpath,"/");
604
605     pstrcat(dirpath,start);
606
607     /*
608      * Don't cache a name with mangled or wildcard components
609      * as this can change the size.
610      */
611
612     if(!component_was_mangled && !name_has_wildcard)
613       stat_cache_add(orig_path, dirpath);
614
615     /* 
616      * Restore the / that we wiped out earlier.
617      */
618     if (end)
619       *end = '/';
620   }
621   
622   /*
623    * Don't cache a name with mangled or wildcard components
624    * as this can change the size.
625    */
626
627   if(!component_was_mangled && !name_has_wildcard)
628     stat_cache_add(orig_path, name);
629
630   /* 
631    * The name has been resolved.
632    */
633
634   DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
635   return(True);
636 }
637
638
639 /****************************************************************************
640 check a filename - possibly caling reducename
641
642 This is called by every routine before it allows an operation on a filename.
643 It does any final confirmation necessary to ensure that the filename is
644 a valid one for the user to access.
645 ****************************************************************************/
646 BOOL check_name(char *name,connection_struct *conn)
647 {
648   BOOL ret;
649
650   errno = 0;
651
652   if (IS_VETO_PATH(conn, name))  {
653           DEBUG(5,("file path name %s vetoed\n",name));
654           return(0);
655   }
656
657   ret = reduce_name(name,conn->connectpath,lp_widelinks(SNUM(conn)));
658
659   /* Check if we are allowing users to follow symlinks */
660   /* Patch from David Clerc <David.Clerc@cui.unige.ch>
661      University of Geneva */
662
663 #ifdef S_ISLNK
664   if (!lp_symlinks(SNUM(conn)))
665     {
666       SMB_STRUCT_STAT statbuf;
667       if ( (conn->vfs_ops.lstat(dos_to_unix(name,False),&statbuf) != -1) &&
668           (S_ISLNK(statbuf.st_mode)) )
669         {
670           DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name));
671           ret=0; 
672         }
673     }
674 #endif
675
676   if (!ret)
677     DEBUG(5,("check_name on %s failed\n",name));
678
679   return(ret);
680 }
681
682
683 /****************************************************************************
684 scan a directory to find a filename, matching without case sensitivity
685
686 If the name looks like a mangled name then try via the mangling functions
687 ****************************************************************************/
688 static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache)
689 {
690   void *cur_dir;
691   char *dname;
692   BOOL mangled;
693   pstring name2;
694
695   mangled = is_mangled(name);
696
697   /* handle null paths */
698   if (*path == 0)
699     path = ".";
700
701   if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) {
702     pstrcpy(name, dname);       
703     return(True);
704   }      
705
706   /*
707    * The incoming name can be mangled, and if we de-mangle it
708    * here it will not compare correctly against the filename (name2)
709    * read from the directory and then mangled by the name_map_mangle()
710    * call. We need to mangle both names or neither.
711    * (JRA).
712    */
713   if (mangled)
714     mangled = !check_mangled_cache( name );
715
716   /* open the directory */
717   if (!(cur_dir = OpenDir(conn, path, True))) 
718     {
719       DEBUG(3,("scan dir didn't open dir [%s]\n",path));
720       return(False);
721     }
722
723   /* now scan for matching names */
724   while ((dname = ReadDirName(cur_dir))) 
725     {
726       if (*dname == '.' &&
727           (strequal(dname,".") || strequal(dname,"..")))
728         continue;
729
730       pstrcpy(name2,dname);
731       if (!name_map_mangle(name2,False,SNUM(conn))) continue;
732
733       if ((mangled && mangled_equal(name,name2))
734           || fname_equal(name, name2))
735         {
736           /* we've found the file, change it's name and return */
737           if (docache) DirCacheAdd(path,name,dname,SNUM(conn));
738           pstrcpy(name, dname);
739           CloseDir(cur_dir);
740           return(True);
741         }
742     }
743
744   CloseDir(cur_dir);
745   return(False);
746 }