diff -urN fileutils-4.0-orig/doc/coreutils.info fileutils-4.0/doc/coreutils.info
--- fileutils-4.0-orig/doc/coreutils.info	Wed Nov 11 05:53:27 1998
+++ fileutils-4.0/doc/coreutils.info	Thu Nov 18 19:44:00 1999
@@ -1961,6 +1961,10 @@
      Make a backup of each file that would otherwise be overwritten or
      removed.  *Note Backup options::.
 
+`-C'
+    Install file, unless target already exists and is the same file, in
+    which case the modification time is not changed.
+
 `-c'
      Ignored; for compatibility with old Unix versions of `install'.
 
diff -urN fileutils-4.0-orig/doc/coreutils.texi fileutils-4.0/doc/coreutils.texi
--- fileutils-4.0-orig/doc/coreutils.texi	Sun Nov  8 17:12:07 1998
+++ fileutils-4.0/doc/coreutils.texi	Thu Nov 18 19:44:00 1999
@@ -1512,6 +1512,11 @@
 Make a backup of each file that would otherwise be overwritten or removed.
 @xref{Backup options}.
 
+@item -C
+@opindex -C
+Install file, unless target already exists and is the same file, in which
+case the modification time is not changed.
+
 @item -c
 @opindex -c
 Ignored; for compatibility with old Unix versions of @code{install}.
diff -urN fileutils-4.0-orig/man/install.1 fileutils-4.0/man/install.1
--- fileutils-4.0-orig/man/install.1	Wed Nov 11 05:53:30 1998
+++ fileutils-4.0/man/install.1	Thu Nov 18 19:44:00 1999
@@ -25,6 +25,10 @@
 \fB\-c\fR
 (ignored)
 .TP
+\fB\-C\fR
+Install file, unless target already exists and is the same as the new file,
+in which case the modification time won't be changed.
+.TP
 \fB\-d\fR, \fB\-\-directory\fR
 treat all arguments as directory names; create all components of the specified directories
 .TP
diff -urN fileutils-4.0-orig/src/install.c fileutils-4.0/src/install.c
--- fileutils-4.0-orig/src/install.c	Mon Oct  5 14:21:58 1998
+++ fileutils-4.0/src/install.c	Thu Nov 18 19:47:12 1999
@@ -68,6 +72,7 @@
 #include <stdio.h>
 #include <getopt.h>
 #include <sys/types.h>
+#include <sys/mman.h>
 #include <pwd.h>
 #include <grp.h>
 
@@ -172,6 +177,9 @@
    no effect. */
 static mode_t mode = 0755;
 
+/* Compare files before installing (-C) */
+static int docompare=0;
+
 /* If nonzero, strip executable files after copying them. */
 static int strip_files;
 
@@ -201,6 +209,82 @@
   {NULL, 0, NULL, 0}
 };
 
+int compare (const char *file, const char *to)
+{
+  void *p, *q;
+  int ret=0;
+  size_t size;
+  int done=0;
+  struct stat file_s, to_s;
+  int file_fd, to_fd;
+  
+  stat(file, &file_s);
+  stat(to, &to_s);
+  
+  if (file_s.st_size != to_s.st_size)
+    return 1;
+
+  file_fd = open(file, O_RDONLY);
+  if (file_fd < 0)
+    return 1;
+  
+  to_fd = open(to, O_RDONLY);
+  if (to_fd < 0)
+    {
+      close(file_fd);
+      return 1;
+    }
+      
+  size = (size_t) file_s.st_size;
+  if (size <= 4194309) /* Don't try to mmap() files > 4 MB */
+    {
+      p = mmap(NULL, size, PROT_READ, MAP_SHARED, file_fd, (off_t) 0);
+      if (p != MAP_FAILED)
+	{
+          q = mmap(NULL, size, PROT_READ, MAP_SHARED, to_fd, (off_t) 0);
+          if (q == MAP_FAILED)
+            {
+              munmap(p, size);
+            }
+	  else
+            {
+              ret = (memcmp(p, q, size)==0) ? 0 : 1;
+              munmap(p, size);
+              munmap(q, size);
+              done = 1;
+            }
+       }
+    }
+  if (!done)
+    {
+      char buf1[65536], buf2[65536];
+      int n1, n2;
+
+      lseek(file_fd, 0, SEEK_SET);
+      lseek(to_fd, 0, SEEK_SET);
+      while (ret == 0)
+        {
+          n1 = read(file_fd, buf1, sizeof(buf1));
+          if (n1 == 0)
+            break;
+          else if (n1 > 0)
+            {
+              n2 = read(to_fd, buf2, n1);
+              if (n2 == n1)
+                ret = memcmp(buf1, buf2, n1);
+              else
+                ret = 1; /* ouf of sync */
+            }
+          else
+            ret = 1; /* read failure */
+        }
+    }
+
+  close(file_fd);
+  close(to_fd);
+  return ret;
+}
+
 static void
 cp_option_init (struct cp_options *x)
 {
@@ -267,7 +351,7 @@
     simple_backup_suffix = version;
   version = getenv ("VERSION_CONTROL");
 
-  while ((optc = getopt_long (argc, argv, "bcsDdg:m:o:pvV:S:", long_options,
+  while ((optc = getopt_long (argc, argv, "bcCsDdg:m:o:pvV:S:", long_options,
 			      NULL)) != -1)
     {
       switch (optc)
@@ -279,6 +363,9 @@
 	  break;
 	case 'c':
 	  break;
+	case 'C':
+	  docompare=1;
+	  break;
 	case 's':
 	  strip_files = 1;
 	  break;
@@ -495,6 +582,12 @@
       return 1;
     }
 
+  if (docompare)
+    {
+      if(compare(from, to)==0) /* Files are identical */
+	return 0;
+    }
+  
   fail = copy (from, to, nonexistent_dst, x, &copy_into_self, NULL);
 
   return fail;
