1 /*
2 * Copyright (c) 2009 - 2011 Miek Gieben
3 * License: GPLv3(+), see LICENSE for details
4 */
5 #include "rdup.h"
6
7 /*
8 * Remove /./ and /../ and // from a pathname
9 * An absolute pathname argument is required.
10 * Returns NULL on error, otherwise NULL terminated
11 * sanitized pathname.
12 *
13 * Also see realpath(3)
14 */
abspath(char * path)15 char *abspath(char *path)
16 {
17 char *p, *c;
18 char *slash, *abspath2;
19 char *abspath;
20 int i;
21
22 if (!path)
23 return NULL;
24
25 if (!g_path_is_absolute(path))
26 return NULL;
27
28 /* abspath can be NULL or abspath[0] == '\0'. The NULL
29 * is initial. the [0] == '\0' is when we got back to
30 * the root
31 */
32 abspath = NULL;
33 abspath2 = g_strdup(path);
34 i = strlen(abspath2);
35 if (i > BUFSIZE)
36 return NULL;
37
38 /* add closing / (guard) */
39 if (abspath2[i - 1] != '/') {
40 abspath2 = g_realloc(abspath2, i + 2);
41 abspath2[i] = '/';
42 abspath2[i + 1] = '\0';
43 }
44
45 /* jump from slash to slash */
46 for (p = abspath2; (c = strchr(p, '/')); p++) {
47 *c = '\0';
48 if (*p == '\0' || (strcmp(p, ".") == 0)) {
49 /* do nothing */
50 p = c;
51 } else if (strcmp(p, "..") == 0) {
52 /* go back a slash */
53 if (abspath == NULL || abspath[0] == '\0') {
54 abspath = g_strdup("/");
55 } else {
56 slash = strrchr(abspath, '/');
57 *slash = '\0';
58 *c = '/';
59 }
60 } else {
61 if (abspath == NULL || abspath[0] == '\0' ||
62 (strcmp(abspath, "/") == 0)) {
63 g_free(abspath);
64 abspath = g_strconcat("/", p, NULL);
65 } else {
66 gchar *tmp = g_strdup(abspath);
67 g_free(abspath);
68 abspath = g_strjoin("/", tmp, p, NULL);
69 g_free(tmp);
70 }
71 *c = '/';
72 }
73 p = c;
74 }
75 if (abspath == NULL || abspath[0] == '\0')
76 abspath = g_strdup("/");
77
78 g_free(abspath2);
79 return abspath;
80 }
81