#if HAVE_YAJL_YAJL_VERSION_H
#include <yajl/yajl_version.h>
#endif
+#ifdef HAVE_SYS_CAPABILITY_H
+# include <sys/capability.h>
+#endif
#include <limits.h>
#include <poll.h>
static struct ceph_daemon **g_daemons = NULL;
/** Number of elements in g_daemons */
-static int g_num_daemons = 0;
+static size_t g_num_daemons = 0;
/**
* A set of data that we build up in memory while parsing the JSON.
#define BUFFER_ADD(dest, src) do { \
size_t dest_size = sizeof (dest); \
- strncat ((dest), (src), dest_size - strlen (dest)); \
- (dest)[dest_size - 1] = '\0'; \
+ size_t dest_len = strlen (dest); \
+ if (dest_size > dest_len) { \
+ sstrncpy ((dest) + dest_len, (src), dest_size - dest_len); \
+ } \
+ (dest)[dest_size - 1] = 0; \
} while (0)
static int
{
yajl_struct *state = (yajl_struct*) ctx;
char buffer[number_len+1];
- char key[2 * DATA_MAX_NAME_LEN];
+ char key[2 * DATA_MAX_NAME_LEN] = { 0 };
_Bool latency_type = 0;
int status;
- key[0] = '\0';
memcpy(buffer, number_val, number_len);
buffer[sizeof(buffer) - 1] = '\0';
{
latency_type = 1;
+ /* depth >= 2 => (stack[-1] != NULL && stack[-2] != NULL) */
+ assert ((state->depth < 2)
+ || ((state->stack[state->depth - 1] != NULL)
+ && (state->stack[state->depth - 2] != NULL)));
+
/* Super-special case for filestore.journal_wr_bytes.avgcount: For
* some reason, Ceph schema encodes this as a count/sum pair while all
* other "Bytes" data (excluding used/capacity bytes for OSD space) uses
static void ceph_daemons_print(void)
{
- for(int i = 0; i < g_num_daemons; ++i)
+ for(size_t i = 0; i < g_num_daemons; ++i)
{
ceph_daemon_print(g_daemons[i]);
}
return ENOMEM;
}
memcpy(nd, &cd, sizeof(*nd));
- g_daemons[g_num_daemons++] = nd;
+ g_daemons[g_num_daemons] = nd;
+ g_num_daemons++;
return 0;
}
struct timeval end_tv;
struct cconn io_array[g_num_daemons];
- DEBUG("ceph plugin: entering cconn_main_loop(request_type = %d)", request_type);
+ DEBUG ("ceph plugin: entering cconn_main_loop(request_type = %"PRIu32")", request_type);
+
+ if (g_num_daemons < 1)
+ {
+ ERROR ("ceph plugin: No daemons configured. See the \"Daemon\" config option.");
+ return ENOENT;
+ }
/* create cconn array */
- memset(io_array, 0, sizeof(io_array));
- for(int i = 0; i < g_num_daemons; ++i)
+ for (size_t i = 0; i < g_num_daemons; i++)
{
- io_array[i].d = g_daemons[i];
- io_array[i].request_type = request_type;
- io_array[i].state = CSTATE_UNCONNECTED;
+ io_array[i] = (struct cconn) {
+ .d = g_daemons[i],
+ .request_type = request_type,
+ .state = CSTATE_UNCONNECTED,
+ };
}
/** Calculate the time at which we should give up */
struct pollfd fds[g_num_daemons];
memset(fds, 0, sizeof(fds));
nfds = 0;
- for(int i = 0; i < g_num_daemons; ++i)
+ for(size_t i = 0; i < g_num_daemons; ++i)
{
struct cconn *io = io_array + i;
ret = cconn_prepare(io, fds + nfds);
if(ret < 0)
{
- WARNING("ceph plugin: cconn_prepare(name=%s,i=%d,st=%d)=%d",
+ WARNING("ceph plugin: cconn_prepare(name=%s,i=%zu,st=%d)=%d",
io->d->name, i, io->state, ret);
cconn_close(io);
io->request_type = ASOK_REQ_NONE;
if(revents == 0)
{
/* do nothing */
+ continue;
}
else if(cconn_validate_revents(io, revents))
{
}
}
}
- done: for(int i = 0; i < g_num_daemons; ++i)
+ done: for(size_t i = 0; i < g_num_daemons; ++i)
{
cconn_close(io_array + i);
}
/******* lifecycle *******/
static int ceph_init(void)
{
- int ret;
+#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_DAC_OVERRIDE)
+ if (check_capability (CAP_DAC_OVERRIDE) != 0)
+ {
+ if (getuid () == 0)
+ WARNING ("ceph plugin: Running collectd as root, but the "
+ "CAP_DAC_OVERRIDE capability is missing. The plugin's read "
+ "function will probably fail. Is your init system dropping "
+ "capabilities?");
+ else
+ WARNING ("ceph plugin: collectd doesn't have the CAP_DAC_OVERRIDE "
+ "capability. If you don't want to run collectd as root, try running "
+ "\"setcap cap_dac_override=ep\" on the collectd binary.");
+ }
+#endif
+
ceph_daemons_print();
- ret = cconn_main_loop(ASOK_REQ_VERSION);
+ if (g_num_daemons < 1)
+ {
+ ERROR ("ceph plugin: No daemons configured. See the \"Daemon\" config option.");
+ return ENOENT;
+ }
- return (ret) ? ret : 0;
+ return cconn_main_loop(ASOK_REQ_VERSION);
}
static int ceph_shutdown(void)
{
- for(int i = 0; i < g_num_daemons; ++i)
+ for(size_t i = 0; i < g_num_daemons; ++i)
{
ceph_daemon_free(g_daemons[i]);
}