smbd/mangle_hash2.c

ソースコードを見る。

関数

static unsigned int mangle_hash (const char *key, unsigned int length)
static BOOL cache_init (void)
static void cache_insert (const char *prefix, int length, unsigned int hash)
static const char * cache_lookup (unsigned int hash)
static BOOL is_mangled_component (const char *name, size_t len)
static BOOL is_mangled (const char *name, const struct share_params *parm)
static BOOL is_8_3 (const char *name, BOOL check_case, BOOL allow_wildcards, const struct share_params *p)
static void mangle_reset (void)
static BOOL check_cache (char *name, size_t maxlen, const struct share_params *p)
static BOOL is_reserved_name (const char *name)
static BOOL is_legal_name (const char *name)
static void name_map (fstring name, BOOL need83, BOOL cache83, int default_case, const struct share_params *p)
static void init_tables (void)
mangle_fnsmangle_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_8_3 (const char *fname, BOOL check_case, BOOL allow_wildcards, const struct share_params *p)
static BOOL posix_check_cache (char *s, size_t maxlen, const struct share_params *p)
static void posix_name_map (char *OutName, BOOL need83, BOOL cache83, int default_case, const struct share_params *p)
mangle_fnsposix_mangle_init (void)

変数

static unsigned char char_flags [256]
static unsigned mangle_prefix
static char ** prefix_cache
static unsigned int * prefix_cache_hashes
static const char * basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
static unsigned char base_reverse [256]
static const char * reserved_names []
static struct mangle_fns mangle_fns
static struct mangle_fns posix_mangle_fns


関数

static unsigned int mangle_hash ( const char *  key,
unsigned int  length 
) [static]

mangle_hash2.c122 行で定義されています。

参照先 strupper_m().

参照元 name_map().

00123 {
00124         unsigned int value;
00125         unsigned int   i;
00126         fstring str;
00127 
00128         /* we have to uppercase here to ensure that the mangled name
00129            doesn't depend on the case of the long name. Note that this
00130            is the only place where we need to use a multi-byte string
00131            function */
00132         length = MIN(length,sizeof(fstring)-1);
00133         strncpy(str, key, length);
00134         str[length] = 0;
00135         strupper_m(str);
00136 
00137         /* the length of a multi-byte string can change after a strupper_m */
00138         length = strlen(str);
00139 
00140         /* Set the initial value from the key size. */
00141         for (value = FNV1_INIT, i=0; i < length; i++) {
00142                 value *= (unsigned int)FNV1_PRIME;
00143                 value ^= (unsigned int)(str[i]);
00144         }
00145 
00146         /* note that we force it to a 31 bit hash, to keep within the limits
00147            of the 36^6 mangle space */
00148         return value & ~0x80000000;  
00149 }

static BOOL cache_init ( void   )  [static]

mangle_hash2.c154 行で定義されています。

参照先 prefix_cacheprefix_cache_hashes.

参照元 mangle_hash2_init().

00155 {
00156         if (prefix_cache) {
00157                 return True;
00158         }
00159 
00160         prefix_cache = SMB_CALLOC_ARRAY(char *,MANGLE_CACHE_SIZE);
00161         if (!prefix_cache) {
00162                 return False;
00163         }
00164 
00165         prefix_cache_hashes = SMB_CALLOC_ARRAY(unsigned int, MANGLE_CACHE_SIZE);
00166         if (!prefix_cache_hashes) {
00167                 return False;
00168         }
00169 
00170         return True;
00171 }

static void cache_insert ( const char *  prefix,
int  length,
unsigned int  hash 
) [static]

mangle_hash2.c176 行で定義されています。

参照先 prefix_cacheprefix_cache_hashes.

参照元 name_map().

00177 {
00178         int i = hash % MANGLE_CACHE_SIZE;
00179 
00180         if (prefix_cache[i]) {
00181                 free(prefix_cache[i]);
00182         }
00183 
00184         prefix_cache[i] = SMB_STRNDUP(prefix, length);
00185         prefix_cache_hashes[i] = hash;
00186 }

static const char* cache_lookup ( unsigned int  hash  )  [static]

