]> granicus.if.org Git - vnstat/commitdiff
enforce the existence and uniqueness of all interfaces in a merge query
authorTeemu Toivola <git@humdi.net>
Sat, 16 Mar 2019 20:24:31 +0000 (22:24 +0200)
committerTeemu Toivola <git@humdi.net>
Sat, 16 Mar 2019 20:24:31 +0000 (22:24 +0200)
man/vnstat.1
man/vnstati.1
src/dbsql.c
src/dbsql.h
src/vnstat.c
src/vnstati.c
tests/dbsql_tests.c

index 0b1b1bc7785866704134211563cb0049dd9f51fe..2ddf7d630ad873449c950b01f2700d54a05835ce 100644 (file)
@@ -188,7 +188,8 @@ Select one specific
 and apply actions to only it. For queries, it is possible to merge the
 information of two or more interfaces using the
 .I interface1+interface2+...
-syntax.
+syntax. All provided interfaces must be unique and must exist in the database
+when the merge syntax is used.
 
 .TP
 .B "--iflist"
index a6e54332336c485dd69f3e53cb6e751021e3e097..4678dc2b1e24ad74dba75bd26c4b4d369a408531 100644 (file)
@@ -188,7 +188,8 @@ Use
 instead of default or configured interface. It is also possible to merge the
 information of two or more interfaces using the
 .I interface1+interface2+...
-syntax.
+syntax.  All provided interfaces must be unique and must exist in the database
+when the merge syntax is used.
 
 .TP
 .BI "--locale " locale
index 91b18d435fc177f246ef018841d17f00186fd475..f60159a2412aa211e8ff05021df0a6d1d7240cb0 100644 (file)
@@ -354,7 +354,6 @@ uint64_t db_getinterfacecountbyname(const char *iface)
                        sqlite3_snprintf(512, sql, "select count(*) from interface");
                }
        } else {
-               /* TODO: possibly verify all given interfaces exist in the database */
                inquery = getifaceinquery(iface);
                if (inquery == NULL) {
                        return 0;
@@ -378,6 +377,13 @@ uint64_t db_getinterfacecountbyname(const char *iface)
        }
        sqlite3_finalize(sqlstmt);
 
+       /* consider merge query as invalid if not all requested interfaces are found or are not unique */
+       if (strchr(iface, '+') != NULL) {
+               if (result != getqueryinterfacecount(iface)) {
+                       result = 0;
+               }
+       }
+
        return result;
 }
 
@@ -1241,25 +1247,38 @@ void dbdatalistfree(dbdatalist **dbdata)
 
 }
 
