new xmalloc_readlink_follow() routine to fully expand trailing symlinks

to get to a "real" file (or directory).
This commit is contained in:
Paul Fox 2007-11-08 01:11:41 +00:00
parent 49cce2b838
commit 459a2ba1ef
2 changed files with 46 additions and 0 deletions

View File

@ -260,6 +260,7 @@ DIR *warn_opendir(const char *path);
/* UNUSED: char *xmalloc_realpath(const char *path); */
char *xmalloc_readlink(const char *path);
char *xmalloc_readlink_follow(const char *path);
char *xmalloc_readlink_or_warn(const char *path);
char *xrealloc_getcwd_or_warn(char *cwd);

View File

@ -32,6 +32,51 @@ char *xmalloc_readlink(const char *path)
return buf;
}
/*
* this routine is not the same as realpath(), which canonicalizes
* the given path completely. this routine only follows trailing
* symlinks until a real file is reached, and returns its name.
* intermediate symlinks are not expanded. as above, a malloced
* char* is returned, which must be freed.
*/
char *xmalloc_readlink_follow(const char *path)
{
char *buf = NULL, *lpc, *linkpath;
int bufsize;
smallint looping = 0;
buf = strdup(path);
bufsize = strlen(path) + 1;
while(1) {
linkpath = xmalloc_readlink(buf);
if (!linkpath) {
if (errno == EINVAL) /* not a symlink */
return buf;
free(buf);
return NULL;
}
if (*linkpath == '/') {
free(buf);
buf = linkpath;
bufsize = strlen(linkpath) + 1;
} else {
bufsize += strlen(linkpath);
if (looping++ > MAXSYMLINKS) {
free(linkpath);
free(buf);
return NULL;
}
buf = xrealloc(buf, bufsize);
lpc = bb_get_last_path_component_strip(buf);
strcpy(lpc, linkpath);
free(linkpath);
}
}
}
char *xmalloc_readlink_or_warn(const char *path)
{
char *buf = xmalloc_readlink(path);