📄 mangle_hash2.c
字号:
M_DEBUG(10,("check_cache: %s -> not mangled\n", name)); return False; } /* we need to extract the hash from the 8.3 name */ hash = base_reverse[(unsigned char)name[7]]; for (multiplier=36, i=5;i>=mangle_prefix;i--) { u32 v = base_reverse[(unsigned char)name[i]]; hash += multiplier * v; multiplier *= 36; } /* now look in the prefix cache for that hash */ prefix = cache_lookup(hash); if (!prefix) { M_DEBUG(10,("check_cache: %s -> %08X -> not found\n", name, hash)); return False; } /* we found it - construct the full name */ if (name[8] == '.') { strncpy(extension, name+9, 3); extension[3] = 0; } else { extension[0] = 0; } if (extension[0]) { M_DEBUG(10,("check_cache: %s -> %s.%s\n", name, prefix, extension)); slprintf(name, maxlen, "%s.%s", prefix, extension); } else { M_DEBUG(10,("check_cache: %s -> %s\n", name, prefix)); safe_strcpy(name, prefix, maxlen); } return True;}/* look for a DOS reserved name*/static BOOL is_reserved_name(const char *name){ if (FLAG_CHECK(name[0], FLAG_POSSIBLE1) && FLAG_CHECK(name[1], FLAG_POSSIBLE2) && FLAG_CHECK(name[2], FLAG_POSSIBLE3) && FLAG_CHECK(name[3], FLAG_POSSIBLE4)) { /* a likely match, scan the lot */ int i; for (i=0; reserved_names[i]; i++) { int len = strlen(reserved_names[i]); /* note that we match on COM1 as well as COM1.foo */ if (strnequal(name, reserved_names[i], len) && (name[len] == '.' || name[len] == 0)) { return True; } } } return False;}/* See if a filename is a legal long filename. A filename ending in a '.' is not legal unless it's "." or "..". JRA. A filename ending in ' ' is not legal either. See bug id #2769.*/static BOOL is_legal_name(const char *name){ const char *dot_pos = NULL; BOOL alldots = True; size_t numdots = 0; while (*name) { if (((unsigned int)name[0]) > 128 && (name[1] != 0)) { /* Possible start of mb character. */ char mbc[2]; /* * Note that if CH_UNIX is utf8 a string may be 3 * bytes, but this is ok as mb utf8 characters don't * contain embedded ascii bytes. We are really checking * for mb UNIX asian characters like Japanese (SJIS) here. * JRA. */ if (convert_string(CH_UNIX, CH_UCS2, name, 2, mbc, 2, False) == 2) { /* Was a good mb string. */ name += 2; continue; } } if (FLAG_CHECK(name[0], FLAG_ILLEGAL)) { return False; } if (name[0] == '.') { dot_pos = name; numdots++; } else { alldots = False; } if ((name[0] == ' ') && (name[1] == '\0')) { /* Can't end in ' ' */ return False; } name++; } if (dot_pos) { if (alldots && (numdots == 1 || numdots == 2)) return True; /* . or .. is a valid name */ /* A valid long name cannot end in '.' */ if (dot_pos[1] == '\0') return False; } return True;}/* 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, int snum){ 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, snum)) { 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_ascii(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_ascii(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 */}/* 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 <= 0x1f) { /* Control characters. */ char_flags[i] |= FLAG_ILLEGAL; } 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_ascii(c1)] |= FLAG_POSSIBLE1; char_flags[tolower_ascii(c2)] |= FLAG_POSSIBLE2; char_flags[tolower_ascii(c3)] |= FLAG_POSSIBLE3; char_flags[tolower_ascii(c4)] |= FLAG_POSSIBLE4; char_flags[(unsigned char)'.'] |= FLAG_POSSIBLE4; }}/* the following provides the abstraction layer to make it easier to drop in an alternative mangling implementation */static struct mangle_fns mangle_fns = { mangle_reset, is_mangled, is_8_3, check_cache, name_map};/* return the methods for this mangling implementation */struct mangle_fns *mangle_hash2_init(void){ /* the mangle prefix can only be in the mange 1 to 6 */ mangle_prefix = lp_mangle_prefix(); if (mangle_prefix > 6) { mangle_prefix = 6; } if (mangle_prefix < 1) { mangle_prefix = 1; } init_tables(); mangle_reset(); if (!cache_init()) { return NULL; } return &mangle_fns;}static void posix_mangle_reset(void){;}static BOOL posix_is_mangled(const char *s, int snum){ return False;}static BOOL posix_is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, int snum){ return False;}static BOOL posix_check_cache( char *s, size_t maxlen, int snum ){ return False;}static void posix_name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, int snum){ if (need83) { memset(OutName, '\0', 13); }}/* POSIX paths backend - no mangle. */static struct mangle_fns posix_mangle_fns = { posix_mangle_reset, posix_is_mangled, posix_is_8_3, posix_check_cache, posix_name_map};struct mangle_fns *posix_mangle_init(void){ return &posix_mangle_fns;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -