char result[2048];
size_t reslen;
- if (run_program(program, udev->dev->subsystem, result, sizeof(result), &reslen, (udev_log_priority >= LOG_INFO)) != 0)
+ if (run_program(program, udev->dev->subsystem, result, sizeof(result), &reslen) != 0)
return -1;
return import_keys_into_env(udev, result, reslen);
}
info("wait for '%s' for %i mseconds", filepath, 1000 / WAIT_LOOP_PER_SECOND);
usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
}
- err("waiting for '%s' failed", filepath);
+ info("waiting for '%s' failed", filepath);
return -1;
}
+/* handle "[$SUBSYSTEM/$KERNEL]<attribute>" lookup */
+static int attr_get_by_subsys_id(const char *attrstr, char *devpath, size_t len, char **attr)
+{
+ char subsys[NAME_SIZE];
+ char *attrib;
+ char *id;
+ int found = 0;
+
+ if (attrstr[0] != '[')
+ goto out;
+
+ strlcpy(subsys, &attrstr[1], sizeof(subsys));
+
+ attrib = strchr(subsys, ']');
+ if (attrib == NULL)
+ goto out;
+ attrib[0] = '\0';
+ attrib = &attrib[1];
+
+ id = strchr(subsys, '/');
+ if (id == NULL)
+ goto out;
+ id[0] = '\0';
+ id = &id[1];
+
+ if (sysfs_lookup_devpath_by_subsys_id(devpath, len, subsys, id)) {
+ if (attr != NULL) {
+ if (attrib[0] != '\0')
+ *attr = attrib;
+ else
+ *attr = NULL;
+ }
+ found = 1;
+ }
+out:
+ return found;
+}
+
void udev_rules_apply_format(struct udevice *udev, char *string, size_t maxsize)
{
char temp[PATH_SIZE];
if (attr == NULL)
err("missing file parameter for attr");
else {
+ char devpath[PATH_SIZE];
+ char *attrib;
const char *value = NULL;
size_t size;
- /* first try the current device, other matches may have selected */
- if (udev->dev_parent != NULL && udev->dev_parent != udev->dev)
+ if (attr_get_by_subsys_id(attr, devpath, sizeof(devpath), &attrib)) {
+ if (attrib != NULL)
+ value = sysfs_attr_get_value(devpath, attrib);
+ else
+ break;
+ }
+
+ /* try the current device, other matches may have selected */
+ if (value == NULL && udev->dev_parent != NULL && udev->dev_parent != udev->dev)
value = sysfs_attr_get_value(udev->dev_parent->devpath, attr);
/* look at all devices along the chain of parents */
if (rule->test.operation != KEY_OP_UNSET) {
char filename[PATH_SIZE];
+ char devpath[PATH_SIZE];
+ char *attr;
struct stat statbuf;
int match;
strlcpy(filename, key_val(rule, &rule->test), sizeof(filename));
udev_rules_apply_format(udev, filename, sizeof(filename));
+ if (attr_get_by_subsys_id(filename, devpath, sizeof(devpath), &attr)) {
+ strlcpy(filename, sysfs_path, sizeof(filename));
+ strlcat(filename, devpath, sizeof(filename));
+ if (attr != NULL) {
+ strlcat(filename, "/", sizeof(filename));
+ strlcat(filename, attr, sizeof(filename));
+ }
+ }
+
match = (stat(filename, &statbuf) == 0);
info("'%s' %s", filename, match ? "exists" : "does not exist");
if (match && rule->test_mode_mask > 0) {
pair->key.operation == KEY_OP_NOMATCH) {
const char *key_name = key_pair_name(rule, pair);
const char *key_value = key_val(rule, &pair->key);
- const char *value;
+ char devpath[PATH_SIZE];
+ char *attrib;
+ const char *value = NULL;
char val[VALUE_SIZE];
size_t len;
- value = sysfs_attr_get_value(udev->dev->devpath, key_name);
+ if (attr_get_by_subsys_id(key_name, devpath, sizeof(devpath), &attrib)) {
+ if (attrib != NULL)
+ value = sysfs_attr_get_value(devpath, attrib);
+ else
+ goto nomatch;
+ }
+ if (value == NULL)
+ value = sysfs_attr_get_value(udev->dev->devpath, key_name);
if (value == NULL)
goto nomatch;
strlcpy(val, value, sizeof(val));
strlcpy(program, key_val(rule, &rule->program), sizeof(program));
udev_rules_apply_format(udev, program, sizeof(program));
- if (run_program(program, udev->dev->subsystem, result, sizeof(result), NULL, (udev_log_priority >= LOG_INFO)) != 0) {
+ if (run_program(program, udev->dev->subsystem, result, sizeof(result), NULL) != 0) {
dbg("PROGRAM is false");
udev->program_result[0] = '\0';
if (rule->program.operation != KEY_OP_NOMATCH)
dbg("PROGRAM matches");
remove_trailing_chars(result, '\n');
- count = replace_chars(result, ALLOWED_CHARS_INPUT);
- if (count)
- info("%i character(s) replaced" , count);
+ if (rule->string_escape == ESCAPE_UNSET ||
+ rule->string_escape == ESCAPE_REPLACE) {
+ count = replace_chars(result, ALLOWED_CHARS_INPUT);
+ if (count > 0)
+ info("%i character(s) replaced" , count);
+ }
dbg("result is '%s'", result);
strlcpy(udev->program_result, result, sizeof(udev->program_result));
dbg("PROGRAM returned successful");
unsetenv(key_name);
info("unset ENV '%s'", key_name);
} else {
- char *key_value = name_list_key_add(&udev->env_list, key_name, temp_value);
+ struct name_entry *entry;
- if (key_value == NULL)
+ entry = name_list_key_add(&udev->env_list, key_name, temp_value);
+ if (entry == NULL)
break;
- putenv(key_value);
- info("set ENV '%s'", key_value);
+ putenv(entry->name);
+ info("set ENV '%s'", entry->name);
}
}
}
if (pair->key.operation == KEY_OP_ASSIGN) {
const char *key_name = key_pair_name(rule, pair);
- char attr[PATH_SIZE];
+ char devpath[PATH_SIZE];
+ char *attrib;
+ char attr[PATH_SIZE] = "";
char value[NAME_SIZE];
FILE *f;
- strlcpy(attr, sysfs_path, sizeof(attr));
- strlcat(attr, udev->dev->devpath, sizeof(attr));
- strlcat(attr, "/", sizeof(attr));
- strlcat(attr, key_name, sizeof(attr));
+ if (attr_get_by_subsys_id(key_name, devpath, sizeof(devpath), &attrib)) {
+ if (attrib != NULL) {
+ strlcpy(attr, sysfs_path, sizeof(attr));
+ strlcat(attr, devpath, sizeof(attr));
+ strlcat(attr, "/", sizeof(attr));
+ strlcat(attr, attrib, sizeof(attr));
+ }
+ }
+
+ if (attr[0] == '\0') {
+ strlcpy(attr, sysfs_path, sizeof(attr));
+ strlcat(attr, udev->dev->devpath, sizeof(attr));
+ strlcat(attr, "/", sizeof(attr));
+ strlcat(attr, key_name, sizeof(attr));
+ }
+
strlcpy(value, key_val(rule, &pair->key), sizeof(value));
udev_rules_apply_format(udev, value, sizeof(value));
info("writing '%s' to sysfs file '%s'", value, attr);
/* allow multiple symlinks separated by spaces */
strlcpy(temp, key_val(rule, &rule->symlink), sizeof(temp));
udev_rules_apply_format(udev, temp, sizeof(temp));
- count = replace_chars(temp, ALLOWED_CHARS_FILE " ");
- if (count)
- info("%i character(s) replaced" , count);
+ if (rule->string_escape == ESCAPE_UNSET ||
+ rule->string_escape == ESCAPE_REPLACE) {
+ count = replace_chars(temp, ALLOWED_CHARS_FILE " ");
+ if (count > 0)
+ info("%i character(s) replaced" , count);
+ }
dbg("rule applied, added symlink(s) '%s'", temp);
pos = temp;
while (isspace(pos[0]))
name_set = 1;
strlcpy(udev->name, key_val(rule, &rule->name), sizeof(udev->name));
udev_rules_apply_format(udev, udev->name, sizeof(udev->name));
- count = replace_chars(udev->name, ALLOWED_CHARS_FILE);
- if (count)
- info("%i character(s) replaced", count);
+ if (rule->string_escape == ESCAPE_UNSET ||
+ rule->string_escape == ESCAPE_REPLACE) {
+ count = replace_chars(udev->name, ALLOWED_CHARS_FILE);
+ if (count > 0)
+ info("%i character(s) replaced", count);
+ }
info("rule applied, '%s' becomes '%s'", udev->dev->kernel, udev->name);
if (strcmp(udev->dev->subsystem, "net") != 0)
}
if (!udev->run_final && rule->run.operation != KEY_OP_UNSET) {
+ struct name_entry *entry;
+
if (rule->run.operation == KEY_OP_ASSIGN_FINAL)
udev->run_final = 1;
if (rule->run.operation == KEY_OP_ASSIGN || rule->run.operation == KEY_OP_ASSIGN_FINAL) {
name_list_cleanup(&udev->run_list);
}
dbg("add run '%s'", key_val(rule, &rule->run));
- name_list_add(&udev->run_list, key_val(rule, &rule->run), 0);
+ entry = name_list_add(&udev->run_list, key_val(rule, &rule->run), 0);
+ if (rule->run_ignore_error)
+ entry->ignore_error = 1;
}
if (rule->last_rule) {
}
if (!udev->run_final && rule->run.operation != KEY_OP_UNSET) {
+ struct name_entry *entry;
+
if (rule->run.operation == KEY_OP_ASSIGN ||
rule->run.operation == KEY_OP_ASSIGN_FINAL) {
info("reset run list");
name_list_cleanup(&udev->run_list);
}
dbg("add run '%s'", key_val(rule, &rule->run));
- name_list_add(&udev->run_list, key_val(rule, &rule->run), 0);
+ entry = name_list_add(&udev->run_list, key_val(rule, &rule->run), 0);
+ if (rule->run_ignore_error)
+ entry->ignore_error = 1;
if (rule->run.operation == KEY_OP_ASSIGN_FINAL)
break;
}