From: Raphaël Beamonte Date: Wed, 13 Nov 2013 05:34:35 +0000 (-0500) Subject: Introduce a new utils_resolve_relative function X-Git-Tag: v2.4.0-rc1~48 X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=commitdiff_plain;h=a2e78ff0442a6a4c290577ff2ecf3c4307c3e9f5;hp=67b5863058c0fbe14e0b527013b50aef8eabdd88 Introduce a new utils_resolve_relative function This function aims to resolve relative path such as './' and '../' in the middle of a path string. This allows to use paths such as '~/../test' that are received as '/home/x/../test' for instance. Signed-off-by: Raphaël Beamonte --- diff --git a/src/common/utils.c b/src/common/utils.c index da4c036b9..4ccf36a6c 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -35,6 +35,74 @@ #include "utils.h" #include "defaults.h" +/* + * Resolve the './' and '../' strings in the middle of a path using + * our very own way to do it, so that it works even if the directory + * does not exist + */ +LTTNG_HIDDEN +char *utils_resolve_relative(const char *path) +{ + char *next, *previous, *slash, *start_path, *absolute_path = NULL; + + /* Safety net */ + if (path == NULL) { + goto error; + } + + /* Allocate memory for the absolute path */ + absolute_path = zmalloc(PATH_MAX); + if (absolute_path == NULL) { + PERROR("zmalloc expand path"); + goto error; + } + + /* Copy the path in the absolute path */ + strncpy(absolute_path, path, PATH_MAX); + + /* As long as we find '/./' in the path string */ + while ((next = strstr(absolute_path, "/./"))) { + + /* We prepare the start_path not containing it */ + start_path = strndup(absolute_path, next - absolute_path); + + /* And we concatenate it with the part after this string */ + snprintf(absolute_path, PATH_MAX, "%s%s", start_path, next + 2); + + free(start_path); + } + + /* As long as we find '/../' in the path string */ + while ((next = strstr(absolute_path, "/../"))) { + /* If the path starts with '/../', there's a problem */ + if (next == absolute_path) { + ERR("%s: Path cannot be resolved", path); + goto error; + } + + /* We find the last level of directory */ + previous = absolute_path; + while ((slash = strpbrk(previous + 1, "/")) && slash != next) { + previous = slash; + } + + /* Then we prepare the start_path not containing it */ + start_path = strndup(absolute_path, previous - absolute_path); + + /* And we concatenate it with the part after the '/../' */ + snprintf(absolute_path, PATH_MAX, "%s%s", start_path, next + 3); + + free(start_path); + } + + return absolute_path; + +error: + free(absolute_path); + return NULL; +} + + /* * Return the realpath(3) of the path even if the last directory token does not * exist. For example, with /tmp/test1/test2, if test2/ does not exist but the diff --git a/src/common/utils.h b/src/common/utils.h index 52f2798d1..c56942f56 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -26,6 +26,7 @@ #define MEBI_LOG2 20 #define GIBI_LOG2 30 +char *utils_resolve_relative(const char *path); char *utils_expand_path(const char *path); int utils_create_pipe(int *dst); int utils_create_pipe_cloexec(int *dst);