irq plugin: Fix for non-Linux systems.
[collectd.git] / src / common.c
index 0b603fa..fc34afe 100644 (file)
@@ -1,21 +1,19 @@
 /**
  * collectd - src/common.c
- * Copyright (C) 2005  Florian octo Forster
+ * Copyright (C) 2005-2007  Florian octo Forster
  *
- * This program is free software; you can redistribute it and/
- * or modify it under the terms of the GNU General Public Li-
- * cence as published by the Free Software Foundation; either
- * version 2 of the Licence, or any later version.
+ * 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
+ * Free Software Foundation; only version 2 of the License is applicable.
  *
- * This program is distributed in the hope that it will be use-
- * ful, but WITHOUT ANY WARRANTY; without even the implied war-
- * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public Licence for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
  *
- * You should have received a copy of the GNU General Public
- * Licence along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  *
  * Authors:
  *   Florian octo Forster <octo at verplant.org>
 #include "common.h"
 #include "utils_debug.h"
 
-extern int operating_mode;
+#ifdef HAVE_MATH_H
+#  include <math.h>
+#endif
+
+/* for ntohl and htonl */
+#if HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
 
 #ifdef HAVE_LIBKSTAT
 extern kstat_ctl_t *kc;
 #endif
 
-#ifdef HAVE_LIBRRD
-static char *rra_def[] =
-{
-               "RRA:AVERAGE:0.2:6:1500",
-               "RRA:AVERAGE:0.1:180:1680",
-               "RRA:AVERAGE:0.1:2160:1520",
-               "RRA:MIN:0.2:6:1500",
-               "RRA:MIN:0.1:180:1680",
-               "RRA:MIN:0.1:2160:1520",
-               "RRA:MAX:0.2:6:1500",
-               "RRA:MAX:0.1:180:1680",
-               "RRA:MAX:0.1:2160:1520",
-               NULL
-};
-static int rra_num = 9;
-#endif /* HAVE_LIBRRD */
-
 void sstrncpy (char *d, const char *s, int len)
 {
        strncpy (d, s, len);
@@ -96,6 +84,70 @@ void sfree (void **ptr)
 }
 #endif
 
