src/daemon/common.c: Add unit test for escape_string().
[collectd.git] / src / daemon / common.c
index 5386739..9e0648c 100644 (file)
@@ -312,44 +312,51 @@ int strsplit (char *string, char **fields, size_t size)
        return ((int) i);
 }
 
-int strjoin (char *dst, size_t dst_len,
+int strjoin (char *buffer, size_t buffer_size,
                char **fields, size_t fields_num,
                const char *sep)
 {
-       size_t field_len;
+       size_t avail;
+       char *ptr;
        size_t sep_len;
-       int i;
-
-       memset (dst, '\0', dst_len);
+       size_t i;
 
-       if (fields_num <= 0)
+       if ((buffer_size < 1) || (fields_num <= 0))
                return (-1);
 
+       memset (buffer, 0, buffer_size);
+       ptr = buffer;
+       avail = buffer_size - 1;
+
        sep_len = 0;
        if (sep != NULL)
                sep_len = strlen (sep);
 
-       for (i = 0; i < (int)fields_num; i++)
+       for (i = 0; i < fields_num; i++)
        {
+               size_t field_len;
+
                if ((i > 0) && (sep_len > 0))
                {
-                       if (dst_len <= sep_len)
+                       if (avail < sep_len)
                                return (-1);
 
-                       strncat (dst, sep, dst_len);
-                       dst_len -= sep_len;
+                       memcpy (ptr, sep, sep_len);
+                       ptr += sep_len;
+                       avail -= sep_len;
                }
 
                field_len = strlen (fields[i]);
-
-               if (dst_len <= field_len)
+               if (avail < field_len)
                        return (-1);
 
-               strncat (dst, fields[i], dst_len);
-               dst_len -= field_len;
+               memcpy (ptr, fields[i], field_len);
+               ptr += field_len;
+               avail -= field_len;
        }
 
-       return (strlen (dst));
+       assert (buffer[buffer_size - 1] == 0);
+       return (strlen (buffer));
 }
 
 int strsubstitute (char *str, char c_from, char c_to)
@@ -373,6 +380,60 @@ int strsubstitute (char *str, char c_from, char c_to)
        return (ret);
 } /* int strsubstitute */
 
+int escape_string (char *buffer, size_t buffer_size)
+{
+  char *temp;
+  size_t i;
+  size_t j;
+
+  /* Check if we need to escape at all first */
+  temp = strpbrk (buffer, " \t\"\\");
+  if (temp == NULL)
+    return (0);
+
+  if (buffer_size < 3)
+    return (EINVAL);
+
+  temp = (char *) malloc (buffer_size);
+  if (temp == NULL)
+    return (ENOMEM);
+  memset (temp, 0, buffer_size);
+
+  temp[0] = '"';
+  j = 1;
+
+  for (i = 0; i < buffer_size; i++)
+  {
+    if (buffer[i] == 0)
+    {
+      break;
+    }
+    else if ((buffer[i] == '"') || (buffer[i] == '\\'))
+    {
+      if (j > (buffer_size - 4))
+        break;
+      temp[j] = '\\';
+      temp[j + 1] = buffer[i];
+      j += 2;
+    }
+    else
+    {
+      if (j > (buffer_size - 3))
+        break;
+      temp[j] = buffer[i];
+      j++;
+    }
+  }
+
+  assert ((j + 1) < buffer_size);
+  temp[j] = '"';
+  temp[j + 1] = 0;
+
+  sstrncpy (buffer, temp, buffer_size);
+  sfree (temp);
+  return (0);
+} /* int escape_string */
+
 int strunescape (char *buf, size_t buf_len)
 {
        size_t i;
@@ -421,8 +482,8 @@ size_t strstripnewline (char *buffer)
                if ((buffer[buffer_len - 1] != '\n')
                                && (buffer[buffer_len - 1] != '\r'))
                        break;
-               buffer[buffer_len] = 0;
                buffer_len--;
+               buffer[buffer_len] = 0;
        }
 
        return (buffer_len);
