]> granicus.if.org Git - vnstat/commitdiff
implement --rename for renaming interfaces already existing the database
authorTeemu Toivola <git@humdi.net>
Wed, 14 Aug 2019 19:02:58 +0000 (22:02 +0300)
committerTeemu Toivola <git@humdi.net>
Wed, 14 Aug 2019 19:02:58 +0000 (22:02 +0300)
CHANGES
man/vnstat.1
src/dbsql.c
src/dbsql.h
src/vnstat.c
src/vnstat.h
tests/dbsql_tests.c

diff --git a/CHANGES b/CHANGES
index 1ef23913eec9ccbafc7589eebd7aa608cac9fb02..d0996f8de52d58814b95c3e4ede163effecf66ea 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -8,6 +8,8 @@
    - Daemon didn't fork() even when requested to with --daemon when started
      by PID 1 (issue seen at least in Docker containers)
    - Move vnstatd man page from section 1 to section 8
+ - New
+   - Add --rename for renaming interfaces already existing the database
 
 
 2.3 / 10-Jul-2019
index 151b2910af0a5aa1c124f1502a52446229f9cc0d..647b92cf5e6443ab64b6b4bfa8a71e2fae240b4c 100644 (file)
@@ -46,6 +46,8 @@ vnstat \- a console-based network traffic monitor
 .RB [ \-\-rateunit
 .RI [ mode ]]
 .RB [ \-\-remove ]
+.RB [ \-\-rename
+.IR name ]
 .RB [ \-ru
 .RI [ mode ]]
 .RB [ \-\-setalias
@@ -97,7 +99,8 @@ Create database entry for interface specified with
 .B \-i
 or
 .B \-\-iface
-option.
+option. The daemon can be running during this operation but will not
+automatically detect the addition without a restart.
 
 .TP
 .BI "-b, --begin " date
@@ -283,7 +286,19 @@ Delete the database entry for the interface specified with
 .B \-i
 or
 .B \-\-iface
-and stop monitoring it.
+and stop monitoring it. The daemon can be running during this operation
+and will automatically detect the change.
+
+.TP
+.BI "--rename " name
+Rename the interface specified with
+.B \-i
+or
+.B \-\-iface
+in the database with new name
+.BR name .
+The new name cannot already exist in the database. This operation doesn't
+cause any data loss. The daemon should not be running during this operation.
 
 .TP
 .BI "-ru, --rateunit " [mode]
@@ -299,7 +314,8 @@ select between bytes (0) and bits (1) regardless of the configuration file setti
 .BI "--setalias " alias
 Set the selected interface
 .I alias
-as an alias that will be displayed in queries.
+as an alias that will be displayed in queries. The daemon can be running during
+this operation.
 
 .TP
 .B "-s, --short"
index f0681d068cb67680187cb24674d4edc1542c4950..9fb81355ad09600dc30ae73c78eb7bcef9a0fff7 100644 (file)
@@ -392,6 +392,24 @@ int db_removeinterface(const char *iface)
        return db_exec(sql);
 }
 
