From: Peter Stamfest Date: Wed, 19 Feb 2014 08:56:16 +0000 (+0100) Subject: Add support for rrd restore to explicitly end xml files when using X-Git-Tag: v1.4.9~21^2^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eb9f3463819cdf2ca81336d90050f56707da4cc7;p=thirdparty%2Frrdtool-1.x.git Add support for rrd restore to explicitly end xml files when using the pipe interface by using the "-" special filename and using ctrl-Z/newline as an end-of-file indicator. --- diff --git a/doc/rrdrestore.pod b/doc/rrdrestore.pod index e098e0df..4d17ba68 100644 --- a/doc/rrdrestore.pod +++ b/doc/rrdrestore.pod @@ -16,7 +16,16 @@ it to the native B format. =item I -The name of the B file you want to restore. +The name of the B file you want to restore. The special filename "-" +(a single dash) is interpreted as standard input. + +In order to support the restore command in pipe mode (especially when +using B over a network connection), when using "-" as a filename +the end of the file can be signalled either by closing the data +channel after the file has transferred (as would be the case when +using input redirection within a suitable shell) or by sending a +crtl-Z / newline combination. This allows to send more commands to the +B server after a restore. =item I diff --git a/src/rrd_restore.c b/src/rrd_restore.c index 2447a3ee..b2bfa8a2 100644 --- a/src/rrd_restore.c +++ b/src/rrd_restore.c @@ -1059,6 +1059,65 @@ static int parse_tag_rrd( return (status); } /* int parse_tag_rrd */ +/* helper type for stdioXmlInputReaderForPipeInterface */ + +typedef struct stdioXmlReaderContext_t { + FILE *stream; + int freeOnClose; + int closed; + char eofchar; +} stdioXmlReaderContext; + +/* + * this is a xmlInputReadCallback that is used for the pipe interface + * in case the passed filename is "-" (meaning standard input) to take + * care it will never actually close the stdio stream stdin. It will + * report eof once it reads the eof character (currently set to ctrl-Z + * (character code 26, hex 0x1A) in the calling code) anywhere on a line. + * + * Note that ctrl-Z is not an allowed character in XML 1.0 (which rrdtool + * uses). + * + */ +static int stdioXmlInputReadCallback( + void *context, + char *buffer, + int len) +{ + stdioXmlReaderContext *sctx = (stdioXmlReaderContext*) context; + + if (sctx == NULL) return -1; + if (sctx->stream == NULL) return -1; + if (sctx->closed) return 0; + + char *r = fgets(buffer, len, sctx->stream); + if (r == NULL) { + sctx->closed = 1; + return 0; + } + + char *where = strchr(r, sctx->eofchar); + if (where != NULL) { + sctx->closed = 1; + *where = 0; + } + + return strlen(r); +} + +static int stdioXmlInputCloseCallback(void *context) +{ + stdioXmlReaderContext *sctx = (stdioXmlReaderContext*) context; + + if (sctx == NULL) return 0; + + if (sctx->freeOnClose) { + sctx->freeOnClose = 0; + free(sctx); + } + return 0; /* everything is OK */ +} + static rrd_t *parse_file( const char *filename) { @@ -1066,15 +1125,43 @@ static rrd_t *parse_file( int status; rrd_t *rrd; - - reader = xmlNewTextReaderFilename(filename); + stdioXmlReaderContext *sctx = NULL; + + if (strcmp(filename, "-") == 0) { + sctx = malloc(sizeof(*sctx)); + if (sctx == NULL) { + rrd_set_error("parse_file: malloc failed."); + return (NULL); + } + sctx->stream = stdin; + sctx->freeOnClose = 1; + sctx->closed = 0; + sctx->eofchar = 0x1A; /* ctrl-Z */ + + reader = xmlReaderForIO(stdioXmlInputReadCallback, + stdioXmlInputCloseCallback, + sctx, + filename, + NULL, + 0); + } else { + reader = xmlNewTextReaderFilename(filename); + } if (reader == NULL) { + if (sctx != NULL) free(sctx); + rrd_set_error("Could not create xml reader for: %s",filename); return (NULL); } + /* NOTE: from now on, sctx will get free'd implicitly through + * xmlFreeTextReader and its call to + * stdioXmlInputCloseCallback. */ + if (expect_element(reader,"rrd") != 0) { xmlFreeTextReader(reader); + + if (sctx != NULL) free(sctx); return (NULL); }