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

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

Re: diffutils: suggested patch for --dontfollow (symlinks when recursing


From: Denis Excoffier
Subject: Re: diffutils: suggested patch for --dontfollow (symlinks when recursing) option
Date: Tue, 24 Mar 2009 23:17:16 +0100

Hello,

Similar patch as in the previous message, except that (when the option is
set) the symlinks are kept undeferenced in all situations, not only in
case of directories. Don't apply both patches!

Option name `--no-dereference' (shortopt `-K') is preferred to
`--dontfollow' for consistency with the similar options in coreutils.

diffutils-2.8.7.tar.gz to be found under http://alpha.gnu.org/gnu/diffutils/



-----------------------------------------------------------
diff -rub diffutils-2.8.7.original/src/diff.c diffutils-2.8.7.nodereference/src/diff.c
--- diffutils-2.8.7.original/src/diff.c 2004-04-12 09:44:13 +0200
+++ diffutils-2.8.7.nodereference/src/diff.c    2009-03-24 22:16:57 +0100
@@ -66,6 +66,9 @@
    recursively.  */
 static bool recursive;

+/* In case of symlinks, use the contents, not the target */
+static bool no_dereference = false;
+
 /* In context diffs, show previous lines that match these regexps.  */
 static struct regexp_list function_regexp_list;

@@ -137,7 +140,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
@@ -216,6 +219,7 @@
   {"new-file", 0, 0, 'N'},
   {"new-group-format", 1, 0, NEW_GROUP_FORMAT_OPTION},
   {"new-line-format", 1, 0, NEW_LINE_FORMAT_OPTION},
+  {"no-dereference", 0, 0, 'K'},
   {"no-ignore-file-name-case", 0, 0, NO_IGNORE_FILE_NAME_CASE_OPTION},
   {"normal", 0, 0, NORMAL_OPTION},
   {"old-group-format", 1, 0, OLD_GROUP_FORMAT_OPTION},
@@ -400,6 +404,10 @@
          add_regexp (&ignore_regexp_list, optarg);
          break;

+        case 'K':
+          no_dereference = true;
+          break;
+
        case 'l':
          if (!pr_program[0])
            try_help ("pagination not supported on this host", 0);
@@ -913,6 +921,7 @@
   "",
N_("-r --recursive Recursively compare any subdirectories found."),
   N_("-N  --new-file  Treat absent files as empty."),
+ N_("-K --no-dereference Don't follow symlinks (elsewhere undocumented)."),
   N_("--unidirectional-new-file  Treat absent first files as empty."),
N_("-s --report-identical-files Report when two files are the same."),
   N_("-x PAT  --exclude=PAT  Exclude files that match PAT."),
@@ -1125,8 +1134,12 @@
                  set_mtime_to_now (&cmp.file[f].stat);
                }
            }
-         else if (stat (cmp.file[f].name, &cmp.file[f].stat) != 0)
+         else {
+ int (*stat_action)(char const *, struct stat *) = no_dereference ? lstat : stat; + if (stat_action(cmp.file[f].name, &cmp.file[f].stat) != 0) {
            cmp.file[f].desc = ERRNO_ENCODE (errno);
+            };
+          };
        }
     }

@@ -1206,6 +1219,36 @@
       /* The two named files are actually the same physical file.
         We know they are identical without actually reading them.  */
     }
+#define LNK_P(f) (S_ISLNK (cmp.file[f].stat.st_mode) != 0)
+  else if (no_dereference && (LNK_P(0) || LNK_P(1))) {
+ /* no_dereference is here only for clarity since S_ISLNK can show up
+      only under lstat(), never under stat() */
+      bool they_differ = true;
+      if (LNK_P(0) && LNK_P(1)) {
+        char linkpath0[PATH_MAX];
+        char linkpath1[PATH_MAX];
+        int nbc0, nbc1;
+ if ((nbc0 = readlink(cmp.file[0].name, linkpath0, sizeof(linkpath0))) == -1) {
+          perror_with_name(cmp.file[0].name);
+          status = EXIT_TROUBLE;
+        } else {
+ if ((nbc1 = readlink(cmp.file[1].name, linkpath1, sizeof(linkpath1))) == -1) {
+            perror_with_name(cmp.file[1].name);
+            status = EXIT_TROUBLE;
+          } else {
+ if ((nbc0 == nbc1) && !strncmp(linkpath0, linkpath1, nbc0)) {
+              they_differ = false;
+            };
+          };
+        };
+      };
+      if (they_differ && (status == EXIT_SUCCESS)) {
+        message("Files %s and %s differ\n",
+           file_label[0] ? file_label[0] : cmp.file[0].name,
+           file_label[1] ? file_label[1] : cmp.file[1].name);
+        status = EXIT_FAILURE;
+      };
+    }
   else if (DIR_P (0) & DIR_P (1))
     {
       if (output_style == OUTPUT_IFDEF)
-----------------------------------------------------------


Denis Excoffier.





reply via email to

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