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