bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

diffutils: suggested patch for --dontfollow (symlinks when recursing) op


From: Nils Goroll
Subject: diffutils: suggested patch for --dontfollow (symlinks when recursing) option
Date: Tue, 9 Jan 2007 11:48:44 +0100
User-agent: Mutt/1.4.1i

Hi there,

at some occasions, I found that diff following symlinks when recursing
(-r) was not what I needed, so I have now changed the code slightly to
give the user the choice of not to do so.

I would very much appreciate if this patch or anything serving the
same function made its way into a future diffutils release.

here's a diff of diff ;-)

--- 8< ---

diff -rub diffutils-2.8.1/doc/diff.texi diffutils-2.8.1.dontfollow/doc/diff.texi
--- diffutils-2.8.1/doc/diff.texi       Fri Apr  5 22:37:31 2002
+++ diffutils-2.8.1.dontfollow/doc/diff.texi    Tue Jan  9 11:41:07 2007
@@ -1740,6 +1740,10 @@
 @option{--recursive} option, it compares every corresponding pair of files
 in the directory trees, as many levels deep as they go.
 
+While normally also symlinKs pointing to directories will be
+traversed, with the additional @option{K} or @option{--dontfollow}
+option, only real directories will be considered for recursion.
+
 For file names that are in only one of the directories, @command{diff}
 normally does not show the contents of the file that exists; it reports
 only that the file exists in that directory and not in the other.  You
@@ -3704,6 +3708,13 @@
 Ignore case when comparing file names during recursive comparison.
 @xref{Comparing Directories}.
 
address@hidden -K
address@hidden --dontfollow
+Only relevant with the @option{-r} or @option{--recursive} option.
+
+When recursing into directories, dont follow SymlinKs pointing to
+directories.  @xref{Comparing Directories}.
+
 @item -l
 @itemx --paginate
 Pass the output through @command{pr} to paginate it.  @xref{Pagination}.
Only in diffutils-2.8.1.dontfollow/doc: diff.texi~
diff -rub diffutils-2.8.1/doc/stamp-vti diffutils-2.8.1.dontfollow/doc/stamp-vti
--- diffutils-2.8.1/doc/stamp-vti       Fri Apr  5 23:49:46 2002
+++ diffutils-2.8.1.dontfollow/doc/stamp-vti    Tue Jan  9 11:35:16 2007
@@ -1,4 +1,4 @@
address@hidden UPDATED 5 April 2002
address@hidden UPDATED-MONTH April 2002
address@hidden UPDATED 9 January 2007
address@hidden UPDATED-MONTH January 2007
 @set EDITION 2.8.1
 @set VERSION 2.8.1
diff -rub diffutils-2.8.1/doc/version.texi 
diffutils-2.8.1.dontfollow/doc/version.texi
--- diffutils-2.8.1/doc/version.texi    Fri Apr  5 23:49:46 2002
+++ diffutils-2.8.1.dontfollow/doc/version.texi Tue Jan  9 11:35:16 2007
@@ -1,4 +1,4 @@
address@hidden UPDATED 5 April 2002
address@hidden UPDATED-MONTH April 2002
address@hidden UPDATED 9 January 2007
address@hidden UPDATED-MONTH January 2007
 @set EDITION 2.8.1
 @set VERSION 2.8.1
Common subdirectories: diffutils-2.8.1/lib/posix and 
diffutils-2.8.1.dontfollow/lib/posix
diff -rub diffutils-2.8.1/src/diff.c diffutils-2.8.1.dontfollow/src/diff.c
--- diffutils-2.8.1/src/diff.c  Sun Mar 24 08:35:28 2002
+++ diffutils-2.8.1.dontfollow/src/diff.c       Tue Jan  9 11:11:18 2007
@@ -70,6 +70,9 @@
    recursively.  */
 static bool recursive;
 
+/* When recursing, respect symlinks */
+static bool follow=1;
+
 /* In context diffs, show previous lines that match these regexps.  */
 static struct regexp_list function_regexp_list;
 
