From 08962d40c076e0343af724db6243c81cff2c7c25 Mon Sep 17 00:00:00 2001 From: Judd Vinet Date: Fri, 19 Aug 2005 22:41:20 +0000 Subject: Imported from pacman-2.9.7-TEST.tar.gz --- src/util.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) (limited to 'src/util.c') 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) -- cgit v1.2.3-24-g4f1b