This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.
[kai/samba-autobuild/.git] / source / smbd / mangle_hash.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Name mangling
4    Copyright (C) Andrew Tridgell 1992-2002
5    Copyright (C) Simo Sorce 2001
6    Copyright (C) Andrew Bartlett 2002
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23
24 /* -------------------------------------------------------------------------- **
25  * Notable problems...
26  *
27  *  March/April 1998  CRH
28  *  - Many of the functions in this module overwrite string buffers passed to
29  *    them.  This causes a variety of problems and is, generally speaking,
30  *    dangerous and scarry.  See the kludge notes in name_map()
31  *    below.
32  *  - It seems that something is calling name_map() twice.  The
33  *    first call is probably some sort of test.  Names which contain
34  *    illegal characters are being doubly mangled.  I'm not sure, but
35  *    I'm guessing the problem is in server.c.
36  *
37  * -------------------------------------------------------------------------- **
38  */
39
40 /* -------------------------------------------------------------------------- **
41  * History...
42  *
43  *  March/April 1998  CRH
44  *  Updated a bit.  Rewrote is_mangled() to be a bit more selective.
45  *  Rewrote the mangled name cache.  Added comments here and there.
46  *  &c.
47  * -------------------------------------------------------------------------- **
48  */
49
50 #include "includes.h"
51
52
53 /* -------------------------------------------------------------------------- **
54  * External Variables...
55  */
56
57 extern int case_default;    /* Are conforming 8.3 names all upper or lower?   */
58 extern BOOL case_mangle;    /* If true, all chars in 8.3 should be same case. */
59
60 /* -------------------------------------------------------------------------- **
61  * Other stuff...
62  *
63  * magic_char     - This is the magic char used for mangling.  It's
64  *                  global.  There is a call to lp_magicchar() in server.c
65  *                  that is used to override the initial value.
66  *
67  * MANGLE_BASE    - This is the number of characters we use for name mangling.
68  *
69  * basechars      - The set characters used for name mangling.  This
70  *                  is static (scope is this file only).
71  *
72  * mangle()       - Macro used to select a character from basechars (i.e.,
73  *                  mangle(n) will return the nth digit, modulo MANGLE_BASE).
74  *
75  * chartest       - array 0..255.  The index range is the set of all possible
76  *                  values of a byte.  For each byte value, the content is a
77  *                  two nibble pair.  See BASECHAR_MASK and ILLEGAL_MASK,
78  *                  below.
79  *
80  * ct_initialized - False until the chartest array has been initialized via
81  *                  a call to init_chartest().
82  *
83  * BASECHAR_MASK  - Masks the upper nibble of a one-byte value.
84  *
85  * ILLEGAL_MASK   - Masks the lower nibble of a one-byte value.
86  *
87  * isbasecahr()   - Given a character, check the chartest array to see
88  *                  if that character is in the basechars set.  This is
89  *                  faster than using strchr_m().
90  *
91  * isillegal()    - Given a character, check the chartest array to see
92  *                  if that character is in the illegal characters set.
93  *                  This is faster than using strchr_m().
94  *
95  * mangled_cache  - Cache header used for storing mangled -> original
96  *                  reverse maps.
97  *
98  * mc_initialized - False until the mangled_cache structure has been
99  *                  initialized via a call to reset_mangled_cache().
100  *
101  * MANGLED_CACHE_MAX_ENTRIES - Default maximum number of entries for the
102  *                  cache.  A value of 0 indicates "infinite".
103  *
104  * MANGLED_CACHE_MAX_MEMORY  - Default maximum amount of memory for the
105  *                  cache.  When the cache was kept as an array of 256
106  *                  byte strings, the default cache size was 50 entries.
107  *                  This required a fixed 12.5Kbytes of memory.  The
108  *                  mangled stack parameter is no longer used (though
109  *                  this might change).  We're now using a fixed 16Kbyte
110  *                  maximum cache size.  This will probably be much more
111  *                  than 50 entries.
112  */
113
114 char magic_char = '~';
115
116 static char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%";
117 #define MANGLE_BASE       (sizeof(basechars)/sizeof(char)-1)
118
119 static unsigned char chartest[256]  = { 0 };
120 static BOOL          ct_initialized = False;
121
122 #define mangle(V) ((char)(basechars[(V) % MANGLE_BASE]))
123 #define BASECHAR_MASK 0xf0
124 #define ILLEGAL_MASK  0x0f
125 #define isbasechar(C) ( (chartest[ ((C) & 0xff) ]) & BASECHAR_MASK )
126 #define isillegal(C) ( (chartest[ ((C) & 0xff) ]) & ILLEGAL_MASK )
127
128 static ubi_cacheRoot mangled_cache[1] =  { { { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0 } };
129 static BOOL          mc_initialized   = False;
130 #define MANGLED_CACHE_MAX_ENTRIES 0
131 #define MANGLED_CACHE_MAX_MEMORY  16384
132
133
134 /* -------------------------------------------------------------------------- **
135  * External Variables...
136  */
137
138 extern int case_default;    /* Are conforming 8.3 names all upper or lower?   */
139 extern BOOL case_mangle;    /* If true, all chars in 8.3 should be same case. */
140
141 /* -------------------------------------------------------------------- */
142
143 static NTSTATUS has_valid_chars(const smb_ucs2_t *s)
144 {
145         if (!s || !*s) return NT_STATUS_INVALID_PARAMETER;
146
147         /* CHECK: this should not be necessary if the ms wild chars
148            are not valid in valid.dat  --- simo */
149         if (ms_has_wild_w(s)) return NT_STATUS_UNSUCCESSFUL;
150
151         while (*s) {
152                 if(!isvalid83_w(*s)) return NT_STATUS_UNSUCCESSFUL;
153                 s++;
154         }
155
156         return NT_STATUS_OK;
157 }
158
159 /* return False if something fail and
160  * return 2 alloced unicode strings that contain prefix and extension
161  */
162 static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix, smb_ucs2_t **extension)
163 {
164         size_t ext_len;
165         smb_ucs2_t *p;
166
167         *extension = 0;
168         *prefix = strdup_w(ucs2_string);
169         if (!*prefix) {
170                 return NT_STATUS_NO_MEMORY;
171         }
172         if ((p = strrchr_w(*prefix, UCS2_CHAR('.'))))
173         {
174                 ext_len = strlen_w(p+1);
175                 if ((ext_len > 0) && (ext_len < 4) && (p != *prefix) &&
176                     (NT_STATUS_IS_OK(has_valid_chars(p+1)))) /* check extension */
177                 {
178                         *p = 0;
179                         *extension = strdup_w(p+1);
180                         if (!*extension) {
181                                 SAFE_FREE(*prefix);
182                                 return NT_STATUS_NO_MEMORY;
183                         }
184                 }
185         }
186         return NT_STATUS_OK;
187 }
188
189 /* ************************************************************************** **
190  * Return NT_STATUS_UNSUCCESSFUL if a name is a special msdos reserved name.
191  *
192  *  Input:  fname - String containing the name to be tested.
193  *
194  *  Output: NT_STATUS_UNSUCCESSFUL, if the name matches one of the list of reserved names.
195  *
196  *  Notes:  This is a static function called by is_8_3(), below.
197  *
198  * ************************************************************************** **
199  */
200 static NTSTATUS is_valid_name(const smb_ucs2_t *fname)
201 {
202         smb_ucs2_t *str, *p;
203         NTSTATUS ret = NT_STATUS_OK;
204
205         if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER;
206
207         if (*fname == UCS2_CHAR('.')) return NT_STATUS_UNSUCCESSFUL;
208         
209         ret = has_valid_chars(fname);
210         if (NT_STATUS_IS_ERR(ret)) return ret;
211
212         str = strdup_w(fname);
213         p = strchr_w(str, UCS2_CHAR('.'));
214         if (p) *p = 0;
215         strupper_w(str);
216         p = &(str[1]);
217
218         switch(str[0])
219         {
220         case UCS2_CHAR('A'):
221                 if(strcmp_wa(p, "UX") == 0)
222                         ret = NT_STATUS_UNSUCCESSFUL;
223                 break;
224         case UCS2_CHAR('C'):
225                 if((strcmp_wa(p, "LOCK$") == 0)
226                 || (strcmp_wa(p, "ON") == 0)
227                 || (strcmp_wa(p, "OM1") == 0)
228                 || (strcmp_wa(p, "OM2") == 0)
229                 || (strcmp_wa(p, "OM3") == 0)
230                 || (strcmp_wa(p, "OM4") == 0)
231                 )
232                         ret = NT_STATUS_UNSUCCESSFUL;
233                 break;
234         case UCS2_CHAR('L'):
235                 if((strcmp_wa(p, "PT1") == 0)
236                 || (strcmp_wa(p, "PT2") == 0)
237                 || (strcmp_wa(p, "PT3") == 0)
238                 )
239                         ret = NT_STATUS_UNSUCCESSFUL;
240                 break;
241         case UCS2_CHAR('N'):
242                 if(strcmp_wa(p, "UL") == 0)
243                         ret = NT_STATUS_UNSUCCESSFUL;
244                 break;
245         case UCS2_CHAR('P'):
246                 if(strcmp_wa(p, "RN") == 0)
247                         ret = NT_STATUS_UNSUCCESSFUL;
248                 break;
249         default:
250                 break;
251         }
252
253         SAFE_FREE(str);
254         return ret;
255 }
256
257 static NTSTATUS is_8_3_w(const smb_ucs2_t *fname)
258 {
259         smb_ucs2_t *pref = 0, *ext = 0;
260         size_t plen;
261         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
262
263         if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER;
264
265         if (strlen_w(fname) > 12) return NT_STATUS_UNSUCCESSFUL;
266         
267         if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0)
268                 return NT_STATUS_OK;
269
270         if (NT_STATUS_IS_ERR(is_valid_name(fname))) goto done;
271
272         if (NT_STATUS_IS_ERR(mangle_get_prefix(fname, &pref, &ext))) goto done;
273         plen = strlen_w(pref);
274
275         if (strchr_wa(pref, '.')) goto done;
276         if (plen < 1 || plen > 8) goto done;
277         if (ext) if (strlen_w(ext) > 3) goto done;
278
279         ret = NT_STATUS_OK;
280
281 done:
282         SAFE_FREE(pref);
283         SAFE_FREE(ext);
284         return ret;
285 }
286
287 static BOOL is_8_3(const char *fname, BOOL check_case)
288 {
289         const char *f;
290         smb_ucs2_t *ucs2name;
291         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
292
293         if (!fname || !*fname) return False;
294         if ((f = strrchr(fname, '/')) == NULL) f = fname;
295         else f++;
296
297         if (strlen(f) > 12) return False;
298         
299         ucs2name = acnv_uxu2(f);
300         if (!ucs2name)
301         {
302                 DEBUG(0,("is_8_3: internal error acnv_uxu2() failed!\n"));
303                 goto done;
304         }
305
306         ret = is_8_3_w(ucs2name);
307
308 done:
309         SAFE_FREE(ucs2name);
310
311         if (!NT_STATUS_IS_OK(ret)) { 
312                 return False;
313         }
314         
315         return True;
316 }
317
318
319
320 /* -------------------------------------------------------------------------- **
321  * Functions...
322  */
323
324 /* ************************************************************************** **
325  * Initialize the static character test array.
326  *
327  *  Input:  none
328  *
329  *  Output: none
330  *
331  *  Notes:  This function changes (loads) the contents of the <chartest>
332  *          array.  The scope of <chartest> is this file.
333  *
334  * ************************************************************************** **
335  */
336 static void init_chartest( void )
337   {
338   char          *illegalchars = "*\\/?<>|\":";
339   unsigned char *s;
340   
341   memset( (char *)chartest, '\0', 256 );
342
343   for( s = (unsigned char *)illegalchars; *s; s++ )
344     chartest[*s] = ILLEGAL_MASK;
345
346   for( s = (unsigned char *)basechars; *s; s++ )
347     chartest[*s] |= BASECHAR_MASK;
348
349   ct_initialized = True;
350   } /* init_chartest */
351
352
353 /* ************************************************************************** **
354  * Return True if the name *could be* a mangled name.
355  *
356  *  Input:  s - A path name - in UNIX pathname format.
357  *
358  *  Output: True if the name matches the pattern described below in the
359  *          notes, else False.
360  *
361  *  Notes:  The input name is *not* tested for 8.3 compliance.  This must be
362  *          done separately.  This function returns true if the name contains
363  *          a magic character followed by excactly two characters from the
364  *          basechars list (above), which in turn are followed either by the
365  *          nul (end of string) byte or a dot (extension) or by a '/' (end of
366  *          a directory name).
367  *
368  * ************************************************************************** **
369  */
370 static BOOL is_mangled(const char *s)
371   {
372   char *magic;
373
374   if( !ct_initialized )
375     init_chartest();
376
377   magic = strchr_m( s, magic_char );
378   while( magic && magic[1] && magic[2] )          /* 3 chars, 1st is magic. */
379     {
380     if( ('.' == magic[3] || '/' == magic[3] || !(magic[3]))          /* Ends with '.' or nul or '/' ?  */
381      && isbasechar( toupper(magic[1]) )           /* is 2nd char basechar?  */
382      && isbasechar( toupper(magic[2]) ) )         /* is 3rd char basechar?  */
383       return( True );                           /* If all above, then true, */
384     magic = strchr_m( magic+1, magic_char );      /*    else seek next magic. */
385     }
386   return( False );
387   } /* is_mangled */
388
389
390 /* ************************************************************************** **
391  * Compare two cache keys and return a value indicating their ordinal
392  * relationship.
393  *
394  *  Input:  ItemPtr - Pointer to a comparison key.  In this case, this will
395  *                    be a mangled name string.
396  *          NodePtr - Pointer to a node in the cache.  The node structure
397  *                    will be followed in memory by a mangled name string.
398  *
399  *  Output: A signed integer, as follows:
400  *            (x < 0)  <==> Key1 less than Key2
401  *            (x == 0) <==> Key1 equals Key2
402  *            (x > 0)  <==> Key1 greater than Key2
403  *
404  *  Notes:  This is a ubiqx-style comparison routine.  See ubi_BinTree for
405  *          more info.
406  *
407  * ************************************************************************** **
408  */
409 static signed int cache_compare( ubi_btItemPtr ItemPtr, ubi_btNodePtr NodePtr )
410   {
411   char *Key1 = (char *)ItemPtr;
412   char *Key2 = (char *)(((ubi_cacheEntryPtr)NodePtr) + 1);
413
414   return( StrCaseCmp( Key1, Key2 ) );
415   } /* cache_compare */
416
417 /* ************************************************************************** **
418  * Free a cache entry.
419  *
420  *  Input:  WarrenZevon - Pointer to the entry that is to be returned to
421  *                        Nirvana.
422  *  Output: none.
423  *
424  *  Notes:  This function gets around the possibility that the standard
425  *          free() function may be implemented as a macro, or other evil
426  *          subversions (oh, so much fun).
427  *
428  * ************************************************************************** **
429  */
430 static void cache_free_entry( ubi_trNodePtr WarrenZevon )
431   {
432           ZERO_STRUCTP(WarrenZevon);
433           SAFE_FREE( WarrenZevon );
434   } /* cache_free_entry */
435
436 /* ************************************************************************** **
437  * Initializes or clears the mangled cache.
438  *
439  *  Input:  none.
440  *  Output: none.
441  *
442  *  Notes:  There is a section below that is commented out.  It shows how
443  *          one might use lp_ calls to set the maximum memory and entry size
444  *          of the cache.  You might also want to remove the constants used
445  *          in ubi_cacheInit() and replace them with lp_ calls.  If so, then
446  *          the calls to ubi_cacheSetMax*() would be moved into the else
447  *          clause.  Another option would be to pass in the max_entries and
448  *          max_memory values as parameters.  crh 09-Apr-1998.
449  *
450  * ************************************************************************** **
451  */
452 static void mangle_reset( void )
453   {
454   if( !mc_initialized )
455     {
456     (void)ubi_cacheInit( mangled_cache,
457                          cache_compare,
458                          cache_free_entry,
459                          MANGLED_CACHE_MAX_ENTRIES,
460                          MANGLED_CACHE_MAX_MEMORY );
461     mc_initialized = True;
462     }
463   else
464     {
465     (void)ubi_cacheClear( mangled_cache );
466     }
467
468   /*
469   (void)ubi_cacheSetMaxEntries( mangled_cache, lp_mangled_cache_entries() );
470   (void)ubi_cacheSetMaxMemory(  mangled_cache, lp_mangled_cache_memory() );
471   */
472   } /* reset_mangled_cache  */
473
474
475 /* ************************************************************************** **
476  * Add a mangled name into the cache.
477  *
478  *  Notes:  If the mangled cache has not been initialized, then the
479  *          function will simply fail.  It could initialize the cache,
480  *          but that's not the way it was done before I changed the
481  *          cache mechanism, so I'm sticking with the old method.
482  *
483  *          If the extension of the raw name maps directly to the
484  *          extension of the mangled name, then we'll store both names
485  *          *without* extensions.  That way, we can provide consistent
486  *          reverse mangling for all names that match.  The test here is
487  *          a bit more careful than the one done in earlier versions of
488  *          mangle.c:
489  *
490  *            - the extension must exist on the raw name,
491  *            - it must be all lower case
492  *            - it must match the mangled extension (to prove that no
493  *              mangling occurred).
494  *
495  *  crh 07-Apr-1998
496  *
497  * ************************************************************************** **
498  */
499 static void cache_mangled_name( char *mangled_name, char *raw_name )
500   {
501   ubi_cacheEntryPtr new_entry;
502   char             *s1;
503   char             *s2;
504   size_t               mangled_len;
505   size_t               raw_len;
506   size_t               i;
507
508   /* If the cache isn't initialized, give up. */
509   if( !mc_initialized )
510     return;
511
512   /* Init the string lengths. */
513   mangled_len = strlen( mangled_name );
514   raw_len     = strlen( raw_name );
515
516   /* See if the extensions are unmangled.  If so, store the entry
517    * without the extension, thus creating a "group" reverse map.
518    */
519   s1 = strrchr( mangled_name, '.' );
520   if( s1 && (s2 = strrchr( raw_name, '.' )) )
521     {
522     i = 1;
523     while( s1[i] && (tolower( s1[i] ) == s2[i]) )
524       i++;
525     if( !s1[i] && !s2[i] )
526       {
527       mangled_len -= i;
528       raw_len     -= i;
529       }
530     }
531
532   /* Allocate a new cache entry.  If the allocation fails, just return. */
533   i = sizeof( ubi_cacheEntry ) + mangled_len + raw_len + 2;
534   new_entry = malloc( i );
535   if( !new_entry )
536     return;
537
538   /* Fill the new cache entry, and add it to the cache. */
539   s1 = (char *)(new_entry + 1);
540   s2 = (char *)&(s1[mangled_len + 1]);
541   (void)StrnCpy( s1, mangled_name, mangled_len );
542   (void)StrnCpy( s2, raw_name,     raw_len );
543   ubi_cachePut( mangled_cache, i, new_entry, s1 );
544   } /* cache_mangled_name */
545
546 /* ************************************************************************** **
547  * Check for a name on the mangled name stack
548  *
549  *  Input:  s - Input *and* output string buffer.
550  *
551  *  Output: True if the name was found in the cache, else False.
552  *
553  *  Notes:  If a reverse map is found, the function will overwrite the string
554  *          space indicated by the input pointer <s>.  This is frightening.
555  *          It should be rewritten to return NULL if the long name was not
556  *          found, and a pointer to the long name if it was found.
557  *
558  * ************************************************************************** **
559  */
560
561 static BOOL check_cache( char *s )
562 {
563   ubi_cacheEntryPtr FoundPtr;
564   char             *ext_start = NULL;
565   char             *found_name;
566   char             *saved_ext = NULL;
567
568   /* If the cache isn't initialized, give up. */
569   if( !mc_initialized )
570     return( False );
571
572   FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s );
573
574   /* If we didn't find the name *with* the extension, try without. */
575   if( !FoundPtr )
576   {
577     ext_start = strrchr( s, '.' );
578     if( ext_start )
579     {
580       if((saved_ext = strdup(ext_start)) == NULL)
581         return False;
582
583       *ext_start = '\0';
584       FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s );
585       /* 
586        * At this point s is the name without the
587        * extension. We re-add the extension if saved_ext
588        * is not null, before freeing saved_ext.
589        */
590     }
591   }
592
593   /* Okay, if we haven't found it we're done. */
594   if( !FoundPtr )
595   {
596     if(saved_ext)
597     {
598       /* Replace the saved_ext as it was truncated. */
599       (void)pstrcat( s, saved_ext );
600       SAFE_FREE(saved_ext);
601     }
602     return( False );
603   }
604
605   /* If we *did* find it, we need to copy it into the string buffer. */
606   found_name = (char *)(FoundPtr + 1);
607   found_name += (strlen( found_name ) + 1);
608
609   (void)pstrcpy( s, found_name );
610   if( saved_ext )
611   {
612     /* Replace the saved_ext as it was truncated. */
613     (void)pstrcat( s, saved_ext );
614     SAFE_FREE(saved_ext);
615   }
616
617   return( True );
618 } /* check_mangled_cache */
619
620
621 /*****************************************************************************
622  * do the actual mangling to 8.3 format
623  * the buffer must be able to hold 13 characters (including the null)
624  *****************************************************************************
625  */
626 static void to_8_3(char *s)
627   {
628   int csum;
629   char *p;
630   char extension[4];
631   char base[9];
632   int baselen = 0;
633   int extlen = 0;
634
635   extension[0] = 0;
636   base[0] = 0;
637
638   p = strrchr(s,'.');  
639   if( p && (strlen(p+1) < (size_t)4) )
640     {
641     BOOL all_normal = ( strisnormal(p+1) ); /* XXXXXXXXX */
642
643     if( all_normal && p[1] != 0 )
644       {
645       *p = 0;
646       csum = str_checksum( s );
647       *p = '.';
648       }
649     else
650       csum = str_checksum(s);
651     }
652   else
653     csum = str_checksum(s);
654
655   strupper( s );
656
657   if( p )
658   {
659           if( p == s )
660                   safe_strcpy( extension, "___", 3 );
661           else
662           {
663                   *p++ = 0;
664                   while( *p && extlen < 3 )
665                   {
666                           if ( *p != '.') {
667                                   extension[extlen++] = p[0];
668                           }
669                           p++;
670                   }
671                   extension[extlen] = 0;
672       }
673   }
674   
675   p = s;
676
677   while( *p && baselen < 5 )
678   {
679           if (*p != '.') {
680                   base[baselen++] = p[0];
681           }
682           p++;
683   }
684   base[baselen] = 0;
685   
686   csum = csum % (MANGLE_BASE*MANGLE_BASE);
687   
688   (void)slprintf(s, 12, "%s%c%c%c",
689                  base, magic_char, mangle( csum/MANGLE_BASE ), mangle( csum ) );
690   
691   if( *extension )
692   {
693           (void)pstrcat( s, "." );
694           (void)pstrcat( s, extension );
695   }
696   
697   } /* mangle_name_83 */
698
699 /*****************************************************************************
700  * Convert a filename to DOS format.  Return True if successful.
701  *
702  *  Input:  OutName - Source *and* destination buffer. 
703  *
704  *                    NOTE that OutName must point to a memory space that
705  *                    is at least 13 bytes in size!
706  *
707  *          need83  - If False, name mangling will be skipped unless the
708  *                    name contains illegal characters.  Mapping will still
709  *                    be done, if appropriate.  This is probably used to
710  *                    signal that a client does not require name mangling,
711  *                    thus skipping the name mangling even on shares which
712  *                    have name-mangling turned on.
713  *          cache83 - If False, the mangled name cache will not be updated.
714  *                    This is usually used to prevent that we overwrite
715  *                    a conflicting cache entry prematurely, i.e. before
716  *                    we know whether the client is really interested in the
717  *                    current name.  (See PR#13758).  UKD.
718  *
719  *  Output: Returns False only if the name wanted mangling but the share does
720  *          not have name mangling turned on.
721  *
722  * ****************************************************************************
723  */
724 static BOOL name_map(char *OutName, BOOL need83, BOOL cache83)
725 {
726         smb_ucs2_t *OutName_ucs2;
727         DEBUG(5,("name_map( %s, need83 = %s, cache83 = %s)\n", OutName,
728                  need83 ? "True" : "False", cache83 ? "True" : "False"));
729         
730         if (push_ucs2_allocate((void **)&OutName_ucs2, OutName) < 0) {
731                 DEBUG(0, ("push_ucs2_allocate failed!\n"));
732                 return False;
733         }
734
735         /* check if it's already in 8.3 format */
736         if (need83 && !NT_STATUS_IS_OK(is_8_3_w(OutName_ucs2))) {
737                 char *tmp = NULL; 
738
739                 /* mangle it into 8.3 */
740                 if (cache83)
741                         tmp = strdup(OutName);
742
743                 to_8_3(OutName);
744
745                 if(tmp != NULL) {
746                         cache_mangled_name(OutName, tmp);
747                         SAFE_FREE(tmp);
748                 }
749         }
750
751         DEBUG(5,("name_map() ==> [%s]\n", OutName));
752         SAFE_FREE(OutName_ucs2);
753         return(True);
754 } /* name_map */
755
756
757 /*
758   the following provides the abstraction layer to make it easier
759   to drop in an alternative mangling implementation
760 */
761 static struct mangle_fns mangle_fns = {
762         is_mangled,
763         is_8_3,
764         mangle_reset,
765         check_cache,
766         name_map
767 };
768
769 /* return the methods for this mangling implementation */
770 struct mangle_fns *mangle_hash_init(void)
771 {
772         mangle_reset();
773
774         return &mangle_fns;
775 }