Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 10 Mar 2008 15:51:23 GMT
From:      Ighighi <ighighi@gmail.com>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   bin/121568: [patch]: wrong "ln -s" behaviour
Message-ID:  <200803101551.m2AFpNfP071097@www.freebsd.org>
Resent-Message-ID: <200803101600.m2AG06KG020494@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         121568
>Category:       bin
>Synopsis:       [patch]: wrong "ln -s" behaviour
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Mar 10 16:00:01 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator:     Ighighi
>Release:        6.3-STABLE
>Organization:
>Environment:
FreeBSD orion 6.3-STABLE FreeBSD 6.3-STABLE #0: Mon Mar  3 04:45:31 VET 2008     root@orion:/usr/obj/usr/src/sys/CUSTOM  i386
>Description:
When running "ln -s" and the last argument is a directory, if any of the source
files has a trailing slash it gives errors.

To create a symlink like this: /tmp/defaults -> /etc/defaults/

$ /bin/rm -f /tmp/defaults
$ /bin/ln -sv /etc/defaults/ /tmp
ln: /tmp/: File exists
$ /bin/ln -sv /etc/defaults /tmp
/tmp/defaults -> /etc/defaults

In this case, both commands should work regardless of any trailing slash, as is
the case with GNU ln(1). I tend to use trailing slashes to make sure I'm hitting
a directory or a symlink to one.

Quoting the POSIX description of ln(1) available at:
See http://www.opengroup.org/onlinepubs/009695399/utilities/ln.html

"The corresponding destination path for each source_file shall be the 
concatenation of the target directory pathname, a slash character, and
the last pathname component of the source_file. The second synopsis form
shall be assumed when the final operand names an existing directory."

The "last pathname component" is defined here:
http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_267

The bug is in ln(1) using strrchr(xxx, '/') instead of basename().


>How-To-Repeat:

>Fix:
Attached patch tested against the latest code in CVS

Patch attached with submission follows:

--- src/bin/ln/ln.c.orig	2007-11-17 17:01:22.000000000 -0400
+++ src/bin/ln/ln.c	2008-03-10 04:52:27.703080785 -0430
@@ -46,6 +46,7 @@
 
 #include <err.h>
 #include <errno.h>
+#include <libgen.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -189,10 +190,8 @@ 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 ((p = basename(source)) == NULL)
+			return (1);
 		if (snprintf(path, sizeof(path), "%s/%s", target, p) >=
 		    (ssize_t)sizeof(path)) {
 			errno = ENAMETOOLONG;


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200803101551.m2AFpNfP071097>