X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=udev_rules.c;h=791e98ec07b0788484a348e5f4f3d2bfe924e3a4;hp=939febe8f69e20986a5b4629f69cd5f5caddbccc;hb=853ccc433c4d45c3e1da4336f87b458ed10311ca;hpb=594dd610252923591ed0f310695e82d3fb87e581 diff --git a/udev_rules.c b/udev_rules.c index 939febe8f..791e98ec0 100644 --- a/udev_rules.c +++ b/udev_rules.c @@ -1,12 +1,9 @@ /* * udev_rules.c * - * Userspace devfs - * * Copyright (C) 2003 Greg Kroah-Hartman * Copyright (C) 2003-2005 Kay Sievers * - * * 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 * Free Software Foundation version 2 of the License. @@ -30,6 +27,7 @@ #include #include #include +#include #include #include @@ -44,59 +42,6 @@ #include "udev_db.h" -/* compare string with pattern (supports * ? [0-9] [!A-Z]) */ -static int strcmp_pattern(const char *p, const char *s) -{ - if (s[0] == '\0') { - while (p[0] == '*') - p++; - return (p[0] != '\0'); - } - switch (p[0]) { - case '[': - { - int not = 0; - p++; - if (p[0] == '!') { - not = 1; - p++; - } - while ((p[0] != '\0') && (p[0] != ']')) { - int match = 0; - if (p[1] == '-') { - if ((s[0] >= p[0]) && (s[0] <= p[2])) - match = 1; - p += 3; - } else { - match = (p[0] == s[0]); - p++; - } - if (match ^ not) { - while ((p[0] != '\0') && (p[0] != ']')) - p++; - if (p[0] == ']') - return strcmp_pattern(p+1, s+1); - } - } - } - break; - case '*': - if (strcmp_pattern(p, s+1)) - return strcmp_pattern(p+1, s); - return 0; - case '\0': - if (s[0] == '\0') { - return 0; - } - break; - default: - if ((p[0] == s[0]) || (p[0] == '?')) - return strcmp_pattern(p+1, s+1); - break; - } - return 1; -} - /* extract possible {attr} and move str behind it */ static char *get_format_attribute(char **str) { @@ -243,7 +188,8 @@ static int import_keys_into_env(struct udevice *udev, const char *buf, size_t bu if (bufline[0] == COMMENT_CHARACTER) continue; - strlcpy(line, bufline, count+1); + memcpy(line, bufline, count); + line[count] = '\0'; linepos = line; if (get_key(&linepos, &variable, &value) == 0) { @@ -276,7 +222,7 @@ static int import_program_into_env(struct udevice *udev, const char *program) char result[1024]; size_t reslen; - if (execute_program(program, udev->subsystem, result, sizeof(result), &reslen) != 0) + if (run_program(program, udev->subsystem, result, sizeof(result), &reslen, (udev_log_priority >= LOG_DEBUG)) != 0) return -1; return import_keys_into_env(udev, result, reslen); } @@ -324,7 +270,7 @@ static int import_parent_into_env(struct udevice *udev, struct sysfs_class_devic /* finds the lowest positive N such that N isn't present in the udevdb * if doesn't exist, 0 is returned, N otherwise */ -static int find_free_number(struct udevice *udev, const char *name) +static int find_free_number(const char *name) { char devpath[PATH_SIZE]; char filename[PATH_SIZE]; @@ -351,6 +297,7 @@ static int find_free_number(struct udevice *udev, const char *name) static int find_sysfs_attribute(struct sysfs_class_device *class_dev, struct sysfs_device *sysfs_device, const char *name, char *value, size_t len) { + struct sysfs_class_device *class_dev_parent; struct sysfs_attribute *tmpattr; dbg("look for device attribute '%s'", name); @@ -359,6 +306,12 @@ static int find_sysfs_attribute(struct sysfs_class_device *class_dev, struct sys tmpattr = sysfs_get_classdev_attr(class_dev, name); if (tmpattr) goto attr_found; + class_dev_parent = sysfs_get_classdev_parent(class_dev); + if (class_dev_parent) { + tmpattr = sysfs_get_classdev_attr(class_dev_parent, name); + if (tmpattr) + goto attr_found; + } } if (sysfs_device) { dbg("look for devices attribute '%s/%s'", sysfs_device->path, name); @@ -444,7 +397,7 @@ static void apply_format(struct udevice *udev, char *string, size_t maxsize, { .name = "root", .fmt = 'r', .type = SUBST_ROOT }, { .name = "modalias", .fmt = 'A', .type = SUBST_MODALIAS }, { .name = "env", .fmt = 'E', .type = SUBST_ENV }, - {} + { NULL, '\0', 0 } }; enum subst_type type; const struct subst_map *subst; @@ -593,7 +546,7 @@ found: dbg("substitute sysfs value '%s'", temp2); break; case SUBST_ENUM: - next_free_number = find_free_number(udev, string); + next_free_number = find_free_number(string); if (next_free_number > 0) { sprintf(temp2, "%d", next_free_number); strlcat(string, temp2, maxsize); @@ -855,7 +808,7 @@ try_parent: apply_format(udev, import, sizeof(import), class_dev, sysfs_device); dbg("check for IMPORT import='%s'", import); if (rule->import_type == IMPORT_PROGRAM) { - dbg("run executable file import='%s'", import); + info("IMPORT executes '%s'", import); rc = import_program_into_env(udev, import); } else if (rule->import_type == IMPORT_FILE) { dbg("import file import='%s'", import); @@ -880,9 +833,10 @@ try_parent: strlcpy(program, key_val(rule, &rule->program), sizeof(program)); apply_format(udev, program, sizeof(program), class_dev, sysfs_device); - dbg("check for PROGRAM program='%s", program); - if (execute_program(program, udev->subsystem, result, sizeof(result), NULL) != 0) { + info("PROGRAM key executes '%s", program); + if (run_program(program, udev->subsystem, result, sizeof(result), NULL, (udev_log_priority >= LOG_DEBUG)) != 0) { dbg("PROGRAM is false"); + udev->program_result[0] = '\0'; if (rule->program.operation != KEY_OP_NOMATCH) goto exit; } else { @@ -1079,7 +1033,7 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev, struct s if (!name_set) { strlcpy(udev->name, udev->kernel_name, sizeof(udev->name)); - info("no rule found, will use kernel name '%s'", udev->name); + info("no node name set, will use kernel name '%s'", udev->name); } if (udev->tmp_node[0] != '\0') { @@ -1091,10 +1045,21 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev, struct s return 0; } -int udev_rules_get_run(struct udev_rules *rules, struct udevice *udev, struct sysfs_device *sysfs_device) +int udev_rules_get_run(struct udev_rules *rules, struct udevice *udev, + struct sysfs_class_device *class_dev, struct sysfs_device *sysfs_dev) { struct udev_rule *rule; + if (class_dev && !sysfs_dev) + sysfs_dev = sysfs_get_classdev_device(class_dev); + if (sysfs_dev) { + dbg("found devices device: path='%s', bus_id='%s', bus='%s'", + sysfs_dev->path, sysfs_dev->bus_id, sysfs_dev->bus); + strlcpy(udev->bus_id, sysfs_dev->bus_id, sizeof(udev->bus_id)); + } + + dbg("udev->kernel_name='%s'", udev->kernel_name); + /* look for a matching rule to apply */ udev_rules_iter_init(rules); while (1) { @@ -1109,7 +1074,7 @@ int udev_rules_get_run(struct udev_rules *rules, struct udevice *udev, struct sy continue; } - if (match_rule(udev, rule, NULL, sysfs_device) == 0) { + if (match_rule(udev, rule, class_dev, sysfs_dev) == 0) { if (rule->ignore_device) { info("rule applied, '%s' is ignored", udev->kernel_name); udev->ignore_device = 1; @@ -1130,7 +1095,7 @@ int udev_rules_get_run(struct udev_rules *rules, struct udevice *udev, struct sy } } strlcpy(program, key_val(rule, &rule->run), sizeof(program)); - apply_format(udev, program, sizeof(program), NULL, sysfs_device); + apply_format(udev, program, sizeof(program), class_dev, sysfs_dev); dbg("add run '%s'", program); name_list_add(&udev->run_list, program, 0); if (rule->run.operation == KEY_OP_ASSIGN_FINAL) @@ -1141,6 +1106,11 @@ int udev_rules_get_run(struct udev_rules *rules, struct udevice *udev, struct sy dbg("last rule to be applied"); break; } + + if (rule->goto_label.operation != KEY_OP_UNSET) { + dbg("moving forward to label '%s'", key_val(rule, &rule->goto_label)); + udev_rules_iter_label(rules, key_val(rule, &rule->goto_label)); + } } }