diff options
author | Christopher R. Hertel <crh@samba.org> | 1997-11-07 03:06:24 +0000 |
---|---|---|
committer | Christopher R. Hertel <crh@samba.org> | 1997-11-07 03:06:24 +0000 |
commit | 34d1b3e4fa7a1158f3a3c5c47adf0417c7144095 (patch) | |
tree | e77de8cd403ea3ecdf82c30f79e06b7d7264d358 /source/smbd/mangle.c | |
parent | ff94f97cf2b0f62cbbddbfd3d126df7f4d649334 (diff) | |
download | samba-34d1b3e4fa7a1158f3a3c5c47adf0417c7144095.tar.gz samba-34d1b3e4fa7a1158f3a3c5c47adf0417c7144095.tar.xz samba-34d1b3e4fa7a1158f3a3c5c47adf0417c7144095.zip |
Modified Files:
mangle.c server.c proto.h
mangle.c
I am planning to replace the mangled_stack array with a proper stack,
but found many style inconsistencies (no, really). As you might expect,
I have standardized on my own preferences. ;)
I also found a potential problem in create_mangled_stack (which I've
renamed as reset_mangled_stack). If the stack size were passed into
the function as 0 or less, there was the possibility that the array
would have been freed twice. I doubt that this ever happens, but I
don't like to leave holes.
Of course, the fix will be irrelevent once I replace the array with
a linked-list-based stack.
server.c
Changed the call to create_mangled_stack() to a call to reset_mangled_stack().
proto.h
Regenerated to match the above changes. (A real comment! How unusual!)
Diffstat (limited to 'source/smbd/mangle.c')
-rw-r--r-- | source/smbd/mangle.c | 557 |
1 files changed, 316 insertions, 241 deletions
diff --git a/source/smbd/mangle.c b/source/smbd/mangle.c index 829e307a85b..bf264757155 100644 --- a/source/smbd/mangle.c +++ b/source/smbd/mangle.c @@ -26,27 +26,33 @@ extern int case_default; extern BOOL case_mangle; /**************************************************************************** -provide a checksum on a string -****************************************************************************/ + * Provide a checksum on a string + * + * Input: s - the nul-terminated character string for which the checksum + * will be calculated. + * Output: The checksum value calculated for s. + * + ****************************************************************************/ int str_checksum(char *s) -{ + { int res = 0; int c; int i=0; - while (*s) + + while( *s ) { - c = *s; - res ^= (c << (i % 15)) ^ (c >> (15-(i%15))); - s++; i++; + c = *s; + res ^= (c << (i % 15)) ^ (c >> (15-(i%15))); + s++; i++; } return(res); -} + } /* str_checksum */ /**************************************************************************** return True if a name is a special msdos reserved name ****************************************************************************/ static BOOL is_reserved_msdos(char *fname) -{ + { char upperFname[13]; char *p; @@ -72,7 +78,7 @@ static BOOL is_reserved_msdos(char *fname) return (True) ; return (False); -} + } /* is_reserved_msdos */ @@ -80,34 +86,37 @@ static BOOL is_reserved_msdos(char *fname) return True if a name is in 8.3 dos format ****************************************************************************/ BOOL is_8_3(char *fname, BOOL check_case) -{ + { int len; char *dot_pos; char *slash_pos = strrchr(fname,'/'); int l; - if (slash_pos) fname = slash_pos+1; + if( slash_pos ) + fname = slash_pos+1; len = strlen(fname); DEBUG(5,("checking %s for 8.3\n",fname)); - if (check_case && case_mangle) + if( check_case && case_mangle ) + { switch (case_default) { case CASE_LOWER: - if (strhasupper(fname)) return(False); - break; + if (strhasupper(fname)) return(False); + break; case CASE_UPPER: - if (strhaslower(fname)) return(False); - break; + if (strhaslower(fname)) return(False); + break; } + } /* can't be longer than 12 chars */ - if (len == 0 || len > 12) + if( len == 0 || len > 12 ) return(False); /* can't be an MS-DOS Special file such as lpt1 or even lpt1.txt */ - if (is_reserved_msdos(fname)) + if( is_reserved_msdos(fname) ) return(False); /* can't contain invalid dos chars */ @@ -121,184 +130,218 @@ BOOL is_8_3(char *fname, BOOL check_case) dot_pos = strchr(fname,'.'); - { + { char *p = fname; + if(lp_client_code_page() == KANJI_CODEPAGE) - { + { dot_pos = 0; while (*p) - { + { if (is_shift_jis (*p)) p += 2; else if (is_kana (*p)) p ++; else - { + { if (*p == '.' && !dot_pos) dot_pos = (char *) p; if (!isdoschar(*p)) return(False); p++; + } } - } - } + } else - { - while (*p) { + while (*p) + { if (!isdoschar(*p)) return(False); p++; - } + } + } } - } /* no dot and less than 9 means OK */ if (!dot_pos) return(len <= 8); - + l = PTR_DIFF(dot_pos,fname); /* base must be at least 1 char except special cases . and .. */ - if (l == 0) + if( l == 0 ) return(strcmp(fname,".") == 0 || strcmp(fname,"..") == 0); /* base can't be greater than 8 */ - if (l > 8) + if( l > 8 ) return(False); - if (lp_strip_dot() && + if( lp_strip_dot() && len - l == 1 && - !strchr(dot_pos+1,'.')) + !strchr(dot_pos+1,'.') ) { - *dot_pos = 0; - return(True); + *dot_pos = 0; + return(True); } /* extension must be between 1 and 3 */ - if ( (len - l < 2 ) || (len - l > 4) ) + if( (len - l < 2 ) || (len - l > 4) ) return(False); /* extension can't have a dot */ - if (strchr(dot_pos+1,'.')) + if( strchr(dot_pos+1,'.') ) return(False); /* must be in 8.3 format */ return(True); -} + } /* is_8_3 */ + +/* -------------------------------------------------------------------------- ** + * This section creates and maintains a stack of name mangling results. + * The original comments read: "keep a stack of name mangling results - just + * so file moves and copies have a chance of working" (whatever that means). + * + * There are three functions to manage the stack: + * reset_mangled_stack() - + * push_mangled_name() - + * check_mangled_stack() - + */ - - -/* -keep a stack of name mangling results - just -so file moves and copies have a chance of working -*/ fstring *mangled_stack = NULL; int mangled_stack_size = 0; int mangled_stack_len = 0; /**************************************************************************** -create the mangled stack -****************************************************************************/ -void create_mangled_stack(int size) -{ - if (mangled_stack) + * create the mangled stack CRH + ****************************************************************************/ +void reset_mangled_stack( int size ) + { + if( mangled_stack ) + { + free(mangled_stack); + mangled_stack_size = 0; + mangled_stack_len = 0; + } + + if( size > 0 ) { - free(mangled_stack); - mangled_stack_size = 0; - mangled_stack_len = 0; + mangled_stack = (fstring *)malloc( sizeof(fstring) * size ); + if( mangled_stack ) + mangled_stack_size = size; } - if (size > 0) - mangled_stack = (fstring *)malloc(sizeof(fstring)*size); - if (mangled_stack) mangled_stack_size = size; -} + else + mangled_stack = NULL; + } /* create_mangled_stack */ /**************************************************************************** -push a mangled name onto the stack -****************************************************************************/ + * push a mangled name onto the stack CRH + ****************************************************************************/ static void push_mangled_name(char *s) -{ + { int i; char *p; - if (!mangled_stack) + /* If the stack doesn't exist... Fail. */ + if( !mangled_stack ) return; - for (i=0;i<mangled_stack_len;i++) - if (strcmp(s,mangled_stack[i]) == 0) + /* If name <s> is already on the stack, move it to the top. */ + for( i=0; i<mangled_stack_len; i++ ) + { + if( strcmp( s, mangled_stack[i] ) == 0 ) { - array_promote(mangled_stack[0],sizeof(fstring),i); - return; + array_promote( mangled_stack[0],sizeof(fstring), i ); + return; } + } - memmove(mangled_stack[1],mangled_stack[0], - sizeof(fstring)*MIN(mangled_stack_len,mangled_stack_size-1)); - strcpy(mangled_stack[0],s); - p = strrchr(mangled_stack[0],'.'); - if (p && (!strhasupper(p+1)) && (strlen(p+1) < 4)) + /* If name <s> wasn't already there, add it to the top of the stack. */ + memmove( mangled_stack[1], mangled_stack[0], + sizeof(fstring) * MIN(mangled_stack_len, mangled_stack_size-1) ); + strcpy( mangled_stack[0], s ); + mangled_stack_len = MIN( mangled_stack_size, mangled_stack_len+1 ); + + /* Hmmm... + * Find the last dot '.' in the name, + * if there are any upper case characters past the last dot + * and there are no more than three characters past the last dot + * then terminate the name *at* the last dot. + */ + p = strrchr( mangled_stack[0], '.' ); + if( p && (!strhasupper(p+1)) && (strlen(p+1) < (size_t)4) ) *p = 0; - mangled_stack_len = MIN(mangled_stack_size,mangled_stack_len+1); -} + + } /* push_mangled_name */ /**************************************************************************** -check for a name on the mangled name stack -****************************************************************************/ + * check for a name on the mangled name stack CRH + ****************************************************************************/ BOOL check_mangled_stack(char *s) -{ + { int i; pstring tmpname; char extension[5]; - char *p = strrchr(s,'.'); + char *p = strrchr( s, '.' ); BOOL check_extension = False; extension[0] = 0; - if (!mangled_stack) return(False); + /* If the stack doesn't exist, fail. */ + if( !mangled_stack ) + return(False); - if (p) + /* If there is a file extension, then we need to play with it, too. */ + if( p ) { - check_extension = True; - StrnCpy(extension,p,4); - strlower(extension); /* XXXXXXX */ + check_extension = True; + StrnCpy( extension, p, 4 ); + strlower( extension ); /* XXXXXXX */ } - for (i=0;i<mangled_stack_len;i++) + for( i=0; i<mangled_stack_len; i++ ) { - strcpy(tmpname,mangled_stack[i]); + strcpy(tmpname,mangled_stack[i]); + mangle_name_83(tmpname); + if( strequal(tmpname,s) ) + { + strcpy(s,mangled_stack[i]); + break; + } + if( check_extension && !strchr(mangled_stack[i],'.') ) + { + pstrcpy(tmpname,mangled_stack[i]); + strcat(tmpname,extension); mangle_name_83(tmpname); - if (strequal(tmpname,s)) - { - strcpy(s,mangled_stack[i]); - break; - } - if (check_extension && !strchr(mangled_stack[i],'.')) - { - pstrcpy(tmpname,mangled_stack[i]); - strcat(tmpname,extension); - mangle_name_83(tmpname); - if (strequal(tmpname,s)) - { - strcpy(s,mangled_stack[i]); - strcat(s,extension); - break; - } - } + if( strequal(tmpname,s) ) + { + strcpy(s,mangled_stack[i]); + strcat(s,extension); + break; + } + } } - if (i < mangled_stack_len) + if( i < mangled_stack_len ) { - DEBUG(3,("Found %s on mangled stack as %s\n",s,mangled_stack[i])); - array_promote(mangled_stack[0],sizeof(fstring),i); - return(True); + DEBUG(3,("Found %s on mangled stack as %s\n",s,mangled_stack[i])); + array_promote(mangled_stack[0],sizeof(fstring),i); + return(True); } return(False); -} + } /* check_mangled_stack */ + + +/* End of the mangled stack section. + * -------------------------------------------------------------------------- ** + */ -static char *map_filename(char *s, /* This is null terminated */ - char *pattern, /* This isn't. */ - int len) /* This is the length of pattern. */ -{ + +static char *map_filename( char *s, /* This is null terminated */ + char *pattern, /* This isn't. */ + int len ) /* This is the length of pattern. */ + { static pstring matching_bit; /* The bit of the string which matches */ /* a * in pattern if indeed there is a * */ char *sp; /* Pointer into s. */ @@ -307,57 +350,68 @@ static char *map_filename(char *s, /* This is null terminated */ pstring pat; StrnCpy(pat, pattern, len); /* Get pattern into a proper string! */ - pstrcpy(matching_bit,""); /* Match but no star gets this. */ + pstrcpy(matching_bit,""); /* Match but no star gets this. */ pp = pat; /* Initialise the pointers. */ sp = s; - if ((len == 1) && (*pattern == '*')) { + if( (len == 1) && (*pattern == '*') ) + { return NULL; /* Impossible, too ambiguous for */ - /* words! */ - } + } /* words! */ while ((*sp) /* Not the end of the string. */ && (*pp) /* Not the end of the pattern. */ && (*sp == *pp) /* The two match. */ - && (*pp != '*')) { /* No wildcard. */ + && (*pp != '*')) /* No wildcard. */ + { sp++; /* Keep looking. */ pp++; - } - if (!*sp && !*pp) /* End of pattern. */ - return matching_bit; /* Simple match. Return empty string. */ - if (*pp == '*') { + } + + if( !*sp && !*pp ) /* End of pattern. */ + return( matching_bit ); /* Simple match. Return empty string. */ + + if (*pp == '*') + { pp++; /* Always interrested in the chacter */ /* after the '*' */ - if (!*pp) { /* It is at the end of the pattern. */ + if (!*pp) /* It is at the end of the pattern. */ + { StrnCpy(matching_bit, s, sp-s); return matching_bit; - } else { + } + else + { /* The next character in pattern must match a character further */ /* along s than sp so look for that character. */ match_start = sp; - while ((*sp) /* Not the end of s. */ + while( (*sp) /* Not the end of s. */ && (*sp != *pp)) /* Not the same */ sp++; /* Keep looking. */ - if (!*sp) { /* Got to the end without a match. */ + if (!*sp) /* Got to the end without a match. */ + { return NULL; - } else { /* Still hope for a match. */ + } /* Still hope for a match. */ + else + { /* Now sp should point to a matching character. */ StrnCpy(matching_bit, match_start, sp-match_start); /* Back to needing a stright match again. */ - while ((*sp) /* Not the end of the string. */ + while( (*sp) /* Not the end of the string. */ && (*pp) /* Not the end of the pattern. */ - && (*sp == *pp)) { /* The two match. */ + && (*sp == *pp) ) /* The two match. */ + { sp++; /* Keep looking. */ pp++; - } + } if (!*sp && !*pp) /* Both at end so it matched */ return matching_bit; else return NULL; + } } } - } return NULL; /* No match. */ -} + } /* map_filename */ /* this is the magic char used for mangling */ @@ -365,22 +419,24 @@ char magic_char = '~'; /**************************************************************************** -determine whther is name could be a mangled name +return True if the name could be a mangled name ****************************************************************************/ -BOOL is_mangled(char *s) -{ +BOOL is_mangled( char *s ) + { char *m = strchr(s,magic_char); - if (!m) return(False); - /* we use two base 36 chars efore the extension */ - if (m[1] == '.' || m[1] == 0 || + if( !m ) + return(False); + + /* we use two base 36 chars before the extension */ + if( m[1] == '.' || m[1] == 0 || m[2] == '.' || m[2] == 0 || - (m[3] != '.' && m[3] != 0)) - return(is_mangled(m+1)); + (m[3] != '.' && m[3] != 0) ) + return( is_mangled(m+1) ); /* it could be */ return(True); -} + } /* is_mangled */ @@ -388,14 +444,14 @@ BOOL is_mangled(char *s) return a base 36 character. v must be from 0 to 35. ****************************************************************************/ static char base36(unsigned int v) -{ + { static char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; return basechars[v % 36]; -} + } /* base36 */ static void do_fwd_mangled_map(char *s, char *MangledMap) -{ + { /* MangledMap is a series of name pairs in () separated by spaces. * If s matches the first of the pair then the name given is the * second of the pair. A * means any number of any character and if @@ -415,7 +471,8 @@ static void do_fwd_mangled_map(char *s, char *MangledMap) char *np; /* Points into new_string. */ DEBUG(5,("Mangled Mapping '%s' map '%s'\n", s, MangledMap)); - while (*start) { + while (*start) + { while ((*start) && (*start != '(')) start++; if (!*start) @@ -425,12 +482,14 @@ static void do_fwd_mangled_map(char *s, char *MangledMap) DEBUG(5,("Start of first in pair '%s'\n", start)); while ((*end) && !((*end == ' ') || (*end == ')'))) end++; - if (!*end) { + if (!*end) + { start = end; continue; /* Always check for the end. */ - } + } DEBUG(5,("End of first in pair '%s'\n", end)); - if ((match_string = map_filename(s, start, end-start))) { + if ((match_string = map_filename(s, start, end-start))) + { DEBUG(5,("Found a match\n")); /* Found a match. */ start = end+1; /* Point to start of what it is to become. */ @@ -441,11 +500,13 @@ static void do_fwd_mangled_map(char *s, char *MangledMap) && (*end != ')') /* Not the end of the pattern. */ && (*end != '*')) /* Not a wildcard. */ *np++ = *end++; - if (!*end) { + if (!*end) + { start = end; continue; /* Always check for the end. */ - } - if (*end == '*') { + } + if (*end == '*') + { pstrcpy(np, match_string); np += strlen(match_string); end++; /* Skip the '*' */ @@ -453,27 +514,28 @@ static void do_fwd_mangled_map(char *s, char *MangledMap) && (*end != ')') /* Not the end of the pattern. */ && (*end != '*')) /* Not a wildcard. */ *np++ = *end++; - } - if (!*end) { + } + if (!*end) + { start = end; continue; /* Always check for the end. */ - } + } *np++ = '\0'; /* NULL terminate it. */ DEBUG(5,("End of second in pair '%s'\n", end)); pstrcpy(s, new_string); /* Substitute with the new name. */ DEBUG(5,("s is now '%s'\n", s)); - } + } start = end; /* Skip a bit which cannot be wanted */ /* anymore. */ start++; - } -} + } + } /* do_fwd_mangled_map */ /**************************************************************************** do the actual mangling to 8.3 format ****************************************************************************/ void mangle_name_83(char *s) -{ + { int csum = str_checksum(s); char *p; char extension[4]; @@ -485,120 +547,127 @@ void mangle_name_83(char *s) base[0]=0; p = strrchr(s,'.'); - if (p && (strlen(p+1)<4) ) + if( p && (strlen(p+1) < (size_t)4) ) { - BOOL all_normal = (strisnormal(p+1)); /* XXXXXXXXX */ - if (all_normal && p[1] != 0) - { - *p = 0; - csum = str_checksum(s); - *p = '.'; - } + BOOL all_normal = (strisnormal(p+1)); /* XXXXXXXXX */ + + if (all_normal && p[1] != 0) + { + *p = 0; + csum = str_checksum(s); + *p = '.'; + } } - strupper(s); DEBUG(5,("Mangling name %s to ",s)); - if (p) - { + if( p ) + { if (p == s) strcpy(extension,"___"); else - { - *p++ = 0; - while (*p && extlen < 3) - { - if(lp_client_code_page() == KANJI_CODEPAGE) + { + *p++ = 0; + while (*p && extlen < 3) { - if (is_shift_jis (*p)) + if(lp_client_code_page() == KANJI_CODEPAGE) { - if (extlen < 2) + if (is_shift_jis (*p)) { + if (extlen < 2) + { extension[extlen++] = p[0]; extension[extlen++] = p[1]; - } + } else - { + { extension[extlen++] = base36 (((unsigned char) *p) % 36); - } + } p += 2; - } - else if (is_kana (*p)) - { - extension[extlen++] = p[0]; - p++; - } - else - { - if (isdoschar (*p) && *p != '.') + } + else + { + if( is_kana (*p) ) + { extension[extlen++] = p[0]; - p++; + p++; + } + else + { + if (isdoschar (*p) && *p != '.') + extension[extlen++] = p[0]; + p++; + } + } } - } else - { + { if (isdoschar(*p) && *p != '.') extension[extlen++] = *p; p++; + } } + extension[extlen] = 0; } - extension[extlen] = 0; } - } p = s; while (*p && baselen < 5) - { - if(lp_client_code_page() == KANJI_CODEPAGE) { - if (is_shift_jis (*p)) + if(lp_client_code_page() == KANJI_CODEPAGE) { - if (baselen < 4) + if (is_shift_jis (*p)) { + if (baselen < 4) + { base[baselen++] = p[0]; base[baselen++] = p[1]; - } + } else - { - base[baselen++] = base36 (((unsigned char) *p) % 36); - } + { + base[baselen++] = base36 (((unsigned char) *p) % 36); + } p += 2; - } - else if (is_kana (*p)) - { - base[baselen++] = p[0]; - p++; - } - else - { - if (isdoschar (*p) && *p != '.') + } + else + { + if( is_kana (*p) ) + { base[baselen++] = p[0]; - p++; + p++; + } + else + { + if (isdoschar (*p) && *p != '.') + base[baselen++] = p[0]; + p++; + } + } } - } else - { + { if (isdoschar(*p) && *p != '.') base[baselen++] = *p; p++; + } } - } base[baselen] = 0; csum = csum % (36*36); - sprintf(s,"%s%c%c%c",base,magic_char,base36(csum/36),base36(csum%36)); + sprintf(s,"%s%c%c%c",base,magic_char,base36(csum/36),base36(csum%36)); - if (*extension) + if( *extension ) { - strcat(s,"."); - strcat(s,extension); + strcat(s,"."); + strcat(s,extension); } DEBUG(5,("%s\n",s)); -} + + } /* mangle_name_83 */ @@ -606,68 +675,74 @@ void mangle_name_83(char *s) work out if a name is illegal, even for long names ******************************************************************/ static BOOL illegal_name(char *name) -{ + { static unsigned char illegal[256]; static BOOL initialised=False; unsigned char *s; - if (!initialised) - { + if( !initialised ) + { char *ill = "*\\/?<>|\":"; initialised = True; bzero((char *)illegal,256); - for (s = (unsigned char *)ill; *s; s++) + for( s = (unsigned char *)ill; *s; s++ ) illegal[*s] = True; - } + } if(lp_client_code_page() == KANJI_CODEPAGE) - { - for (s = (unsigned char *)name; *s;) { - if (is_shift_jis (*s)) { + { + for (s = (unsigned char *)name; *s;) + { + if (is_shift_jis (*s)) s += 2; - } else if (illegal[*s]) { - return(True); - } else { - s++; + else + { + if (illegal[*s]) + return(True); + else + s++; + } } } - } else - { + { for (s = (unsigned char *)name;*s;s++) if (illegal[*s]) return(True); - } + } return(False); -} + } /* illegal_name */ /**************************************************************************** convert a filename to DOS format. return True if successful. ****************************************************************************/ BOOL name_map_mangle(char *OutName,BOOL need83,int snum) -{ + { #ifdef MANGLE_LONG_FILENAMES - if (!need83 && illegal_name(OutName)) need83 = True; + if( !need83 && illegal_name(OutName) ) + need83 = True; #endif /* apply any name mappings */ { - char *map = lp_mangled_map(snum); - if (map && *map) - do_fwd_mangled_map(OutName,map); + char *map = lp_mangled_map(snum); + + if (map && *map) + do_fwd_mangled_map(OutName,map); } /* check if it's already in 8.3 format */ - if (need83 && !is_8_3(OutName, True)) { - if (!lp_manglednames(snum)) return(False); + if( need83 && !is_8_3(OutName, True) ) + { + if( !lp_manglednames(snum) ) + return(False); /* mangle it into 8.3 */ push_mangled_name(OutName); mangle_name_83(OutName); - } + } return(True); -} - + } /* name_map_mangle */ |