chiark / gitweb /
remove old error message
[elogind.git] / udev_rules.c
index 1483f8f4930d50b0d62d2c2a594b1a31f38353c2..c0f4cd2077b1f643898eeb7e9e9a97cda5982413 100644 (file)
@@ -186,7 +186,13 @@ static int import_keys_into_env(struct udevice *udev, const char *buf, size_t bu
                linepos = line;
                if (get_key(&linepos, &variable, &value) == 0) {
                        dbg("import '%s=%s'", variable, value);
-                       name_list_key_add(&udev->env_list, variable, value);
+
+                       /* handle device, renamed by external tool, returning new path */
+                       if (strcmp(variable, "DEVPATH") == 0) {
+                               info("updating devpath from '%s' to '%s'", udev->dev->devpath, value);
+                               sysfs_device_set_values(udev->dev, value, NULL, NULL);
+                       } else
+                               name_list_key_add(&udev->env_list, variable, value);
                        setenv(variable, value, 1);
                }
        }
@@ -364,6 +370,8 @@ void udev_rules_apply_format(struct udevice *udev, char *string, size_t maxsize)
                                                goto found;
                                        }
                                }
+                               head[0] = '$';
+                               err("unknown format variable '%s'", head);
                        } else if (head[0] == '%') {
                                /* substitute format char */
                                if (head[1] == '\0')
@@ -385,6 +393,8 @@ void udev_rules_apply_format(struct udevice *udev, char *string, size_t maxsize)
                                                goto found;
                                        }
                                }
+                               head[0] = '%';
+                               err("unknown format char '%c'", tail[0]);
                        }
                        head++;
                }
@@ -458,30 +468,42 @@ found:
                        }
                        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);
@@ -542,7 +564,7 @@ found:
                        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);
                }
@@ -693,7 +715,7 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule)
                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];
 
@@ -826,18 +848,20 @@ try_parent:
 
                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
@@ -885,6 +909,10 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev)
                                udev->ignore_remove = 1;
                                dbg("remove event should be ignored");
                        }
+                       if (rule->link_priority) {
+                               udev->link_priority = rule->link_priority;
+                               info("link_priority=%i", udev->link_priority);
+                       }
                        /* apply all_partitions option only at a main block device */
                        if (rule->partitions &&
                            strcmp(udev->dev->subsystem, "block") == 0 && udev->dev->kernel_number[0] == '\0') {