/**
* collectd - src/common.c
- * Copyright (C) 2005-2008 Florian octo Forster
+ * Copyright (C) 2005-2009 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
# include <arpa/inet.h>
#endif
+/* for getaddrinfo */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
#ifdef HAVE_LIBKSTAT
extern kstat_ctl_t *kc;
#endif
break;
}
- return (i);
+ return ((int) i);
}
int strjoin (char *dst, size_t dst_len,
*/
if (fields[i][0] == '.')
{
- ERROR ("Cowardly refusing to create a directory that begins with a `.' (dot): `%s'", file_orig);
+ ERROR ("Cowardly refusing to create a directory that "
+ "begins with a `.' (dot): `%s'", file_orig);
return (-2);
}
return (-1);
}
- if (stat (dir, &statbuf) == -1)
- {
- if (errno == ENOENT)
+ while (42) {
+ if (stat (dir, &statbuf) == -1)
{
- if (mkdir (dir, 0755) == -1)
+ if (errno == ENOENT)
{
+ if (mkdir (dir, 0755) == 0)
+ break;
+
+ /* this might happen, if a different thread created
+ * the directory in the meantime
+ * => call stat() again to check for S_ISDIR() */
+ if (EEXIST == errno)
+ continue;
+
char errbuf[1024];
ERROR ("check_create_dir: mkdir (%s): %s", dir,
sstrerror (errno,
errbuf, sizeof (errbuf)));
return (-1);
}
+ else
+ {
+ char errbuf[1024];
+ ERROR ("check_create_dir: stat (%s): %s", dir,
+ sstrerror (errno, errbuf,
+ sizeof (errbuf)));
+ return (-1);
+ }
}
- else
+ else if (!S_ISDIR (statbuf.st_mode))
{
- char errbuf[1024];
- ERROR ("stat (%s): %s", dir,
- sstrerror (errno, errbuf,
- sizeof (errbuf)));
+ ERROR ("check_create_dir: `%s' exists but is not "
+ "a directory!", dir);
return (-1);
}
- }
- else if (!S_ISDIR (statbuf.st_mode))
- {
- ERROR ("stat (%s): Not a directory!", dir);
- return (-1);
+ break;
}
}
int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name)
{
char ident[128];
+
+ *ksp_ptr = NULL;
if (kc == NULL)
return (-1);
ssnprintf (ident, sizeof (ident), "%s,%i,%s", module, instance, name);
+ *ksp_ptr = kstat_lookup (kc, module, instance, name);
if (*ksp_ptr == NULL)
{
- if ((*ksp_ptr = kstat_lookup (kc, module, instance, name)) == NULL)
- {
- ERROR ("Cound not find kstat %s", ident);
- return (-1);
- }
+ ERROR ("get_kstat: Cound not find kstat %s", ident);
+ return (-1);
+ }
- if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED)
- {
- WARNING ("kstat %s has wrong type", ident);
- *ksp_ptr = NULL;
- return (-1);
- }
+ if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED)
+ {
+ ERROR ("get_kstat: kstat %s has wrong type", ident);
+ *ksp_ptr = NULL;
+ return (-1);
}
#ifdef assert
if (kstat_read (kc, *ksp_ptr, NULL) == -1)
{
- WARNING ("kstat %s could not be read", ident);
+ ERROR ("get_kstat: kstat %s could not be read", ident);
return (-1);
}
if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED)
{
- WARNING ("kstat %s has wrong type", ident);
+ ERROR ("get_kstat: kstat %s has wrong type", ident);
return (-1);
}
return (0);
} /* int parse_identifier */
-int parse_value (const char *value, value_t *ret_value, const data_source_t ds)
+int parse_value (const char *value, value_t *ret_value, int ds_type)
{
- char *endptr = NULL;
-
- if (DS_TYPE_COUNTER == ds.type)
- ret_value->counter = (counter_t)strtoll (value, &endptr, 0);
- else if (DS_TYPE_GAUGE == ds.type)
- ret_value->gauge = (gauge_t)strtod (value, &endptr);
- else {
- ERROR ("parse_value: Invalid data source \"%s\" "
- "(type = %i).", ds.name, ds.type);
- return -1;
- }
-
- if (value == endptr) {
- ERROR ("parse_value: Failed to parse string as number: %s.", value);
- return -1;
- }
- else if ((NULL != endptr) && ('\0' != *endptr))
- WARNING ("parse_value: Ignoring trailing garbage after number: %s.",
- endptr);
- return 0;
+ char *endptr = NULL;
+
+ switch (ds_type)
+ {
+ case DS_TYPE_COUNTER:
+ ret_value->counter = (counter_t) strtoull (value, &endptr, 0);
+ break;
+
+ case DS_TYPE_GAUGE:
+ ret_value->gauge = (gauge_t) strtod (value, &endptr);
+ break;
+
+ case DS_TYPE_DERIVE:
+ ret_value->counter = (derive_t) strtoll (value, &endptr, 0);
+ break;
+
+ case DS_TYPE_ABSOLUTE:
+ ret_value->counter = (absolute_t) strtoull (value, &endptr, 0);
+ break;
+
+ default:
+ ERROR ("parse_value: Invalid data source type: %i.", ds_type);
+ return -1;
+ }
+
+ if (value == endptr) {
+ ERROR ("parse_value: Failed to parse string as number: %s.", value);
+ return -1;
+ }
+ else if ((NULL != endptr) && ('\0' != *endptr))
+ WARNING ("parse_value: Ignoring trailing garbage after number: %s.",
+ endptr);
+ return 0;
} /* int parse_value */
int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds)
dummy = NULL;
if (i >= vl->values_len)
+ {
+ /* Make sure i is invalid. */
+ i = vl->values_len + 1;
break;
+ }
if (i == -1)
{
{
if ((strcmp ("U", ptr) == 0) && (ds->ds[i].type == DS_TYPE_GAUGE))
vl->values[i].gauge = NAN;
- else if (0 != parse_value (ptr, &vl->values[i], ds->ds[i]))
+ else if (0 != parse_value (ptr, &vl->values[i], ds->ds[i].type))
return -1;
}
return (diff);
} /* counter_t counter_to_gauge */
+
+int service_name_to_port_number (const char *service_name)
+{
+ struct addrinfo *ai_list;
+ struct addrinfo *ai_ptr;
+ struct addrinfo ai_hints;
+ int status;
+ int service_number;
+
+ if (service_name == NULL)
+ return (-1);
+
+ ai_list = NULL;
+ memset (&ai_hints, 0, sizeof (ai_hints));
+ ai_hints.ai_family = AF_UNSPEC;
+
+ status = getaddrinfo (/* node = */ NULL, service_name,
+ &ai_hints, &ai_list);
+ if (status != 0)
+ {
+ ERROR ("service_name_to_port_number: getaddrinfo failed: %s",
+ gai_strerror (status));
+ return (-1);
+ }
+
+ service_number = -1;
+ for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+ {
+ if (ai_ptr->ai_family == AF_INET)
+ {
+ struct sockaddr_in *sa;
+
+ sa = (void *) ai_ptr->ai_addr;
+ service_number = (int) ntohs (sa->sin_port);
+ }
+ else if (ai_ptr->ai_family == AF_INET6)
+ {
+ struct sockaddr_in6 *sa;
+
+ sa = (void *) ai_ptr->ai_addr;
+ service_number = (int) ntohs (sa->sin6_port);
+ }
+
+ if ((service_number > 0) && (service_number <= 65535))
+ break;
+ }
+
+ freeaddrinfo (ai_list);
+
+ if ((service_number > 0) && (service_number <= 65535))
+ return (service_number);
+ return (-1);
+} /* int service_name_to_port_number */