+int db_renameinterface(const char *iface, const char *newifname)
+{
+       char sql[128];
+       sqlite3_int64 ifaceid = 0;
+
+       if (!strlen(newifname)) {
+               return 0;
+       }
+
+       ifaceid = db_getinterfaceid(iface, 0);
+       if (ifaceid == 0) {
+               return 0;
+       }
+
+       sqlite3_snprintf(128, sql, "update interface set name='%q' where id=%" PRId64 "", newifname, (int64_t)ifaceid);
+       return db_exec(sql);
+}
+
 uint64_t db_getinterfacecount(void)
 {
        return db_getinterfacecountbyname("");
index 8b2da670b5bbeff506c4a7a44686f36e3401eff3..e534650127e8ff51af35b11a8d3665ba94b89dbf 100644 (file)
@@ -38,6 +38,7 @@ int db_exec(const char *sql);
 int db_create(void);
 int db_addinterface(const char *iface);
 int db_removeinterface(const char *iface);
+int db_renameinterface(const char *iface, const char *newifname);
 uint64_t db_getinterfacecount(void);
 uint64_t db_getinterfacecountbyname(const char *iface);
 sqlite3_int64 db_getinterfaceid(const char *iface, const int createifnotfound);
index f3181c8a8d46be33e3903c97d18477b0f04b71fc..ed7f693d5a4cec12c7e68f78342bc0bb7184129c 100644 (file)
@@ -361,6 +361,19 @@ int main(int argc, char *argv[])
                } else if (strcmp(argv[currentarg], "--remove") == 0) {
                        p.removeiface = 1;
                        p.query = 0;
+               } else if (strcmp(argv[currentarg], "--rename") == 0) {
+                       if (currentarg + 1 < argc) {
+                               strncpy_nt(p.newifname, argv[currentarg + 1], 32);
+                               if (debug)
+                                       printf("Given new interface name: \"%s\"\n", p.newifname);
+                               p.renameiface = 1;
+                               p.query = 0;
+                               currentarg++;
+                               continue;
+                       } else {
+                               printf("Error: New interface name for %s missing.\n", argv[currentarg]);
+                               return 1;
+                       }
                } else if ((strcmp(argv[currentarg], "-b") == 0) || (strcmp(argv[currentarg], "--begin") == 0)) {
                        if (currentarg + 1 < argc) {
                                if (!validatedatetime(argv[currentarg + 1])) {
@@ -442,6 +455,7 @@ int main(int argc, char *argv[])
 
        /* parameter handlers */
        handleremoveinterface(&p);
+       handlerenameinterface(&p);
        handleaddinterface(&p);
        handlesetalias(&p);
        handleshowdatabases(&p);
@@ -491,8 +505,14 @@ void initparams(PARAMS *p)
        p->livetraffic = 0;
        p->defaultiface = 1;
        p->removeiface = 0;
+       p->renameiface = 0;
        p->livemode = 0;
        p->ifacelist = NULL;
+       p->interface[0] = '\0';
+       p->alias[0] = '\0';
+       p->newifname[0] = '\0';
+       p->filename[0] = '\0';
+       p->definterface[0] = '\0';
        p->cfgfile[0] = '\0';
        p->jsonmode = 'a';
        p->xmlmode = 'a';
@@ -555,6 +575,7 @@ void showlonghelp(PARAMS *p)
 
        printf("      --add                        add interface to database\n");
        printf("      --remove                     remove interface from database\n");
+       printf("      --rename <name>              rename interface in database\n");
        printf("      --setalias <alias>           set alias for interface\n\n");
 
        printf("Misc:\n");
@@ -587,6 +608,11 @@ void handleremoveinterface(PARAMS *p)
                return;
        }
 
+       if (p->defaultiface) {
+               printf("Error: Use -i parameter to specify an interface.\n");
+               exit(EXIT_FAILURE);
+       }
+
        if (!db_getinterfacecountbyname(p->interface)) {
                printf("Error: Interface \"%s\" not found in database.\n", p->interface);
                exit(EXIT_FAILURE);
@@ -614,6 +640,52 @@ void handleremoveinterface(PARAMS *p)
        }
 }
 
+void handlerenameinterface(PARAMS *p)
+{
+       if (!p->renameiface) {
+               return;
+       }
+
+       if (p->defaultiface) {
+               printf("Error: Use -i parameter to specify an interface.\n");
+               exit(EXIT_FAILURE);
+       }
+
+       if (!strlen(p->newifname)) {
+               printf("Error: New interface name must be at least one character long.\n");
+               exit(EXIT_FAILURE);
+       }
+
+       if (!db_getinterfacecountbyname(p->interface)) {
+               printf("Error: Interface \"%s\" not found in database.\n", p->interface);
+               exit(EXIT_FAILURE);
+       }
+
+       if (db_getinterfacecountbyname(p->newifname)) {
+               printf("Error: Interface \"%s\" already exists in database.\n", p->interface);
+               exit(EXIT_FAILURE);
+       }
+
+       if (!p->force) {
+               printf("Warning:\nThe current option would rename\ninterface \"%s\" -> \"%s\" in the database.\n", p->interface, p->newifname);
+               printf("Use --force in order to really do that.\n");
+               exit(EXIT_FAILURE);
+       }
+
+       if (!db_close() || !db_open_rw(0)) {
+               printf("Error: Handling database \"%s/%s\" failing: %s\n", cfg.dbdir, DATABASEFILE, strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+
+       if (db_renameinterface(p->interface, p->newifname)) {
+               printf("Interface \"%s\" has been renamed \"%s\".\n", p->interface, p->newifname);
+               exit(EXIT_SUCCESS);
+       } else {
+               printf("Error: Renaming interface \"%s\" -> \"%s\" failed.\n", p->interface, p->newifname);
+               exit(EXIT_FAILURE);
+       }
+}
+
 void handleaddinterface(PARAMS *p)
 {
        if (!p->addiface) {
@@ -657,7 +729,7 @@ void handleaddinterface(PARAMS *p)
                printf("\nRestart the vnStat daemon if it is currently running in order to start monitoring \"%s\".\n", p->interface);
                exit(EXIT_SUCCESS);
        } else {
-               printf("Error: Adding interface \"%s\" to database failed: %s\n", p->interface, strerror(errno));
+               printf("Error: Adding interface \"%s\" to database failed.\n", p->interface);
                exit(EXIT_FAILURE);
        }
 }
@@ -687,7 +759,7 @@ void handlesetalias(PARAMS *p)
                printf("Alias of interface \"%s\" set to \"%s\".\n", p->interface, p->alias);
                exit(EXIT_SUCCESS);
        } else {
-               printf("Error: Changing interface \"%s\" alias failed: %s\n", p->interface, strerror(errno));
+               printf("Error: Setting interface \"%s\" alias failed.\n", p->interface);
                exit(EXIT_FAILURE);
        }
 }
@@ -832,7 +904,7 @@ void handleifselection(PARAMS *p)
        iflist *ifl = NULL;
        iflist *dbifl = NULL, *dbifl_iterator = NULL;
 
-       if (!p->defaultiface) {
+       if (!p->defaultiface || !p->query) {
                return;
        }
 
index 3e345a8b9ec61587e1aa2c2f5c6565dd77f625c9..92645d7388a361434fe21cd66e23f9c0ce037ae2 100644 (file)
@@ -4,9 +4,9 @@
 typedef struct {
        int query, setalias;
        int addiface, force, traffic;
-       int livetraffic, defaultiface, removeiface, livemode;
+       int livetraffic, defaultiface, removeiface, renameiface, livemode;
        uint64_t dbifcount;
-       char interface[32], alias[32], filename[512];
+       char interface[32], alias[32], newifname[32], filename[512];
        char definterface[32], cfgfile[512], *ifacelist, jsonmode, xmlmode;
        char databegin[18], dataend[18];
 } PARAMS;
@@ -15,6 +15,7 @@ void initparams(PARAMS *p);
 void showhelp(PARAMS *p);
 void showlonghelp(PARAMS *p);
 void handleremoveinterface(PARAMS *p);
+void handlerenameinterface(PARAMS *p);
 void handleaddinterface(PARAMS *p);
 void handlesetalias(PARAMS *p);
 void handleshowdatabases(PARAMS *p);
index 94f68b803aafbe7679e2b274cfd5f00104d900bc..165805bd2af98e68c6354936c1c2c96d6443fbcc 100644 (file)
@@ -488,6 +488,71 @@ START_TEST(db_removeinterface_can_remove_interfaces)
 }
 END_TEST
 
+START_TEST(db_renameinterface_knows_if_interface_exists)
+{
+       int ret;
+
+       defaultcfg();
+
+       ret = db_open_rw(1);
+       ck_assert_int_eq(ret, 1);
+
+       ret = db_renameinterface("eth0", "eth1");
+       ck_assert_int_eq(ret, 0);
+       ret = db_renameinterface("nothing", "something");
+       ck_assert_int_eq(ret, 0);
+       ret = db_renameinterface("", "");
+       ck_assert_int_eq(ret, 0);
+
+       ret = db_close();
+       ck_assert_int_eq(ret, 1);
+}
+END_TEST
+
+START_TEST(db_renameinterface_can_rename_interfaces)
+{
+       int ret;
+
+       defaultcfg();
+
+       ret = db_open_rw(1);
+       ck_assert_int_eq(ret, 1);
+
+       ret = db_addinterface("eth0");
+       ck_assert_int_eq(ret, 1);
+       ret = db_addinterface("eth1");
+       ck_assert_int_eq(ret, 1);
+       ret = db_addinterface("eth2");
+       ck_assert_int_eq(ret, 1);
+
+       ck_assert_int_eq(db_getinterfacecount(), 3);
+       ck_assert_int_eq(db_getinterfacecountbyname("eth0"), 1);
+       ck_assert_int_eq(db_getinterfacecountbyname("eth1"), 1);
+       ck_assert_int_eq(db_getinterfacecountbyname("eth2"), 1);
+       ck_assert_int_eq(db_getinterfacecountbyname("eth3"), 0);
+
+       ret = db_renameinterface("eth0", "eth1");
+       ck_assert_int_eq(ret, 0);
+       ret = db_renameinterface("eth2", "eth3");
+       ck_assert_int_eq(ret, 1);
+       ret = db_renameinterface("eth1", "eth2");
+       ck_assert_int_eq(ret, 1);
+       ret = db_renameinterface("eth0", "");
+       ck_assert_int_eq(ret, 0);
+       ret = db_renameinterface("eth0", "eth1");
+       ck_assert_int_eq(ret, 1);
+
+       ck_assert_int_eq(db_getinterfacecount(), 3);
+       ck_assert_int_eq(db_getinterfacecountbyname("eth0"), 0);
+       ck_assert_int_eq(db_getinterfacecountbyname("eth1"), 1);
+       ck_assert_int_eq(db_getinterfacecountbyname("eth2"), 1);
+       ck_assert_int_eq(db_getinterfacecountbyname("eth3"), 1);
+
+       ret = db_close();
+       ck_assert_int_eq(ret, 1);
+}
+END_TEST
+
 START_TEST(db_getinterfacecount_counts_interfaces)
 {
        int ret;
@@ -2216,6 +2281,8 @@ void add_dbsql_tests(Suite *s)
        tcase_add_test(tc_dbsql, db_addinterface_can_not_add_same_interface_twice);
        tcase_add_test(tc_dbsql, db_removeinterface_knows_if_interface_exists);
        tcase_add_test(tc_dbsql, db_removeinterface_can_remove_interfaces);
+       tcase_add_test(tc_dbsql, db_renameinterface_knows_if_interface_exists);
+       tcase_add_test(tc_dbsql, db_renameinterface_can_rename_interfaces);
        tcase_add_test(tc_dbsql, db_getcounters_with_no_interface);
        tcase_add_test(tc_dbsql, db_setcounters_with_no_interface);
        tcase_add_test(tc_dbsql, db_interface_info_manipulation);