X-Git-Url: https://git.octo.it/?p=rrdtool.git;a=blobdiff_plain;f=src%2Frrd_client.c;h=21139f0ba3be7b772fc00001239d841fb136fa0c;hp=b677d4f37e439746e6fd0e697ae538468c036798;hb=96b0f4aace0deef034a792a08dc2d426cd2b61a4;hpb=13b88eef5c5fee3e33a06383315df6e57af605b0 diff --git a/src/rrd_client.c b/src/rrd_client.c index b677d4f..21139f0 100644 --- a/src/rrd_client.c +++ b/src/rrd_client.c @@ -73,30 +73,31 @@ static const char *get_path (const char *path, char *resolved_path) /* {{{ */ const char *ret = path; int is_unix = 0; + if ((path == NULL) || (resolved_path == NULL) || (sd_path == NULL)) + return (NULL); + if ((*sd_path == '/') || (strncmp ("unix:", sd_path, strlen ("unix:")) == 0)) is_unix = 1; - if (*path == '/') /* absolute path */ + if (is_unix) { - if (! is_unix) - { - rrd_set_error ("absolute path names not allowed when talking " - "to a remote daemon"); - return (NULL); - } - /* else: nothing to do */ + ret = realpath(path, resolved_path); + if (ret == NULL) + rrd_set_error("realpath(%s): %s", path, rrd_strerror(errno)); + return ret; } - else /* relative path */ + else { - if (is_unix) + if (*path == '/') /* not absolute path */ { - realpath (path, resolved_path); - ret = resolved_path; + rrd_set_error ("absolute path names not allowed when talking " + "to a remote daemon"); + return NULL; } - /* else: nothing to do */ } - return (ret); + + return path; } /* }}} char *get_path */ static size_t strsplit (char *string, char **fields, size_t size) /* {{{ */ @@ -315,6 +316,16 @@ static int buffer_add_value (const char *value, /* {{{ */ return (buffer_add_string (temp, buffer_ret, buffer_size_ret)); } /* }}} int buffer_add_value */ +static int buffer_add_ulong (const unsigned long value, /* {{{ */ + char **buffer_ret, size_t *buffer_size_ret) +{ + char temp[4096]; + + snprintf (temp, sizeof (temp), "%lu", value); + temp[sizeof (temp) - 1] = 0; + return (buffer_add_string (temp, buffer_ret, buffer_size_ret)); +} /* }}} int buffer_add_ulong */ + /* Remove trailing newline (NL) and carriage return (CR) characters. Similar to * the Perl function `chomp'. Returns the number of characters that have been * removed. */ @@ -358,34 +369,36 @@ static void response_free (rrdc_response_t *res) /* {{{ */ static int response_read (rrdc_response_t **ret_response) /* {{{ */ { - rrdc_response_t *ret; + rrdc_response_t *ret = NULL; + int status = 0; char buffer[4096]; char *buffer_ptr; size_t i; +#define DIE(code) do { status = code; goto err_out; } while(0) + if (sh == NULL) - return (-1); + DIE(-1); ret = (rrdc_response_t *) malloc (sizeof (rrdc_response_t)); if (ret == NULL) - return (-2); + DIE(-2); memset (ret, 0, sizeof (*ret)); ret->lines = NULL; ret->lines_num = 0; buffer_ptr = fgets (buffer, sizeof (buffer), sh); if (buffer_ptr == NULL) - return (-3); + DIE(-3); + chomp (buffer); ret->status = strtol (buffer, &ret->message, 0); if (buffer == ret->message) - { - response_free (ret); - return (-4); - } + DIE(-4); + /* Skip leading whitespace of the status message */ ret->message += strspn (ret->message, " \t"); @@ -393,16 +406,13 @@ static int response_read (rrdc_response_t **ret_response) /* {{{ */ { if (ret->status < 0) rrd_set_error("rrdcached: %s", ret->message); - *ret_response = ret; - return (0); + goto out; } ret->lines = (char **) malloc (sizeof (char *) * ret->status); if (ret->lines == NULL) - { - response_free (ret); - return (-5); - } + DIE(-5); + memset (ret->lines, 0, sizeof (char *) * ret->status); ret->lines_num = (size_t) ret->status; @@ -410,22 +420,27 @@ static int response_read (rrdc_response_t **ret_response) /* {{{ */ { buffer_ptr = fgets (buffer, sizeof (buffer), sh); if (buffer_ptr == NULL) - { - response_free (ret); - return (-6); - } + DIE(-6); + chomp (buffer); ret->lines[i] = strdup (buffer); if (ret->lines[i] == NULL) - { - response_free (ret); - return (-7); - } + DIE(-7); } +out: *ret_response = ret; - return (0); + fflush(sh); + return (status); + +err_out: + response_free(ret); + close_connection(); + return (status); + +#undef DIE + } /* }}} rrdc_response_t *response_read */ static int request (const char *buffer, size_t buffer_size, /* {{{ */ @@ -810,6 +825,320 @@ int rrdc_flush (const char *filename) /* {{{ */ return (status); } /* }}} int rrdc_flush */ +rrd_info_t * rrdc_info (const char *filename) /* {{{ */ +{ + char buffer[4096]; + char *buffer_ptr; + size_t buffer_free; + size_t buffer_size; + rrdc_response_t *res; + int status; + char file_path[PATH_MAX]; + rrd_info_t *data = NULL, *cd; + rrd_infoval_t info; + unsigned int l; + rrd_info_type_t itype; + char *k, *s; + + if (filename == NULL) { + rrd_set_error ("rrdc_info: no filename"); + return (NULL); + } + + memset (buffer, 0, sizeof (buffer)); + buffer_ptr = &buffer[0]; + buffer_free = sizeof (buffer); + + status = buffer_add_string ("info", &buffer_ptr, &buffer_free); + if (status != 0) { + rrd_set_error ("rrdc_info: out of memory"); + return (NULL); + } + + pthread_mutex_lock (&lock); + filename = get_path (filename, file_path); + if (filename == NULL) + { + pthread_mutex_unlock (&lock); + return (NULL); + } + + status = buffer_add_string (filename, &buffer_ptr, &buffer_free); + if (status != 0) + { + pthread_mutex_unlock (&lock); + rrd_set_error ("rrdc_info: out of memory"); + return (NULL); + } + + assert (buffer_free < sizeof (buffer)); + buffer_size = sizeof (buffer) - buffer_free; + assert (buffer[buffer_size - 1] == ' '); + buffer[buffer_size - 1] = '\n'; + + res = NULL; + status = request (buffer, buffer_size, &res); + pthread_mutex_unlock (&lock); + + if (status != 0) { + rrd_set_error ("rrdcached: %s", res->message); + return (NULL); + } + data = cd = NULL; + for( l=0 ; l < res->lines_num ; l++ ) { + /* first extract the keyword */ + for(k = s = res->lines[l];s && *s;s++) { + if(*s == ' ') { *s = 0; s++; break; } + } + if(!s || !*s) break; + itype = atoi(s); /* extract type code */ + for(;*s;s++) { if(*s == ' ') { *s = 0; s++; break; } } + if(!*s) break; + /* finally, we're pointing to the value */ + switch(itype) { + case RD_I_VAL: + if(*s == 'N') { info.u_val = DNAN; } else { info.u_val = atof(s); } + break; + case RD_I_CNT: + info.u_cnt = atol(s); + break; + case RD_I_INT: + info.u_int = atoi(s); + break; + case RD_I_STR: + chomp(s); + info.u_str = (char*)malloc(sizeof(char) * (strlen(s) + 1)); + strcpy(info.u_str,s); + break; + case RD_I_BLO: + rrd_set_error ("rrdc_info: BLOB objects are not supported"); + return (NULL); + default: + rrd_set_error ("rrdc_info: Unsupported info type %d",itype); + return (NULL); + } + + cd = rrd_info_push(cd, sprintf_alloc("%s",k), itype, info); + if(!data) data = cd; + } + response_free (res); + + return (data); +} /* }}} int rrdc_info */ + +time_t rrdc_last (const char *filename) /* {{{ */ +{ + char buffer[4096]; + char *buffer_ptr; + size_t buffer_free; + size_t buffer_size; + rrdc_response_t *res; + int status; + char file_path[PATH_MAX]; + time_t lastup; + + if (filename == NULL) { + rrd_set_error ("rrdc_last: no filename"); + return (-1); + } + + memset (buffer, 0, sizeof (buffer)); + buffer_ptr = &buffer[0]; + buffer_free = sizeof (buffer); + + status = buffer_add_string ("last", &buffer_ptr, &buffer_free); + if (status != 0) { + rrd_set_error ("rrdc_last: out of memory"); + return (-1); + } + + 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); + rrd_set_error ("rrdc_last: out of memory"); + return (-1); + } + + assert (buffer_free < sizeof (buffer)); + buffer_size = sizeof (buffer) - buffer_free; + assert (buffer[buffer_size - 1] == ' '); + buffer[buffer_size - 1] = '\n'; + + res = NULL; + status = request (buffer, buffer_size, &res); + pthread_mutex_unlock (&lock); + + if (status != 0) { + rrd_set_error ("rrdcached: %s", res->message); + return (-1); + } + lastup = atol(res->message); + response_free (res); + + return (lastup); +} /* }}} int rrdc_last */ + +time_t rrdc_first (const char *filename, int rraindex) /* {{{ */ +{ + char buffer[4096]; + char *buffer_ptr; + size_t buffer_free; + size_t buffer_size; + rrdc_response_t *res; + int status; + char file_path[PATH_MAX]; + time_t firstup; + + if (filename == NULL) { + rrd_set_error ("rrdc_first: no filename specified"); + return (-1); + } + + memset (buffer, 0, sizeof (buffer)); + buffer_ptr = &buffer[0]; + buffer_free = sizeof (buffer); + + status = buffer_add_string ("first", &buffer_ptr, &buffer_free); + if (status != 0) { + rrd_set_error ("rrdc_first: out of memory"); + return (-1); + } + + 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); + rrd_set_error ("rrdc_first: out of memory"); + return (-1); + } + status = buffer_add_ulong (rraindex, &buffer_ptr, &buffer_free); + if (status != 0) + { + pthread_mutex_unlock (&lock); + rrd_set_error ("rrdc_first: out of memory"); + return (-1); + } + + assert (buffer_free < sizeof (buffer)); + buffer_size = sizeof (buffer) - buffer_free; + assert (buffer[buffer_size - 1] == ' '); + buffer[buffer_size - 1] = '\n'; + + res = NULL; + status = request (buffer, buffer_size, &res); + pthread_mutex_unlock (&lock); + + if (status != 0) { + rrd_set_error ("rrdcached: %s", res->message); + return (-1); + } + firstup = atol(res->message); + response_free (res); + + return (firstup); +} /* }}} int rrdc_first */ + +int rrdc_create (const char *filename, /* {{{ */ + unsigned long pdp_step, + time_t last_up, + int no_overwrite, + int argc, + const char **argv) +{ + char buffer[4096]; + char *buffer_ptr; + size_t buffer_free; + size_t buffer_size; + rrdc_response_t *res; + int status; + char file_path[PATH_MAX]; + int i; + + if (filename == NULL) { + rrd_set_error ("rrdc_create: no filename specified"); + return (-1); + } + + memset (buffer, 0, sizeof (buffer)); + buffer_ptr = &buffer[0]; + buffer_free = sizeof (buffer); + + status = buffer_add_string ("create", &buffer_ptr, &buffer_free); + if (status != 0) { + rrd_set_error ("rrdc_create: out of memory"); + return (-1); + } + + 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); + status = buffer_add_string ("-b", &buffer_ptr, &buffer_free); + status = buffer_add_ulong (last_up, &buffer_ptr, &buffer_free); + status = buffer_add_string ("-s", &buffer_ptr, &buffer_free); + status = buffer_add_ulong (pdp_step, &buffer_ptr, &buffer_free); + if(no_overwrite) { + status = buffer_add_string ("-O", &buffer_ptr, &buffer_free); + } + if (status != 0) + { + pthread_mutex_unlock (&lock); + rrd_set_error ("rrdc_create: out of memory"); + return (-1); + } + + for( i=0; imessage); + return (-1); + } + response_free (res); + return(0); +} /* }}} int rrdc_create */ + int rrdc_fetch (const char *filename, /* {{{ */ const char *cf, time_t *ret_start, time_t *ret_end, @@ -824,7 +1153,7 @@ int rrdc_fetch (const char *filename, /* {{{ */ size_t buffer_size; rrdc_response_t *res; char path_buffer[PATH_MAX]; - char *path_ptr; + const char *path_ptr; char *str_tmp; unsigned long flush_version;