findutils-patches
[Top][All Lists]
Advanced

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

[Findutils-patches] [PATCH] Fix Savannah bug #22056, -Xtime tests are of


From: James Youngman
Subject: [Findutils-patches] [PATCH] Fix Savannah bug #22056, -Xtime tests are off by one second.
Date: Sat, 9 Feb 2008 15:22:25 +0000

2008-02-09  James Youngman  <address@hidden>

        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.

Signed-off-by: James Youngman <address@hidden>
---
 NEWS                                 |    3 ++
 find/defs.h                          |    5 +--
 find/parser.c                        |   61 +++++++++++++++++++++-------------
 find/testsuite/Makefile.am           |    1 +
 find/testsuite/find.posix/mtime0.exp |   10 +++++
 find/testsuite/find.posix/mtime0.xo  |    1 +
 find/util.c                          |    5 ++-
 7 files changed, 59 insertions(+), 27 deletions(-)
 create mode 100644 find/testsuite/find.posix/mtime0.exp
 create mode 100644 find/testsuite/find.posix/mtime0.xo

diff --git a/NEWS b/NEWS
index d947f64..e139d3c 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 c3e330b..d076aa9 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 7eaefc1..b7ef88f 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 3712f0c..0f98e0c 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 0000000..23237a1
--- /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 0000000..74c14ef
--- /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 f057f5d..40f36d5 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;
-- 
1.5.3.8





reply via email to

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