summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Youngman <jay@gnu.org>2008-02-12 12:00:32 +0000
committerJames Youngman <jay@gnu.org>2008-02-12 12:00:32 +0000
commit22de27a812cff5a33422eabb2f296ce35c8349ba (patch)
tree8ac5aa94031c26ae8c9830f947d9b0ac3e41943d
parentca9d2f5d004ed825149fe5d48cc18ad31048e41c (diff)
downloadfindutils-22de27a812cff5a33422eabb2f296ce35c8349ba.tar.gz
Fix Savannah bug #22056, -Xtime tests are off by one second.
-rw-r--r--ChangeLog19
-rw-r--r--NEWS3
-rw-r--r--find/defs.h5
-rw-r--r--find/parser.c61
-rw-r--r--find/testsuite/Makefile.am1
-rw-r--r--find/testsuite/find.posix/mtime0.exp10
-rw-r--r--find/testsuite/find.posix/mtime0.xo1
-rw-r--r--find/util.c5
8 files changed, 78 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index 6590c08e..563b8ab8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2008-02-12 James Youngman <jay@gnu.org>
+
+ Fix Savannah bug #22056, -Xtime tests are off by one second.
+ * find/defs.h (struct options): Change cur_day_start from time_t
+ to strct timespec.
+ * find/util.c (set_option_defaults): Likewise.
+ * find/parser.c (get_relative_timestamp): Change the origin
+ argument from time_t to struct timespec.
+ (estimate_timestamp_success_rate): Ignore the nanoseconds field of
+ the timestamp when estimating the probable success rate.
+ (parse_daystart): Handle the nanoseconds field too.
+ (do_parse_xmin): The origin argument to get_relative_timestamp()
+ is of type struct timespec, not time_t.
+ (parse_used): Likewise.
+ (parse_time): Likewise.
+ * find/testsuite/Makefile.am (EXTRA_DIST_EXP): Added test for
+ -mtime 0; find.posix/mtime0.{exp,xo}.
+ * NEWS: mention this bugfix.
+
2008-02-09 James Youngman <jay@gnu.org>
* doc/find.texi (xargs options): Moved documentation of xargs'
diff --git a/NEWS b/NEWS
index d947f648..e139d3c6 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,9 @@ GNU findutils NEWS - User visible changes. -*- outline -*- (allout)
atomically, instead of just claiming the rename is atomic in a
comment.
+#22056: -Xtime tests are off by one second (e.g. rm -f x; touch x;
+find x -mtime 0 should print x).
+
#21960: xargs should collect the exit status of child processes even if
the total count of unreaped children has not yet reached the maximum
allowed.
diff --git a/find/defs.h b/find/defs.h
index c3e330b8..d076aa9b 100644
--- a/find/defs.h
+++ b/find/defs.h
@@ -571,9 +571,8 @@ struct options
struct timespec start_time; /* Time at start of execution. */
- /* Seconds between 00:00 1/1/70 and either one day before now
- (the default), or the start of today (if -daystart is given). */
- time_t cur_day_start;
+ /* Either one day before now (the default), or the start of today (if -daystart is given). */
+ struct timespec cur_day_start;
/* If true, cur_day_start has been adjusted to the start of the day. */
boolean full_days;
diff --git a/find/parser.c b/find/parser.c
index 7eaefc18..b7ef88f8 100644
--- a/find/parser.c
+++ b/find/parser.c
@@ -185,7 +185,7 @@ static boolean get_comp_type PARAMS((const char **str,
enum comparison_type *comp_type));
static boolean get_relative_timestamp PARAMS((const char *str,
struct time_val *tval,
- time_t origin,
+ struct timespec origin,
double sec_per_unit,
const char *overflowmessage));
static boolean get_num PARAMS((const char *str,
@@ -613,7 +613,11 @@ estimate_file_age_success_rate(float num_days)
static float
estimate_timestamp_success_rate(time_t when)
{
- int num_days = (options.cur_day_start - when) / 86400;
+ /* This calculation ignores the nanoseconds field of the
+ * origin, but I don't think that makes much difference
+ * to our estimate.
+ */
+ int num_days = (options.cur_day_start.tv_sec - when) / 86400;
return estimate_file_age_success_rate(num_days);
}
@@ -764,12 +768,13 @@ parse_daystart (const struct parser_table* entry, char **argv, int *arg_ptr)
if (options.full_days == false)
{
- options.cur_day_start += DAYSECS;
- local = localtime (&options.cur_day_start);
- options.cur_day_start -= (local
- ? (local->tm_sec + local->tm_min * 60
- + local->tm_hour * 3600)
- : options.cur_day_start % DAYSECS);
+ options.cur_day_start.tv_sec += DAYSECS;
+ options.cur_day_start.tv_nsec = 0;
+ local = localtime (&options.cur_day_start.tv_sec);
+ options.cur_day_start.tv_sec -= (local
+ ? (local->tm_sec + local->tm_min * 60
+ + local->tm_hour * 3600)
+ : options.cur_day_start.tv_sec % DAYSECS);
options.full_days = true;
}
return true;
@@ -1381,8 +1386,9 @@ do_parse_xmin (const struct parser_table* entry,
{
struct time_val tval;
tval.xval = xv;
- if (get_relative_timestamp(minutes, &tval,
- options.cur_day_start + DAYSECS, 60,
+ struct timespec origin = options.cur_day_start;
+ origin.tv_sec += DAYSECS;
+ if (get_relative_timestamp(minutes, &tval, origin, 60,
"arithmetic overflow while converting %s "
"minutes to a number of seconds"))
{
@@ -2397,7 +2403,8 @@ parse_used (const struct parser_table* entry, char **argv, int *arg_ptr)
if (collect_arg(argv, arg_ptr, &offset_str))
{
/* The timespec is actually a delta value, so we use an origin of 0. */
- if (get_relative_timestamp(offset_str, &tval, 0, DAYSECS, errmsg))
+ struct timespec zero = {0,0};
+ if (get_relative_timestamp(offset_str, &tval, zero, DAYSECS, errmsg))
{
our_pred = insert_primary (entry);
our_pred->args.reftime = tval;
@@ -3223,12 +3230,12 @@ insert_exec_ok (const char *action,
static boolean
get_relative_timestamp (const char *str,
struct time_val *result,
- time_t origin,
+ struct timespec origin,
double sec_per_unit,
const char *overflowmessage)
{
uintmax_t checkval;
- double offset, seconds, f;
+ double offset, seconds, nanosec;
if (get_comp_type(&str, &result->kind))
{
@@ -3245,15 +3252,23 @@ get_relative_timestamp (const char *str,
{
/* Separate the floating point number the user specified
* (which is a number of days, or minutes, etc) into an
- * integral number of seconds (SECONDS) and a fraction (F).
+ * integral number of seconds (SECONDS) and a fraction (NANOSEC).
*/
- f = modf(offset * sec_per_unit, &seconds);
+ nanosec = modf(offset * sec_per_unit, &seconds);
+ nanosec *= 1.0e9; /* convert from fractional seconds to ns. */
- result->ts.tv_sec = origin - seconds;
- result->ts.tv_nsec = fabs(f * 1e9);
-
+ result->ts.tv_sec = origin.tv_sec - seconds;
+ result->ts.tv_nsec = origin.tv_nsec - nanosec;
+ checkval = (uintmax_t)origin.tv_sec - seconds;
+
+ if (origin.tv_nsec < nanosec)
+ {
+ /* Perform a carry operation */
+ result->ts.tv_nsec += 1000000000;
+ result->ts.tv_sec -= 1;
+ checkval -= 1;
+ }
/* Check for overflow. */
- checkval = (uintmax_t)origin - seconds;
if (checkval != result->ts.tv_sec)
{
/* an overflow has occurred. */
@@ -3294,7 +3309,7 @@ parse_time (const struct parser_table* entry, char *argv[], int *arg_ptr)
const char *timearg, *orig_timearg;
const char *errmsg = "arithmetic overflow while converting %s "
"days to a number of seconds";
- time_t origin;
+ struct timespec origin;
if (!collect_arg(argv, arg_ptr, &timearg))
return false;
@@ -3310,9 +3325,9 @@ parse_time (const struct parser_table* entry, char *argv[], int *arg_ptr)
*/
if (COMP_LT == comp)
{
- uintmax_t expected = origin + (DAYSECS-1);
- origin += (DAYSECS-1);
- if (origin != expected)
+ uintmax_t expected = origin.tv_sec + (DAYSECS-1);
+ origin.tv_sec += (DAYSECS-1);
+ if (origin.tv_sec != expected)
{
error(1, 0,
_("arithmetic overflow when trying to calculate the end of today"));
diff --git a/find/testsuite/Makefile.am b/find/testsuite/Makefile.am
index 3712f0ca..0f98e0c0 100644
--- a/find/testsuite/Makefile.am
+++ b/find/testsuite/Makefile.am
@@ -190,6 +190,7 @@ find.posix/grouping.exp \
find.posix/group-empty.exp \
find.posix/group-missing.exp \
find.posix/links.exp \
+find.posix/mtime0.exp \
find.posix/sv-bug-11175.exp \
find.posix/sv-bug-12181.exp \
find.posix/depth1.exp \
diff --git a/find/testsuite/find.posix/mtime0.exp b/find/testsuite/find.posix/mtime0.exp
new file mode 100644
index 00000000..23237a1c
--- /dev/null
+++ b/find/testsuite/find.posix/mtime0.exp
@@ -0,0 +1,10 @@
+## Test for find . -mtime 0
+## This detects Savannah bug #22056, -Xtime tests are off by one second
+
+exec rm -rf tmp
+exec mkdir tmp
+# Touch the file in the setup phase, to make sure its mtime is as
+# recent as possible.
+proc prep {} { exec touch tmp/x }
+find_start p { tmp -type f -mtime 0 } "" "" prep
+exec rm -rf tmp
diff --git a/find/testsuite/find.posix/mtime0.xo b/find/testsuite/find.posix/mtime0.xo
new file mode 100644
index 00000000..74c14ef1
--- /dev/null
+++ b/find/testsuite/find.posix/mtime0.xo
@@ -0,0 +1 @@
+tmp/x
diff --git a/find/util.c b/find/util.c
index f057f5de..40f36d5a 100644
--- a/find/util.c
+++ b/find/util.c
@@ -925,8 +925,11 @@ set_option_defaults(struct options *p)
p->do_dir_first = true;
p->explicit_depth = false;
p->maxdepth = p->mindepth = -1;
+
p->start_time = now();
- p->cur_day_start = p->start_time.tv_sec - DAYSECS;
+ p->cur_day_start.tv_sec = p->start_time.tv_sec - DAYSECS;
+ p->cur_day_start.tv_nsec = p->start_time.tv_nsec;
+
p->full_days = false;
p->stay_on_filesystem = false;
p->ignore_readdir_race = false;