From: Sebastian Harl Date: Sun, 4 Oct 2009 13:25:34 +0000 (+0200) Subject: Imported upstream SVN snapshot 1.4~rc2+20091004. X-Git-Tag: upstream/1.4--rc2+20091004~1 X-Git-Url: https://git.tokkee.org/?p=pkg-rrdtool.git;a=commitdiff_plain;h=615f2d5cbdd20dca2a51151f82dd13dcb189012f Imported upstream SVN snapshot 1.4~rc2+20091004. This is based on SVN trunk at revision 1930. --- diff --git a/src/rrd_client.c b/src/rrd_client.c index 8e60664..a4f1ba9 100644 --- a/src/rrd_client.c +++ b/src/rrd_client.c @@ -17,6 +17,7 @@ * * Authors: * Florian octo Forster + * Sebastian tokkee Harl **/ #include "rrd.h" @@ -51,6 +52,45 @@ static int sd = -1; 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) /* {{{ */ { @@ -255,19 +295,13 @@ static int request (const char *buffer, size_t buffer_size, /* {{{ */ 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); @@ -277,8 +311,6 @@ static int request (const char *buffer, size_t buffer_size, /* {{{ */ res = NULL; status = response_read (&res); - pthread_mutex_unlock (&lock); - if (status != 0) { if (status < 0) @@ -404,8 +436,8 @@ static int rrdc_connect_network (const char *addr_orig) /* {{{ */ 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) @@ -420,7 +452,12 @@ static int rrdc_connect_network (const char *addr_orig) /* {{{ */ 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) { @@ -478,6 +515,7 @@ int rrdc_connect (const char *addr) /* {{{ */ close_connection(); } + rrd_clear_error (); if (strncmp ("unix:", addr, strlen ("unix:")) == 0) status = rrdc_connect_unix (addr + strlen ("unix:")); else if (addr[0] == '/') @@ -488,10 +526,18 @@ int rrdc_connect (const char *addr) /* {{{ */ 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); @@ -528,19 +574,29 @@ int rrdc_update (const char *filename, int values_num, /* {{{ */ 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)); @@ -550,6 +606,8 @@ int rrdc_update (const char *filename, int values_num, /* {{{ */ res = NULL; status = request (buffer, buffer_size, &res); + pthread_mutex_unlock (&lock); + if (status != 0) return (status); @@ -580,13 +638,20 @@ int rrdc_flush (const char *filename) /* {{{ */ 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; @@ -595,6 +660,8 @@ int rrdc_flush (const char *filename) /* {{{ */ res = NULL; status = request (buffer, buffer_size, &res); + pthread_mutex_unlock (&lock); + if (status != 0) return (status); @@ -659,7 +726,10 @@ int rrdc_stats_get (rrdc_stats_t **ret_stats) /* {{{ */ * }}} */ 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 710fa01..0ca1818 100644 --- a/src/rrd_daemon.c +++ b/src/rrd_daemon.c @@ -105,6 +105,7 @@ #include #include #include +#include #include /* }}} */ @@ -348,12 +349,32 @@ static void install_signal_handlers(void) /* {{{ */ 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", @@ -1652,6 +1673,9 @@ static int socket_permission_check (listen_socket_t *sock, /* {{{ */ { ssize_t i; + if (sock == NULL) /* journal replay */ + return (1); + if (cmd == NULL) return (-1); @@ -2239,11 +2263,31 @@ static int open_listen_socket_unix (const listen_socket_t *sock) /* {{{ */ 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) @@ -2346,8 +2390,8 @@ static int open_listen_socket_network(const listen_socket_t *sock) /* {{{ */ 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) @@ -2866,6 +2910,13 @@ static int read_options (int argc, char **argv) /* {{{ */ 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 @@ -2873,17 +2924,8 @@ static int read_options (int argc, char **argv) /* {{{ */ */ 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; } @@ -2901,6 +2943,24 @@ static int read_options (int argc, char **argv) /* {{{ */ } _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 2c30a98..b60ea15 100644 --- a/src/rrd_fetch.c +++ b/src/rrd_fetch.c @@ -163,7 +163,7 @@ int rrd_fetch( *step = step_tmp; if (optind + 1 >= argc) { - rrd_set_error("not enough arguments"); + rrd_set_error("Usage: rrdtool %s [options]", argv[0]); return -1; } diff --git a/src/rrd_fetch_libdbi.c b/src/rrd_fetch_libdbi.c index ad9a766..0e8bc93 100644 --- a/src/rrd_fetch_libdbi.c +++ b/src/rrd_fetch_libdbi.c @@ -17,20 +17,20 @@ struct sql_table_helper { }; /* 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 */ @@ -87,7 +87,7 @@ long rrd_fetch_dbi_long(dbi_result *result,int idx) { 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 */ @@ -144,7 +144,7 @@ double rrd_fetch_dbi_double(dbi_result *result,int idx) { 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) ); } @@ -158,7 +158,7 @@ void _sql_close(struct sql_table_helper* th) { } } -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 */ @@ -200,7 +200,7 @@ int _sql_setparam(struct sql_table_helper* th,char* key, char* value) { 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) { @@ -282,7 +282,7 @@ char* _find_next_separator(char* start,char separator) { 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) { @@ -300,7 +300,7 @@ char* _find_next_separator_twice(char*start,char separator) { return NULL; } -char _hexcharhelper(char c) { +static char _hexcharhelper(char c) { switch (c) { case '0': return 0 ; break; case '1': return 1 ; break; @@ -328,7 +328,7 @@ char _hexcharhelper(char c) { return -1; } -int _inline_unescape (char* string) { +static int _inline_unescape (char* string) { char *src=string; char *dst=string; char c,h1,h2; @@ -341,9 +341,15 @@ int _inline_unescape (char* string) { } 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; @@ -358,8 +364,8 @@ int _inline_unescape (char* string) { 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 f7a715e..5d18a1e 100644 --- a/src/rrd_flushcached.c +++ b/src/rrd_flushcached.c @@ -74,7 +74,6 @@ int rrd_flushcached (int argc, char **argv) /* 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)) @@ -107,6 +106,8 @@ int rrd_flushcached (int argc, char **argv) } } + 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 c1c9728..47d231d 100644 --- a/src/rrd_tool.h +++ b/src/rrd_tool.h @@ -94,7 +94,7 @@ extern "C" { #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,