[PATCH 1/2] add realpathm() to libutil

From: Brad Barden <brad_AT_13os.net>
Date: Fri, 20 Nov 2015 13:54:43 -0600

---
 Makefile            |   1 +
 libutil/realpathm.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 104 insertions(+)
 create mode 100644 libutil/realpathm.c
diff --git a/Makefile b/Makefile
index c2d8266..c4ca41d 100644
--- a/Makefile
+++ b/Makefile
_AT_@ -59,6 +59,7 @@ LIBUTILSRC =\
 	libutil/parseoffset.c\
 	libutil/putword.c\
 	libutil/reallocarray.c\
+	libutil/realpathm.c\
 	libutil/recurse.c\
 	libutil/rm.c\
 	libutil/sha1.c\
diff --git a/libutil/realpathm.c b/libutil/realpathm.c
new file mode 100644
index 0000000..7636383
--- /dev/null
+++ b/libutil/realpathm.c
_AT_@ -0,0 +1,103 @@
+/* See LICENSE file for copyright and license details. */
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../util.h"
+
+char *
+realpathm(const char * path, char * resolvedpath) {
+	const char *p = path;
+	char buf1[PATH_MAX] = {0}, buf2[PATH_MAX] = {0},
+			 *a = buf1, *b = buf2, *ret = NULL;
+	int i = 0, m = 0;
+
+	if (!p)
+		errno = EINVAL;
+		goto badpath;
+
+	if (!*p) {
+		errno = ENOENT;
+		goto badpath;
+	}
+
+	if (strnlen(path, PATH_MAX) == PATH_MAX) {
+		errno = ENAMETOOLONG;
+		goto badpath;
+	}
+
+	if (*p == '/') {
+		p++;
+	} else { 
+		if (!realpath(".", a)) {
+			goto badpath;
+		}
+	}
+	strcat(a, "/");
+
+	while (*p) {
+		i = strlen(a);
+		while (*p && *p != '/') {
+			if (i >= PATH_MAX) {
+				errno = ENAMETOOLONG;
+				goto badpath;
+			}
+			a[i++] = *p++;
+		}
+		a[i] = '\0';
+		if (*p)
+			++p;
+		if (i > 2 && !strcmp(&a[i-3], "/..")) {
+			if (m)
+				--m;
+			if (i == 3) {
+				strcpy(a, "/");
+				i = 1;
+			}
+			else {
+				i -= 3;
+				while (i > 0 && a[--i] != '/') ;
+				a[i] = '\0';
+			}
+		} else if (i > 1 && !strcmp(&a[i-2], "/.")) {
+			if (i == 2) {
+				strcpy(a, "/");
+				i = 1;
+			} else {
+				i -= 2;
+				a[i] = '\0';
+			}
+		} else if (a[i] == '/') {
+			if (i > 1)
+				a[--i] = '\0';
+		} else if (m) {
+				++m;
+		} else if (!realpath(a, b)) {
+			if (errno == ENOENT) {
+				m = 1;
+			} else {
+				goto badpath;
+			}
+		} else if (a == buf1) {
+			a = buf2;
+			b = buf1;
+		} else {
+			a = buf1;
+			b = buf2;
+		}
+		if (*p && a[i-1] != '/' && strlcat(a, "/", PATH_MAX) >= PATH_MAX) {
+			errno = ENAMETOOLONG;
+			goto badpath;
+		}
+	}
+	i = strlen(a)-1;
+	if (a[i] == '/')
+		a[i] = '\0';
+	if (!(ret = resolvedpath))
+		ret = emalloc(PATH_MAX);
+	estrlcpy(ret, a, PATH_MAX);
+
+badpath:
+	return ret;
+}
-- 
2.3.6
--dkEUBIird37B8yKS
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment; filename="0002-restore-readlink-e-and-m-flags-add-realpath.patch"
Received on Mon Sep 17 2001 - 00:00:00 CEST

This archive was generated by hypermail 2.3.0 : Sat Nov 21 2015 - 10:00:11 CET