From 28ce66de1750320d7f09547d8910d42ae580fe5e Mon Sep 17 00:00:00 2001 From: "kay.sievers@vrfy.org" Date: Sun, 13 Mar 2005 05:46:31 +0100 Subject: [PATCH] [PATCH] support =, ==, !=, += for the key match and assignment --- RELEASE-NOTES | 10 ++ test/udev-test.pl | 354 ++++++++++++++++++++++++--------------------- udev.8.in | 42 +++--- udev_config.c | 80 +++++++--- udev_rules.c | 108 +++++++++----- udev_rules.h | 50 ++++--- udev_rules_parse.c | 191 +++++++++++++++++------- udev_utils.c | 35 ----- 8 files changed, 537 insertions(+), 333 deletions(-) diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 870020c4..ee77d845 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -8,3 +8,13 @@ a built-in userdb parser to resolve user and group names. THE PLACE= key is gone. It can be replaced by an ID= for a long time, cause we walk up the chain of physical devices to find a match. +The KEY="" format supports '=', '==', '!=,' , '+=' now. This makes it +easier to skip certain devices without composing rules with weird character +class negations like: + KERNEL="[!s][!c][!d]*" + +this can be replaced by: + KERNEL!="scd*" + +The simple '=' is still supported, but the rules should be converted if +possible, to be better human-readable. diff --git a/test/udev-test.pl b/test/udev-test.pl index 52c5c8d4..8d66536b 100644 --- a/test/udev-test.pl +++ b/test/udev-test.pl @@ -39,8 +39,8 @@ my @tests = ( devpath => "/block/sda", exp_name => "boot_disk" , conf => < "/block/sda/sda1", exp_name => "boot_disk1" , conf => < "/block/sda/sda1", exp_name => "boot_disk1" , conf => < "/block/sda/sda1", exp_name => "boot_disk1" , conf => < "/block/sda/sda1", exp_name => "boot_disk1" , conf => < "/class/tty/ttyUSB0", exp_name => "visor/0" , conf => < "/class/tty/ttyUSB0", exp_name => "visor/0" , conf => < "/class/tty/ttyUSB0", exp_name => "visor/0" , conf => < "/class/tty/ttyUSB0", exp_name => "visor/0" , conf => < "/class/tty/ttyUSB0", exp_name => "visor" , conf => < "visor" , conf => < "visor" , conf => < "visor" , conf => < "/class/tty/ttyUSB0", exp_name => "visor" , conf => < "/class/tty/ttyUSB0", exp_name => "aaa", conf => < "/class/tty/ttyUSB0", exp_name => "sub/direct/ory/visor" , conf => < "/block/sda/sda3", exp_name => "first_disk3" , conf => < "/block/sda/sda3", exp_name => "Major:8:minor:3:kernelnumber:3:bus:0:0:0:0" , conf => < "/block/sda/sda3", exp_name => "M8-m3-n3-b0:0-sIBM" , conf => < "/block/sda", exp_name => "good" , conf => < "/block/sda", exp_name => "disk-IBM-ESXS-sda" , conf => < "/block/sda/sda3", exp_name => "special-device-3" , conf => < "/block/sda/sda3", exp_name => "subsys_block" , conf => < "/block/sda/sda3", exp_name => "newline_removed" , conf => < "/block/sda/sda3", exp_name => "test-0:0:0:0" , conf => < "/block/sda/sda3", exp_name => "escape-3" , conf => < "/block/sda/sda3", exp_name => "foo9" , conf => < "/block/sda/sda3", exp_name => "bar9" , conf => < "/block/sda/sda3", exp_name => "foo7" , conf => < "/block/sda/sda3", exp_name => "my-foo9" , conf => < "/block/sda/sda3", exp_name => "my-foo8" , conf => < "/class/tty/console", exp_name => "TTY" , conf => < "/class/tty/console", exp_name => "foo" , conf => < "/class/tty/console", exp_name => "TTY" , conf => < "/class/tty/console", exp_name => "foo" , conf => < "/block/sda", exp_name => "scsi-0:0:0:0" , conf => < "/block/sda", exp_name => "boot_disk15" , conf => < "/class/tty/ttyUSB0", exp_name => "visor" , conf => < "/block/rd!c0d0", exp_name => "rd/c0d0" , conf => < "/block/rd!c0d0", exp_name => "rd/c0d0" , conf => < "/block/cciss!c0d0/cciss!c0d0p1", exp_name => "cciss/c0d0p1" , conf => < "/block/sda", exp_name => "scsi-0:0:0:0", conf => < "/block/sda", exp_name => "scsi-0:0:0:0", conf => < "/block/sda", exp_name => "scsi-0:0:0:0", conf => < "/block/sda", exp_name => "scsi-0:0:0:0", conf => < "/block/sda", exp_name => "ignored", conf => < "/block/sda", exp_name => "matched-with-space", conf => < "tty33", exp_perms => "0:0:0660", conf => < "node", exp_perms => "5000::0660", conf => < "node", exp_perms => ":100:0660", conf => < "node", exp_perms => "::0777", conf => < "node", exp_perms => "5000:100:0777", conf => < "ttyUSB0", exp_perms => "5000::", conf => < "ttyUSB0", exp_perms => ":100:0660", conf => < "ttyUSB0", exp_perms => "::0060", conf => < "ttyUSB0", exp_perms => "5000:100:0777", conf => < "ttyUSB0", exp_perms => "5000:100:0777", conf => < "ttyUSB0", exp_perms => "3000:4000:0777", conf => < "ttyUSB0", exp_perms => "3000:8000:0777", conf => < "node", exp_majorminor => "8:0", conf => < "node", exp_majorminor => "89:300", conf => < "node", exp_majorminor => "4095:1", conf => < "node", exp_majorminor => "4094:89999", conf => < "symlink2-ttyUSB0", exp_target => "ttyUSB0", conf => < "visor0", exp_target => "ttyUSB0", conf => < "1/2/symlink" , exp_target => "a/b/node", conf => < "1/2/c/d/symlink" , exp_target => "../../a/b/node", conf => < "second-0" , exp_target => "visor" , conf => < "symlink-only2", exp_target => "link", conf => < "yes", exp_rem_error => "yes", conf => < "yes", option => "clear", conf => < "symlink0", exp_target => "ttyUSB0", conf => < "symlink-ttyUSB0", exp_target => "ttyUSB0", conf => < "major-188:0", exp_target => "ttyUSB0", conf => < "symlink-0:0:0:0", exp_target => "node", conf => < "test", exp_target => "ttyUSB0", conf => < "test", exp_target => "ttyUSB0", conf => < "this", exp_target => "ttyUSB0", conf => < "test", exp_target => "link", conf => < "188:0", exp_target => "ttyUSB0", conf => < "188", exp_target => "ttyUSB0", conf => < "percent%sign", exp_target => "ttyUSB0", conf => < "%ttyUSB0_name", exp_target => "ttyUSB0", conf => < "link1", exp_target => "node", conf => < "link4", exp_target => "node", conf => < "/block/sda", exp_name => "cdrom", conf => < "cdrom", option => "keep", conf => < "enum", option => "keep", conf => < "cdrom1", option => "keep", conf => < "enum1", option => "keep", conf => < "cdrom2", option => "clear", conf => < "/block/sda", exp_name => "cdrom", conf => < "node", exp_add_error => "yes", conf => < "/block/sda", exp_name => "node6", conf => < "node6", exp_add_error => "yes", conf => < "node", exp_rem_error => "yes", conf => < "yes", option => "clear", conf => < "/block/sda", exp_name => "node", conf => < "/block/sda", exp_name => "node", conf => < "/block/sda", exp_name => "node", conf => < "/block/sda", exp_name => "sda", conf => < "main_device", option => "keep", conf => < "main_device-part-1", option => "clean", conf => < "/block/sda/sda1", exp_name => "start-udev-root-end", conf => < "/block/sda/sda1", exp_name => "last", conf => < "negation KERNEL!=", + subsys => "block", + devpath => "/block/sda/sda1", + exp_name => "match", + conf => < "negation SUBSYSTEM!=", + subsys => "block", + devpath => "/block/sda/sda1", + exp_name => "not-anything", + conf => < "negation PROGRAM!= exit code", + subsys => "block", + devpath => "/block/sda/sda1", + exp_name => "nonzero-program", + conf => <file[0] == '\0') || (pair->value[0] == '\0')) break; if (compare_sysfs_attribute(class_dev, sysfs_device, pair) != 0) { - dbg("sysfs attribute doesn't match"); - return -ENODEV; + dbg("sysfs pair #%u does not match", i); + if (pair->operation != KEY_OP_NOMATCH) + return -1; + } else { + dbg("sysfs pair #%u matches", i); + if (pair->operation == KEY_OP_NOMATCH) + return -1; } } @@ -535,23 +540,33 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule, struct sysfs_class_device *class_dev, struct sysfs_device *sysfs_device) { if (rule->kernel[0] != '\0') { - dbg("check for " FIELD_KERNEL " rule->kernel='%s' class_dev->name='%s'", + dbg("check for " KEY_KERNEL " rule->kernel='%s' class_dev->name='%s'", rule->kernel, class_dev->name); if (strcmp_pattern(rule->kernel, class_dev->name) != 0) { - dbg(FIELD_KERNEL " is not matching"); - goto exit; + dbg(KEY_KERNEL " is not matching"); + if (rule->kernel_operation != KEY_OP_NOMATCH) + goto exit; + } else { + dbg(KEY_KERNEL " matches"); + if (rule->kernel_operation == KEY_OP_NOMATCH) + goto exit; } - dbg(FIELD_KERNEL " matches"); + dbg(KEY_KERNEL " key is true"); } if (rule->subsystem[0] != '\0') { - dbg("check for " FIELD_SUBSYSTEM " rule->subsystem='%s' class_dev->name='%s'", + dbg("check for " KEY_SUBSYSTEM " rule->subsystem='%s' class_dev->name='%s'", rule->subsystem, class_dev->name); if (strcmp_pattern(rule->subsystem, udev->subsystem) != 0) { - dbg(FIELD_SUBSYSTEM " is not matching"); - goto exit; + dbg(KEY_SUBSYSTEM " is not matching"); + if (rule->subsystem_operation != KEY_OP_NOMATCH) + goto exit; + } else { + dbg(KEY_SUBSYSTEM " matches"); + if (rule->subsystem_operation == KEY_OP_NOMATCH) + goto exit; } - dbg(FIELD_SUBSYSTEM " matches"); + dbg(KEY_SUBSYSTEM " key is true"); } /* walk up the chain of physical devices and find a match */ @@ -562,13 +577,18 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule, dbg("device has no sysfs_device"); goto try_parent; } - dbg("check for " FIELD_DRIVER " rule->driver='%s' sysfs_device->driver_name='%s'", + dbg("check for " KEY_DRIVER " rule->driver='%s' sysfs_device->driver_name='%s'", rule->driver, sysfs_device->driver_name); if (strcmp_pattern(rule->driver, sysfs_device->driver_name) != 0) { - dbg(FIELD_DRIVER " is not matching"); - goto try_parent; + dbg(KEY_DRIVER " is not matching"); + if (rule->driver_operation != KEY_OP_NOMATCH) + goto try_parent; + } else { + dbg(KEY_DRIVER " matches"); + if (rule->driver_operation == KEY_OP_NOMATCH) + goto try_parent; } - dbg(FIELD_DRIVER " matches"); + dbg(KEY_DRIVER " key is true"); } /* check for matching bus value */ @@ -577,13 +597,18 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule, dbg("device has no sysfs_device"); goto try_parent; } - dbg("check for " FIELD_BUS " rule->bus='%s' sysfs_device->bus='%s'", + dbg("check for " KEY_BUS " rule->bus='%s' sysfs_device->bus='%s'", rule->bus, sysfs_device->bus); if (strcmp_pattern(rule->bus, sysfs_device->bus) != 0) { - dbg(FIELD_BUS " is not matching"); - goto try_parent; + dbg(KEY_BUS " is not matching"); + if (rule->bus_operation != KEY_OP_NOMATCH) + goto try_parent; + } else { + dbg(KEY_BUS " matches"); + if (rule->bus_operation == KEY_OP_NOMATCH) + goto try_parent; } - dbg(FIELD_BUS " matches"); + dbg(KEY_BUS " key is true"); } /* check for matching bus id */ @@ -592,22 +617,27 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule, dbg("device has no sysfs_device"); goto try_parent; } - dbg("check " FIELD_ID); + dbg("check " KEY_ID); if (match_id(rule, sysfs_device) != 0) { - dbg(FIELD_ID " is not matching"); - goto try_parent; + dbg(KEY_ID " is not matching"); + if (rule->id_operation != KEY_OP_NOMATCH) + goto try_parent; + } else { + dbg(KEY_ID " matches"); + if (rule->id_operation == KEY_OP_NOMATCH) + goto try_parent; } - dbg(FIELD_ID " matches"); + dbg(KEY_ID " key is true"); } /* check for matching sysfs pairs */ if (rule->sysfs_pair[0].file[0] != '\0') { - dbg("check " FIELD_SYSFS " pairs"); + dbg("check " KEY_SYSFS " pairs"); if (match_sysfs_pairs(rule, class_dev, sysfs_device) != 0) { - dbg(FIELD_SYSFS " is not matching"); + dbg(KEY_SYSFS " is not matching"); goto try_parent; } - dbg(FIELD_SYSFS " matches"); + dbg(KEY_SYSFS " keys are true"); } /* found matching physical device */ @@ -625,25 +655,35 @@ try_parent: if (rule->program[0] != '\0') { char program[PATH_SIZE]; - dbg("check " FIELD_PROGRAM); + dbg("check " KEY_PROGRAM); strlcpy(program, rule->program, sizeof(program)); apply_format(udev, program, sizeof(program), class_dev, sysfs_device); if (execute_program(udev, program, udev->program_result, sizeof(udev->program_result)) != 0) { - dbg(FIELD_PROGRAM " returned nonzero"); - goto try_parent; + dbg(KEY_PROGRAM " returned nonzero"); + if (rule->program_operation != KEY_OP_NOMATCH) + goto exit; + } else { + dbg(KEY_PROGRAM " returned successful"); + if (rule->program_operation == KEY_OP_NOMATCH) + goto exit; } - dbg(FIELD_PROGRAM " returned successful"); + dbg(KEY_PROGRAM " key is true"); } /* check for matching result of external program */ if (rule->result[0] != '\0') { - dbg("check for " FIELD_RESULT "rule->result='%s', udev->program_result='%s'", + dbg("check for " KEY_RESULT " rule->result='%s', udev->program_result='%s'", rule->result, udev->program_result); if (strcmp_pattern(rule->result, udev->program_result) != 0) { - dbg(FIELD_RESULT " is not matching"); - goto try_parent; + dbg(KEY_RESULT " is not matching"); + if (rule->result_operation != KEY_OP_NOMATCH) + goto exit; + } else { + dbg(KEY_RESULT " matches"); + if (rule->result_operation == KEY_OP_NOMATCH) + goto exit; } - dbg(FIELD_RESULT " matches"); + dbg(KEY_RESULT " key is true"); } /* rule matches */ diff --git a/udev_rules.h b/udev_rules.h index 42552cfa..d0142031 100644 --- a/udev_rules.h +++ b/udev_rules.h @@ -28,20 +28,20 @@ #include "list.h" -#define FIELD_KERNEL "KERNEL" -#define FIELD_SUBSYSTEM "SUBSYSTEM" -#define FIELD_BUS "BUS" -#define FIELD_SYSFS "SYSFS" -#define FIELD_ID "ID" -#define FIELD_PROGRAM "PROGRAM" -#define FIELD_RESULT "RESULT" -#define FIELD_DRIVER "DRIVER" -#define FIELD_NAME "NAME" -#define FIELD_SYMLINK "SYMLINK" -#define FIELD_OWNER "OWNER" -#define FIELD_GROUP "GROUP" -#define FIELD_MODE "MODE" -#define FIELD_OPTIONS "OPTIONS" +#define KEY_KERNEL "KERNEL" +#define KEY_SUBSYSTEM "SUBSYSTEM" +#define KEY_BUS "BUS" +#define KEY_SYSFS "SYSFS" +#define KEY_ID "ID" +#define KEY_PROGRAM "PROGRAM" +#define KEY_RESULT "RESULT" +#define KEY_DRIVER "DRIVER" +#define KEY_NAME "NAME" +#define KEY_SYMLINK "SYMLINK" +#define KEY_OWNER "OWNER" +#define KEY_GROUP "GROUP" +#define KEY_MODE "MODE" +#define KEY_OPTIONS "OPTIONS" #define OPTION_LAST_RULE "last_rule" #define OPTION_IGNORE_DEVICE "ignore_device" @@ -52,25 +52,41 @@ #define RULEFILE_SUFFIX ".rules" +enum key_operation { + KEY_OP_UNKNOWN, + KEY_OP_MATCH, + KEY_OP_NOMATCH, + KEY_OP_ADD, + KEY_OP_ASSIGN, +}; + struct sysfs_pair { char file[PATH_SIZE]; char value[VALUE_SIZE]; + enum key_operation operation; }; struct udev_rule { struct list_head node; char kernel[NAME_SIZE]; + enum key_operation kernel_operation; char subsystem[NAME_SIZE]; + enum key_operation subsystem_operation; char bus[NAME_SIZE]; + enum key_operation bus_operation; char id[NAME_SIZE]; - struct sysfs_pair sysfs_pair[MAX_SYSFS_PAIRS]; + enum key_operation id_operation; + char driver[NAME_SIZE]; + enum key_operation driver_operation; char program[PATH_SIZE]; + enum key_operation program_operation; char result[PATH_SIZE]; - char driver[NAME_SIZE]; + enum key_operation result_operation; + struct sysfs_pair sysfs_pair[MAX_SYSFS_PAIRS]; + char name[PATH_SIZE]; char symlink[PATH_SIZE]; - char owner[USER_SIZE]; char group[USER_SIZE]; mode_t mode; diff --git a/udev_rules_parse.c b/udev_rules_parse.c index f77f3db9..ac4755fd 100644 --- a/udev_rules_parse.c +++ b/udev_rules_parse.c @@ -73,6 +73,90 @@ void udev_rule_list_dump(void) udev_rule_dump(rule); } +static int get_key(char **line, char **key, enum key_operation *operation, char **value) +{ + char *linepos; + char *temp; + + linepos = *line; + if (!linepos) + return -1; + + /* skip whitespace */ + while (isspace(linepos[0]) || linepos[0] == ',') + linepos++; + + /* get the key */ + *key = linepos; + while (1) { + linepos++; + if (linepos[0] == '\0') + return -1; + if (isspace(linepos[0])) + break; + if (linepos[0] == '=') + break; + if (linepos[0] == '+') + break; + if (linepos[0] == '!') + break; + } + + /* remember end of key */ + temp = linepos; + + /* skip whitespace after key */ + while (isspace(linepos[0])) + linepos++; + + /* get operation type */ + if (linepos[0] == '=' && linepos[1] == '=') { + *operation = KEY_OP_MATCH; + linepos += 2; + dbg("operator=match"); + } else if (linepos[0] == '!' && linepos[1] == '=') { + *operation = KEY_OP_NOMATCH; + linepos += 2; + dbg("operator=nomatch"); + } else if (linepos[0] == '+' && linepos[1] == '=') { + *operation = KEY_OP_ADD; + linepos += 2; + dbg("operator=add"); + } else if (linepos[0] == '=') { + *operation = KEY_OP_ASSIGN; + linepos++; + dbg("operator=assign"); + } else + return -1; + + /* terminate key */ + temp[0] = '\0'; + dbg("key='%s'", *key); + + /* skip whitespace after operator */ + while (isspace(linepos[0])) + linepos++; + + /* get the value*/ + if (linepos[0] == '"') + linepos++; + else + return -1; + *value = linepos; + + temp = strchr(linepos, '"'); + if (!temp) + return -1; + temp[0] = '\0'; + temp++; + dbg("value='%s'", *value); + + /* move line to next key */ + *line = temp; + + return 0; +} + /* extract possible KEY{attr} */ static char *get_key_attribute(char *str) { @@ -100,9 +184,7 @@ static int rules_parse(struct udevice *udev, const char *filename) char line[LINE_SIZE]; char *bufline; int lineno; - char *temp; - char *temp2; - char *temp3; + char *linepos; char *attr; char *buf; size_t bufsize; @@ -113,12 +195,11 @@ static int rules_parse(struct udevice *udev, const char *filename) int retval = 0; struct udev_rule rule; - if (file_map(filename, &buf, &bufsize) == 0) { - dbg("reading '%s' as rules file", filename); - } else { + if (file_map(filename, &buf, &bufsize) != 0) { dbg("can't open '%s' as rules file", filename); return -1; } + dbg("reading '%s' as rules file", filename); /* loop through the whole file */ cur = 0; @@ -160,39 +241,47 @@ static int rules_parse(struct udevice *udev, const char *filename) /* get all known keys */ memset(&rule, 0x00, sizeof(struct udev_rule)); - temp = line; + linepos = line; valid = 0; while (1) { - retval = parse_get_pair(&temp, &temp2, &temp3); + char *key; + char *value; + enum key_operation operation = KEY_OP_UNKNOWN; + + retval = get_key(&linepos, &key, &operation, &value); if (retval) break; - if (strcasecmp(temp2, FIELD_KERNEL) == 0) { - strlcpy(rule.kernel, temp3, sizeof(rule.kernel)); + if (strcasecmp(key, KEY_KERNEL) == 0) { + strlcpy(rule.kernel, value, sizeof(rule.kernel)); + rule.kernel_operation = operation; valid = 1; continue; } - if (strcasecmp(temp2, FIELD_SUBSYSTEM) == 0) { - strlcpy(rule.subsystem, temp3, sizeof(rule.subsystem)); + if (strcasecmp(key, KEY_SUBSYSTEM) == 0) { + strlcpy(rule.subsystem, value, sizeof(rule.subsystem)); + rule.subsystem_operation = operation; valid = 1; continue; } - if (strcasecmp(temp2, FIELD_BUS) == 0) { - strlcpy(rule.bus, temp3, sizeof(rule.bus)); + if (strcasecmp(key, KEY_BUS) == 0) { + strlcpy(rule.bus, value, sizeof(rule.bus)); + rule.bus_operation = operation; valid = 1; continue; } - if (strcasecmp(temp2, FIELD_ID) == 0) { - strlcpy(rule.id, temp3, sizeof(rule.id)); + if (strcasecmp(key, KEY_ID) == 0) { + strlcpy(rule.id, value, sizeof(rule.id)); + rule.id_operation = operation; valid = 1; continue; } - if (strncasecmp(temp2, FIELD_SYSFS, sizeof(FIELD_SYSFS)-1) == 0) { + if (strncasecmp(key, KEY_SYSFS, sizeof(KEY_SYSFS)-1) == 0) { struct sysfs_pair *pair = &rule.sysfs_pair[0]; int sysfs_pair_num = 0; @@ -206,39 +295,43 @@ static int rules_parse(struct udevice *udev, const char *filename) ++pair; } if (pair) { - attr = get_key_attribute(temp2 + sizeof(FIELD_SYSFS)-1); + attr = get_key_attribute(key + sizeof(KEY_SYSFS)-1); if (attr == NULL) { - dbg("error parsing " FIELD_SYSFS " attribute"); + dbg("error parsing " KEY_SYSFS " attribute"); continue; } strlcpy(pair->file, attr, sizeof(pair->file)); - strlcpy(pair->value, temp3, sizeof(pair->value)); + strlcpy(pair->value, value, sizeof(pair->value)); + pair->operation = operation; valid = 1; } continue; } - if (strcasecmp(temp2, FIELD_DRIVER) == 0) { - strlcpy(rule.driver, temp3, sizeof(rule.driver)); + if (strcasecmp(key, KEY_DRIVER) == 0) { + strlcpy(rule.driver, value, sizeof(rule.driver)); + rule.driver_operation = operation; valid = 1; continue; } - if (strcasecmp(temp2, FIELD_PROGRAM) == 0) { - program_given = 1; - strlcpy(rule.program, temp3, sizeof(rule.program)); + if (strcasecmp(key, KEY_RESULT) == 0) { + strlcpy(rule.result, value, sizeof(rule.result)); + rule.result_operation = operation; valid = 1; continue; } - if (strcasecmp(temp2, FIELD_RESULT) == 0) { - strlcpy(rule.result, temp3, sizeof(rule.result)); + if (strcasecmp(key, KEY_PROGRAM) == 0) { + strlcpy(rule.program, value, sizeof(rule.program)); + rule.program_operation = operation; + program_given = 1; valid = 1; continue; } - if (strncasecmp(temp2, FIELD_NAME, sizeof(FIELD_NAME)-1) == 0) { - attr = get_key_attribute(temp2 + sizeof(FIELD_NAME)-1); + if (strncasecmp(key, KEY_NAME, sizeof(KEY_NAME)-1) == 0) { + attr = get_key_attribute(key + sizeof(KEY_NAME)-1); /* FIXME: remove old style options and make OPTIONS= mandatory */ if (attr != NULL) { if (strstr(attr, OPTION_PARTITIONS) != NULL) { @@ -250,52 +343,52 @@ static int rules_parse(struct udevice *udev, const char *filename) rule.ignore_remove = 1; } } - if (temp3[0] != '\0') - strlcpy(rule.name, temp3, sizeof(rule.name)); + if (value[0] != '\0') + strlcpy(rule.name, value, sizeof(rule.name)); else rule.ignore_device = 1; valid = 1; continue; } - if (strcasecmp(temp2, FIELD_SYMLINK) == 0) { - strlcpy(rule.symlink, temp3, sizeof(rule.symlink)); + if (strcasecmp(key, KEY_SYMLINK) == 0) { + strlcpy(rule.symlink, value, sizeof(rule.symlink)); valid = 1; continue; } - if (strcasecmp(temp2, FIELD_OWNER) == 0) { - strlcpy(rule.owner, temp3, sizeof(rule.owner)); + if (strcasecmp(key, KEY_OWNER) == 0) { + strlcpy(rule.owner, value, sizeof(rule.owner)); valid = 1; continue; } - if (strcasecmp(temp2, FIELD_GROUP) == 0) { - strlcpy(rule.group, temp3, sizeof(rule.group)); + if (strcasecmp(key, KEY_GROUP) == 0) { + strlcpy(rule.group, value, sizeof(rule.group)); valid = 1; continue; } - if (strcasecmp(temp2, FIELD_MODE) == 0) { - rule.mode = strtol(temp3, NULL, 8); + if (strcasecmp(key, KEY_MODE) == 0) { + rule.mode = strtol(value, NULL, 8); valid = 1; continue; } - if (strcasecmp(temp2, FIELD_OPTIONS) == 0) { - if (strstr(temp3, OPTION_LAST_RULE) != NULL) { + if (strcasecmp(key, KEY_OPTIONS) == 0) { + if (strstr(value, OPTION_LAST_RULE) != NULL) { dbg("last rule to be applied"); rule.last_rule = 1; } - if (strstr(temp3, OPTION_IGNORE_DEVICE) != NULL) { + if (strstr(value, OPTION_IGNORE_DEVICE) != NULL) { dbg("device should be ignored"); rule.ignore_device = 1; } - if (strstr(temp3, OPTION_IGNORE_REMOVE) != NULL) { + if (strstr(value, OPTION_IGNORE_REMOVE) != NULL) { dbg("remove event should be ignored"); rule.ignore_remove = 1; } - if (strstr(temp3, OPTION_PARTITIONS) != NULL) { + if (strstr(value, OPTION_PARTITIONS) != NULL) { dbg("creation of partition nodes requested"); rule.partitions = DEFAULT_PARTITIONS_COUNT; } @@ -303,7 +396,7 @@ static int rules_parse(struct udevice *udev, const char *filename) continue; } - dbg("unknown type of field '%s'", temp2); + dbg("unknown key '%s'", key); goto error; } @@ -314,13 +407,13 @@ static int rules_parse(struct udevice *udev, const char *filename) /* simple plausibility checks for given keys */ if ((rule.sysfs_pair[0].file[0] == '\0') ^ (rule.sysfs_pair[0].value[0] == '\0')) { - info("inconsistency in " FIELD_SYSFS " key"); + info("inconsistency in " KEY_SYSFS " key"); goto error; } if ((rule.result[0] != '\0') && (program_given == 0)) { - info(FIELD_RESULT " is only useful when " - FIELD_PROGRAM " is called in any rule before"); + info(KEY_RESULT " is only useful when " + KEY_PROGRAM " is called in any rule before"); goto error; } @@ -332,7 +425,7 @@ static int rules_parse(struct udevice *udev, const char *filename) continue; error: info("parse error %s, line %d:%d, rule skipped", - filename, lineno, (int) (temp - line)); + filename, lineno, (int) (linepos - line)); } } diff --git a/udev_utils.c b/udev_utils.c index b6500965..c6658e69 100644 --- a/udev_utils.c +++ b/udev_utils.c @@ -177,41 +177,6 @@ int unlink_secure(const char *filename) return retval; } -int parse_get_pair(char **orig_string, char **left, char **right) -{ - char *temp; - char *string = *orig_string; - - if (!string) - return -ENODEV; - - /* eat any whitespace */ - while (isspace(*string) || *string == ',') - ++string; - - /* split based on '=' */ - temp = strsep(&string, "="); - *left = temp; - if (!string) - return -ENODEV; - - /* take the right side and strip off the '"' */ - while (isspace(string[0])) - ++string; - if (string[0] == '"') - ++string; - else - return -ENODEV; - - temp = strsep(&string, "\""); - if (!string || temp[0] == '\0') - return -ENODEV; - *right = temp; - *orig_string = string; - - return 0; -} - int file_map(const char *filename, char **buf, size_t *bufsize) { struct stat stats; -- 2.39.5