/etc/passwd and symlinks

Denys Vlasenko vda.linux at googlemail.com
Thu Nov 8 18:30:47 UTC 2007


On Thursday 08 November 2007 09:11, Paul Fox wrote:
> $ 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.

to me too.

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

I thought you are done and edited it in svn already, sorry.
I didn't want to collide.

> {
> 	char *buf = NULL, *lpc, *linkpath;

No need to store NULL

> 	int bufsize;
> 	smallint looping = 0;
>
> 	buf = strdup(path);

xstrdup

> 	bufsize = strlen(path) + 1;
>
> 	while(1) {
> 		linkpath = xmalloc_readlink(buf);
> 		if (!linkpath) {
> 			if (errno == EINVAL || errno == ENOENT)

I see. You added ENOENT. If it is the only new addition,
it seems ok to me.

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


Thanks
--
vda



More information about the busybox mailing list