* the old implementation checks only presence of the time file
* now we check validity of the time file

Signed-off-by: Jakub Filak <[email protected]>
---
 src/lib/dump_dir.c |   57 +++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 54 insertions(+), 3 deletions(-)

diff --git a/src/lib/dump_dir.c b/src/lib/dump_dir.c
index eef01f7..e945bad 100644
--- a/src/lib/dump_dir.c
+++ b/src/lib/dump_dir.c
@@ -109,6 +109,57 @@ static bool exist_file_dir(const char *path)
     return false;
 }
 
+static bool not_valid_time_file(const char *filename)
+{
+    /* Open input file, and parse it. */
+    int fd = open(filename, O_RDONLY);
+    if (fd < 0)
+    {
+        VERB1 log("Unable to open '%s': %s.\n", filename, strerror(errno));
+        return true;
+    }
+
+    off_t size = lseek(fd, 0, SEEK_END);
+    if (size == (off_t)-1) /* EOVERFLOW? */
+    {
+        VERB1 log("Unable to seek in '%s': %s.\n", filename, strerror(errno));
+        close(fd);
+        return true;
+    }
+
+    lseek(fd, 0, SEEK_SET); /* No reason to fail. */
+
+    static const size_t FILE_SIZE_LIMIT = sizeof(time_t) * 3; /* ~ maximal 
number of digits */
+    if (size > FILE_SIZE_LIMIT)
+    {
+        VERB1 log("Input file too big (%lld). Maximum size is %zd.\n",
+                (long long)size, FILE_SIZE_LIMIT);
+        close(fd);
+        return true;
+    }
+
+    char *time_str = xmalloc(size + 1);
+    if (size != read(fd, time_str, size))
+    {
+        VERB1 log("Unable to read from '%s'.\n", filename);
+        close(fd);
+        free(time_str);
+        return true;
+    }
+
+    /* Just reading, so no need to check the returned value. */
+    close(fd);
+
+    time_str[size] = '\0';
+
+    /* range should OK because of file size condition above */
+    const bool invalidity = !isdigit_str(time_str);
+
+    free(time_str);
+
+    return invalidity;
+}
+
 /* Return values:
  * -1: error (in this case, errno is 0 if error message is already logged)
  *  0: failed to lock (someone else has it locked)
@@ -203,7 +254,7 @@ 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 (access(lock_buf, F_OK) != 0)
+        if (not_valid_time_file(lock_buf))
         {
             /* time file doesn't exist. We managed to lock the directory
              * which was just created by somebody else, or is almost deleted
@@ -212,7 +263,7 @@ static int dd_lock(struct dump_dir *dd, unsigned 
sleep_usec, int flags)
              */
             strcpy(lock_buf + dirname_len, "/.lock");
             xunlink(lock_buf);
-            VERB1 log("Unlocked '%s' (no time file)", lock_buf);
+            VERB1 log("Unlocked '%s' (no or corrupted time file)", lock_buf);
             if (--count == 0)
             {
                 errno = EISDIR; /* "this is an ordinary dir, not dump dir" */
@@ -303,7 +354,7 @@ 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 (access(time_file_name, R_OK) != 0)
+                if (not_valid_time_file(time_file_name))
                 {
                     dd_close(dd);
                     dd = NULL;
-- 
1.7.10.4

Reply via email to