-char *getifaceinquery(const char *input)
+unsigned int getqueryinterfacecount(const char *input)
 {
-       unsigned int i, j, ifacecount = 1;
-       char *result;
+       unsigned int i, ifacecount = 1;
 
        if (input[0] == '+' || input[strlen(input)-1] == '+' || !strlen(input)) {
-               return NULL;
+               return 0;
        }
 
        for (i = 0; i < (unsigned int)strlen(input); i++) {
                if (input[i] == '+') {
                        if (i > 0 && input[i-1] == '+') {
-                               return NULL;
+                               return 0;
                        } else {
                                ifacecount++;
                        }
                }
        }
 
+       return ifacecount;
+}
+
+char *getifaceinquery(const char *input)
+{
+       unsigned int i, j, ifacecount = 1;
+       char *result;
+
+       ifacecount = getqueryinterfacecount(input);
+
+       if (ifacecount == 0) {
+               return NULL;
+       }
+
        /* each interface requires two quotes and comma or \0 so 3 extra chars */
        j = (unsigned int)strlen(input) + ifacecount * 3;
        result = malloc(sizeof(char) * j);
index 0b8950f6717ae07e05344da6aa16e71c00193b09..67455aaae5d08b5bbfa1bd9c098595f100960769 100644 (file)
@@ -78,6 +78,7 @@ void updatelistinfo(dbdatalistinfo *listinfo, const uint64_t rx, const uint64_t
 int dbdatalistadd(dbdatalist **dbdata, const uint64_t rx, const uint64_t tx, const time_t timestamp, const int64_t rowid);
 void dbdatalistfree(dbdatalist **dbdata);
 
+unsigned int getqueryinterfacecount(const char *input);
 char *getifaceinquery(const char *input);
 
 /* global db */
index 1c9eb91cf1c2b0c5646c9af4461f1575b3a268cc..78e80ab065ba34fa35bc33825ca18594be02799a 100644 (file)
@@ -766,7 +766,7 @@ void showoneinterface(PARAMS *p, const char *interface)
                if (strchr(p->interface, '+') == NULL)  {
                        printf("Error: Interface \"%s\" not found in database.\n", p->interface);
                } else {
-                       printf("Error: Not all requested interfaces found in database.\n");
+                       printf("Error: Not all requested interfaces found in database or given interfaces aren't unique.\n");
                }
                exit(EXIT_FAILURE);
        }
index d236586a0e2c61aa93af4d94d9260758d794671f..6c2a02413b969af21062fe26e09865d2bd074281 100644 (file)
@@ -415,7 +415,11 @@ void handledatabase(IPARAMS *p, IMAGECONTENT *ic)
                exit(EXIT_FAILURE);
        }
        if (!db_getinterfacecountbyname(p->interface)) {
-               printf("Error: Interface \"%s\" not found in database.\n", p->interface);
+               if (strchr(p->interface, '+') == NULL)  {
+                       printf("Error: Interface \"%s\" not found in database.\n", p->interface);
+               } else {
+                       printf("Error: Not all requested interfaces found in database or given interfaces aren't unique.\n");
+               }
                exit(EXIT_FAILURE);
        }
        if (!db_getinterfaceinfo(p->interface, &ic->interface)) {
index e5e27ea85669c3731ed9063aa85422bd3ae16dea..e85318138368fbc616e6c24cd23c27a8c3b0fc74 100644 (file)
@@ -563,7 +563,7 @@ START_TEST(db_getinterfacecountbyname_counts_interfaces)
        ck_assert_int_eq(ret, 3);
 
        ret = (int)db_getinterfacecountbyname("eth0+eth1+eth2");
-       ck_assert_int_eq(ret, 2);
+       ck_assert_int_eq(ret, 0);
 
        ret = db_close();
        ck_assert_int_eq(ret, 1);
@@ -2183,6 +2183,27 @@ START_TEST(db_getinterfaceinfo_can_handle_invalid_input)
 }
 END_TEST
 
+START_TEST(getqueryinterfacecount_can_count)
+{
+       ck_assert_int_eq(getqueryinterfacecount("eth0"), 1);
+       ck_assert_int_eq(getqueryinterfacecount("eth1"), 1);
+       ck_assert_int_eq(getqueryinterfacecount("eth1+eth2"), 2);
+       ck_assert_int_eq(getqueryinterfacecount("eth1+eth2+eth3"), 3);
+       ck_assert_int_eq(getqueryinterfacecount("eth1+eth2+eth3+eth1"), 4);
+       ck_assert_int_eq(getqueryinterfacecount("eth0+eth0"), 2);
+       ck_assert_int_eq(getqueryinterfacecount("eth0++eth1"), 0);
+       ck_assert_int_eq(getqueryinterfacecount(""), 0);
+       ck_assert_int_eq(getqueryinterfacecount("1"), 1);
+       ck_assert_int_eq(getqueryinterfacecount("+"), 0);
+       ck_assert_int_eq(getqueryinterfacecount("++"), 0);
+       ck_assert_int_eq(getqueryinterfacecount("+ +"), 0);
+       ck_assert_int_eq(getqueryinterfacecount("+ethsomething"), 0);
+       ck_assert_int_eq(getqueryinterfacecount("ethnothing+"), 0);
+       ck_assert_int_eq(getqueryinterfacecount("eth+nothing"), 2);
+       ck_assert_int_eq(getqueryinterfacecount("ethlongcanbelong+ethnotsoshort+ethdoesnotcare"), 3);
+}
+END_TEST
+
 void add_dbsql_tests(Suite *s)
 {
        TCase *tc_dbsql = tcase_create("DB SQL");
@@ -2259,5 +2280,6 @@ void add_dbsql_tests(Suite *s)
        tcase_add_test(tc_dbsql, db_getinterfaceidin_can_handle_error_situations);
        tcase_add_test(tc_dbsql, db_getinterfaceinfo_can_handle_interface_merges);
        tcase_add_test(tc_dbsql, db_getinterfaceinfo_can_handle_invalid_input);
+       tcase_add_test(tc_dbsql, getqueryinterfacecount_can_count);
        suite_add_tcase(s, tc_dbsql);
 }