+ssize_t sread (int fd, void *buf, size_t count)
+{
+       char    *ptr;
+       size_t   nleft;
+       ssize_t  status;
+
+       ptr   = (char *) buf;
+       nleft = count;
+
+       while (nleft > 0)
+       {
+               status = read (fd, (void *) ptr, nleft);
+
+               if ((status < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+                       continue;
+
+               if (status < 0)
+                       return (status);
+
+               if (status == 0)
+               {
+                       DBG ("Received EOF from fd %i. "
+                                       "Closing fd and returning error.",
+                                       fd);
+                       close (fd);
+                       return (-1);
+               }
+
+               assert (nleft >= status);
+
+               nleft = nleft - status;
+               ptr   = ptr   + status;
+       }
+
+       return (0);
+}
+
+
+ssize_t swrite (int fd, const void *buf, size_t count)
+{
+       const char *ptr;
+       size_t      nleft;
+       ssize_t     status;
+
+       ptr   = (const char *) buf;
+       nleft = count;
+
+       while (nleft > 0)
+       {
+               status = write (fd, (const void *) ptr, nleft);
+
+               if ((status < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+                       continue;
+
+               if (status < 0)
+                       return (status);
+
+               nleft = nleft - status;
+               ptr   = ptr   + status;
+       }
+
+       return (0);
+}
+
 int strsplit (char *string, char **fields, size_t size)
 {
        size_t i;
@@ -155,6 +207,27 @@ int strjoin (char *dst, size_t dst_len,
        return (strlen (dst));
 }
 
+int strsubstitute (char *str, char c_from, char c_to)
+{
+       int ret;
+
+       if (str == NULL)
+               return (-1);
+
+       ret = 0;
+       while (*str != '\0')
+       {
+               if (*str == c_from)
+               {
+                       *str = c_to;
+                       ret++;
+               }
+               str++;
+       }
+
+       return (ret);
+}
+
 int escape_slashes (char *buf, int buf_len)
 {
        int i;
@@ -183,7 +256,30 @@ int escape_slashes (char *buf, int buf_len)
        return (0);
 }
 
-static int check_create_dir (const char *file_orig)
+int timeval_sub_timespec (struct timeval *tv0, struct timeval *tv1, struct timespec *ret)
+{
+       if ((tv0 == NULL) || (tv1 == NULL) || (ret == NULL))
+               return (-2);
+
+       if ((tv0->tv_sec < tv1->tv_sec)
+                       || ((tv0->tv_sec == tv1->tv_sec) && (tv0->tv_usec < tv1->tv_usec)))
+               return (-1);
+
+       ret->tv_sec  = tv0->tv_sec - tv1->tv_sec;
+       ret->tv_nsec = 1000 * ((long) (tv0->tv_usec - tv1->tv_usec));
+
+       if (ret->tv_nsec < 0)
+       {
+               assert (ret->tv_sec > 0);
+
+               ret->tv_nsec += 1000000000;
+               ret->tv_sec  -= 1;
+       }
+
+       return (0);
+}
+
+int check_create_dir (const char *file_orig)
 {
        struct stat statbuf;
 
@@ -194,6 +290,7 @@ static int check_create_dir (const char *file_orig)
        int   fields_num;
        char *ptr;
        int   last_is_file = 1;
+       int   path_is_absolute = 0;
        int   len;
        int   i;
 
@@ -214,6 +311,8 @@ static int check_create_dir (const char *file_orig)
         */
        if (file_orig[len - 1] == '/')
                last_is_file = 0;
+       if (file_orig[0] == '/')
+               path_is_absolute = 1;
 
        /*
         * Create a copy for `strtok' to destroy
@@ -255,7 +354,9 @@ static int check_create_dir (const char *file_orig)
                /*
                 * Join the components together again
                 */
-               if (strjoin (dir, dir_len, fields, i + 1, "/") < 0)
+               dir[0] = '/';
+               if (strjoin (dir + path_is_absolute, dir_len - path_is_absolute,
+                                       fields, i + 1, "/") < 0)
                {
                        syslog (LOG_ERR, "strjoin failed: `%s', component #%i", file_orig, i);
                        return (-1);
@@ -287,238 +388,6 @@ static int check_create_dir (const char *file_orig)
        return (0);
 }
 
-static int log_create_file (char *filename, char **ds_def, int ds_num)
-{
-       FILE *log;
-       int i;
-
-       log = fopen (filename, "w");
-       if (log == NULL)
-       {
-               syslog (LOG_WARNING, "Failed to create %s: %s", filename,
-                               strerror(errno));
-               return (-1);
-       }
-
-       for (i = 0; i < ds_num; i++)
-       {
-               char *name;
-               char *tmp;
-
-               name = index (ds_def[i], ':');
-               if (name == NULL)
-               {
-                       syslog (LOG_WARNING, "Invalid DS definition '%s' for %s",
-                                       ds_def[i], filename);
-                       fclose(log);
-                       remove(filename);
-                       return (-1);
-               }
-
-               name += 1;
-               tmp = index(name, ':');
-               if (tmp == NULL)
-               {
-                       syslog (LOG_WARNING, "Invalid DS definition '%s' for %s",
-                                       ds_def[i], filename);
-                       fclose(log);
-                       remove(filename);
-                       return (-1);
-               }
-
-               if (i != 0)
-                       fprintf (log, ":");
-               fprintf(log, "%.*s", (tmp - name), name);
-       }
-       fprintf(log, "\n");
-       fclose(log);
-
-       return 0;
-}
-
-static int log_update_file (char *host, char *file, char *values,
-               char **ds_def, int ds_num)
-{
-       char *tmp;
-       FILE *fp;
-       struct stat statbuf;
-       char full_file[1024];
-
-       /* host == NULL => local mode */
-       if (host != NULL)
-       {
-               if (snprintf (full_file, 1024, "%s/%s", host, file) >= 1024)
-                       return (-1);
-       }
-       else
-       {
-               if (snprintf (full_file, 1024, "%s", file) >= 1024)
-                       return (-1);
-       }
-
-       strncpy (full_file, file, 1024);
-
-       tmp = full_file + strlen (full_file) - 4;
-       assert (tmp > 0);
-
-       /* Change the filename for logfiles. */
-       if (strncmp (tmp, ".rrd", 4) == 0)
-       {
-               time_t now;
-               struct tm *tm;
-
-               now = time (NULL);
-               tm = localtime (&now);
-
-               strftime (tmp, 1024 - (tmp - full_file), "-%Y-%m-%d", tm);
-
-               /* `localtime(3)' returns a pointer to static data,
-                * therefore the pointer may not be free'd. */
-       }
-       else
-               DBG ("The filename ends with `%s' which is unexpected.", tmp);
-
-       if (stat (full_file, &statbuf) == -1)
-       {
-               if (errno == ENOENT)
-               {
-                       if (log_create_file (full_file, ds_def, ds_num))
-                               return (-1);
-               }
-               else
-               {
-                       syslog (LOG_ERR, "stat %s: %s", full_file, strerror (errno));
-                       return (-1);
-               }
-       }
-       else if (!S_ISREG (statbuf.st_mode))
-       {
-               syslog (LOG_ERR, "stat %s: Not a regular file!", full_file);
-               return (-1);
-       }
-
-
-       fp = fopen (full_file, "a");
-       if (fp == NULL)
-       {
-               syslog (LOG_WARNING, "Failed to append to %s: %s", full_file,
-                               strerror(errno));
-               return (-1);
-       }
-       fprintf(fp, "%s\n", values);
-       fclose(fp);
-
-       return (0);
-} /* int log_update_file */
-
-#if HAVE_LIBRRD
-static int rrd_create_file (char *filename, char **ds_def, int ds_num)
-{
-       char **argv;
-       int argc;
-       int i, j;
-       int status = 0;
-
-       if (check_create_dir (filename))
-               return (-1);
-
-       argc = ds_num + rra_num + 4;
-
-       if ((argv = (char **) malloc (sizeof (char *) * (argc + 1))) == NULL)
-       {
-               syslog (LOG_ERR, "rrd_create failed: %s", strerror (errno));
-               return (-1);
-       }
-
-       argv[0] = "create";
-       argv[1] = filename;
-       argv[2] = "-s";
-       argv[3] = "10";
-
-       j = 4;
-       for (i = 0; i < ds_num; i++)
-               argv[j++] = ds_def[i];
-       for (i = 0; i < rra_num; i++)
-               argv[j++] = rra_def[i];
-       argv[j] = NULL;
-
-       optind = 0; /* bug in librrd? */
-       rrd_clear_error ();
-       if (rrd_create (argc, argv) == -1)
-       {
-               syslog (LOG_ERR, "rrd_create failed: %s: %s", filename, rrd_get_error ());
-               status = -1;
-       }
-
-       free (argv);
-
-       return (status);
-}
-#endif /* HAVE_LIBRRD */
-
-int rrd_update_file (char *host, char *file, char *values,
-               char **ds_def, int ds_num)
-{
-#if HAVE_LIBRRD
-       struct stat statbuf;
-       char full_file[1024];
-       char *argv[4] = { "update", full_file, values, NULL };
-#endif /* HAVE_LIBRRD */
-
-       /* I'd rather have a function `common_update_file' to make this
-        * decission, but for that we'd need to touch all plugins.. */
-       if (operating_mode == MODE_LOG)
-               return (log_update_file (host, file, values,
-                                       ds_def, ds_num));
-
-#if HAVE_LIBRRD
-       /* host == NULL => local mode */
-       if (host != NULL)
-       {
-               if (snprintf (full_file, 1024, "%s/%s", host, file) >= 1024)
-                       return (-1);
-       }
-       else
-       {
-               if (snprintf (full_file, 1024, "%s", file) >= 1024)
-                       return (-1);
-       }
-
-       if (stat (full_file, &statbuf) == -1)
-       {
-               if (errno == ENOENT)
-               {
-                       if (rrd_create_file (full_file, ds_def, ds_num))
-                               return (-1);
-               }
-               else
-               {
-                       syslog (LOG_ERR, "stat %s: %s", full_file, strerror (errno));
-                       return (-1);
-               }
-       }
-       else if (!S_ISREG (statbuf.st_mode))
-       {
-               syslog (LOG_ERR, "stat %s: Not a regular file!", full_file);
-               return (-1);
-       }
-
-       optind = 0; /* bug in librrd? */
-       rrd_clear_error ();
-       if (rrd_update (3, argv) == -1)
-       {
-               syslog (LOG_WARNING, "rrd_update failed: %s: %s", full_file, rrd_get_error ());
-               return (-1);
-       }
-       return (0);
-/* #endif HAVE_LIBRRD */
-
-#else
-       syslog (LOG_ERR, "`rrd_update_file' was called, but collectd isn't linked against librrd!");
-       return (-1);
-#endif
-}
-
 #ifdef HAVE_LIBKSTAT
 int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name)
 {
@@ -604,3 +473,21 @@ long long get_kstat_value (kstat_t *ksp, char *name)
        return (retval);
 }
 #endif /* HAVE_LIBKSTAT */
+
+unsigned long long ntohll (unsigned long long n)
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+       return (n);
+#else
+       return (((unsigned long long) ntohl (n)) << 32) + ntohl (n >> 32);
+#endif
+}
+
+unsigned long long htonll (unsigned long long n)
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+       return (n);
+#else
+       return (((unsigned long long) htonl (n)) << 32) + htonl (n >> 32);
+#endif
+}