chiark / gitweb /
add udev_rules_run() to handle RUN list
[elogind.git] / udev_rules_parse.c
index bfbad367e9d41e4dfda8f806e5b737c08099bb3c..638ea159fbdf71e15f9a65b9cd6efb84a894a39b 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)
@@ -418,13 +425,13 @@ static int add_to_rules(struct udev_rules *rules, char *line, const char *filena
 
                if (strncasecmp(key, "IMPORT", sizeof("IMPORT")-1) == 0) {
                        attr = get_key_attribute(key + sizeof("IMPORT")-1);
-                       if (attr && strstr(attr, "program")) {
+                       if (attr != NULL && strstr(attr, "program")) {
                                dbg("IMPORT will be executed");
                                rule->import_type  = IMPORT_PROGRAM;
-                       } else if (attr && strstr(attr, "file")) {
+                       } else if (attr != NULL && strstr(attr, "file")) {
                                dbg("IMPORT will be included as file");
                                rule->import_type  = IMPORT_FILE;
-                       } else if (attr && strstr(attr, "parent")) {
+                       } else if (attr != NULL && strstr(attr, "parent")) {
                                dbg("IMPORT will include the parent values");
                                rule->import_type = IMPORT_PARENT;
                        } else {
@@ -461,7 +468,21 @@ 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 != NULL) {
+                               if (strstr(attr, "ignore_error"))
+                                       rule->run_ignore_error = 1;
+                       }
                        add_rule_key(rule, &rule->run, operation, value);
                        valid = 1;
                        continue;
@@ -574,6 +595,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 +638,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;
 }