/* initialise the flags table we allow only a very restricted set of characters as 'ascii' in this mangling backend. This isn't a significant problem as modern clients use the 'long' filenames anyway, and those don't have these restrictions. */ static void init_tables(void) { int i; memset(char_flags, 0, sizeof(char_flags)); for (i=1;i<128;i++) { if ((i >= '0' && i <= '9') || (i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z')) { char_flags[i] |= (FLAG_ASCII | FLAG_BASECHAR); } if (strchr("_-$~", i)) { char_flags[i] |= FLAG_ASCII; } if (strchr("*\\/?<>|\":", i)) { char_flags[i] |= FLAG_ILLEGAL; } if (strchr("*?\"<>", i)) { char_flags[i] |= FLAG_WILDCARD; } } memset(base_reverse, 0, sizeof(base_reverse)); for (i=0;i<36;i++) { base_reverse[(unsigned char)base_forward(i)] = i; } /* fill in the reserved names flags. These are used as a very fast filter for finding possible DOS reserved filenames */ for (i=0; reserved_names[i]; i++) { unsigned char c1, c2, c3, c4; c1 = (unsigned char)reserved_names[i][0]; c2 = (unsigned char)reserved_names[i][1]; c3 = (unsigned char)reserved_names[i][2]; c4 = (unsigned char)reserved_names[i][3]; char_flags[c1] |= FLAG_POSSIBLE1; char_flags[c2] |= FLAG_POSSIBLE2; char_flags[c3] |= FLAG_POSSIBLE3; char_flags[c4] |= FLAG_POSSIBLE4; char_flags[tolower(c1)] |= FLAG_POSSIBLE1; char_flags[tolower(c2)] |= FLAG_POSSIBLE2; char_flags[tolower(c3)] |= FLAG_POSSIBLE3; char_flags[tolower(c4)] |= FLAG_POSSIBLE4; char_flags[(unsigned char)'.'] |= FLAG_POSSIBLE4; } }
/* the main forward mapping function, which converts a long filename to a 8.3 name if need83 is not set then we only do the mangling if the name is illegal as a long name if cache83 is not set then we don't cache the result the name parameter must be able to hold 13 bytes */ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case) { char *dot_p; char lead_chars[7]; char extension[4]; unsigned int extension_length, i; unsigned int prefix_len; u32 hash, v; char new_name[13]; /* reserved names are handled specially */ if (!is_reserved_name(name)) { /* if the name is already a valid 8.3 name then we don't need to do anything */ if (is_8_3(name, False, False)) { return; } /* if the caller doesn't strictly need 8.3 then just check for illegal filenames */ if (!need83 && is_legal_name(name)) { return; } } /* find the '.' if any */ dot_p = strrchr(name, '.'); if (dot_p) { /* if the extension contains any illegal characters or is too long or zero length then we treat it as part of the prefix */ for (i=0; i<4 && dot_p[i+1]; i++) { if (! FLAG_CHECK(dot_p[i+1], FLAG_ASCII)) { dot_p = NULL; break; } } if (i == 0 || i == 4) dot_p = NULL; } /* the leading characters in the mangled name is taken from the first characters of the name, if they are ascii otherwise '_' is used */ for (i=0;i<mangle_prefix && name[i];i++) { lead_chars[i] = name[i]; if (! FLAG_CHECK(lead_chars[i], FLAG_ASCII)) { lead_chars[i] = '_'; } lead_chars[i] = toupper(lead_chars[i]); } for (;i<mangle_prefix;i++) { lead_chars[i] = '_'; } /* the prefix is anything up to the first dot */ if (dot_p) { prefix_len = PTR_DIFF(dot_p, name); } else { prefix_len = strlen(name); } /* the extension of the mangled name is taken from the first 3 ascii chars after the dot */ extension_length = 0; if (dot_p) { for (i=1; extension_length < 3 && dot_p[i]; i++) { char c = dot_p[i]; if (FLAG_CHECK(c, FLAG_ASCII)) { extension[extension_length++] = toupper(c); } } } /* find the hash for this prefix */ v = hash = mangle_hash(name, prefix_len); /* now form the mangled name. */ for (i=0;i<mangle_prefix;i++) { new_name[i] = lead_chars[i]; } new_name[7] = base_forward(v % 36); new_name[6] = '~'; for (i=5; i>=mangle_prefix; i--) { v = v / 36; new_name[i] = base_forward(v % 36); } /* add the extension */ if (extension_length) { new_name[8] = '.'; memcpy(&new_name[9], extension, extension_length); new_name[9+extension_length] = 0; } else { new_name[8] = 0; } if (cache83) { /* put it in the cache */ cache_insert(name, prefix_len, hash); } M_DEBUG(10,("name_map: %s -> %08X -> %s (cache=%d)\n", name, hash, new_name, cache83)); /* and overwrite the old name */ fstrcpy(name, new_name); /* all done, we've managed to mangle it */ }
/* the main forward mapping function, which converts a long filename to a 8.3 name if cache83 is not set then we don't cache the result */ static bool hash2_name_to_8_3(const char *name, char new_name[13], bool cache83, int default_case, const struct share_params *p) { char *dot_p; char lead_chars[7]; char extension[4]; unsigned int extension_length, i; unsigned int prefix_len; unsigned int hash, v; /* reserved names are handled specially */ if (!is_reserved_name(name)) { /* if the name is already a valid 8.3 name then we don't need to * change anything */ if (is_legal_name(name) && is_8_3(name, False, False, p)) { safe_strcpy(new_name, name, 12); return True; } } /* find the '.' if any */ dot_p = strrchr(name, '.'); if (dot_p) { /* if the extension contains any illegal characters or is too long or zero length then we treat it as part of the prefix */ for (i=0; i<4 && dot_p[i+1]; i++) { if (! FLAG_CHECK(dot_p[i+1], FLAG_ASCII)) { dot_p = NULL; break; } } if (i == 0 || i == 4) { dot_p = NULL; } } /* the leading characters in the mangled name is taken from the first characters of the name, if they are ascii otherwise '_' is used */ for (i=0;i<mangle_prefix && name[i];i++) { lead_chars[i] = name[i]; if (! FLAG_CHECK(lead_chars[i], FLAG_ASCII)) { lead_chars[i] = '_'; } lead_chars[i] = toupper_m(lead_chars[i]); } for (;i<mangle_prefix;i++) { lead_chars[i] = '_'; } /* the prefix is anything up to the first dot */ if (dot_p) { prefix_len = PTR_DIFF(dot_p, name); } else { prefix_len = strlen(name); } /* the extension of the mangled name is taken from the first 3 ascii chars after the dot */ extension_length = 0; if (dot_p) { for (i=1; extension_length < 3 && dot_p[i]; i++) { char c = dot_p[i]; if (FLAG_CHECK(c, FLAG_ASCII)) { extension[extension_length++] = toupper_m(c); } } } /* find the hash for this prefix */ v = hash = mangle_hash(name, prefix_len); /* now form the mangled name. */ for (i=0;i<mangle_prefix;i++) { new_name[i] = lead_chars[i]; } new_name[7] = base_forward(v % 36); new_name[6] = '~'; for (i=5; i>=mangle_prefix; i--) { v = v / 36; new_name[i] = base_forward(v % 36); } /* add the extension */ if (extension_length) { new_name[8] = '.'; memcpy(&new_name[9], extension, extension_length); new_name[9+extension_length] = 0; } else { new_name[8] = 0; } if (cache83) { /* put it in the cache */ cache_insert(name, prefix_len, hash); } M_DEBUG(10,("hash2_name_to_8_3: %s -> %08X -> %s (cache=%d)\n", name, hash, new_name, cache83)); return True; }