/*****************************************************************************
- * RRDtool 1.GIT, Copyright by Tobi Oetiker
+ * RRDtool 1.8.0 Copyright by Tobi Oetiker, 1997-2022
*****************************************************************************
* rrd_dump Display a RRD
*****************************************************************************
* library is identical to librrd, but it contains support code for per-thread
* global variables currently used for error information only. This is similar
* to how errno per-thread variables are implemented. librrd_th must be linked
- * alongside of libpthred
+ * alongside of libpthread
*
* There is also a new file "THREADS", holding some documentation.
*
#include "rrd_snprintf.h"
-#if !(defined(NETWARE) || defined(WIN32))
+#if !(defined(NETWARE) || defined(_WIN32))
extern char *tzname[2];
#endif
-//Local prototypes
-size_t rrd_dump_opt_cb_fileout(
- const void *data,
- size_t len,
- void *user);
-
-int rrd_dump_opt_r(
- const char *filename,
- char *outname,
- int opt_noheader);
-
int rrd_dump_cb_r(
const char *filename,
int opt_header,
rrd_value_t value;
struct tm tm;
-//These two macros are local defines to clean up visible code from its redndancy
+//These two macros are local defines to clean up visible code from its redundancy
//and make it easier to read.
#define CB_PUTS(str) \
- cb((str), strlen((str)), user)
+ do { \
+ size_t len = strlen(str); \
+ \
+ if (cb((str), len, user) != len) \
+ goto err_out; \
+ } while (0);
#define CB_FMTS(...) do { \
char buffer[256]; \
rrd_snprintf (buffer, sizeof(buffer), __VA_ARGS__); \
rrd_init(&rrd);
- rrd_file = rrd_open(filename, &rrd, RRD_READONLY | RRD_READAHEAD);
+ rrd_file = rrd_open(filename, &rrd, RRD_READONLY | RRD_LOCK |
+ RRD_READAHEAD);
if (rrd_file == NULL) {
rrd_free(&rrd);
return (-1);
if (opt_header == 1) {
CB_PUTS("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
- CB_PUTS("<!DOCTYPE rrd SYSTEM \"http://oss.oetiker.ch/rrdtool/rrdtool.dtd\">\n");
+ CB_PUTS("<!DOCTYPE rrd SYSTEM \"https://oss.oetiker.ch/rrdtool/rrdtool.dtd\">\n");
CB_PUTS("<!-- Round Robin Database Dump -->\n");
CB_PUTS("<rrd>\n");
} else if (opt_header == 2) {
CB_PUTS("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
CB_PUTS("<!-- Round Robin Database Dump -->\n");
- CB_PUTS("<rrd xmlns=\"http://oss.oetiker.ch/rrdtool/rrdtool-dump.xml\" "
+ CB_PUTS("<rrd xmlns=\"https://oss.oetiker.ch/rrdtool/rrdtool-dump.xml\" "
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
- CB_PUTS("\txsi:schemaLocation=\"http://oss.oetiker.ch/rrdtool/rrdtool-dump.xml "
- "http://oss.oetiker.ch/rrdtool/rrdtool-dump.xsd\">\n");
+ CB_PUTS("\txsi:schemaLocation=\"https://oss.oetiker.ch/rrdtool/rrdtool-dump.xml "
+ "https://oss.oetiker.ch/rrdtool/rrdtool-dump.xsd\">\n");
} else {
CB_PUTS("<!-- Round Robin Database Dump -->\n");
CB_PUTS("<rrd>\n");
#else
# error "Need strftime"
#endif
+#if defined (_MSC_VER) && (_M_IX86)
+/* Otherwise (null) will be written to %s when compiling for 32-bit using MSVC */
+/* works for both, with or without _USE_32BIT_TIME_T */
+ CB_FMTS("\t<lastupdate>%ld</lastupdate> <!-- %s -->\n\n",
+ (long int) rrd.live_head->last_up, somestring);
+#else
CB_FMTS("\t<lastupdate>%lld</lastupdate> <!-- %s -->\n\n",
(long long int) rrd.live_head->last_up, somestring);
+#endif
for (i = 0; i < rrd.stat_head->ds_cnt; i++) {
CB_PUTS("\t<ds>\n");
/* support for RRA parameters */
CB_PUTS("\t\t<params>\n");
- switch (cf_conv(rrd.rra_def[i].cf_nam)) {
+ switch (rrd_cf_conv(rrd.rra_def[i].cf_nam)) {
case CF_HWPREDICT:
case CF_MHWPREDICT:
CB_FMTS("\t\t<hw_alpha>%0.10e</hw_alpha>\n",
CB_FMTS("\t\t\t<secondary_value>%0.10e</secondary_value>\n", value);
}
- switch (cf_conv(rrd.rra_def[i].cf_nam)) {
+ switch (rrd_cf_conv(rrd.rra_def[i].cf_nam)) {
case CF_HWPREDICT:
case CF_MHWPREDICT:
value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
now = (rrd.live_head->last_up
- rrd.live_head->last_up
% (rrd.rra_def[i].pdp_cnt * rrd.stat_head->pdp_step))
- + (timer * rrd.rra_def[i].pdp_cnt * rrd.stat_head->pdp_step);
+ + (timer * (long)rrd.rra_def[i].pdp_cnt * (long)rrd.stat_head->pdp_step);
timer++;
-#if HAVE_STRFTIME
+#ifdef HAVE_STRFTIME
localtime_r(&now, &tm);
strftime(somestring, 255, "%Y-%m-%d %H:%M:%S %Z", &tm);
#else
return rrd_close(rrd_file);
+err_out:
+ rrd_set_error("error writing output file: %s", rrd_strerror(errno));
+ rrd_free(&rrd);
+ rrd_close(rrd_file);
+ return (-1);
+
//Undefining the previously defined shortcuts
//See start of this function
#undef CB_PUTS
}
-size_t rrd_dump_opt_cb_fileout(
+static size_t rrd_dump_opt_cb_fileout(
const void *data,
size_t len,
void *user)
res = rrd_dump_cb_r(filename, opt_noheader, rrd_dump_opt_cb_fileout, (void *)out_file);
+ if (fflush(out_file) != 0) {
+ rrd_set_error("error flushing output: %s", rrd_strerror(errno));
+ res = -1;
+ }
if (out_file != stdout) {
fclose(out_file);
+ if (res != 0)
+ unlink(outname);
}
return res;
int argc,
char **argv)
{
+ int opt;
+ struct optparse_long longopts[] = {
+ {"daemon", 'd', OPTPARSE_REQUIRED},
+ {"header", 'h', OPTPARSE_REQUIRED},
+ {"no-header", 'n', OPTPARSE_NONE},
+ {0},
+ };
+ struct optparse options;
int rc;
/**
* 0 = no header
/* init rrd clean */
- optind = 0;
- opterr = 0; /* initialize getopt */
-
- while (42) {/* ha ha */
- int opt;
- int option_index = 0;
- static struct option long_options[] = {
- {"daemon", required_argument, 0, 'd'},
- {"header", required_argument, 0, 'h'},
- {"no-header", no_argument, 0, 'n'},
- {0, 0, 0, 0}
- };
-
- opt = getopt_long(argc, argv, "d:h:n", long_options, &option_index);
-
- if (opt == EOF)
- break;
-
+ optparse_init(&options, argc, argv);
+ while ((opt = optparse_long(&options, longopts, NULL)) != -1) {
switch (opt) {
case 'd':
- if (opt_daemon != NULL)
+ if (opt_daemon != NULL) {
free (opt_daemon);
- opt_daemon = strdup (optarg);
+ }
+ opt_daemon = strdup(options.optarg);
if (opt_daemon == NULL)
{
rrd_set_error ("strdup failed.");
break;
case 'h':
- if (strcmp(optarg, "dtd") == 0) {
+ if (strcmp(options.optarg, "dtd") == 0) {
opt_header = 1;
- } else if (strcmp(optarg, "xsd") == 0) {
+ } else if (strcmp(options.optarg, "xsd") == 0) {
opt_header = 2;
- } else if (strcmp(optarg, "none") == 0) {
+ } else if (strcmp(options.optarg, "none") == 0) {
opt_header = 0;
}
break;
default:
- rrd_set_error("usage rrdtool %s [--header|-h {none,xsd,dtd}] [--no-header]"
- "file.rrd [file.xml]", argv[0]);
+ rrd_set_error("usage rrdtool %s [--header|-h {none,xsd,dtd}]\n"
+ "[--no-header|-n]\n"
+ "[--daemon|-d address]\n"
+ "file.rrd [file.xml]", options.argv[0]);
+ if (opt_daemon != NULL) {
+ free(opt_daemon);
+ }
return (-1);
break;
}
- } /* while (42) */
-
- if ((argc - optind) < 1 || (argc - optind) > 2) {
- rrd_set_error("usage rrdtool %s [--header|-h {none,xsd,dtd}] [--no-header]"
- "file.rrd [file.xml]", argv[0]);
+ } /* while (opt != -1) */
+
+ if ((options.argc - options.optind) < 1 || (options.argc - options.optind) > 2) {
+ rrd_set_error("usage rrdtool %s [--header|-h {none,xsd,dtd}]\n"
+ "[--no-header|-n]\n"
+ "[--daemon|-d address]\n"
+ "file.rrd [file.xml]", options.argv[0]);
+ if (opt_daemon != NULL) {
+ free(opt_daemon);
+ }
return (-1);
}
- rc = rrdc_flush_if_daemon(opt_daemon, argv[optind]);
- if (opt_daemon) free(opt_daemon);
+ rc = rrdc_flush_if_daemon(opt_daemon, options.argv[options.optind]);
+ if (opt_daemon != NULL) {
+ free(opt_daemon);
+ }
if (rc) return (rc);
- if ((argc - optind) == 2) {
- rc = rrd_dump_opt_r(argv[optind], argv[optind + 1], opt_header);
+ if ((options.argc - options.optind) == 2) {
+ rc = rrd_dump_opt_r(options.argv[options.optind], options.argv[options.optind + 1], opt_header);
} else {
- rc = rrd_dump_opt_r(argv[optind], NULL, opt_header);
+ rc = rrd_dump_opt_r(options.argv[options.optind], NULL, opt_header);
}
return rc;