summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 645054b)
raw | patch | inline | side by side (parent: 645054b)
author | Sebastian Harl <sh@tokkee.org> | |
Sun, 4 Oct 2009 13:25:34 +0000 (15:25 +0200) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Sun, 4 Oct 2009 13:25:34 +0000 (15:25 +0200) |
This is based on SVN trunk at revision 1930.
diff --git a/src/rrd_client.c b/src/rrd_client.c
index 8e606640455eaa01b47d6f4ff7c7771c2b746a34..a4f1ba9c86fd8022db488da266547af6b8fba4f9 100644 (file)
--- a/src/rrd_client.c
+++ b/src/rrd_client.c
*
* Authors:
* Florian octo Forster <octo at verplant.org>
+ * Sebastian tokkee Harl <sh at tokkee.org>
**/
#include "rrd.h"
static FILE *sh = NULL;
static char *sd_path = NULL; /* cache the path for sd */
+/* get_path: Return a path name appropriate to be sent to the daemon.
+ *
+ * When talking to a local daemon (thru a UNIX socket), relative path names
+ * are resolved to absolute path names to allow for transparent integration
+ * into existing solutions (as requested by Tobi). Else, absolute path names
+ * are not allowed, since path name translation is done by the server.
+ *
+ * One must hold `lock' when calling this function. */
+static const char *get_path (const char *path, char *resolved_path) /* {{{ */
+{
+ const char *ret = path;
+ int is_unix = 0;
+
+ if ((*sd_path == '/')
+ || (strncmp ("unix:", sd_path, strlen ("unix:")) == 0))
+ is_unix = 1;
+
+ if (*path == '/') /* absolute path */
+ {
+ if (! is_unix)
+ {
+ rrd_set_error ("absolute path names not allowed when talking "
+ "to a remote daemon");
+ return (NULL);
+ }
+ /* else: nothing to do */
+ }
+ else /* relative path */
+ {
+ if (is_unix)
+ {
+ realpath (path, resolved_path);
+ ret = resolved_path;
+ }
+ /* else: nothing to do */
+ }
+ return (ret);
+} /* }}} char *get_path */
+
/* One must hold `lock' when calling `close_connection'. */
static void close_connection (void) /* {{{ */
{
int status;
rrdc_response_t *res;
- pthread_mutex_lock (&lock);
-
if (sh == NULL)
- {
- pthread_mutex_unlock (&lock);
return (ENOTCONN);
- }
status = (int) fwrite (buffer, buffer_size, /* nmemb = */ 1, sh);
if (status != 1)
{
close_connection ();
- pthread_mutex_unlock (&lock);
rrd_set_error("request: socket error (%d) while talking to rrdcached",
status);
return (-1);
res = NULL;
status = response_read (&res);
- pthread_mutex_unlock (&lock);
-
if (status != 0)
{
if (status < 0)
rrd_set_error("garbage after address: %s", port);
return (-1);
}
- } /* if (*addr = ']') */
- else if (strchr (addr, '.') != NULL) /* Hostname or IPv4 */
+ } /* if (*addr == '[') */
+ else
{
port = rindex(addr, ':');
if (port != NULL)
port == NULL ? RRDCACHED_DEFAULT_PORT : port,
&ai_hints, &ai_res);
if (status != 0)
- return (status);
+ {
+ rrd_set_error ("failed to resolve address `%s' (port %s): %s",
+ addr, port == NULL ? RRDCACHED_DEFAULT_PORT : port,
+ gai_strerror (status));
+ return (-1);
+ }
for (ai_ptr = ai_res; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
{
close_connection();
}
+ rrd_clear_error ();
if (strncmp ("unix:", addr, strlen ("unix:")) == 0)
status = rrdc_connect_unix (addr + strlen ("unix:"));
else if (addr[0] == '/')
if (status == 0 && sd >= 0)
sd_path = strdup(addr);
else
+ {
+ char *err = rrd_test_error () ? rrd_get_error () : "Internal error";
+ /* err points the string that gets written to by rrd_set_error(), thus we
+ * cannot pass it to that function */
+ err = strdup (err);
rrd_set_error("Unable to connect to rrdcached: %s",
(status < 0)
- ? "Internal error"
+ ? (err ? err : "Internal error")
: rrd_strerror (status));
+ if (err != NULL)
+ free (err);
+ }
pthread_mutex_unlock (&lock);
return (status);
if (status != 0)
return (ENOBUFS);
- /* change to absolute path for rrdcached */
- if (*filename != '/' && realpath(filename, file_path) != NULL)
- filename = file_path;
+ pthread_mutex_lock (&lock);
+ filename = get_path (filename, file_path);
+ if (filename == NULL)
+ {
+ pthread_mutex_unlock (&lock);
+ return (-1);
+ }
status = buffer_add_string (filename, &buffer_ptr, &buffer_free);
if (status != 0)
+ {
+ pthread_mutex_unlock (&lock);
return (ENOBUFS);
+ }
for (i = 0; i < values_num; i++)
{
status = buffer_add_value (values[i], &buffer_ptr, &buffer_free);
if (status != 0)
+ {
+ pthread_mutex_unlock (&lock);
return (ENOBUFS);
+ }
}
assert (buffer_free < sizeof (buffer));
res = NULL;
status = request (buffer, buffer_size, &res);
+ pthread_mutex_unlock (&lock);
+
if (status != 0)
return (status);
if (status != 0)
return (ENOBUFS);
- /* change to absolute path for rrdcached */
- if (*filename != '/' && realpath(filename, file_path) != NULL)
- filename = file_path;
+ pthread_mutex_lock (&lock);
+ filename = get_path (filename, file_path);
+ if (filename == NULL)
+ {
+ pthread_mutex_unlock (&lock);
+ return (-1);
+ }
status = buffer_add_string (filename, &buffer_ptr, &buffer_free);
if (status != 0)
+ {
+ pthread_mutex_unlock (&lock);
return (ENOBUFS);
+ }
assert (buffer_free < sizeof (buffer));
buffer_size = sizeof (buffer) - buffer_free;
res = NULL;
status = request (buffer, buffer_size, &res);
+ pthread_mutex_unlock (&lock);
+
if (status != 0)
return (status);
* }}} */
res = NULL;
+ pthread_mutex_lock (&lock);
status = request ("STATS\n", strlen ("STATS\n"), &res);
+ pthread_mutex_unlock (&lock);
+
if (status != 0)
return (status);
diff --git a/src/rrd_daemon.c b/src/rrd_daemon.c
index 710fa017d747210882aeba6e9ecdba188b93c933..0ca1818d462b40e0bdd766c2de45eda6003178ef 100644 (file)
--- a/src/rrd_daemon.c
+++ b/src/rrd_daemon.c
#include <assert.h>
#include <sys/time.h>
#include <time.h>
+#include <libgen.h>
#include <glib-2.0/glib.h>
/* }}} */
static int open_pidfile(char *action, int oflag) /* {{{ */
{
int fd;
- char *file;
+ const char *file;
+ char *file_copy, *dir;
file = (config_pid_file != NULL)
? config_pid_file
: LOCALSTATEDIR "/run/rrdcached.pid";
+ /* dirname may modify its argument */
+ file_copy = strdup(file);
+ if (file_copy == NULL)
+ {
+ fprintf(stderr, "rrdcached: strdup(): %s\n",
+ rrd_strerror(errno));
+ return -1;
+ }
+
+ dir = dirname(file_copy);
+ if (rrd_mkdir_p(dir, 0777) != 0)
+ {
+ fprintf(stderr, "Failed to create pidfile directory '%s': %s\n",
+ dir, rrd_strerror(errno));
+ return -1;
+ }
+
+ free(file_copy);
+
fd = open(file, oflag, S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH);
if (fd < 0)
fprintf(stderr, "rrdcached: can't %s pid file '%s' (%s)\n",
{
ssize_t i;
+ if (sock == NULL) /* journal replay */
+ return (1);
+
if (cmd == NULL)
return (-1);
listen_socket_t *temp;
int status;
const char *path;
+ char *path_copy, *dir;
path = sock->addr;
if (strncmp(path, "unix:", strlen("unix:")) == 0)
path += strlen("unix:");
+ /* dirname may modify its argument */
+ path_copy = strdup(path);
+ if (path_copy == NULL)
+ {
+ fprintf(stderr, "rrdcached: strdup(): %s\n",
+ rrd_strerror(errno));
+ return (-1);
+ }
+
+ dir = dirname(path_copy);
+ if (rrd_mkdir_p(dir, 0777) != 0)
+ {
+ fprintf(stderr, "Failed to create socket directory '%s': %s\n",
+ dir, rrd_strerror(errno));
+ return (-1);
+ }
+
+ free(path_copy);
+
temp = (listen_socket_t *) rrd_realloc (listen_fds,
sizeof (listen_fds[0]) * (listen_fds_num + 1));
if (temp == NULL)
fprintf (stderr, "rrdcached: Garbage after address: %s\n", port);
return (-1);
}
- } /* if (*addr = ']') */
- else if (strchr (addr, '.') != NULL) /* Hostname or IPv4 */
+ } /* if (*addr == '[') */
+ else
{
port = rindex(addr, ':');
if (port != NULL)
return (3);
}
+ if (rrd_mkdir_p (config_base_dir, 0777) != 0)
+ {
+ fprintf (stderr, "Failed to create base directory '%s': %s\n",
+ config_base_dir, rrd_strerror (errno));
+ return (3);
+ }
+
/* make sure that the base directory is not resolved via
* symbolic links. this makes some performance-enhancing
* assumptions possible (we don't have to resolve paths
*/
if (realpath(config_base_dir, base_realpath) == NULL)
{
- fprintf (stderr, "Invalid base directory '%s'.\n", config_base_dir);
- return 5;
- }
- else if (strncmp(config_base_dir,
- base_realpath, sizeof(base_realpath)) != 0)
- {
- fprintf(stderr,
- "Base directory (-b) resolved via file system links!\n"
- "Please consult rrdcached '-b' documentation!\n"
- "Consider specifying the real directory (%s)\n",
- base_realpath);
+ fprintf (stderr, "Failed to canonicalize the base directory '%s': "
+ "%s\n", config_base_dir, rrd_strerror(errno));
return 5;
}
}
_config_base_dir_len = len;
+
+ len = strlen (base_realpath);
+ while ((len > 0) && (base_realpath[len - 1] == '/'))
+ {
+ base_realpath[len - 1] = '\0';
+ len--;
+ }
+
+ if (strncmp(config_base_dir,
+ base_realpath, sizeof(base_realpath)) != 0)
+ {
+ fprintf(stderr,
+ "Base directory (-b) resolved via file system links!\n"
+ "Please consult rrdcached '-b' documentation!\n"
+ "Consider specifying the real directory (%s)\n",
+ base_realpath);
+ return 5;
+ }
}
break;
diff --git a/src/rrd_fetch.c b/src/rrd_fetch.c
index 2c30a980735dd40f24b6fb575672ea6e8c1ef865..b60ea158e53223651b6ac4c54a100c38f97fd000 100644 (file)
--- a/src/rrd_fetch.c
+++ b/src/rrd_fetch.c
*step = step_tmp;
if (optind + 1 >= argc) {
- rrd_set_error("not enough arguments");
+ rrd_set_error("Usage: rrdtool %s <file> <CF> [options]", argv[0]);
return -1;
}
diff --git a/src/rrd_fetch_libdbi.c b/src/rrd_fetch_libdbi.c
index ad9a7664d0439af7fb20bb22e8a483b496e759fa..0e8bc939b32eab0bdc5c4999241fdaebb25be7ba 100644 (file)
--- a/src/rrd_fetch_libdbi.c
+++ b/src/rrd_fetch_libdbi.c
};
/* the prototypes */
-void _sql_close(struct sql_table_helper* th);
-int _sql_setparam(struct sql_table_helper* th,char* key, char* value);
-int _sql_fetchrow(struct sql_table_helper* th,time_t *timestamp, rrd_value_t *value,int ordered);
-char* _find_next_separator(char* start,char separator);
-char* _find_next_separator_twice(char*start,char separator);
-char _hexcharhelper(char c);
-int _inline_unescape (char* string);
-double rrd_fetch_dbi_double(dbi_result *result,int idx);
-long rrd_fetch_dbi_long(dbi_result *result,int idx);
+static void _sql_close(struct sql_table_helper* th);
+static int _sql_setparam(struct sql_table_helper* th,char* key, char* value);
+static int _sql_fetchrow(struct sql_table_helper* th,time_t *timestamp, rrd_value_t *value,int ordered);
+static char* _find_next_separator(char* start,char separator);
+static char* _find_next_separator_twice(char*start,char separator);
+static char _hexcharhelper(char c);
+static int _inline_unescape (char* string);
+static double rrd_fetch_dbi_double(dbi_result *result,int idx);
+static long rrd_fetch_dbi_long(dbi_result *result,int idx);
/* the real code */
/* helpers to get correctly converted values from DB*/
-long rrd_fetch_dbi_long(dbi_result *result,int idx) {
+static long rrd_fetch_dbi_long(dbi_result *result,int idx) {
char *ptmp="";
long value=DNAN;
/* get the attributes for this filed */
return value;
}
-double rrd_fetch_dbi_double(dbi_result *result,int idx) {
+static double rrd_fetch_dbi_double(dbi_result *result,int idx) {
char *ptmp="";
double value=DNAN;
/* get the attributes for this filed */
return value;
}
-void _sql_close(struct sql_table_helper* th) {
+static void _sql_close(struct sql_table_helper* th) {
/* close only if connected */
if (th->conn) {
if (getenv("RRDDEBUGSQL")) { fprintf(stderr,"RRDDEBUGSQL: %li: close connection\n",time(NULL) ); }
}
}
-int _sql_setparam(struct sql_table_helper* th,char* key, char* value) {
+static int _sql_setparam(struct sql_table_helper* th,char* key, char* value) {
char* dbi_errstr=NULL;
dbi_driver driver;
/* if not connected */
return 0;
}
-int _sql_fetchrow(struct sql_table_helper* th,time_t *timestamp, rrd_value_t *value,int ordered) {
+static int _sql_fetchrow(struct sql_table_helper* th,time_t *timestamp, rrd_value_t *value,int ordered) {
char* dbi_errstr=NULL;
char sql[10240];
time_t startt=0,endt=0;
@@ -269,7 +269,7 @@ int _sql_fetchrow(struct sql_table_helper* th,time_t *timestamp, rrd_value_t *va
return 1;
}
-char* _find_next_separator(char* start,char separator) {
+static char* _find_next_separator(char* start,char separator) {
char* found=strchr(start,separator);
/* have we found it */
if (found) {
return NULL;
}
-char* _find_next_separator_twice(char*start,char separator) {
+static char* _find_next_separator_twice(char*start,char separator) {
char *found=start;
/* find next separator in string*/
while (found) {
return NULL;
}
-char _hexcharhelper(char c) {
+static char _hexcharhelper(char c) {
switch (c) {
case '0': return 0 ; break;
case '1': return 1 ; break;
return -1;
}
-int _inline_unescape (char* string) {
+static int _inline_unescape (char* string) {
char *src=string;
char *dst=string;
char c,h1,h2;
} else {
/* try to calculate hex value from the next 2 values*/
h1=_hexcharhelper(*src);
- if (h1<0) { rrd_set_error( "string escape error at: %s\n",string);return(1); }
+ if (h1 == (char)-1) {
+ rrd_set_error("string escape error at: %s\n",string);
+ return(1);
+ }
h2=_hexcharhelper(*(src+1));
- if (h2<0) { rrd_set_error( "string escape error at: %s\n",string);return(1); }
+ if (h1 == (char)-1) {
+ rrd_set_error("string escape error at: %s\n",string);
+ return(1);
+ }
c=h2+(h1<<4);
/* increase src pointer by 2 skiping 2 chars */
src+=2;
int
rrd_fetch_fn_libdbi(
- char *filename, /* name of the rrd */
- enum cf_en cf_idx, /* which consolidation function ?*/
+ const char *filename, /* name of the rrd */
+ enum cf_en cf_idx __attribute__((unused)), /* consolidation function */
time_t *start,
time_t *end, /* which time frame do you want ?
* will be changed to represent reality */
diff --git a/src/rrd_flushcached.c b/src/rrd_flushcached.c
index f7a715e110c85528ae991decff7ea10a8eecd5a7..5d18a1e211549e948f863c978771dbf2c1787bf8 100644 (file)
--- a/src/rrd_flushcached.c
+++ b/src/rrd_flushcached.c
/* try to connect to rrdcached */
status = rrdc_connect(opt_daemon);
- if (opt_daemon) free(opt_daemon);
if (status != 0) return status;
if (! rrdc_is_connected(opt_daemon))
}
}
+ if (opt_daemon) free(opt_daemon);
+
return ((status == 0) ? 0 : -1);
} /* int rrd_flush */
diff --git a/src/rrd_tool.h b/src/rrd_tool.h
index c1c9728436a327ea5f4d924eb207f4fbb9a7c359..47d231db4bbf711f7a696e368a2d853fdf5b138e 100644 (file)
--- a/src/rrd_tool.h
+++ b/src/rrd_tool.h
#ifdef HAVE_LIBDBI
-int rrd_fetch_fn_libdbi(char *filename, enum cf_en cf_idx,
+int rrd_fetch_fn_libdbi(const char *filename, enum cf_en cf_idx,
time_t *start,time_t *end,
unsigned long *step,
unsigned long *ds_cnt,