chiark / gitweb /
update slackware rules
[elogind.git] / udev_rules_parse.c
index 4fcd6db08ee362bec4233683df6143956baa1364..271de6f87968c4d8aa897e592248a9d6cf830944 100644 (file)
@@ -235,7 +235,7 @@ static int add_rule_key_pair(struct udev_rule *rule, struct key_pairs *pairs,
        return 0;
 }
 
-static int add_to_rules(struct udev_rules *rules, char *line)
+static int add_to_rules(struct udev_rules *rules, char *line, const char *filename, unsigned int lineno)
 {
        struct udev_rule *rule;
        size_t rule_size;
@@ -276,42 +276,77 @@ static int add_to_rules(struct udev_rules *rules, char *line)
                }
 
                if (strcasecmp(key, "KERNEL") == 0) {
+                       if (operation != KEY_OP_MATCH &&
+                           operation != KEY_OP_NOMATCH) {
+                               err("invalid KERNEL operation");
+                               goto invalid;
+                       }
                        add_rule_key(rule, &rule->kernel_name, operation, value);
                        valid = 1;
                        continue;
                }
 
                if (strcasecmp(key, "SUBSYSTEM") == 0) {
+                       if (operation != KEY_OP_MATCH &&
+                           operation != KEY_OP_NOMATCH) {
+                               err("invalid SUBSYSTEM operation");
+                               goto invalid;
+                       }
                        add_rule_key(rule, &rule->subsystem, operation, value);
                        valid = 1;
                        continue;
                }
 
                if (strcasecmp(key, "ACTION") == 0) {
+                       if (operation != KEY_OP_MATCH &&
+                           operation != KEY_OP_NOMATCH) {
+                               err("invalid ACTION operation");
+                               goto invalid;
+                       }
                        add_rule_key(rule, &rule->action, operation, value);
                        valid = 1;
                        continue;
                }
 
                if (strcasecmp(key, "DEVPATH") == 0) {
+                       if (operation != KEY_OP_MATCH &&
+                           operation != KEY_OP_NOMATCH) {
+                               err("invalid DEVPATH operation");
+                               goto invalid;
+                       }
                        add_rule_key(rule, &rule->devpath, operation, value);
                        valid = 1;
                        continue;
                }
 
                if (strcasecmp(key, "BUS") == 0) {
+                       if (operation != KEY_OP_MATCH &&
+                           operation != KEY_OP_NOMATCH) {
+                               err("invalid BUS operation");
+                               goto invalid;
+                       }
                        add_rule_key(rule, &rule->bus, operation, value);
                        valid = 1;
                        continue;
                }
 
                if (strcasecmp(key, "ID") == 0) {
+                       if (operation != KEY_OP_MATCH &&
+                           operation != KEY_OP_NOMATCH) {
+                               err("invalid ID operation");
+                               goto invalid;
+                       }
                        add_rule_key(rule, &rule->id, operation, value);
                        valid = 1;
                        continue;
                }
 
                if (strncasecmp(key, "SYSFS", sizeof("SYSFS")-1) == 0) {
+                       if (operation != KEY_OP_MATCH &&
+                           operation != KEY_OP_NOMATCH) {
+                               err("invalid SYSFS operation");
+                               goto invalid;
+                       }
                        attr = get_key_attribute(key + sizeof("SYSFS")-1);
                        if (attr == NULL) {
                                err("error parsing SYSFS attribute in '%s'", line);
@@ -339,12 +374,6 @@ static int add_to_rules(struct udev_rules *rules, char *line)
                        continue;
                }
 
-               if (strcasecmp(key, "MODALIAS") == 0) {
-                       add_rule_key(rule, &rule->modalias, operation, value);
-                       valid = 1;
-                       continue;
-               }
-
                if (strncasecmp(key, "IMPORT", sizeof("IMPORT")-1) == 0) {
                        attr = get_key_attribute(key + sizeof("IMPORT")-1);
                        if (attr && strstr(attr, "program")) {
@@ -366,6 +395,16 @@ static int add_to_rules(struct udev_rules *rules, char *line)
                                pos = strchr(file, ' ');
                                if (pos)
                                        pos[0] = '\0';
+
+                               /* allow programs in /lib/udev called without the path */
+                               if (strchr(file, '/') == NULL) {
+                                       strlcpy(file, "/lib/udev/", sizeof(file));
+                                       strlcat(file, value, sizeof(file));
+                                       pos = strchr(file, ' ');
+                                       if (pos)
+                                               pos[0] = '\0';
+                               }
+
                                dbg("IMPORT auto mode for '%s'", file);
                                if (!lstat(file, &stats) && (stats.st_mode & S_IXUSR)) {
                                        dbg("IMPORT is executable, will be executed (autotype)");
@@ -381,12 +420,22 @@ static int add_to_rules(struct udev_rules *rules, char *line)
                }
 
                if (strcasecmp(key, "DRIVER") == 0) {
+                       if (operation != KEY_OP_MATCH &&
+                           operation != KEY_OP_NOMATCH) {
+                               err("invalid DRIVER operation");
+                               goto invalid;
+                       }
                        add_rule_key(rule, &rule->driver, operation, value);
                        valid = 1;
                        continue;
                }
 
                if (strcasecmp(key, "RESULT") == 0) {
+                       if (operation != KEY_OP_MATCH &&
+                           operation != KEY_OP_NOMATCH) {
+                               err("invalid RESULT operation");
+                               goto invalid;
+                       }
                        add_rule_key(rule, &rule->result, operation, value);
                        valid = 1;
                        continue;
@@ -411,7 +460,7 @@ static int add_to_rules(struct udev_rules *rules, char *line)
                                }
                        }
                        if (value[0] == '\0')
-                               dbg("name empty, not creation supressed");
+                               dbg("name empty, node creation supressed");
                        add_rule_key(rule, &rule->name, operation, value);
                        continue;
                }
@@ -494,14 +543,12 @@ static int add_to_rules(struct udev_rules *rules, char *line)
                        continue;
                }
 
-               err("unknown key '%s', in '%s'", key, line);
+               err("unknown key '%s'", key);
        }
 
        /* skip line if not any valid key was found */
-       if (!valid) {
-               err("invalid rule '%s'", line);
-               goto exit;
-       }
+       if (!valid)
+               goto invalid;
 
        /* grow buffer and add rule */
        rule_size = sizeof(struct udev_rule) + rule->bufsize;
@@ -521,13 +568,18 @@ static int add_to_rules(struct udev_rules *rules, char *line)
 exit:
        free(rule);
        return 0;
+
+invalid:
+       free(rule);
+       err("invalid rule '%s:%u'", filename, lineno);
+       return -1;
 }
 
 static int parse_file(struct udev_rules *rules, const char *filename)
 {
        char line[LINE_SIZE];
        char *bufline;
-       int lineno;
+       unsigned int lineno;
        char *buf;
        size_t bufsize;
        size_t cur;
@@ -552,7 +604,7 @@ static int parse_file(struct udev_rules *rules, const char *filename)
                lineno++;
 
                if (count >= sizeof(line)) {
-                       info("line too long, rule skipped %s, line %d", filename, lineno);
+                       err("line too long, rule skipped '%s:%u'", filename, lineno);
                        continue;
                }
 
@@ -578,7 +630,7 @@ static int parse_file(struct udev_rules *rules, const char *filename)
                line[j] = '\0';
 
                dbg("read '%s'", line);
-               add_to_rules(rules, line);
+               add_to_rules(rules, line, filename, lineno);
        }
 
        file_unmap(buf, bufsize);