From e40c873f0b555d4280c7fc01dca882069c42739c Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Wed, 19 Jan 2022 11:35:20 -0500 Subject: [PATCH] Move utils_expand_path and utils_expand_path_keep_symlink to libpath.la MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Move the GPLv2 helper functions utils_expand_path and utils_expand_path_keep_symlink to libpath.la. This will allow utils.cpp to be relicensed to LGPLv2.1 by making sure EfficiOS owns the copyright for the entire source file. Statically include libpath.la into libcommon-gpl.la. The "lttng" executable is GPLv2 and only depends on libcommon-lgpl.la, so it needs to explicitly list libpath.la as its dependency. Signed-off-by: Mathieu Desnoyers Signed-off-by: Jérémie Galarneau Change-Id: I2108e0bd35ce75797d4a20e65891c820a1dd79f8 --- src/bin/lttng-relayd/main.c | 1 + src/bin/lttng-relayd/utils.c | 1 + src/bin/lttng-sessiond/main.c | 1 + src/bin/lttng-sessiond/sessiond-config.c | 1 + src/bin/lttng/Makefile.am | 1 + src/bin/lttng/commands/create.c | 2 + src/bin/lttng/commands/enable_events.c | 1 + src/common/Makefile.am | 9 +- src/common/path.c | 384 +++++++++++++++++++++++ src/common/path.h | 13 + src/common/utils.c | 372 ---------------------- src/common/utils.h | 2 - tests/unit/ini_config/ini_config.c | 1 + tests/unit/test_utils_expand_path.c | 1 + 14 files changed, 415 insertions(+), 375 deletions(-) create mode 100644 src/common/path.c create mode 100644 src/common/path.h diff --git a/src/bin/lttng-relayd/main.c b/src/bin/lttng-relayd/main.c index 7ffc1e9c5..902fcab8e 100644 --- a/src/bin/lttng-relayd/main.c +++ b/src/bin/lttng-relayd/main.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include diff --git a/src/bin/lttng-relayd/utils.c b/src/bin/lttng-relayd/utils.c index 4646a88a6..ecf64f31b 100644 --- a/src/bin/lttng-relayd/utils.c +++ b/src/bin/lttng-relayd/utils.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "lttng-relayd.h" #include "utils.h" diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index b9ce08575..449a58952 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include diff --git a/src/bin/lttng-sessiond/sessiond-config.c b/src/bin/lttng-sessiond/sessiond-config.c index f0ab4ce04..843586e60 100644 --- a/src/bin/lttng-sessiond/sessiond-config.c +++ b/src/bin/lttng-sessiond/sessiond-config.c @@ -15,6 +15,7 @@ #include #include #include +#include #include static diff --git a/src/bin/lttng/Makefile.am b/src/bin/lttng/Makefile.am index de23c2412..df20dc012 100644 --- a/src/bin/lttng/Makefile.am +++ b/src/bin/lttng/Makefile.am @@ -35,6 +35,7 @@ lttng_CFLAGS = $(AM_CFLAGS) $(POPT_CFLAGS) lttng_LDADD = $(top_builddir)/src/lib/lttng-ctl/liblttng-ctl.la \ $(top_builddir)/src/common/libcommon-lgpl.la \ + $(top_builddir)/src/common/libpath.la \ $(top_builddir)/src/common/config/libconfig.la \ $(top_builddir)/src/common/string-utils/libstring-utils.la \ $(POPT_LIBS) diff --git a/src/bin/lttng/commands/create.c b/src/bin/lttng/commands/create.c index 87a66c710..2b44dd63a 100644 --- a/src/bin/lttng/commands/create.c +++ b/src/bin/lttng/commands/create.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include static char *opt_output_path; static char *opt_session_name; diff --git a/src/bin/lttng/commands/enable_events.c b/src/bin/lttng/commands/enable_events.c index c2a6e7621..8dc44a1fc 100644 --- a/src/bin/lttng/commands/enable_events.c +++ b/src/bin/lttng/commands/enable_events.c @@ -21,6 +21,7 @@ #include #include #include +#include #include /* Mi dependancy */ diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 213e21772..ca9c70d80 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -23,7 +23,7 @@ DIST_SUBDIRS = \ fd-tracker # Common library -noinst_LTLIBRARIES = libcommon-lgpl.la libcommon-gpl.la +noinst_LTLIBRARIES = libpath.la libcommon-lgpl.la libcommon-gpl.la EXTRA_DIST = mi-lttng-4.0.xsd # The libcommon-lgpl static archive contains only LGPLv2.1 code. It is @@ -68,6 +68,12 @@ libcommon_lgpl_la_LIBADD = \ $(top_builddir)/src/common/config/libconfig.la \ $(top_builddir)/src/common/hashtable/libhashtable-lgpl.la +# The libpath static archive contains GPLv2 compatible code. It is +# meant to be used by GPL executables. + +libpath_la_SOURCES = \ + path.c path.h + # The libcommon-gpl static archive contains GPLv2 compatible code. It is # meant to be used by GPL executables. libcommon_gpl_la_SOURCES = \ @@ -88,6 +94,7 @@ libcommon_gpl_la_SOURCES = \ libcommon_gpl_la_LIBADD = \ -lurcu -lurcu-common \ libcommon-lgpl.la \ + libpath.la \ $(top_builddir)/src/common/hashtable/libhashtable-gpl.la \ $(top_builddir)/src/common/fd-tracker/libfd-tracker.la diff --git a/src/common/path.c b/src/common/path.c new file mode 100644 index 000000000..60cec2778 --- /dev/null +++ b/src/common/path.c @@ -0,0 +1,384 @@ +/* + * Copyright (C) 2012 David Goulet + * Copyright (C) 2013 Raphaël Beamonte + * Copyright (C) 2013 Jérémie Galarneau + * Copyright (C) 2021 Mathieu Desnoyers + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#define _LGPL_SOURCE +#include +#include +#include +#include + +/* + * Return a partial realpath(3) of the path even if the full path does not + * exist. For instance, with /tmp/test1/test2/test3, if test2/ does not exist + * but the /tmp/test1 does, the real path for /tmp/test1 is concatened with + * /test2/test3 then returned. In normal time, realpath(3) fails if the end + * point directory does not exist. + * + * Return a newly-allocated string. + */ +static +char *utils_partial_realpath(const char *path) +{ + char *cut_path = NULL, *try_path = NULL, *try_path_prev = NULL; + const char *next, *prev, *end; + char *resolved_path = NULL; + + /* Safety net */ + if (path == NULL) { + goto error; + } + + /* + * Identify the end of the path, we don't want to treat the + * last char if it is a '/', we will just keep it on the side + * to be added at the end, and return a value coherent with + * the path given as argument + */ + end = path + strlen(path); + if (*(end-1) == '/') { + end--; + } + + /* Initiate the values of the pointers before looping */ + next = path; + prev = next; + /* Only to ensure try_path is not NULL to enter the while */ + try_path = (char *)next; + + /* Resolve the canonical path of the first part of the path */ + while (try_path != NULL && next != end) { + char *try_path_buf = NULL; + + /* + * If there is not any '/' left, we want to try with + * the full path + */ + next = strpbrk(next + 1, "/"); + if (next == NULL) { + next = end; + } + + /* Cut the part we will be trying to resolve */ + cut_path = lttng_strndup(path, next - path); + if (cut_path == NULL) { + PERROR("lttng_strndup"); + goto error; + } + + try_path_buf = (char *) zmalloc(LTTNG_PATH_MAX); + if (!try_path_buf) { + PERROR("zmalloc"); + goto error; + } + + /* Try to resolve this part */ + try_path = realpath((char *) cut_path, try_path_buf); + if (try_path == NULL) { + free(try_path_buf); + /* + * There was an error, we just want to be assured it + * is linked to an unexistent directory, if it's another + * reason, we spawn an error + */ + switch (errno) { + case ENOENT: + /* Ignore the error */ + break; + default: + PERROR("realpath (partial_realpath)"); + goto error; + break; + } + } else { + /* Save the place we are before trying the next step */ + try_path_buf = NULL; + free(try_path_prev); + try_path_prev = try_path; + prev = next; + } + + /* Free the allocated memory */ + free(cut_path); + cut_path = NULL; + } + + /* Allocate memory for the resolved path. */ + resolved_path = (char *) zmalloc(LTTNG_PATH_MAX); + if (resolved_path == NULL) { + PERROR("zmalloc resolved path"); + goto error; + } + + /* + * If we were able to solve at least partially the path, we can concatenate + * what worked and what didn't work + */ + if (try_path_prev != NULL) { + /* If we risk to concatenate two '/', we remove one of them */ + if (try_path_prev[strlen(try_path_prev) - 1] == '/' && prev[0] == '/') { + try_path_prev[strlen(try_path_prev) - 1] = '\0'; + } + + /* + * Duplicate the memory used by prev in case resolved_path and + * path are pointers for the same memory space + */ + cut_path = strdup(prev); + if (cut_path == NULL) { + PERROR("strdup"); + goto error; + } + + /* Concatenate the strings */ + snprintf(resolved_path, LTTNG_PATH_MAX, "%s%s", + try_path_prev, cut_path); + + /* Free the allocated memory */ + free(cut_path); + free(try_path_prev); + cut_path = NULL; + try_path_prev = NULL; + /* + * Else, we just copy the path in our resolved_path to + * return it as is + */ + } else { + strncpy(resolved_path, path, LTTNG_PATH_MAX); + } + + /* Then we return the 'partially' resolved path */ + return resolved_path; + +error: + free(resolved_path); + free(cut_path); + free(try_path); + if (try_path_prev != try_path) { + free(try_path_prev); + } + return NULL; +} + +static +int expand_double_slashes_dot_and_dotdot(char *path) +{ + size_t expanded_path_len, path_len; + const char *curr_char, *path_last_char, *next_slash, *prev_slash; + + path_len = strlen(path); + path_last_char = &path[path_len]; + + if (path_len == 0) { + goto error; + } + + expanded_path_len = 0; + + /* We iterate over the provided path to expand the "//", "../" and "./" */ + for (curr_char = path; curr_char <= path_last_char; curr_char = next_slash + 1) { + /* Find the next forward slash. */ + size_t curr_token_len; + + if (curr_char == path_last_char) { + expanded_path_len++; + break; + } + + next_slash = (const char *) memchr(curr_char, '/', path_last_char - curr_char); + if (next_slash == NULL) { + /* Reached the end of the provided path. */ + next_slash = path_last_char; + } + + /* Compute how long is the previous token. */ + curr_token_len = next_slash - curr_char; + switch(curr_token_len) { + case 0: + /* + * The pointer has not move meaning that curr_char is + * pointing to a slash. It that case there is no token + * to copy, so continue the iteration to find the next + * token + */ + continue; + case 1: + /* + * The pointer moved 1 character. Check if that + * character is a dot ('.'), if it is: omit it, else + * copy the token to the normalized path. + */ + if (curr_char[0] == '.') { + continue; + } + break; + case 2: + /* + * The pointer moved 2 characters. Check if these + * characters are double dots ('..'). If that is the + * case, we need to remove the last token of the + * normalized path. + */ + if (curr_char[0] == '.' && curr_char[1] == '.') { + /* + * Find the previous path component by + * using the memrchr function to find the + * previous forward slash and substract that + * len to the resulting path. + */ + prev_slash = (const char *) lttng_memrchr(path, '/', expanded_path_len); + /* + * If prev_slash is NULL, we reached the + * beginning of the path. We can't go back any + * further. + */ + if (prev_slash != NULL) { + expanded_path_len = prev_slash - path; + } + continue; + } + break; + default: + break; + } + + /* + * Copy the current token which is neither a '.' nor a '..'. + */ + path[expanded_path_len++] = '/'; + memmove(&path[expanded_path_len], curr_char, curr_token_len); + expanded_path_len += curr_token_len; + } + + if (expanded_path_len == 0) { + path[expanded_path_len++] = '/'; + } + + path[expanded_path_len] = '\0'; + return 0; +error: + return -1; +} + +/* + * Make a full resolution of the given path even if it doesn't exist. + * This function uses the utils_partial_realpath function to resolve + * symlinks and relatives paths at the start of the string, and + * implements functionnalities to resolve the './' and '../' strings + * in the middle of a path. This function is only necessary because + * realpath(3) does not accept to resolve unexistent paths. + * The returned string was allocated in the function, it is thus of + * the responsibility of the caller to free this memory. + */ +static +char *_utils_expand_path(const char *path, bool keep_symlink) +{ + int ret; + char *absolute_path = NULL; + char *last_token; + bool is_dot, is_dotdot; + + /* Safety net */ + if (path == NULL) { + goto error; + } + + /* Allocate memory for the absolute_path */ + absolute_path = (char *) zmalloc(LTTNG_PATH_MAX); + if (absolute_path == NULL) { + PERROR("zmalloc expand path"); + goto error; + } + + if (path[0] == '/') { + ret = lttng_strncpy(absolute_path, path, LTTNG_PATH_MAX); + if (ret) { + ERR("Path exceeds maximal size of %i bytes", LTTNG_PATH_MAX); + goto error; + } + } else { + /* + * This is a relative path. We need to get the present working + * directory and start the path walk from there. + */ + char current_working_dir[LTTNG_PATH_MAX]; + char *cwd_ret; + + cwd_ret = getcwd(current_working_dir, sizeof(current_working_dir)); + if (!cwd_ret) { + goto error; + } + /* + * Get the number of character in the CWD and allocate an array + * to can hold it and the path provided by the caller. + */ + ret = snprintf(absolute_path, LTTNG_PATH_MAX, "%s/%s", + current_working_dir, path); + if (ret >= LTTNG_PATH_MAX) { + ERR("Concatenating current working directory %s and path %s exceeds maximal size of %i bytes", + current_working_dir, path, LTTNG_PATH_MAX); + goto error; + } + } + + if (keep_symlink) { + /* Resolve partially our path */ + char *new_absolute_path = utils_partial_realpath(absolute_path); + if (!new_absolute_path) { + goto error; + } + + free(absolute_path); + absolute_path = new_absolute_path; + } + + ret = expand_double_slashes_dot_and_dotdot(absolute_path); + if (ret) { + goto error; + } + + /* Identify the last token */ + last_token = strrchr(absolute_path, '/'); + + /* Verify that this token is not a relative path */ + is_dotdot = (strcmp(last_token, "/..") == 0); + is_dot = (strcmp(last_token, "/.") == 0); + + /* If it is, take action */ + if (is_dot || is_dotdot) { + /* For both, remove this token */ + *last_token = '\0'; + + /* If it was a reference to parent directory, go back one more time */ + if (is_dotdot) { + last_token = strrchr(absolute_path, '/'); + + /* If there was only one level left, we keep the first '/' */ + if (last_token == absolute_path) { + last_token++; + } + + *last_token = '\0'; + } + } + + return absolute_path; + +error: + free(absolute_path); + return NULL; +} +char *utils_expand_path(const char *path) +{ + return _utils_expand_path(path, true); +} + +char *utils_expand_path_keep_symlink(const char *path) +{ + return _utils_expand_path(path, false); +} diff --git a/src/common/path.h b/src/common/path.h new file mode 100644 index 000000000..3f81eeb20 --- /dev/null +++ b/src/common/path.h @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2021 Mathieu Desnoyers + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#ifndef _COMMON_PATH_H +#define _COMMON_PATH_H + +char *utils_expand_path(const char *path); +char *utils_expand_path_keep_symlink(const char *path); + +#endif /* _COMMON_PATH_H */ diff --git a/src/common/utils.c b/src/common/utils.c index 76185c11e..4295a584a 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -1,6 +1,5 @@ /* * Copyright (C) 2012 David Goulet - * Copyright (C) 2013 Raphaël Beamonte * Copyright (C) 2013 Jérémie Galarneau * * SPDX-License-Identifier: GPL-2.0-only @@ -54,377 +53,6 @@ #define FALLBACK_USER_BUFLEN 16384 #define FALLBACK_GROUP_BUFLEN 16384 -/* - * Return a partial realpath(3) of the path even if the full path does not - * exist. For instance, with /tmp/test1/test2/test3, if test2/ does not exist - * but the /tmp/test1 does, the real path for /tmp/test1 is concatened with - * /test2/test3 then returned. In normal time, realpath(3) fails if the end - * point directory does not exist. - * - * Return a newly-allocated string. - */ -static -char *utils_partial_realpath(const char *path) -{ - char *cut_path = NULL, *try_path = NULL, *try_path_prev = NULL; - const char *next, *prev, *end; - char *resolved_path = NULL; - - /* Safety net */ - if (path == NULL) { - goto error; - } - - /* - * Identify the end of the path, we don't want to treat the - * last char if it is a '/', we will just keep it on the side - * to be added at the end, and return a value coherent with - * the path given as argument - */ - end = path + strlen(path); - if (*(end-1) == '/') { - end--; - } - - /* Initiate the values of the pointers before looping */ - next = path; - prev = next; - /* Only to ensure try_path is not NULL to enter the while */ - try_path = (char *)next; - - /* Resolve the canonical path of the first part of the path */ - while (try_path != NULL && next != end) { - char *try_path_buf = NULL; - - /* - * If there is not any '/' left, we want to try with - * the full path - */ - next = strpbrk(next + 1, "/"); - if (next == NULL) { - next = end; - } - - /* Cut the part we will be trying to resolve */ - cut_path = lttng_strndup(path, next - path); - if (cut_path == NULL) { - PERROR("lttng_strndup"); - goto error; - } - - try_path_buf = zmalloc(LTTNG_PATH_MAX); - if (!try_path_buf) { - PERROR("zmalloc"); - goto error; - } - - /* Try to resolve this part */ - try_path = realpath((char *) cut_path, try_path_buf); - if (try_path == NULL) { - free(try_path_buf); - /* - * There was an error, we just want to be assured it - * is linked to an unexistent directory, if it's another - * reason, we spawn an error - */ - switch (errno) { - case ENOENT: - /* Ignore the error */ - break; - default: - PERROR("realpath (partial_realpath)"); - goto error; - break; - } - } else { - /* Save the place we are before trying the next step */ - try_path_buf = NULL; - free(try_path_prev); - try_path_prev = try_path; - prev = next; - } - - /* Free the allocated memory */ - free(cut_path); - cut_path = NULL; - } - - /* Allocate memory for the resolved path. */ - resolved_path = zmalloc(LTTNG_PATH_MAX); - if (resolved_path == NULL) { - PERROR("zmalloc resolved path"); - goto error; - } - - /* - * If we were able to solve at least partially the path, we can concatenate - * what worked and what didn't work - */ - if (try_path_prev != NULL) { - /* If we risk to concatenate two '/', we remove one of them */ - if (try_path_prev[strlen(try_path_prev) - 1] == '/' && prev[0] == '/') { - try_path_prev[strlen(try_path_prev) - 1] = '\0'; - } - - /* - * Duplicate the memory used by prev in case resolved_path and - * path are pointers for the same memory space - */ - cut_path = strdup(prev); - if (cut_path == NULL) { - PERROR("strdup"); - goto error; - } - - /* Concatenate the strings */ - snprintf(resolved_path, LTTNG_PATH_MAX, "%s%s", - try_path_prev, cut_path); - - /* Free the allocated memory */ - free(cut_path); - free(try_path_prev); - cut_path = NULL; - try_path_prev = NULL; - /* - * Else, we just copy the path in our resolved_path to - * return it as is - */ - } else { - strncpy(resolved_path, path, LTTNG_PATH_MAX); - } - - /* Then we return the 'partially' resolved path */ - return resolved_path; - -error: - free(resolved_path); - free(cut_path); - free(try_path); - if (try_path_prev != try_path) { - free(try_path_prev); - } - return NULL; -} - -static -int expand_double_slashes_dot_and_dotdot(char *path) -{ - size_t expanded_path_len, path_len; - const char *curr_char, *path_last_char, *next_slash, *prev_slash; - - path_len = strlen(path); - path_last_char = &path[path_len]; - - if (path_len == 0) { - goto error; - } - - expanded_path_len = 0; - - /* We iterate over the provided path to expand the "//", "../" and "./" */ - for (curr_char = path; curr_char <= path_last_char; curr_char = next_slash + 1) { - /* Find the next forward slash. */ - size_t curr_token_len; - - if (curr_char == path_last_char) { - expanded_path_len++; - break; - } - - next_slash = memchr(curr_char, '/', path_last_char - curr_char); - if (next_slash == NULL) { - /* Reached the end of the provided path. */ - next_slash = path_last_char; - } - - /* Compute how long is the previous token. */ - curr_token_len = next_slash - curr_char; - switch(curr_token_len) { - case 0: - /* - * The pointer has not move meaning that curr_char is - * pointing to a slash. It that case there is no token - * to copy, so continue the iteration to find the next - * token - */ - continue; - case 1: - /* - * The pointer moved 1 character. Check if that - * character is a dot ('.'), if it is: omit it, else - * copy the token to the normalized path. - */ - if (curr_char[0] == '.') { - continue; - } - break; - case 2: - /* - * The pointer moved 2 characters. Check if these - * characters are double dots ('..'). If that is the - * case, we need to remove the last token of the - * normalized path. - */ - if (curr_char[0] == '.' && curr_char[1] == '.') { - /* - * Find the previous path component by - * using the memrchr function to find the - * previous forward slash and substract that - * len to the resulting path. - */ - prev_slash = lttng_memrchr(path, '/', expanded_path_len); - /* - * If prev_slash is NULL, we reached the - * beginning of the path. We can't go back any - * further. - */ - if (prev_slash != NULL) { - expanded_path_len = prev_slash - path; - } - continue; - } - break; - default: - break; - } - - /* - * Copy the current token which is neither a '.' nor a '..'. - */ - path[expanded_path_len++] = '/'; - memmove(&path[expanded_path_len], curr_char, curr_token_len); - expanded_path_len += curr_token_len; - } - - if (expanded_path_len == 0) { - path[expanded_path_len++] = '/'; - } - - path[expanded_path_len] = '\0'; - return 0; -error: - return -1; -} - -/* - * Make a full resolution of the given path even if it doesn't exist. - * This function uses the utils_partial_realpath function to resolve - * symlinks and relatives paths at the start of the string, and - * implements functionnalities to resolve the './' and '../' strings - * in the middle of a path. This function is only necessary because - * realpath(3) does not accept to resolve unexistent paths. - * The returned string was allocated in the function, it is thus of - * the responsibility of the caller to free this memory. - */ -static -char *_utils_expand_path(const char *path, bool keep_symlink) -{ - int ret; - char *absolute_path = NULL; - char *last_token; - bool is_dot, is_dotdot; - - /* Safety net */ - if (path == NULL) { - goto error; - } - - /* Allocate memory for the absolute_path */ - absolute_path = zmalloc(LTTNG_PATH_MAX); - if (absolute_path == NULL) { - PERROR("zmalloc expand path"); - goto error; - } - - if (path[0] == '/') { - ret = lttng_strncpy(absolute_path, path, LTTNG_PATH_MAX); - if (ret) { - ERR("Path exceeds maximal size of %i bytes", LTTNG_PATH_MAX); - goto error; - } - } else { - /* - * This is a relative path. We need to get the present working - * directory and start the path walk from there. - */ - char current_working_dir[LTTNG_PATH_MAX]; - char *cwd_ret; - - cwd_ret = getcwd(current_working_dir, sizeof(current_working_dir)); - if (!cwd_ret) { - goto error; - } - /* - * Get the number of character in the CWD and allocate an array - * to can hold it and the path provided by the caller. - */ - ret = snprintf(absolute_path, LTTNG_PATH_MAX, "%s/%s", - current_working_dir, path); - if (ret >= LTTNG_PATH_MAX) { - ERR("Concatenating current working directory %s and path %s exceeds maximal size of %i bytes", - current_working_dir, path, LTTNG_PATH_MAX); - goto error; - } - } - - if (keep_symlink) { - /* Resolve partially our path */ - char *new_absolute_path = utils_partial_realpath(absolute_path); - if (!new_absolute_path) { - goto error; - } - - free(absolute_path); - absolute_path = new_absolute_path; - } - - ret = expand_double_slashes_dot_and_dotdot(absolute_path); - if (ret) { - goto error; - } - - /* Identify the last token */ - last_token = strrchr(absolute_path, '/'); - - /* Verify that this token is not a relative path */ - is_dotdot = (strcmp(last_token, "/..") == 0); - is_dot = (strcmp(last_token, "/.") == 0); - - /* If it is, take action */ - if (is_dot || is_dotdot) { - /* For both, remove this token */ - *last_token = '\0'; - - /* If it was a reference to parent directory, go back one more time */ - if (is_dotdot) { - last_token = strrchr(absolute_path, '/'); - - /* If there was only one level left, we keep the first '/' */ - if (last_token == absolute_path) { - last_token++; - } - - *last_token = '\0'; - } - } - - return absolute_path; - -error: - free(absolute_path); - return NULL; -} -LTTNG_HIDDEN -char *utils_expand_path(const char *path) -{ - return _utils_expand_path(path, true); -} - -LTTNG_HIDDEN -char *utils_expand_path_keep_symlink(const char *path) -{ - return _utils_expand_path(path, false); -} /* * Create a pipe in dst. */ diff --git a/src/common/utils.h b/src/common/utils.h index 18722f9f2..9544eba37 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -21,8 +21,6 @@ #define MEBI_LOG2 20 #define GIBI_LOG2 30 -char *utils_expand_path(const char *path); -char *utils_expand_path_keep_symlink(const char *path); int utils_create_pipe(int *dst); int utils_create_pipe_cloexec(int *dst); int utils_create_pipe_cloexec_nonblock(int *dst); diff --git a/tests/unit/ini_config/ini_config.c b/tests/unit/ini_config/ini_config.c index a16d1b9e8..a17e3ef9d 100644 --- a/tests/unit/ini_config/ini_config.c +++ b/tests/unit/ini_config/ini_config.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include diff --git a/tests/unit/test_utils_expand_path.c b/tests/unit/test_utils_expand_path.c index d7e7f2b05..30fceeb8a 100644 --- a/tests/unit/test_utils_expand_path.c +++ b/tests/unit/test_utils_expand_path.c @@ -17,6 +17,7 @@ #include #include +#include #include /* For error.h */ -- 2.34.1