From joelh@gnu.org  Sun Jul 12 16:59:10 1998
Received: from mail.camalott.com (root@mail.camalott.com [208.203.140.2])
          by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id QAA07868
          for <FreeBSD-gnats-submit@freebsd.org>; Sun, 12 Jul 1998 16:59:09 -0700 (PDT)
          (envelope-from joelh@gnu.org)
Received: from detlev.UUCP (tex-69.camalott.com [208.229.74.69])
	by mail.camalott.com (8.8.7/8.8.5) with ESMTP id SAA31901
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 12 Jul 1998 18:59:48 -0500
Received: (from joelh@localhost)
	by detlev.UUCP (8.8.8/8.8.8) id SAA03409;
	Sun, 12 Jul 1998 18:55:03 -0500 (CDT)
	(envelope-from joelh)
Message-Id: <199807122355.SAA03409@detlev.UUCP>
Date: Sun, 12 Jul 1998 18:55:03 -0500 (CDT)
From: Joel Ray Holveck <detlev!joelh@mail.camalott.com>
Reply-To: joelh@gnu.org
To: FreeBSD-gnats-submit@freebsd.org
Subject: [patch] Improvement of ln(1)
X-Send-Pr-Version: 3.2

>Number:         7265
>Category:       bin
>Synopsis:       [patch] A warning flag is added to ln(1).
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    keramida
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Jul 12 17:00:01 PDT 1998
>Closed-Date:    Sat Nov 13 11:03:32 UTC 2010
>Last-Modified:  Sat Nov 13 11:03:32 UTC 2010
>Originator:     Joel Ray Holveck
>Release:        FreeBSD 3.0-CURRENT i386
>Organization:
Little to none.
>Environment:

June 28 3.0-current.

>Description:

It is easy at 4:00 AM to give, to ln -s, a target relative to the
current path rather than the source's path.  (source and target are
here used as in the source, ie, the source and target of the eventual
resulting symlink.)  No facilities are provided to allow for warnings.

(For more information, please see the flamefest^H^H^H^H^H^H^H^H^H^H
thread in freebsd-current entitled 'Improvemnet of ln(1).'  Note that
the fix proposed here is markedly different than what was originally
proposed by the originator of said thread, as well as my own
proposal.)

>How-To-Repeat:

# cd /usr
# ln -s src/sys /sys
# cd /sys
/sys: No such file or directory.

(Emit the anguished wails of a tired sysadmin who thinks he's just
lost his kernel source.  Repeating this last step is optional.)

>Fix:
	
A new flag, -w, is proposed.  If the symlink created would be invalid,
and the -w flag is specified, a warning is emitted to stderr.

----- cut here -----
*** ln.1-orig	Sun Jul 12 18:02:09 1998
--- ln.1	Sun Jul 12 18:36:43 1998
***************
*** 72,77 ****
--- 72,79 ----
  Unlink any already existing file, permitting the link to occur.
  .It Fl s
  Create a symbolic link.
+ .It Fl w
+ Warn if the target of a symbolic link does not currently exist.
  .El
  .Pp
  By default
*** ln.c-orig	Sun Jul 12 18:02:06 1998
--- ln.c	Sun Jul 12 18:42:42 1998
***************
*** 57,62 ****
--- 57,63 ----
  
  int	fflag;				/* Unlink existing files. */
  int	sflag;				/* Symbolic, not hard, link. */
+ int	wflag;				/* Warn if dest does not exist. */
  					/* System link call. */
  int (*linkf) __P((const char *, const char *));
  
***************
*** 73,79 ****
  	int ch, exitval;
  	char *sourcedir;
  
