Author: jilles Date: Wed Apr 21 21:57:03 2010 New Revision: 207021 URL: http://svn.freebsd.org/changeset/base/207021
Log: ln: Allow a trailing slash when creating a link to a directory. In the 'ln source... directory' synopsis, the basename of each source determines the name of the created link. Determine this using basename(3) instead of strrchr(..., '/') which is incorrect if the pathname ends in a slash. The patch is somewhat changed to allow for basename(3) implementations that change the passed pathname, and to fix the -w option's checking also. The code to compare directory entries only applies to hard links, which cannot be created to directories using ln. Example: ln -s /etc/defaults/ /tmp This should create a symlink named defaults. PR: 121568 Submitted by: Ighighi MFC after: 1 week Modified: head/bin/ln/ln.c Modified: head/bin/ln/ln.c ============================================================================== --- head/bin/ln/ln.c Wed Apr 21 21:51:14 2010 (r207020) +++ head/bin/ln/ln.c Wed Apr 21 21:57:03 2010 (r207021) @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include <err.h> #include <errno.h> #include <fcntl.h> +#include <libgen.h> #include <limits.h> #include <stdio.h> #include <stdlib.h> @@ -226,6 +227,7 @@ linkit(const char *source, const char *t int ch, exists, first; char path[PATH_MAX]; char wbuf[PATH_MAX]; + char bbuf[PATH_MAX]; if (!sflag) { /* If source doesn't exist, quit now. */ @@ -248,11 +250,9 @@ linkit(const char *source, const char *t if (isdir || (lstat(target, &sb) == 0 && S_ISDIR(sb.st_mode)) || (!hflag && stat(target, &sb) == 0 && S_ISDIR(sb.st_mode))) { - if ((p = strrchr(source, '/')) == NULL) - p = source; - else - ++p; - if (snprintf(path, sizeof(path), "%s/%s", target, p) >= + if (strlcpy(bbuf, source, sizeof(bbuf)) >= sizeof(bbuf) || + (p = basename(bbuf)) == NULL || + snprintf(path, sizeof(path), "%s/%s", target, p) >= (ssize_t)sizeof(path)) { errno = ENAMETOOLONG; warn("%s", source); @@ -276,15 +276,14 @@ linkit(const char *source, const char *t * absolute path of the source, by appending `source' * to the parent directory of the target. */ - p = strrchr(target, '/'); - if (p != NULL) - p++; - else - p = target; - (void)snprintf(wbuf, sizeof(wbuf), "%.*s%s", - (int)(p - target), target, source); - if (stat(wbuf, &sb) != 0) - warn("warning: %s", source); + strlcpy(bbuf, target, sizeof(bbuf)); + p = dirname(bbuf); + if (p != NULL) { + (void)snprintf(wbuf, sizeof(wbuf), "%s/%s", + p, source); + if (stat(wbuf, &sb) != 0) + warn("warning: %s", source); + } } } _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"