diff options
author | James Youngman <jay@gnu.org> | 2008-02-12 12:00:32 +0000 |
---|---|---|
committer | James Youngman <jay@gnu.org> | 2008-02-12 12:00:32 +0000 |
commit | 22de27a812cff5a33422eabb2f296ce35c8349ba (patch) | |
tree | 8ac5aa94031c26ae8c9830f947d9b0ac3e41943d | |
parent | ca9d2f5d004ed825149fe5d48cc18ad31048e41c (diff) | |
download | findutils-22de27a812cff5a33422eabb2f296ce35c8349ba.tar.gz |
Fix Savannah bug #22056, -Xtime tests are off by one second.
-rw-r--r-- | ChangeLog | 19 | ||||
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | find/defs.h | 5 | ||||
-rw-r--r-- | find/parser.c | 61 | ||||
-rw-r--r-- | find/testsuite/Makefile.am | 1 | ||||
-rw-r--r-- | find/testsuite/find.posix/mtime0.exp | 10 | ||||
-rw-r--r-- | find/testsuite/find.posix/mtime0.xo | 1 | ||||
-rw-r--r-- | find/util.c | 5 |
8 files changed, 78 insertions, 27 deletions
@@ -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' @@ -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; |