mangle_hash2.c191 行で定義されています。

参照先 prefix_cacheprefix_cache_hashes.

参照元 check_cache().

00192 {
00193         int i = hash % MANGLE_CACHE_SIZE;
00194 
00195         if (!prefix_cache[i] || hash != prefix_cache_hashes[i]) {
00196                 return NULL;
00197         }
00198 
00199         /* yep, it matched */
00200         return prefix_cache[i];
00201 }

static BOOL is_mangled_component ( const char *  name,
size_t  len 
) [static]

mangle_hash2.c211 行で定義されています。

参照先 mangle_prefix.

参照元 is_mangled().

00212 {
00213         unsigned int i;
00214 
00215         M_DEBUG(10,("is_mangled_component %s (len %lu) ?\n", name, (unsigned long)len));
00216 
00217         /* check the length */
00218         if (len > 12 || len < 8)
00219                 return False;
00220 
00221         /* the best distinguishing characteristic is the ~ */
00222         if (name[6] != '~')
00223                 return False;
00224 
00225         /* check extension */
00226         if (len > 8) {
00227                 if (name[8] != '.')
00228                         return False;
00229                 for (i=9; name[i] && i < len; i++) {
00230                         if (! FLAG_CHECK(name[i], FLAG_ASCII)) {
00231                                 return False;
00232                         }
00233                 }
00234         }
00235         
00236         /* check lead characters */
00237         for (i=0;i<mangle_prefix;i++) {
00238                 if (! FLAG_CHECK(name[i], FLAG_ASCII)) {
00239                         return False;
00240                 }
00241         }
00242         
00243         /* check rest of hash */
00244         if (! FLAG_CHECK(name[7], FLAG_BASECHAR)) {
00245                 return False;
00246         }
00247         for (i=mangle_prefix;i<6;i++) {
00248                 if (! FLAG_CHECK(name[i], FLAG_BASECHAR)) {
00249                         return False;
00250                 }
00251         }
00252 
00253         M_DEBUG(10,("is_mangled_component %s (len %lu) -> yes\n", name, (unsigned long)len));
00254 
00255         return True;
00256 }

static BOOL is_mangled ( const char *  name,
const struct share_params parm 
) [static]

mangle_hash2.c271 行で定義されています。

参照先 is_mangled_component().

00272 {
00273         const char *p;
00274         const char *s;
00275 
00276         M_DEBUG(10,("is_mangled %s ?\n", name));
00277 
00278         for (s=name; (p=strchr(s, '/')); s=p+1) {
00279                 if (is_mangled_component(s, PTR_DIFF(p, s))) {
00280                         return True;
00281                 }
00282         }
00283         
00284         /* and the last part ... */
00285         return is_mangled_component(s,strlen(s));
00286 }

static BOOL is_8_3 ( const char *  name,
BOOL  check_case,
BOOL  allow_wildcards,
const struct share_params p 
) [static]

mangle_hash2.c296 行で定義されています。

参照先 len.

00297 {
00298         int len, i;
00299         char *dot_p;
00300 
00301         /* as a special case, the names '.' and '..' are allowable 8.3 names */
00302         if (name[0] == '.') {
00303                 if (!name[1] || (name[1] == '.' && !name[2])) {
00304                         return True;
00305                 }
00306         }
00307 
00308         /* the simplest test is on the overall length of the
00309          filename. Note that we deliberately use the ascii string
00310          length (not the multi-byte one) as it is faster, and gives us
00311          the result we need in this case. Using strlen_m would not
00312          only be slower, it would be incorrect */
00313         len = strlen(name);
00314         if (len > 12)
00315                 return False;
00316 
00317         /* find the '.'. Note that once again we use the non-multibyte
00318            function */
00319         dot_p = strchr(name, '.');
00320 
00321         if (!dot_p) {
00322                 /* if the name doesn't contain a '.' then its length
00323                    must be less than 8 */
00324                 if (len > 8) {
00325                         return False;
00326                 }
00327         } else {
00328                 int prefix_len, suffix_len;
00329 
00330                 /* if it does contain a dot then the prefix must be <=
00331                    8 and the suffix <= 3 in length */
00332                 prefix_len = PTR_DIFF(dot_p, name);
00333                 suffix_len = len - (prefix_len+1);
00334 
00335                 if (prefix_len > 8 || suffix_len > 3 || suffix_len == 0) {
00336                         return False;
00337                 }
00338 
00339                 /* a 8.3 name cannot contain more than 1 '.' */
00340                 if (strchr(dot_p+1, '.')) {
00341                         return False;
00342                 }
00343         }
00344 
00345         /* the length are all OK. Now check to see if the characters themselves are OK */
00346         for (i=0; name[i]; i++) {
00347                 /* note that we may allow wildcard petterns! */
00348                 if (!FLAG_CHECK(name[i], FLAG_ASCII|(allow_wildcards ? FLAG_WILDCARD : 0)) && name[i] != '.') {
00349                         return False;
00350                 }
00351         }
00352 
00353         /* it is a good 8.3 name */
00354         return True;
00355 }

