- 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
.RB [ \-\-rateunit
.RI [ mode ]]
.RB [ \-\-remove ]
+.RB [ \-\-rename
+.IR name ]
.RB [ \-ru
.RI [ mode ]]
.RB [ \-\-setalias
.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
.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]
.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"
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("");
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);
} 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])) {
/* parameter handlers */
handleremoveinterface(&p);
+ handlerenameinterface(&p);
handleaddinterface(&p);
handlesetalias(&p);
handleshowdatabases(&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';
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");
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);
}
}
+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) {
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);
}
}
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);
}
}
iflist *ifl = NULL;
iflist *dbifl = NULL, *dbifl_iterator = NULL;
- if (!p->defaultiface) {
+ if (!p->defaultiface || !p->query) {
return;
}
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;
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);
}
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;
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);