smbd: remove dead code
[samba.git] / source3 / smbd / mangle_hash2.c
1 /* 
2    Unix SMB/CIFS implementation.
3    new hash based name mangling implementation
4    Copyright (C) Andrew Tridgell 2002
5    Copyright (C) Simo Sorce 2002
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 3 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, see <http://www.gnu.org/licenses/>.
19 */
20
21 /*
22   this mangling scheme uses the following format
23
24   Annnn~n.AAA
25
26   where nnnnn is a base 36 hash, and A represents characters from the original string
27
28   The hash is taken of the leading part of the long filename, in uppercase
29
30   for simplicity, we only allow ascii characters in 8.3 names
31  */
32
33  /* hash alghorithm changed to FNV1 by idra@samba.org (Simo Sorce).
34   * see http://www.isthe.com/chongo/tech/comp/fnv/index.html for a
35   * discussion on Fowler / Noll / Vo (FNV) Hash by one of it's authors
36   */
37
38 /*
39   ===============================================================================
40   NOTE NOTE NOTE!!!
41
42   This file deliberately uses non-multibyte string functions in many places. This
43   is *not* a mistake. This code is multi-byte safe, but it gets this property
44   through some very subtle knowledge of the way multi-byte strings are encoded 
45   and the fact that this mangling algorithm only supports ascii characters in
46   8.3 names.
47
48   please don't convert this file to use the *_m() functions!!
49   ===============================================================================
50 */
51
52 /*
53  * ============================================================================
54  * Whenever you change anything in the FLAG_ or other fields,
55  * re-initialize the tables char_flags and base_reverse by running the
56  * init_tables() routine once and dump its results. To do this, a
57  * single smbd run with
58  *
59  * #define DYNAMIC_MANGLE_TABLES 1
60  *
61  * and debug level 10 should be sufficient.
62  * ============================================================================
63  */
64
65
66 #include "includes.h"
67 #include "smbd/smbd.h"
68 #include "smbd/globals.h"
69 #include "../lib/util/memcache.h"
70 #include "mangle.h"
71
72 #if 1
73 #define M_DEBUG(level, x) DEBUG(level, x)
74 #else
75 #define M_DEBUG(level, x)
76 #endif
77
78 /* these flags are used to mark characters in as having particular
79    properties */
80 #define FLAG_BASECHAR 1
81 #define FLAG_ASCII 2
82 #define FLAG_ILLEGAL 4
83 #define FLAG_WILDCARD 8
84
85 /* the "possible" flags are used as a fast way to find possible DOS
86    reserved filenames */
87 #define FLAG_POSSIBLE1 16
88 #define FLAG_POSSIBLE2 32
89 #define FLAG_POSSIBLE3 64
90 #define FLAG_POSSIBLE4 128
91
92 #define FNV1_PRIME 0x01000193
93 /*the following number is a fnv1 of the string: idra@samba.org 2002 */
94 #define FNV1_INIT  0xa6b93095
95
96 #define FLAG_CHECK(c, flag) (char_flags[(unsigned char)(c)] & (flag))
97
98 /* these are the characters we use in the 8.3 hash. Must be 36 chars long */
99 static const char basechars[36] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
100 #define base_forward(v) basechars[v]
101
102 /* the list of reserved dos names - all of these are illegal */
103 static const char * const reserved_names[] =
104 { "AUX", "LOCK$", "CON", "COM1", "COM2", "COM3", "COM4",
105   "LPT1", "LPT2", "LPT3", "NUL", "PRN", NULL };
106
107 #define DYNAMIC_MANGLE_TABLES 0
108
109 #if DYNAMIC_MANGLE_TABLES
110
111 /* these tables are used to provide fast tests for characters */
112 static unsigned char char_flags[256];
113 static unsigned char base_reverse[256];
114
115 /* initialise the flags table
116
117   we allow only a very restricted set of characters as 'ascii' in this
118   mangling backend. This isn't a significant problem as modern clients
119   use the 'long' filenames anyway, and those don't have these
120   restrictions.
121 */
122 static void init_tables(void)
123 {
124         int i;
125
126         memset(char_flags, 0, sizeof(char_flags));
127
128         for (i=1;i<128;i++) {
129                 if (i <= 0x1f) {
130                         /* Control characters. */
131                         char_flags[i] |= FLAG_ILLEGAL;
132                 }
133
134                 if ((i >= '0' && i <= '9') ||
135                     (i >= 'a' && i <= 'z') ||
136                     (i >= 'A' && i <= 'Z')) {
137                         char_flags[i] |=  (FLAG_ASCII | FLAG_BASECHAR);
138                 }
139                 if (strchr("_-$~", i)) {
140                         char_flags[i] |= FLAG_ASCII;
141                 }
142
143                 if (strchr("*\\/?<>|\":", i)) {
144                         char_flags[i] |= FLAG_ILLEGAL;
145                 }
146
147                 if (strchr("*?\"<>", i)) {
148                         char_flags[i] |= FLAG_WILDCARD;
149                 }
150         }
151
152         memset(base_reverse, 0, sizeof(base_reverse));
153         for (i=0;i<36;i++) {
154                 base_reverse[(unsigned char)base_forward(i)] = i;
155         }
156
157         /* fill in the reserved names flags. These are used as a very
158            fast filter for finding possible DOS reserved filenames */
159         for (i=0; reserved_names[i]; i++) {
160                 unsigned char c1, c2, c3, c4;
161
162                 c1 = (unsigned char)reserved_names[i][0];
163                 c2 = (unsigned char)reserved_names[i][1];
164                 c3 = (unsigned char)reserved_names[i][2];
165                 c4 = (unsigned char)reserved_names[i][3];
166
167                 char_flags[c1] |= FLAG_POSSIBLE1;
168                 char_flags[c2] |= FLAG_POSSIBLE2;
169                 char_flags[c3] |= FLAG_POSSIBLE3;
170                 char_flags[c4] |= FLAG_POSSIBLE4;
171                 char_flags[tolower_m(c1)] |= FLAG_POSSIBLE1;
172                 char_flags[tolower_m(c2)] |= FLAG_POSSIBLE2;
173                 char_flags[tolower_m(c3)] |= FLAG_POSSIBLE3;
174                 char_flags[tolower_m(c4)] |= FLAG_POSSIBLE4;
175
176                 char_flags[(unsigned char)'.'] |= FLAG_POSSIBLE4;
177         }
178
179 #if 0
180         DEBUG(10, ("char_flags\n"));
181         dump_data(10, char_flags, sizeof(char_flags));
182
183         DEBUG(10, ("base_reverse\n"));
184         dump_data(10, base_reverse, sizeof(base_reverse));
185 #endif
186 }
187
188 #else /* DYNAMIC_MANGLE_TABLES */
189
190 /*
191  * These tables were initialized by a single run of the above
192  * init_tables() routine, dumping the tables and a simple emacs macro.
193  *
194  * Technically we could leave out the 0's at the end of the array
195  * initializers, but I'll leave it in: less surprise.
196  */
197
198 static const uint8_t char_flags[256] = {
199         0x80, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
200         0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
201         0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
202         0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
203         0x00, 0x00, 0x0C, 0x00, 0x02, 0x00, 0x00, 0x00,
204         0x00, 0x00, 0x0C, 0x00, 0x00, 0x02, 0x80, 0x04,
205         0x03, 0x83, 0x83, 0x83, 0x83, 0x03, 0x03, 0x03,
206         0x03, 0x03, 0x04, 0x00, 0x0C, 0x00, 0x0C, 0x0C,
207         0x00, 0x13, 0x03, 0x53, 0x03, 0x03, 0x03, 0x03,
208         0x03, 0x03, 0x03, 0x83, 0x53, 0x43, 0x53, 0x23,
209         0x33, 0x03, 0x23, 0x03, 0x43, 0x23, 0x03, 0x03,
210         0x43, 0x03, 0x03, 0x00, 0x04, 0x00, 0x00, 0x02,
211         0x00, 0x13, 0x03, 0x53, 0x03, 0x03, 0x03, 0x03,
212         0x03, 0x03, 0x03, 0x83, 0x53, 0x43, 0x53, 0x23,
213         0x33, 0x03, 0x23, 0x03, 0x43, 0x23, 0x03, 0x03,
214         0x43, 0x03, 0x03, 0x00, 0x04, 0x00, 0x02, 0x00,
215         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
216         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
221         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
222         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
223         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
224         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
225         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
226         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
227         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
230         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
231 };
232
233 static const uint8_t base_reverse[256] = {
234         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
239         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
240         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
241         0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
242         0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
243         0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
244         0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
245         0x21, 0x22, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00,
246         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
247         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
248         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
249         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
250         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
251         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
252         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
253         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
254         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
255         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
256         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
257         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
258         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
259         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
260         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
261         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
262         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
263         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
264         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
265         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
266 };
267
268 #endif /* DYNAMIC_MANGLE_TABLES */
269
270 /* 
271    hash a string of the specified length. The string does not need to be
272    null terminated 
273
274    this hash needs to be fast with a low collision rate (what hash doesn't?)
275 */
276 static unsigned int mangle_hash(const char *key, unsigned int length)
277 {
278         unsigned int value;
279         unsigned int   i;
280         fstring str;
281
282         /* we have to uppercase here to ensure that the mangled name
283            doesn't depend on the case of the long name. Note that this
284            is the only place where we need to use a multi-byte string
285            function */
286         length = MIN(length,sizeof(fstring)-1);
287         strncpy(str, key, length);
288         str[length] = 0;
289         (void)strupper_m(str);
290
291         /* the length of a multi-byte string can change after a strupper_m */
292         length = strlen(str);
293
294         /* Set the initial value from the key size. */
295         for (value = FNV1_INIT, i=0; i < length; i++) {
296                 value *= (unsigned int)FNV1_PRIME;
297                 value ^= (unsigned int)(str[i]);
298         }
299
300         /* note that we force it to a 31 bit hash, to keep within the limits
301            of the 36^6 mangle space */
302         return value & ~0x80000000;  
303 }
304
305 /*
306   insert an entry into the prefix cache. The string might not be null
307   terminated */
308 static void cache_insert(const char *prefix, int length, unsigned int hash)
309 {
310         char *str = SMB_STRNDUP(prefix, length);
311
312         if (str == NULL) {
313                 return;
314         }
315
316         memcache_add(smbd_memcache(), MANGLE_HASH2_CACHE,
317                      data_blob_const(&hash, sizeof(hash)),
318                      data_blob_const(str, length+1));
319         SAFE_FREE(str);
320 }
321
322 /*
323   lookup an entry in the prefix cache. Return NULL if not found.
324 */
325 static char *cache_lookup(TALLOC_CTX *mem_ctx, unsigned int hash)
326 {
327         DATA_BLOB value;
328
329         if (!memcache_lookup(smbd_memcache(), MANGLE_HASH2_CACHE,
330                              data_blob_const(&hash, sizeof(hash)), &value)) {
331                 return NULL;
332         }
333
334         SMB_ASSERT((value.length > 0)
335                    && (value.data[value.length-1] == '\0'));
336
337         return talloc_strdup(mem_ctx, (char *)value.data);
338 }
339
340
341 /* 
342    determine if a string is possibly in a mangled format, ignoring
343    case 
344
345    In this algorithm, mangled names use only pure ascii characters (no
346    multi-byte) so we can avoid doing a UCS2 conversion 
347  */
348 static bool is_mangled_component(const char *name, size_t len)
349 {
350         unsigned int i;
351
352         M_DEBUG(10,("is_mangled_component %s (len %lu) ?\n", name, (unsigned long)len));
353
354         /* check the length */
355         if (len > 12 || len < 8)
356                 return False;
357
358         /* the best distinguishing characteristic is the ~ */
359         if (name[6] != '~')
360                 return False;
361
362         /* check extension */
363         if (len > 8) {
364                 if (name[8] != '.')
365                         return False;
366                 for (i=9; name[i] && i < len; i++) {
367                         if (! FLAG_CHECK(name[i], FLAG_ASCII)) {
368                                 return False;
369                         }
370                 }
371         }
372         
373         /* check lead characters */
374         for (i=0;i<mangle_prefix;i++) {
375                 if (! FLAG_CHECK(name[i], FLAG_ASCII)) {
376                         return False;
377                 }
378         }
379         
380         /* check rest of hash */
381         if (! FLAG_CHECK(name[7], FLAG_BASECHAR)) {
382                 return False;
383         }
384         for (i=mangle_prefix;i<6;i++) {
385                 if (! FLAG_CHECK(name[i], FLAG_BASECHAR)) {
386                         return False;
387                 }
388         }
389
390         M_DEBUG(10,("is_mangled_component %s (len %lu) -> yes\n", name, (unsigned long)len));
391
392         return True;
393 }
394
395
396
397 /* 
398    determine if a string is possibly in a mangled format, ignoring
399    case 
400
401    In this algorithm, mangled names use only pure ascii characters (no
402    multi-byte) so we can avoid doing a UCS2 conversion 
403
404    NOTE! This interface must be able to handle a path with unix
405    directory separators. It should return true if any component is
406    mangled
407  */
408 static bool is_mangled(const char *name, const struct share_params *parm)
409 {
410         const char *p;
411         const char *s;
412
413         M_DEBUG(10,("is_mangled %s ?\n", name));
414
415         for (s=name; (p=strchr(s, '/')); s=p+1) {
416                 if (is_mangled_component(s, PTR_DIFF(p, s))) {
417                         return True;
418                 }
419         }
420         
421         /* and the last part ... */
422         return is_mangled_component(s,strlen(s));
423 }
424
425
426 /* 
427    see if a filename is an allowable 8.3 name to return to the client.
428    Note this is not testing if this is a valid Samba mangled name, so
429    the rules are different for is_mangled.
430
431    we are only going to allow ascii characters in 8.3 names, as this
432    simplifies things greatly (it means that we know the string won't
433    get larger when converted from UNIX to DOS formats)
434 */
435
436 static const char force_shortname_chars[] = " +,[];=";
437
438 static bool is_8_3(const char *name, bool check_case, bool allow_wildcards, const struct share_params *p)
439 {
440         int len, i;
441         char *dot_p;
442
443         /* as a special case, the names '.' and '..' are allowable 8.3 names */
444         if (name[0] == '.') {
445                 if (!name[1] || (name[1] == '.' && !name[2])) {
446                         return True;
447                 }
448         }
449
450         /* the simplest test is on the overall length of the
451          filename. Note that we deliberately use the ascii string
452          length (not the multi-byte one) as it is faster, and gives us
453          the result we need in this case. Using strlen_m would not
454          only be slower, it would be incorrect */
455         len = strlen(name);
456         if (len > 12)
457                 return False;
458
459         /* find the '.'. Note that once again we use the non-multibyte
460            function */
461         dot_p = strchr(name, '.');
462
463         if (!dot_p) {
464                 /* if the name doesn't contain a '.' then its length
465                    must be less than 8 */
466                 if (len > 8) {
467                         return False;
468                 }
469         } else {
470                 int prefix_len, suffix_len;
471
472                 /* if it does contain a dot then the prefix must be <=
473                    8 and the suffix <= 3 in length */
474                 prefix_len = PTR_DIFF(dot_p, name);
475                 suffix_len = len - (prefix_len+1);
476
477                 if (prefix_len > 8 || suffix_len > 3 || suffix_len == 0) {
478                         return False;
479                 }
480
481                 /* a 8.3 name cannot contain more than 1 '.' */
482                 if (strchr(dot_p+1, '.')) {
483                         return False;
484                 }
485         }
486
487         /* the length are all OK. Now check to see if the characters themselves are OK */
488         for (i=0; name[i]; i++) {
489                 if (FLAG_CHECK(name[i], FLAG_ILLEGAL)) {
490                         return false;
491                 }
492                 /* note that we may allow wildcard petterns! */
493                 if (!allow_wildcards && FLAG_CHECK(name[i], FLAG_WILDCARD)) {
494                         return false;
495                 }
496                 if (((unsigned char)name[i]) > 0x7e) {
497                         return false;
498                 }
499                 if (strchr(force_shortname_chars, name[i])) {
500                         return false;
501                 }
502         }
503
504         /* it is a good 8.3 name */
505         return True;
506 }
507
508
509 /*
510   reset the mangling cache on a smb.conf reload. This only really makes sense for
511   mangling backends that have parameters in smb.conf, and as this backend doesn't
512   this is a NULL operation
513 */
514 static void mangle_reset(void)
515 {
516         /* noop */
517 }
518
519
520 /*
521   try to find a 8.3 name in the cache, and if found then
522   replace the string with the original long name.
523 */
524 static bool lookup_name_from_8_3(TALLOC_CTX *ctx,
525                         const char *name,
526                         char **pp_out, /* talloced on the given context. */
527                         const struct share_params *p)
528 {
529         unsigned int hash, multiplier;
530         unsigned int i;
531         char *prefix;
532         char extension[4];
533
534         *pp_out = NULL;
535
536         /* make sure that this is a mangled name from this cache */
537         if (!is_mangled(name, p)) {
538                 M_DEBUG(10,("lookup_name_from_8_3: %s -> not mangled\n", name));
539                 return False;
540         }
541
542         /* we need to extract the hash from the 8.3 name */
543         hash = base_reverse[(unsigned char)name[7]];
544         for (multiplier=36, i=5;i>=mangle_prefix;i--) {
545                 unsigned int v = base_reverse[(unsigned char)name[i]];
546                 hash += multiplier * v;
547                 multiplier *= 36;
548         }
549
550         /* now look in the prefix cache for that hash */
551         prefix = cache_lookup(ctx, hash);
552         if (!prefix) {
553                 M_DEBUG(10,("lookup_name_from_8_3: %s -> %08X -> not found\n",
554                                         name, hash));
555                 return False;
556         }
557
558         /* we found it - construct the full name */
559         if (name[8] == '.') {
560                 strncpy(extension, name+9, 3);
561                 extension[3] = 0;
562         } else {
563                 extension[0] = 0;
564         }
565
566         if (extension[0]) {
567                 M_DEBUG(10,("lookup_name_from_8_3: %s -> %s.%s\n",
568                                         name, prefix, extension));
569                 *pp_out = talloc_asprintf(ctx, "%s.%s", prefix, extension);
570         } else {
571                 M_DEBUG(10,("lookup_name_from_8_3: %s -> %s\n", name, prefix));
572                 *pp_out = talloc_strdup(ctx, prefix);
573         }
574
575         TALLOC_FREE(prefix);
576
577         if (!*pp_out) {
578                 M_DEBUG(0,("talloc_fail"));
579                 return False;
580         }
581
582         return True;
583 }
584
585 /*
586   look for a DOS reserved name
587 */
588 static bool is_reserved_name(const char *name)
589 {
590         if (FLAG_CHECK(name[0], FLAG_POSSIBLE1) &&
591             FLAG_CHECK(name[1], FLAG_POSSIBLE2) &&
592             FLAG_CHECK(name[2], FLAG_POSSIBLE3) &&
593             FLAG_CHECK(name[3], FLAG_POSSIBLE4)) {
594                 /* a likely match, scan the lot */
595                 int i;
596                 for (i=0; reserved_names[i]; i++) {
597                         int len = strlen(reserved_names[i]);
598                         /* note that we match on COM1 as well as COM1.foo */
599                         if (strnequal(name, reserved_names[i], len) &&
600                             (name[len] == '.' || name[len] == 0)) {
601                                 return True;
602                         }
603                 }
604         }
605
606         return False;
607 }
608
609 /*
610  See if a filename is a legal long filename.
611  A filename ending in a '.' is not legal unless it's "." or "..". JRA.
612  A filename ending in ' ' is not legal either. See bug id #2769.
613 */
614
615 static bool is_legal_name(const char *name)
616 {
617         const char *dot_pos = NULL;
618         bool alldots = True;
619         size_t numdots = 0;
620
621         while (*name) {
622                 if (((unsigned int)name[0]) > 128 && (name[1] != 0)) {
623                         /* Possible start of mb character. */
624                         size_t size = 0;
625                         (void)next_codepoint(name, &size);
626                         /*
627                          * Note that we're only looking for multibyte
628                          * encoding here. No encoding with a length > 1
629                          * contains invalid characters.
630                          */
631                         if (size > 1) {
632                                 /* Was a mb string. */
633                                 name += size;
634                                 continue;
635                         }
636                 }
637
638                 if (FLAG_CHECK(name[0], FLAG_ILLEGAL)) {
639                         return False;
640                 }
641                 if (name[0] == '.') {
642                         dot_pos = name;
643                         numdots++;
644                 } else {
645                         alldots = False;
646                 }
647                 if ((name[0] == ' ') && (name[1] == '\0')) {
648                         /* Can't end in ' ' */
649                         return False;
650                 }
651                 name++;
652         }
653
654         if (dot_pos) {
655                 if (alldots && (numdots == 1 || numdots == 2))
656                         return True; /* . or .. is a valid name */
657
658                 /* A valid long name cannot end in '.' */
659                 if (dot_pos[1] == '\0')
660                         return False;
661         }
662         return True;
663 }
664
665 static bool must_mangle(const char *name,
666                         const struct share_params *p)
667 {
668         if (is_reserved_name(name)) {
669                 return True;
670         }
671         return !is_legal_name(name);
672 }
673
674 /*
675   the main forward mapping function, which converts a long filename to 
676   a 8.3 name
677
678   if cache83 is not set then we don't cache the result
679
680 */
681 static bool hash2_name_to_8_3(const char *name,
682                         char new_name[13],
683                         bool cache83,
684                         int default_case,
685                         const struct share_params *p)
686 {
687         char *dot_p;
688         char lead_chars[7];
689         char extension[4];
690         unsigned int extension_length, i;
691         unsigned int prefix_len;
692         unsigned int hash, v;
693
694         /* reserved names are handled specially */
695         if (!is_reserved_name(name)) {
696                 /* if the name is already a valid 8.3 name then we don't need to
697                  * change anything */
698                 if (is_legal_name(name) && is_8_3(name, False, False, p)) {
699                         strlcpy(new_name, name, 13);
700                         return True;
701                 }
702         }
703
704         /* find the '.' if any */
705         dot_p = strrchr(name, '.');
706
707         if (dot_p) {
708                 /* if the extension contains any illegal characters or
709                    is too long or zero length then we treat it as part
710                    of the prefix */
711                 for (i=0; i<4 && dot_p[i+1]; i++) {
712                         if (! FLAG_CHECK(dot_p[i+1], FLAG_ASCII)) {
713                                 dot_p = NULL;
714                                 break;
715                         }
716                 }
717                 if (i == 0 || i == 4) {
718                         dot_p = NULL;
719                 }
720         }
721
722         /* the leading characters in the mangled name is taken from
723            the first characters of the name, if they are ascii otherwise
724            '_' is used
725         */
726         for (i=0;i<mangle_prefix && name[i];i++) {
727                 lead_chars[i] = name[i];
728                 if (! FLAG_CHECK(lead_chars[i], FLAG_ASCII)) {
729                         lead_chars[i] = '_';
730                 }
731                 lead_chars[i] = toupper_m(lead_chars[i]);
732         }
733         for (;i<mangle_prefix;i++) {
734                 lead_chars[i] = '_';
735         }
736
737         /* the prefix is anything up to the first dot */
738         if (dot_p) {
739                 prefix_len = PTR_DIFF(dot_p, name);
740         } else {
741                 prefix_len = strlen(name);
742         }
743
744         /* the extension of the mangled name is taken from the first 3
745            ascii chars after the dot */
746         extension_length = 0;
747         if (dot_p) {
748                 for (i=1; extension_length < 3 && dot_p[i]; i++) {
749                         char c = dot_p[i];
750                         if (FLAG_CHECK(c, FLAG_ASCII)) {
751                                 extension[extension_length++] =
752                                         toupper_m(c);
753                         }
754                 }
755         }
756
757         /* find the hash for this prefix */
758         v = hash = mangle_hash(name, prefix_len);
759
760         /* now form the mangled name. */
761         for (i=0;i<mangle_prefix;i++) {
762                 new_name[i] = lead_chars[i];
763         }
764         new_name[7] = base_forward(v % 36);
765         new_name[6] = '~';
766         for (i=5; i>=mangle_prefix; i--) {
767                 v = v / 36;
768                 new_name[i] = base_forward(v % 36);
769         }
770
771         /* add the extension */
772         if (extension_length) {
773                 new_name[8] = '.';
774                 memcpy(&new_name[9], extension, extension_length);
775                 new_name[9+extension_length] = 0;
776         } else {
777                 new_name[8] = 0;
778         }
779
780         if (cache83) {
781                 /* put it in the cache */
782                 cache_insert(name, prefix_len, hash);
783         }
784
785         M_DEBUG(10,("hash2_name_to_8_3: %s -> %08X -> %s (cache=%d)\n",
786                    name, hash, new_name, cache83));
787
788         return True;
789 }
790
791 /*
792   the following provides the abstraction layer to make it easier
793   to drop in an alternative mangling implementation */
794 static const struct mangle_fns mangle_hash2_fns = {
795         mangle_reset,
796         is_mangled,
797         must_mangle,
798         is_8_3,
799         lookup_name_from_8_3,
800         hash2_name_to_8_3
801 };
802
803 /* return the methods for this mangling implementation */
804 const struct mangle_fns *mangle_hash2_init(void)
805 {
806         /* the mangle prefix can only be in the mange 1 to 6 */
807         mangle_prefix = lp_mangle_prefix();
808         if (mangle_prefix > 6) {
809                 mangle_prefix = 6;
810         }
811         if (mangle_prefix < 1) {
812                 mangle_prefix = 1;
813         }
814
815 #if DYNAMIC_MANGLE_TABLES
816         init_tables();
817 #endif
818         mangle_reset();
819
820         return &mangle_hash2_fns;
821 }
822
823 static void posix_mangle_reset(void)
824 {;}
825
826 static bool posix_is_mangled(const char *s, const struct share_params *p)
827 {
828         return False;
829 }
830
831 static bool posix_must_mangle(const char *s, const struct share_params *p)
832 {
833         return False;
834 }
835
836 static bool posix_is_8_3(const char *fname,
837                         bool check_case,
838                         bool allow_wildcards,
839                         const struct share_params *p)
840 {
841         return False;
842 }
843
844 static bool posix_lookup_name_from_8_3(TALLOC_CTX *ctx,
845                                 const char *in,
846                                 char **out, /* talloced on the given context. */
847                                 const struct share_params *p)
848 {
849         return False;
850 }
851
852 static bool posix_name_to_8_3(const char *in,
853                                 char out[13],
854                                 bool cache83,
855                                 int default_case,
856                                 const struct share_params *p)
857 {
858         memset(out, '\0', 13);
859         return True;
860 }
861
862 /* POSIX paths backend - no mangle. */
863 static const struct mangle_fns posix_mangle_fns = {
864         posix_mangle_reset,
865         posix_is_mangled,
866         posix_must_mangle,
867         posix_is_8_3,
868         posix_lookup_name_from_8_3,
869         posix_name_to_8_3
870 };
871
872 const struct mangle_fns *posix_mangle_init(void)
873 {
874         return &posix_mangle_fns;
875 }