Mirror of the lttng-dev mailing list
 help / color / mirror / Atom feed
From: raphael.beamonte@gmail.com (Raphaël Beamonte)
Subject: [lttng-dev] [lttng-tools PATCH 3/5] Introduce a new utils_partial_realpath function
Date: Thu, 14 Nov 2013 19:58:33 -0500	[thread overview]
Message-ID: <1384477115-18809-4-git-send-email-raphael.beamonte@gmail.com> (raw)
In-Reply-To: <1384477115-18809-1-git-send-email-raphael.beamonte@gmail.com>

This new utils function allows to resolve partially the paths
using realpath. As realpath(3) is not available to use for
unexistent paths, this function that allows to resolve partially
existent paths can be used in cases we don't know if the path
fully exists. It first resolves the existent part using
realpath(3) and then concatenate the unexistent part to it.

Signed-off-by: Rapha?l Beamonte <raphael.beamonte at gmail.com>
---
 src/common/utils.c |  128 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/common/utils.h |    2 +
 2 files changed, 130 insertions(+)

diff --git a/src/common/utils.c b/src/common/utils.c
index 6938a5a..57add31 100644
--- a/src/common/utils.c
+++ b/src/common/utils.c
@@ -36,6 +36,134 @@
 #include "defaults.h"
 
 /*
+ * 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.
+ * In case resolved_path is NULL, the string returned was allocated in the
+ * function and thus need to be freed by the caller. The size argument allows
+ * to specify the size of the resolved_path argument if given, or the size to
+ * allocate.
+ */
+LTTNG_HIDDEN
+char *utils_partial_realpath(const char *path, char *resolved_path, size_t size)
+{
+	char *cut_path, *try_path = NULL, *try_path_prev = NULL;
+	const char *next, *prev, *end;
+
+	/* 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) {
+		/*
+		 * 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 = strndup(path, next - path);
+
+		/* Try to resolve this part */
+		try_path = realpath((char *)cut_path, NULL);
+		if (try_path == NULL) {
+			/*
+			 * 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 */
+			free(try_path_prev);
+			try_path_prev = try_path;
+			prev = next;
+		}
+
+		/* Free the allocated memory */
+		free(cut_path);
+	};
+
+	/* Allocate memory for the resolved path if necessary */
+	if (resolved_path == NULL) {
+		resolved_path = zmalloc(size);
+		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);
+
+		/* Concatenate the strings */
+		snprintf(resolved_path, size, "%s%s", try_path_prev, cut_path);
+
+		/* Free the allocated memory */
+		free(cut_path);
+		free(try_path_prev);
+	/*
+	 * Else, we just copy the path in our resolved_path to
+	 * return it as is
+	 */
+	} else {
+		strncpy(resolved_path, path, size);
+	}
+
+	/* Then we return the 'partially' resolved path */
+	return resolved_path;
+
+error:
+	free(resolved_path);
+	return NULL;
+}
+
+/*
  * 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
diff --git a/src/common/utils.h b/src/common/utils.h
index c56942f..036e416 100644
--- a/src/common/utils.h
+++ b/src/common/utils.h
@@ -27,6 +27,8 @@
 #define GIBI_LOG2 30
 
 char *utils_resolve_relative(const char *path);
+char *utils_partial_realpath(const char *path, char *resolved_path,
+		size_t size);
 char *utils_expand_path(const char *path);
 int utils_create_pipe(int *dst);
 int utils_create_pipe_cloexec(int *dst);
-- 
1.7.10.4




  parent reply	other threads:[~2013-11-15  0:58 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-11-08  4:32 [lttng-dev] [lttng-tools PATCH 0/2] utils_expand_path as realpath(3) for non-existing directories Raphaël Beamonte
2013-11-08  4:32 ` [lttng-dev] [lttng-tools PATCH 1/2] Introduce a new utils_resolve_relative function Raphaël Beamonte
2013-11-12 19:51   ` David Goulet
2013-11-13  5:34     ` [lttng-dev] [lttng-tools PATCH 0/4] Update to utils_expand_path as realpath(3) for non-existing directories Raphaël Beamonte
2013-11-13  5:34       ` [lttng-dev] [lttng-tools PATCH 1/4] Introduce a new utils_resolve_relative function Raphaël Beamonte
2013-11-14 14:19         ` Mathieu Desnoyers
2013-11-14 17:07           ` Raphaël Beamonte
2013-11-13  5:34       ` [lttng-dev] [lttng-tools PATCH 2/4] Tests: Add test_utils_resolve_relative to unit tests Raphaël Beamonte
2013-11-13  5:34       ` [lttng-dev] [lttng-tools PATCH 3/4] Correct the behavior of the utils_expand_path function Raphaël Beamonte
2013-11-14  2:44         ` Mathieu Desnoyers
2013-11-14  3:27           ` Raphaël Beamonte
2013-11-14 13:46             ` Mathieu Desnoyers
2013-11-14 14:10         ` Mathieu Desnoyers
2013-11-14 16:00           ` Raphaël Beamonte
2013-11-14 16:14             ` Mathieu Desnoyers
2013-11-15  0:58               ` [lttng-dev] [lttng-tools PATCH 0/5] Follow up to the realpath(3) for unexistent paths Raphaël Beamonte
2013-11-15  0:58                 ` [lttng-dev] [lttng-tools PATCH 1/5] Tests: add a check in test_utils_expand_path to avoid segfault if result is NULL Raphaël Beamonte
2013-11-15  0:58                 ` [lttng-dev] [lttng-tools PATCH 2/5] Tests: move invalid tests in test_utils_expand_path that should be valid Raphaël Beamonte
2013-11-15  0:58                 ` Raphaël Beamonte [this message]
2013-11-15  0:58                 ` [lttng-dev] [lttng-tools PATCH 4/5] Change the utils_expand_path function to use utils_partial_realpath Raphaël Beamonte
2013-11-15  0:58                 ` [lttng-dev] [lttng-tools PATCH 5/5] Remove the utils_resolve_relative function that is not useful anymore Raphaël Beamonte
2013-11-15 15:45                 ` [lttng-dev] [lttng-tools PATCH 0/5] Follow up to the realpath(3) for unexistent paths David Goulet
2013-11-23 22:32                   ` [lttng-dev] [lttng-tools PATCH 0/5] utils_expand_path fix Raphaël Beamonte
2013-11-23 22:32                     ` [lttng-dev] [lttng-tools PATCH 1/5] Add missing copyright to utils.c Raphaël Beamonte
2013-11-23 22:32                     ` [lttng-dev] [lttng-tools PATCH 2/5] Fix: comment indentation Raphaël Beamonte
2013-11-23 22:32                     ` [lttng-dev] [lttng-tools PATCH 3/5] Fix: utils_expand_path now works for paths that ends with '/.' or '/..' Raphaël Beamonte
2013-11-23 22:32                     ` [lttng-dev] [lttng-tools PATCH 4/5] Tests: add symlink tests for test_utils_expand_path Raphaël Beamonte
2013-11-23 22:32                     ` [lttng-dev] [lttng-tools PATCH 5/5] Tests: add valid test cases to test_utils_expand_path Raphaël Beamonte
2013-11-25 15:51                     ` [lttng-dev] [lttng-tools PATCH 0/5] utils_expand_path fix David Goulet
2013-11-13  5:34       ` [lttng-dev] [lttng-tools PATCH 4/4] Tests: Add test_utils_expand_path to unit tests Raphaël Beamonte
2013-11-13 21:28       ` [lttng-dev] [lttng-tools PATCH 0/4] Update to utils_expand_path as realpath(3) for non-existing directories David Goulet
2013-11-08  4:32 ` [lttng-dev] [lttng-tools PATCH 2/2] Correct the behavior of the utils_expand_path function Raphaël Beamonte

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1384477115-18809-4-git-send-email-raphael.beamonte@gmail.com \
    --to=raphael.beamonte@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox