chiark / gitweb /
add option to RUN key to ignore the return value of the program
[elogind.git] / udev_rules_parse.c
index bfbad367e9d41e4dfda8f806e5b737c08099bb3c..c4fa142b04a21c078db43607acf7c178d68472c9 100644 (file)
@@ -232,6 +232,7 @@ static int add_rule_key_pair(struct udev_rule *rule, struct key_pairs *pairs,
 
 static int add_to_rules(struct udev_rules *rules, char *line, const char *filename, unsigned int lineno)
 {
+       char buf[sizeof(struct udev_rule) + LINE_SIZE];
        struct udev_rule *rule;
        size_t rule_size;
        int valid;
@@ -241,15 +242,12 @@ static int add_to_rules(struct udev_rules *rules, char *line, const char *filena
        int physdev = 0;
        int retval;
 
-       /* get all the keys */
-       rule = calloc(1, sizeof (struct udev_rule) + LINE_SIZE);
-       if (!rule) {
-               err("malloc failed");
-               return -1;
-       }
+       memset(buf, 0x00, sizeof(buf));
+       rule = (struct udev_rule *) buf;
        linepos = line;
        valid = 0;
 
+       /* get all the keys */
        while (1) {
                char *key;
                char *value;
@@ -298,7 +296,16 @@ static int add_to_rules(struct udev_rules *rules, char *line, const char *filena
                                err("invalid SUBSYSTEM operation");
                                goto invalid;
                        }
-                       add_rule_key(rule, &rule->subsystem, operation, value);
+                       /* bus, class, subsystem events should all be the same */
+                       if (strcmp(value, "subsystem") == 0 ||
+                           strcmp(value, "bus") == 0 ||
+                           strcmp(value, "class") == 0) {
+                               if (strcmp(value, "bus") == 0 || strcmp(value, "class") == 0)
+                                       err("'%s' must be specified as 'subsystem' "
+                                           "please fix it in %s:%u", value, filename, lineno);
+                               add_rule_key(rule, &rule->subsystem, operation, "subsystem|class|bus");
+                       } else
+                               add_rule_key(rule, &rule->subsystem, operation, value);
                        valid = 1;
                        continue;
                }
@@ -376,7 +383,7 @@ static int add_to_rules(struct udev_rules *rules, char *line, const char *filena
                        if (strncmp(attr, "device/", 7) == 0)
                                err("the 'device' link is deprecated and will be removed from a future kernel, "
                                    "please fix it in %s:%u", filename, lineno);
-                       else if (strchr(attr, '/') != NULL)
+                       else if (strstr(attr, "../") != NULL)
                                err("do not reference parent sysfs directories directly, that may break with a future kernel, "
                                    "please fix it in %s:%u", filename, lineno);
                        if (add_rule_key_pair(rule, &rule->attrs, operation, attr, value) != 0)
@@ -461,7 +468,19 @@ static int add_to_rules(struct udev_rules *rules, char *line, const char *filena
                        continue;
                }
 
-               if (strcasecmp(key, "RUN") == 0) {
+               if (strncasecmp(key, "TEST", sizeof("TEST")-1) == 0) {
+                       attr = get_key_attribute(key + sizeof("TEST")-1);
+                       if (attr != NULL)
+                               rule->test_mode_mask = strtol(attr, NULL, 8);
+                       add_rule_key(rule, &rule->test, operation, value);
+                       valid = 1;
+                       continue;
+               }
+
+               if (strncasecmp(key, "RUN", sizeof("RUN")-1) == 0) {
+                       attr = get_key_attribute(key + sizeof("RUN")-1);
+                       if (attr && strstr(attr, "ignore_error"))
+                               rule->run_ignore_error = 1;
                        add_rule_key(rule, &rule->run, operation, value);
                        valid = 1;
                        continue;
@@ -574,6 +593,14 @@ static int add_to_rules(struct udev_rules *rules, char *line, const char *filena
                                rule->link_priority = atoi(&pos[strlen("link_priority=")]);
                                info("link priority=%i", rule->link_priority);
                        }
+                       pos = strstr(value, "string_escape=");
+                       if (pos != NULL) {
+                               pos = &pos[strlen("string_escape=")];
+                               if (strncmp(pos, "none", strlen("none")) == 0)
+                                       rule->string_escape = ESCAPE_NONE;
+                               else if (strncmp(pos, "replace", strlen("replace")) == 0)
+                                       rule->string_escape = ESCAPE_REPLACE;
+                       }
                        if (strstr(value, "all_partitions") != NULL) {
                                dbg("creation of partition nodes requested");
                                rule->partitions = DEFAULT_PARTITIONS_COUNT;
@@ -609,11 +636,9 @@ static int add_to_rules(struct udev_rules *rules, char *line, const char *filena
        memcpy(rules->buf + rules->bufsize, rule, rule_size);
        rules->bufsize += rule_size;
 exit:
-       free(rule);
        return 0;
 
 invalid:
-       free(rule);
        err("invalid rule '%s:%u'", filename, lineno);
        return -1;
 }