- closes #123

Signed-off-by: Jakub Filak <[email protected]>
---
 src/include/dump_dir.h |  1 +
 src/lib/dump_dir.c     | 68 ++++++++++++++++++++++++++++++++++----------------
 2 files changed, 48 insertions(+), 21 deletions(-)

diff --git a/src/include/dump_dir.h b/src/include/dump_dir.h
index 21169c8..63c0639 100644
--- a/src/include/dump_dir.h
+++ b/src/include/dump_dir.h
@@ -45,6 +45,7 @@ struct dump_dir {
     gid_t dd_gid;
     /* mode fo saved files */
     mode_t mode;
+    time_t dd_time;
 };
 
 void dd_close(struct dump_dir *dd);
diff --git a/src/lib/dump_dir.c b/src/lib/dump_dir.c
index f7732ea..2736ba9 100644
--- a/src/lib/dump_dir.c
+++ b/src/lib/dump_dir.c
@@ -109,18 +109,19 @@ static bool exist_file_dir(const char *path)
     return false;
 }
 
-/* Returns true if the file is not readable or */
-/* if the file doesn't contain valid unixt time stamp */
-/* implementation is a compromise between efficiency and accuracy */
-/* the function gets false negative results for big numbers */
-static bool not_valid_time_file(const char *filename)
+/* Returns value less than 0 if the file is not readable or
+ * if the file doesn't contain valid unixt time stamp.
+ *
+ * Any possible failure will be logged.
+ */
+static long int parse_time_file(const char *filename)
 {
     /* Open input file, and parse it. */
     int fd = open(filename, O_RDONLY | O_NOFOLLOW);
     if (fd < 0)
     {
         VERB2 perror_msg("Can't open '%s'", filename);
-        return true;
+        return -1;
     }
 
     /* ~ maximal number of digits for positive time stamp string*/
@@ -133,18 +134,17 @@ static bool not_valid_time_file(const char *filename)
     if (rdsz == -1)
     {
         VERB2 perror_msg("Can't read from '%s'", filename);
-        return true;
+        return -1;
     }
-
     /* approximate maximal number of digits in timestamp is sizeof(time_t)*3 */
     /* buffer has this size + 1 byte for trailing '\0' */
     /* if whole size of buffer was read then file is bigger */
     /* than string representing maximal time stamp */
     if (rdsz == sizeof(time_buf))
     {
-        VERB2 log("File '%s' is too long to be valid unix "
-                  "time stamp (max size %zdB)", filename, sizeof(time_buf));
-        return true;
+        VERB2 error_msg("File '%s' is too long to be valid unix "
+                        "time stamp (max size %zdB)", filename, 
sizeof(time_buf));
+        return -1;
     }
 
     /* Our tools don't put trailing newline into time file,
@@ -154,16 +154,38 @@ static bool not_valid_time_file(const char *filename)
         rdsz--;
     time_buf[rdsz] = '\0';
 
-    /* the value should fit to timestamp number range because of file size */
-    /* condition above, hence check if the value string consists only from 
digits */
-    if (!isdigit_str(time_buf))
+    errno = 0;    /* To distinguish success/failure after call */
+    char *endptr;
+    long val = strtol(time_buf, &endptr, /* base */ 10);
+
+    /* Check for various possible errors */
+    if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
+            || (errno != 0 && val == 0))
     {
-        VERB2 log("File '%s' doesn't contain valid unix "
-                  "time stamp ('%s')", filename, time_buf);
-        return true;
+        VERB2 perror_msg("File '%s' doesn't contain valid unix "
+                         "time stamp ('%s')", filename, time_buf);
+        return -1;
     }
 
-    return false;
+    if (endptr == time_buf)
+    {
+        VERB2 error_msg("No digits were found in file '%s'", filename);
+        return -1;
+    }
+
+    if (*endptr != '\0')
+    {
+        VERB2 error_msg("Further characters after number: '%s' in file '%s'", 
endptr, filename);
+        return -1;
+    }
+
+    if (val < 0)
+    {
+        VERB2 error_msg("Negative time found in file '%s'", filename);
+    }
+
+    /* If we got here, strtol() successfully parsed a number */
+    return val;
 }
 
 /* Return values:
@@ -260,7 +282,8 @@ static int dd_lock(struct dump_dir *dd, unsigned 
sleep_usec, int flags)
     if (sleep_usec == WAIT_FOR_OTHER_PROCESS_USLEEP) /* yes */
     {
         strcpy(lock_buf + dirname_len, "/"FILENAME_TIME);
-        if (not_valid_time_file(lock_buf))
+        dd->dd_time = parse_time_file(lock_buf);
+        if (dd->dd_time < 0)
         {
             /* time file doesn't exist. We managed to lock the directory
              * which was just created by somebody else, or is almost deleted
@@ -302,7 +325,9 @@ static void dd_unlock(struct dump_dir *dd)
 
 static inline struct dump_dir *dd_init(void)
 {
-    return (struct dump_dir*)xzalloc(sizeof(struct dump_dir));
+    struct dump_dir* dd = (struct dump_dir*)xzalloc(sizeof(struct dump_dir));
+    dd->dd_time = -1;
+    return dd;
 }
 
 int dd_exist(const struct dump_dir *dd, const char *path)
@@ -361,7 +386,8 @@ struct dump_dir *dd_opendir(const char *dir, int flags)
              && access(dir, R_OK) == 0
             ) {
                 char *time_file_name = concat_path_file(dir, FILENAME_TIME);
-                if (not_valid_time_file(time_file_name))
+                dd->dd_time = parse_time_file(time_file_name);
+                if (dd->dd_time < 0)
                 {
                     dd_close(dd);
                     dd = NULL;
-- 
1.8.1.2

Reply via email to