From 484fd7168e776f1af747b65fa0da8a43571f5c9a Mon Sep 17 00:00:00 2001 From: oetiker Date: Sun, 4 Oct 2009 11:35:02 +0000 Subject: [PATCH] rrd_client: Do not rewrite path names when accessing remote daemons. 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). However, when talking to a remote daemon, absolute path names are not allowed, since path name translation is done by the server (relative to the base directory). -- Sebastian Harl git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk/program@1928 a5681a0c-68f1-0310-ab6d-d61299d08faa --- src/rrd_client.c | 84 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 14 deletions(-) diff --git a/src/rrd_client.c b/src/rrd_client.c index 8e60664..013b7e3 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) @@ -528,19 +560,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 +592,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 +624,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 +646,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 +712,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); -- 2.30.2