denys wrote:
 > 
 > Thus I propose introducing xmalloc_readlink_recursive()
 > which does not suffer from those two problems,
 > and using it here (and elsewhere: insmod, syslogd -
 > grep for xmalloc_readlink).

well, i've written a new version, but it doesn't do what you
thought it was going to.  :-)

realpath() fully canonicalizes a path -- it makes it absolute,
removes "/..", and expands symlinks all along the path.

readlink() (and also xmalloc_readlink()) simply returns the value
of the named symlink.  (which makes the switch from realpath()
to xmalloc_readlink() somewhat suspicious, by the way.)

i've written xmalloc_readlink_follow(char *path) which iteratively
does textual expansion of path, expanding symlinks at the tail end
of path.  no other canonicalization is done, and the result is not
necessarily absolute.  this is the minimum needed for my "allow
/etc/passwd to be a symlink" change, and it's probably useful for
most of the other current uses of xmalloc_readlink().

paul

/*
 * 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);
                }
        }

}


=---------------------
 paul fox, [EMAIL PROTECTED]
_______________________________________________
busybox mailing list
busybox@busybox.net
http://busybox.net/cgi-bin/mailman/listinfo/busybox

Reply via email to