goto found;
}
}
+ head[0] = '$';
+ err("unknown format variable '%s'", head);
} else if (head[0] == '%') {
/* substitute format char */
if (head[1] == '\0')
goto found;
}
}
+ head[0] = '%';
+ err("unknown format char '%c'", tail[0]);
}
head++;
}
}
break;
case SUBST_ATTR:
- if (attr == NULL) {
- dbg("missing attribute");
- break;
- } else {
- struct sysfs_device *dev_parent;
- const char *value;
+ if (attr == NULL)
+ err("missing file parameter for attr");
+ else {
+ 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)
+ value = sysfs_attr_get_value(udev->dev_parent->devpath, attr);
+
+ /* look at all devices along the chain of parents */
+ if (value == NULL) {
+ struct sysfs_device *dev_parent = udev->dev;
+
+ do {
+ dbg("looking at '%s'", dev_parent->devpath);
+ value = sysfs_attr_get_value(dev_parent->devpath, attr);
+ if (value != NULL) {
+ strlcpy(temp2, value, sizeof(temp2));
+ break;
+ }
+ dev_parent = sysfs_device_get_parent(dev_parent);
+ } while (dev_parent != NULL);
+ }
- dev_parent = udev->dev;
- do {
- dbg("looking at '%s'", dev_parent->devpath);
- value = sysfs_attr_get_value(dev_parent->devpath, attr);
- if (value != NULL) {
- strlcpy(temp2, value, sizeof(temp2));
- break;
- }
- dev_parent = sysfs_device_get_parent(dev_parent);
- } while (dev_parent != NULL);
+ if (value == NULL)
+ break;
- /* strip trailing whitespace of sysfs value */
- i = strlen(temp2);
- while (i > 0 && isspace(temp2[i-1]))
- temp2[--i] = '\0';
+ /* strip trailing whitespace and replace untrusted characters of sysfs value */
+ size = strlcpy(temp2, value, sizeof(temp2));
+ if (size >= sizeof(temp2))
+ size = sizeof(temp2)-1;
+ while (size > 0 && isspace(temp2[size-1]))
+ temp2[--size] = '\0';
count = replace_untrusted_chars(temp2);
- if (count)
+ if (count > 0)
info("%i untrusted character(s) replaced" , count);
strlcat(string, temp2, maxsize);
dbg("substitute sysfs value '%s'", temp2);
break;
}
/* possibly truncate to format-char specified length */
- if (len != -1) {
+ if (len >= 0 && len < (int)strlen(head)) {
head[len] = '\0';
dbg("truncate to %i chars, subtitution string becomes '%s'", len, head);
}
if (match_key("DRIVERS", rule, &rule->drivers, udev->dev_parent->driver))
goto try_parent;
- /* check for matching sysfs attrubute pairs */
+ /* check for matching sysfs attribute pairs */
for (i = 0; i < rule->attrs.count; i++) {
struct key_pair *pair = &rule->attrs.keys[i];
if (pair->key.operation == KEY_OP_ASSIGN) {
const char *key_name = key_pair_name(rule, pair);
- const char *key_value = key_val(rule, &pair->key);
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));
- dbg("write '%s' to '%s'", key_value, 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);
f = fopen(attr, "w");
if (f != NULL) {
- if (fprintf(f, "%s\n", key_value) <= 0)
+ if (fprintf(f, "%s", value) <= 0)
err("error writing ATTR{%s}: %s", attr, strerror(errno));
fclose(f);
} else