Fix a few "might be uninitialized" errors
[samba.git] / source4 / ntvfs / posix / pvfs_shortname.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    POSIX NTVFS backend - 8.3 name routines
5
6    Copyright (C) Andrew Tridgell 2004
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 3 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, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "system/locale.h"
24 #include "vfs_posix.h"
25 #include "param/param.h"
26
27 #undef strcasecmp
28
29 /*
30   this mangling scheme uses the following format
31
32   Annnn~n.AAA
33
34   where nnnnn is a base 36 hash, and A represents characters from the original string
35
36   The hash is taken of the leading part of the long filename, in uppercase
37
38   for simplicity, we only allow ascii characters in 8.3 names
39 */
40
41 /*
42   ===============================================================================
43   NOTE NOTE NOTE!!!
44
45   This file deliberately uses non-multibyte string functions in many places. This
46   is *not* a mistake. This code is multi-byte safe, but it gets this property
47   through some very subtle knowledge of the way multi-byte strings are encoded 
48   and the fact that this mangling algorithm only supports ascii characters in
49   8.3 names.
50
51   please don't convert this file to use the *_m() functions!!
52   ===============================================================================
53 */
54
55
56 #if 1
57 #define M_DEBUG(level, x) DEBUG(level, x)
58 #else
59 #define M_DEBUG(level, x)
60 #endif
61
62 /* these flags are used to mark characters in as having particular
63    properties */
64 #define FLAG_BASECHAR 1
65 #define FLAG_ASCII 2
66 #define FLAG_ILLEGAL 4
67 #define FLAG_WILDCARD 8
68
69 /* the "possible" flags are used as a fast way to find possible DOS
70    reserved filenames */
71 #define FLAG_POSSIBLE1 16
72 #define FLAG_POSSIBLE2 32
73 #define FLAG_POSSIBLE3 64
74 #define FLAG_POSSIBLE4 128
75
76 #define DEFAULT_MANGLE_PREFIX 4
77
78 #define MANGLE_BASECHARS "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
79
80 #define FLAG_CHECK(c, flag) (ctx->char_flags[(uint8_t)(c)] & (flag))
81
82 static const char *reserved_names[] = 
83 { "AUX", "CON",
84   "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
85   "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
86   "NUL", "PRN", NULL };
87
88
89 struct pvfs_mangle_context {
90         uint8_t char_flags[256];
91         /*
92           this determines how many characters are used from the original
93           filename in the 8.3 mangled name. A larger value leads to a weaker
94           hash and more collisions.  The largest possible value is 6.
95         */
96         int mangle_prefix;
97         uint32_t mangle_modulus;
98
99         /* we will use a very simple direct mapped prefix cache. The big
100            advantage of this cache structure is speed and low memory usage 
101
102            The cache is indexed by the low-order bits of the hash, and confirmed by
103            hashing the resulting cache entry to match the known hash
104         */
105         uint32_t cache_size;
106         char **prefix_cache;
107         uint32_t *prefix_cache_hashes;
108
109         /* this is used to reverse the base 36 mapping */
110         unsigned char base_reverse[256];
111 };
112
113
114 /* 
115    hash a string of the specified length. The string does not need to be
116    null terminated 
117
118    this hash needs to be fast with a low collision rate (what hash doesn't?)
119 */
120 static uint32_t mangle_hash(struct pvfs_mangle_context *ctx,
121                             const char *key, size_t length)
122 {
123         return pvfs_name_hash(key, length) % ctx->mangle_modulus;
124 }
125
126 /*
127   insert an entry into the prefix cache. The string might not be null
128   terminated */
129 static void cache_insert(struct pvfs_mangle_context *ctx,
130                          const char *prefix, int length, uint32_t hash)
131 {
132         int i = hash % ctx->cache_size;
133
134         if (ctx->prefix_cache[i]) {
135                 talloc_free(ctx->prefix_cache[i]);
136         }
137
138         ctx->prefix_cache[i] = talloc_strndup(ctx->prefix_cache, prefix, length);
139         ctx->prefix_cache_hashes[i] = hash;
140 }
141
142 /*
143   lookup an entry in the prefix cache. Return NULL if not found.
144 */
145 static const char *cache_lookup(struct pvfs_mangle_context *ctx, uint32_t hash)
146 {
147         int i = hash % ctx->cache_size;
148
149
150         if (!ctx->prefix_cache[i] || hash != ctx->prefix_cache_hashes[i]) {
151                 return NULL;
152         }
153
154         /* yep, it matched */
155         return ctx->prefix_cache[i];
156 }
157
158
159 /* 
160    determine if a string is possibly in a mangled format, ignoring
161    case 
162
163    In this algorithm, mangled names use only pure ascii characters (no
164    multi-byte) so we can avoid doing a UCS2 conversion 
165  */
166 static bool is_mangled_component(struct pvfs_mangle_context *ctx,
167                                  const char *name, size_t len)
168 {
169         unsigned int i;
170
171         M_DEBUG(10,("is_mangled_component %s (len %u) ?\n", name, (unsigned int)len));
172
173         /* check the length */
174         if (len > 12 || len < 8)
175                 return false;
176
177         /* the best distinguishing characteristic is the ~ */
178         if (name[6] != '~')
179                 return false;
180
181         /* check extension */
182         if (len > 8) {
183                 if (name[8] != '.')
184                         return false;
185                 for (i=9; name[i] && i < len; i++) {
186                         if (! FLAG_CHECK(name[i], FLAG_ASCII)) {
187                                 return false;
188                         }
189                 }
190         }
191         
192         /* check lead characters */
193         for (i=0;i<ctx->mangle_prefix;i++) {
194                 if (! FLAG_CHECK(name[i], FLAG_ASCII)) {
195                         return false;
196                 }
197         }
198         
199         /* check rest of hash */
200         if (! FLAG_CHECK(name[7], FLAG_BASECHAR)) {
201                 return false;
202         }
203         for (i=ctx->mangle_prefix;i<6;i++) {
204                 if (! FLAG_CHECK(name[i], FLAG_BASECHAR)) {
205                         return false;
206                 }
207         }
208
209         M_DEBUG(10,("is_mangled_component %s (len %u) -> yes\n", name, (unsigned int)len));
210
211         return true;
212 }
213
214
215
216 /* 
217    determine if a string is possibly in a mangled format, ignoring
218    case 
219
220    In this algorithm, mangled names use only pure ascii characters (no
221    multi-byte) so we can avoid doing a UCS2 conversion 
222
223    NOTE! This interface must be able to handle a path with unix
224    directory separators. It should return true if any component is
225    mangled
226  */
227 static bool is_mangled(struct pvfs_mangle_context *ctx, const char *name)
228 {
229         const char *p;
230         const char *s;
231
232         M_DEBUG(10,("is_mangled %s ?\n", name));
233
234         for (s=name; (p=strchr(s, '/')); s=p+1) {
235                 if (is_mangled_component(ctx, s, PTR_DIFF(p, s))) {
236                         return true;
237                 }
238         }
239         
240         /* and the last part ... */
241         return is_mangled_component(ctx, s, strlen(s));
242 }
243
244
245 /* 
246    see if a filename is an allowable 8.3 name.
247
248    we are only going to allow ascii characters in 8.3 names, as this
249    simplifies things greatly (it means that we know the string won't
250    get larger when converted from UNIX to DOS formats)
251 */
252 static bool is_8_3(struct pvfs_mangle_context *ctx,
253                    const char *name, bool check_case, bool allow_wildcards)
254 {
255         int len, i;
256         char *dot_p;
257
258         /* as a special case, the names '.' and '..' are allowable 8.3 names */
259         if (name[0] == '.') {
260                 if (!name[1] || (name[1] == '.' && !name[2])) {
261                         return true;
262                 }
263         }
264
265         /* the simplest test is on the overall length of the
266          filename. Note that we deliberately use the ascii string
267          length (not the multi-byte one) as it is faster, and gives us
268          the result we need in this case. Using strlen_m would not
269          only be slower, it would be incorrect */
270         len = strlen(name);
271         if (len > 12)
272                 return false;
273
274         /* find the '.'. Note that once again we use the non-multibyte
275            function */
276         dot_p = strchr(name, '.');
277
278         if (!dot_p) {
279                 /* if the name doesn't contain a '.' then its length
280                    must be less than 8 */
281                 if (len > 8) {
282                         return false;
283                 }
284         } else {
285                 int prefix_len, suffix_len;
286
287                 /* if it does contain a dot then the prefix must be <=
288                    8 and the suffix <= 3 in length */
289                 prefix_len = PTR_DIFF(dot_p, name);
290                 suffix_len = len - (prefix_len+1);
291
292                 if (prefix_len > 8 || suffix_len > 3 || suffix_len == 0) {
293                         return false;
294                 }
295
296                 /* a 8.3 name cannot contain more than 1 '.' */
297                 if (strchr(dot_p+1, '.')) {
298                         return false;
299                 }
300         }
301
302         /* the length are all OK. Now check to see if the characters themselves are OK */
303         for (i=0; name[i]; i++) {
304                 /* note that we may allow wildcard petterns! */
305                 if (!FLAG_CHECK(name[i], FLAG_ASCII|(allow_wildcards ? FLAG_WILDCARD : 0)) && 
306                     name[i] != '.') {
307                         return false;
308                 }
309         }
310
311         /* it is a good 8.3 name */
312         return true;
313 }
314
315
316 /*
317   try to find a 8.3 name in the cache, and if found then
318   return the original long name. 
319 */
320 static char *check_cache(struct pvfs_mangle_context *ctx, 
321                          TALLOC_CTX *mem_ctx, const char *name)
322 {
323         uint32_t hash, multiplier;
324         unsigned int i;
325         const char *prefix;
326         char extension[4];
327
328         /* make sure that this is a mangled name from this cache */
329         if (!is_mangled(ctx, name)) {
330                 M_DEBUG(10,("check_cache: %s -> not mangled\n", name));
331                 return NULL;
332         }
333
334         /* we need to extract the hash from the 8.3 name */
335         hash = ctx->base_reverse[(unsigned char)name[7]];
336         for (multiplier=36, i=5;i>=ctx->mangle_prefix;i--) {
337                 uint32_t v = ctx->base_reverse[(unsigned char)name[i]];
338                 hash += multiplier * v;
339                 multiplier *= 36;
340         }
341
342         /* now look in the prefix cache for that hash */
343         prefix = cache_lookup(ctx, hash);
344         if (!prefix) {
345                 M_DEBUG(10,("check_cache: %s -> %08X -> not found\n", name, hash));
346                 return NULL;
347         }
348
349         /* we found it - construct the full name */
350         if (name[8] == '.') {
351                 strncpy(extension, name+9, 3);
352                 extension[3] = 0;
353         } else {
354                 extension[0] = 0;
355         }
356
357         if (extension[0]) {
358                 return talloc_asprintf(mem_ctx, "%s.%s", prefix, extension);
359         }
360
361         return talloc_strdup(mem_ctx, prefix);
362 }
363
364
365 /*
366   look for a DOS reserved name
367 */
368 static bool is_reserved_name(struct pvfs_mangle_context *ctx, const char *name)
369 {
370         if (FLAG_CHECK(name[0], FLAG_POSSIBLE1) &&
371             FLAG_CHECK(name[1], FLAG_POSSIBLE2) &&
372             FLAG_CHECK(name[2], FLAG_POSSIBLE3) &&
373             FLAG_CHECK(name[3], FLAG_POSSIBLE4)) {
374                 /* a likely match, scan the lot */
375                 int i;
376                 for (i=0; reserved_names[i]; i++) {
377                         if (strcasecmp(name, reserved_names[i]) == 0) {
378                                 return true;
379                         }
380                 }
381         }
382
383         return false;
384 }
385
386
387 /*
388  See if a filename is a legal long filename.
389  A filename ending in a '.' is not legal unless it's "." or "..". JRA.
390 */
391 static bool is_legal_name(struct pvfs_mangle_context *ctx, const char *name)
392 {
393         while (*name) {
394                 size_t c_size;
395                 codepoint_t c = next_codepoint(name, &c_size);
396                 if (c == INVALID_CODEPOINT) {
397                         return false;
398                 }
399                 /* all high chars are OK */
400                 if (c >= 128) {
401                         name += c_size;
402                         continue;
403                 }
404                 if (FLAG_CHECK(c, FLAG_ILLEGAL)) {
405                         return false;
406                 }
407                 name += c_size;
408         }
409
410         return true;
411 }
412
413 /*
414   the main forward mapping function, which converts a long filename to 
415   a 8.3 name
416
417   if need83 is not set then we only do the mangling if the name is illegal
418   as a long name
419
420   if cache83 is not set then we don't cache the result
421
422   return NULL if we don't need to do any conversion
423 */
424 static char *name_map(struct pvfs_mangle_context *ctx,
425                       const char *name, bool need83, bool cache83)
426 {
427         char *dot_p;
428         char lead_chars[7];
429         char extension[4];
430         unsigned int extension_length, i;
431         unsigned int prefix_len;
432         uint32_t hash, v;
433         char *new_name;
434         const char *basechars = MANGLE_BASECHARS;
435
436         /* reserved names are handled specially */
437         if (!is_reserved_name(ctx, name)) {
438                 /* if the name is already a valid 8.3 name then we don't need to 
439                    do anything */
440                 if (is_8_3(ctx, name, false, false)) {
441                         return NULL;
442                 }
443
444                 /* if the caller doesn't strictly need 8.3 then just check for illegal 
445                    filenames */
446                 if (!need83 && is_legal_name(ctx, name)) {
447                         return NULL;
448                 }
449         }
450
451         /* find the '.' if any */
452         dot_p = strrchr(name, '.');
453
454         if (dot_p) {
455                 /* if the extension contains any illegal characters or
456                    is too long or zero length then we treat it as part
457                    of the prefix */
458                 for (i=0; i<4 && dot_p[i+1]; i++) {
459                         if (! FLAG_CHECK(dot_p[i+1], FLAG_ASCII)) {
460                                 dot_p = NULL;
461                                 break;
462                         }
463                 }
464                 if (i == 0 || i == 4) dot_p = NULL;
465         }
466
467         /* the leading characters in the mangled name is taken from
468            the first characters of the name, if they are ascii otherwise
469            '_' is used
470         */
471         for (i=0;i<ctx->mangle_prefix && name[i];i++) {
472                 lead_chars[i] = name[i];
473                 if (! FLAG_CHECK(lead_chars[i], FLAG_ASCII)) {
474                         lead_chars[i] = '_';
475                 }
476                 lead_chars[i] = toupper((unsigned char)lead_chars[i]);
477         }
478         for (;i<ctx->mangle_prefix;i++) {
479                 lead_chars[i] = '_';
480         }
481
482         /* the prefix is anything up to the first dot */
483         if (dot_p) {
484                 prefix_len = PTR_DIFF(dot_p, name);
485         } else {
486                 prefix_len = strlen(name);
487         }
488
489         /* the extension of the mangled name is taken from the first 3
490            ascii chars after the dot */
491         extension_length = 0;
492         if (dot_p) {
493                 for (i=1; extension_length < 3 && dot_p[i]; i++) {
494                         unsigned char c = dot_p[i];
495                         if (FLAG_CHECK(c, FLAG_ASCII)) {
496                                 extension[extension_length++] = toupper(c);
497                         }
498                 }
499         }
500            
501         /* find the hash for this prefix */
502         v = hash = mangle_hash(ctx, name, prefix_len);
503
504         new_name = talloc_array(ctx, char, 13);
505         if (new_name == NULL) {
506                 return NULL;
507         }
508
509         /* now form the mangled name. */
510         for (i=0;i<ctx->mangle_prefix;i++) {
511                 new_name[i] = lead_chars[i];
512         }
513         new_name[7] = basechars[v % 36];
514         new_name[6] = '~';      
515         for (i=5; i>=ctx->mangle_prefix; i--) {
516                 v = v / 36;
517                 new_name[i] = basechars[v % 36];
518         }
519
520         /* add the extension */
521         if (extension_length) {
522                 new_name[8] = '.';
523                 memcpy(&new_name[9], extension, extension_length);
524                 new_name[9+extension_length] = 0;
525         } else {
526                 new_name[8] = 0;
527         }
528
529         if (cache83) {
530                 /* put it in the cache */
531                 cache_insert(ctx, name, prefix_len, hash);
532         }
533
534         M_DEBUG(10,("name_map: %s -> %08X -> %s (cache=%d)\n", 
535                    name, hash, new_name, cache83));
536
537         return new_name;
538 }
539
540
541 /* initialise the flags table 
542
543   we allow only a very restricted set of characters as 'ascii' in this
544   mangling backend. This isn't a significant problem as modern clients
545   use the 'long' filenames anyway, and those don't have these
546   restrictions. 
547 */
548 static void init_tables(struct pvfs_mangle_context *ctx)
549 {
550         const char *basechars = MANGLE_BASECHARS;
551         int i;
552         /* the list of reserved dos names - all of these are illegal */
553
554         ZERO_STRUCT(ctx->char_flags);
555
556         for (i=1;i<128;i++) {
557                 if ((i >= '0' && i <= '9') || 
558                     (i >= 'a' && i <= 'z') || 
559                     (i >= 'A' && i <= 'Z')) {
560                         ctx->char_flags[i] |=  (FLAG_ASCII | FLAG_BASECHAR);
561                 }
562                 if (strchr("_-$~", i)) {
563                         ctx->char_flags[i] |= FLAG_ASCII;
564                 }
565
566                 if (strchr("*\\/?<>|\":", i)) {
567                         ctx->char_flags[i] |= FLAG_ILLEGAL;
568                 }
569
570                 if (strchr("*?\"<>", i)) {
571                         ctx->char_flags[i] |= FLAG_WILDCARD;
572                 }
573         }
574
575         ZERO_STRUCT(ctx->base_reverse);
576         for (i=0;i<36;i++) {
577                 ctx->base_reverse[(uint8_t)basechars[i]] = i;
578         }       
579
580         /* fill in the reserved names flags. These are used as a very
581            fast filter for finding possible DOS reserved filenames */
582         for (i=0; reserved_names[i]; i++) {
583                 unsigned char c1, c2, c3, c4;
584
585                 c1 = (unsigned char)reserved_names[i][0];
586                 c2 = (unsigned char)reserved_names[i][1];
587                 c3 = (unsigned char)reserved_names[i][2];
588                 c4 = (unsigned char)reserved_names[i][3];
589
590                 ctx->char_flags[c1] |= FLAG_POSSIBLE1;
591                 ctx->char_flags[c2] |= FLAG_POSSIBLE2;
592                 ctx->char_flags[c3] |= FLAG_POSSIBLE3;
593                 ctx->char_flags[c4] |= FLAG_POSSIBLE4;
594                 ctx->char_flags[tolower(c1)] |= FLAG_POSSIBLE1;
595                 ctx->char_flags[tolower(c2)] |= FLAG_POSSIBLE2;
596                 ctx->char_flags[tolower(c3)] |= FLAG_POSSIBLE3;
597                 ctx->char_flags[tolower(c4)] |= FLAG_POSSIBLE4;
598
599                 ctx->char_flags[(unsigned char)'.'] |= FLAG_POSSIBLE4;
600         }
601
602         ctx->mangle_modulus = 1;
603         for (i=0;i<(7-ctx->mangle_prefix);i++) {
604                 ctx->mangle_modulus *= 36;
605         }
606 }
607
608 /* 
609    initialise the mangling code 
610  */
611 NTSTATUS pvfs_mangle_init(struct pvfs_state *pvfs)
612 {
613         struct pvfs_mangle_context *ctx;
614
615         ctx = talloc(pvfs, struct pvfs_mangle_context);
616         if (ctx == NULL) {
617                 return NT_STATUS_NO_MEMORY;
618         }
619
620         /* by default have a max of 512 entries in the cache. */
621         ctx->cache_size = lpcfg_parm_int(pvfs->ntvfs->ctx->lp_ctx, NULL, "mangle", "cachesize", 512);
622
623         ctx->prefix_cache = talloc_array(ctx, char *, ctx->cache_size);
624         if (ctx->prefix_cache == NULL) {
625                 return NT_STATUS_NO_MEMORY;
626         }
627         ctx->prefix_cache_hashes = talloc_array(ctx, uint32_t, ctx->cache_size);
628         if (ctx->prefix_cache_hashes == NULL) {
629                 return NT_STATUS_NO_MEMORY;
630         }
631
632         memset(ctx->prefix_cache, 0, sizeof(char *) * ctx->cache_size);
633         memset(ctx->prefix_cache_hashes, 0, sizeof(uint32_t) * ctx->cache_size);
634
635         ctx->mangle_prefix = lpcfg_parm_int(pvfs->ntvfs->ctx->lp_ctx, NULL, "mangle", "prefix", -1);
636         if (ctx->mangle_prefix < 0 || ctx->mangle_prefix > 6) {
637                 ctx->mangle_prefix = DEFAULT_MANGLE_PREFIX;
638         }
639
640         init_tables(ctx);
641
642         pvfs->mangle_ctx = ctx;
643
644         return NT_STATUS_OK;
645 }
646
647
648 /*
649   return the short name for a component of a full name
650 */
651 char *pvfs_short_name_component(struct pvfs_state *pvfs, const char *name)
652 {
653         return name_map(pvfs->mangle_ctx, name, true, true);
654 }
655
656
657 /*
658   return the short name for a given entry in a directory
659 */
660 const char *pvfs_short_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, 
661                             struct pvfs_filename *name)
662 {
663         char *p = strrchr(name->full_name, '/');
664         char *ret = pvfs_short_name_component(pvfs, p+1);
665         if (ret == NULL) {
666                 return p+1;
667         }
668         talloc_steal(mem_ctx, ret);
669         return ret;
670 }
671
672 /*
673   lookup a mangled name, returning the original long name if present
674   in the cache
675 */
676 char *pvfs_mangled_lookup(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, 
677                           const char *name)
678 {
679         return check_cache(pvfs->mangle_ctx, mem_ctx, name);
680 }
681
682
683 /*
684   look for a DOS reserved name
685 */
686 bool pvfs_is_reserved_name(struct pvfs_state *pvfs, const char *name)
687 {
688         return is_reserved_name(pvfs->mangle_ctx, name);
689 }
690
691
692 /*
693   see if a component of a filename could be a mangled name from our
694   mangling code
695 */
696 bool pvfs_is_mangled_component(struct pvfs_state *pvfs, const char *name)
697 {
698         return is_mangled_component(pvfs->mangle_ctx, name, strlen(name));
699 }