Use VFS operations for file I/O.
[tprouty/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( char *name, char *dirpath, char **start, SMB_STRUCT_STAT *pst)
233 {
234   stat_cache_entry *scp;
235   stat_cache_entry *longest_hit = NULL;
236   pstring chk_name;
237   int namelen;
238
239   if (!lp_stat_cache()) return False;
240  
241   namelen = strlen(name);
242
243   *start = name;
244   global_stat_cache_lookups++;
245
246   /*
247    * Don't lookup trivial valid directory entries.
248    */
249   if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) {
250     global_stat_cache_misses++;
251     return False;
252   }
253
254   pstrcpy(chk_name, name);
255   if(!case_sensitive)
256     strupper( chk_name );
257
258   for( scp = (stat_cache_entry *)ubi_dlFirst( &stat_cache); scp; 
259                         scp = (stat_cache_entry *)ubi_dlNext( scp )) {
260     if(scp->name_len <= namelen) {
261       if(stat_name_equal_len(scp->orig_name, chk_name, scp->name_len)) {
262         if((longest_hit == NULL) || (longest_hit->name_len <= scp->name_len))
263           longest_hit = scp;
264       }
265     }
266   }
267
268   if(longest_hit == NULL) {
269     DEBUG(10,("stat_cache_lookup: cache miss on %s\n", name));
270     global_stat_cache_misses++;
271     return False;
272   }
273
274   global_stat_cache_hits++;
275
276   DEBUG(10,("stat_cache_lookup: cache hit for name %s. %s -> %s\n",
277         name, longest_hit->orig_name, longest_hit->translated_name ));
278
279   /*
280    * longest_hit is the longest match we got in the list.
281    * Check it exists - if so, overwrite the original name
282    * and then promote it to the top.
283    */
284
285   if(dos_stat( longest_hit->translated_name, pst) != 0) {
286     /*
287      * Discard this entry.
288      */
289     ubi_dlRemThis( &stat_cache, longest_hit);
290     free((char *)longest_hit);
291     return False;
292   }
293
294   memcpy(name, longest_hit->translated_name, longest_hit->name_len);
295   if( (stat_cache_entry *)ubi_dlFirst( &stat_cache) != longest_hit ) {
296     ubi_dlRemThis( &stat_cache, longest_hit);
297     ubi_dlAddHead( &stat_cache, longest_hit);
298   }
299
300   *start = &name[longest_hit->name_len];
301   if(**start == '/')
302     ++*start;
303
304   StrnCpy( dirpath, longest_hit->translated_name, name - (*start));
305
306   return (namelen == longest_hit->name_len);
307 }
308
309 /****************************************************************************
310 This routine is called to convert names from the dos namespace to unix
311 namespace. It needs to handle any case conversions, mangling, format
312 changes etc.
313
314 We assume that we have already done a chdir() to the right "root" directory
315 for this service.
316
317 The function will return False if some part of the name except for the last
318 part cannot be resolved
319
320 If the saved_last_component != 0, then the unmodified last component
321 of the pathname is returned there. This is used in an exceptional
322 case in reply_mv (so far). If saved_last_component == 0 then nothing
323 is returned there.
324
325 The bad_path arg is set to True if the filename walk failed. This is
326 used to pick the correct error code to return between ENOENT and ENOTDIR
327 as Windows applications depend on ERRbadpath being returned if a component
328 of a pathname does not exist.
329 ****************************************************************************/
330
331 BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, 
332                   BOOL *bad_path, SMB_STRUCT_STAT *pst)
333 {
334   SMB_STRUCT_STAT st;
335   char *start, *end;
336   pstring dirpath;
337   pstring orig_path;
338   int saved_errno;
339   BOOL component_was_mangled = False;
340   BOOL name_has_wildcard = False;
341 #if 0
342   /* Andrew's conservative code... JRA. */
343   extern char magic_char;
344 #endif
345
346   DEBUG(5, ("unix_convert called on file \"%s\"\n", name));
347
348   *dirpath = 0;
349   *bad_path = False;
350   if(pst) {
351           ZERO_STRUCTP(pst);
352   }
353
354   if(saved_last_component)
355     *saved_last_component = 0;
356
357   /* 
358    * Convert to basic unix format - removing \ chars and cleaning it up.
359    */
360
361   unix_format(name);
362   unix_clean_name(name);
363
364   /* 
365    * Names must be relative to the root of the service - trim any leading /.
366    * also trim trailing /'s.
367    */
368
369   trim_string(name,"/","/");
370
371   /*
372    * If we trimmed down to a single '\0' character
373    * then we should use the "." directory to avoid
374    * searching the cache, but not if we are in a
375    * printing share.
376    */
377
378   if (!*name && (!conn -> printer)) {
379     name[0] = '.';
380     name[1] = '\0';
381   }
382
383   /*
384    * Ensure saved_last_component is valid even if file exists.
385    */
386
387   if(saved_last_component) {
388     end = strrchr(name, '/');
389     if(end)
390       pstrcpy(saved_last_component, end + 1);
391     else
392       pstrcpy(saved_last_component, name);
393   }
394
395   if (!case_sensitive && 
396       (!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
397     strnorm(name);
398
399   /* 
400    * Check if it's a printer file.
401    */
402   if (conn->printer) {
403     if ((! *name) || strchr(name,'/') || !is_8_3(name, True)) {
404       char *s;
405       fstring name2;
406       slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine);
407
408       /* 
409        * Sanitise the name.
410        */
411
412       for (s=name2 ; *s ; s++)
413         if (!issafe(*s)) *s = '_';
414       pstrcpy(name,(char *)mktemp(name2));        
415     }      
416     return(True);
417   }
418
419   /*
420    * If we trimmed down to a single '\0' character
421    * then we will be using the "." directory.
422    * As we know this is valid we can return true here.
423    */
424
425   if(!*name)
426     return(True);
427
428   start = name;
429   while (strncmp(start,"./",2) == 0)
430     start += 2;
431
432   pstrcpy(orig_path, name);
433
434   if(stat_cache_lookup( name, dirpath, &start, &st)) {
435     if(pst)
436       *pst = st;
437     return True;
438   }
439
440   /* 
441    * stat the name - if it exists then we are all done!
442    */
443
444   if (conn->vfs_ops.stat(name,&st) == 0) {
445     stat_cache_add(orig_path, name);
446     DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
447     if(pst)
448       *pst = st;
449     return(True);
450   }
451
452   saved_errno = errno;
453
454   DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n",
455         name, dirpath, start));
456
457   /* 
458    * A special case - if we don't have any mangling chars and are case
459    * sensitive then searching won't help.
460    */
461
462   if (case_sensitive && !is_mangled(name) && 
463       !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT))
464     return(False);
465
466   if(strchr(start,'?') || strchr(start,'*'))
467     name_has_wildcard = True;
468
469   /* 
470    * is_mangled() was changed to look at an entire pathname, not 
471    * just a component. JRA.
472    */
473
474   if(is_mangled(start))
475     component_was_mangled = True;
476
477 #if 0
478   /* Keep Andrew's conservative code around, just in case. JRA. */
479   /* this is an extremely conservative test for mangled names. */
480   if (strchr(start,magic_char))
481     component_was_mangled = True;
482 #endif
483
484   /* 
485    * Now we need to recursively match the name against the real 
486    * directory structure.
487    */
488
489   /* 
490    * Match each part of the path name separately, trying the names
491    * as is first, then trying to scan the directory for matching names.
492    */
493
494   for (; start ; start = (end?end+1:(char *)NULL)) {
495       /* 
496        * Pinpoint the end of this section of the filename.
497        */
498       end = strchr(start, '/');
499
500       /* 
501        * Chop the name at this point.
502        */
503       if (end) 
504         *end = 0;
505
506       if(saved_last_component != 0)
507         pstrcpy(saved_last_component, end ? end + 1 : start);
508
509       /* 
510        * Check if the name exists up to this point.
511        */
512
513       if (conn->vfs_ops.stat(name, &st) == 0) {
514         /*
515          * It exists. it must either be a directory or this must be
516          * the last part of the path for it to be OK.
517          */
518         if (end && !(st.st_mode & S_IFDIR)) {
519           /*
520            * An intermediate part of the name isn't a directory.
521             */
522           DEBUG(5,("Not a dir %s\n",start));
523           *end = '/';
524           return(False);
525         }
526
527       } else {
528         pstring rest;
529
530         *rest = 0;
531
532         /*
533          * Remember the rest of the pathname so it can be restored
534          * later.
535          */
536
537         if (end)
538           pstrcpy(rest,end+1);
539
540         /*
541          * Try to find this part of the path in the directory.
542          */
543
544         if (strchr(start,'?') || strchr(start,'*') ||
545             !scan_directory(dirpath, start, conn, end?True:False)) {
546           if (end) {
547             /*
548              * An intermediate part of the name can't be found.
549              */
550             DEBUG(5,("Intermediate not found %s\n",start));
551             *end = '/';
552
553             /* 
554              * We need to return the fact that the intermediate
555              * name resolution failed. This is used to return an
556              * error of ERRbadpath rather than ERRbadfile. Some
557              * Windows applications depend on the difference between
558              * these two errors.
559              */
560             *bad_path = True;
561             return(False);
562           }
563               
564           /* 
565            * Just the last part of the name doesn't exist.
566                * We may need to strupper() or strlower() it in case
567            * this conversion is being used for file creation 
568            * purposes. If the filename is of mixed case then 
569            * don't normalise it.
570            */
571
572           if (!case_preserve && (!strhasupper(start) || !strhaslower(start)))           
573             strnorm(start);
574
575           /*
576            * check on the mangled stack to see if we can recover the 
577            * base of the filename.
578            */
579
580           if (is_mangled(start)) {
581             check_mangled_cache( start );
582           }
583
584           DEBUG(5,("New file %s\n",start));
585           return(True); 
586         }
587
588       /* 
589        * Restore the rest of the string.
590        */
591       if (end) {
592         pstrcpy(start+strlen(start)+1,rest);
593         end = start + strlen(start);
594       }
595     } /* end else */
596
597     /* 
598      * Add to the dirpath that we have resolved so far.
599      */
600     if (*dirpath)
601       pstrcat(dirpath,"/");
602
603     pstrcat(dirpath,start);
604
605     /*
606      * Don't cache a name with mangled or wildcard components
607      * as this can change the size.
608      */
609
610     if(!component_was_mangled && !name_has_wildcard)
611       stat_cache_add(orig_path, dirpath);
612
613     /* 
614      * Restore the / that we wiped out earlier.
615      */
616     if (end)
617       *end = '/';
618   }
619   
620   /*
621    * Don't cache a name with mangled or wildcard components
622    * as this can change the size.
623    */
624
625   if(!component_was_mangled && !name_has_wildcard)
626     stat_cache_add(orig_path, name);
627
628   /* 
629    * The name has been resolved.
630    */
631
632   DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
633   return(True);
634 }
635
636
637 /****************************************************************************
638 check a filename - possibly caling reducename
639
640 This is called by every routine before it allows an operation on a filename.
641 It does any final confirmation necessary to ensure that the filename is
642 a valid one for the user to access.
643 ****************************************************************************/
644 BOOL check_name(char *name,connection_struct *conn)
645 {
646   BOOL ret;
647
648   errno = 0;
649
650   if (IS_VETO_PATH(conn, name))  {
651           DEBUG(5,("file path name %s vetoed\n",name));
652           return(0);
653   }
654
655   ret = reduce_name(name,conn->connectpath,lp_widelinks(SNUM(conn)));
656
657   /* Check if we are allowing users to follow symlinks */
658   /* Patch from David Clerc <David.Clerc@cui.unige.ch>
659      University of Geneva */
660
661 #ifdef S_ISLNK
662   if (!lp_symlinks(SNUM(conn)))
663     {
664       SMB_STRUCT_STAT statbuf;
665       if ( (conn->vfs_ops.lstat(dos_to_unix(name,False),&statbuf) != -1) &&
666           (S_ISLNK(statbuf.st_mode)) )
667         {
668           DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name));
669           ret=0; 
670         }
671     }
672 #endif
673
674   if (!ret)
675     DEBUG(5,("check_name on %s failed\n",name));
676
677   return(ret);
678 }
679
680
681 /****************************************************************************
682 scan a directory to find a filename, matching without case sensitivity
683
684 If the name looks like a mangled name then try via the mangling functions
685 ****************************************************************************/
686 static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache)
687 {
688   void *cur_dir;
689   char *dname;
690   BOOL mangled;
691   pstring name2;
692
693   mangled = is_mangled(name);
694
695   /* handle null paths */
696   if (*path == 0)
697     path = ".";
698
699   if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) {
700     pstrcpy(name, dname);       
701     return(True);
702   }      
703
704   /*
705    * The incoming name can be mangled, and if we de-mangle it
706    * here it will not compare correctly against the filename (name2)
707    * read from the directory and then mangled by the name_map_mangle()
708    * call. We need to mangle both names or neither.
709    * (JRA).
710    */
711   if (mangled)
712     mangled = !check_mangled_cache( name );
713
714   /* open the directory */
715   if (!(cur_dir = OpenDir(conn, path, True))) 
716     {
717       DEBUG(3,("scan dir didn't open dir [%s]\n",path));
718       return(False);
719     }
720
721   /* now scan for matching names */
722   while ((dname = ReadDirName(cur_dir))) 
723     {
724       if (*dname == '.' &&
725           (strequal(dname,".") || strequal(dname,"..")))
726         continue;
727
728       pstrcpy(name2,dname);
729       if (!name_map_mangle(name2,False,SNUM(conn))) continue;
730
731       if ((mangled && mangled_equal(name,name2))
732           || fname_equal(name, name2))
733         {
734           /* we've found the file, change it's name and return */
735           if (docache) DirCacheAdd(path,name,dname,SNUM(conn));
736           pstrcpy(name, dname);
737           CloseDir(cur_dir);
738           return(True);
739         }
740     }
741
742   CloseDir(cur_dir);
743   return(False);
744 }