! 	while ((ch = getopt(argc, argv, "fs")) != -1)
  		switch (ch) {
  		case 'f':
  			fflag = 1;
--- 74,80 ----
  	int ch, exitval;
  	char *sourcedir;
  
! 	while ((ch = getopt(argc, argv, "fsw")) != -1)
  		switch (ch) {
  		case 'f':
  			fflag = 1;
***************
*** 81,86 ****
--- 82,90 ----
  		case 's':
  			sflag = 1;
  			break;
+ 		case 'w':
+ 			wflag = 1;
+ 			break;
  		case '?':
  		default:
  			usage();
***************
*** 117,123 ****
  {
  	struct stat sb;
  	int exists;
! 	char *p, path[MAXPATHLEN];
  
  	if (!sflag) {
  		/* If target doesn't exist, quit now. */
--- 121,127 ----
  {
  	struct stat sb;
  	int exists;
! 	char *p, path[MAXPATHLEN], *st, wbuf[MAXPATHLEN];
  
  	if (!sflag) {
  		/* If target doesn't exist, quit now. */
***************
*** 146,151 ****
--- 150,183 ----
  		exists = !lstat(source, &sb);
  
  	/*
+ 	 * If the target doesn't exist, and a symbolic link was
+ 	 * requested, and -w was specified, give a warning.
+ 	 */
+ 	if (sflag && wflag) {
+ 		if (*target == '/')
+ 			/* Absolute target */
+ 			st = target;
+ 		else {
+ 			/* Relative target */
+ 			st = strdup(source);
+ 			if (!st) {
+ 				warnx("-w: Cannot allocate memory (continuing)");
+ 				goto nowarn;
+ 			}
+ 			p = strrchr(st, '/');
+ 			* (p ? p+1 : st) = '\0';
+ 			(void)snprintf(wbuf, sizeof(wbuf), "%s%s", st,
+ 				       target);
+ 			free(st);
+ 			st = wbuf;
+ 		}
+ 		if (stat(st, &sb))
+ 			warn("warning: %s inaccessible relative to %s",
+ 			     target, source);
+ 	}
+  nowarn:
+ 
+ 	/*
  	 * If the file exists, and -f was specified, unlink it.
  	 * Attempt the link.
  	 */
***************
*** 160,166 ****
  usage()
  {
  	(void)fprintf(stderr, "%s\n%s\n",
! 	    "usage: ln [-fs] file1 file2",
! 	    "       ln [-fs] file ... directory");
  	exit(1);
  }
--- 192,198 ----
  usage()
  {
  	(void)fprintf(stderr, "%s\n%s\n",
! 	    "usage: ln [-fsw] file1 file2",
! 	    "       ln [-fsw] file ... directory");
  	exit(1);
  }
----- cut here -----

>Release-Note:
>Audit-Trail:

From: Giorgos Keramidas <charon@labs.gr>
To: freebsd-gnats-submit@FreeBSD.org
Cc: joelh@gnu.org
Subject: Re: bin/7265: A warning flag is added to ln(1).
Date: Thu, 14 Jun 2001 05:50:05 +0300

 I cant locate the thread that is referenced in the PR
 in the -current archives.  This PR seems to be too old
 and the change it suggests does not seem to interest
 anyone, for such a long time.
 
 Maybe its time we killed this beast...
 
 -giorgos

From: Joel Ray Holveck <joelh@gnu.org>
To: Giorgos Keramidas <charon@labs.gr>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: bin/7265: A warning flag is added to ln(1).
Date: 13 Jun 2001 22:33:22 -0700

 > I cant locate the thread that is referenced in the PR
 > in the -current archives.  This PR seems to be too old
 > and the change it suggests does not seem to interest
 > anyone, for such a long time.
 > Maybe its time we killed this beast...
 
 I think it should be applied, under the "better late than never" clause.
 
 My apologies on the reference, the thread was in -hackers; see
 http://docs.freebsd.org/mail/archive/1998/freebsd-hackers/19980705.freebsd-hackers.html
 and
 http://docs.freebsd.org/mail/archive/1998/freebsd-hackers/19980712.freebsd-hackers.html
 for the details, and note the typo in "Improvemnet" when you search.
 
 Or, I can briefly sum up what happened.
 
 Shigio Yamaguchi noticed that doing things like "cd /usr; ln -s
 src/sys /tmp; cd /tmp/sys" didn't work as a naive user may expect, or
 even an experienced user whose brain skipped a groove briefly.  He
 made a suggestion to add flags to ln which would cause it to do the
 expected thing-- one flag which would create a symlink to
 "/usr/src/sys" in that event, and another to create a "../usr/src/sys"
 symlink.
 
 rminnich replied that it may be simpler-- and possibly more
 effective-- just to issue a warning whenever such a symlink was made.
 Somebody replied that it would be against the Unix philosophy to do
 that, since Unix shouldn't keep you from doing what you said.  I
 replied that this wouldn't keep you from making the symlink; it'd just
 remind you in case you forgot that something may be amiss.
 
 Some people argued against the change, stating that it would most
 certainly break something.  (Quote: "As you are not able to prove for
 -all- cases that this change will not break things...")  Some people
 argued against the change, stating that it was against the Unix
 philosophy to issue warnings.  (Quote: "If dmr & ken had wanted
 warnings they would have added stdwarn [warning: that is a joke]") And
 some people argued against the change, since they simply misunderstood
 the effect, thinking that it would be a fatal error.  (Quote:
 "Besides, creating a link to a non existant directory is not cause for
 an error condition")
 
 Then, there were those who supported the change, because they believed
 it would be useful, and did not believe that the above arguments were
 valid.  (Quote: "Obviously this guy is on crack.")
 
 Now, I had some fairly strong opinions about the Unix UI at that time.
 (I still do, but I'm not as vocal about them.)  I myself argued for
 the change most vehemently.  To address the first point, I described
 the absurdity of the situation (My quote: "So, we've now got a script
 which relies on the stderr of another script, the latter of which
 makes symlinks to non-existent files, and the former of which will
 break if a line is added.  Have I got you right?").  I also cited
 previous changes which had (IMHO) greater potential to break things,
 but didn't.  Then, I challenged the list members to cite an example of
 something which would break, and offered a beer as bounty.
 
 To address the second point, I argued that the Unix philosophy was not
 to prevent stuff, but that warnings were okay; to back this up, I
 cited other staples which issued "superfluous" warnings (16 core
 programs, including cp, make, lex, and cdcontrol).
 
 I just now realized that I'm the one who seems to have proposed the
 "-w" flag, in a sentence in which I objected to it.  Nobody else
 objected to adding the "-w" flag (although Terry Lambert reserved the
 right to do so later, on the grounds that POSIX may someday define a
 -w flag).  It soon became clear that the entire issue was a religious
 war-- which I was helping to perpetuate-- and not worth the effort.
 In an effort to end it, I wrote a patch to implement the -w flag,
 submitted a pr, and sent out a message with the subject line "Re:
 Improvemnet of ln(1). (THE END OF IT!)" and went on with my life.
 
 I had expected the patch to be merged quickly, and figured I'd add an
 alias to my .bash_profile once it was.
 
 Today, I'm not sure whether I would hold the same position as I did
 before.  I definitely support the -w addition, though; I still think
 it's a good idea.  Seeing as how there were no objections (other than
 mine, and I'm the guy who later wrote the patch), I see no reason to
 refrain from applying the patch.
 
 Hope this helps,
 joelh
 
 -- 
 Joel Ray Holveck - joelh@gnu.org
    Fourth law of programming:
    Anything that can go wrong wi
 sendmail: segmentation violation - core dumped

From: Leo Bicknell <bicknell@ufp.org>
To: freebsd-gnats-submit@freebsd.org, joelh@gnu.org
Cc:  
Subject: Re: bin/7265: A warning flag is added to ln(1).
Date: Tue, 10 Jul 2001 20:53:08 -0400

 I found this pr quite funny, but it hit me that the real solution is
 not a patch to ln.  It's right there in the how to repeat:
 
 # cd /usr
 # ln -s src/sys /sys
 # cd /sys
 /sys: No such file or directory.
 
 The ln was successful, there were no errors, and warning are, in general,
 bad.  However, there was very much an error on the cd, an error that was
 poorly reported.
 
 "No such file or directory" actually means:
     "Directory does not exist."
     "Symlink points to directory that does not exist."
 
 Note, the file bit is completely misleading, as that's another error:
 
 % touch foo
 % cd foo
 foo: Not a directory.
 
 So, I do believe the right answer is to patch cd (which sadly means
 patching shells) so that it reports errors correctly.  Here's a sample
 of the results with the (non-existant) patch applied:
 
 # cd /usr
 # ln -s src/sys /sys    
 # cd /sys    
 /sys: Symlink points to directory that does not exist.
 
 I think that would stop our friendly sysadmins from pulling their
 hair out, stands no chance of ever breaking ln, and it's hard to
 argue that more precise error reporting is a bad thing.
 
 Who's going to do patches for the 952 shells out there? :-)
 
 -- 
 Leo Bicknell - bicknell@ufp.org
 Systems Engineer - Internetworking Engineer - CCIE 3440
 Read TMBG List - tmbg-list-request@tmbg.org, www.tmbg.org

From: Joel Ray Holveck <joelh@gnu.org>
To: Leo Bicknell <bicknell@ufp.org>
Cc: freebsd-gnats-submit@freebsd.org
Subject: Re: bin/7265: A warning flag is added to ln(1).
Date: 11 Jul 2001 02:32:47 -0700

 > I found this pr quite funny, but it hit me that the real solution is
 > not a patch to ln.  It's right there in the how to repeat:
 
 You have a good point there.  However, the original idea got shot down
 because adding a message was determined to be unsafe.  It is possible
 that others may deem changing an existing message to be unsafe.  You
 may want to discuss the idea with -hackers.
 
 Feel free to cc me on that discussion; I'm not presently subscribed to
 -hackers.
 
 joelh
 
 -- 
 Joel Ray Holveck - joelh@gnu.org
    Fourth law of programming:
    Anything that can go wrong wi
 sendmail: segmentation violation - core dumped
Responsible-Changed-From-To: freebsd-bugs->keramida 
Responsible-Changed-By: keramida 
Responsible-Changed-When: Tue Jun 3 14:27:09 UTC 2008 
Responsible-Changed-Why:  
I'll take care of this. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=7265 

From: Giorgos Keramidas <keramida@freebsd.org>
To: joelh@gnu.org
Cc: bug-followup@freebsd.org
Subject: Re: bin/7265: [patch] Improvement of ln(1)
Date: Tue, 03 Jun 2008 20:30:44 +0300

 On Sun, 12 Jul 1998 18:55:03 -0500 (CDT), Joel Ray Holveck <detlev!joelh@mail.camalott.com> wrote:
 > ***************
 > *** 146,151 ****
 > --- 150,183 ----
 >   		exists = !lstat(source, &sb);
 >
 >   	/*
 > + 	 * If the target doesn't exist, and a symbolic link was
 > + 	 * requested, and -w was specified, give a warning.
 > + 	 */
 > + 	if (sflag && wflag) {
 > + 		if (*target == '/')
 > + 			/* Absolute target */
 > + 			st = target;
 > + 		else {
 > + 			/* Relative target */
 > + 			st = strdup(source);
 > + 			if (!st) {
 > + 				warnx("-w: Cannot allocate memory (continuing)");
 > + 				goto nowarn;
 > + 			}
 > + 			p = strrchr(st, '/');
 > + 			* (p ? p+1 : st) = '\0';
 > + 			(void)snprintf(wbuf, sizeof(wbuf), "%s%s", st,
 > + 				       target);
 > + 			free(st);
 > + 			st = wbuf;
 > + 		}
 > + 		if (stat(st, &sb))
 > + 			warn("warning: %s inaccessible relative to %s",
 > + 			     target, source);
 > + 	}
 
 The source of ln(1) has been constified, so we can't really assign
 `const char *target' to `char *st' here, but there's something else
 that seemed to bother me about the check.  I tried the patch as shown
 above, and it was checking for the wrong thing in stat().  The log
 from the final Perforce commit which fixed the patch may help a bit
 with the confusion between source/target in ln.c and ln.1 :/
 
 % Change 142835 by keramida on 2008/06/03 17:14:08
 %
 %   Reverse the `logic' of the patch in bin/7265.
 %
 %   The terms `source' and `target' are a bit misleading in the
 %   source of ln(1), so this caused a bit of confusion in the
 %   original submitter's patch.  In ln.c we use `source' to refer to
 %   the original, existing filesystem entry where the link will
 %   point to, and `target' refers to the place where we are about to
 %   create a new link.
 %
 %   This is a bit `backwards' from the terminology one tends to use
 %   when thinking of `source -> target' in the sense of ls(1) output,
 %   so the original patch in bin/7265 checked for the wrong thing.
 %
 %   This one should work a bit better, i.e.:
 %
 %   % ln -sw /no-such-file lala
 %   ln: warning: /no-such-file inaccessible: No such file or directory
 %   ln: lala: File exists
 %
 %   % mkdir -p foo
 %   % ./ln -sw foo/nonexistent.file lala
 %   ln: warning: foo/nonexistent.file inaccessible relative to lala: No such file or directory
 %   % ls -ld lala
 %   lrwxrwxr-x  1 keramida  users  - 40 Jun  3 20:13 lala -> foo/nonexistent.file
 %
 % Affected files ...
 %
 % ... //depot/user/keramida/ln/ln.c#3 edit
 
 The following patch adds a new -w option to ln(1) in 8.0-CURRENT and
 updates a few of the places we missed in the manpage back when the
 patch was originally submitted.
 
 If there are no serious objections, I'll try to get this reviewed and
 committed in the next few days.
 
 ----- ln.bin-7265.patch starts here -----
 diff -ruN ln.orig/ln.1 ln/ln.1
 --- ln.orig/ln.1	2008-06-03 20:14:36.000000000 +0300
 +++ ln/ln.1	2008-06-03 20:14:54.000000000 +0300
 @@ -42,13 +42,13 @@
  .Sh SYNOPSIS
  .Nm
  .Op Fl s Op Fl F
 -.Op Fl f | i
 +.Op Fl f | iw
  .Op Fl hnv
  .Ar source_file
  .Op Ar target_file
  .Nm
  .Op Fl s Op Fl F
 -.Op Fl f | i
 +.Op Fl f | iw
  .Op Fl hnv
  .Ar source_file ...
  .Ar target_dir
 @@ -79,6 +79,8 @@
  .Fl f
  option overrides any previous
  .Fl i
 +and
 +.Fl w
  options.)
  .It Fl F
  If the target file already exists and is a directory, then remove it
 @@ -134,6 +136,8 @@
  Cause
  .Nm
  to be verbose, showing files as they are processed.
 +.It Fl w
 +Warn if the target of a symbolic link does not currently exist.
  .El
  .Pp
  By default,
 @@ -194,9 +198,10 @@
  The
  .Fl h ,
  .Fl i ,
 -.Fl n
 -and
 +.Fl n ,
  .Fl v
 +and
 +.Fl w
  options are non-standard and their use in scripts is not recommended.
  They are provided solely for compatibility with other
  .Nm
 diff -ruN ln.orig/ln.bin-7265.patch ln/ln.bin-7265.patch
 --- ln.orig/ln.bin-7265.patch	1970-01-01 02:00:00.000000000 +0200
 +++ ln/ln.bin-7265.patch	2008-06-03 20:17:12.000000000 +0300
 @@ -0,0 +1 @@
 +Files ln.orig and ln differ
 diff -ruN ln.orig/ln.c ln/ln.c
 --- ln.orig/ln.c	2008-06-03 20:14:37.000000000 +0300
 +++ ln/ln.c	2008-06-03 20:14:54.000000000 +0300
 @@ -58,6 +58,8 @@
  int	iflag;				/* Interactive mode. */
  int	sflag;				/* Symbolic, not hard, link. */
  int	vflag;				/* Verbose output. */
 +int	wflag;				/* Warn if symlink target does not
 +					 * exist, and -f is not enabled. */
  					/* System link call. */
  int (*linkf)(const char *, const char *);
  char	linkch;
 @@ -92,7 +94,7 @@
  		exit(linkit(argv[0], argv[1], 0));
  	}
 
 -	while ((ch = getopt(argc, argv, "Ffhinsv")) != -1)
 +	while ((ch = getopt(argc, argv, "Ffhinsvw")) != -1)
  		switch (ch) {
  		case 'F':
  			Fflag = 1;
 @@ -100,6 +102,7 @@
  		case 'f':
  			fflag = 1;
  			iflag = 0;
 +			wflag = 0;
  			break;
  		case 'h':
  		case 'n':
 @@ -115,6 +118,9 @@
  		case 'v':
  			vflag = 1;
  			break;
 +		case 'w':
 +			wflag = 1;
 +			break;
  		case '?':
  		default:
  			usage();
 @@ -127,8 +133,10 @@
  	linkch = sflag ? '-' : '=';
  	if (sflag == 0)
  		Fflag = 0;
 -	if (Fflag == 1 && iflag == 0)
 +	if (Fflag == 1 && iflag == 0) {
  		fflag = 1;
 +		wflag = 0;		/* Implied when fflag != 0 */
 +	}
 
  	switch(argc) {
  	case 0:
 @@ -167,6 +175,7 @@
  	const char *p;
  	int ch, exists, first;
  	char path[PATH_MAX];
 +	char wbuf[PATH_MAX];
 
  	if (!sflag) {
  		/* If source doesn't exist, quit now. */
 @@ -204,6 +213,33 @@
 
  	exists = !lstat(target, &sb);
  	/*
 +	 * If the link source doesn't exist, and a symbolic link was
 +	 * requested, and -w was specified, give a warning.
 +	 */
 +	if (sflag && wflag) {
 +		if (*source == '/') {
 +			/* Absolute link source. */
 +			if (stat(source, &sb) != 0)
 +				 warn("warning: %s inaccessible", source);
 +		} else {
 +			/*
 +			 * Relative symlink source.  Try to construct the
 +			 * 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",
 +			    (p - target), target, source);
 +			if (stat(wbuf, &sb) != 0)
 +				warn("warning: %s inaccessible relative to %s",
 +				    source, target);
 +		}
 +	}
 +	/*
  	 * If the file exists, then unlink it forcibly if -f was specified
  	 * and interactively if -i was specified.
  	 */
 ----- ln.bin-7265.patch ends here -----
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/7265: commit references a PR
Date: Fri,  6 Jun 2008 08:28:19 +0000 (UTC)

 keramida    2008-06-06 08:27:59 UTC
 
   FreeBSD src repository
 
   Modified files:
     bin/ln               ln.1 ln.c 
   Log:
   SVN rev 179603 on 2008-06-06 08:27:59Z by keramida
   
   Add a -w warning flag to ln(1).  When the -w option is enabled,
   ln(1) checks to see if the source of a symlink, i.e. the file it
   should point to actually exists.  The default is the old ln
   behavior, that does not check, to avoid surprising people who may
   be using ln(1) in scripts or other non-interactive places.
   
   PR:             bin/7265
   Submitted by:   Joel Ray Holveck, detlev!joelh at mail.camalott.com
   MFC after:      2 weeks
   
   Revision  Changes    Path
   1.33      +10 -5     src/bin/ln/ln.1
   1.37      +37 -2     src/bin/ln/ln.c
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->patched 
State-Changed-By: keramida 
State-Changed-When: Fri Jun 6 08:31:02 UTC 2008 
State-Changed-Why:  
A new ln -w option has been committed to HEAD. Thanks! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=7265 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/7265: commit references a PR
Date: Fri, 23 Jan 2009 11:58:40 +0000 (UTC)

 Author: keramida (doc committer)
 Date: Fri Jan 23 11:58:24 2009
 New Revision: 187629
 URL: http://svn.freebsd.org/changeset/base/187629
 
 Log:
   MFC 179603 and 179636 from /head
   
     Add a -w warning flag to ln(1).  When the -w option is enabled,
     ln(1) checks to see if the source of a symlink, i.e. the file it
     should point to actually exists.  The default is the old ln
     behavior, that does not check, to avoid surprising people who may
     be using ln(1) in scripts or other non-interactive places.
   
     PR:             bin/7265
     Submitted by:   Joel Ray Holveck, detlev!joelh at mail.camalott.com
 
 Modified:
   stable/7/bin/ln/   (props changed)
   stable/7/bin/ln/ln.1
   stable/7/bin/ln/ln.c
 
 Modified: stable/7/bin/ln/ln.1
 ==============================================================================
 --- stable/7/bin/ln/ln.1	Fri Jan 23 11:54:31 2009	(r187628)
 +++ stable/7/bin/ln/ln.1	Fri Jan 23 11:58:24 2009	(r187629)
 @@ -32,7 +32,7 @@
  .\"	@(#)ln.1	8.2 (Berkeley) 12/30/93
  .\" $FreeBSD$
  .\"
 -.Dd February 14, 2006
 +.Dd June 6, 2008
  .Dt LN 1
  .Os
  .Sh NAME
 @@ -42,13 +42,13 @@
  .Sh SYNOPSIS
  .Nm
  .Op Fl s Op Fl F
 -.Op Fl f | i
 +.Op Fl f | iw
  .Op Fl hnv
  .Ar source_file
  .Op Ar target_file
  .Nm
  .Op Fl s Op Fl F
 -.Op Fl f | i
 +.Op Fl f | iw
  .Op Fl hnv
  .Ar source_file ...
  .Ar target_dir
 @@ -79,6 +79,8 @@ then unlink it so that the link may occu
  .Fl f
  option overrides any previous
  .Fl i
 +and
 +.Fl w
  options.)
  .It Fl F
  If the target file already exists and is a directory, then remove it
 @@ -134,6 +136,8 @@ Create a symbolic link.
  Cause
  .Nm
  to be verbose, showing files as they are processed.
 +.It Fl w
 +Warn if the source of a symbolic link does not currently exist.
  .El
  .Pp
  By default,
 @@ -194,9 +198,10 @@ operation using the two passed arguments
  The
  .Fl h ,
  .Fl i ,
 -.Fl n
 -and
 +.Fl n ,
  .Fl v
 +and
 +.Fl w
  options are non-standard and their use in scripts is not recommended.
  They are provided solely for compatibility with other
  .Nm
 
 Modified: stable/7/bin/ln/ln.c
 ==============================================================================
 --- stable/7/bin/ln/ln.c	Fri Jan 23 11:54:31 2009	(r187628)
 +++ stable/7/bin/ln/ln.c	Fri Jan 23 11:58:24 2009	(r187629)
 @@ -58,6 +58,8 @@ int	hflag;				/* Check new name for syml
  int	iflag;				/* Interactive mode. */
  int	sflag;				/* Symbolic, not hard, link. */
  int	vflag;				/* Verbose output. */
 +int	wflag;				/* Warn if symlink target does not
 +					 * exist, and -f is not enabled. */
  					/* System link call. */
  int (*linkf)(const char *, const char *);
  char	linkch;
 @@ -92,7 +94,7 @@ main(int argc, char *argv[])
  		exit(linkit(argv[0], argv[1], 0));
  	}
  
 -	while ((ch = getopt(argc, argv, "Ffhinsv")) != -1)
 +	while ((ch = getopt(argc, argv, "Ffhinsvw")) != -1)
  		switch (ch) {
  		case 'F':
  			Fflag = 1;
 @@ -100,6 +102,7 @@ main(int argc, char *argv[])
  		case 'f':
  			fflag = 1;
  			iflag = 0;
 +			wflag = 0;
  			break;
  		case 'h':
  		case 'n':
 @@ -115,6 +118,9 @@ main(int argc, char *argv[])
  		case 'v':
  			vflag = 1;
  			break;
 +		case 'w':
 +			wflag = 1;
 +			break;
  		case '?':
  		default:
  			usage();
 @@ -127,8 +133,10 @@ main(int argc, char *argv[])
  	linkch = sflag ? '-' : '=';
  	if (sflag == 0)
  		Fflag = 0;
 -	if (Fflag == 1 && iflag == 0)
 +	if (Fflag == 1 && iflag == 0) {
  		fflag = 1;
 +		wflag = 0;		/* Implied when fflag != 0 */
 +	}
  
  	switch(argc) {
  	case 0:
 @@ -167,6 +175,7 @@ linkit(const char *target, const char *s
  	const char *p;
  	int ch, exists, first;
  	char path[PATH_MAX];
 +	char wbuf[PATH_MAX];
  
  	if (!sflag) {
  		/* If target doesn't exist, quit now. */
 @@ -204,6 +213,32 @@ linkit(const char *target, const char *s
  
  	exists = !lstat(source, &sb);
  	/*
 +	 * If the link source doesn't exist, and a symbolic link was
 +	 * requested, and -w was specified, give a warning.
 +	 */
 +	if (sflag && wflag) {
 +		if (*source == '/') {
 +			/* Absolute link source. */
 +			if (stat(source, &sb) != 0)
 +				 warn("warning: %s inaccessible", source);
 +		} else {
 +			/*
 +			 * Relative symlink source.  Try to construct the
 +			 * 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);
 +		}
 +	}
 +	/*
  	 * If the file exists, then unlink it forcibly if -f was specified
  	 * and interactively if -i was specified.
  	 */
 _______________________________________________
 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-unsubscribe@freebsd.org"
 

From: Giorgos Keramidas <keramida@freebsd.org>
To: joelh@gnu.org
Cc: bug-followup@freebsd.org
Subject: Re: bin/7265: bin/7265: [patch] Improvement of ln(1)
Date: Fri, 23 Jan 2009 14:10:09 +0200

 Adding to audit trail...
 
 This has been MFC'ed to the stable/7 branch in svn change 187629:
 
   r187629 | keramida | 2009-01-23 13:58:24 +0200 (Fri, 23 Jan 2009) | 11 lines
 
   MFC 179603 and 179636 from /head
 
     Add a -w warning flag to ln(1).  When the -w option is enabled,
     ln(1) checks to see if the source of a symlink, i.e. the file it
     should point to actually exists.  The default is the old ln
     behavior, that does not check, to avoid surprising people who may
     be using ln(1) in scripts or other non-interactive places.
 
     PR:             bin/7265
     Submitted by:   Joel Ray Holveck, detlev!joelh at mail.camalott.com
 
 There is another small change to be MFC'ed to stable/6 before his can be
 committed to that branch too, so I'll keep this PR `patched' until the
 patch from svn change 173701 (ru) has been merged to stable/6 too.
 
State-Changed-From-To: patched->closed 
State-Changed-By: arundel 
State-Changed-When: Sat Nov 13 11:02:47 UTC 2010 
State-Changed-Why:  
Patch is in HEAD, 8.x and 7.x. 6.x went EoL. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=7265 
>Unformatted:
