in mysql_sys/mf_pack.cc [77:175]
size_t cleanup_dirname(char *to, const char *from) {
char *pos;
const char *from_ptr;
char *start;
char parent[5], /* for "FN_PARENTDIR" */
buff[FN_REFLEN + 1], *end_parentdir;
#ifdef _WIN32
CHARSET_INFO *fs = fs_character_set();
#endif
DBUG_TRACE;
DBUG_PRINT("enter", ("from: '%s'", from));
start = buff;
from_ptr = from;
#ifdef FN_DEVCHAR
{
const char *dev_pos = strrchr(from_ptr, FN_DEVCHAR);
if (dev_pos != nullptr) { /* Skip device part */
size_t length = (dev_pos - from_ptr) + 1;
start = my_stpnmov(buff, from_ptr, length);
from_ptr += length;
}
}
#endif
parent[0] = FN_LIBCHAR;
size_t length = my_stpcpy(parent + 1, FN_PARENTDIR) - parent;
const char *end = start + FN_REFLEN;
for (pos = start; pos < end && ((*pos = *from_ptr++) != 0); pos++) {
#ifdef _WIN32
uint l;
if (use_mb(fs) && (l = my_ismbchar(fs, from_ptr - 1, from_ptr + 2))) {
for (l--; l; *++pos = *from_ptr++, l--)
;
start = pos + 1; /* Don't look inside multi-byte char */
continue;
}
#endif
if (*pos == '/') *pos = FN_LIBCHAR;
if (*pos == FN_LIBCHAR) {
if ((size_t)(pos - start) > length &&
memcmp(pos - length, parent, length) ==
0) { /* If .../../; skip prev */
pos -= length;
if (pos != start) { /* not /../ */
pos--;
if (*pos == FN_HOMELIB && (pos == start || pos[-1] == FN_LIBCHAR)) {
if (!home_dir) {
pos += length + 1; /* Don't unpack ~/.. */
continue;
}
pos = my_stpcpy(buff, home_dir) - 1; /* Unpacks ~/.. */
if (*pos == FN_LIBCHAR) pos--; /* home ended with '/' */
}
if (*pos == FN_CURLIB && (pos == start || pos[-1] == FN_LIBCHAR)) {
if (my_getwd(curr_dir, FN_REFLEN, MYF(0))) {
pos += length + 1; /* Don't unpack ./.. */
continue;
}
pos = my_stpcpy(buff, curr_dir) - 1; /* Unpacks ./.. */
if (*pos == FN_LIBCHAR) pos--; /* home ended with '/' */
}
end_parentdir = pos;
while (pos >= start && *pos != FN_LIBCHAR) /* remove prev dir */
pos--;
if (pos[1] == FN_HOMELIB ||
(pos >= start &&
memcmp(pos, parent, length) == 0)) { /* Don't remove ~user/ */
pos = my_stpcpy(end_parentdir + 1, parent);
*pos = FN_LIBCHAR;
continue;
}
}
} else if ((size_t)(pos - start) == length - 1 &&
!memcmp(start, parent + 1, length - 1))
start = pos; /* Starts with "../" */
else if (pos - start > 0 && pos[-1] == FN_LIBCHAR) {
#ifdef FN_NETWORK_DRIVES
if (pos - start != 1)
#endif
pos--; /* Remove dupplicate '/' */
} else if (pos - start > 1 && pos[-1] == FN_CURLIB &&
pos[-2] == FN_LIBCHAR)
pos -= 2; /* Skip /./ */
else if (pos > buff + 1 && pos[-1] == FN_HOMELIB &&
pos[-2] == FN_LIBCHAR) { /* Found ..../~/ */
buff[0] = FN_HOMELIB;
buff[1] = FN_LIBCHAR;
start = buff;
pos = buff + 1;
}
}
}
buff[FN_REFLEN - 1] = '\0';
(void)my_stpcpy(to, buff);
DBUG_PRINT("exit", ("to: '%s'", to));
return (size_t)(pos - buff);
} /* cleanup_dirname */