let $attr{symlink} return the last element of the path

Example for /block/sda:
  SUBSYSTEMS="scsi", ENV{COMMENT}="$attr{driver}"
sets COMMENT=sd
  SUBSYSTEMS="pci", ENV{COMMENT}="$attr{driver}"
sets COMMENT=ata_piix
This commit is contained in:
Kay Sievers 2006-09-05 02:18:06 +02:00
parent ac528431dd
commit eef5447934
3 changed files with 92 additions and 38 deletions

View File

@ -579,6 +579,24 @@ EOF
rules => <<EOF
SUBSYSTEMS=="scsi", KERNELS=="*:0:0:0", NAME="scsi-0:0:0:0"
SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", NAME="bad"
EOF
},
{
desc => "substitute attr with link target value (first match)",
subsys => "block",
devpath => "/block/sda",
exp_name => "driver-is-sd",
rules => <<EOF
SUBSYSTEMS=="scsi", NAME="driver-is-\$attr{driver}"
EOF
},
{
desc => "substitute attr with link target value (currently selected device)",
subsys => "block",
devpath => "/block/sda",
exp_name => "driver-is-aic7xxx",
rules => <<EOF
SUBSYSTEMS=="pci", NAME="driver-is-\$attr{driver}"
EOF
},
{

View File

@ -458,30 +458,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;
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);
/* 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);
/* strip trailing whitespace of sysfs value */
i = strlen(temp2);
while (i > 0 && isspace(temp2[i-1]))
temp2[--i] = '\0';
/* 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);
}
if (value == NULL)
break;
/* 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);
@ -693,7 +705,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];

View File

@ -346,6 +346,7 @@ char *sysfs_attr_get_value(const char *devpath, const char *attr_name)
char value[NAME_SIZE];
struct sysfs_attr *attr_loop;
struct sysfs_attr *attr;
struct stat statbuf;
int fd;
ssize_t size;
size_t sysfs_len;
@ -375,25 +376,48 @@ char *sysfs_attr_get_value(const char *devpath, const char *attr_name)
dbg("add to cache '%s'", path_full);
list_add(&attr->node, &attr_list);
/* read attribute value */
fd = open(path_full, O_RDONLY);
if (fd < 0) {
dbg("attribute '%s' does not exist", path_full);
if (lstat(path_full, &statbuf) != 0) {
dbg("stat '%s' failed: %s", path_full, strerror(errno));
goto out;
}
size = read(fd, value, sizeof(value));
close(fd);
if (size < 0)
goto out;
if (size == sizeof(value))
goto out;
/* got a valid value, store and return it */
value[size] = '\0';
remove_trailing_chars(value, '\n');
dbg("cache '%s' with value '%s'", path_full, value);
strlcpy(attr->value_local, value, sizeof(attr->value_local));
attr->value = attr->value_local;
if (S_ISLNK(statbuf.st_mode)) {
/* links return the last element of the target path */
char link_target[PATH_SIZE];
int len;
const char *pos;
len = readlink(path_full, link_target, sizeof(link_target));
if (len > 0) {
link_target[len] = '\0';
pos = strrchr(link_target, '/');
if (pos != NULL) {
dbg("cache '%s' with link value '%s'", path_full, value);
strlcpy(attr->value_local, &pos[1], sizeof(attr->value_local));
attr->value = attr->value_local;
}
}
} else {
/* read attribute value */
fd = open(path_full, O_RDONLY);
if (fd < 0) {
dbg("attribute '%s' does not exist", path_full);
goto out;
}
size = read(fd, value, sizeof(value));
close(fd);
if (size < 0)
goto out;
if (size == sizeof(value))
goto out;
/* got a valid value, store and return it */
value[size] = '\0';
remove_trailing_chars(value, '\n');
dbg("cache '%s' with attribute value '%s'", path_full, value);
strlcpy(attr->value_local, value, sizeof(attr->value_local));
attr->value = attr->value_local;
}
out:
return attr->value;