X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fcommon.c;h=3ec4c6e1442947422eff75e5a3ed3f6d24dc7224;hb=f453199292b45007e5078f568f3bce2e8c8b4067;hp=951bae306e834d15f3b7d1e66fb217740bedaff0;hpb=4320ac5ec142c87bcf634cd85b89eadea65011ff;p=collectd.git diff --git a/src/common.c b/src/common.c index 951bae30..3ec4c6e1 100644 --- a/src/common.c +++ b/src/common.c @@ -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,27 +49,52 @@ 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) { 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_ @@ -76,29 +102,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 +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) @@ -156,7 +197,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 +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++; @@ -217,8 +258,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 +271,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)) { @@ -306,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) { @@ -342,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; /* @@ -353,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); /* @@ -368,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 @@ -421,7 +502,7 @@ int check_create_dir (const char *file_orig) if (mkdir (dir, 0755) == -1) { char errbuf[1024]; - ERROR ("mkdir (%s): %s", dir, + ERROR ("check_create_dir: mkdir (%s): %s", dir, sstrerror (errno, errbuf, sizeof (errbuf))); return (-1); @@ -444,7 +525,7 @@ int check_create_dir (const char *file_orig) } return (0); -} +} /* check_create_dir */ #ifdef HAVE_LIBKSTAT int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name) @@ -454,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) { @@ -504,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 @@ -534,7 +614,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 +623,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 +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); } @@ -726,4 +883,105 @@ 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, + 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 */