Moved remove_special() from the bind plugin to the "common" module.
[collectd.git] / src / common.c
index 82b4aaa..3ec4c6e 100644 (file)
@@ -61,18 +61,37 @@ char *sstrncpy (char *dest, const char *src, size_t n)
        return (dest);
 } /* char *sstrncpy */
 
+int ssnprintf (char *dest, size_t n, const char *format, ...)
+{
+       int ret = 0;
+       va_list ap;
+
+       va_start (ap, format);
+       ret = vsnprintf (dest, n, format, ap);
+       dest[n - 1] = '\0';
+       va_end (ap);
+
+       return (ret);
+} /* int ssnprintf */
+
 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)
        {
-               ERROR ("Not enough memory.");
+               ERROR ("sstrdup: Out of memory.");
                exit (3);
        }
+       memcpy (r, s, sizeof (char) * sz);
 
        return (r);
 } /* char *sstrdup */
@@ -91,7 +110,7 @@ char *sstrerror (int errnum, char *buf, size_t buflen)
                pthread_mutex_lock (&strerror_r_lock);
 
                temp = strerror (errnum);
-               strncpy (buf, temp, buflen);
+               sstrncpy (buf, temp, buflen);
 
                pthread_mutex_unlock (&strerror_r_lock);
        }
@@ -104,9 +123,9 @@ char *sstrerror (int errnum, char *buf, size_t buflen)
                if (buf[0] == '\0')
                {
                        if ((temp != NULL) && (temp != buf) && (temp[0] != '\0'))
-                               strncpy (buf, temp, buflen);
+                               sstrncpy (buf, temp, buflen);
                        else
-                               strncpy (buf, "strerror_r did not return "
+                               sstrncpy (buf, "strerror_r did not return "
                                                "an error message", buflen);
                }
        }
@@ -115,13 +134,12 @@ char *sstrerror (int errnum, char *buf, size_t buflen)
 #else
        if (strerror_r (errnum, buf, buflen) != 0)
        {
-               snprintf (buf, buflen, "Error #%i; "
+               ssnprintf (buf, buflen, "Error #%i; "
                                "Additionally, strerror_r failed.",
                                errnum);
        }
 #endif /* STRERROR_R_CHAR_P */
 
-       buf[buflen - 1] = '\0';
        return (buf);
 } /* char *sstrerror */
 
@@ -329,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;
 
-       ret->tv_sec  = tv0->tv_sec - tv1->tv_sec;
-       ret->tv_nsec = 1000 * ((long) (tv0->tv_usec - tv1->tv_usec));
+       int status;
 
-       if (ret->tv_nsec < 0)
+       NORMALIZE_TIMEVAL (tv0);
+       NORMALIZE_TIMEVAL (tv1);
+
+       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)
 {
@@ -365,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;
 
        /*
@@ -376,7 +435,7 @@ int check_create_dir (const char *file_orig)
 
        if ((len = strlen (file_orig)) < 1)
                return (-1);
-       else if (len >= 512)
+       else if (len >= sizeof (file_copy))
                return (-1);
 
        /*
@@ -391,8 +450,7 @@ int check_create_dir (const char *file_orig)
        /*
         * Create a copy for `strtok_r' to destroy
         */
-       strncpy (file_copy, file_orig, 512);
-       file_copy[511] = '\0';
+       sstrncpy (file_copy, file_orig, sizeof (file_copy));
 
        /*
         * Break into components. This will eat up several slashes in a row and
@@ -477,8 +535,7 @@ int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name)
        if (kc == NULL)
                return (-1);
 
-       snprintf (ident, 128, "%s,%i,%s", module, instance, name);
-       ident[127] = '\0';
+       ssnprintf (ident, sizeof (ident), "%s,%i,%s", module, instance, name);
 
        if (*ksp_ptr == NULL)
        {
@@ -527,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
@@ -663,21 +720,21 @@ int format_name (char *ret, int ret_len,
        if ((plugin_instance == NULL) || (strlen (plugin_instance) == 0))
        {
                if ((type_instance == NULL) || (strlen (type_instance) == 0))
-                       status = snprintf (ret, ret_len, "%s/%s/%s",
+                       status = ssnprintf (ret, ret_len, "%s/%s/%s",
                                        hostname, plugin, type);
                else
-                       status = snprintf (ret, ret_len, "%s/%s/%s-%s",
+                       status = ssnprintf (ret, ret_len, "%s/%s/%s-%s",
                                        hostname, plugin, type,
                                        type_instance);
        }
        else
        {
                if ((type_instance == NULL) || (strlen (type_instance) == 0))
-                       status = snprintf (ret, ret_len, "%s/%s-%s/%s",
+                       status = ssnprintf (ret, ret_len, "%s/%s-%s/%s",
                                        hostname, plugin, plugin_instance,
                                        type);
                else
-                       status = snprintf (ret, ret_len, "%s/%s-%s/%s-%s",
+                       status = ssnprintf (ret, ret_len, "%s/%s-%s/%s-%s",
                                        hostname, plugin, plugin_instance,
                                        type, type_instance);
        }
@@ -838,26 +895,93 @@ int notification_init (notification_t *n, int severity, const char *message,
        n->severity = severity;
 
        if (message != NULL)
-               strncpy (n->message, message, sizeof (n->message));
+               sstrncpy (n->message, message, sizeof (n->message));
        if (host != NULL)
-               strncpy (n->host, host, sizeof (n->host));
+               sstrncpy (n->host, host, sizeof (n->host));
        if (plugin != NULL)
-               strncpy (n->plugin, plugin, sizeof (n->plugin));
+               sstrncpy (n->plugin, plugin, sizeof (n->plugin));
        if (plugin_instance != NULL)
-               strncpy (n->plugin_instance, plugin_instance,
+               sstrncpy (n->plugin_instance, plugin_instance,
                                sizeof (n->plugin_instance));
        if (type != NULL)
-               strncpy (n->type, type, sizeof (n->type));
+               sstrncpy (n->type, type, sizeof (n->type));
        if (type_instance != NULL)
-               strncpy (n->type_instance, type_instance,
+               sstrncpy (n->type_instance, type_instance,
                                sizeof (n->type_instance));
 
-       n->message[sizeof (n->message) - 1] = '\0';
-       n->host[sizeof (n->host) - 1] = '\0';
-       n->plugin[sizeof (n->plugin) - 1] = '\0';
-       n->plugin_instance[sizeof (n->plugin_instance) - 1] = '\0';
-       n->type[sizeof (n->type) - 1] = '\0';
-       n->type_instance[sizeof (n->type_instance) - 1] = '\0';
-
        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 */