The big character set handling changeover!
[kai/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    Copyright (C) Jeremy Allison 1999-200
7    Copyright (C) Ying Chen 2000
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 /*
25  * New hash table stat cache code added by Ying Chen.
26  */
27
28 #include "includes.h"
29
30 extern int DEBUGLEVEL;
31 extern BOOL case_sensitive;
32 extern BOOL case_preserve;
33 extern BOOL short_case_preserve;
34 extern fstring remote_machine;
35 extern BOOL use_mangled_map;
36
37 static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache);
38
39 /****************************************************************************
40  Check if two filenames are equal.
41  This needs to be careful about whether we are case sensitive.
42 ****************************************************************************/
43 static BOOL fname_equal(char *name1, char *name2)
44 {
45   int l1 = strlen(name1);
46   int l2 = strlen(name2);
47
48   /* handle filenames ending in a single dot */
49   if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
50     {
51       BOOL ret;
52       name1[l1-1] = 0;
53       ret = fname_equal(name1,name2);
54       name1[l1-1] = '.';
55       return(ret);
56     }
57
58   if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
59     {
60       BOOL ret;
61       name2[l2-1] = 0;
62       ret = fname_equal(name1,name2);
63       name2[l2-1] = '.';
64       return(ret);
65     }
66
67   /* now normal filename handling */
68   if (case_sensitive)
69     return(strcmp(name1,name2) == 0);
70
71   return(strequal(name1,name2));
72 }
73
74
75 /****************************************************************************
76  Mangle the 2nd name and check if it is then equal to the first name.
77 ****************************************************************************/
78 static BOOL mangled_equal(char *name1, char *name2)
79 {
80   pstring tmpname;
81
82   if (is_8_3(name2, True))
83     return(False);
84
85   pstrcpy(tmpname,name2);
86   mangle_name_83(tmpname);
87
88   return(strequal(name1,tmpname));
89 }
90
91
92 /****************************************************************************
93 This routine is called to convert names from the dos namespace to unix
94 namespace. It needs to handle any case conversions, mangling, format
95 changes etc.
96
97 We assume that we have already done a chdir() to the right "root" directory
98 for this service.
99
100 The function will return False if some part of the name except for the last
101 part cannot be resolved
102
103 If the saved_last_component != 0, then the unmodified last component
104 of the pathname is returned there. This is used in an exceptional
105 case in reply_mv (so far). If saved_last_component == 0 then nothing
106 is returned there.
107
108 The bad_path arg is set to True if the filename walk failed. This is
109 used to pick the correct error code to return between ENOENT and ENOTDIR
110 as Windows applications depend on ERRbadpath being returned if a component
111 of a pathname does not exist.
112
113 On exit from unix_convert, if *pst was not null, then the file stat
114 struct will be returned if the file exists and was found, if not this
115 stat struct will be filled with zeros (and this can be detected by checking
116 for nlinks = 0, which can never be true for any file).
117 ****************************************************************************/
118
119 BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, 
120                   BOOL *bad_path, SMB_STRUCT_STAT *pst)
121 {
122   SMB_STRUCT_STAT st;
123   char *start, *end;
124   pstring dirpath;
125   pstring orig_path;
126   BOOL component_was_mangled = False;
127   BOOL name_has_wildcard = False;
128 #if 0
129   /* Andrew's conservative code... JRA. */
130   extern char magic_char;
131 #endif
132
133   ZERO_STRUCTP(pst);
134
135   *dirpath = 0;
136   *bad_path = False;
137   if(saved_last_component)
138     *saved_last_component = 0;
139
140   if (conn->printer) {
141           /* we don't ever use the filenames on a printer share as a
142              filename - so don't convert them */
143           return True;
144   }
145
146   DEBUG(5, ("unix_convert called on file \"%s\"\n", name));
147
148   /* 
149    * Convert to basic unix format - removing \ chars and cleaning it up.
150    */
151
152   unix_format(name);
153   unix_clean_name(name);
154
155   /* 
156    * Names must be relative to the root of the service - trim any leading /.
157    * also trim trailing /'s.
158    */
159
160   trim_string(name,"/","/");
161
162   /*
163    * If we trimmed down to a single '\0' character
164    * then we should use the "." directory to avoid
165    * searching the cache, but not if we are in a
166    * printing share.
167    */
168
169   if (!*name) {
170     name[0] = '.';
171     name[1] = '\0';
172   }
173
174   /*
175    * Ensure saved_last_component is valid even if file exists.
176    */
177
178   if(saved_last_component) {
179     end = strrchr(name, '/');
180     if(end)
181       pstrcpy(saved_last_component, end + 1);
182     else
183       pstrcpy(saved_last_component, name);
184   }
185
186   if (!case_sensitive && 
187       (!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
188     strnorm(name);
189
190   /*
191    * If we trimmed down to a single '\0' character
192    * then we will be using the "." directory.
193    * As we know this is valid we can return true here.
194    */
195
196   if(!*name)
197     return(True);
198
199   start = name;
200   while (strncmp(start,"./",2) == 0)
201     start += 2;
202
203   pstrcpy(orig_path, name);
204
205   if(stat_cache_lookup(conn, name, dirpath, &start, &st)) {
206     *pst = st;
207     return True;
208   }
209
210   /* 
211    * stat the name - if it exists then we are all done!
212    */
213
214   if (vfs_stat(conn,name,&st) == 0) {
215     stat_cache_add(orig_path, name);
216     DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
217     *pst = st;
218     return(True);
219   }
220
221   DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n",
222         name, dirpath, start));
223
224   /* 
225    * A special case - if we don't have any mangling chars and are case
226    * sensitive then searching won't help.
227    */
228
229   if (case_sensitive && !is_mangled(name) && 
230       !lp_strip_dot() && !use_mangled_map)
231     return(False);
232
233   name_has_wildcard = ms_has_wild(start);
234
235   /* 
236    * is_mangled() was changed to look at an entire pathname, not 
237    * just a component. JRA.
238    */
239
240   if(is_mangled(start))
241     component_was_mangled = True;
242
243 #if 0
244   /* Keep Andrew's conservative code around, just in case. JRA. */
245   /* this is an extremely conservative test for mangled names. */
246   if (strchr(start,magic_char))
247     component_was_mangled = True;
248 #endif
249
250   /* 
251    * Now we need to recursively match the name against the real 
252    * directory structure.
253    */
254
255   /* 
256    * Match each part of the path name separately, trying the names
257    * as is first, then trying to scan the directory for matching names.
258    */
259
260   for (; start ; start = (end?end+1:(char *)NULL)) {
261       /* 
262        * Pinpoint the end of this section of the filename.
263        */
264       end = strchr(start, '/');
265
266       /* 
267        * Chop the name at this point.
268        */
269       if (end) 
270         *end = 0;
271
272       if(saved_last_component != 0)
273         pstrcpy(saved_last_component, end ? end + 1 : start);
274
275       /* 
276        * Check if the name exists up to this point.
277        */
278
279       if (vfs_stat(conn,name, &st) == 0) {
280         /*
281          * It exists. it must either be a directory or this must be
282          * the last part of the path for it to be OK.
283          */
284         if (end && !(st.st_mode & S_IFDIR)) {
285           /*
286            * An intermediate part of the name isn't a directory.
287             */
288           DEBUG(5,("Not a dir %s\n",start));
289           *end = '/';
290           return(False);
291         }
292
293       } else {
294         pstring rest;
295
296                 /* Stat failed - ensure we don't use it. */
297         ZERO_STRUCT(st);
298         *rest = 0;
299
300         /*
301          * Remember the rest of the pathname so it can be restored
302          * later.
303          */
304
305         if (end)
306           pstrcpy(rest,end+1);
307
308         /*
309          * Try to find this part of the path in the directory.
310          */
311
312         if (ms_has_wild(start) || !scan_directory(dirpath, start, conn, end?True:False)) {
313           if (end) {
314             /*
315              * An intermediate part of the name can't be found.
316              */
317             DEBUG(5,("Intermediate not found %s\n",start));
318             *end = '/';
319
320             /* 
321              * We need to return the fact that the intermediate
322              * name resolution failed. This is used to return an
323              * error of ERRbadpath rather than ERRbadfile. Some
324              * Windows applications depend on the difference between
325              * these two errors.
326              */
327             *bad_path = True;
328             return(False);
329           }
330               
331           /* 
332            * Just the last part of the name doesn't exist.
333                * We may need to strupper() or strlower() it in case
334            * this conversion is being used for file creation 
335            * purposes. If the filename is of mixed case then 
336            * don't normalise it.
337            */
338
339           if (!case_preserve && (!strhasupper(start) || !strhaslower(start)))           
340             strnorm(start);
341
342           /*
343            * check on the mangled stack to see if we can recover the 
344            * base of the filename.
345            */
346
347           if (is_mangled(start)) {
348             check_mangled_cache( start );
349           }
350
351           DEBUG(5,("New file %s\n",start));
352           return(True); 
353         }
354
355       /* 
356        * Restore the rest of the string.
357        */
358       if (end) {
359         pstrcpy(start+strlen(start)+1,rest);
360         end = start + strlen(start);
361       }
362     } /* end else */
363
364     /* 
365      * Add to the dirpath that we have resolved so far.
366      */
367     if (*dirpath)
368       pstrcat(dirpath,"/");
369
370     pstrcat(dirpath,start);
371
372     /*
373      * Don't cache a name with mangled or wildcard components
374      * as this can change the size.
375      */
376
377     if(!component_was_mangled && !name_has_wildcard)
378       stat_cache_add(orig_path, dirpath);
379
380     /* 
381      * Restore the / that we wiped out earlier.
382      */
383     if (end)
384       *end = '/';
385   }
386   
387   /*
388    * Don't cache a name with mangled or wildcard components
389    * as this can change the size.
390    */
391
392   if(!component_was_mangled && !name_has_wildcard)
393     stat_cache_add(orig_path, name);
394
395   /*
396    * If we ended up resolving the entire path then return a valid
397    * stat struct if we got one.
398    */
399
400   if (VALID_STAT(st) && (strlen(orig_path) == strlen(name)))
401     *pst = st;
402
403   /* 
404    * The name has been resolved.
405    */
406
407   DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
408   return(True);
409 }
410
411
412 /****************************************************************************
413 check a filename - possibly caling reducename
414
415 This is called by every routine before it allows an operation on a filename.
416 It does any final confirmation necessary to ensure that the filename is
417 a valid one for the user to access.
418 ****************************************************************************/
419 BOOL check_name(char *name,connection_struct *conn)
420 {
421   BOOL ret;
422
423   errno = 0;
424
425   if (IS_VETO_PATH(conn, name))  {
426           DEBUG(5,("file path name %s vetoed\n",name));
427           return(0);
428   }
429
430   ret = reduce_name(conn,name,conn->connectpath,lp_widelinks(SNUM(conn)));
431
432   /* Check if we are allowing users to follow symlinks */
433   /* Patch from David Clerc <David.Clerc@cui.unige.ch>
434      University of Geneva */
435
436 #ifdef S_ISLNK
437   if (!lp_symlinks(SNUM(conn))) {
438       SMB_STRUCT_STAT statbuf;
439       if ( (conn->vfs_ops.lstat(conn,name,&statbuf) != -1) &&
440                 (S_ISLNK(statbuf.st_mode)) ) {
441           DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name));
442           ret=0; 
443       }
444     }
445 #endif
446
447   if (!ret)
448     DEBUG(5,("check_name on %s failed\n",name));
449
450   return(ret);
451 }
452
453
454 /****************************************************************************
455 scan a directory to find a filename, matching without case sensitivity
456
457 If the name looks like a mangled name then try via the mangling functions
458 ****************************************************************************/
459 static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache)
460 {
461   void *cur_dir;
462   char *dname;
463   BOOL mangled;
464   pstring name2;
465
466   mangled = is_mangled(name);
467
468   /* handle null paths */
469   if (*path == 0)
470     path = ".";
471
472   if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) {
473     pstrcpy(name, dname);       
474     return(True);
475   }      
476
477   /*
478    * The incoming name can be mangled, and if we de-mangle it
479    * here it will not compare correctly against the filename (name2)
480    * read from the directory and then mangled by the name_map_mangle()
481    * call. We need to mangle both names or neither.
482    * (JRA).
483    */
484   if (mangled)
485     mangled = !check_mangled_cache( name );
486
487   /* open the directory */
488   if (!(cur_dir = OpenDir(conn, path, True))) {
489       DEBUG(3,("scan dir didn't open dir [%s]\n",path));
490       return(False);
491   }
492
493   /* now scan for matching names */
494   while ((dname = ReadDirName(cur_dir))) {
495       if (*dname == '.' && (strequal(dname,".") || strequal(dname,"..")))
496         continue;
497
498       pstrcpy(name2,dname);
499       if (!name_map_mangle(name2,False,True,SNUM(conn)))
500         continue;
501
502       if ((mangled && mangled_equal(name,name2)) || fname_equal(name, name2)) {
503         /* we've found the file, change it's name and return */
504         if (docache)
505           DirCacheAdd(path,name,dname,SNUM(conn));
506         pstrcpy(name, dname);
507         CloseDir(cur_dir);
508         return(True);
509     }
510   }
511
512   CloseDir(cur_dir);
513   return(False);
514 }