[Top][All Lists]
[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
- [PATCH] cp --update --preserve,
Paolo Montrasio <=