#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#include <fnmatch.h>
#include <inttypes.h>
#include <netinet/in.h>
#include <stdlib.h>
dirty = true;
}
+void
+cfg_del_match(const char *pattern_, ...)
+{
+ char *pattern;
+ char **p;
+
+ FORMAT_KEY(pattern_, pattern);
+
+ for (p = cfg.names; *p; p++) {
+ if (!fnmatch(pattern, *p, 0)) {
+ free(*p);
+ *p = NULL;
+ }
+ }
+ svec_compact(&cfg);
+ svec_terminate(&cfg);
+
+ free(pattern);
+ dirty = true;
+}
/* Fills 'svec' with all of the key-value pairs that have sections that
* begin with 'section'. The caller must first initialize 'svec'. */
void cfg_add_entry(const char *key, ...) PRINTF_FORMAT(1, 2);
void cfg_del_entry(const char *key, ...) PRINTF_FORMAT(1, 2);
void cfg_del_section(const char *key, ...) PRINTF_FORMAT(1, 2);
+void cfg_del_match(const char *pattern, ...) PRINTF_FORMAT(1, 2);
void cfg_get_section(struct svec *svec, const char *key, ...)
PRINTF_FORMAT(2, 3);
.
Delete section \fIkey\fR from \fIfile\fR.
+.IP "\fB--del-match=\fIpattern\fR"
+Deletes every entry that matches the given shell glob \fIpattern\fR.
+For example, \fB--del-match=bridge.*.port=*\fR deletes all the ports
+from every bridge, and \fB--del-match=bonding.bond0.*\fR is equivalent
+to \fB--del-section=bonding.bond0\fR.
+
.TP
\fB-q\fR \fIkey\fR, \fB--query=\fIkey\fR
.
" -a, --add=ENTRY add ENTRY\n"
" -d, --del-entry=ENTRY delete ENTRY\n"
" -D, --del-section=KEY delete section matching KEY\n"
+ " --del-match=PATTERN delete entries matching shell PATTERN\n"
" -q, --query=KEY return all entries matching KEY \n",
prog_name);
exit(exit_code);
int main(int argc, char *argv[])
{
+ enum {
+ OPT_DEL_MATCH = UCHAR_MAX + 1,
+ };
static const struct option long_options[] = {
{"config-file", required_argument, 0, 'F'},
{"add", required_argument, 0, 'a'},
{"del-entry", required_argument, 0, 'd'},
{"del-section", required_argument, 0, 'D'},
+ {"del-match", required_argument, 0, OPT_DEL_MATCH},
{"query", required_argument, 0, 'q'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0},
break;
}
- if (!strchr("Fh?", option) && config_set == false) {
+ if ((option > UCHAR_MAX || !strchr("Fh?", option))
+ && config_set == false) {
ofp_fatal(0, "no config file specified (use --help for help)");
}
modified = true;
break;
+ case OPT_DEL_MATCH:
+ cfg_del_match("%s", optarg);
+ modified = true;
+ break;
+
case 'q':
print_vals(optarg);
break;