i wrote:
 > ralf wrote:
 >  > Another question is what the function should do if the target of the 
 >  > link does not exist. xmalloc_readlink will always return the target 
 >  > name, whether it exists or not. I don't know whether this behavior would 
 >  > be useful for xmalloc_readlink_follow or not.
 > 
 > they should probably be consistent.  i can't picture a case where it
 > wouldn't be okay to return a dangling linkname.  i'll fix this too.

the new version is below.

there are two more behaviors that that we should be sure we agree
on.  these are, what to do if the pathname doesn't exist, and
what to do if it's a real file.

here are some test results, using the new code shown below:

$ ls -l tmp
total 1
lrwxrwxrwx 1 pgf users 7 Nov  8 11:03 dangling -> no-file
-rw-rw-r-- 1 pgf users 0 Nov  8 11:03 existingfile
lrwxrwxrwx 1 pgf users 6 Nov  8 11:02 foobar -> foobar

$ ./busybox testreadlink tmp/dangling
xmalloc_readlink returns no-file
xmalloc_readlink_follow returns tmp/no-file

$ ./busybox testreadlink tmp/existingfile
xmalloc_readlink returns (null)
xmalloc_readlink_follow returns tmp/existingfile

$ ./busybox testreadlink tmp/foobar
xmalloc_readlink returns foobar
xmalloc_readlink_follow returns (null)

$ ./busybox testreadlink tmp/non-existingfile
xmalloc_readlink returns (null)
xmalloc_readlink_follow returns tmp/non-existingfile


this seems like the right behavior to me.  however, the semantics
are different enough between the two that maybe the new routine
should have a different name.  xmalloc_follow_symlinks(), perhaps.

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.  if the path ends in a dangling link, or if
 * the target doesn't exist, the path is returned in any case. 
 * intermediate symlinks in the path are not expanded -- only
 * those at the tail.
 * a malloced char* is returned, which must be freed by the caller.
 */
char *xmalloc_follow_symlinks(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 || errno == ENOENT)
                                return buf;
                        free(buf);
                        return NULL;
                } 

                if (looping++ > MAXSYMLINKS) {
                        free(linkpath);
                        free(buf);
                        return NULL;
                }

                if (*linkpath == '/') {
                        free(buf);
                        bufsize = strlen(linkpath) + 1;
                        buf = linkpath;
                } else {
                        bufsize += strlen(linkpath);
                        buf = xrealloc(buf, bufsize);
                        lpc = bb_get_last_path_component_strip(buf);
                        strcpy(lpc, linkpath);
                        free(linkpath);
                }
        }

}



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

Reply via email to