mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-22 13:33:56 +03:00
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:
parent
ac528431dd
commit
eef5447934
@ -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
|
||||
},
|
||||
{
|
||||
|
56
udev_rules.c
56
udev_rules.c
@ -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];
|
||||
|
||||
|
56
udev_sysfs.c
56
udev_sysfs.c
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user