@@ -430,8 +491,8 @@ size_t strstripnewline (char *buffer)
 
 int escape_slashes (char *buffer, size_t buffer_size)
 {
-       int i;
        size_t buffer_len;
+       size_t i;
 
        buffer_len = strlen (buffer);
 
@@ -453,7 +514,7 @@ int escape_slashes (char *buffer, size_t buffer_size)
                buffer_len--;
        }
 
-       for (i = 0; i < buffer_len - 1; i++)
+       for (i = 0; i < buffer_len; i++)
        {
                if (buffer[i] == '/')
                        buffer[i] = '_';
@@ -885,7 +946,7 @@ int format_values (char *ret, size_t ret_len, /* {{{ */
 {
         size_t offset = 0;
         int status;
-        int i;
+        size_t i;
         gauge_t *rates = NULL;
 
         assert (0 == strcmp (ds->type, vl->type));
@@ -914,18 +975,17 @@ int format_values (char *ret, size_t ret_len, /* {{{ */
         for (i = 0; i < ds->ds_num; i++)
         {
                 if (ds->ds[i].type == DS_TYPE_GAUGE)
-                        BUFFER_ADD (":%f", vl->values[i].gauge);
+                        BUFFER_ADD (":"GAUGE_FORMAT, vl->values[i].gauge);
                 else if (store_rates)
                 {
                         if (rates == NULL)
                                 rates = uc_get_rate (ds, vl);
                         if (rates == NULL)
                         {
-                                WARNING ("format_values: "
-                                               "uc_get_rate failed.");
+                                WARNING ("format_values: uc_get_rate failed.");
                                 return (-1);
                         }
-                        BUFFER_ADD (":%g", rates[i]);
+                        BUFFER_ADD (":"GAUGE_FORMAT, rates[i]);
                 }
                 else if (ds->ds[i].type == DS_TYPE_COUNTER)
                         BUFFER_ADD (":%llu", vl->values[i].counter);
@@ -935,7 +995,7 @@ int format_values (char *ret, size_t ret_len, /* {{{ */
                         BUFFER_ADD (":%"PRIu64, vl->values[i].absolute);
                 else
                 {
-                        ERROR ("format_values plugin: Unknown data source type: %i",
+                        ERROR ("format_values: Unknown data source type: %i",
                                         ds->ds[i].type);
                         sfree (rates);
                         return (-1);
@@ -1089,14 +1149,15 @@ int parse_value (const char *value_orig, value_t *ret_value, int ds_type)
 
 int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds)
 {
-       int i;
+       size_t i;
        char *dummy;
        char *ptr;
        char *saveptr;
 
-       i = -1;
+       i = 0;
        dummy = buffer;
        saveptr = NULL;
+       vl->time = 0;
        while ((ptr = strtok_r (dummy, ":", &saveptr)) != NULL)
        {
                dummy = NULL;
@@ -1104,11 +1165,11 @@ int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds)
                if (i >= vl->values_len)
                {
                        /* Make sure i is invalid. */
-                       i = vl->values_len + 1;
+                       i = 0;
                        break;
                }
 
-               if (i == -1)
+               if (vl->time == 0)
                {
                        if (strcmp ("N", ptr) == 0)
                                vl->time = cdtime ();
@@ -1127,19 +1188,19 @@ int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds)
 
                                vl->time = DOUBLE_TO_CDTIME_T (tmp);
                        }
+
+                       continue;
                }
-               else
-               {
-                       if ((strcmp ("U", ptr) == 0) && (ds->ds[i].type == DS_TYPE_GAUGE))
-                               vl->values[i].gauge = NAN;
-                       else if (0 != parse_value (ptr, &vl->values[i], ds->ds[i].type))
-                               return -1;
-               }
+
+               if ((strcmp ("U", ptr) == 0) && (ds->ds[i].type == DS_TYPE_GAUGE))
+                       vl->values[i].gauge = NAN;
+               else if (0 != parse_value (ptr, &vl->values[i], ds->ds[i].type))
+                       return -1;
 
                i++;
        } /* while (strtok_r) */
 
-       if ((ptr != NULL) || (i != vl->values_len))
+       if ((ptr != NULL) || (i == 0))
                return (-1);
        return (0);
 } /* int parse_values */