char *make_path_absolute(const char *path) {
static const char *cwd = NULL;
static size_t cwdlen = 0;
static const char fs = FILE_SEPARATOR;
char *abspath;
if (path_is_relative(path)) {
if (cwdlen == 0) {
get_working_dir(&cwd, &cwdlen);
}
size_t pathlen = strlen(path);
char *result = malloc(pathlen+cwdlen+1);
const char *part = path;
size_t partlen = pathlen;
if (part[0] == '.' && part[1] == fs) {
part += 2;
partlen -= 2;
}
memcpy(result, cwd, cwdlen);
memcpy(result+cwdlen, part, partlen);
result[cwdlen+partlen] = '\0';
abspath = result;
} else {
abspath = strdup(path);
}
size_t abspathlen = strlen(abspath);
char *canonical = malloc(abspathlen + 1);
size_t canonicallen = 0;
for (size_t j = 0; j < abspathlen; j++) {
if (abspath[j] == fs) {
while (abspath[j + 1] == fs) j++;
}
canonical[canonicallen++] = abspath[j];
if (abspath[j] == fs && abspath[j + 1] == '.') {
if (abspath[j + 2] == fs || abspath[j + 2] == 0) {
canonicallen--;
j++;
} else if (abspath[j + 2] == '.' &&
(abspath[j + 3] == fs || abspath[j + 3] == 0)) {
canonicallen--;
while (canonical[--canonicallen] != fs) {}
j += 2;
}
}
}
if (canonical[canonicallen - 1] == fs) canonicallen--;
canonical[canonicallen] = '\0';
free(abspath);
return canonical;
}