From 714518e550f3c6ee36fa6e3e2447b943898a2ac5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 11 Apr 2002 09:56:38 +0000 Subject: this adds a completely new hash based mangling scheme the hash for this scheme is *much* larger (approximately 31 bits) and the code is written to be very fast, correctly handling multibyte while not doing any actual multi-byte conversions in the vast majority of cases you can select this scheme using "mangling method = hash2", although I may make it the default if it works out well. (This used to be commit bb173c1a7e2408ced967ebac40b5e3f852ccd3a1) --- source3/smbd/mangle_hash2.c | 510 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 510 insertions(+) create mode 100644 source3/smbd/mangle_hash2.c (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c new file mode 100644 index 0000000000..661ae7eb44 --- /dev/null +++ b/source3/smbd/mangle_hash2.c @@ -0,0 +1,510 @@ +/* + Unix SMB/CIFS implementation. + new hash based name mangling implementation + Copyright (C) Andrew Tridgell 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + this mangling scheme uses the following format + + Annnn~n.AAA + + where nnnnn is a base 36 hash, and A represents characters from the original string + + The hash is taken of the leading part of the long filename, in uppercase + + for simplicity, we only allow ascii characters in 8.3 names + */ + + +/* + =============================================================================== + NOTE NOTE NOTE!!! + + This file deliberately uses non-multibyte string functions in many places. This + is *not* a mistake. This code is multi-byte safe, but it gets this property + through some very subtle knowledge of the way multi-byte strings are encoded + and the fact that this mangling algorithm only supports ascii characters in + 8.3 names. + + please don't convert this file to use the *_m() functions!! + =============================================================================== +*/ + + +#include "includes.h" + + +#define FLAG_BASECHAR 1 +#define FLAG_ASCII 2 +#define FLAG_ILLEGAL 4 +#define FLAG_POSSIBLE1 8 +#define FLAG_POSSIBLE2 16 +#define FLAG_POSSIBLE3 32 + +#define CACHE_SIZE 8192 + +/* these tables are used to provide fast tests for characters */ +static unsigned char char_flags[256]; + +/* we will use a very simple direct mapped prefix cache. The big + advantage of this cache structure is speed and low memory usage + + The cache is indexed by the low-order bits of the hash, and confirmed by + hashing the resulting cache entry to match the known hash +*/ +static char **prefix_cache; + +/* these are the characters we use in the 8.3 hash. Must be 36 chars long */ +const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +static unsigned char base_reverse[256]; +#define base_forward(v) basechars[v] + +/* the list of reserved dos names - all of these are illegal */ +const char *reserved_names[] = { "AUX", "LOCK$", "CON", "COM1", "COM2", "COM3", "COM4", + "LPT1", "LPT2", "LPT3", "NUL", "PRN", NULL }; + +/* + hash a string of the specified length. The string does not need to be + null terminated + + this hash needs to be fast with a low collision rate (what hash doesn't?) +*/ +static u32 mangle_hash(const char *key, unsigned length) +{ + u32 value; + u32 i; + fstring str; + + strncpy(str, key, length); + str[length] = 0; + strupper_m(str); + + /* the length of a multi-byte string can change after a strupper */ + length = strlen(str); + + /* Set the initial value from the key size. */ + for (value = 0x238F13AF * length, i=0; i < length; i++) { + value = (value + (((unsigned char)str[i]) << (i*5 % 24))); + } + + return (1103515243 * value + 12345); +} + +/* + initialise the prefix cache + */ +static BOOL cache_init(void) +{ + if (prefix_cache) return True; + + prefix_cache = malloc(sizeof(char *) * CACHE_SIZE); + if (!prefix_cache) return False; + + memset(prefix_cache, 0, sizeof(char *) * CACHE_SIZE); + return True; +} + +/* + insert an entry into the prefix cache. The string may not be null terminated +*/ +static void cache_insert(const char *prefix, int length, u32 hash) +{ + int i = hash % CACHE_SIZE; + + if (prefix_cache[i]) { + free(prefix_cache[i]); + } + + prefix_cache[i] = strndup(prefix, length); +} + +/* + lookup an entry in the prefix cache. Return NULL if not found. +*/ +static const char *cache_lookup(u32 hash) +{ + int i = hash % CACHE_SIZE; + + if (!prefix_cache[i]) return NULL; + + /* we have a possible match - compute the hash to confirm */ + if (hash != mangle_hash(prefix_cache[i], strlen(prefix_cache[i]))) { + return NULL; + } + + /* yep, it matched */ + return prefix_cache[i]; +} + + +/* + determine if a string is possibly in a mangled format, ignoring + case + + In this algorithm, mangled names use only pure ascii characters (no + multi-byte) so we can avoid doing a UCS2 conversion +*/ +static BOOL is_mangled(const char *name) +{ + /* the best distinguishing characteristic is the ~ */ + if (name[6] != '~') return False; + + /* check extension */ + /* check first character */ + /* check rest of hash */ + + return True; +} + + +/* + see if a filename is an allowable 8.3 name. + + we are only going to allow ascii characters in 8.3 names, as this + simplifies things greatly (it means that we know the string won't + get larger when converted from UNIX to DOS formats) +*/ +static BOOL is_8_3(const char *name, BOOL check_case) +{ + int len, i; + char *dot_p; + + /* as a special case, the names '.' and '..' are allowable 8.3 names */ + if (name[0] == '.') { + if (!name[1] || (name[1] == '.' && !name[2])) { + return True; + } + } + + /* the simplest test is on the overall length of the + filename. Note that we deliberately use the ascii string + length (not the multi-byte one) as it is faster, and gives us + the result we need in this case. Using strlen_m would not + only be slower, it would be incorrect */ + len = strlen(name); + if (len > 12) return False; + + /* find the '.'. Note that once again we use the non-multibyte + function */ + dot_p = strchr(name, '.'); + + if (!dot_p) { + /* if the name doesn't contain a '.' then its length + must be less than 8 */ + if (len > 8) { + return False; + } + } else { + int prefix_len, suffix_len; + + /* if it does contain a dot then the prefix must be <= + 8 and the suffix <= 3 in length */ + prefix_len = PTR_DIFF(dot_p, name); + suffix_len = len - (prefix_len+1); + + if (prefix_len > 8 || suffix_len > 3) { + return False; + } + + /* a 8.3 name cannot contain more than 1 '.' */ + if (strchr(dot_p+1, '.')) { + return False; + } + } + + /* the length are all OK. Now check to see if the characters themselves are OK */ + for (i=0; name[i]; i++) { + if (!(char_flags[(unsigned)(name[i])] & FLAG_ASCII)) { + return False; + } + } + + /* it is a good 8.3 name */ + return True; +} + + +/* + reset the mangling cache on a smb.conf reload. This only really makes sense for + mangling backends that have parameters in smb.conf, and as this backend doesn't + this is a NULL operation +*/ +static void mangle_reset(void) +{ + /* noop */ +} + + +/* + try to find a 8.3 name in the cache, and if found then + replace the string with the original long name. + + The filename must be able to hold at least sizeof(fstring) +*/ +static BOOL check_cache(char *name) +{ + u32 hash, multiplier; + int i; + const char *prefix; + char extension[4]; + + /* make sure that this is a mangled name from this cache */ + if (!is_mangled(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>=1;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) { + return False; + } + + /* we found it - construct the full name */ + strncpy(extension, name+9, 3); + + if (extension[0]) { + slprintf(name, sizeof(fstring), "%s.%s", prefix, extension); + } else { + fstrcpy(name, prefix); + } + return True; +} + + +/* + look for a DOS reserved name +*/ +static BOOL is_reserved_name(const char *name) +{ + if ((char_flags[(unsigned char)name[0]] & FLAG_POSSIBLE1) && + (char_flags[(unsigned char)name[1]] & FLAG_POSSIBLE2) && + (char_flags[(unsigned char)name[2]] & FLAG_POSSIBLE3)) { + /* 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 (strncasecmp(name, reserved_names[i], len) == 0 && + (name[len] == '.' || name[len] == 0)) { + return True; + } + } + } + + return False; +} + +/* + see if a filename is a legal long filename +*/ +static BOOL is_legal_name(const char *name) +{ + while (*name) { + if (char_flags[(unsigned char)*name] & FLAG_ILLEGAL) { + return False; + } + name++; + } + + 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 BOOL name_map(char *name, BOOL need83, BOOL cache83) +{ + char *dot_p; + char lead_char; + char extension[4]; + int extension_length, i; + 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)) { + return True; + } + + /* if the caller doesn't strictly need 8.3 then just check for illegal + filenames */ + if (!need83 && is_legal_name(name)) { + return True; + } + } + + /* find the '.' if any */ + dot_p = strchr(name, '.'); + + /* the leading character in the mangled name is taken from + the first character of the name, if it is ascii + otherwise '_' is used + */ + lead_char = name[0]; + if (! (char_flags[(unsigned char)lead_char] & FLAG_ASCII)) { + lead_char = '_'; + } + + /* 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 (char_flags[(unsigned char)c] & FLAG_ASCII) { + extension[extension_length++] = c; + } + } + } + + /* find the hash for this prefix */ + v = hash = mangle_hash(name, prefix_len); + + /* now form the mangled name */ + new_name[0] = lead_char; + new_name[7] = base_forward(v % 36); + new_name[6] = '~'; + for (i=5; i>=1; 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); + } + + /* and overwrite the old name */ + fstrcpy(name, new_name); + + /* all done, we've managed to mangle it */ + return True; +} + + +/* 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=0;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; + } + } + + 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; + + c1 = (unsigned char)reserved_names[i][0]; + c2 = (unsigned char)reserved_names[i][1]; + c3 = (unsigned char)reserved_names[i][2]; + + char_flags[c1] |= FLAG_POSSIBLE1; + char_flags[c2] |= FLAG_POSSIBLE2; + char_flags[c3] |= FLAG_POSSIBLE3; + char_flags[tolower(c1)] |= FLAG_POSSIBLE1; + char_flags[tolower(c2)] |= FLAG_POSSIBLE2; + char_flags[tolower(c3)] |= FLAG_POSSIBLE3; + } +} + + +/* + the following provides the abstraction layer to make it easier + to drop in an alternative mangling implementation */ +static struct mangle_fns mangle_fns = { + is_mangled, + is_8_3, + mangle_reset, + check_cache, + name_map +}; + +/* return the methods for this mangling implementation */ +struct mangle_fns *mangle_hash2_init(void) +{ + init_tables(); + mangle_reset(); + + if (!cache_init()) { + return NULL; + } + + return &mangle_fns; +} -- cgit From b1f04740ad705249cc783e8a084ca2d70fd8f3a7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 11 Apr 2002 10:52:59 +0000 Subject: some optimisations to the new mangling system (This used to be commit 30b35d0c1f41f72ebe230905f76db8807802a6cc) --- source3/smbd/mangle_hash2.c | 60 +++++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 16 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 661ae7eb44..88b9ba20cb 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -48,15 +48,24 @@ #include "includes.h" +#if 0 +#define M_DEBUG(level, x) DEBUG(level, x) +#else +#define M_DEBUG(level, x) +#endif #define FLAG_BASECHAR 1 #define FLAG_ASCII 2 #define FLAG_ILLEGAL 4 -#define FLAG_POSSIBLE1 8 -#define FLAG_POSSIBLE2 16 -#define FLAG_POSSIBLE3 32 +#define FLAG_WILDCARD 8 +#define FLAG_POSSIBLE1 16 +#define FLAG_POSSIBLE2 32 +#define FLAG_POSSIBLE3 64 +#define FLAG_POSSIBLE4 128 -#define CACHE_SIZE 8192 +#ifndef MANGLE_CACHE_SIZE +#define MANGLE_CACHE_SIZE 4096 +#endif /* these tables are used to provide fast tests for characters */ static unsigned char char_flags[256]; @@ -68,6 +77,7 @@ static unsigned char char_flags[256]; hashing the resulting cache entry to match the known hash */ static char **prefix_cache; +static u32 *prefix_cache_hashes; /* these are the characters we use in the 8.3 hash. Must be 36 chars long */ const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -112,10 +122,14 @@ static BOOL cache_init(void) { if (prefix_cache) return True; - prefix_cache = malloc(sizeof(char *) * CACHE_SIZE); + prefix_cache = malloc(sizeof(char *) * MANGLE_CACHE_SIZE); if (!prefix_cache) return False; - memset(prefix_cache, 0, sizeof(char *) * CACHE_SIZE); + prefix_cache_hashes = malloc(sizeof(u32) * MANGLE_CACHE_SIZE); + if (!prefix_cache_hashes) return False; + + memset(prefix_cache, 0, sizeof(char *) * MANGLE_CACHE_SIZE); + memset(prefix_cache_hashes, 0, sizeof(char *) * MANGLE_CACHE_SIZE); return True; } @@ -124,13 +138,14 @@ static BOOL cache_init(void) */ static void cache_insert(const char *prefix, int length, u32 hash) { - int i = hash % CACHE_SIZE; + int i = hash % MANGLE_CACHE_SIZE; if (prefix_cache[i]) { free(prefix_cache[i]); } prefix_cache[i] = strndup(prefix, length); + prefix_cache_hashes[i] = hash; } /* @@ -138,12 +153,9 @@ static void cache_insert(const char *prefix, int length, u32 hash) */ static const char *cache_lookup(u32 hash) { - int i = hash % CACHE_SIZE; - - if (!prefix_cache[i]) return NULL; + int i = hash % MANGLE_CACHE_SIZE; - /* we have a possible match - compute the hash to confirm */ - if (hash != mangle_hash(prefix_cache[i], strlen(prefix_cache[i]))) { + if (!prefix_cache[i] || hash != prefix_cache_hashes[i]) { return NULL; } @@ -229,7 +241,7 @@ static BOOL is_8_3(const char *name, BOOL check_case) /* the length are all OK. Now check to see if the characters themselves are OK */ for (i=0; name[i]; i++) { - if (!(char_flags[(unsigned)(name[i])] & FLAG_ASCII)) { + if (!(char_flags[(unsigned)(name[i])] & (FLAG_ASCII|FLAG_WILDCARD))) { return False; } } @@ -286,10 +298,13 @@ static BOOL check_cache(char *name) strncpy(extension, name+9, 3); if (extension[0]) { + M_DEBUG(0,("check_cache: %s -> %s.%s\n", name, prefix, extension)); slprintf(name, sizeof(fstring), "%s.%s", prefix, extension); } else { + M_DEBUG(0,("check_cache: %s -> %s\n", name, prefix)); fstrcpy(name, prefix); } + return True; } @@ -301,7 +316,8 @@ static BOOL is_reserved_name(const char *name) { if ((char_flags[(unsigned char)name[0]] & FLAG_POSSIBLE1) && (char_flags[(unsigned char)name[1]] & FLAG_POSSIBLE2) && - (char_flags[(unsigned char)name[2]] & FLAG_POSSIBLE3)) { + (char_flags[(unsigned char)name[2]] & FLAG_POSSIBLE3) && + (char_flags[(unsigned char)name[3]] & FLAG_POSSIBLE4)) { /* a likely match, scan the lot */ int i; for (i=0; reserved_names[i]; i++) { @@ -379,6 +395,7 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) if (! (char_flags[(unsigned char)lead_char] & FLAG_ASCII)) { lead_char = '_'; } + lead_char = toupper(lead_char); /* the prefix is anything up to the first dot */ if (dot_p) { @@ -394,7 +411,7 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) for (i=1; extension_length < 3 && dot_p[i]; i++) { char c = dot_p[i]; if (char_flags[(unsigned char)c] & FLAG_ASCII) { - extension[extension_length++] = c; + extension[extension_length++] = toupper(c); } } } @@ -425,6 +442,8 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) cache_insert(name, prefix_len, hash); } + M_DEBUG(0,("name_map: %s -> %s\n", name, new_name)); + /* and overwrite the old name */ fstrcpy(name, new_name); @@ -459,6 +478,10 @@ static void init_tables(void) if (strchr("*\\/?<>|\":", i)) { char_flags[i] |= FLAG_ILLEGAL; } + + if (strchr("*?\"<>", i)) { + char_flags[i] |= FLAG_WILDCARD; + } } memset(base_reverse, 0, sizeof(base_reverse)); @@ -469,18 +492,23 @@ static void init_tables(void) /* 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; + 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; } } -- cgit From ef88357403280922dc5fa707f6d58c7255083902 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 11 Apr 2002 11:46:42 +0000 Subject: added some more comments (This used to be commit 8d6f2e239940cbac44f6f0e9d584a47553acbc56) --- source3/smbd/mangle_hash2.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 88b9ba20cb..28200eb3ee 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -54,15 +54,21 @@ #define M_DEBUG(level, x) #endif +/* these flags are used to mark characters in as having particular + properties */ #define FLAG_BASECHAR 1 #define FLAG_ASCII 2 #define FLAG_ILLEGAL 4 #define FLAG_WILDCARD 8 + +/* the "possible" flags are used as a fast way to find possible DOS + reserved filenames */ #define FLAG_POSSIBLE1 16 #define FLAG_POSSIBLE2 32 #define FLAG_POSSIBLE3 64 #define FLAG_POSSIBLE4 128 +/* by default have a max of 4096 entries in the cache. */ #ifndef MANGLE_CACHE_SIZE #define MANGLE_CACHE_SIZE 4096 #endif @@ -100,11 +106,15 @@ static u32 mangle_hash(const char *key, unsigned length) u32 i; fstring str; + /* we have to uppercase here to ensure that the mangled name + doesn't depend on the case of the long name. Note that this + is the only place where we need to use a multi-byte string + function */ strncpy(str, key, length); str[length] = 0; strupper_m(str); - /* the length of a multi-byte string can change after a strupper */ + /* the length of a multi-byte string can change after a strupper_m */ length = strlen(str); /* Set the initial value from the key size. */ @@ -116,7 +126,7 @@ static u32 mangle_hash(const char *key, unsigned length) } /* - initialise the prefix cache + initialise (ie. allocate) the prefix cache */ static BOOL cache_init(void) { @@ -134,8 +144,8 @@ static BOOL cache_init(void) } /* - insert an entry into the prefix cache. The string may not be null terminated -*/ + insert an entry into the prefix cache. The string might not be null + terminated */ static void cache_insert(const char *prefix, int length, u32 hash) { int i = hash % MANGLE_CACHE_SIZE; @@ -419,7 +429,7 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) /* find the hash for this prefix */ v = hash = mangle_hash(name, prefix_len); - /* now form the mangled name */ + /* now form the mangled name. */ new_name[0] = lead_char; new_name[7] = base_forward(v % 36); new_name[6] = '~'; -- cgit From bf9cb3c5f3c5096bcf25a16f63ae18dad73bbef7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 11 Apr 2002 12:14:55 +0000 Subject: - tidier flag checking code - finished the is_mangled() function (This used to be commit 128bec2071d640c775b58322256ac6bb03363741) --- source3/smbd/mangle_hash2.c | 48 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 28200eb3ee..0bd538d2f4 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -76,6 +76,8 @@ /* these tables are used to provide fast tests for characters */ static unsigned char char_flags[256]; +#define FLAG_CHECK(c, flag) (char_flags[(unsigned char)(c)] & (flag)) + /* we will use a very simple direct mapped prefix cache. The big advantage of this cache structure is speed and low memory usage @@ -183,12 +185,41 @@ static const char *cache_lookup(u32 hash) */ static BOOL is_mangled(const char *name) { + int len, i; + + M_DEBUG(0,("is_mangled %s\n", name)); + /* the best distinguishing characteristic is the ~ */ if (name[6] != '~') return False; + /* check the length */ + len = strlen(name); + if (len > 12 || len < 8) return False; + /* check extension */ + if (len > 8) { + if (name[8] != '.') return False; + for (i=9; name[i]; i++) { + if (! FLAG_CHECK(name[i], FLAG_ASCII)) { + return False; + } + } + } + /* check first character */ + if (! FLAG_CHECK(name[0], FLAG_ASCII)) { + return False; + } + /* check rest of hash */ + if (! FLAG_CHECK(name[7], FLAG_BASECHAR)) { + return False; + } + for (i=1;i<6;i++) { + if (! FLAG_CHECK(name[i], FLAG_BASECHAR)) { + return False; + } + } return True; } @@ -251,7 +282,8 @@ static BOOL is_8_3(const char *name, BOOL check_case) /* the length are all OK. Now check to see if the characters themselves are OK */ for (i=0; name[i]; i++) { - if (!(char_flags[(unsigned)(name[i])] & (FLAG_ASCII|FLAG_WILDCARD))) { + /* note that we allow wildcard petterns! */ + if (!FLAG_CHECK(name[i], FLAG_ASCII|FLAG_WILDCARD)) { return False; } } @@ -324,10 +356,10 @@ static BOOL check_cache(char *name) */ static BOOL is_reserved_name(const char *name) { - if ((char_flags[(unsigned char)name[0]] & FLAG_POSSIBLE1) && - (char_flags[(unsigned char)name[1]] & FLAG_POSSIBLE2) && - (char_flags[(unsigned char)name[2]] & FLAG_POSSIBLE3) && - (char_flags[(unsigned char)name[3]] & FLAG_POSSIBLE4)) { + 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++) { @@ -349,7 +381,7 @@ static BOOL is_reserved_name(const char *name) static BOOL is_legal_name(const char *name) { while (*name) { - if (char_flags[(unsigned char)*name] & FLAG_ILLEGAL) { + if (FLAG_CHECK(name[0], FLAG_ILLEGAL)) { return False; } name++; @@ -402,7 +434,7 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) otherwise '_' is used */ lead_char = name[0]; - if (! (char_flags[(unsigned char)lead_char] & FLAG_ASCII)) { + if (! FLAG_CHECK(lead_char, FLAG_ASCII)) { lead_char = '_'; } lead_char = toupper(lead_char); @@ -420,7 +452,7 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) if (dot_p) { for (i=1; extension_length < 3 && dot_p[i]; i++) { char c = dot_p[i]; - if (char_flags[(unsigned char)c] & FLAG_ASCII) { + if (FLAG_CHECK(c, FLAG_ASCII)) { extension[extension_length++] = toupper(c); } } -- cgit From 4c889cb8b6ebaf73fd4034c590b758c367b69bae Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 11 Apr 2002 13:35:28 +0000 Subject: don't treat '.' as FLAG_ASCII, instead handle it separately (This used to be commit ecdddd674f2ffad16eaa01a68c9c91ff3b355b3f) --- source3/smbd/mangle_hash2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 0bd538d2f4..8b4b0f478d 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -283,7 +283,7 @@ static BOOL is_8_3(const char *name, BOOL check_case) /* the length are all OK. Now check to see if the characters themselves are OK */ for (i=0; name[i]; i++) { /* note that we allow wildcard petterns! */ - if (!FLAG_CHECK(name[i], FLAG_ASCII|FLAG_WILDCARD)) { + if (!FLAG_CHECK(name[i], FLAG_ASCII|FLAG_WILDCARD) && name[i] != '.') { return False; } } @@ -513,7 +513,7 @@ static void init_tables(void) (i >= 'A' && i <= 'Z')) { char_flags[i] |= (FLAG_ASCII | FLAG_BASECHAR); } - if (strchr("._-$~", i)) { + if (strchr("_-$~", i)) { char_flags[i] |= FLAG_ASCII; } -- cgit From 1ed0c5ea704a64a5ace6ba9ad600cb320c7d7ea4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 11 Apr 2002 14:03:30 +0000 Subject: a few debug statements (disabled) (This used to be commit 582f753eac7a111a93a8d6c049398a0998af848f) --- source3/smbd/mangle_hash2.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 8b4b0f478d..0ecea59caf 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -187,7 +187,7 @@ static BOOL is_mangled(const char *name) { int len, i; - M_DEBUG(0,("is_mangled %s\n", name)); + M_DEBUG(0,("is_mangled %s ?\n", name)); /* the best distinguishing characteristic is the ~ */ if (name[6] != '~') return False; @@ -221,6 +221,8 @@ static BOOL is_mangled(const char *name) } } + M_DEBUG(0,("is_mangled %s -> yes\n", name)); + return True; } @@ -319,6 +321,7 @@ static BOOL check_cache(char *name) /* make sure that this is a mangled name from this cache */ if (!is_mangled(name)) { + M_DEBUG(0,("check_cache: %s -> not mangled\n", name)); return False; } @@ -333,6 +336,7 @@ static BOOL check_cache(char *name) /* now look in the prefix cache for that hash */ prefix = cache_lookup(hash); if (!prefix) { + M_DEBUG(0,("check_cache: %s -> %08X -> not found\n", name, hash)); return False; } @@ -484,7 +488,8 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) cache_insert(name, prefix_len, hash); } - M_DEBUG(0,("name_map: %s -> %s\n", name, new_name)); + M_DEBUG(0,("name_map: %s -> %08X -> %s (cache=%d)\n", + name, hash, new_name, cache83)); /* and overwrite the old name */ fstrcpy(name, new_name); -- cgit From 5c0e682c4a2e8bb91911064c51bf4c690555cb33 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 11 Apr 2002 14:20:18 +0000 Subject: - the 36^6 hash space gives 31 bits, not 32 bits. We need to mask the hash to suit - the prefix ends at the last dot, not the first (This used to be commit 91a3ccd3e790f980421c1ee93388e19e87026b29) --- source3/smbd/mangle_hash2.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 0ecea59caf..96ca7360b8 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -124,7 +124,9 @@ static u32 mangle_hash(const char *key, unsigned length) value = (value + (((unsigned char)str[i]) << (i*5 % 24))); } - return (1103515243 * value + 12345); + /* note that we force it to a 31 bit hash, to keep within the limits + of the 36^6 mangle space */ + return (1103515243 * value + 12345) & ~0x80000000; } /* @@ -431,7 +433,7 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) } /* find the '.' if any */ - dot_p = strchr(name, '.'); + dot_p = strrchr(name, '.'); /* the leading character in the mangled name is taken from the first character of the name, if it is ascii -- cgit From 4023a61892278c9e09acd035166a55ff2b3d4f30 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 12 Apr 2002 10:18:46 +0000 Subject: merged the mangling test and passdb bugfixes into SAMBA_3_0 (This used to be commit 97eb3a121d33200ee7559b2413d6252efc04ebaf) --- source3/smbd/mangle_hash2.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 96ca7360b8..959a93e07b 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -344,6 +344,7 @@ static BOOL check_cache(char *name) /* we found it - construct the full name */ strncpy(extension, name+9, 3); + extension[3] = 0; if (extension[0]) { M_DEBUG(0,("check_cache: %s -> %s.%s\n", name, prefix, extension)); @@ -435,6 +436,19 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) /* 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 character in the mangled name is taken from the first character of the name, if it is ascii otherwise '_' is used -- cgit From e90b65284812aaa5ff9e9935ce9bbad7791cbbcd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 15 Jul 2002 10:35:28 +0000 Subject: updated the 3.0 branch from the head branch - ready for alpha18 (This used to be commit 03ac082dcb375b6f3ca3d810a6a6367542bc23ce) --- source3/smbd/mangle_hash2.c | 110 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 89 insertions(+), 21 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 959a93e07b..e2c4b43bc3 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. new hash based name mangling implementation Copyright (C) Andrew Tridgell 2002 + Copyright (C) Simo Sorce 2002 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,6 +31,10 @@ for simplicity, we only allow ascii characters in 8.3 names */ + /* hash alghorithm changed to FNV1 by idra@samba.org (Simo Sorce). + * see http://www.isthe.com/chongo/tech/comp/fnv/index.html for a + * discussion on Fowler / Noll / Vo (FNV) Hash by one of it's authors + */ /* =============================================================================== @@ -73,6 +78,10 @@ #define MANGLE_CACHE_SIZE 4096 #endif +#define FNV1_PRIME 0x01000193 +/*the following number is a fnv1 of the string: idra@samba.org 2002 */ +#define FNV1_INIT 0xa6b93095 + /* these tables are used to provide fast tests for characters */ static unsigned char char_flags[256]; @@ -88,13 +97,14 @@ static char **prefix_cache; static u32 *prefix_cache_hashes; /* these are the characters we use in the 8.3 hash. Must be 36 chars long */ -const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +static const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; static unsigned char base_reverse[256]; #define base_forward(v) basechars[v] /* the list of reserved dos names - all of these are illegal */ -const char *reserved_names[] = { "AUX", "LOCK$", "CON", "COM1", "COM2", "COM3", "COM4", - "LPT1", "LPT2", "LPT3", "NUL", "PRN", NULL }; +static const char *reserved_names[] = +{ "AUX", "LOCK$", "CON", "COM1", "COM2", "COM3", "COM4", + "LPT1", "LPT2", "LPT3", "NUL", "PRN", NULL }; /* hash a string of the specified length. The string does not need to be @@ -120,13 +130,14 @@ static u32 mangle_hash(const char *key, unsigned length) length = strlen(str); /* Set the initial value from the key size. */ - for (value = 0x238F13AF * length, i=0; i < length; i++) { - value = (value + (((unsigned char)str[i]) << (i*5 % 24))); - } + for (value = FNV1_INIT, i=0; i < length; i++) { + value *= (u32)FNV1_PRIME; + value ^= (u32)(str[i]); + } /* note that we force it to a 31 bit hash, to keep within the limits of the 36^6 mangle space */ - return (1103515243 * value + 12345) & ~0x80000000; + return value & ~0x80000000; } /* @@ -184,12 +195,12 @@ static const char *cache_lookup(u32 hash) In this algorithm, mangled names use only pure ascii characters (no multi-byte) so we can avoid doing a UCS2 conversion -*/ -static BOOL is_mangled(const char *name) + */ +static BOOL is_mangled_component(const char *name) { int len, i; - M_DEBUG(0,("is_mangled %s ?\n", name)); + M_DEBUG(0,("is_mangled_component %s ?\n", name)); /* the best distinguishing characteristic is the ~ */ if (name[6] != '~') return False; @@ -229,6 +240,39 @@ static BOOL is_mangled(const char *name) } + +/* + determine if a string is possibly in a mangled format, ignoring + case + + In this algorithm, mangled names use only pure ascii characters (no + multi-byte) so we can avoid doing a UCS2 conversion + + NOTE! This interface must be able to handle a path with unix + directory separators. It should return true if any component is + mangled + */ +static BOOL is_mangled(const char *name) +{ + const char *p; + const char *s; + + M_DEBUG(0,("is_mangled %s ?\n", name)); + + for (s=name; (p=strchr(s, '/')); s=p+1) { + char *component = strndup(s, PTR_DIFF(p, s)); + if (is_mangled_component(component)) { + free(component); + return True; + } + free(component); + } + + /* and the last part ... */ + return is_mangled_component(s); +} + + /* see if a filename is an allowable 8.3 name. @@ -236,7 +280,7 @@ static BOOL is_mangled(const char *name) simplifies things greatly (it means that we know the string won't get larger when converted from UNIX to DOS formats) */ -static BOOL is_8_3(const char *name, BOOL check_case) +static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards) { int len, i; char *dot_p; @@ -286,8 +330,8 @@ static BOOL is_8_3(const char *name, BOOL check_case) /* the length are all OK. Now check to see if the characters themselves are OK */ for (i=0; name[i]; i++) { - /* note that we allow wildcard petterns! */ - if (!FLAG_CHECK(name[i], FLAG_ASCII|FLAG_WILDCARD) && name[i] != '.') { + /* note that we may allow wildcard petterns! */ + if (!FLAG_CHECK(name[i], FLAG_ASCII|(allow_wildcards ? FLAG_WILDCARD : 0)) && name[i] != '.') { return False; } } @@ -343,8 +387,12 @@ static BOOL check_cache(char *name) } /* we found it - construct the full name */ - strncpy(extension, name+9, 3); - extension[3] = 0; + if (name[8] == '.') { + strncpy(extension, name+9, 3); + extension[3] = 0; + } else { + extension[0] = 0; + } if (extension[0]) { M_DEBUG(0,("check_cache: %s -> %s.%s\n", name, prefix, extension)); @@ -383,17 +431,38 @@ static BOOL is_reserved_name(const char *name) } /* - see if a filename is a legal long filename + See if a filename is a legal long filename. + A filename ending in a '.' is not legal unless it's "." or "..". JRA. */ + static BOOL is_legal_name(const char *name) { + const char *dot_pos = NULL; + BOOL alldots = True; + size_t numdots = 0; + while (*name) { if (FLAG_CHECK(name[0], FLAG_ILLEGAL)) { return False; } + if (name[0] == '.') { + dot_pos = name; + numdots++; + } else { + alldots = 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; } @@ -408,7 +477,7 @@ static BOOL is_legal_name(const char *name) the name parameter must be able to hold 13 bytes */ -static BOOL name_map(char *name, BOOL need83, BOOL cache83) +static void name_map(char *name, BOOL need83, BOOL cache83) { char *dot_p; char lead_char; @@ -422,14 +491,14 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) 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)) { - return True; + 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 True; + return; } } @@ -511,7 +580,6 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83) fstrcpy(name, new_name); /* all done, we've managed to mangle it */ - return True; } -- cgit From 127e77e6e334fdc33086bffcbe00d340c0ba0097 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 17 Aug 2002 15:27:10 +0000 Subject: Sync 3.0 branch with head (This used to be commit 42615b945e2e48e53a21ea47f2e45407913a6a1e) --- source3/smbd/mangle_hash2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index e2c4b43bc3..6b53cc72aa 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -202,13 +202,13 @@ static BOOL is_mangled_component(const char *name) M_DEBUG(0,("is_mangled_component %s ?\n", name)); - /* the best distinguishing characteristic is the ~ */ - if (name[6] != '~') return False; - /* check the length */ len = strlen(name); if (len > 12 || len < 8) return False; + /* the best distinguishing characteristic is the ~ */ + if (name[6] != '~') return False; + /* check extension */ if (len > 8) { if (name[8] != '.') return False; -- cgit From a834a73e341059be154426390304a42e4a011f72 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 25 Sep 2002 15:19:00 +0000 Subject: sync'ing up for 3.0alpha20 release (This used to be commit 65e7b5273bb58802bf0c389b77f7fcae0a1f6139) --- source3/smbd/mangle_hash2.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 6b53cc72aa..a0a3d51139 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -200,7 +200,7 @@ static BOOL is_mangled_component(const char *name) { int len, i; - M_DEBUG(0,("is_mangled_component %s ?\n", name)); + M_DEBUG(10,("is_mangled_component %s ?\n", name)); /* check the length */ len = strlen(name); @@ -234,7 +234,7 @@ static BOOL is_mangled_component(const char *name) } } - M_DEBUG(0,("is_mangled %s -> yes\n", name)); + M_DEBUG(10,("is_mangled %s -> yes\n", name)); return True; } @@ -257,7 +257,7 @@ static BOOL is_mangled(const char *name) const char *p; const char *s; - M_DEBUG(0,("is_mangled %s ?\n", name)); + M_DEBUG(10,("is_mangled %s ?\n", name)); for (s=name; (p=strchr(s, '/')); s=p+1) { char *component = strndup(s, PTR_DIFF(p, s)); @@ -367,7 +367,7 @@ static BOOL check_cache(char *name) /* make sure that this is a mangled name from this cache */ if (!is_mangled(name)) { - M_DEBUG(0,("check_cache: %s -> not mangled\n", name)); + M_DEBUG(10,("check_cache: %s -> not mangled\n", name)); return False; } @@ -382,7 +382,7 @@ static BOOL check_cache(char *name) /* now look in the prefix cache for that hash */ prefix = cache_lookup(hash); if (!prefix) { - M_DEBUG(0,("check_cache: %s -> %08X -> not found\n", name, hash)); + M_DEBUG(10,("check_cache: %s -> %08X -> not found\n", name, hash)); return False; } @@ -395,10 +395,10 @@ static BOOL check_cache(char *name) } if (extension[0]) { - M_DEBUG(0,("check_cache: %s -> %s.%s\n", name, prefix, extension)); + M_DEBUG(10,("check_cache: %s -> %s.%s\n", name, prefix, extension)); slprintf(name, sizeof(fstring), "%s.%s", prefix, extension); } else { - M_DEBUG(0,("check_cache: %s -> %s\n", name, prefix)); + M_DEBUG(10,("check_cache: %s -> %s\n", name, prefix)); fstrcpy(name, prefix); } @@ -573,7 +573,7 @@ static void name_map(char *name, BOOL need83, BOOL cache83) cache_insert(name, prefix_len, hash); } - M_DEBUG(0,("name_map: %s -> %08X -> %s (cache=%d)\n", + M_DEBUG(10,("name_map: %s -> %08X -> %s (cache=%d)\n", name, hash, new_name, cache83)); /* and overwrite the old name */ -- cgit From b8e4a3331ddcda9339b2508e1ef24a1c2eab19cb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 15 Oct 2002 05:58:32 +0000 Subject: Merge Anton's 64-bit fix. Jeremy. (This used to be commit 0644f6a68e5c1d9a2c236ab0f90d4801848a9b33) --- source3/smbd/mangle_hash2.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index a0a3d51139..5adde19eea 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -147,14 +147,12 @@ static BOOL cache_init(void) { if (prefix_cache) return True; - prefix_cache = malloc(sizeof(char *) * MANGLE_CACHE_SIZE); + prefix_cache = calloc(MANGLE_CACHE_SIZE, sizeof(char *)); if (!prefix_cache) return False; - prefix_cache_hashes = malloc(sizeof(u32) * MANGLE_CACHE_SIZE); + prefix_cache_hashes = calloc(MANGLE_CACHE_SIZE, sizeof(u32)); if (!prefix_cache_hashes) return False; - memset(prefix_cache, 0, sizeof(char *) * MANGLE_CACHE_SIZE); - memset(prefix_cache_hashes, 0, sizeof(char *) * MANGLE_CACHE_SIZE); return True; } -- cgit From 1ef283d5c34d58389309a86e768ba52413943e9d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 21 Oct 2002 20:40:23 +0000 Subject: Merge mangle prefix code. Jeremy. (This used to be commit 83261f43326ae65af498399b5c933dfb20df1df7) --- source3/smbd/mangle_hash2.c | 57 ++++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 16 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 5adde19eea..bbc9020eab 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -87,6 +87,13 @@ static unsigned char char_flags[256]; #define FLAG_CHECK(c, flag) (char_flags[(unsigned char)(c)] & (flag)) +/* + this determines how many characters are used from the original filename + in the 8.3 mangled name. A larger value leads to a weaker hash and more collisions. + The largest possible value is 6. +*/ +static unsigned mangle_prefix; + /* we will use a very simple direct mapped prefix cache. The big advantage of this cache structure is speed and low memory usage @@ -217,16 +224,18 @@ static BOOL is_mangled_component(const char *name) } } - /* check first character */ - if (! FLAG_CHECK(name[0], FLAG_ASCII)) { - return False; + /* check lead characters */ + for (i=0;i=1;i--) { + for (multiplier=36, i=5;i>=mangle_prefix;i--) { u32 v = base_reverse[(unsigned char)name[i]]; hash += multiplier * v; multiplier *= 36; @@ -478,7 +487,7 @@ static BOOL is_legal_name(const char *name) static void name_map(char *name, BOOL need83, BOOL cache83) { char *dot_p; - char lead_char; + char lead_chars[7]; char extension[4]; int extension_length, i; int prefix_len; @@ -516,15 +525,20 @@ static void name_map(char *name, BOOL need83, BOOL cache83) if (i == 0 || i == 4) dot_p = NULL; } - /* the leading character in the mangled name is taken from - the first character of the name, if it is ascii - otherwise '_' is used + /* the leading characters in the mangled name is taken from + the first characters of the name, if they are ascii otherwise + '_' is used */ - lead_char = name[0]; - if (! FLAG_CHECK(lead_char, FLAG_ASCII)) { - lead_char = '_'; + for (i=0;i=1; i--) { + for (i=5; i>=mangle_prefix; i--) { v = v / 36; new_name[i] = base_forward(v % 36); } @@ -594,7 +610,7 @@ static void init_tables(void) memset(char_flags, 0, sizeof(char_flags)); - for (i=0;i<128;i++) { + for (i=1;i<128;i++) { if ((i >= '0' && i <= '9') || (i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z')) { @@ -656,6 +672,15 @@ static struct mangle_fns mangle_fns = { /* 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(); -- cgit From 266ec4aac04cb8666234f18baa38ff6387f40cb3 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 24 Feb 2003 03:09:08 +0000 Subject: Merge doxygen, signed/unsigned, const and other small fixes from HEAD to 3.0. Andrew Bartlett (This used to be commit 9ef0d40c3f8aef52ab321dc065264c42065bc876) --- source3/smbd/mangle_hash2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index bbc9020eab..eda509214d 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -203,7 +203,7 @@ static const char *cache_lookup(u32 hash) */ static BOOL is_mangled_component(const char *name) { - int len, i; + unsigned int len, i; M_DEBUG(10,("is_mangled_component %s ?\n", name)); @@ -368,7 +368,7 @@ static void mangle_reset(void) static BOOL check_cache(char *name) { u32 hash, multiplier; - int i; + unsigned int i; const char *prefix; char extension[4]; @@ -489,8 +489,8 @@ static void name_map(char *name, BOOL need83, BOOL cache83) char *dot_p; char lead_chars[7]; char extension[4]; - int extension_length, i; - int prefix_len; + unsigned int extension_length, i; + unsigned int prefix_len; u32 hash, v; char new_name[13]; -- cgit From ad0d6509a761154c113e040a82ad78e72a3ccf30 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 17 Mar 2003 22:56:13 +0000 Subject: Merge from HEAD: - Make ReadDirName return a const char*. - Consequential changes from that - mark our fstring/pstring assumptions in function prototypes Andrew Bartlett (This used to be commit 10b53d7c6fd77f23433dd2ef12bb14b227147a48) --- source3/smbd/mangle_hash2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index eda509214d..cdce28e1bd 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -484,7 +484,7 @@ static BOOL is_legal_name(const char *name) the name parameter must be able to hold 13 bytes */ -static void name_map(char *name, BOOL need83, BOOL cache83) +static void name_map(fstring name, BOOL need83, BOOL cache83) { char *dot_p; char lead_chars[7]; -- cgit From 8df07f37a280a15e16423006e3d2cc66f03cd787 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 27 Aug 2003 18:17:33 +0000 Subject: Remove completely unneeded malloc/free out of this codepath. Jeremy. (This used to be commit fda254169778cc3fa9c226473b5a1f95c17c99a7) --- source3/smbd/mangle_hash2.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index cdce28e1bd..27d044f56d 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -201,22 +201,24 @@ static const char *cache_lookup(u32 hash) In this algorithm, mangled names use only pure ascii characters (no multi-byte) so we can avoid doing a UCS2 conversion */ -static BOOL is_mangled_component(const char *name) +static BOOL is_mangled_component(const char *name, size_t len) { - unsigned int len, i; + unsigned int i; M_DEBUG(10,("is_mangled_component %s ?\n", name)); /* check the length */ - len = strlen(name); - if (len > 12 || len < 8) return False; + if (len > 12 || len < 8) + return False; /* the best distinguishing characteristic is the ~ */ - if (name[6] != '~') return False; + if (name[6] != '~') + return False; /* check extension */ if (len > 8) { - if (name[8] != '.') return False; + if (name[8] != '.') + return False; for (i=9; name[i]; i++) { if (! FLAG_CHECK(name[i], FLAG_ASCII)) { return False; @@ -241,7 +243,7 @@ static BOOL is_mangled_component(const char *name) } } - M_DEBUG(10,("is_mangled %s -> yes\n", name)); + M_DEBUG(10,("is_mangled_component %s (len %u) -> yes\n", name, (unsigned int)len)); return True; } @@ -267,16 +269,13 @@ static BOOL is_mangled(const char *name) M_DEBUG(10,("is_mangled %s ?\n", name)); for (s=name; (p=strchr(s, '/')); s=p+1) { - char *component = strndup(s, PTR_DIFF(p, s)); - if (is_mangled_component(component)) { - free(component); + if (is_mangled_component(s, PTR_DIFF(p, s))) { return True; } - free(component); } /* and the last part ... */ - return is_mangled_component(s); + return is_mangled_component(s,strlen(s)); } -- cgit From 9511c987df258a9c558f9ade18c5e5549c24eafb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 27 Aug 2003 18:21:26 +0000 Subject: Fix initial debug. Jeremy. (This used to be commit bd40da06352184ed1c4bcaf3449dcdc7fdc59bbd) --- source3/smbd/mangle_hash2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 27d044f56d..ee0ef69feb 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -205,7 +205,7 @@ static BOOL is_mangled_component(const char *name, size_t len) { unsigned int i; - M_DEBUG(10,("is_mangled_component %s ?\n", name)); + M_DEBUG(10,("is_mangled_component %s (len %u) ?\n", name, (unsigned int)len)); /* check the length */ if (len > 12 || len < 8) -- cgit From 46765d97fae2930836582a2590a4bfb9f2a78e9a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 27 Aug 2003 19:01:55 +0000 Subject: Check for embedded mb chars when testing for illegal characters like /. Should fix mangling for Japanese language. Jeremy. (This used to be commit a238bcc440e310a9ea7800e4fb0b4d39c1f0a0d7) --- source3/smbd/mangle_hash2.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index ee0ef69feb..9cd0438d51 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -304,7 +304,8 @@ static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards) the result we need in this case. Using strlen_m would not only be slower, it would be incorrect */ len = strlen(name); - if (len > 12) return False; + if (len > 12) + return False; /* find the '.'. Note that once again we use the non-multibyte function */ @@ -448,6 +449,27 @@ static BOOL is_legal_name(const char *name) size_t numdots = 0; while (*name) { + if (((unsigned int)name[0]) > 128 && (name[1] != 0)) { + /* Possible start of mb character. */ + char mbc[2]; + /* + * We know the following will return 2 bytes. What + * we need to know was if errno was set. + * 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. + */ + errno = 0; + convert_string(CH_UNIX, CH_UCS2, name, 2, mbc, 2); + if (!errno) { + /* Was a good mb string. */ + name += 2; + continue; + } + } + if (FLAG_CHECK(name[0], FLAG_ILLEGAL)) { return False; } -- cgit From dd50c0ed68457ac8118b00e568a30ae4abf5d33b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 15 Sep 2003 18:53:01 +0000 Subject: A *curse* upon the person who #ifdefed out the mangle debug statements by default ! This is code that really needs to be able to be looked at on a customer system if it's misbehaving ! Jeremy (This used to be commit d512650340b3d28db763d018a6b05f6edf165bf0) --- source3/smbd/mangle_hash2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 9cd0438d51..351461f11f 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -53,7 +53,7 @@ #include "includes.h" -#if 0 +#if 1 #define M_DEBUG(level, x) DEBUG(level, x) #else #define M_DEBUG(level, x) -- cgit From 9b8cbdfc2b0a601da1424784fbf02b705cc3fc8d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 15 Sep 2003 21:19:43 +0000 Subject: Fix OOPS when dealing with mangled names reported by several users. This was my bug when removing a redundant strlen. Jerry - last showstopper I knew about. Jeremy. (This used to be commit 6e6769c20643f784d1b5023df3071a35d2e5bf89) --- source3/smbd/mangle_hash2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 351461f11f..e0efb3e41b 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -219,7 +219,7 @@ static BOOL is_mangled_component(const char *name, size_t len) if (len > 8) { if (name[8] != '.') return False; - for (i=9; name[i]; i++) { + for (i=9; name[i] && i < len; i++) { if (! FLAG_CHECK(name[i], FLAG_ASCII)) { return False; } -- cgit From bb0598faf58679a7ad26a1caab8eadb154a07ae2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 22 Oct 2003 23:38:20 +0000 Subject: Put strcasecmp/strncasecmp on the banned list (except for needed calls in iconv.c and nsswitch/). Using them means you're not thinking about multibyte at all and I really want to discourage that. Jeremy. (This used to be commit d7e35dfb9283d560d0ed2ab231f36ed92767dace) --- source3/smbd/mangle_hash2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index e0efb3e41b..7e7bc8c68c 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -427,7 +427,7 @@ static BOOL is_reserved_name(const char *name) 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 (strncasecmp(name, reserved_names[i], len) == 0 && + if (strnequal(name, reserved_names[i], len) && (name[len] == '.' || name[len] == 0)) { return True; } -- cgit From 7b39861342279a3ecfb4b2b854162f2ec602afbd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Nov 2003 01:47:27 +0000 Subject: Ensure we mangle names ending in '.' in hash2 mangling method. Jeremy. (This used to be commit fc2af591f5a2b08caa7389150c8cc5e298bd0ed4) --- source3/smbd/mangle_hash2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 7e7bc8c68c..8dfa84d054 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -325,7 +325,7 @@ static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards) prefix_len = PTR_DIFF(dot_p, name); suffix_len = len - (prefix_len+1); - if (prefix_len > 8 || suffix_len > 3) { + if (prefix_len > 8 || suffix_len > 3 || suffix_len == 0) { return False; } -- cgit From e3f5b542707e2328030b9d5eff0836a904eccde5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 11 Mar 2004 22:48:24 +0000 Subject: Restore the contract on all convert_stringXX() interfaces. Add a "allow_bad_conv" boolean parameter that allows broken iconv conversions to work. Gets rid of the nasty errno checks in mangle_hash2 and check_path_syntax and allows correct return code checking. Jeremy. (This used to be commit 7b96765c23637613f079d37566d95d5edd511f05) --- source3/smbd/mangle_hash2.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 8dfa84d054..62087e7e59 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -453,17 +453,13 @@ static BOOL is_legal_name(const char *name) /* Possible start of mb character. */ char mbc[2]; /* - * We know the following will return 2 bytes. What - * we need to know was if errno was set. * 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. */ - errno = 0; - convert_string(CH_UNIX, CH_UCS2, name, 2, mbc, 2); - if (!errno) { + if (convert_string(CH_UNIX, CH_UCS2, name, 2, mbc, 2, False) == 2) { /* Was a good mb string. */ name += 2; continue; -- cgit From e0da56a84808c522bc7324b5d636f1cbd317a2c5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 May 2004 18:37:47 +0000 Subject: r570: Remove lots of globals to handle case issues - move them to connection struct entries (as they should have been from the start). Jerry, once you've cut over to 3.0.4 release branch I'll add this to 3.0 also. - Jerry cut over :-). Jeremy. (This used to be commit 578a508509d21226ad3332fc54c3ab54cd8ae452) --- source3/smbd/mangle_hash2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 62087e7e59..dcfd7663ba 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -501,7 +501,7 @@ static BOOL is_legal_name(const char *name) the name parameter must be able to hold 13 bytes */ -static void name_map(fstring name, BOOL need83, BOOL cache83) +static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case) { char *dot_p; char lead_chars[7]; -- cgit From 0c6d7f28d6c1066cc6b3055ebf6a8fcf685ca1f6 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 22 Jul 2004 13:39:43 +0000 Subject: r1570: merging changes from 3.0.5 (This used to be commit 430cf63b9148441bce42bfb15a8045de5da108f4) --- source3/smbd/mangle_hash2.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index dcfd7663ba..f68873687b 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -362,10 +362,8 @@ static void mangle_reset(void) /* try to find a 8.3 name in the cache, and if found then replace the string with the original long name. - - The filename must be able to hold at least sizeof(fstring) */ -static BOOL check_cache(char *name) +static BOOL check_cache(char *name, size_t maxlen) { u32 hash, multiplier; unsigned int i; @@ -403,10 +401,10 @@ static BOOL check_cache(char *name) if (extension[0]) { M_DEBUG(10,("check_cache: %s -> %s.%s\n", name, prefix, extension)); - slprintf(name, sizeof(fstring), "%s.%s", prefix, extension); + slprintf(name, maxlen, "%s.%s", prefix, extension); } else { M_DEBUG(10,("check_cache: %s -> %s\n", name, prefix)); - fstrcpy(name, prefix); + safe_strcpy(name, prefix, maxlen); } return True; -- cgit From 5ef08833b8aea6fffe19173349c0ac9b50994b5f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 26 Aug 2004 21:39:10 +0000 Subject: r2082: lp_path should be lp_pathname. Paranoia fix on mangle prefix. Jeremy. (This used to be commit cc91bbe20d9cb26e52ad417f279e2d60c85af2dc) --- source3/smbd/mangle_hash2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index f68873687b..c6ad1215b0 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -119,7 +119,7 @@ static const char *reserved_names[] = this hash needs to be fast with a low collision rate (what hash doesn't?) */ -static u32 mangle_hash(const char *key, unsigned length) +static u32 mangle_hash(const char *key, unsigned int length) { u32 value; u32 i; @@ -129,6 +129,7 @@ static u32 mangle_hash(const char *key, unsigned length) doesn't depend on the case of the long name. Note that this is the only place where we need to use a multi-byte string function */ + length = MIN(length,sizeof(fstring)-1); strncpy(str, key, length); str[length] = 0; strupper_m(str); -- cgit From acf9d61421faa6c0055d57fdee7db300dc5431aa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Dec 2004 18:25:53 +0000 Subject: r4088: Get medieval on our ass about malloc.... :-). Take control of all our allocation functions so we can funnel through some well known functions. Should help greatly with malloc checking. HEAD patch to follow. Jeremy. (This used to be commit 620f2e608f70ba92f032720c031283d295c5c06a) --- source3/smbd/mangle_hash2.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index c6ad1215b0..4896cfb17b 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -153,13 +153,19 @@ static u32 mangle_hash(const char *key, unsigned int length) */ static BOOL cache_init(void) { - if (prefix_cache) return True; + if (prefix_cache) { + return True; + } - prefix_cache = calloc(MANGLE_CACHE_SIZE, sizeof(char *)); - if (!prefix_cache) return False; + prefix_cache = SMB_CALLOC_ARRAY(char *,MANGLE_CACHE_SIZE); + if (!prefix_cache) { + return False; + } - prefix_cache_hashes = calloc(MANGLE_CACHE_SIZE, sizeof(u32)); - if (!prefix_cache_hashes) return False; + prefix_cache_hashes = SMB_CALLOC_ARRAY(u32, MANGLE_CACHE_SIZE); + if (!prefix_cache_hashes) { + return False; + } return True; } @@ -175,7 +181,7 @@ static void cache_insert(const char *prefix, int length, u32 hash) free(prefix_cache[i]); } - prefix_cache[i] = strndup(prefix, length); + prefix_cache[i] = SMB_STRNDUP(prefix, length); prefix_cache_hashes[i] = hash; } -- cgit From 02e3717ee9e045d197d845489e84ac40083ca868 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 May 2005 08:07:39 +0000 Subject: r6625: Remove another global variable left over from a long time ago (magic char). Jeremy. (This used to be commit b1bfa9cb37deb22d1d08bc60ba44d61334f6446e) --- source3/smbd/mangle_hash2.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 4896cfb17b..6a8462ee3d 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -268,7 +268,7 @@ static BOOL is_mangled_component(const char *name, size_t len) directory separators. It should return true if any component is mangled */ -static BOOL is_mangled(const char *name) +static BOOL is_mangled(const char *name, int snum) { const char *p; const char *s; @@ -293,7 +293,7 @@ static BOOL is_mangled(const char *name) simplifies things greatly (it means that we know the string won't get larger when converted from UNIX to DOS formats) */ -static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards) +static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards, int snum) { int len, i; char *dot_p; @@ -370,7 +370,7 @@ static void mangle_reset(void) try to find a 8.3 name in the cache, and if found then replace the string with the original long name. */ -static BOOL check_cache(char *name, size_t maxlen) +static BOOL check_cache(char *name, size_t maxlen, int snum) { u32 hash, multiplier; unsigned int i; @@ -378,7 +378,7 @@ static BOOL check_cache(char *name, size_t maxlen) char extension[4]; /* make sure that this is a mangled name from this cache */ - if (!is_mangled(name)) { + if (!is_mangled(name, snum)) { M_DEBUG(10,("check_cache: %s -> not mangled\n", name)); return False; } @@ -506,7 +506,7 @@ static BOOL is_legal_name(const char *name) the name parameter must be able to hold 13 bytes */ -static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case) +static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, int snum) { char *dot_p; char lead_chars[7]; @@ -520,7 +520,7 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case) 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)) { + if (is_8_3(name, False, False, snum)) { return; } @@ -679,14 +679,13 @@ static void init_tables(void) } } - /* 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, - mangle_reset, check_cache, name_map }; -- cgit From 75f109bc81c0ff0d714070b3f324bce62c2f3984 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 25 May 2005 19:25:35 +0000 Subject: r6977: Fix bug #2735 (not mangling control characters) plus ensure we don't create files with control characters either. Jeremy. (This used to be commit 0ca2423c706423a07721e375345b6d45a45cbcf4) --- source3/smbd/mangle_hash2.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 6a8462ee3d..4325c07f58 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -633,6 +633,11 @@ static void init_tables(void) 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')) { -- cgit From 7e509e9b99a18495bde01a990e37de70bae35aac Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 22 Jun 2005 21:20:41 +0000 Subject: r7842: With the patch I sent Steve yesterday this gives us complete POSIX pathnames. ie. files containing : and \ can be accessed from Linux. Jeremy. (This used to be commit e9b8d23d6138d909a65ea70b2e801881e8333b38) --- source3/smbd/mangle_hash2.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 4325c07f58..e44aaf17e7 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -716,3 +716,42 @@ struct mangle_fns *mangle_hash2_init(void) 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; +} -- cgit From 4850bc63104f5f2945d9e91cfbd99773a5bc570f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 29 Sep 2005 01:27:19 +0000 Subject: r10600: Fix bug #2769 (mangle filenames ending in a space) and an old bug where mangle mathod hash wasn't mangling file names with more than one dot which also end in a dot. Jeremy. (This used to be commit 105e38847dc0078951abcda16808590ccc363b00) --- source3/smbd/mangle_hash2.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index e44aaf17e7..613dda9a16 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -445,6 +445,7 @@ static BOOL is_reserved_name(const char *name) /* 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) @@ -480,6 +481,10 @@ static BOOL is_legal_name(const char *name) } else { alldots = False; } + if ((name[0] == ' ') && (name[1] == '\0')) { + /* Can't end in ' ' */ + return False; + } name++; } @@ -491,7 +496,6 @@ static BOOL is_legal_name(const char *name) if (dot_pos[1] == '\0') return False; } - return True; } -- cgit From 54abd2aa66069e6baf7769c496f46d9dba18db39 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 30 Sep 2005 17:13:37 +0000 Subject: r10656: BIG merge from trunk. Features not copied over * \PIPE\unixinfo * winbindd's {group,alias}membership new functions * winbindd's lookupsids() functionality * swat (trunk changes to be reverted as per discussion with Deryck) (This used to be commit 939c3cb5d78e3a2236209b296aa8aba8bdce32d3) --- source3/smbd/mangle_hash2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 613dda9a16..335ba8e2ef 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -212,7 +212,7 @@ static BOOL is_mangled_component(const char *name, size_t len) { unsigned int i; - M_DEBUG(10,("is_mangled_component %s (len %u) ?\n", name, (unsigned int)len)); + M_DEBUG(10,("is_mangled_component %s (len %lu) ?\n", name, (unsigned long)len)); /* check the length */ if (len > 12 || len < 8) @@ -250,7 +250,7 @@ static BOOL is_mangled_component(const char *name, size_t len) } } - M_DEBUG(10,("is_mangled_component %s (len %u) -> yes\n", name, (unsigned int)len)); + M_DEBUG(10,("is_mangled_component %s (len %lu) -> yes\n", name, (unsigned long)len)); return True; } -- cgit From 5a4881bf396e691524329bcd6aa1ae4a7f4084ec Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 Dec 2005 20:52:36 +0000 Subject: r12522: Try and fix bug #2926 by removing setlocale(LC_ALL, "C") and replace calls to isupper/islower/toupper/tolower with ASCII equivalents (mapping into _w variants). Jeremy. (This used to be commit c2752347eb2deeb2798c580ec7fc751a847717e9) --- source3/smbd/mangle_hash2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 335ba8e2ef..0a161c9e76 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -560,7 +560,7 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, if (! FLAG_CHECK(lead_chars[i], FLAG_ASCII)) { lead_chars[i] = '_'; } - lead_chars[i] = toupper(lead_chars[i]); + lead_chars[i] = toupper_ascii(lead_chars[i]); } for (;i Date: Mon, 17 Apr 2006 12:23:38 +0000 Subject: r15102: u32 is a tdb-only thing that's not exported by samba4 tdb. Replace by uint32. Volker (This used to be commit 0a1665a1b78d063840e42e85229ace5a751e3985) --- source3/smbd/mangle_hash2.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 0a161c9e76..ec17109422 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -101,7 +101,7 @@ static unsigned mangle_prefix; hashing the resulting cache entry to match the known hash */ static char **prefix_cache; -static u32 *prefix_cache_hashes; +static uint32 *prefix_cache_hashes; /* these are the characters we use in the 8.3 hash. Must be 36 chars long */ static const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -119,10 +119,10 @@ static const char *reserved_names[] = this hash needs to be fast with a low collision rate (what hash doesn't?) */ -static u32 mangle_hash(const char *key, unsigned int length) +static uint32 mangle_hash(const char *key, unsigned int length) { - u32 value; - u32 i; + uint32 value; + uint32 i; fstring str; /* we have to uppercase here to ensure that the mangled name @@ -139,8 +139,8 @@ static u32 mangle_hash(const char *key, unsigned int length) /* Set the initial value from the key size. */ for (value = FNV1_INIT, i=0; i < length; i++) { - value *= (u32)FNV1_PRIME; - value ^= (u32)(str[i]); + value *= (uint32)FNV1_PRIME; + value ^= (uint32)(str[i]); } /* note that we force it to a 31 bit hash, to keep within the limits @@ -162,7 +162,7 @@ static BOOL cache_init(void) return False; } - prefix_cache_hashes = SMB_CALLOC_ARRAY(u32, MANGLE_CACHE_SIZE); + prefix_cache_hashes = SMB_CALLOC_ARRAY(uint32, MANGLE_CACHE_SIZE); if (!prefix_cache_hashes) { return False; } @@ -173,7 +173,7 @@ static BOOL cache_init(void) /* insert an entry into the prefix cache. The string might not be null terminated */ -static void cache_insert(const char *prefix, int length, u32 hash) +static void cache_insert(const char *prefix, int length, uint32 hash) { int i = hash % MANGLE_CACHE_SIZE; @@ -188,7 +188,7 @@ static void cache_insert(const char *prefix, int length, u32 hash) /* lookup an entry in the prefix cache. Return NULL if not found. */ -static const char *cache_lookup(u32 hash) +static const char *cache_lookup(uint32 hash) { int i = hash % MANGLE_CACHE_SIZE; @@ -372,7 +372,7 @@ static void mangle_reset(void) */ static BOOL check_cache(char *name, size_t maxlen, int snum) { - u32 hash, multiplier; + uint32 hash, multiplier; unsigned int i; const char *prefix; char extension[4]; @@ -386,7 +386,7 @@ static BOOL check_cache(char *name, size_t maxlen, int snum) /* 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]]; + uint32 v = base_reverse[(unsigned char)name[i]]; hash += multiplier * v; multiplier *= 36; } @@ -517,7 +517,7 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, char extension[4]; unsigned int extension_length, i; unsigned int prefix_len; - u32 hash, v; + uint32 hash, v; char new_name[13]; /* reserved names are handled specially */ -- cgit From 76e581b983989377d3ac3ae89b2b7d925aadc3f5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 17 Apr 2006 12:27:35 +0000 Subject: r15103: Okay, looking closer: Samba4 tdb not exporting u32 is a bug in samba4's tdb. tdb_open_ex needs it. Can someone from samba4 tell me how this should be handled? Thanks, Volker (This used to be commit 0a2f1ed5e9012e07ef158666b68994d0961768b6) --- source3/smbd/mangle_hash2.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index ec17109422..0a161c9e76 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -101,7 +101,7 @@ static unsigned mangle_prefix; hashing the resulting cache entry to match the known hash */ static char **prefix_cache; -static uint32 *prefix_cache_hashes; +static u32 *prefix_cache_hashes; /* these are the characters we use in the 8.3 hash. Must be 36 chars long */ static const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -119,10 +119,10 @@ static const char *reserved_names[] = this hash needs to be fast with a low collision rate (what hash doesn't?) */ -static uint32 mangle_hash(const char *key, unsigned int length) +static u32 mangle_hash(const char *key, unsigned int length) { - uint32 value; - uint32 i; + u32 value; + u32 i; fstring str; /* we have to uppercase here to ensure that the mangled name @@ -139,8 +139,8 @@ static uint32 mangle_hash(const char *key, unsigned int length) /* Set the initial value from the key size. */ for (value = FNV1_INIT, i=0; i < length; i++) { - value *= (uint32)FNV1_PRIME; - value ^= (uint32)(str[i]); + value *= (u32)FNV1_PRIME; + value ^= (u32)(str[i]); } /* note that we force it to a 31 bit hash, to keep within the limits @@ -162,7 +162,7 @@ static BOOL cache_init(void) return False; } - prefix_cache_hashes = SMB_CALLOC_ARRAY(uint32, MANGLE_CACHE_SIZE); + prefix_cache_hashes = SMB_CALLOC_ARRAY(u32, MANGLE_CACHE_SIZE); if (!prefix_cache_hashes) { return False; } @@ -173,7 +173,7 @@ static BOOL cache_init(void) /* insert an entry into the prefix cache. The string might not be null terminated */ -static void cache_insert(const char *prefix, int length, uint32 hash) +static void cache_insert(const char *prefix, int length, u32 hash) { int i = hash % MANGLE_CACHE_SIZE; @@ -188,7 +188,7 @@ static void cache_insert(const char *prefix, int length, uint32 hash) /* lookup an entry in the prefix cache. Return NULL if not found. */ -static const char *cache_lookup(uint32 hash) +static const char *cache_lookup(u32 hash) { int i = hash % MANGLE_CACHE_SIZE; @@ -372,7 +372,7 @@ static void mangle_reset(void) */ static BOOL check_cache(char *name, size_t maxlen, int snum) { - uint32 hash, multiplier; + u32 hash, multiplier; unsigned int i; const char *prefix; char extension[4]; @@ -386,7 +386,7 @@ static BOOL check_cache(char *name, size_t maxlen, int snum) /* 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--) { - uint32 v = base_reverse[(unsigned char)name[i]]; + u32 v = base_reverse[(unsigned char)name[i]]; hash += multiplier * v; multiplier *= 36; } @@ -517,7 +517,7 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, char extension[4]; unsigned int extension_length, i; unsigned int prefix_len; - uint32 hash, v; + u32 hash, v; char new_name[13]; /* reserved names are handled specially */ -- cgit From fbdcf2663b56007a438ac4f0d8d82436b1bfe688 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Jul 2006 18:01:26 +0000 Subject: r16945: Sync trunk -> 3.0 for 3.0.24 code. Still need to do the upper layer directories but this is what everyone is waiting for.... Jeremy. (This used to be commit 9dafb7f48ca3e7af956b0a7d1720c2546fc4cfb8) --- source3/smbd/mangle_hash2.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 0a161c9e76..d1ce1af9ea 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -101,7 +101,7 @@ static unsigned mangle_prefix; hashing the resulting cache entry to match the known hash */ static char **prefix_cache; -static u32 *prefix_cache_hashes; +static unsigned int *prefix_cache_hashes; /* these are the characters we use in the 8.3 hash. Must be 36 chars long */ static const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -119,10 +119,10 @@ static const char *reserved_names[] = this hash needs to be fast with a low collision rate (what hash doesn't?) */ -static u32 mangle_hash(const char *key, unsigned int length) +static unsigned int mangle_hash(const char *key, unsigned int length) { - u32 value; - u32 i; + unsigned int value; + unsigned int i; fstring str; /* we have to uppercase here to ensure that the mangled name @@ -139,8 +139,8 @@ static u32 mangle_hash(const char *key, unsigned int length) /* Set the initial value from the key size. */ for (value = FNV1_INIT, i=0; i < length; i++) { - value *= (u32)FNV1_PRIME; - value ^= (u32)(str[i]); + value *= (unsigned int)FNV1_PRIME; + value ^= (unsigned int)(str[i]); } /* note that we force it to a 31 bit hash, to keep within the limits @@ -162,7 +162,7 @@ static BOOL cache_init(void) return False; } - prefix_cache_hashes = SMB_CALLOC_ARRAY(u32, MANGLE_CACHE_SIZE); + prefix_cache_hashes = SMB_CALLOC_ARRAY(unsigned int, MANGLE_CACHE_SIZE); if (!prefix_cache_hashes) { return False; } @@ -173,7 +173,7 @@ static BOOL cache_init(void) /* insert an entry into the prefix cache. The string might not be null terminated */ -static void cache_insert(const char *prefix, int length, u32 hash) +static void cache_insert(const char *prefix, int length, unsigned int hash) { int i = hash % MANGLE_CACHE_SIZE; @@ -188,7 +188,7 @@ static void cache_insert(const char *prefix, int length, u32 hash) /* lookup an entry in the prefix cache. Return NULL if not found. */ -static const char *cache_lookup(u32 hash) +static const char *cache_lookup(unsigned int hash) { int i = hash % MANGLE_CACHE_SIZE; @@ -268,7 +268,7 @@ static BOOL is_mangled_component(const char *name, size_t len) directory separators. It should return true if any component is mangled */ -static BOOL is_mangled(const char *name, int snum) +static BOOL is_mangled(const char *name, const struct share_params *parm) { const char *p; const char *s; @@ -293,7 +293,7 @@ static BOOL is_mangled(const char *name, int snum) simplifies things greatly (it means that we know the string won't get larger when converted from UNIX to DOS formats) */ -static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards, int snum) +static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards, const struct share_params *p) { int len, i; char *dot_p; @@ -370,15 +370,15 @@ static void mangle_reset(void) try to find a 8.3 name in the cache, and if found then replace the string with the original long name. */ -static BOOL check_cache(char *name, size_t maxlen, int snum) +static BOOL check_cache(char *name, size_t maxlen, const struct share_params *p) { - u32 hash, multiplier; + unsigned int hash, multiplier; unsigned int i; const char *prefix; char extension[4]; /* make sure that this is a mangled name from this cache */ - if (!is_mangled(name, snum)) { + if (!is_mangled(name, p)) { M_DEBUG(10,("check_cache: %s -> not mangled\n", name)); return False; } @@ -386,7 +386,7 @@ static BOOL check_cache(char *name, size_t maxlen, int snum) /* 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]]; + unsigned int v = base_reverse[(unsigned char)name[i]]; hash += multiplier * v; multiplier *= 36; } @@ -510,21 +510,21 @@ static BOOL is_legal_name(const char *name) 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) +static void name_map(fstring name, BOOL need83, 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; - u32 hash, v; + unsigned int 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)) { + if (is_8_3(name, False, False, p)) { return; } @@ -724,22 +724,22 @@ struct mangle_fns *mangle_hash2_init(void) static void posix_mangle_reset(void) {;} -static BOOL posix_is_mangled(const char *s, int snum) +static BOOL posix_is_mangled(const char *s, const struct share_params *p) { return False; } -static BOOL posix_is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, int snum) +static BOOL posix_is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, const struct share_params *p) { return False; } -static BOOL posix_check_cache( char *s, size_t maxlen, int snum ) +static BOOL posix_check_cache( char *s, size_t maxlen, const struct share_params *p ) { return False; } -static void posix_name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, int snum) +static void posix_name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, const struct share_params *p) { if (need83) { memset(OutName, '\0', 13); -- cgit From 3a60a6743262ab2ab221e0fe13ef6b510424ca3f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 21 Sep 2006 18:37:09 +0000 Subject: r18793: Fix BE string handling in the auto-generated code. Should now work again with ASU. Jeremy. (This used to be commit 53e97bf92817b6cfc3f93c999a81ef8ad49a1609) --- source3/smbd/mangle_hash2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index d1ce1af9ea..a39f49ec79 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -465,7 +465,7 @@ static BOOL is_legal_name(const char *name) * for mb UNIX asian characters like Japanese (SJIS) here. * JRA. */ - if (convert_string(CH_UNIX, CH_UCS2, name, 2, mbc, 2, False) == 2) { + if (convert_string(CH_UNIX, CH_UTF16LE, name, 2, mbc, 2, False) == 2) { /* Was a good mb string. */ name += 2; continue; -- cgit From d824b98f80ba186030cbb70b3a1e5daf80469ecd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 9 Jul 2007 19:25:36 +0000 Subject: r23779: Change from v2 or later to v3 or later. Jeremy. (This used to be commit 407e6e695b8366369b7c76af1ff76869b45347b3) --- source3/smbd/mangle_hash2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index a39f49ec79..70b0d86f10 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -6,7 +6,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, -- cgit From 5e54558c6dea67b56bbfaba5698f3a434d3dffb6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 00:52:41 +0000 Subject: r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text (This used to be commit b0132e94fc5fef936aa766fb99a306b3628e9f07) --- source3/smbd/mangle_hash2.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 70b0d86f10..299d7c99fa 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -15,8 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with this program. If not, see . */ /* -- cgit From 281931ea77d6a38606261d5056e7dba21ed6d357 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 21 Aug 2007 18:45:45 +0000 Subject: r24603: In case of error we need to free prefix_cache otherwise on re-init the first statement will return positively but prefix_cache_hashes would be NULL (This used to be commit fdc20894a0deb3c68b834e5d9d466873ca634bed) --- source3/smbd/mangle_hash2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 299d7c99fa..c3db112051 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -163,6 +163,7 @@ static BOOL cache_init(void) prefix_cache_hashes = SMB_CALLOC_ARRAY(unsigned int, MANGLE_CACHE_SIZE); if (!prefix_cache_hashes) { + SAFE_FREE(prefix_cache); return False; } -- cgit From 132ee3990af5d31573978f5a3abf43db2303880b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 Sep 2007 20:57:01 +0000 Subject: r25009: Large patch discussed with Volker. Move unix_convert to a talloc-based interface. More development will come on top of this. Remove the "mangled map" parameter. Jeremy. (This used to be commit dee8beba7a92b8a3f68bbcc59fd0a827f68c7736) --- source3/smbd/mangle_hash2.c | 135 +++++++++++++++++++++++++++----------------- 1 file changed, 82 insertions(+), 53 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index c3db112051..73f81fe9ae 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -368,18 +368,23 @@ static void mangle_reset(void) /* try to find a 8.3 name in the cache, and if found then - replace the string with the original long name. + replace the string with the original long name. */ -static BOOL check_cache(char *name, size_t maxlen, const struct share_params *p) +static BOOL lookup_name_from_8_3(TALLOC_CTX *ctx, + const char *name, + char **pp_out, /* talloced on the given context. */ + const struct share_params *p) { unsigned int hash, multiplier; unsigned int i; const char *prefix; char extension[4]; + *pp_out = NULL; + /* make sure that this is a mangled name from this cache */ if (!is_mangled(name, p)) { - M_DEBUG(10,("check_cache: %s -> not mangled\n", name)); + M_DEBUG(10,("lookup_name_from_8_3: %s -> not mangled\n", name)); return False; } @@ -394,7 +399,8 @@ static BOOL check_cache(char *name, size_t maxlen, const struct share_params *p) /* 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)); + M_DEBUG(10,("lookup_name_from_8_3: %s -> %08X -> not found\n", + name, hash)); return False; } @@ -407,17 +413,22 @@ static BOOL check_cache(char *name, size_t maxlen, const struct share_params *p) } if (extension[0]) { - M_DEBUG(10,("check_cache: %s -> %s.%s\n", name, prefix, extension)); - slprintf(name, maxlen, "%s.%s", prefix, extension); + M_DEBUG(10,("lookup_name_from_8_3: %s -> %s.%s\n", + name, prefix, extension)); + *pp_out = talloc_asprintf(ctx, "%s.%s", prefix, extension); } else { - M_DEBUG(10,("check_cache: %s -> %s\n", name, prefix)); - safe_strcpy(name, prefix, maxlen); + M_DEBUG(10,("lookup_name_from_8_3: %s -> %s\n", name, prefix)); + *pp_out = talloc_strdup(ctx, prefix); + } + + if (!pp_out) { + M_DEBUG(0,("talloc_fail")); + return False; } return True; } - /* look for a DOS reserved name */ @@ -499,18 +510,27 @@ static BOOL is_legal_name(const char *name) return True; } +static BOOL must_mangle(const char *name, + const struct share_params *p) +{ + if (is_reserved_name(name)) { + return True; + } + return !is_legal_name(name); +} + /* 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, const struct share_params *p) +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]; @@ -518,20 +538,14 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, unsigned int extension_length, i; unsigned int prefix_len; unsigned int 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, p)) { - return; - } - - /* if the caller doesn't strictly need 8.3 then just check for illegal - filenames */ - if (!need83 && is_legal_name(name)) { - return; + /* 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; } } @@ -548,7 +562,9 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, break; } } - if (i == 0 || i == 4) dot_p = NULL; + if (i == 0 || i == 4) { + dot_p = NULL; + } } /* the leading characters in the mangled name is taken from @@ -580,11 +596,12 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, 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); + extension[extension_length++] = + toupper_ascii(c); } } } - + /* find the hash for this prefix */ v = hash = mangle_hash(name, prefix_len); @@ -593,7 +610,7 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, new_name[i] = lead_chars[i]; } new_name[7] = base_forward(v % 36); - new_name[6] = '~'; + new_name[6] = '~'; for (i=5; i>=mangle_prefix; i--) { v = v / 36; new_name[i] = base_forward(v % 36); @@ -613,22 +630,18 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, cache_insert(name, prefix_len, hash); } - M_DEBUG(10,("name_map: %s -> %08X -> %s (cache=%d)\n", + M_DEBUG(10,("hash2_name_to_8_3: %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 */ + return True; } - -/* initialise the flags table +/* 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. + restrictions. */ static void init_tables(void) { @@ -642,8 +655,8 @@ static void init_tables(void) char_flags[i] |= FLAG_ILLEGAL; } - if ((i >= '0' && i <= '9') || - (i >= 'a' && i <= 'z') || + if ((i >= '0' && i <= '9') || + (i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z')) { char_flags[i] |= (FLAG_ASCII | FLAG_BASECHAR); } @@ -663,7 +676,7 @@ static void init_tables(void) 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 */ @@ -694,9 +707,10 @@ static void init_tables(void) static struct mangle_fns mangle_fns = { mangle_reset, is_mangled, + must_mangle, is_8_3, - check_cache, - name_map + lookup_name_from_8_3, + hash2_name_to_8_3 }; /* return the methods for this mangling implementation */ @@ -729,30 +743,45 @@ static BOOL posix_is_mangled(const char *s, const struct share_params *p) return False; } -static BOOL posix_is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, const struct share_params *p) +static BOOL posix_must_mangle(const char *s, const struct share_params *p) { return False; } -static BOOL posix_check_cache( char *s, size_t maxlen, const struct share_params *p ) +static BOOL posix_is_8_3(const char *fname, + BOOL check_case, + BOOL allow_wildcards, + const struct share_params *p) { return False; } -static void posix_name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, const struct share_params *p) +static BOOL posix_lookup_name_from_8_3(TALLOC_CTX *ctx, + const char *in, + char **out, /* talloced on the given context. */ + const struct share_params *p) { - if (need83) { - memset(OutName, '\0', 13); - } + return False; +} + +static BOOL posix_name_to_8_3(const char *in, + char out[13], + BOOL cache83, + int default_case, + const struct share_params *p) +{ + memset(out, '\0', 13); + return True; } /* 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 + posix_mangle_reset, + posix_is_mangled, + posix_must_mangle, + posix_is_8_3, + posix_lookup_name_from_8_3, + posix_name_to_8_3 }; struct mangle_fns *posix_mangle_init(void) -- cgit From 30191d1a5704ad2b158386b511558972d539ce47 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Oct 2007 17:40:25 -0700 Subject: RIP BOOL. Convert BOOL -> bool. I found a few interesting bugs in various places whilst doing this (places that assumed BOOL == int). I also need to fix the Samba4 pidl generation (next checkin). Jeremy. (This used to be commit f35a266b3cbb3e5fa6a86be60f34fe340a3ca71f) --- source3/smbd/mangle_hash2.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 73f81fe9ae..7066c2a4e5 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -150,7 +150,7 @@ static unsigned int mangle_hash(const char *key, unsigned int length) /* initialise (ie. allocate) the prefix cache */ -static BOOL cache_init(void) +static bool cache_init(void) { if (prefix_cache) { return True; @@ -208,7 +208,7 @@ static const char *cache_lookup(unsigned int hash) In this algorithm, mangled names use only pure ascii characters (no multi-byte) so we can avoid doing a UCS2 conversion */ -static BOOL is_mangled_component(const char *name, size_t len) +static bool is_mangled_component(const char *name, size_t len) { unsigned int i; @@ -268,7 +268,7 @@ static BOOL is_mangled_component(const char *name, size_t len) directory separators. It should return true if any component is mangled */ -static BOOL is_mangled(const char *name, const struct share_params *parm) +static bool is_mangled(const char *name, const struct share_params *parm) { const char *p; const char *s; @@ -293,7 +293,7 @@ static BOOL is_mangled(const char *name, const struct share_params *parm) simplifies things greatly (it means that we know the string won't get larger when converted from UNIX to DOS formats) */ -static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards, const struct share_params *p) +static bool is_8_3(const char *name, bool check_case, bool allow_wildcards, const struct share_params *p) { int len, i; char *dot_p; @@ -370,7 +370,7 @@ static void mangle_reset(void) try to find a 8.3 name in the cache, and if found then replace the string with the original long name. */ -static BOOL lookup_name_from_8_3(TALLOC_CTX *ctx, +static bool lookup_name_from_8_3(TALLOC_CTX *ctx, const char *name, char **pp_out, /* talloced on the given context. */ const struct share_params *p) @@ -432,7 +432,7 @@ static BOOL lookup_name_from_8_3(TALLOC_CTX *ctx, /* look for a DOS reserved name */ -static BOOL is_reserved_name(const char *name) +static bool is_reserved_name(const char *name) { if (FLAG_CHECK(name[0], FLAG_POSSIBLE1) && FLAG_CHECK(name[1], FLAG_POSSIBLE2) && @@ -459,10 +459,10 @@ static BOOL is_reserved_name(const char *name) A filename ending in ' ' is not legal either. See bug id #2769. */ -static BOOL is_legal_name(const char *name) +static bool is_legal_name(const char *name) { const char *dot_pos = NULL; - BOOL alldots = True; + bool alldots = True; size_t numdots = 0; while (*name) { @@ -510,7 +510,7 @@ static BOOL is_legal_name(const char *name) return True; } -static BOOL must_mangle(const char *name, +static bool must_mangle(const char *name, const struct share_params *p) { if (is_reserved_name(name)) { @@ -526,9 +526,9 @@ static BOOL must_mangle(const char *name, if cache83 is not set then we don't cache the result */ -static BOOL hash2_name_to_8_3(const char *name, +static bool hash2_name_to_8_3(const char *name, char new_name[13], - BOOL cache83, + bool cache83, int default_case, const struct share_params *p) { @@ -738,25 +738,25 @@ struct mangle_fns *mangle_hash2_init(void) static void posix_mangle_reset(void) {;} -static BOOL posix_is_mangled(const char *s, const struct share_params *p) +static bool posix_is_mangled(const char *s, const struct share_params *p) { return False; } -static BOOL posix_must_mangle(const char *s, const struct share_params *p) +static bool posix_must_mangle(const char *s, const struct share_params *p) { return False; } -static BOOL posix_is_8_3(const char *fname, - BOOL check_case, - BOOL allow_wildcards, +static bool posix_is_8_3(const char *fname, + bool check_case, + bool allow_wildcards, const struct share_params *p) { return False; } -static BOOL posix_lookup_name_from_8_3(TALLOC_CTX *ctx, +static bool posix_lookup_name_from_8_3(TALLOC_CTX *ctx, const char *in, char **out, /* talloced on the given context. */ const struct share_params *p) @@ -764,9 +764,9 @@ static BOOL posix_lookup_name_from_8_3(TALLOC_CTX *ctx, return False; } -static BOOL posix_name_to_8_3(const char *in, +static bool posix_name_to_8_3(const char *in, char out[13], - BOOL cache83, + bool cache83, int default_case, const struct share_params *p) { -- cgit From f427d4ce65659419c8989d87acd97d00b4db41e6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 18 Dec 2007 09:41:03 +0100 Subject: Add a in-memory cache This is a more general API that caches data with a LRU scheme. See include/cache.h. No comments yet, I'm still working on it. But Jeremy has given me a hint in one of his checkins that he would like to make use of this now. The idea is that we get rid of all our silly little caches and merge them all into one cache that we can then very easily trim, for example even with a smbcontrol message if someone decides memory is tight. The main user is the stat cache, this patch also converts the getwd cache. More caches to come. (This used to be commit 7a911b35713538d82001a3c9f34152e293fe1943) --- source3/smbd/mangle_hash2.c | 67 +++++++++++++-------------------------------- 1 file changed, 19 insertions(+), 48 deletions(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 7066c2a4e5..9643506aea 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -93,15 +93,6 @@ static unsigned char char_flags[256]; */ static unsigned mangle_prefix; -/* we will use a very simple direct mapped prefix cache. The big - advantage of this cache structure is speed and low memory usage - - The cache is indexed by the low-order bits of the hash, and confirmed by - hashing the resulting cache entry to match the known hash -*/ -static char **prefix_cache; -static unsigned int *prefix_cache_hashes; - /* these are the characters we use in the 8.3 hash. Must be 36 chars long */ static const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; static unsigned char base_reverse[256]; @@ -147,57 +138,39 @@ static unsigned int mangle_hash(const char *key, unsigned int length) return value & ~0x80000000; } -/* - initialise (ie. allocate) the prefix cache - */ -static bool cache_init(void) -{ - if (prefix_cache) { - return True; - } - - prefix_cache = SMB_CALLOC_ARRAY(char *,MANGLE_CACHE_SIZE); - if (!prefix_cache) { - return False; - } - - prefix_cache_hashes = SMB_CALLOC_ARRAY(unsigned int, MANGLE_CACHE_SIZE); - if (!prefix_cache_hashes) { - SAFE_FREE(prefix_cache); - return False; - } - - return True; -} - /* insert an entry into the prefix cache. The string might not be null terminated */ static void cache_insert(const char *prefix, int length, unsigned int hash) { - int i = hash % MANGLE_CACHE_SIZE; + char *str = SMB_STRNDUP(prefix, length); - if (prefix_cache[i]) { - free(prefix_cache[i]); + if (str == NULL) { + return; } - prefix_cache[i] = SMB_STRNDUP(prefix, length); - prefix_cache_hashes[i] = hash; + memcache_add(smbd_memcache(), MANGLE_HASH2_CACHE, + data_blob_const(&hash, sizeof(hash)), + data_blob_const(str, length+1)); + SAFE_FREE(str); } /* lookup an entry in the prefix cache. Return NULL if not found. */ -static const char *cache_lookup(unsigned int hash) +static char *cache_lookup(TALLOC_CTX *mem_ctx, unsigned int hash) { - int i = hash % MANGLE_CACHE_SIZE; + DATA_BLOB value; - if (!prefix_cache[i] || hash != prefix_cache_hashes[i]) { + if (!memcache_lookup(smbd_memcache(), MANGLE_HASH2_CACHE, + data_blob_const(&hash, sizeof(hash)), &value)) { return NULL; } - /* yep, it matched */ - return prefix_cache[i]; + SMB_ASSERT((value.length > 0) + && (value.data[value.length-1] == '\0')); + + return talloc_strdup(mem_ctx, (char *)value.data); } @@ -377,7 +350,7 @@ static bool lookup_name_from_8_3(TALLOC_CTX *ctx, { unsigned int hash, multiplier; unsigned int i; - const char *prefix; + char *prefix; char extension[4]; *pp_out = NULL; @@ -397,7 +370,7 @@ static bool lookup_name_from_8_3(TALLOC_CTX *ctx, } /* now look in the prefix cache for that hash */ - prefix = cache_lookup(hash); + prefix = cache_lookup(ctx, hash); if (!prefix) { M_DEBUG(10,("lookup_name_from_8_3: %s -> %08X -> not found\n", name, hash)); @@ -421,6 +394,8 @@ static bool lookup_name_from_8_3(TALLOC_CTX *ctx, *pp_out = talloc_strdup(ctx, prefix); } + TALLOC_FREE(prefix); + if (!pp_out) { M_DEBUG(0,("talloc_fail")); return False; @@ -728,10 +703,6 @@ struct mangle_fns *mangle_hash2_init(void) init_tables(); mangle_reset(); - if (!cache_init()) { - return NULL; - } - return &mangle_fns; } -- cgit From 915647da9cb1227378f53a5a386df69e9348754b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Jan 2008 22:50:13 -0800 Subject: Fix CID 523 - wrong null deref check. Jeremy. (This used to be commit 05cadffeab38ca9df7ffd46785b536266c4438c4) --- source3/smbd/mangle_hash2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/mangle_hash2.c') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 9643506aea..a9b94aabc3 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -396,7 +396,7 @@ static bool lookup_name_from_8_3(TALLOC_CTX *ctx, TALLOC_FREE(prefix); - if (!pp_out) { + if (!*pp_out) { M_DEBUG(0,("talloc_fail")); return False; } -- cgit