/*
- * udev_rules_parse.c
- *
* Copyright (C) 2003,2004 Greg Kroah-Hartman <greg@kroah.com>
- * Copyright (C) 2003-2005 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2003-2006 Kay Sievers <kay.sievers@vrfy.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
size_t key_len = strnlen(key, PATH_SIZE);
if (pairs->count >= PAIRS_MAX) {
- err("skip, too many keys in a single rule");
+ err("skip, too many keys of the same type in a single rule");
return -1;
}
char *linepos;
char *attr;
size_t padding;
+ int physdev = 0;
int retval;
/* get all the keys */
if (retval)
break;
- if (strcasecmp(key, "LABEL") == 0) {
- add_rule_key(rule, &rule->label, operation, value);
+ 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, "GOTO") == 0) {
- add_rule_key(rule, &rule->goto_label, operation, value);
+ 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;
}
err("invalid KERNEL operation");
goto invalid;
}
- add_rule_key(rule, &rule->kernel_name, operation, value);
+ add_rule_key(rule, &rule->kernel, operation, value);
valid = 1;
continue;
}
continue;
}
- if (strcasecmp(key, "ACTION") == 0) {
+ if (strcasecmp(key, "DRIVER") == 0) {
if (operation != KEY_OP_MATCH &&
operation != KEY_OP_NOMATCH) {
- err("invalid ACTION operation");
+ err("invalid DRIVER operation");
goto invalid;
}
- add_rule_key(rule, &rule->action, operation, value);
+ err("DRIVER== will change in a future relase, "
+ "please use DRIVERS== in %s:%u", filename, lineno);
+ /* FIXME: this should be rule->driver to match only the event device */
+ add_rule_key(rule, &rule->drivers, operation, value);
valid = 1;
continue;
}
- if (strcasecmp(key, "DEVPATH") == 0) {
- if (operation != KEY_OP_MATCH &&
- operation != KEY_OP_NOMATCH) {
- err("invalid DEVPATH operation");
+ if (strncasecmp(key, "ATTR{", sizeof("ATTR{")-1) == 0) {
+ attr = get_key_attribute(key + sizeof("ATTR")-1);
+ if (attr == NULL) {
+ err("error parsing ATTR attribute");
goto invalid;
}
- add_rule_key(rule, &rule->devpath, operation, value);
+ if (add_rule_key_pair(rule, &rule->attr, operation, attr, value) != 0)
+ goto invalid;
valid = 1;
continue;
}
- if (strcasecmp(key, "BUS") == 0) {
+ if (strcasecmp(key, "KERNELS") == 0 ||
+ strcasecmp(key, "ID") == 0) {
if (operation != KEY_OP_MATCH &&
operation != KEY_OP_NOMATCH) {
- err("invalid BUS operation");
+ err("invalid KERNELS operation");
goto invalid;
}
- add_rule_key(rule, &rule->bus, operation, value);
+ add_rule_key(rule, &rule->kernels, operation, value);
valid = 1;
continue;
}
- if (strcasecmp(key, "ID") == 0) {
+ if (strcasecmp(key, "SUBSYSTEMS") == 0 ||
+ strcasecmp(key, "BUS") == 0) {
if (operation != KEY_OP_MATCH &&
operation != KEY_OP_NOMATCH) {
- err("invalid ID operation");
+ err("invalid SUBSYSTEMS operation");
goto invalid;
}
- add_rule_key(rule, &rule->id, operation, value);
+ add_rule_key(rule, &rule->subsystems, operation, value);
valid = 1;
continue;
}
- if (strncasecmp(key, "SYSFS", sizeof("SYSFS")-1) == 0) {
+ if (strcasecmp(key, "DRIVERS") == 0) {
if (operation != KEY_OP_MATCH &&
operation != KEY_OP_NOMATCH) {
- err("invalid SYSFS operation");
+ err("invalid DRIVERS operation");
goto invalid;
}
- attr = get_key_attribute(key + sizeof("SYSFS")-1);
- if (attr == NULL) {
- err("error parsing SYSFS attribute in '%s'", line);
- continue;
- }
- add_rule_key_pair(rule, &rule->sysfs, operation, attr, value);
+ add_rule_key(rule, &rule->drivers, operation, value);
valid = 1;
continue;
}
- if (strcasecmp(key, "WAIT_FOR_SYSFS") == 0) {
- add_rule_key(rule, &rule->wait_for_sysfs, operation, value);
+ if (strncasecmp(key, "ATTRS{", sizeof("ATTRS{")-1) == 0 ||
+ strncasecmp(key, "SYSFS{", sizeof("SYSFS{")-1) == 0) {
+ attr = get_key_attribute(key + sizeof("ATTRS")-1);
+ if (attr == NULL) {
+ err("error parsing ATTRS attribute");
+ goto invalid;
+ }
+ 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)
+ 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)
+ goto invalid;
valid = 1;
continue;
}
- if (strncasecmp(key, "ENV", sizeof("ENV")-1) == 0) {
+ if (strncasecmp(key, "ENV{", sizeof("ENV{")-1) == 0) {
attr = get_key_attribute(key + sizeof("ENV")-1);
if (attr == NULL) {
err("error parsing ENV attribute");
- continue;
+ goto invalid;
}
- add_rule_key_pair(rule, &rule->env, operation, attr, value);
+ if (strncmp(attr, "PHYSDEV", 7) == 0)
+ physdev = 1;
+ if (add_rule_key_pair(rule, &rule->env, operation, attr, value) != 0)
+ goto invalid;
+ valid = 1;
+ continue;
+ }
+
+ if (strcasecmp(key, "PROGRAM") == 0) {
+ add_rule_key(rule, &rule->program, operation, value);
valid = 1;
continue;
}
- if (strcasecmp(key, "MODALIAS") == 0) {
- add_rule_key(rule, &rule->modalias, operation, value);
+ 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;
}
continue;
}
- 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);
+ if (strcasecmp(key, "RUN") == 0) {
+ add_rule_key(rule, &rule->run, 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);
+ if (strcasecmp(key, "WAIT_FOR_SYSFS") == 0) {
+ add_rule_key(rule, &rule->wait_for_sysfs, operation, value);
valid = 1;
continue;
}
- if (strcasecmp(key, "PROGRAM") == 0) {
- add_rule_key(rule, &rule->program, operation, value);
+ if (strcasecmp(key, "LABEL") == 0) {
+ add_rule_key(rule, &rule->label, operation, value);
+ valid = 1;
+ continue;
+ }
+
+ if (strcasecmp(key, "GOTO") == 0) {
+ add_rule_key(rule, &rule->goto_label, operation, value);
valid = 1;
continue;
}
continue;
}
- if (strcasecmp(key, "RUN") == 0) {
- add_rule_key(rule, &rule->run, operation, value);
- valid = 1;
- continue;
- }
-
if (strcasecmp(key, "OPTIONS") == 0) {
if (strstr(value, "last_rule") != NULL) {
dbg("last rule to be applied");
continue;
}
- err("unknown key '%s'", key);
+ err("unknown key '%s' in %s:%u", key, filename, lineno);
}
+ if (physdev && rule->wait_for_sysfs.operation == KEY_OP_UNSET)
+ err("PHYSDEV* values are deprected and will be removed from a future kernel, "
+ "please fix it in %s:%u", filename, lineno);
+
/* skip line if not any valid key was found */
if (!valid)
goto invalid;
cur += count+1;
lineno++;
- if (count >= sizeof(line)) {
- err("line too long, rule skipped '%s:%u'", filename, lineno);
- continue;
- }
-
/* eat the whitespace */
while ((count > 0) && isspace(bufline[0])) {
bufline++;
if (bufline[0] == COMMENT_CHARACTER)
continue;
- /* skip backslash and newline from multi line rules */
+ if (count >= sizeof(line)) {
+ err("line too long, rule skipped '%s:%u'", filename, lineno);
+ continue;
+ }
+
+ /* skip backslash and newline from multiline rules */
for (i = j = 0; i < count; i++) {
if (bufline[i] == '\\' && bufline[i+1] == '\n')
continue;