Merge branch 'collectd-4.5' into collectd-4.6
[collectd.git] / src / common.c
index aeea28d..b654719 100644 (file)
@@ -18,6 +18,8 @@
  * Authors:
  *   Florian octo Forster <octo at verplant.org>
  *   Niki W. Waibel <niki.waibel@gmx.net>
+ *   Sebastian Harl <sh at tokkee.org>
+ *   Michał Mirosław <mirq-linux at rere.qmqm.pl>
 **/
 
 #if HAVE_CONFIG_H
@@ -347,28 +349,56 @@ int escape_slashes (char *buf, int buf_len)
        return (0);
 } /* int escape_slashes */
 
-int timeval_sub_timespec (struct timeval *tv0, struct timeval *tv1, struct timespec *ret)
+int timeval_cmp (struct timeval tv0, struct timeval tv1, struct timeval *delta)
 {
-       if ((tv0 == NULL) || (tv1 == NULL) || (ret == NULL))
-               return (-2);
+       struct timeval *larger;
+       struct timeval *smaller;
 
-       if ((tv0->tv_sec < tv1->tv_sec)
-                       || ((tv0->tv_sec == tv1->tv_sec) && (tv0->tv_usec < tv1->tv_usec)))
-               return (-1);
+       int status;
 
-       ret->tv_sec  = tv0->tv_sec - tv1->tv_sec;
-       ret->tv_nsec = 1000 * ((long) (tv0->tv_usec - tv1->tv_usec));
+       NORMALIZE_TIMEVAL (tv0);
+       NORMALIZE_TIMEVAL (tv1);
 
-       if (ret->tv_nsec < 0)
+       if ((tv0.tv_sec == tv1.tv_sec) && (tv0.tv_usec == tv1.tv_usec))
        {
-               assert (ret->tv_sec > 0);
+               if (delta != NULL) {
+                       delta->tv_sec  = 0;
+                       delta->tv_usec = 0;
+               }
+               return (0);
+       }
 
-               ret->tv_nsec += 1000000000;
-               ret->tv_sec  -= 1;
+       if ((tv0.tv_sec < tv1.tv_sec)
+                       || ((tv0.tv_sec == tv1.tv_sec) && (tv0.tv_usec < tv1.tv_usec)))
+       {
+               larger  = &tv1;
+               smaller = &tv0;
+               status  = -1;
+       }
+       else
+       {
+               larger  = &tv0;
+               smaller = &tv1;
+               status  = 1;
        }
 
-       return (0);
-}
+       if (delta != NULL) {
+               delta->tv_sec = larger->tv_sec - smaller->tv_sec;
+
+               if (smaller->tv_usec <= larger->tv_usec)
+                       delta->tv_usec = larger->tv_usec - smaller->tv_usec;
+               else
+               {
+                       --delta->tv_sec;
+                       delta->tv_usec = 1000000 + larger->tv_usec - smaller->tv_usec;
+               }
+       }
+
+       assert ((delta == NULL)
+                       || ((0 <= delta->tv_usec) && (delta->tv_usec < 1000000)));
+
+       return (status);
+} /* int timeval_cmp */
 
 int check_create_dir (const char *file_orig)
 {
@@ -383,7 +413,7 @@ int check_create_dir (const char *file_orig)
        char *saveptr;
        int   last_is_file = 1;
        int   path_is_absolute = 0;
-       int   len;
+       size_t len;
        int   i;
 
        /*
@@ -439,7 +469,8 @@ int check_create_dir (const char *file_orig)
                 */
                if (fields[i][0] == '.')
                {
-                       ERROR ("Cowardly refusing to create a directory that begins with a `.' (dot): `%s'", file_orig);
+                       ERROR ("Cowardly refusing to create a directory that "
+                                       "begins with a `.' (dot): `%s'", file_orig);
                        return (-2);
                }
 
@@ -454,32 +485,42 @@ int check_create_dir (const char *file_orig)
                        return (-1);
                }
 
-               if (stat (dir, &statbuf) == -1)
-               {
-                       if (errno == ENOENT)
+               while (42) {
+                       if (stat (dir, &statbuf) == -1)
                        {
-                               if (mkdir (dir, 0755) == -1)
+                               if (errno == ENOENT)
                                {
+                                       if (mkdir (dir, 0755) == 0)
+                                               break;
+
+                                       /* this might happen, if a different thread created
+                                        * the directory in the meantime
+                                        * => call stat() again to check for S_ISDIR() */
+                                       if (EEXIST == errno)
+                                               continue;
+
                                        char errbuf[1024];
                                        ERROR ("check_create_dir: mkdir (%s): %s", dir,
                                                        sstrerror (errno,
                                                                errbuf, sizeof (errbuf)));
                                        return (-1);
                                }
+                               else
+                               {
+                                       char errbuf[1024];
+                                       ERROR ("check_create_dir: stat (%s): %s", dir,
+                                                       sstrerror (errno, errbuf,
+                                                               sizeof (errbuf)));
+                                       return (-1);
+                               }
                        }
-                       else
+                       else if (!S_ISDIR (statbuf.st_mode))
                        {
-                               char errbuf[1024];
-                               ERROR ("stat (%s): %s", dir,
-                                               sstrerror (errno, errbuf,
-                                                       sizeof (errbuf)));
+                               ERROR ("check_create_dir: `%s' exists but is not "
+                                               "a directory!", dir);
                                return (-1);
                        }
-               }
-               else if (!S_ISDIR (statbuf.st_mode))
-               {
-                       ERROR ("stat (%s): Not a directory!", dir);
-                       return (-1);
+                       break;
                }
        }