teach rrd_restore to be able to read the #text value of <a></a> ... this fixes proble...
[rrdtool.git] / src / rrd_restore.c
index 46a79b5..2f671a1 100644 (file)
@@ -1,18 +1,23 @@
 /*****************************************************************************
- * RRDtool 1.3.2  Copyright by Tobi Oetiker, 1997-2009                    
+ * RRDtool 1.4.2  Copyright by Tobi Oetiker, 1997-2009                    
  *****************************************************************************
  * rrd_restore.c  Contains logic to parse XML input and create an RRD file
- *                initial libxml2 version of rrd_restore (c) by Florian octo Forster
+ * This file:
+ * Copyright (C) 2008  Florian octo Forster  (original libxml2 code)
+ * Copyright (C) 2008,2009 Tobias Oetiker
  *****************************************************************************
  * $Id$
  *************************************************************************** */
 
+#include "rrd_tool.h"
+#include "rrd_rpncalc.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <libxml/parser.h>
 #include <libxml/xmlreader.h>
-
+#include <locale.h>
 
 #ifndef WIN32
 #      include <unistd.h>     /* for off_t */
@@ -28,8 +33,6 @@
 # define close _close
 #endif
 
-#include "rrd_tool.h"
-#include "rrd_rpncalc.h"
 
 #define ARRAY_LENGTH(a) (sizeof (a) / sizeof ((a)[0]))
 
@@ -116,7 +119,19 @@ static int expect_element_end (
     char *exp_name)
 {
     xmlChar *name;
-    name = get_xml_element(reader);
+    /* maybe we are already on the end element ... lets see */
+    if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT){
+         xmlChar *temp;
+         xmlChar *temp2;            
+         temp = xmlTextReaderName(reader);
+         temp2 = (xmlChar*)sprintf_alloc("/%s", temp);
+         name = xmlStrdup(temp2);
+         xmlFree(temp);
+         free(temp2);            
+    } else {     
+         name = get_xml_element(reader);
+    }
+
     if (name == NULL)
         return -1;    
     if (xmlStrcasecmp(name+1,(xmlChar *)exp_name) != 0 || name[0] != '/'){
@@ -144,14 +159,24 @@ static xmlChar* get_xml_text (
         if (type == XML_READER_TYPE_ELEMENT){
             xmlChar *name;
             name = xmlTextReaderName(reader);
-            rrd_set_error("line %d: expected a value but found an <%s> element",
+            rrd_set_error("line %d: expected a value but found a <%s> element",
                           xmlTextReaderGetParserLineNumber(reader),
                           name);
             xmlFree(name);            
             return NULL;            
         }
+
+        /* trying to read text from <a></a> we end up here
+           lets return an empty string insead. This is a tad optimistic
+           since we do not check if it is actually </a> and not </b>
+           we got, but first we do not know if we expect </a> and second
+           we the whole implementation is on the optimistic side. */
+        if (type == XML_READER_TYPE_END_ELEMENT){
+            return  xmlStrdup(BAD_CAST "");
+        }        
+
         /* skip all other non-text */
-        if (xmlTextReaderNodeType(reader) != XML_READER_TYPE_TEXT)
+        if (type != XML_READER_TYPE_TEXT)
             continue;
         
         text = xmlTextReaderValue(reader);
@@ -273,21 +298,21 @@ static int get_xml_double(
     double *value)
 {
     
-    char *text;
+    xmlChar *text;
     double temp;    
-    if ((text = (char *)get_xml_text(reader))!= NULL){
-        if (strcasestr(text,"nan")){
+    if ((text = get_xml_text(reader))!= NULL){
+        if (xmlStrcasestr(text,(xmlChar *)"nan")){
             *value = DNAN;
             xmlFree(text);
             return 0;            
         }
-        else if (strcasestr(text,"-inf")){
+        else if (xmlStrcasestr(text,(xmlChar *)"-inf")){
             *value = -DINF;
             xmlFree(text);
             return 0;            
         }
-        else if (strcasestr(text,"+inf")
-                 || strcasestr(text,"inf")){
+        else if (xmlStrcasestr(text,(xmlChar *)"+inf")
+                 || xmlStrcasestr(text,(xmlChar *)"inf")){
             *value = DINF;
             xmlFree(text);
             return 0;            
@@ -1212,7 +1237,7 @@ int rrd_restore(
     char **argv)
 {
     rrd_t    *rrd;
-
+    char     *old_locale;
     /* init rrd clean */
     optind = 0;
     opterr = 0;         /* initialize getopt */
@@ -1254,7 +1279,12 @@ int rrd_restore(
         return (-1);
     }
 
+    old_locale = setlocale(LC_NUMERIC, "C");
+
     rrd = parse_file(argv[optind]);
+
+    setlocale(LC_NUMERIC, old_locale);
+
     if (rrd == NULL)
         return (-1);