Code

fix freeing order when generating error messages. found by Dmitry V. Krivenok
[rrdtool.git] / src / rrd_restore.c
index 57eb82ebd4d4b00d0a5ac87af30c20dcf9c831e5..c5cbcd2dffae485242236e9bd7793dd45054a604 100644 (file)
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * RRDtool 1.3.1  Copyright by Tobi Oetiker, 1997-2008
+ * RRDtool 1.3.8  Copyright by Tobi Oetiker, 1997-2009
  * This file:     Copyright 2008 Florian octo Forster
  * Distributed under the GPL
  *****************************************************************************
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
-#include <unistd.h>
 #include <fcntl.h>
-#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
+
+#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
+#include <math.h>
 # include <io.h>
 # define open _open
 # define close _close
+#else
+# include <unistd.h>
 #endif
+
 #include <libxml/parser.h>
 #include "rrd_tool.h"
 #include "rrd_rpncalc.h"
@@ -87,35 +91,106 @@ static int get_string_from_node(
     return (0);
 }                       /* int get_string_from_node */
 
-static int get_int_from_node(
+static int get_long_from_node(
     xmlDoc * doc,
     xmlNode * node,
-    int *value)
+    long *value)
 {
-    int       temp;
+    long       temp;
     char     *str_ptr;
     char     *end_ptr;
 
     str_ptr = (char *) xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
     if (str_ptr == NULL) {
-        rrd_set_error("get_int_from_node: xmlNodeListGetString failed.");
+        rrd_set_error("get_long_from_node: xmlNodeListGetString failed.");
         return (-1);
     }
 
     end_ptr = NULL;
     temp = strtol(str_ptr, &end_ptr, 0);
+
+    if (str_ptr == end_ptr) {
+        rrd_set_error("get_long_from_node: Cannot parse buffer as long: %s",
+                      str_ptr);
+        xmlFree(str_ptr);
+        return (-1);
+    }
     xmlFree(str_ptr);
+    *value = temp;
+
+    return (0);
+}                       /* int get_long_from_node */
+
+static int get_ulong_from_node(
+    xmlDoc * doc,
+    xmlNode * node,
+    unsigned long *value)
+{
+    unsigned long       temp;
+    char     *str_ptr;
+    char     *end_ptr;
+
+    str_ptr = (char *) xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+    if (str_ptr == NULL) {
+        rrd_set_error("get_ulong_from_node: xmlNodeListGetString failed.");
+        return (-1);
+    }
+
+    end_ptr = NULL;
+    temp = strtoul(str_ptr, &end_ptr, 0);
 
     if (str_ptr == end_ptr) {
-        rrd_set_error("get_int_from_node: Cannot parse buffer as int: %s",
+        rrd_set_error("get_ulong_from_node: Cannot parse buffer as unsigned long: %s",
                       str_ptr);
+        xmlFree(str_ptr);
         return (-1);
     }
+    xmlFree(str_ptr);
+    *value = temp;
 
+    return (0);
+}                       /* int get_ulong_from_node */
+
+
+#ifdef WIN32
+/* Gross Hack Alert */
+#if _MSC_VER < 1300
+#define strtoll(p, e, b) ((*(e) = (char*)(p) + (((b) == 10) ? strspn((p), "0123456789") : 0)), _atoi64(p))
+#else
+#define strtoll(p, e, b) _strtoi64(p, e, b)
+#endif
+#endif
+
+static int get_llong_from_node(
+    xmlDoc * doc,
+    xmlNode * node,
+    long long *value)
+{
+    long long       temp;
+    char     *str_ptr;
+    char     *end_ptr;
+
+    str_ptr = (char *) xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+    if (str_ptr == NULL) {
+        rrd_set_error("get_llong_from_node: xmlNodeListGetString failed.");
+        return (-1);
+    }
+
+    end_ptr = NULL;
+    temp = strtoll(str_ptr, &end_ptr, 10);
+
+    if (str_ptr == end_ptr) {
+        rrd_set_error("get_llong_from_node: Cannot parse buffer as unsigned long long: %s",
+                      str_ptr);
+        xmlFree(str_ptr);
+        return (-1);
+    }
+    xmlFree(str_ptr);
     *value = temp;
 
     return (0);
-}                       /* int get_int_from_node */
+}                       /* int get_llong_from_node */
 
 static int get_double_from_node(
     xmlDoc * doc,
@@ -132,17 +207,24 @@ static int get_double_from_node(
         return (-1);
     }
 
+    if (strstr(str_ptr, "NaN") != NULL)
+    {
+        *value = DNAN;
+        xmlFree(str_ptr);
+        return 0;
+    }
+
     end_ptr = NULL;
     temp = strtod(str_ptr, &end_ptr);
-    xmlFree(str_ptr);
 
     if (str_ptr == end_ptr) {
         rrd_set_error
             ("get_double_from_node: Cannot parse buffer as double: %s",
              str_ptr);
+        xmlFree(str_ptr);
         return (-1);
     }
-
+    xmlFree(str_ptr);           
     *value = temp;
 
     return (0);
@@ -356,14 +438,14 @@ static int parse_tag_rra_cdp_prep_ds(
                                           &cdp_prep->
                                           scratch[CDP_hw_last_slope].u_val);
         else if (xmlStrcmp(child->name, (const xmlChar *) "nan_count") == 0)
-            status = get_int_from_node(doc, child,
-                                       (int *) &cdp_prep->
+            status = get_ulong_from_node(doc, child,
+                                        &cdp_prep->
                                        scratch[CDP_null_count].u_cnt);
         else if (xmlStrcmp(child->name, (const xmlChar *) "last_nan_count") ==
                  0)
             status =
-                get_int_from_node(doc, child,
-                                  (int *) &cdp_prep->
+                get_ulong_from_node(doc, child,
+                                   &cdp_prep->
                                   scratch[CDP_last_null_count].u_cnt);
         else if (xmlStrcmp(child->name, (const xmlChar *) "seasonal") == 0)
             status = get_double_from_node(doc, child,
@@ -376,8 +458,8 @@ static int parse_tag_rra_cdp_prep_ds(
                                      &cdp_prep->scratch[CDP_hw_last_seasonal].
                                      u_val);
         else if (xmlStrcmp(child->name, (const xmlChar *) "init_flag") == 0)
-            status = get_int_from_node(doc, child,
-                                       (int *) &cdp_prep->
+            status = get_ulong_from_node(doc, child,
+                                        &cdp_prep->
                                        scratch[CDP_init_seasonal].u_cnt);
         else if (xmlStrcmp(child->name, (const xmlChar *) "history") == 0)
             status = parse_tag_rra_cdp_prep_ds_history(doc, child, cdp_prep);
@@ -386,8 +468,8 @@ static int parse_tag_rra_cdp_prep_ds(
                                           &cdp_prep->scratch[CDP_val].u_val);
         else if (xmlStrcmp(child->name,
                            (const xmlChar *) "unknown_datapoints") == 0)
-            status = get_int_from_node(doc, child,
-                                       (int *) &cdp_prep->
+            status = get_ulong_from_node(doc, child,
+                                        &cdp_prep->
                                        scratch[CDP_unkn_pdp_cnt].u_cnt);
         else {
             rrd_set_error("parse_tag_rra_cdp_prep: Unknown tag: %s",
@@ -473,8 +555,8 @@ static int parse_tag_rra_params(
                                           &rra_def->par[RRA_hw_beta].u_val);
         else if (xmlStrcmp(child->name,
                            (const xmlChar *) "dependent_rra_idx") == 0)
-            status = get_int_from_node(doc, child,
-                                       (int *) &rra_def->
+            status = get_ulong_from_node(doc, child,
+                                        &rra_def->
                                        par[RRA_dependent_rra_idx].u_cnt);
         /*
          * Parameters for CF_SEASONAL and CF_DEVSEASONAL
@@ -487,8 +569,8 @@ static int parse_tag_rra_params(
         else if (xmlStrcmp
                  (child->name, (const xmlChar *) "seasonal_smooth_idx") == 0)
             status =
-                get_int_from_node(doc, child,
-                                  (int *) &rra_def->
+                get_ulong_from_node(doc, child,
+                                   &rra_def->
                                   par[RRA_seasonal_smooth_idx].u_cnt);
         else if (xmlStrcmp(child->name, (const xmlChar *) "smoothing_window")
                  == 0)
@@ -508,14 +590,14 @@ static int parse_tag_rra_params(
             status = get_double_from_node(doc, child,
                                           &rra_def->par[RRA_delta_neg].u_val);
         else if (xmlStrcmp(child->name, (const xmlChar *) "window_len") == 0)
-            status = get_int_from_node(doc, child,
-                                       (int *) &rra_def->par[RRA_window_len].
+            status = get_ulong_from_node(doc, child,
+                                        &rra_def->par[RRA_window_len].
                                        u_cnt);
         else if (xmlStrcmp(child->name, (const xmlChar *) "failure_threshold")
                  == 0)
             status =
-                get_int_from_node(doc, child,
-                                  (int *) &rra_def->
+                get_ulong_from_node(doc, child,
+                                   &rra_def->
                                   par[RRA_failure_threshold].u_cnt);
         /*
          * Parameters for CF_AVERAGE, CF_MAXIMUM, CF_MINIMUM, and CF_LAST
@@ -539,8 +621,8 @@ static int parse_tag_rra_params(
                 if ((i == RRA_dependent_rra_idx)
                     || (i == RRA_seasonal_smooth_idx)
                     || (i == RRA_failure_threshold))
-                    status = get_int_from_node(doc, child,
-                                               (int *) &rra_def->par[i].
+                    status = get_ulong_from_node(doc, child,
+                                                &rra_def->par[i].
                                                u_cnt);
                 else
                     status = get_double_from_node(doc, child,
@@ -671,8 +753,8 @@ static int parse_tag_rra(
         else if (xmlStrcmp(child->name, (const xmlChar *) "cf") == 0)
             status = parse_tag_rra_cf(doc, child, cur_rra_def);
         else if (xmlStrcmp(child->name, (const xmlChar *) "pdp_per_row") == 0)
-            status = get_int_from_node(doc, child,
-                                       (int *) &cur_rra_def->pdp_cnt);
+            status = get_ulong_from_node(doc, child,
+                                        &cur_rra_def->pdp_cnt);
         else if (atoi(rrd->stat_head->version) == 1
                  && xmlStrcmp(child->name, (const xmlChar *) "xff") == 0)
             status = get_double_from_node(doc, child,
@@ -695,7 +777,11 @@ static int parse_tag_rra(
     }
 
     /* Set the RRA pointer to a random location */
+#ifdef WIN32
+    cur_rra_ptr->cur_row = rand() % cur_rra_def->row_cnt;
+#else
     cur_rra_ptr->cur_row = random() % cur_rra_def->row_cnt;
+#endif
 
     return (status);
 }                       /* int parse_tag_rra */
@@ -814,8 +900,8 @@ static int parse_tag_ds(
             status = parse_tag_ds_type(doc, child, cur_ds_def);
         else if (xmlStrcmp(child->name,
                            (const xmlChar *) "minimal_heartbeat") == 0)
-            status = get_int_from_node(doc, child,
-                                       (int *) &cur_ds_def->par[DS_mrhb_cnt].
+            status = get_ulong_from_node(doc, child,
+                                        &cur_ds_def->par[DS_mrhb_cnt].
                                        u_cnt);
         else if (xmlStrcmp(child->name, (const xmlChar *) "min") == 0)
             status = get_double_from_node(doc, child,
@@ -834,8 +920,8 @@ static int parse_tag_ds(
                                           &cur_pdp_prep->scratch[PDP_val].
                                           u_val);
         else if (xmlStrcmp(child->name, (const xmlChar *) "unknown_sec") == 0)
-            status = get_int_from_node(doc, child,
-                                       (int *) &cur_pdp_prep->
+            status = get_ulong_from_node(doc, child,
+                                        &cur_pdp_prep->
                                        scratch[PDP_unkn_sec_cnt].u_cnt);
         else {
             rrd_set_error("parse_tag_ds: Unknown tag: %s", child->name);
@@ -870,11 +956,21 @@ static int parse_tag_rrd(
                                           rrd->stat_head->version,
                                           sizeof(rrd->stat_head->version));
         else if (xmlStrcmp(child->name, (const xmlChar *) "step") == 0)
-            status = get_int_from_node(doc, child,
-                                       (int *) &rrd->stat_head->pdp_step);
-        else if (xmlStrcmp(child->name, (const xmlChar *) "lastupdate") == 0)
-            status = get_int_from_node(doc, child,
-                                       (int *) &rrd->live_head->last_up);
+            status = get_ulong_from_node(doc, child,
+                                        &rrd->stat_head->pdp_step);
+        else if (xmlStrcmp(child->name, (const xmlChar *) "lastupdate") == 0) {
+            if (sizeof(time_t) == sizeof(long)) {
+               status = get_long_from_node(doc, child, (long *)&rrd->live_head->last_up);
+            }
+            else { if (sizeof(time_t) == sizeof(long long)) {
+                       status = get_llong_from_node(doc, child, (long long *)&rrd->live_head->last_up);
+                    }
+                    else {
+                       rrd_set_error("can't convert to time_t ...", child->name);
+                       status = -1;    
+                    }
+            }
+        }
         else if (xmlStrcmp(child->name, (const xmlChar *) "ds") == 0)
             status = parse_tag_ds(doc, child, rrd);
         else if (xmlStrcmp(child->name, (const xmlChar *) "rra") == 0)
@@ -1043,7 +1139,11 @@ int rrd_restore(
 {
     rrd_t    *rrd;
 
+#ifdef WIN32
+    srand((unsigned int) time(NULL));
+#else
     srandom((unsigned int) time(NULL) + (unsigned int) getpid());
+#endif
     /* init rrd clean */
     optind = 0;
     opterr = 0;         /* initialize getopt */