From nobody@FreeBSD.org  Fri Aug 25 18:43:56 2006
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 642B616A4DA
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 25 Aug 2006 18:43:56 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [216.136.204.117])
	by mx1.FreeBSD.org (Postfix) with ESMTP id AB9E143D6D
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 25 Aug 2006 18:43:55 +0000 (GMT)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.13.1/8.13.1) with ESMTP id k7PIhtgF092958
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 25 Aug 2006 18:43:55 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.13.1/8.13.1/Submit) id k7PIhtBo092957;
	Fri, 25 Aug 2006 18:43:55 GMT
	(envelope-from nobody)
Message-Id: <200608251843.k7PIhtBo092957@www.freebsd.org>
Date: Fri, 25 Aug 2006 18:43:55 GMT
From: Jin Guojun <jin@george.lbl.gov>
To: freebsd-gnats-submit@FreeBSD.org
Subject: diff should not follow symlink in recursive (-r) mode
X-Send-Pr-Version: www-2.3

>Number:         102510
>Category:       bin
>Synopsis:       [patch] diff(1) should not follow symlink in recursive (-r) mode
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    edwin
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Aug 25 18:50:18 GMT 2006
>Closed-Date:    Tue Aug 05 08:55:09 UTC 2008
>Last-Modified:  Tue Aug 05 08:55:09 UTC 2008
>Originator:     Jin Guojun
>Release:        All FreeBSD release
>Organization:
>Environment:
Non hardware related issue
>Description:
/usr/bin/diff should not follow symlink in recursive mode (with option "-r").

Where "-r" option is used to compare two structures/trees, where one of them is a
mirror or duplication of the other. 
It is not clear what is the historical reason "diff -r" follows symlink in
this mode. It is hardly to see "diff -r" may be used to compare two completely
different file structure or trees.

Therefore, to compare two same/similar file trees, there is no any good reason
to follow the symlink for diffing. 
If the node at the end of the link exists, it will be compared eventually anyway.
If the symlink points to nowhere, then there is no meaning to follow it.

It wastes time to follow symlink to do number of extra comparisons.
Also, if user(s) create some long-multi-path links between directories/trees,
diff -r will loop forever (no infinit, but may take a day) in comparing such
file trees.


>How-To-Repeat:
I have send a simple example to hackers for comment, but have not heard any feedback. It can be found in mailing archive.

The real problem on a large file tree/structure may take time to debug.
However, it is not hard to see the problem through above description.

A patch is provide to disable the feature of following symlink in "-r" mode.
Since the patch is copy/pasted, it may not be directly applied via "patch",
but it is very simple (tree line added, and one line changed), so manually
apply it is easy. When I receive the reply,I will send the patch in via email
if people agree this patch.

If for some reason following symlink is needed in "-r" mode, then a switch
(option) can be added for such purpose to enable following symlink feature
in "-r" recursive mode.
>Fix:
*** /usr/src/contrib/diff/diff.c.orig   Tue Aug 15 14:05:30 2006
--- /usr/src/contrib/diff/diff.c        Tue Aug 15 14:04:45 2006
***************
*** 832,837 ****
--- 832,840 ----

    /* other popular file types */
    /* S_ISLNK is impossible with `fstat' and `stat'.  */
+ #ifdef S_ISLNK
+   if (S_ISLNK (st->st_mode)) return "symlink";
+ #endif
  #ifdef S_ISSOCK
    if (S_ISSOCK (st->st_mode)) return "socket";
  #endif
***************
*** 927,933 ****
                }
            }
          else
!           stat_result = stat (inf[i].name, &inf[i].stat);

          if (stat_result != 0)
            {
--- 930,936 ----
                }
            }
          else
!           stat_result = (recursive ? lstat : stat) (inf[i].name, &inf[i].stat)
;

          if (stat_result != 0)
            {

>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->edwin 
Responsible-Changed-By: edwin 
Responsible-Changed-When: Mon Aug 4 12:22:38 UTC 2008 
Responsible-Changed-Why:  
Handle with mentor. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=102510 
State-Changed-From-To: open->closed 
State-Changed-By: edwin 
State-Changed-When: Tue Aug 5 08:52:11 UTC 2008 
State-Changed-Why:  
The POSIX standard doesn't say anything about symlinks, it only 
talks about text-files, directories and FIFO and block files. 
The rest of the files are "The behavior of diff on other file types 
is implementation-defined when found in directories." 

We can't make the behaviour of diff different from the behaviour 
of diff on other platforms. Since we are using the GNU diff, I 
suggest you talk to them to change the behaviour (but I am afraid 
they will tell you the same story as I did). 


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