Line data Source code
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 361831 : static uint32_t mangle_hash(struct pvfs_mangle_context *ctx,
121 : const char *key, size_t length)
122 : {
123 361831 : 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 361831 : static void cache_insert(struct pvfs_mangle_context *ctx,
130 : const char *prefix, int length, uint32_t hash)
131 : {
132 361831 : int i = hash % ctx->cache_size;
133 :
134 361831 : if (ctx->prefix_cache[i]) {
135 356048 : talloc_free(ctx->prefix_cache[i]);
136 : }
137 :
138 361831 : ctx->prefix_cache[i] = talloc_strndup(ctx->prefix_cache, prefix, length);
139 361831 : ctx->prefix_cache_hashes[i] = hash;
140 361831 : }
141 :
142 : /*
143 : lookup an entry in the prefix cache. Return NULL if not found.
144 : */
145 26 : static const char *cache_lookup(struct pvfs_mangle_context *ctx, uint32_t hash)
146 : {
147 26 : int i = hash % ctx->cache_size;
148 :
149 :
150 26 : if (!ctx->prefix_cache[i] || hash != ctx->prefix_cache_hashes[i]) {
151 0 : return NULL;
152 : }
153 :
154 : /* yep, it matched */
155 26 : 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 463024 : static bool is_mangled_component(struct pvfs_mangle_context *ctx,
167 : const char *name, size_t len)
168 : {
169 0 : unsigned int i;
170 :
171 463024 : M_DEBUG(10,("is_mangled_component %s (len %u) ?\n", name, (unsigned int)len));
172 :
173 : /* check the length */
174 463024 : if (len > 12 || len < 8)
175 294097 : return false;
176 :
177 : /* the best distinguishing characteristic is the ~ */
178 168927 : if (name[6] != '~')
179 168901 : return false;
180 :
181 : /* check extension */
182 26 : if (len > 8) {
183 3 : if (name[8] != '.')
184 0 : return false;
185 12 : for (i=9; name[i] && i < len; i++) {
186 9 : if (! FLAG_CHECK(name[i], FLAG_ASCII)) {
187 0 : return false;
188 : }
189 : }
190 : }
191 :
192 : /* check lead characters */
193 130 : for (i=0;i<ctx->mangle_prefix;i++) {
194 104 : if (! FLAG_CHECK(name[i], FLAG_ASCII)) {
195 0 : return false;
196 : }
197 : }
198 :
199 : /* check rest of hash */
200 26 : if (! FLAG_CHECK(name[7], FLAG_BASECHAR)) {
201 0 : return false;
202 : }
203 78 : for (i=ctx->mangle_prefix;i<6;i++) {
204 52 : if (! FLAG_CHECK(name[i], FLAG_BASECHAR)) {
205 0 : return false;
206 : }
207 : }
208 :
209 26 : M_DEBUG(10,("is_mangled_component %s (len %u) -> yes\n", name, (unsigned int)len));
210 :
211 26 : 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 463024 : static bool is_mangled(struct pvfs_mangle_context *ctx, const char *name)
228 : {
229 0 : const char *p;
230 0 : const char *s;
231 :
232 463024 : M_DEBUG(10,("is_mangled %s ?\n", name));
233 :
234 463024 : for (s=name; (p=strchr(s, '/')); s=p+1) {
235 0 : if (is_mangled_component(ctx, s, PTR_DIFF(p, s))) {
236 0 : return true;
237 : }
238 : }
239 :
240 : /* and the last part ... */
241 463024 : 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 38133377 : static bool is_8_3(struct pvfs_mangle_context *ctx,
253 : const char *name, bool check_case, bool allow_wildcards)
254 : {
255 0 : int len, i;
256 0 : char *dot_p;
257 :
258 : /* as a special case, the names '.' and '..' are allowable 8.3 names */
259 38133377 : if (name[0] == '.') {
260 349790 : if (!name[1] || (name[1] == '.' && !name[2])) {
261 349765 : 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 37783612 : len = strlen(name);
271 37783612 : if (len > 12)
272 295528 : return false;
273 :
274 : /* find the '.'. Note that once again we use the non-multibyte
275 : function */
276 37488084 : dot_p = strchr(name, '.');
277 :
278 37488084 : if (!dot_p) {
279 : /* if the name doesn't contain a '.' then its length
280 : must be less than 8 */
281 36849144 : if (len > 8) {
282 66003 : return false;
283 : }
284 : } else {
285 0 : 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 638940 : prefix_len = PTR_DIFF(dot_p, name);
290 638940 : suffix_len = len - (prefix_len+1);
291 :
292 638940 : if (prefix_len > 8 || suffix_len > 3 || suffix_len == 0) {
293 285 : return false;
294 : }
295 :
296 : /* a 8.3 name cannot contain more than 1 '.' */
297 638655 : if (strchr(dot_p+1, '.')) {
298 4 : return false;
299 : }
300 : }
301 :
302 : /* the length are all OK. Now check to see if the characters themselves are OK */
303 218296763 : for (i=0; name[i]; i++) {
304 : /* note that we may allow wildcard petterns! */
305 180874982 : if (!FLAG_CHECK(name[i], FLAG_ASCII|(allow_wildcards ? FLAG_WILDCARD : 0)) &&
306 638662 : name[i] != '.') {
307 11 : return false;
308 : }
309 : }
310 :
311 : /* it is a good 8.3 name */
312 37421781 : 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 463024 : static char *check_cache(struct pvfs_mangle_context *ctx,
321 : TALLOC_CTX *mem_ctx, const char *name)
322 : {
323 0 : uint32_t hash, multiplier;
324 0 : unsigned int i;
325 0 : const char *prefix;
326 0 : char extension[4];
327 :
328 : /* make sure that this is a mangled name from this cache */
329 463024 : if (!is_mangled(ctx, name)) {
330 462998 : M_DEBUG(10,("check_cache: %s -> not mangled\n", name));
331 462998 : return NULL;
332 : }
333 :
334 : /* we need to extract the hash from the 8.3 name */
335 26 : hash = ctx->base_reverse[(unsigned char)name[7]];
336 78 : for (multiplier=36, i=5;i>=ctx->mangle_prefix;i--) {
337 52 : uint32_t v = ctx->base_reverse[(unsigned char)name[i]];
338 52 : hash += multiplier * v;
339 52 : multiplier *= 36;
340 : }
341 :
342 : /* now look in the prefix cache for that hash */
343 26 : prefix = cache_lookup(ctx, hash);
344 26 : if (!prefix) {
345 0 : M_DEBUG(10,("check_cache: %s -> %08X -> not found\n", name, hash));
346 0 : return NULL;
347 : }
348 :
349 : /* we found it - construct the full name */
350 26 : if (name[8] == '.') {
351 3 : strncpy(extension, name+9, 3);
352 3 : extension[3] = 0;
353 : } else {
354 23 : extension[0] = 0;
355 : }
356 :
357 26 : if (extension[0]) {
358 3 : return talloc_asprintf(mem_ctx, "%s.%s", prefix, extension);
359 : }
360 :
361 23 : return talloc_strdup(mem_ctx, prefix);
362 : }
363 :
364 :
365 : /*
366 : look for a DOS reserved name
367 : */
368 38596480 : static bool is_reserved_name(struct pvfs_mangle_context *ctx, const char *name)
369 : {
370 38596480 : if (FLAG_CHECK(name[0], FLAG_POSSIBLE1) &&
371 302572 : FLAG_CHECK(name[1], FLAG_POSSIBLE2) &&
372 142824 : FLAG_CHECK(name[2], FLAG_POSSIBLE3) &&
373 6103 : FLAG_CHECK(name[3], FLAG_POSSIBLE4)) {
374 : /* a likely match, scan the lot */
375 : int i;
376 0 : for (i=0; reserved_names[i]; i++) {
377 0 : if (strcasecmp(name, reserved_names[i]) == 0) {
378 0 : return true;
379 : }
380 : }
381 : }
382 :
383 38596480 : 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 0 : static bool is_legal_name(struct pvfs_mangle_context *ctx, const char *name)
392 : {
393 0 : while (*name) {
394 0 : size_t c_size;
395 0 : codepoint_t c = next_codepoint(name, &c_size);
396 0 : if (c == INVALID_CODEPOINT) {
397 0 : return false;
398 : }
399 : /* all high chars are OK */
400 0 : if (c >= 128) {
401 0 : name += c_size;
402 0 : continue;
403 : }
404 0 : if (FLAG_CHECK(c, FLAG_ILLEGAL)) {
405 0 : return false;
406 : }
407 0 : name += c_size;
408 : }
409 :
410 0 : 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 38133377 : static char *name_map(struct pvfs_mangle_context *ctx,
425 : const char *name, bool need83, bool cache83)
426 : {
427 0 : char *dot_p;
428 0 : char lead_chars[7];
429 0 : char extension[4];
430 0 : unsigned int extension_length, i;
431 0 : unsigned int prefix_len;
432 0 : uint32_t hash, v;
433 0 : char *new_name;
434 38133377 : const char *basechars = MANGLE_BASECHARS;
435 :
436 : /* reserved names are handled specially */
437 38133377 : 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 38133377 : if (is_8_3(ctx, name, false, false)) {
441 37771546 : return NULL;
442 : }
443 :
444 : /* if the caller doesn't strictly need 8.3 then just check for illegal
445 : filenames */
446 361831 : if (!need83 && is_legal_name(ctx, name)) {
447 0 : return NULL;
448 : }
449 : }
450 :
451 : /* find the '.' if any */
452 361831 : dot_p = strrchr(name, '.');
453 :
454 361831 : 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 1181857 : for (i=0; i<4 && dot_p[i+1]; i++) {
459 886368 : if (! FLAG_CHECK(dot_p[i+1], FLAG_ASCII)) {
460 0 : dot_p = NULL;
461 0 : break;
462 : }
463 : }
464 295489 : 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 1809139 : for (i=0;i<ctx->mangle_prefix && name[i];i++) {
472 1447308 : lead_chars[i] = name[i];
473 1447308 : if (! FLAG_CHECK(lead_chars[i], FLAG_ASCII)) {
474 298 : lead_chars[i] = '_';
475 : }
476 1447308 : lead_chars[i] = toupper((unsigned char)lead_chars[i]);
477 : }
478 361847 : for (;i<ctx->mangle_prefix;i++) {
479 16 : lead_chars[i] = '_';
480 : }
481 :
482 : /* the prefix is anything up to the first dot */
483 361831 : if (dot_p) {
484 294706 : prefix_len = PTR_DIFF(dot_p, name);
485 : } else {
486 67125 : 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 361831 : extension_length = 0;
492 361831 : if (dot_p) {
493 1178750 : for (i=1; extension_length < 3 && dot_p[i]; i++) {
494 884044 : unsigned char c = dot_p[i];
495 884044 : if (FLAG_CHECK(c, FLAG_ASCII)) {
496 884044 : extension[extension_length++] = toupper(c);
497 : }
498 : }
499 : }
500 :
501 : /* find the hash for this prefix */
502 361831 : v = hash = mangle_hash(ctx, name, prefix_len);
503 :
504 361831 : new_name = talloc_array(ctx, char, 13);
505 361831 : if (new_name == NULL) {
506 0 : return NULL;
507 : }
508 :
509 : /* now form the mangled name. */
510 1809155 : for (i=0;i<ctx->mangle_prefix;i++) {
511 1447324 : new_name[i] = lead_chars[i];
512 : }
513 361831 : new_name[7] = basechars[v % 36];
514 361831 : new_name[6] = '~';
515 1085493 : for (i=5; i>=ctx->mangle_prefix; i--) {
516 723662 : v = v / 36;
517 723662 : new_name[i] = basechars[v % 36];
518 : }
519 :
520 : /* add the extension */
521 361831 : if (extension_length) {
522 294706 : new_name[8] = '.';
523 294706 : memcpy(&new_name[9], extension, extension_length);
524 294706 : new_name[9+extension_length] = 0;
525 : } else {
526 67125 : new_name[8] = 0;
527 : }
528 :
529 361831 : if (cache83) {
530 : /* put it in the cache */
531 361831 : cache_insert(ctx, name, prefix_len, hash);
532 : }
533 :
534 361831 : M_DEBUG(10,("name_map: %s -> %08X -> %s (cache=%d)\n",
535 : name, hash, new_name, cache83));
536 :
537 361831 : 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 1328 : static void init_tables(struct pvfs_mangle_context *ctx)
549 : {
550 1328 : const char *basechars = MANGLE_BASECHARS;
551 0 : int i;
552 : /* the list of reserved dos names - all of these are illegal */
553 :
554 1328 : ZERO_STRUCT(ctx->char_flags);
555 :
556 169984 : for (i=1;i<128;i++) {
557 168656 : if ((i >= '0' && i <= '9') ||
558 155376 : (i >= 'a' && i <= 'z') ||
559 49136 : (i >= 'A' && i <= 'Z')) {
560 82336 : ctx->char_flags[i] |= (FLAG_ASCII | FLAG_BASECHAR);
561 : }
562 168656 : if (strchr("_-$~", i)) {
563 5312 : ctx->char_flags[i] |= FLAG_ASCII;
564 : }
565 :
566 168656 : if (strchr("*\\/?<>|\":", i)) {
567 11952 : ctx->char_flags[i] |= FLAG_ILLEGAL;
568 : }
569 :
570 168656 : if (strchr("*?\"<>", i)) {
571 6640 : ctx->char_flags[i] |= FLAG_WILDCARD;
572 : }
573 : }
574 :
575 1328 : ZERO_STRUCT(ctx->base_reverse);
576 49136 : for (i=0;i<36;i++) {
577 47808 : 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 30544 : for (i=0; reserved_names[i]; i++) {
583 0 : unsigned char c1, c2, c3, c4;
584 :
585 29216 : c1 = (unsigned char)reserved_names[i][0];
586 29216 : c2 = (unsigned char)reserved_names[i][1];
587 29216 : c3 = (unsigned char)reserved_names[i][2];
588 29216 : c4 = (unsigned char)reserved_names[i][3];
589 :
590 29216 : ctx->char_flags[c1] |= FLAG_POSSIBLE1;
591 29216 : ctx->char_flags[c2] |= FLAG_POSSIBLE2;
592 29216 : ctx->char_flags[c3] |= FLAG_POSSIBLE3;
593 29216 : ctx->char_flags[c4] |= FLAG_POSSIBLE4;
594 29216 : ctx->char_flags[tolower(c1)] |= FLAG_POSSIBLE1;
595 29216 : ctx->char_flags[tolower(c2)] |= FLAG_POSSIBLE2;
596 29216 : ctx->char_flags[tolower(c3)] |= FLAG_POSSIBLE3;
597 29216 : ctx->char_flags[tolower(c4)] |= FLAG_POSSIBLE4;
598 :
599 29216 : ctx->char_flags[(unsigned char)'.'] |= FLAG_POSSIBLE4;
600 : }
601 :
602 1328 : ctx->mangle_modulus = 1;
603 5312 : for (i=0;i<(7-ctx->mangle_prefix);i++) {
604 3984 : ctx->mangle_modulus *= 36;
605 : }
606 1328 : }
607 :
608 : /*
609 : initialise the mangling code
610 : */
611 1328 : NTSTATUS pvfs_mangle_init(struct pvfs_state *pvfs)
612 : {
613 0 : struct pvfs_mangle_context *ctx;
614 :
615 1328 : ctx = talloc(pvfs, struct pvfs_mangle_context);
616 1328 : if (ctx == NULL) {
617 0 : return NT_STATUS_NO_MEMORY;
618 : }
619 :
620 : /* by default have a max of 512 entries in the cache. */
621 1328 : ctx->cache_size = lpcfg_parm_int(pvfs->ntvfs->ctx->lp_ctx, NULL, "mangle", "cachesize", 512);
622 :
623 1328 : ctx->prefix_cache = talloc_array(ctx, char *, ctx->cache_size);
624 1328 : if (ctx->prefix_cache == NULL) {
625 0 : return NT_STATUS_NO_MEMORY;
626 : }
627 1328 : ctx->prefix_cache_hashes = talloc_array(ctx, uint32_t, ctx->cache_size);
628 1328 : if (ctx->prefix_cache_hashes == NULL) {
629 0 : return NT_STATUS_NO_MEMORY;
630 : }
631 :
632 1328 : memset(ctx->prefix_cache, 0, sizeof(char *) * ctx->cache_size);
633 1328 : memset(ctx->prefix_cache_hashes, 0, sizeof(uint32_t) * ctx->cache_size);
634 :
635 1328 : ctx->mangle_prefix = lpcfg_parm_int(pvfs->ntvfs->ctx->lp_ctx, NULL, "mangle", "prefix", -1);
636 1328 : if (ctx->mangle_prefix < 0 || ctx->mangle_prefix > 6) {
637 1328 : ctx->mangle_prefix = DEFAULT_MANGLE_PREFIX;
638 : }
639 :
640 1328 : init_tables(ctx);
641 :
642 1328 : pvfs->mangle_ctx = ctx;
643 :
644 1328 : return NT_STATUS_OK;
645 : }
646 :
647 :
648 : /*
649 : return the short name for a component of a full name
650 : */
651 38133377 : char *pvfs_short_name_component(struct pvfs_state *pvfs, const char *name)
652 : {
653 38133377 : 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 25900 : const char *pvfs_short_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
661 : struct pvfs_filename *name)
662 : {
663 25900 : char *p = strrchr(name->full_name, '/');
664 25900 : char *ret = pvfs_short_name_component(pvfs, p+1);
665 25900 : if (ret == NULL) {
666 24143 : return p+1;
667 : }
668 1757 : talloc_steal(mem_ctx, ret);
669 1757 : return ret;
670 : }
671 :
672 : /*
673 : lookup a mangled name, returning the original long name if present
674 : in the cache
675 : */
676 463024 : char *pvfs_mangled_lookup(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
677 : const char *name)
678 : {
679 463024 : return check_cache(pvfs->mangle_ctx, mem_ctx, name);
680 : }
681 :
682 :
683 : /*
684 : look for a DOS reserved name
685 : */
686 463103 : bool pvfs_is_reserved_name(struct pvfs_state *pvfs, const char *name)
687 : {
688 463103 : 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 0 : bool pvfs_is_mangled_component(struct pvfs_state *pvfs, const char *name)
697 : {
698 0 : return is_mangled_component(pvfs->mangle_ctx, name, strlen(name));
699 : }
|