static void mangle_reset ( void   )  [static]

mangle_hash2.c363 行で定義されています。

00364 {
00365         /* noop */
00366 }

static BOOL check_cache ( char *  name,
size_t  maxlen,
const struct share_params p 
) [static]

mangle_hash2.c373 行で定義されています。

参照先 base_reversecache_lookup()is_mangled()mangle_prefix.

00374 {
00375         unsigned int hash, multiplier;
00376         unsigned int i;
00377         const char *prefix;
00378         char extension[4];
00379 
00380         /* make sure that this is a mangled name from this cache */
00381         if (!is_mangled(name, p)) {
00382                 M_DEBUG(10,("check_cache: %s -> not mangled\n", name));
00383                 return False;
00384         }
00385 
00386         /* we need to extract the hash from the 8.3 name */
00387         hash = base_reverse[(unsigned char)name[7]];
00388         for (multiplier=36, i=5;i>=mangle_prefix;i--) {
00389                 unsigned int v = base_reverse[(unsigned char)name[i]];
00390                 hash += multiplier * v;
00391                 multiplier *= 36;
00392         }
00393 
00394         /* now look in the prefix cache for that hash */
00395         prefix = cache_lookup(hash);
00396         if (!prefix) {
00397                 M_DEBUG(10,("check_cache: %s -> %08X -> not found\n", name, hash));
00398                 return False;
00399         }
00400 
00401         /* we found it - construct the full name */
00402         if (name[8] == '.') {
00403                 strncpy(extension, name+9, 3);
00404                 extension[3] = 0;
00405         } else {
00406                 extension[0] = 0;
00407         }
00408 
00409         if (extension[0]) {
00410                 M_DEBUG(10,("check_cache: %s -> %s.%s\n", name, prefix, extension));
00411                 slprintf(name, maxlen, "%s.%s", prefix, extension);
00412         } else {
00413                 M_DEBUG(10,("check_cache: %s -> %s\n", name, prefix));
00414                 safe_strcpy(name, prefix, maxlen);
00415         }
00416 
00417         return True;
00418 }

static BOOL is_reserved_name ( const char *  name  )  [static]

mangle_hash2.c424 行で定義されています。

参照先 lenreserved_namesstrnequal().

参照元 name_map().

00425 {
00426         if (FLAG_CHECK(name[0], FLAG_POSSIBLE1) &&
00427             FLAG_CHECK(name[1], FLAG_POSSIBLE2) &&
00428             FLAG_CHECK(name[2], FLAG_POSSIBLE3) &&
00429             FLAG_CHECK(name[3], FLAG_POSSIBLE4)) {
00430                 /* a likely match, scan the lot */
00431                 int i;
00432                 for (i=0; reserved_names[i]; i++) {
00433                         int len = strlen(reserved_names[i]);
00434                         /* note that we match on COM1 as well as COM1.foo */
00435                         if (strnequal(name, reserved_names[i], len) &&
00436                             (name[len] == '.' || name[len] == 0)) {
00437                                 return True;
00438                         }
00439                 }
00440         }
00441 
00442         return False;
00443 }

static BOOL is_legal_name ( const char *  name  )  [static]

mangle_hash2.c451 行で定義されています。

