Merge branch 'collectd-4.4'
[collectd.git] / src / common.c
index 974a29e..fd7c199 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * collectd - src/common.c
- * Copyright (C) 2005-2007  Florian octo Forster
+ * Copyright (C) 2005-2008  Florian octo Forster
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -24,6 +24,7 @@
 # include "config.h"
 #endif
 
+#include "collectd.h"
 #include "common.h"
 #include "plugin.h"
 
@@ -48,11 +49,30 @@ extern kstat_ctl_t *kc;
 static pthread_mutex_t getpwnam_r_lock = PTHREAD_MUTEX_INITIALIZER;
 #endif
 
-void sstrncpy (char *d, const char *s, int len)
+#if !HAVE_STRERROR_R
+static pthread_mutex_t strerror_r_lock = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+char *sstrncpy (char *dest, const char *src, size_t n)
 {
-       strncpy (d, s, len);
-       d[len - 1] = '\0';
-}
+       strncpy (dest, src, n);
+       dest[n - 1] = '\0';
+
+       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)
 {
@@ -63,12 +83,12 @@ char *sstrdup (const char *s)
 
        if((r = strdup (s)) == NULL)
        {
-               DEBUG ("Not enough memory.");
-               exit(3);
+               ERROR ("Not enough memory.");
+               exit (3);
        }
 
        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_
@@ -76,29 +96,44 @@ char *sstrdup (const char *s)
 char *sstrerror (int errnum, char *buf, size_t buflen)
 {
        buf[0] = '\0';
-#ifdef STRERROR_R_CHAR_P
+
+#if !HAVE_STRERROR_R
+       {
+               char *temp;
+
+               pthread_mutex_lock (&strerror_r_lock);
+
+               temp = strerror (errnum);
+               sstrncpy (buf, temp, buflen);
+
+               pthread_mutex_unlock (&strerror_r_lock);
+       }
+/* #endif !HAVE_STRERROR_R */
+
+#elif STRERROR_R_CHAR_P
        {
                char *temp;
                temp = strerror_r (errnum, buf, 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);
-                       buf[buflen - 1] = '\0';
                }
        }
+/* #endif STRERROR_R_CHAR_P */
+
 #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 */
 
@@ -108,12 +143,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)
@@ -156,7 +191,7 @@ ssize_t sread (int fd, void *buf, size_t count)
                        return (-1);
                }
 
-               assert (nleft >= status);
+               assert ((0 > status) || (nleft >= (size_t)status));
 
                nleft = nleft - status;
                ptr   = ptr   + status;
