X-Git-Url: https://git.octo.it/?p=collectd.git;a=blobdiff_plain;f=src%2Fhddtemp.c;h=a7eaf3699f139ea7df470b01d42376f7433f255d;hp=fbaff3ac0e2a5bd00ab14fabb2299441080b5e9b;hb=1159cb5d383c55a80a0db100b8f7aadcf44740a5;hpb=79963d13c1884d1d92667cc502ad20758b084a12 diff --git a/src/hddtemp.c b/src/hddtemp.c index fbaff3ac..a7eaf369 100644 --- a/src/hddtemp.c +++ b/src/hddtemp.c @@ -3,6 +3,7 @@ * Copyright (C) 2005,2006 Vincent Stehlé * Copyright (C) 2006-2010 Florian octo Forster * Copyright (C) 2008 Sebastian Harl + * Copyright (C) 2014 Carnegie Mellon University * * 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 @@ -22,6 +23,7 @@ * Vincent Stehlé * Florian octo Forster * Sebastian Harl + * Benjamin Gilbert * * TODO: * Do a pass, some day, and spare some memory. We consume too much for now @@ -34,6 +36,7 @@ #include "common.h" #include "plugin.h" +#include #include /* for basename */ #include #include @@ -45,6 +48,7 @@ #define HDDTEMP_DEF_HOST "127.0.0.1" #define HDDTEMP_DEF_PORT "7634" +#define HDDTEMP_MAX_RECV_BUF (1 << 20) static const char *config_keys[] = {"Host", "Port"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); @@ -75,10 +79,14 @@ static char hddtemp_port[16]; * we need to create a new socket each time. Is there another way? * Hm, maybe we can re-use the `sockaddr' structure? -octo */ -static int hddtemp_query_daemon(char *buffer, int buffer_size) { +static char *hddtemp_query_daemon(void) { int fd; ssize_t status; + + char *buffer; + int buffer_size; int buffer_fill; + char *new_buffer; const char *host; const char *port; @@ -104,7 +112,7 @@ static int hddtemp_query_daemon(char *buffer, int buffer_size) { ERROR("hddtemp plugin: getaddrinfo (%s, %s): %s", host, port, (ai_return == EAI_SYSTEM) ? sstrerror(errno, errbuf, sizeof(errbuf)) : gai_strerror(ai_return)); - return (-1); + return NULL; } fd = -1; @@ -138,16 +146,37 @@ static int hddtemp_query_daemon(char *buffer, int buffer_size) { if (fd < 0) { ERROR("hddtemp plugin: Could not connect to daemon."); - return (-1); + return NULL; } /* receive data from the hddtemp daemon */ - memset(buffer, '\0', buffer_size); - + buffer = NULL; + buffer_size = 0; buffer_fill = 0; - while ((status = read(fd, buffer + buffer_fill, buffer_size - buffer_fill)) != - 0) { - if (status == -1) { + while (1) { + if ((buffer_size == 0) || (buffer_fill >= buffer_size - 1)) { + if (buffer_size == 0) + buffer_size = 1024; + else + buffer_size *= 2; + if (buffer_size > HDDTEMP_MAX_RECV_BUF) { + WARNING("hddtemp plugin: Message from hddtemp has been " + "truncated."); + break; + } + new_buffer = realloc(buffer, buffer_size); + if (new_buffer == NULL) { + close(fd); + free(buffer); + ERROR("hddtemp plugin: Allocation failed."); + return NULL; + } + buffer = new_buffer; + } + status = read(fd, buffer + buffer_fill, buffer_size - buffer_fill - 1); + if (status == 0) { + break; + } else if (status == -1) { char errbuf[1024]; if ((errno == EAGAIN) || (errno == EINTR)) @@ -156,28 +185,25 @@ static int hddtemp_query_daemon(char *buffer, int buffer_size) { ERROR("hddtemp plugin: Error reading from socket: %s", sstrerror(errno, errbuf, sizeof(errbuf))); close(fd); - return (-1); + free(buffer); + return NULL; } buffer_fill += status; - - if (buffer_fill >= buffer_size) - break; } - if (buffer_fill >= buffer_size) { - buffer[buffer_size - 1] = '\0'; - WARNING("hddtemp plugin: Message from hddtemp has been " - "truncated."); - } else if (buffer_fill == 0) { + if (buffer_fill == 0) { WARNING("hddtemp plugin: Peer has unexpectedly shut down " "the socket. Buffer: `%s'", buffer); close(fd); - return (-1); + free(buffer); + return NULL; } + assert(buffer_fill < buffer_size); + buffer[buffer_fill] = '\0'; close(fd); - return (0); + return buffer; } static int hddtemp_config(const char *key, const char *value) { @@ -188,25 +214,21 @@ static int hddtemp_config(const char *key, const char *value) { } else if (strcasecmp(key, "Port") == 0) { int port = (int)(atof(value)); if ((port > 0) && (port <= 65535)) - ssnprintf(hddtemp_port, sizeof(hddtemp_port), "%i", port); + snprintf(hddtemp_port, sizeof(hddtemp_port), "%i", port); else sstrncpy(hddtemp_port, value, sizeof(hddtemp_port)); } else { - return (-1); + return -1; } - return (0); + return 0; } static void hddtemp_submit(char *type_instance, double value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t){.gauge = value}; vl.values_len = 1; - sstrncpy(vl.host, hostname_g, sizeof(vl.host)); sstrncpy(vl.plugin, "hddtemp", sizeof(vl.plugin)); sstrncpy(vl.type, "temperature", sizeof(vl.type)); sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance)); @@ -215,53 +237,46 @@ static void hddtemp_submit(char *type_instance, double value) { } static int hddtemp_read(void) { - char buf[1024]; - char *fields[128]; + char *buf; char *ptr; char *saveptr; - int num_fields; - int num_disks; + char *name; + char *model; + char *temperature; + char *mode; /* get data from daemon */ - if (hddtemp_query_daemon(buf, sizeof(buf)) < 0) - return (-1); + buf = hddtemp_query_daemon(); + if (buf == NULL) + return -1; /* NB: strtok_r will eat up "||" and leading "|"'s */ - num_fields = 0; ptr = buf; saveptr = NULL; - while ((fields[num_fields] = strtok_r(ptr, "|", &saveptr)) != NULL) { - ptr = NULL; - num_fields++; - - if (num_fields >= 128) - break; - } + while ((name = strtok_r(ptr, "|", &saveptr)) != NULL && + (model = strtok_r(NULL, "|", &saveptr)) != NULL && + (temperature = strtok_r(NULL, "|", &saveptr)) != NULL && + (mode = strtok_r(NULL, "|", &saveptr)) != NULL) { + double temperature_value; - num_disks = num_fields / 4; - - for (int i = 0; i < num_disks; i++) { - char *name; - double temperature; - char *mode; - - mode = fields[4 * i + 3]; - name = basename(fields[4 * i + 0]); + ptr = NULL; /* Skip non-temperature information */ if (mode[0] != 'C' && mode[0] != 'F') continue; - temperature = atof(fields[4 * i + 2]); + name = basename(name); + temperature_value = atof(temperature); /* Convert farenheit to celsius */ if (mode[0] == 'F') - temperature = (temperature - 32.0) * 5.0 / 9.0; + temperature_value = (temperature_value - 32.0) * 5.0 / 9.0; - hddtemp_submit(name, temperature); + hddtemp_submit(name, temperature_value); } - return (0); + free(buf); + return 0; } /* int hddtemp_read */ /* module_register