参照先 CH_UNIXCH_UTF16LEconvert_string().

参照元 name_map().

00452 {
00453         const char *dot_pos = NULL;
00454         BOOL alldots = True;
00455         size_t numdots = 0;
00456 
00457         while (*name) {
00458                 if (((unsigned int)name[0]) > 128 && (name[1] != 0)) {
00459                         /* Possible start of mb character. */
00460                         char mbc[2];
00461                         /*
00462                          * Note that if CH_UNIX is utf8 a string may be 3
00463                          * bytes, but this is ok as mb utf8 characters don't
00464                          * contain embedded ascii bytes. We are really checking
00465                          * for mb UNIX asian characters like Japanese (SJIS) here.
00466                          * JRA.
00467                          */
00468                         if (convert_string(CH_UNIX, CH_UTF16LE, name, 2, mbc, 2, False) == 2) {
00469                                 /* Was a good mb string. */
00470                                 name += 2;
00471                                 continue;
00472                         }
00473                 }
00474 
00475                 if (FLAG_CHECK(name[0], FLAG_ILLEGAL)) {
00476                         return False;
00477                 }
00478                 if (name[0] == '.') {
00479                         dot_pos = name;
00480                         numdots++;
00481                 } else {
00482                         alldots = False;
00483                 }
00484                 if ((name[0] == ' ') && (name[1] == '\0')) {
00485                         /* Can't end in ' ' */
00486                         return False;
00487                 }
00488                 name++;
00489         }
00490 
00491         if (dot_pos) {
00492                 if (alldots && (numdots == 1 || numdots == 2))
00493                         return True; /* . or .. is a valid name */
00494 
00495                 /* A valid long name cannot end in '.' */
00496                 if (dot_pos[1] == '\0')
00497                         return False;
00498         }
00499         return True;
00500 }

static void name_map ( fstring  name,
BOOL  need83,
BOOL  cache83,
int  default_case,
const struct share_params p 
) [static]

mangle_hash2.c513 行で定義されています。

参照先 ccache_insert()is_8_3()is_legal_name()is_reserved_name()mangle_hash()mangle_prefixtoupper_ascii().

