Merge branch 'pr/1792'
authorFlorian Forster <octo@collectd.org>
Thu, 15 Sep 2016 08:10:30 +0000 (10:10 +0200)
committerFlorian Forster <octo@collectd.org>
Thu, 15 Sep 2016 08:10:30 +0000 (10:10 +0200)
1  2 
src/daemon/common.c
src/daemon/common.h

diff --combined src/daemon/common.c
@@@ -334,50 -334,60 +334,60 @@@ int strsplit (char *string, char **fiel
        return ((int) i);
  }
  
- int strjoin (char *buffer, size_t buffer_size,
-               char **fields, size_t fields_num,
-               const char *sep)
- {
-       size_t avail;
-       char *ptr;
-       size_t sep_len;
+ int strjoin(char *buffer, size_t buffer_size, char **fields, size_t fields_num,
+             const char *sep) {
+   size_t avail = 0;
+   char *ptr = buffer;
+   size_t sep_len = 0;
  
-       if ((buffer_size < 1) || (fields_num == 0))
-               return (-1);
+   size_t buffer_req = 0;
  
-       memset (buffer, 0, buffer_size);
-       ptr = buffer;
-       avail = buffer_size - 1;
+   if (((fields_num != 0) && (fields == NULL)) ||
+       ((buffer_size != 0) && (buffer == NULL)))
+     return (-EINVAL);
  
-       sep_len = 0;
-       if (sep != NULL)
-               sep_len = strlen (sep);
+   if (buffer != NULL)
+     buffer[0] = 0;
  
-       for (size_t i = 0; i < fields_num; i++)
-       {
-               size_t field_len;
+   if (buffer_size != 0)
+     avail = buffer_size - 1;
  
-               if ((i > 0) && (sep_len > 0))
-               {
-                       if (avail < sep_len)
-                               return (-1);
+   if (sep != NULL)
+     sep_len = strlen(sep);
  
-                       memcpy (ptr, sep, sep_len);
-                       ptr += sep_len;
-                       avail -= sep_len;
-               }
+   for (size_t i = 0; i < fields_num; i++) {
+     size_t field_len = strlen(fields[i]);
  
-               field_len = strlen (fields[i]);
-               if (avail < field_len)
-                       return (-1);
+     if (i != 0)
+       buffer_req += sep_len;
+     buffer_req += field_len;
  
-               memcpy (ptr, fields[i], field_len);
-               ptr += field_len;
-               avail -= field_len;
-       }
+     if ((i != 0) && (sep_len > 0)) {
+       if (sep_len >= avail) {
+         /* prevent subsequent iterations from writing to the
+          * buffer. */
+         avail = 0;
+         continue;
+       }
+       memcpy(ptr, sep, sep_len);
+       ptr += sep_len;
+       avail -= sep_len;
+     }
+     if (field_len > avail)
+       field_len = avail;
+     memcpy(ptr, fields[i], field_len);
+     ptr += field_len;
+     avail -= field_len;
+     if (ptr != NULL)
+       *ptr = 0;
+   }
  
-       assert (buffer[buffer_size - 1] == 0);
-       return ((int) strlen (buffer));
+   return (int)buffer_req;
  }
  
  int escape_string (char *buffer, size_t buffer_size)
@@@ -1199,18 -1209,6 +1209,18 @@@ int parse_values (char *buffer, value_l
        return (0);
  } /* int parse_values */
  
 +int parse_value_file (char const *path, value_t *ret_value, int ds_type)
 +{
 +      char buffer[256];
 +
 +      if (read_file_contents (path, buffer, sizeof (buffer)) < 0)
 +              return errno;
 +
 +      strstripnewline (buffer);
 +
 +      return parse_value (buffer, ret_value, ds_type);
 +} /* int parse_value_file */
 +
  #if !HAVE_GETPWNAM_R
  int getpwnam_r (const char *name, struct passwd *pwbuf, char *buf,
                size_t buflen, struct passwd **pwbufp)
diff --combined src/daemon/common.h
@@@ -147,10 -147,12 +147,12 @@@ int strsplit (char *string, char **fiel
   *   is equivalent to the Perl built-in `join'.
   *
   * PARAMETERS
-  *   `dst'         Buffer where the result is stored.
+  *   `dst'         Buffer where the result is stored. Can be NULL if you need to
+  *                 determine the required buffer size only.
   *   `dst_len'     Length of the destination buffer. No more than this many
   *                 bytes will be written to the memory pointed to by `dst',
-  *                 including the trailing null-byte.
+  *                 including the trailing null-byte. Must be zero if dst is
+  *                 NULL.
   *   `fields'      Array of strings to be joined.
   *   `fields_num'  Number of elements in the `fields' array.
   *   `sep'         String to be inserted between any two elements of `fields'.
   *                 Instead of passing "" (empty string) one can pass NULL.
   *
   * RETURN VALUE
-  *   Returns the number of characters in `dst', NOT including the trailing
-  *   null-byte. If an error occurred (empty array or `dst' too small) a value
-  *   smaller than zero will be returned.
+  *   Returns the number of characters in the resulting string, excluding a
+  *   tailing null byte. If this value is greater than or equal to "dst_len", the
+  *   result in "dst" is truncated (but still null terminated). On error a
+  *   negative value is returned.
   */
  int strjoin (char *dst, size_t dst_len, char **fields, size_t fields_num, const char *sep);
  
@@@ -322,11 -325,6 +325,11 @@@ int parse_identifier_vl (const char *st
  int parse_value (const char *value, value_t *ret_value, int ds_type);
  int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds);
  
 +/* parse_value_file reads "path" and parses its content as an integer or
 + * floating point, depending on "ds_type". On success, the value is stored in
 + * "ret_value" and zero is returned. On failure, a non-zero value is returned. */
 +int parse_value_file (char const *path, value_t *ret_value, int ds_type);
 +
  #if !HAVE_GETPWNAM_R
  int getpwnam_r (const char *name, struct passwd *pwbuf, char *buf,
                size_t buflen, struct passwd **pwbufp);