[lttng-dev] [lttng-tools PATCH 2/2] Correct the behavior of the utils_expand_path function
Raphaël Beamonte
raphael.beamonte at gmail.com
Thu Nov 7 23:32:14 EST 2013
Even if the utils_expand_path function was intended to allow to
use unexistent directory paths, it was in fact only working for
some kind of arguments. Paths like "foo", "bar/" or "bar/foo"
when the "bar" directory does not exist wasn't working. This
patch introduce a new way to expand paths in this function that
also works properly for these kind of arguments.
Signed-off-by: Raphaël Beamonte <raphael.beamonte at gmail.com>
---
src/common/utils.c | 72 +++++++++++++++++++++++++++++++++++++---------------
1 file changed, 51 insertions(+), 21 deletions(-)
diff --git a/src/common/utils.c b/src/common/utils.c
index 7b52760..b68f12e 100644
--- a/src/common/utils.c
+++ b/src/common/utils.c
@@ -92,7 +92,7 @@ int utils_resolve_relative(char *path)
LTTNG_HIDDEN
char *utils_expand_path(const char *path)
{
- const char *end_path = path;
+ const char *end_path = NULL;
char *next, *cut_path = NULL, *expanded_path = NULL;
/* Safety net */
@@ -100,35 +100,65 @@ char *utils_expand_path(const char *path)
goto error;
}
- /* Find last token delimited by '/' */
- while ((next = strpbrk(end_path + 1, "/"))) {
- end_path = next;
- }
-
- /* Cut last token from original path */
- cut_path = strndup(path, end_path - path);
-
+ /* Allocate memory for the expanded path */
expanded_path = zmalloc(PATH_MAX);
if (expanded_path == NULL) {
PERROR("zmalloc expand path");
goto error;
}
- expanded_path = realpath((char *)cut_path, expanded_path);
- if (expanded_path == NULL) {
- switch (errno) {
- case ENOENT:
- ERR("%s: No such file or directory", cut_path);
- break;
- default:
- PERROR("realpath utils expand path");
- break;
+ /* If given path is already absolute */
+ if (*path == '/') {
+ strncpy(expanded_path, path, PATH_MAX);
+ /* Else, we have some work to do */
+ } else {
+ /* Pointer to the last char of the path */
+ const char *last_char = path+strlen(path)-1;
+
+ end_path = path;
+ /* If the path is just a directory name */
+ if (strchr(path, '/') == NULL || strchr(path, '/') == last_char) {
+ cut_path = strdup(".");
+ /* Else, we have to analyse the full path */
+ } else {
+ /* Split part that will be resolved by realpath (relative path from
+ * current directory using ./ or ../ only) and part that could not
+ * (directory names)
+ */
+ while ((next = strpbrk(end_path, "/")) && (next != last_char)) {
+ end_path = next + 1;
+ if (strncmp(end_path, "./", 2) != 0 && strncmp(end_path, "../", 3) != 0) {
+ break;
+ }
+ }
+
+ /* Cut last token from original path */
+ cut_path = strndup(path, end_path - path);
}
- goto error;
+
+ /* Resolve the canonical path of the first part of the path */
+ expanded_path = realpath((char *)cut_path, expanded_path);
+ if (expanded_path == NULL) {
+ switch (errno) {
+ case ENOENT:
+ ERR("%s: No such file or directory", cut_path);
+ break;
+ default:
+ PERROR("realpath utils expand path");
+ break;
+ }
+ goto error;
+ }
+
+ /* Add end part to expanded path */
+ strncat(expanded_path, "/", PATH_MAX - strlen(expanded_path) - 1);
+ strncat(expanded_path, end_path, PATH_MAX - strlen(expanded_path) - 1);
}
- /* Add end part to expanded path */
- strncat(expanded_path, end_path, PATH_MAX - strlen(expanded_path) - 1);
+ /* Resolve the internal './' and '../' strings */
+ if (utils_resolve_relative(expanded_path) != 0) {
+ goto error;
+ }
free(cut_path);
return expanded_path;
--
1.7.10.4
More information about the lttng-dev
mailing list