00514 {
00515         char *dot_p;
00516         char lead_chars[7];
00517         char extension[4];
00518         unsigned int extension_length, i;
00519         unsigned int prefix_len;
00520         unsigned int hash, v;
00521         char new_name[13];
00522 
00523         /* reserved names are handled specially */
00524         if (!is_reserved_name(name)) {
00525                 /* if the name is already a valid 8.3 name then we don't need to 
00526                    do anything */
00527                 if (is_8_3(name, False, False, p)) {
00528                         return;
00529                 }
00530 
00531                 /* if the caller doesn't strictly need 8.3 then just check for illegal 
00532                    filenames */
00533                 if (!need83 && is_legal_name(name)) {
00534                         return;
00535                 }
00536         }
00537 
00538         /* find the '.' if any */
00539         dot_p = strrchr(name, '.');
00540 
00541         if (dot_p) {
00542                 /* if the extension contains any illegal characters or
00543                    is too long or zero length then we treat it as part
00544                    of the prefix */
00545                 for (i=0; i<4 && dot_p[i+1]; i++) {
00546                         if (! FLAG_CHECK(dot_p[i+1], FLAG_ASCII)) {
00547                                 dot_p = NULL;
00548                                 break;
00549                         }
00550                 }
00551                 if (i == 0 || i == 4) dot_p = NULL;
00552         }
00553 
00554         /* the leading characters in the mangled name is taken from
00555            the first characters of the name, if they are ascii otherwise
00556            '_' is used
00557         */
00558         for (i=0;i<mangle_prefix && name[i];i++) {
00559                 lead_chars[i] = name[i];
00560                 if (! FLAG_CHECK(lead_chars[i], FLAG_ASCII)) {
00561                         lead_chars[i] = '_';
00562                 }
00563                 lead_chars[i] = toupper_ascii(lead_chars[i]);
00564         }
00565         for (;i<mangle_prefix;i++) {
00566                 lead_chars[i] = '_';
00567         }
00568 
00569         /* the prefix is anything up to the first dot */
00570         if (dot_p) {
00571                 prefix_len = PTR_DIFF(dot_p, name);
00572         } else {
00573                 prefix_len = strlen(name);
00574         }
00575 
00576         /* the extension of the mangled name is taken from the first 3
00577            ascii chars after the dot */
00578         extension_length = 0;
00579         if (dot_p) {
00580                 for (i=1; extension_length < 3 && dot_p[i]; i++) {
00581                         char c = dot_p[i];
00582                         if (FLAG_CHECK(c, FLAG_ASCII)) {
00583                                 extension[extension_length++] = toupper_ascii(c);
00584                         }
00585                 }
00586         }
00587            
00588         /* find the hash for this prefix */
00589         v = hash = mangle_hash(name, prefix_len);
00590 
00591         /* now form the mangled name. */
00592         for (i=0;i<mangle_prefix;i++) {
00593                 new_name[i] = lead_chars[i];
00594         }
00595         new_name[7] = base_forward(v % 36);
00596         new_name[6] = '~';      
00597         for (i=5; i>=mangle_prefix; i--) {
00598                 v = v / 36;
00599                 new_name[i] = base_forward(v % 36);
00600         }
00601 
00602         /* add the extension */
00603         if (extension_length) {
00604                 new_name[8] = '.';
00605                 memcpy(&new_name[9], extension, extension_length);
00606                 new_name[9+extension_length] = 0;
00607         } else {
00608                 new_name[8] = 0;
00609         }
00610 
00611         if (cache83) {
00612                 /* put it in the cache */
00613                 cache_insert(name, prefix_len, hash);
00614         }
00615 
00616         M_DEBUG(10,("name_map: %s -> %08X -> %s (cache=%d)\n", 
00617                    name, hash, new_name, cache83));
00618 
00619         /* and overwrite the old name */
00620         fstrcpy(name, new_name);
00621 
00622         /* all done, we've managed to mangle it */
00623 }

static void init_tables ( void   )  [static]

mangle_hash2.c633 行で定義されています。

参照先 base_reversechar_flagsreserved_namestolower_ascii().

参照元 mangle_hash2_init().

00634 {
00635         int i;
00636 
00637         memset(char_flags, 0, sizeof(char_flags));
00638 
00639         for (i=1;i<128;i++) {
00640                 if (i <= 0x1f) {
00641                         /* Control characters. */
00642                         char_flags[i] |= FLAG_ILLEGAL;
00643                 }
00644 
00645                 if ((i >= '0' && i <= '9') || 
00646                     (i >= 'a' && i <= 'z') || 
00647                     (i >= 'A' && i <= 'Z')) {
00648                         char_flags[i] |=  (FLAG_ASCII | FLAG_BASECHAR);
00649                 }
00650                 if (strchr("_-$~", i)) {
00651                         char_flags[i] |= FLAG_ASCII;
00652                 }
00653 
00654                 if (strchr("*\\/?<>|\":", i)) {
00655                         char_flags[i] |= FLAG_ILLEGAL;
00656                 }
00657 
00658                 if (strchr("*?\"<>", i)) {
00659                         char_flags[i] |= FLAG_WILDCARD;
00660                 }
00661         }
00662 
00663         memset(base_reverse, 0, sizeof(base_reverse));
00664         for (i=0;i<36;i++) {
00665                 base_reverse[(unsigned char)base_forward(i)] = i;
00666         }       
00667 
00668         /* fill in the reserved names flags. These are used as a very
00669            fast filter for finding possible DOS reserved filenames */
00670         for (i=0; reserved_names[i]; i++) {
00671                 unsigned char c1, c2, c3, c4;
00672 
00673                 c1 = (unsigned char)reserved_names[i][0];
00674                 c2 = (unsigned char)reserved_names[i][1];
00675                 c3 = (unsigned char)reserved_names[i][2];
00676                 c4 = (unsigned char)reserved_names[i][3];
00677 
00678                 char_flags[c1] |= FLAG_POSSIBLE1;
00679                 char_flags[c2] |= FLAG_POSSIBLE2;
00680                 char_flags[c3] |= FLAG_POSSIBLE3;
00681                 char_flags[c4] |= FLAG_POSSIBLE4;
00682                 char_flags[tolower_ascii(c1)] |= FLAG_POSSIBLE1;
00683                 char_flags[tolower_ascii(c2)] |= FLAG_POSSIBLE2;
00684                 char_flags[tolower_ascii(c3)] |= FLAG_POSSIBLE3;
00685                 char_flags[tolower_ascii(c4)] |= FLAG_POSSIBLE4;
00686 
00687                 char_flags[(unsigned char)'.'] |= FLAG_POSSIBLE4;
00688         }
00689 }