@@ -201,7 +236,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++;
@@ -217,8 +252,8 @@ int strjoin (char *dst, size_t dst_len,
                char **fields, size_t fields_num,
                const char *sep)
 {
-       int field_len;
-       int sep_len;
+       size_t field_len;
+       size_t sep_len;
        int i;
 
        memset (dst, '\0', dst_len);
@@ -230,7 +265,7 @@ int strjoin (char *dst, size_t dst_len,
        if (sep != NULL)
                sep_len = strlen (sep);
 
-       for (i = 0; i < fields_num; i++)
+       for (i = 0; i < (int)fields_num; i++)
        {
                if ((i > 0) && (sep_len > 0))
                {
@@ -353,7 +388,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);
 
        /*
@@ -368,8 +403,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
@@ -454,8 +488,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)
        {
@@ -534,7 +567,7 @@ long long get_kstat_value (kstat_t *ksp, char *name)
 
 unsigned long long ntohll (unsigned long long n)
 {
-#if __BYTE_ORDER == __BIG_ENDIAN
+#if BYTE_ORDER == BIG_ENDIAN
        return (n);
 #else
        return (((unsigned long long) ntohl (n)) << 32) + ntohl (n >> 32);
@@ -543,13 +576,90 @@ unsigned long long ntohll (unsigned long long n)
 
 unsigned long long htonll (unsigned long long n)
 {
-#if __BYTE_ORDER == __BIG_ENDIAN
+#if BYTE_ORDER == BIG_ENDIAN
        return (n);
 #else
        return (((unsigned long long) htonl (n)) << 32) + htonl (n >> 32);
 #endif
 } /* unsigned long long htonll */
 
+#if FP_LAYOUT_NEED_NOTHING
+/* Well, we need nothing.. */
+/* #endif FP_LAYOUT_NEED_NOTHING */
+
+#elif FP_LAYOUT_NEED_ENDIANFLIP || FP_LAYOUT_NEED_INTSWAP
+# if FP_LAYOUT_NEED_ENDIANFLIP
+#  define FP_CONVERT(A) ((((uint64_t)(A) & 0xff00000000000000LL) >> 56) | \
+                         (((uint64_t)(A) & 0x00ff000000000000LL) >> 40) | \
+                         (((uint64_t)(A) & 0x0000ff0000000000LL) >> 24) | \
+                         (((uint64_t)(A) & 0x000000ff00000000LL) >> 8)  | \
+                         (((uint64_t)(A) & 0x00000000ff000000LL) << 8)  | \
+                         (((uint64_t)(A) & 0x0000000000ff0000LL) << 24) | \
+                         (((uint64_t)(A) & 0x000000000000ff00LL) << 40) | \
+                         (((uint64_t)(A) & 0x00000000000000ffLL) << 56))
+# else
+#  define FP_CONVERT(A) ((((uint64_t)(A) & 0xffffffff00000000LL) >> 32) | \
+                         (((uint64_t)(A) & 0x00000000ffffffffLL) << 32))
+# endif
+
+double ntohd (double d)
+{
+       union
+       {
+               uint8_t  byte[8];
+               uint64_t integer;
+               double   floating;
+       } ret;
+
+       ret.floating = d;
+
+       /* NAN in x86 byte order */
+       if ((ret.byte[0] == 0x00) && (ret.byte[1] == 0x00)
+                       && (ret.byte[2] == 0x00) && (ret.byte[3] == 0x00)
+                       && (ret.byte[4] == 0x00) && (ret.byte[5] == 0x00)
+                       && (ret.byte[6] == 0xf8) && (ret.byte[7] == 0x7f))
+       {
+               return (NAN);
+       }
+       else
+       {
+               uint64_t tmp;
+
+               tmp = ret.integer;
+               ret.integer = FP_CONVERT (tmp);
+               return (ret.floating);
+       }
+} /* double ntohd */
+
+double htond (double d)
+{
+       union
+       {
+               uint8_t  byte[8];
+               uint64_t integer;
+               double   floating;
+       } ret;
+
+       if (isnan (d))
+       {
+               ret.byte[0] = ret.byte[1] = ret.byte[2] = ret.byte[3] = 0x00;
+               ret.byte[4] = ret.byte[5] = 0x00;
+               ret.byte[6] = 0xf8;
+               ret.byte[7] = 0x7f;
+               return (ret.floating);
+       }
+       else
+       {
+               uint64_t tmp;
+
+               ret.floating = d;
+               tmp = FP_CONVERT (ret.integer);
+               ret.integer = tmp;
+               return (ret.floating);
+       }
+} /* double htond */
+#endif /* FP_LAYOUT_NEED_ENDIANFLIP || FP_LAYOUT_NEED_INTSWAP */
+
 int format_name (char *ret, int ret_len,
                const char *hostname,
                const char *plugin, const char *plugin_instance,
@@ -563,21 +673,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);
        }
@@ -726,4 +836,75 @@ int getpwnam_r (const char *name, struct passwd *pwbuf, char *buf,
 
        return (status);
 } /* int getpwnam_r */
-#endif
+#endif /* !HAVE_GETPWNAM_R */
+
+int notification_init (notification_t *n, int severity, const char *message,
+               const char *host,
+               const char *plugin, const char *plugin_instance,
+               const char *type, const char *type_instance)
+{
+       memset (n, '\0', sizeof (notification_t));
+
+       n->severity = severity;
+
+       if (message != NULL)
+               sstrncpy (n->message, message, sizeof (n->message));
+       if (host != NULL)
+               sstrncpy (n->host, host, sizeof (n->host));
+       if (plugin != NULL)
+               sstrncpy (n->plugin, plugin, sizeof (n->plugin));
+       if (plugin_instance != NULL)
+               sstrncpy (n->plugin_instance, plugin_instance,
+                               sizeof (n->plugin_instance));
+       if (type != NULL)
+               sstrncpy (n->type, type, sizeof (n->type));
+       if (type_instance != NULL)
+               sstrncpy (n->type_instance, type_instance,
+                               sizeof (n->type_instance));
+
+       return (0);
+} /* int notification_init */
+
+int walk_directory (const char *dir, dirwalk_callback_f callback)
+{
+       struct dirent *ent;
+       DIR *dh;
+       int ok = 0;
+
+       if ((dh = opendir (dir)) == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("Cannot open '%s': %s", dir,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return -1;
+       }
+
+       while ((ent = readdir (dh)) != NULL)
+       {
+               if (ent->d_name[0] == '.')
+                       continue;
+
+               if (!callback(ent->d_name))
+                       ++ok;
+       }
+
+       closedir (dh);
+
+       return ok ? 0 : -1;
+}
+
+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;
+}
+
+