X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=udev_rules.c;h=3dc77855da29359f38b354236d92901c9d547877;hb=92ebb398ed004348d5f92a242f323fb25dc7d6e5;hp=16f23ccb04ebc570fc6b66066ce4f47db378fdf4;hpb=3b6ed8bb06d18a2855d530dcb9034e9d37114827;p=elogind.git diff --git a/udev_rules.c b/udev_rules.c index 16f23ccb0..3dc77855d 100644 --- a/udev_rules.c +++ b/udev_rules.c @@ -390,7 +390,7 @@ static int execute_program(struct udevice *udev, const char *path, char *value, dup2(fds[1], STDOUT_FILENO); retval = execv(arg, argv); - info(FIELD_PROGRAM " execution of '%s' failed", path); + info(KEY_PROGRAM " execution of '%s' failed", path); exit(1); case -1: dbg("fork failed"); @@ -463,16 +463,16 @@ attr_found: return tmpattr; } -static int compare_sysfs_attribute(struct sysfs_class_device *class_dev, struct sysfs_device *sysfs_device, struct sysfs_pair *pair) +static int compare_sysfs_attribute(struct sysfs_class_device *class_dev, struct sysfs_device *sysfs_device, struct key_pair *pair) { struct sysfs_attribute *tmpattr; int i; int len; - if ((pair == NULL) || (pair->file[0] == '\0') || (pair->value == '\0')) + if ((pair == NULL) || (pair->name[0] == '\0') || (pair->value == '\0')) return -ENODEV; - tmpattr = find_sysfs_attribute(class_dev, sysfs_device, pair->file); + tmpattr = find_sysfs_attribute(class_dev, sysfs_device, pair->name); if (tmpattr == NULL) return -ENODEV; @@ -489,45 +489,12 @@ static int compare_sysfs_attribute(struct sysfs_class_device *class_dev, struct } dbg("compare attribute '%s' value '%s' with '%s'", - pair->file, tmpattr->value, pair->value); + pair->name, tmpattr->value, pair->value); if (strcmp_pattern(pair->value, tmpattr->value) != 0) return -ENODEV; dbg("found matching attribute '%s' with value '%s'", - pair->file, pair->value); - return 0; -} - -static int match_sysfs_pairs(struct udev_rule *rule, struct sysfs_class_device *class_dev, struct sysfs_device *sysfs_device) -{ - struct sysfs_pair *pair; - int i; - - for (i = 0; i < MAX_SYSFS_PAIRS; ++i) { - pair = &rule->sysfs_pair[i]; - if ((pair->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; - } - } - - return 0; -} - -static int match_id(struct udev_rule *rule, struct sysfs_device *sysfs_device) -{ - char path[PATH_SIZE]; - char *temp; - - strlcpy(path, sysfs_device->path, sizeof(path)); - temp = strrchr(path, '/'); - temp++; - dbg("search '%s' in '%s', path='%s'", rule->id, temp, path); - if (strcmp_pattern(rule->id, temp) != 0) - return -ENODEV; - + pair->name, pair->value); return 0; } @@ -535,23 +502,60 @@ 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"); + } + + if (rule->env_pair_count) { + int i; + + dbg("check for " KEY_ENV " pairs"); + for (i = 0; i < rule->env_pair_count; i++) { + struct key_pair *pair; + const char *value; + + pair = &rule->env_pair[i]; + value = getenv(pair->name); + if (!value) { + dbg(KEY_ENV "{'%s'} is not found", pair->name); + goto exit; + } + if (strcmp_pattern(pair->value, value) != 0) { + dbg(KEY_ENV "{'%s'} is not matching", pair->name); + if (pair->operation != KEY_OP_NOMATCH) + goto exit; + } else { + dbg(KEY_ENV "{'%s'} matches", pair->name); + if (pair->operation == KEY_OP_NOMATCH) + goto exit; + } + } + dbg(KEY_ENV " key is true"); } /* walk up the chain of physical devices and find a match */ @@ -560,54 +564,81 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule, if (rule->driver[0] != '\0') { if (sysfs_device == NULL) { dbg("device has no sysfs_device"); - goto try_parent; + goto exit; } - 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 */ if (rule->bus[0] != '\0') { if (sysfs_device == NULL) { dbg("device has no sysfs_device"); - goto try_parent; + goto exit; } - 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 */ if (rule->id[0] != '\0') { if (sysfs_device == NULL) { dbg("device has no sysfs_device"); - goto try_parent; + goto exit; } - dbg("check " FIELD_ID); - if (match_id(rule, sysfs_device) != 0) { - dbg(FIELD_ID " is not matching"); - goto try_parent; + dbg("check " KEY_ID); + if (strcmp_pattern(rule->id, sysfs_device->bus_id) != 0) { + 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"); - if (match_sysfs_pairs(rule, class_dev, sysfs_device) != 0) { - dbg(FIELD_SYSFS " is not matching"); - goto try_parent; + if (rule->sysfs_pair_count) { + int i; + + dbg("check " KEY_SYSFS " pairs"); + for (i = 0; i < rule->sysfs_pair_count; i++) { + struct key_pair *pair; + + pair = &rule->sysfs_pair[i]; + if (compare_sysfs_attribute(class_dev, sysfs_device, pair) != 0) { + dbg(KEY_SYSFS "{'%s'} is not matching", pair->name); + if (pair->operation != KEY_OP_NOMATCH) + goto try_parent; + } else { + dbg(KEY_SYSFS "{'%s'} matches", pair->name); + if (pair->operation == KEY_OP_NOMATCH) + goto try_parent; + } } - dbg(FIELD_SYSFS " matches"); + dbg(KEY_SYSFS " keys are true"); } /* found matching physical device */ @@ -617,33 +648,43 @@ try_parent: sysfs_device = sysfs_get_device_parent(sysfs_device); if (sysfs_device == NULL) goto exit; - dbg("sysfs_device->path='%s'", sysfs_device->path); - dbg("sysfs_device->bus_id='%s'", sysfs_device->bus_id); + dbg("look at sysfs_device->path='%s'", sysfs_device->path); + dbg("look at sysfs_device->bus_id='%s'", sysfs_device->bus_id); } /* execute external program */ 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 */