cfg-mod: Add new --del-match option.
authorBen Pfaff <blp@nicira.com>
Fri, 3 Apr 2009 00:12:14 +0000 (17:12 -0700)
committerBen Pfaff <blp@nicira.com>
Mon, 6 Apr 2009 23:35:31 +0000 (16:35 -0700)
lib/cfg.c
lib/cfg.h
utilities/cfg-mod.8.in
utilities/cfg-mod.c

index 4495f670df0163db207ec91db65d3ba4f3d036aa..203880d21156a094cb439868ad1e7e195a69a110 100644 (file)
--- a/lib/cfg.c
+++ b/lib/cfg.c
@@ -30,6 +30,7 @@
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <fnmatch.h>
 #include <inttypes.h>
 #include <netinet/in.h>
 #include <stdlib.h>
@@ -539,6 +540,26 @@ cfg_del_section(const char *section_, ...)
     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'. */
index 8ecace9431d1aefd60eb988340f56d3913ca6b22..8b21922e6ac4e42307c1530b6fb6a088e9be2e58 100644 (file)
--- a/lib/cfg.h
+++ b/lib/cfg.h
@@ -70,6 +70,7 @@ void cfg_register(const char *key_spec, enum cfg_flags);
 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);
 
index 224fcc47ca5c34d48de9e18c5f2bd1c8921fd5d6..1cb8d6d96a7eb51cf76d186e62cdd9795d2bf106 100644 (file)
@@ -51,6 +51,12 @@ that matches \fIentry\fR.
 .
 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
 .
index f7d0b634c70a992dc1e7aba76cf0ccedd4477ec2..5cb1767a7331a02c72595003706cdd1cfa4b4bd2 100644 (file)
@@ -49,6 +49,7 @@ usage(char *prog_name, int exit_code)
            "  -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);
@@ -87,11 +88,15 @@ print_vals(char *key)
     
 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},
@@ -112,7 +117,8 @@ int main(int argc, char *argv[])
             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)");
         }
 
@@ -137,6 +143,11 @@ int main(int argc, char *argv[])
             modified = true;
             break;
 
+        case OPT_DEL_MATCH:
+            cfg_del_match("%s", optarg);
+            modified = true;
+            break;
+
         case 'q':
             print_vals(optarg);
             break;