Moved remove_special() from the bind plugin to the "common" module.
[collectd.git] / src / common.c
index 3f6eecc..3ec4c6e 100644 (file)
@@ -77,18 +77,24 @@ int ssnprintf (char *dest, size_t n, const char *format, ...)
 char *sstrdup (const char *s)
 {
        char *r;
+       size_t sz;
 
        if (s == NULL)
                return (NULL);
 
-       if((r = strdup (s)) == NULL)
+       /* Do not use `strdup' here, because it's not specified in POSIX. It's
+        * ``only'' an XSI extension. */
+       sz = strlen (s) + 1;
+       r = (char *) malloc (sizeof (char) * sz);
+       if (r == NULL)
        {
-               DEBUG ("Not enough memory.");
-               exit(3);
+               ERROR ("sstrdup: Out of memory.");
+               exit (3);
        }
+       memcpy (r, s, sizeof (char) * sz);
 
        return (r);
-}
+} /* char *sstrdup */
 
 /* Even though Posix requires "strerror_r" to return an "int",
  * some systems (e.g. the GNU libc) return a "char *" _and_
@@ -143,12 +149,12 @@ void *smalloc (size_t size)
 
        if ((r = malloc (size)) == NULL)
        {
-               DEBUG("Not enough memory.");
-               exit(3);
+               ERROR ("Not enough memory.");
+               exit (3);
        }
 
-       return r;
-}
+       return (r);
+} /* void *smalloc */
 
 #if 0
 void sfree (void **ptr)
@@ -236,7 +242,7 @@ int strsplit (char *string, char **fields, size_t size)
        i = 0;
        ptr = string;
        saveptr = NULL;
-       while ((fields[i] = strtok_r (ptr, " \t", &saveptr)) != NULL)
+       while ((fields[i] = strtok_r (ptr, " \t\r\n", &saveptr)) != NULL)
        {
                ptr = NULL;
                i++;
@@ -341,28 +347,69 @@ 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)
+void replace_special (char *buffer, size_t buffer_size)
 {
-       if ((tv0 == NULL) || (tv1 == NULL) || (ret == NULL))
-               return (-2);
+       size_t i;
 
-       if ((tv0->tv_sec < tv1->tv_sec)
-                       || ((tv0->tv_sec == tv1->tv_sec) && (tv0->tv_usec < tv1->tv_usec)))
-               return (-1);
+       for (i = 0; i < buffer_size; i++)
+       {
+               if (buffer[i] == 0)
+                       return;
+               if ((!isalnum ((int) buffer[i])) && (buffer[i] != '-'))
+                       buffer[i] = '_';
+       }
+} /* void replace_special */
+
+int timeval_cmp (struct timeval tv0, struct timeval tv1, struct timeval *delta)
+{
+       struct timeval *larger;
+       struct timeval *smaller;
+
+       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)
 {
@@ -377,7 +424,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;
 
        /*
@@ -537,12 +584,12 @@ long long get_kstat_value (kstat_t *ksp, char *name)
 #else
        if (ksp == NULL)
        {
-               fprintf (stderr, "ERROR: %s:%i: ksp == NULL\n", __FILE__, __LINE__);
+               ERROR ("ERROR: %s:%i: ksp == NULL\n", __FILE__, __LINE__);
                return (-1LL);
        }
        else if (ksp->ks_type != KSTAT_TYPE_NAMED)
        {
-               fprintf (stderr, "ERROR: %s:%i: ksp->ks_type != KSTAT_TYPE_NAMED\n", __FILE__, __LINE__);
+               ERROR ("ERROR: %s:%i: ksp->ks_type != KSTAT_TYPE_NAMED\n", __FILE__, __LINE__);
                return (-1LL);
        }
 #endif
@@ -864,3 +911,77 @@ int notification_init (notification_t *n, int severity, const char *message,
 
        return (0);
 } /* int notification_init */
+
+int walk_directory (const char *dir, dirwalk_callback_f callback,
+               void *user_data)
+{
+       struct dirent *ent;
+       DIR *dh;
+       int success;
+       int failure;
+
+       success = 0;
+       failure = 0;
+
+       if ((dh = opendir (dir)) == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("walk_directory: Cannot open '%s': %s", dir,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return -1;
+       }
+
+       while ((ent = readdir (dh)) != NULL)
+       {
+               int status;
+
+               if (ent->d_name[0] == '.')
+                       continue;
+
+               status = (*callback) (dir, ent->d_name, user_data);
+               if (status != 0)
+                       failure++;
+               else
+                       success++;
+       }
+
+       closedir (dh);
+
+       if ((success == 0) && (failure > 0))
+               return (-1);
+       return (0);
+}
+
+int read_file_contents (const char *filename, char *buf, int bufsize)
+{
+       FILE *fh;
+       int n;
+
+       if ((fh = fopen (filename, "r")) == NULL)
+               return -1;
+
+       n = fread(buf, 1, bufsize, fh);
+       fclose(fh);
+
+       return n;
+}
+
+counter_t counter_diff (counter_t old_value, counter_t new_value)
+{
+       counter_t diff;
+
+       if (old_value > new_value)
+       {
+               if (old_value <= 4294967295U)
+                       diff = (4294967295U - old_value) + new_value;
+               else
+                       diff = (18446744073709551615ULL - old_value)
+                               + new_value;
+       }
+       else
+       {
+               diff = new_value - old_value;
+       }
+
+       return (diff);
+} /* counter_t counter_to_gauge */