| 122 | */ |
| 123 | |
| 124 | size_t cleanup_dirname(register char *to, const char *from) |
| 125 | { |
| 126 | reg5 size_t length; |
| 127 | reg2 char * pos; |
| 128 | reg3 char * from_ptr; |
| 129 | reg4 char * start; |
| 130 | char parent[5], /* for "FN_PARENTDIR" */ |
| 131 | buff[FN_REFLEN+1],*end_parentdir; |
| 132 | #ifdef BACKSLASH_MBTAIL |
| 133 | CHARSET_INFO *fs= fs_character_set(); |
| 134 | #endif |
| 135 | DBUG_ENTER("cleanup_dirname"); |
| 136 | DBUG_PRINT("enter",("from: '%s'",from)); |
| 137 | |
| 138 | start=buff; |
| 139 | from_ptr=(char *) from; |
| 140 | #ifdef FN_DEVCHAR |
| 141 | if ((pos=strrchr(from_ptr,FN_DEVCHAR)) != 0) |
| 142 | { /* Skip device part */ |
| 143 | length=(size_t) (pos-from_ptr)+1; |
| 144 | start=strnmov(buff,from_ptr,length); from_ptr+=length; |
| 145 | } |
| 146 | #endif |
| 147 | |
| 148 | parent[0]=FN_LIBCHAR; |
| 149 | length=(size_t) (strmov(parent+1,FN_PARENTDIR)-parent); |
| 150 | for (pos=start ; (*pos= *from_ptr++) != 0 ; pos++) |
| 151 | { |
| 152 | #ifdef BACKSLASH_MBTAIL |
| 153 | uint l; |
| 154 | if (use_mb(fs) && (l= my_ismbchar(fs, from_ptr - 1, from_ptr + 2))) |
| 155 | { |
| 156 | for (l-- ; l ; *++pos= *from_ptr++, l--); |
| 157 | start= pos + 1; /* Don't look inside multi-byte char */ |
| 158 | continue; |
| 159 | } |
| 160 | #endif |
| 161 | if (*pos == '/') |
| 162 | *pos = FN_LIBCHAR; |
| 163 | if (*pos == FN_LIBCHAR) |
| 164 | { |
| 165 | if ((size_t) (pos-start) > length && memcmp(pos-length,parent,length) == 0) |
| 166 | { /* If .../../; skip prev */ |
| 167 | pos-=length; |
| 168 | if (pos != start) |
| 169 | { /* not /../ */ |
| 170 | pos--; |
| 171 | if (*pos == FN_HOMELIB && (pos == start || pos[-1] == FN_LIBCHAR)) |
| 172 | { |
| 173 | if (!home_dir) |
| 174 | { |
| 175 | pos+=length+1; /* Don't unpack ~/.. */ |
| 176 | continue; |
| 177 | } |
| 178 | pos=strmov(buff,home_dir)-1; /* Unpacks ~/.. */ |
| 179 | if (*pos == FN_LIBCHAR) |
| 180 | pos--; /* home ended with '/' */ |
| 181 | } |
no test coverage detected