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