rrdtool is assuming that rrd_xport will always return -1 on failure;
[rrdtool.git] / src / rrd_create.c
index 707e601..a36b31d 100644 (file)
@@ -14,7 +14,6 @@
 #include "rrd_client.h"
 
 #include "rrd_is_thread_safe.h"
-static int opt_no_overwrite = 0;
 
 #ifdef WIN32
 # include <process.h>
@@ -34,12 +33,6 @@ void      parseGENERIC_DS(
 static void rrd_free2(
     rrd_t *rrd);        /* our onwn copy, immmune to mmap */
 
-void rrd_create_set_no_overwrite( 
-    int opt ) 
-{
-       opt_no_overwrite = (opt?1:0);
-}
-
 int rrd_create(
     int argc,
     char **argv)
@@ -60,6 +53,7 @@ int rrd_create(
     long      long_tmp;
     int       rc;
     char * opt_daemon = NULL;
+    int       opt_no_overwrite = 0;
 
     optind = 0;
     opterr = 0;         /* initialize getopt */
@@ -135,8 +129,8 @@ int rrd_create(
                       pdp_step, last_up, opt_no_overwrite,
                       argc - optind - 1, (const char **) (argv + optind + 1));
        } else {
-    rc = rrd_create_r(argv[optind],
-                      pdp_step, last_up,
+        rc = rrd_create_r2(argv[optind],
+                      pdp_step, last_up, opt_no_overwrite,
                       argc - optind - 1, (const char **) (argv + optind + 1));
        }
 
@@ -144,6 +138,8 @@ int rrd_create(
 }
 
 /* #define DEBUG */
+/* For backwards compatibility with previous API.  Use rrd_create_r2 if you
+   need to have the no_overwrite parameter.                                */
 int rrd_create_r(
     const char *filename,
     unsigned long pdp_step,
@@ -151,6 +147,16 @@ int rrd_create_r(
     int argc,
     const char **argv)
 {
+       return rrd_create_r2(filename,pdp_step,last_up,0,argc,argv);
+}
+int rrd_create_r2(
+    const char *filename,
+    unsigned long pdp_step,
+    time_t last_up,
+    int no_overwrite,
+    int argc,
+    const char **argv)
+{
     rrd_t     rrd;
     long      i;
     int       offset;
@@ -269,9 +275,10 @@ int rrd_create_r(
         } else if (strncmp(argv[i], "RRA:", 4) == 0) {
             char     *argvcopy;
             char     *tokptr = "";
+            int       cf_id = -1;
             size_t    old_size = sizeof(rra_def_t) * (rrd.stat_head->rra_cnt);
             int       row_cnt;
-
+            int       token_min = 4;
             if ((rrd.rra_def = (rra_def_t*)rrd_realloc(rrd.rra_def,
                                            old_size + sizeof(rra_def_t))) ==
                 NULL) {
@@ -285,6 +292,7 @@ int rrd_create_r(
             argvcopy = strdup(argv[i]);
             token = strtok_r(&argvcopy[4], ":", &tokptr);
             token_idx = error_flag = 0;
+            
             while (token != NULL) {
                 switch (token_idx) {
                 case 0:
@@ -292,11 +300,12 @@ int rrd_create_r(
                                rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam) !=
                         1)
                         rrd_set_error("Failed to parse CF name");
-                    switch (cf_conv
-                            (rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
+                    cf_id = cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam);
+                    switch (cf_id) {
                     case CF_MHWPREDICT:
                         strcpy(rrd.stat_head->version, RRD_VERSION);    /* MHWPREDICT causes Version 4 */
                     case CF_HWPREDICT:
+                        token_min = 5;
                         /* initialize some parameters */
                         rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_hw_alpha].
                             u_val = 0.1;
@@ -307,7 +316,11 @@ int rrd_create_r(
                             rrd.stat_head->rra_cnt;
                         break;
                     case CF_DEVSEASONAL:
+                        token_min = 3;
                     case CF_SEASONAL:
+                        if (cf_id == CF_SEASONAL){
+                           token_min = 4;
+                        }
                         /* initialize some parameters */
                         rrd.rra_def[rrd.stat_head->rra_cnt].
                             par[RRA_seasonal_gamma].u_val = 0.1;
@@ -315,10 +328,14 @@ int rrd_create_r(
                             par[RRA_seasonal_smoothing_window].u_val = 0.05;
                         /* fall through */
                     case CF_DEVPREDICT:
+                        if (cf_id == CF_DEVPREDICT){
+                           token_min = 3;
+                        }
                         rrd.rra_def[rrd.stat_head->rra_cnt].
                             par[RRA_dependent_rra_idx].u_cnt = -1;
                         break;
                     case CF_FAILURES:
+                        token_min = 5;
                         rrd.rra_def[rrd.stat_head->rra_cnt].
                             par[RRA_delta_pos].u_val = 2.0;
                         rrd.rra_def[rrd.stat_head->rra_cnt].
@@ -540,6 +557,11 @@ int rrd_create_r(
                 token_idx++;
             }           /* end while */
             free(argvcopy);
+            if (token_idx < token_min){
+                rrd_set_error("Expected at least %i arguments for RRA but got %i",token_min,token_idx);
+                rrd_free2(&rrd);
+                return(-1);
+            }
 #ifdef DEBUG
             fprintf(stderr,
                     "Creating RRA CF: %s, dep idx %lu, current idx %lu\n",
@@ -584,7 +606,7 @@ int rrd_create_r(
         rrd_free2(&rrd);
         return (-1);
     }
-    return rrd_create_fn(filename, &rrd);
+    return rrd_create_fn(filename, &rrd, no_overwrite);
 }
 
 void parseGENERIC_DS(
@@ -708,7 +730,8 @@ int create_hw_contingent_rras(
 
 int rrd_create_fn(
     const char *file_name,
-    rrd_t *rrd)
+    rrd_t *rrd,
+    int no_overwrite )
 {
     unsigned long i, ii;
     rrd_value_t *unknown;
@@ -717,7 +740,7 @@ int rrd_create_fn(
     rrd_t     rrd_dn;
     unsigned  rrd_flags = RRD_READWRITE | RRD_CREAT;
 
-    if (opt_no_overwrite) {
+    if (no_overwrite) {
       rrd_flags |= RRD_EXCL ;
     }