rrd_client: Do not rewrite path names when accessing remote daemons.
authoroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Sun, 4 Oct 2009 11:35:02 +0000 (11:35 +0000)
committeroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Sun, 4 Oct 2009 11:35:02 +0000 (11:35 +0000)
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

index 8e60664..013b7e3 100644 (file)
@@ -17,6 +17,7 @@
  *
  * Authors:
  *   Florian octo Forster <octo at verplant.org>
+ *   Sebastian tokkee Harl <sh at tokkee.org>
  **/
 
 #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);