@@ -139,7 +142,7 @@
 }
 
 static char const shortopts[] =
-"0123456789abBcC:dD:eEfF:hHiI:lL:nNpPqrsS:tTuU:vwW:x:X:y";
+"0123456789abBcC:dD:eEfF:hHiI:KlL:nNpPqrsS:tTuU:vwW:x:X:y";
 
 /* Values for long options that do not have single-letter equivalents.  */
 enum
@@ -224,6 +227,7 @@
   {"paginate", 0, 0, 'l'},
   {"rcs", 0, 0, 'n'},
   {"recursive", 0, 0, 'r'},
+  {"dontfollow", 0, 0, 'K'},
   {"report-identical-files", 0, 0, 's'},
   {"sdiff-merge-assist", 0, 0, SDIFF_MERGE_ASSIST_OPTION},
   {"show-c-function", 0, 0, 'p'},
@@ -445,6 +449,11 @@
          recursive = 1;
          break;
 
+         /* dont follow symlinKs when recursing */
+       case 'K':
+         follow = 0;
+         break;
+
        case 's':
          report_identical_files = 1;
          break;
@@ -888,6 +897,7 @@
   N_("-T  --initial-tab  Make tabs line up by prepending a tab."),
   "",
   N_("-r  --recursive  Recursively compare any subdirectories found."),
+  N_("-K  --dontfollow Dont follow symlinKs when recursing."),
   N_("-N  --new-file  Treat absent files as empty."),
   N_("--unidirectional-new-file  Treat absent first files as empty."),
   N_("-s  --report-identical-files  Report when two files are the same."),
@@ -1219,18 +1229,51 @@
       if (output_style == OUTPUT_IFDEF)
        fatal ("-D option not supported with directories");
 
-      /* If both are directories, compare the files in them.  */
+      /* If both are directories, we might want to recurse
+        and compare the files in them .
 
+        Simple decision tree here, goto used for clarity */
+
       if (parent && !recursive)
+       goto both_dir_dontrecurse; /* dont want to recurse */
+      else
        {
+         if (follow)
+           goto both_dir_recurse; /* want to recurse ignoring symlinks */
+         else
+           {
+             struct stat lstatbuf[2];
+             
+             /* we dont want to follow symlinks, so unfortunately
+                we need to lstat() those files again. */
+             
+             for (f = 0; f < 2; f++)
+               if (lstat (cmp.file[f].name, &lstatbuf[f]) != 0)
+                 {
+                   cmp.file[f].desc = ERRNO_ENCODE (errno);
+                   /* really, those lstats should not fail, but
+                      if they do, we should drop the standard message */
+                   goto both_dir_dontrecurse;
+                 }
+
+             if (S_ISLNK (lstatbuf[0].st_mode) | S_ISLNK (lstatbuf[1].st_mode) 
)
+               goto both_dir_dontrecurse; /* one of them is a link - dont 
recurse */
+             else
+               goto both_dir_recurse; /* neither is a link, recurse */
+           }
+       }
+
+    both_dir_dontrecurse:
          /* But don't compare dir contents one level down
             unless -r was specified.
             See POSIX 1003.1-2001 for this format.  */
          message ("Common subdirectories: %s and %s\n",
                   cmp.file[0].name, cmp.file[1].name);
-       }
-      else
+      goto done;
+    both_dir_recurse:
        status = diff_dirs (&cmp, compare_files);
+    done:
+      1; /* ignore warning */
     }
   else if ((DIR_P (0) | DIR_P (1))
           || (parent

--- 8< ---

-- 

MCS - Technik

MCS MOORBEK COMPUTER SYSTEME GmbH
Essener Bogen 17 - 22419 Hamburg - Germany
Tel.: +49 (0)40.53773.0 -  Fax: +49 (0)40.53773.200
eMail: mailto:address@hidden
Web: http://www.mcs.de




reply via email to

[Prev in Thread] Current Thread [Next in Thread]