Mercurial > hg > toybox
diff lib/lib.c @ 707:977e19296b3f
Update readlink so -f works. Add -menq while there.
author | Rob Landley <rob@landley.net> |
---|---|
date | Tue, 20 Nov 2012 09:21:52 -0600 |
parents | 078138791b5c |
children | 50d759f8b371 |
line wrap: on
line diff
--- a/lib/lib.c Tue Nov 20 01:00:17 2012 -0600 +++ b/lib/lib.c Tue Nov 20 09:21:52 2012 -0600 @@ -323,52 +323,37 @@ if(stat(path, st)) perror_exit("Can't stat %s", path); } -// Cannonicalizes path by removing ".", "..", and "//" elements. This is not -// the same as realpath(), where "dir/.." could wind up somewhere else by -// following symlinks. -char *xabspath(char *path) +// Cannonicalize path, even to file with one or more missing components at end +char *xabspath(char *path, unsigned missing) { - char *from, *to; + char *apath, *temp, *slash; + int i=0; // If this isn't an absolute path, make it one with cwd. if (path[0]!='/') { - char *cwd=xgetcwd(); - path = xmsprintf("%s/%s", cwd, path); - free(cwd); - } else path = xstrdup(path); - - // Loop through path elements - from = to = path; - while (*from) { - - // Continue any current path component. - if (*from!='/') { - *(to++) = *(from++); - continue; - } - - // Skip duplicate slashes. - while (*from=='/') from++; + char *temp=xgetcwd(); + apath = xmsprintf("%s/%s", temp, path); + free(temp); + } else apath = path; + slash = apath+strlen(apath); - // Start of a new filename. Handle . and .. - while (*from=='.') { - // Skip . - if (from[1]=='/') from += 2; - else if (!from[1]) from++; - // Back up for .. - else if (from[1]=='.') { - if (from[2]=='/') from +=3; - else if(!from[2]) from+=2; - else break; - while (to>path && *(--to)!='/'); - } else break; - } - // Add directory separator slash. - *(to++) = '/'; + for (;;) { + temp = realpath(apath, NULL); + if (i) *slash = '/'; + if (temp || ++i > missing) break; + while (slash>apath) if (*--slash == '/') break; + *slash=0; + free(temp); } - *to = 0; - return path; + if (i && temp) { + slash = xmsprintf("%s%s", temp, slash); + free(temp); + temp = slash; + } + + if (path != apath) free(apath); + return temp; } // Resolve all symlinks, returning malloc() memory.