bug-coreutils
[Top][All Lists]
Advanced

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

[PATCH] cp --update --preserve


From: Paolo Montrasio
Subject: [PATCH] cp --update --preserve
Date: Fri, 9 Jan 2004 13:34:53 +0100

I was trying to combine the many options of cp to create a simple backup 
program when I run into an unexpected behaviour of the program. I was using the 
cp from the fileutils 1.4.2 distribution, so I downloaded coreutils-5.0 and 
compiled it and I still have the same problem. Here it is the test case.

Run this script

------------------------------------------------------------------------------
#!/bin/sh

if [ ! -d bug-demo-dir ]; then
  mkdir bug-demo-dir
else
  rm bug-demo-dir/*
fi
cd bug-demo-dir
echo source > source
cp --backup=numbered --preserve --update source dest
cp --backup=numbered --preserve --update source dest
ls -la dest*
------------------------------------------------------------------------------

(The --backup option is there only to spot the problem more easily.)
You'll see that the source file is copied twice.
The behaviour I expected is that the second run of cp won't copy anything, 
because the source file didn't change.
However cp does copy it and this seems to break the semantic of the --update 
option, if I got it right.

I looked at the source code (src/copy.c) and I found that utime is used to 
preserve the timestamps. It seems that utime sets the nanoseconds of the 
timestamp of the destination file to zero, making it older than the source 
file. That's why it is copied again over the destination after the check made 
by --update on the second run of cp.

The fix I devised is to make cp check if --update is used together 
--preserve=timestamps
In that case cp will use a modified timestamp comparation macro that doesn't 
look at the nanoseconds. IMHO this
level of inaccuracy is good enough for the kind of applications that the 
combination of those two options is useful for. The patch is below.

(copy-original.c is the file in the coreutils distribution, copy-new.c is my 
version)

------------------------------------------------------------------------------
--- copy-original.c     2003-03-11 19:02:23.000000000 +0100
+++ copy-new.c  2004-01-09 12:56:56.497432000 +0100
@@ -46,6 +46,12 @@
 #include "same.h"
 #include "xreadlink.h"

+
+/* 2 macros to handle timestamp comparison in the --preserve --update case */
+#define ST_TIME_CMP_SEC(a, b, s) \
+  ((a).s < (b).s ? -1 : (a).s > (b).s ? 1 : 0)
+#define MTIME_CMP_SEC(a, b) ST_TIME_CMP_SEC (a, b, st_mtime)
+
 #define DO_CHOWN(Chown, File, New_uid, New_gid)
\
   (Chown (File, New_uid, New_gid)                                      \
    /* If non-root uses -p, it's ok if we can't preserve ownership.     \
@@ -800,6 +806,7 @@
   int copied_as_regular = 0;
   int ran_chown = 0;
   int preserve_metadata;
+  int preserve_update_test;

   if (x->move_mode && rename_succeeded)
     *rename_succeeded = 0;
@@ -906,8 +913,20 @@
                  return 1;
                }

-             if (x->update && MTIME_CMP (src_sb, dst_sb) <= 0)
-               {
+              /* If --update is used in combination with preservation of
+               * timestamps, don't use nanoseconds when comparing timestamps.
+               */
+              if (x->preserve_timestamps && x->update)
+                {
+                  preserve_update_test = MTIME_CMP_SEC (src_sb, dst_sb);
+                }
+              else
+                {
+                  preserve_update_test = x->update
+                                               && MTIME_CMP (src_sb, dst_sb);
+                }
+              if (preserve_update_test <= 0)
+                {
                  /* We're using --update and the source file is older
                     than the destination file, so there is no need to
                     copy or move.  */
------------------------------------------------------------------------------

If you run the test script with this version of cp you'll see that it copies 
the source file only once.

If I'm mistaken about the semantic of --update or if there is a way to get this 
result without patching cp, I'd love to learn it.

Paolo
--
Play Go! http://www.figg.org





reply via email to

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