summaryrefslogtreecommitdiffstats
path: root/src/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.c')
-rw-r--r--src/util.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/src/util.c b/src/util.c
index 08241691..b68b71f2 100644
--- a/src/util.c
+++ b/src/util.c
@@ -219,6 +219,103 @@ int rmrf(char *path)
return(0);
}
+/* Convert a relative path to an absolute path
+ *
+ * This function was taken from the pathconvert library and massaged
+ * to match our coding style. The pathconvert version is
+ * Copyright (c) 1997 Shigio Yamaguchi.
+ */
+char *rel2abs(const char *path, char *result, const size_t size)
+{
+ const char *pp, *bp;
+ /* endp points the last position which is safe in the result buffer. */
+ const char *endp = result + size - 1;
+ char *rp;
+ int length;
+ char base[PATH_MAX+1];
+
+ getcwd(base, PATH_MAX);
+
+ if(*path == '/') {
+ if(strlen(path) >= size) {
+ goto erange;
+ }
+ strcpy(result, path);
+ goto finish;
+ } else if(*base != '/' || !size) {
+ errno = EINVAL;
+ return (NULL);
+ } else if(size == 1) {
+ goto erange;
+ }
+
+ length = strlen(base);
+
+ if(!strcmp(path, ".") || !strcmp(path, "./")) {
+ if(length >= size) {
+ goto erange;
+ }
+ strcpy(result, base);
+ /* rp points the last char. */
+ rp = result + length - 1;
+ /* remove the last '/'. */
+ if(*rp == '/') {
+ if(length > 1) {
+ *rp = 0;
+ }
+ } else {
+ rp++;
+ }
+ /* rp point NULL char */
+ if(*++path == '/') {
+ /* Append '/' to the tail of path name. */
+ *rp++ = '/';
+ if(rp > endp) {
+ goto erange;
+ }
+ *rp = 0;
+ }
+ goto finish;
+ }
+ bp = base + length;
+ if(*(bp - 1) == '/') {
+ --bp;
+ }
+ /* up to root. */
+ for(pp = path; *pp && *pp == '.'; ) {
+ if(!strncmp(pp, "../", 3)) {
+ pp += 3;
+ while(bp > base && *--bp != '/');
+ } else if(!strncmp(pp, "./", 2)) {
+ pp += 2;
+ } else if(!strncmp(pp, "..\0", 3)) {
+ pp += 2;
+ while(bp > base && *--bp != '/');
+ } else {
+ break;
+ }
+ }
+ /* down to leaf. */
+ length = bp - base;
+ if(length >= size) {
+ goto erange;
+ }
+ strncpy(result, base, length);
+ rp = result + length;
+ if(*pp || *(pp - 1) == '/' || length == 0) {
+ *rp++ = '/';
+ }
+ if(rp + strlen(pp) > endp) {
+ goto erange;
+ }
+ strcpy(rp, pp);
+finish:
+ return result;
+erange:
+ errno = ERANGE;
+ return (NULL);
+}
+
/* output a string, but wrap words properly with a specified indentation
*/
void indentprint(char *str, int indent)