diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2011-01-30 11:22:51 -0800 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2011-01-30 11:22:51 -0800 |
commit | fcabb1a6e66f7e6cf4fe0984c4d5c169f4decd8a (patch) | |
tree | 4926d2f913499164126038fc65515eff32521172 | |
parent | 253f7d1bc55aec58986aa36f8a6e4725d311ed24 (diff) | |
parent | 3de84ad9c45382c181e3383d433442f4e19ba722 (diff) | |
download | emacs-fcabb1a6e66f7e6cf4fe0984c4d5c169f4decd8a.tar.gz emacs-fcabb1a6e66f7e6cf4fe0984c4d5c169f4decd8a.tar.bz2 emacs-fcabb1a6e66f7e6cf4fe0984c4d5c169f4decd8a.zip |
Merge: import mktime and move-if-change fixes from gnulib
-rw-r--r-- | ChangeLog | 99 | ||||
-rwxr-xr-x | configure | 19 | ||||
-rw-r--r-- | lib/intprops.h | 4 | ||||
-rw-r--r-- | lib/mktime.c | 198 | ||||
-rw-r--r-- | m4/mktime.m4 | 21 | ||||
-rwxr-xr-x | move-if-change | 16 |
6 files changed, 268 insertions, 89 deletions
diff --git a/ChangeLog b/ChangeLog index 6bf329b4d2f..2878150f5cb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,102 @@ +2011-01-30 Paul Eggert <eggert@cs.ucla.edu> + + gnulib: import mktime and move-if-change fixes from gnulib + + * configure: Regenerate from the following. + + 2011-01-30 Paul Eggert <eggert@cs.ucla.edu> + + mktime: clarify long_int width checking + * lib/mktime.c (long_int_is_wide_enough): Move this assertion to + the top level, to make it clearer that the assumption about + long_int width is being checked. See + <http://lists.gnu.org/archive/html/bug-gnulib/2011-01/msg00554.html>. + + 2011-01-29 Paul Eggert <eggert@cs.ucla.edu> + + TYPE_MAXIMUM: avoid theoretically undefined behavior + * lib/intprops.h (TYPE_MINIMUM, TYPE_MAXIMUM): Do not shift a + negative number, which the C Standard says has undefined behavior. + In practice this is not a problem, but might as well do it by the book. + Reported by Rich Felker and Eric Blake; see + <http://lists.gnu.org/archive/html/bug-gnulib/2011-01/msg00493.html>. + * m4/mktime.m4 (AC_FUNC_MKTIME): Likewise. + * lib/mktime.c (TYPE_MAXIMUM): Redo slightly to match the others. + + mktime: #undef mktime before #defining it + * lib/mktime.c (mktime) [DEBUG]: #undef mktime before #defining it. + + mktime: systematically normalize tm_isdst comparisons + * lib/mktime.c (isdst_differ): New function. + (__mktime_internal): Use it systematically for all isdst comparisons. + This completes the fix for libc BZ #6723, and removes the need for + normalizing tm_isdst. See + <http://sourceware.org/bugzilla/show_bug.cgi?id=6723> + (not_equal_tm) [DEBUG]: Use isdst_differ here, too. + + mktime: fix some integer overflow issues and sidestep the rest + + This was prompted by a bug report by Benjamin Lindner for MinGW + <http://lists.gnu.org/archive/html/bug-gnulib/2011-01/msg00472.html>. + His bug is due to signed integer overflow (0 - INT_MIN), and I + I scanned through mktime.c looking for other integer overflow + problems, fixing all the bugs I found. + + Although the C Standard says the resulting code is still not safe + in the presence of integer overflow, in practice it should be good + enough for all real-world two's-complement implementations, except + for debugging environments that deliberately trap on integer + overflow (e.g., gcc -ftrapv). + + * lib/mktime.c (WRAPV): New macro. + (SHR): Also check that long_int and time_t shift right in the + usual way, before using the fast-but-unportable method. + (TYPE_ONES_COMPLEMENT, TYPE_SIGNED_MAGNITUDE): Remove, no longer + used. The code already assumed two's complement, so there's + no need to test for alternatives. All uses removed. + (TYPE_MAXIMUM): Don't rely here on overflow behavior not defined by + the C standard. Problem reported by Rich Felker in + <http://lists.gnu.org/archive/html/bug-gnulib/2011-01/msg00488.html>. + (twos_complement_arithmetic): Also check long_int and time_t. + (time_t_avg, time_t_add_ok, time_t_int_add_ok): New functions. + (guess_time_tm, ranged_convert, __mktime_internal): Use them. + (__mktime_internal): Avoid integer overflow with unary subtraction + in two instances where -1 - X is an adequate replacement for -X, + since the calculations are approximate. + + 2011-01-29 Eric Blake <eblake@redhat.com> + + mktime: avoid infinite loop + * m4/mktime.m4 (AC_FUNC_MKTIME): Avoid overflow on possibly-signed + type; behavior is still undefined but portable to all known targets. + Reported by Rich Felker. + + 2011-01-28 Paul Eggert <eggert@cs.ucla.edu> + + mktime: avoid problems on NetBSD 5 / i386 + * lib/mktime.c (long_int): New type. This works around a problem + on NetBSD 5 / i386, where 'long int' and 'int' are both 32 bits + but time_t is 64 bits, and where I expect the existing code is + wrong in some cases. + (leapyear, ydhms_diff, guess_time_tm, __mktime_internal): Use it. + (ydhms_diff): Bring back the compile-time check for wide-enough + year and yday. + + mktime: fix misspelling in comment + * lib/mktime.c (__mktime_internal): Fix misspelling in comment. + This merges all recent glibc changes of importance. + + 2011-01-28 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + move-if-change: cope with concurrent mv of identical file. + * move-if-change (CMPPROG): Accept environment + variable as an override for `cmp'. + (usage): Document CMPPROG. + Adjust comparison to drop stdout. Cope with failure of mv if + the target file exists and is identical to the source, for + parallel builds. + Report from H.J. Lu against binutils in PR binutils/12283. + 2011-01-29 Eli Zaretskii <eliz@gnu.org> * lib/makefile.w32-in: diff --git a/configure b/configure index c8b5263db17..0aa010d3c65 100755 --- a/configure +++ b/configure @@ -14906,20 +14906,23 @@ main () int result = 0; time_t t, delta; int i, j; + int time_t_signed_magnitude = (time_t) ~ (time_t) 0 < (time_t) -1; + int time_t_signed = ! ((time_t) 0 < (time_t) -1); /* This test makes some buggy mktime implementations loop. Give up after 60 seconds; a mktime slower than that isn't worth using anyway. */ alarm (60); - for (;;) - { - t = (time_t_max << 1) + 1; - if (t <= time_t_max) - break; - time_t_max = t; - } - time_t_min = - ((time_t) ~ (time_t) 0 == (time_t) -1) - time_t_max; + time_t_max = (! time_t_signed + ? (time_t) -1 + : ((((time_t) 1 << (sizeof (time_t) * CHAR_BIT - 2)) - 1) + * 2 + 1)); + time_t_min = (! time_t_signed + ? (time_t) 0 + : time_t_signed_magnitude + ? ~ (time_t) 0 + : ~ time_t_max); delta = time_t_max / 997; /* a suitable prime number */ for (i = 0; i < N_STRINGS; i++) diff --git a/lib/intprops.h b/lib/intprops.h index 511a5aa9890..58b1b3fbf44 100644 --- a/lib/intprops.h +++ b/lib/intprops.h @@ -49,11 +49,11 @@ ? (t) 0 \ : TYPE_SIGNED_MAGNITUDE (t) \ ? ~ (t) 0 \ - : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))) + : ~ TYPE_MAXIMUM (t))) # define TYPE_MAXIMUM(t) \ ((t) (! TYPE_SIGNED (t) \ ? (t) -1 \ - : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))) + : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1))) /* Return zero if T can be determined to be an unsigned type. Otherwise, return 1. diff --git a/lib/mktime.c b/lib/mktime.c index f77330564fc..c68ad9ba262 100644 --- a/lib/mktime.c +++ b/lib/mktime.c @@ -25,6 +25,24 @@ # include <config.h> #endif +/* Some of the code in this file assumes that signed integer overflow + silently wraps around. This assumption can't easily be programmed + around, nor can it be checked for portably at compile-time or + easily eliminated at run-time. + + Define WRAPV to 1 if the assumption is valid. Otherwise, define it + to 0; this forces the use of slower code that, while not guaranteed + by the C Standard, works on all production platforms that we know + about. */ +#ifndef WRAPV +# if (__GNUC__ == 4 && 4 <= __GNUC_MINOR__) || 4 < __GNUC__ +# pragma GCC optimize ("wrapv") +# define WRAPV 1 +# else +# define WRAPV 0 +# endif +#endif + /* Assume that leap seconds are possible, unless told otherwise. If the host has a `zic' command with a `-L leapsecondfilename' option, then it supports leap seconds; otherwise it probably doesn't. */ @@ -42,9 +60,21 @@ # include <stdio.h> # include <stdlib.h> /* Make it work even if the system's libc has its own mktime routine. */ +# undef mktime # define mktime my_mktime #endif /* DEBUG */ +/* Verify a requirement at compile-time (unlike assert, which is runtime). */ +#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; } + +/* A signed type that is at least one bit wider than int. */ +#if INT_MAX <= LONG_MAX / 2 +typedef long int long_int; +#else +typedef long long int long_int; +#endif +verify (long_int_is_wide_enough, INT_MAX == INT_MAX * (long_int) 2 / 2); + /* Shift A right by B bits portably, by dividing A by 2**B and truncating towards minus infinity. A and B should be free of side effects, and B should be in the range 0 <= B <= INT_BITS - 2, where @@ -55,9 +85,11 @@ implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift right in the usual way when A < 0, so SHR falls back on division if ordinary A >> B doesn't seem to be the usual signed shift. */ -#define SHR(a, b) \ - (-1 >> 1 == -1 \ - ? (a) >> (b) \ +#define SHR(a, b) \ + ((-1 >> 1 == -1 \ + && (long_int) -1 >> 1 == -1 \ + && ((time_t) -1 >> 1 == -1 || ! TYPE_SIGNED (time_t))) \ + ? (a) >> (b) \ : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0)) /* The extra casts in the following macros work around compiler bugs, @@ -68,12 +100,8 @@ #define TYPE_IS_INTEGER(t) ((t) 1.5 == 1) /* True if negative values of the signed integer type T use two's - complement, ones' complement, or signed magnitude representation, - respectively. Much GNU code assumes two's complement, but some - people like to be portable to all possible C hosts. */ + complement, or if T is an unsigned integer type. */ #define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1) -#define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0) -#define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1) /* True if the arithmetic type T is signed. */ #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) @@ -85,13 +113,11 @@ #define TYPE_MINIMUM(t) \ ((t) (! TYPE_SIGNED (t) \ ? (t) 0 \ - : TYPE_SIGNED_MAGNITUDE (t) \ - ? ~ (t) 0 \ - : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))) + : ~ TYPE_MAXIMUM (t))) #define TYPE_MAXIMUM(t) \ ((t) (! TYPE_SIGNED (t) \ ? (t) -1 \ - : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))) + : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1))) #ifndef TIME_T_MIN # define TIME_T_MIN TYPE_MINIMUM (time_t) @@ -101,14 +127,11 @@ #endif #define TIME_T_MIDPOINT (SHR (TIME_T_MIN + TIME_T_MAX, 1) + 1) -/* Verify a requirement at compile-time (unlike assert, which is runtime). */ -#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; } - verify (time_t_is_integer, TYPE_IS_INTEGER (time_t)); -verify (twos_complement_arithmetic, TYPE_TWOS_COMPLEMENT (int)); -/* The code also assumes that signed integer overflow silently wraps - around, but this assumption can't be stated without causing a - diagnostic on some hosts. */ +verify (twos_complement_arithmetic, + (TYPE_TWOS_COMPLEMENT (int) + && TYPE_TWOS_COMPLEMENT (long_int) + && TYPE_TWOS_COMPLEMENT (time_t))); #define EPOCH_YEAR 1970 #define TM_YEAR_BASE 1900 @@ -116,7 +139,7 @@ verify (base_year_is_a_multiple_of_100, TM_YEAR_BASE % 100 == 0); /* Return 1 if YEAR + TM_YEAR_BASE is a leap year. */ static inline int -leapyear (long int year) +leapyear (long_int year) { /* Don't add YEAR to TM_YEAR_BASE, as that might overflow. Also, work even if YEAR is negative. */ @@ -150,6 +173,14 @@ const unsigned short int __mon_yday[2][13] = # include "mktime-internal.h" #endif +/* Return 1 if the values A and B differ according to the rules for + tm_isdst: A and B differ if one is zero and the other positive. */ +static int +isdst_differ (int a, int b) +{ + return (!a != !b) & (0 <= a) & (0 <= b); +} + /* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) - (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks were not adjusted between the time stamps. @@ -162,15 +193,10 @@ const unsigned short int __mon_yday[2][13] = detect overflow. */ static inline time_t -ydhms_diff (long int year1, long int yday1, int hour1, int min1, int sec1, +ydhms_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1, int year0, int yday0, int hour0, int min0, int sec0) { verify (C99_integer_division, -1 / 2 == 0); -#if 0 /* This assertion fails on 32-bit systems with 64-bit time_t, such as - NetBSD 5 on i386. */ - verify (long_int_year_and_yday_are_wide_enough, - INT_MAX <= LONG_MAX / 2 || TIME_T_MAX <= UINT_MAX); -#endif /* Compute intervening leap days correctly even if year is negative. Take care to avoid integer overflow here. */ @@ -193,6 +219,53 @@ ydhms_diff (long int year1, long int yday1, int hour1, int min1, int sec1, return seconds; } +/* Return the average of A and B, even if A + B would overflow. */ +static time_t +time_t_avg (time_t a, time_t b) +{ + return SHR (a, 1) + SHR (b, 1) + (a & b & 1); +} + +/* Return 1 if A + B does not overflow. If time_t is unsigned and if + B's top bit is set, assume that the sum represents A - -B, and + return 1 if the subtraction does not wrap around. */ +static int +time_t_add_ok (time_t a, time_t b) +{ + if (! TYPE_SIGNED (time_t)) + { + time_t sum = a + b; + return (sum < a) == (TIME_T_MIDPOINT <= b); + } + else if (WRAPV) + { + time_t sum = a + b; + return (sum < a) == (b < 0); + } + else + { + time_t avg = time_t_avg (a, b); + return TIME_T_MIN / 2 <= avg && avg <= TIME_T_MAX / 2; + } +} + +/* Return 1 if A + B does not overflow. */ +static int +time_t_int_add_ok (time_t a, int b) +{ + verify (int_no_wider_than_time_t, INT_MAX <= TIME_T_MAX); + if (WRAPV) + { + time_t sum = a + b; + return (sum < a) == (b < 0); + } + else + { + int a_odd = a & 1; + time_t avg = SHR (a, 1) + (SHR (b, 1) + (a_odd & b)); + return TIME_T_MIN / 2 <= avg && avg <= TIME_T_MAX / 2; + } +} /* Return a time_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC), assuming that *T corresponds to *TP and that no clock adjustments @@ -201,7 +274,7 @@ ydhms_diff (long int year1, long int yday1, int hour1, int min1, int sec1, If overflow occurs, yield the minimal or maximal value, except do not yield a value equal to *T. */ static time_t -guess_time_tm (long int year, long int yday, int hour, int min, int sec, +guess_time_tm (long_int year, long_int yday, int hour, int min, int sec, const time_t *t, const struct tm *tp) { if (tp) @@ -209,9 +282,8 @@ guess_time_tm (long int year, long int yday, int hour, int min, int sec, time_t d = ydhms_diff (year, yday, hour, min, sec, tp->tm_year, tp->tm_yday, tp->tm_hour, tp->tm_min, tp->tm_sec); - time_t t1 = *t + d; - if ((t1 < *t) == (TYPE_SIGNED (time_t) ? d < 0 : TIME_T_MAX / 2 < d)) - return t1; + if (time_t_add_ok (*t, d)) + return *t + d; } /* Overflow occurred one way or another. Return the nearest result @@ -243,9 +315,7 @@ ranged_convert (struct tm *(*convert) (const time_t *, struct tm *), they differ by 1. */ while (bad != ok + (bad < 0 ? -1 : 1)) { - time_t mid = *t = (bad < 0 - ? bad + ((ok - bad) >> 1) - : ok + ((bad - ok) >> 1)); + time_t mid = *t = time_t_avg (ok, bad); r = convert (t, tp); if (r) ok = mid; @@ -294,9 +364,7 @@ __mktime_internal (struct tm *tp, int mday = tp->tm_mday; int mon = tp->tm_mon; int year_requested = tp->tm_year; - /* Normalize the value. */ - int isdst = ((tp->tm_isdst >> (8 * sizeof (tp->tm_isdst) - 1)) - | (tp->tm_isdst != 0)); + int isdst = tp->tm_isdst; /* 1 if the previous probe was DST. */ int dst2; @@ -305,8 +373,8 @@ __mktime_internal (struct tm *tp, int mon_remainder = mon % 12; int negative_mon_remainder = mon_remainder < 0; int mon_years = mon / 12 - negative_mon_remainder; - long int lyear_requested = year_requested; - long int year = lyear_requested + mon_years; + long_int lyear_requested = year_requested; + long_int year = lyear_requested + mon_years; /* The other values need not be in range: the remaining code handles minor overflows correctly, @@ -318,8 +386,8 @@ __mktime_internal (struct tm *tp, int mon_yday = ((__mon_yday[leapyear (year)] [mon_remainder + 12 * negative_mon_remainder]) - 1); - long int lmday = mday; - long int yday = mon_yday + lmday; + long_int lmday = mday; + long_int yday = mon_yday + lmday; time_t guessed_offset = *offset; @@ -373,9 +441,9 @@ __mktime_internal (struct tm *tp, int approx_biennia = SHR (t0, ALOG2_SECONDS_PER_BIENNIUM); int diff = approx_biennia - approx_requested_biennia; - int abs_diff = diff < 0 ? - diff : diff; + int abs_diff = diff < 0 ? -1 - diff : diff; - /* IRIX 4.0.5 cc miscaculates TIME_T_MIN / 3: it erroneously + /* IRIX 4.0.5 cc miscalculates TIME_T_MIN / 3: it erroneously gives a positive value of 715827882. Setting a variable first then doing math on it seems to work. (ghazi@caip.rutgers.edu) */ @@ -391,7 +459,7 @@ __mktime_internal (struct tm *tp, time_t repaired_t0 = -1 - t0; approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM); diff = approx_biennia - approx_requested_biennia; - abs_diff = diff < 0 ? - diff : diff; + abs_diff = diff < 0 ? -1 - diff : diff; if (overflow_threshold < abs_diff) return -1; guessed_offset += repaired_t0 - t0; @@ -426,7 +494,7 @@ __mktime_internal (struct tm *tp, /* We have a match. Check whether tm.tm_isdst has the requested value, if any. */ - if (isdst != tm.tm_isdst && 0 <= isdst && 0 <= tm.tm_isdst) + if (isdst_differ (isdst, tm.tm_isdst)) { /* tm.tm_isdst has the wrong value. Look for a neighboring time with the right value, and use its UTC offset. @@ -459,22 +527,20 @@ __mktime_internal (struct tm *tp, for (delta = stride; delta < delta_bound; delta += stride) for (direction = -1; direction <= 1; direction += 2) - { - time_t ot = t + delta * direction; - if ((ot < t) == (direction < 0)) - { - struct tm otm; - ranged_convert (convert, &ot, &otm); - if (otm.tm_isdst == isdst) - { - /* We found the desired tm_isdst. - Extrapolate back to the desired time. */ - t = guess_time_tm (year, yday, hour, min, sec, &ot, &otm); - ranged_convert (convert, &t, &tm); - goto offset_found; - } - } - } + if (time_t_int_add_ok (t, delta * direction)) + { + time_t ot = t + delta * direction; + struct tm otm; + ranged_convert (convert, &ot, &otm); + if (! isdst_differ (isdst, otm.tm_isdst)) + { + /* We found the desired tm_isdst. + Extrapolate back to the desired time. */ + t = guess_time_tm (year, yday, hour, min, sec, &ot, &otm); + ranged_convert (convert, &t, &tm); + goto offset_found; + } + } } offset_found: @@ -485,11 +551,13 @@ __mktime_internal (struct tm *tp, /* Adjust time to reflect the tm_sec requested, not the normalized value. Also, repair any damage from a false match due to a leap second. */ int sec_adjustment = (sec == 0 && tm.tm_sec == 60) - sec; + if (! time_t_int_add_ok (t, sec_requested)) + return -1; t1 = t + sec_requested; + if (! time_t_int_add_ok (t1, sec_adjustment)) + return -1; t2 = t1 + sec_adjustment; - if (((t1 < t) != (sec_requested < 0)) - | ((t2 < t1) != (sec_adjustment < 0)) - | ! convert (&t2, &tm)) + if (! convert (&t2, &tm)) return -1; t = t2; } @@ -540,7 +608,7 @@ not_equal_tm (const struct tm *a, const struct tm *b) | (a->tm_mon ^ b->tm_mon) | (a->tm_year ^ b->tm_year) | (a->tm_yday ^ b->tm_yday) - | (a->tm_isdst ^ b->tm_isdst)); + | isdst_differ (a->tm_isdst, b->tm_isdst)); } static void @@ -664,6 +732,6 @@ main (int argc, char **argv) /* Local Variables: -compile-command: "gcc -DDEBUG -Wall -W -O -g mktime.c -o mktime" +compile-command: "gcc -DDEBUG -I. -Wall -W -O2 -g mktime.c -o mktime" End: */ diff --git a/m4/mktime.m4 b/m4/mktime.m4 index f2b131ba456..56b2416d619 100644 --- a/m4/mktime.m4 +++ b/m4/mktime.m4 @@ -1,4 +1,4 @@ -# serial 17 +# serial 19 dnl Copyright (C) 2002-2003, 2005-2007, 2009-2011 Free Software Foundation, dnl Inc. dnl This file is free software; the Free Software Foundation @@ -165,20 +165,23 @@ main () int result = 0; time_t t, delta; int i, j; + int time_t_signed_magnitude = (time_t) ~ (time_t) 0 < (time_t) -1; + int time_t_signed = ! ((time_t) 0 < (time_t) -1); /* This test makes some buggy mktime implementations loop. Give up after 60 seconds; a mktime slower than that isn't worth using anyway. */ alarm (60); - for (;;) - { - t = (time_t_max << 1) + 1; - if (t <= time_t_max) - break; - time_t_max = t; - } - time_t_min = - ((time_t) ~ (time_t) 0 == (time_t) -1) - time_t_max; + time_t_max = (! time_t_signed + ? (time_t) -1 + : ((((time_t) 1 << (sizeof (time_t) * CHAR_BIT - 2)) - 1) + * 2 + 1)); + time_t_min = (! time_t_signed + ? (time_t) 0 + : time_t_signed_magnitude + ? ~ (time_t) 0 + : ~ time_t_max); delta = time_t_max / 997; /* a suitable prime number */ for (i = 0; i < N_STRINGS; i++) diff --git a/move-if-change b/move-if-change index a891ca51f0c..e7ba25e3127 100755 --- a/move-if-change +++ b/move-if-change @@ -2,7 +2,7 @@ # Like mv $1 $2, but if the files are the same, just delete $1. # Status is zero if successful, nonzero otherwise. -VERSION='2007-09-28 23:10'; # UTC +VERSION='2011-01-28 20:09'; # UTC # The definition above must lie within the first 8 lines in order # for the Emacs time-stamp write hook (at end) to update it. # If you change this file with Emacs, please let the write hook @@ -32,15 +32,18 @@ If SOURCE is different than DEST, then move it to DEST; else remove SOURCE. --help display this help and exit --version output version information and exit +The variable CMPPROG can be used to specify an alternative to \`cmp'. + Report bugs to <bug-gnulib@gnu.org>." version=`expr "$VERSION" : '\([^ ]*\)'` version="move-if-change (gnulib) $version -Copyright (C) 2007 Free Software Foundation, Inc. +Copyright (C) 2011 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law." +cmpprog=${CMPPROG-cmp} for arg do @@ -60,12 +63,15 @@ do esac done -test $# = 2 || { echo "$0: $usage" >&2; exit 1; } +test $# -eq 2 || { echo "$0: $usage" >&2; exit 1; } -if test -r "$2" && cmp -s -- "$1" "$2"; then +if test -r "$2" && $cmpprog -- "$1" "$2" >/dev/null; then rm -f -- "$1" else - mv -f -- "$1" "$2" + if mv -f -- "$1" "$2"; then :; else + # Ignore failure due to a concurrent move-if-change. + test -r "$2" && $cmpprog -- "$1" "$2" >/dev/null && rm -f -- "$1" + fi fi ## Local Variables: |