1 char *make_path_absolute(
const char *path) {
2 static const char *cwd =
NULL;
3 static size_t cwdlen =
0;
4 static const char fs =
FILE_SEPARATOR;
5 char *abspath;
6 if (path_is_relative(path)) {
7 if (cwdlen ==
0) {
8 get_working_dir(&cwd, &cwdlen);
9 }
10 size_t pathlen = strlen(path);
11 char *result = malloc(pathlen+cwdlen
+1);
12 const char *part = path;
13 size_t partlen = pathlen;
14 if (part[
0] ==
'.' && part[
1] == fs) {
15 part +=
2;
16 partlen -=
2;
17 }
18 memcpy(result, cwd, cwdlen);
19 memcpy(result+cwdlen, part, partlen);
20 result[cwdlen+partlen] =
'\0';
21 abspath = result;
22 }
else {
23 abspath = strdup(path);
24 }
25
26 size_t abspathlen = strlen(abspath);
27 char *canonical = malloc(abspathlen +
1);
28 size_t canonicallen =
0;
29 for (
size_t j =
0; j < abspathlen; j++) {
30
31 if (abspath[j] == fs) {
32 while (abspath[j +
1] == fs) j++;
33 }
34
35 canonical[canonicallen++] = abspath[j];
36
37 if (abspath[j] == fs && abspath[j +
1] ==
'.') {
38 if (abspath[j +
2] == fs || abspath[j +
2] ==
0) {
39
40 canonicallen--;
41 j++;
42 }
else if (abspath[j +
2] ==
'.' &&
43 (abspath[j +
3] == fs || abspath[j +
3] ==
0)) {
44
45 canonicallen--;
46 while (canonical[--canonicallen] != fs) {}
47 j +=
2;
48 }
49 }
50 }
51
52 if (canonical[canonicallen -
1] == fs) canonicallen--;
53 canonical[canonicallen] =
'\0';
54 free(abspath);
55 return canonical;
56 }
57
58