struct mangle_fns* mangle_hash2_init ( void   ) 

mangle_hash2.c703 行で定義されています。

参照先 cache_init()init_tables()mangle_fnsmangle_prefixmangle_reset().

00704 {
00705         /* the mangle prefix can only be in the mange 1 to 6 */
00706         mangle_prefix = lp_mangle_prefix();
00707         if (mangle_prefix > 6) {
00708                 mangle_prefix = 6;
00709         }
00710         if (mangle_prefix < 1) {
00711                 mangle_prefix = 1;
00712         }
00713 
00714         init_tables();
00715         mangle_reset();
00716 
00717         if (!cache_init()) {
00718                 return NULL;
00719         }
00720 
00721         return &mangle_fns;
00722 }

static void posix_mangle_reset ( void   )  [static]

mangle_hash2.c724 行で定義されています。

00725 {;}

static BOOL posix_is_mangled ( const char *  s,
const struct share_params p 
) [static]

mangle_hash2.c727 行で定義されています。

00728 {
00729         return False;
00730 }

static BOOL posix_is_8_3 ( const char *  fname,
BOOL  check_case,
BOOL  allow_wildcards,
const struct share_params p 
) [static]

mangle_hash2.c732 行で定義されています。

00733 {
00734         return False;
00735 }

static BOOL posix_check_cache ( char *  s,
size_t  maxlen,
const struct share_params p 
) [static]

mangle_hash2.c737 行で定義されています。

00738 {
00739         return False;
00740 }

static void posix_name_map ( char *  OutName,
BOOL  need83,
BOOL  cache83,
int  default_case,
const struct share_params p 
) [static]

mangle_hash2.c742 行で定義されています。

00743 {
00744         if (need83) {
00745                 memset(OutName, '\0', 13);
00746         }
00747 }

struct mangle_fns* posix_mangle_init ( void   ) 

mangle_hash2.c758 行で定義されています。

参照先 posix_mangle_fns.

00759 {
00760         return &posix_mangle_fns;
00761 }


変数

unsigned char char_flags[256] [static]

mangle_hash2.c86 行で定義されています。

参照元 init_tables().

unsigned mangle_prefix [static]

mangle_hash2.c95 行で定義されています。

参照元 check_cache()is_mangled_component()mangle_hash2_init()name_map().

char** prefix_cache [static]

mangle_hash2.c103 行で定義されています。

参照元 cache_init()cache_insert()cache_lookup().

unsigned int* prefix_cache_hashes [static]

mangle_hash2.c104 行で定義されています。

参照元 cache_init()cache_insert()cache_lookup().

const char* basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" [static]

mangle_hash2.c107 行で定義されています。

unsigned char base_reverse[256] [static]

mangle_hash2.c108 行で定義されています。

参照元 check_cache()init_tables().

const char* reserved_names[] [static]

初期値:

 
{ "AUX", "LOCK$", "CON", "COM1", "COM2", "COM3", "COM4",
  "LPT1", "LPT2", "LPT3", "NUL", "PRN", NULL }

mangle_hash2.c112 行で定義されています。

参照元 init_tables()is_reserved_name().

struct mangle_fns mangle_fns [static]

初期値:

mangle_hash2.c694 行で定義されています。

struct mangle_fns posix_mangle_fns [static]

初期値:

mangle_hash2.c750 行で定義されています。

参照元 posix_mangle_init().


Sambaに対してSat Aug 29 21:24:26 2009に生成されました。  doxygen 1.4.7