if (reformat_serial)
format_serial(serial);
if (display_bus_id)
- printf("%s: ", dev_scsi->kernel_name);
+ printf("%s: ", dev_scsi->kernel);
printf("%s\n", serial);
}
dbg("%s\n", serial);
sb_len = io->sb_len_wr;
if (sb_len < 1) {
- info("%s: sense buffer empty", dev_scsi->kernel_name);
+ info("%s: sense buffer empty", dev_scsi->kernel);
return -1;
}
s = sense_buffer[7] + 8;
if (sb_len < s) {
info("%s: sense buffer too small %d bytes, %d bytes too short",
- dev_scsi->kernel_name, sb_len, s - sb_len);
+ dev_scsi->kernel, sb_len, s - sb_len);
return -1;
}
if ((code == 0x0) || (code == 0x1)) {
* Possible?
*/
info("%s: sense result too" " small %d bytes",
- dev_scsi->kernel_name, s);
+ dev_scsi->kernel, s);
return -1;
}
asc = sense_buffer[12];
ascq = sense_buffer[3];
} else {
info("%s: invalid sense code 0x%x",
- dev_scsi->kernel_name, code);
+ dev_scsi->kernel, code);
return -1;
}
info("%s: sense key 0x%x ASC 0x%x ASCQ 0x%x",
- dev_scsi->kernel_name, sense_key, asc, ascq);
+ dev_scsi->kernel, sense_key, asc, ascq);
} else {
if (sb_len < 4) {
info("%s: sense buffer too small %d bytes, %d bytes too short",
- dev_scsi->kernel_name, sb_len, 4 - sb_len);
+ dev_scsi->kernel, sb_len, 4 - sb_len);
return -1;
}
if (sense_buffer[0] < 15)
- info("%s: old sense key: 0x%x", dev_scsi->kernel_name, sense_buffer[0] & 0x0f);
+ info("%s: old sense key: 0x%x", dev_scsi->kernel, sense_buffer[0] & 0x0f);
else
info("%s: sense = %2x %2x",
- dev_scsi->kernel_name, sense_buffer[0], sense_buffer[2]);
+ dev_scsi->kernel, sense_buffer[0], sense_buffer[2]);
info("%s: non-extended sense class %d code 0x%0x",
- dev_scsi->kernel_name, sense_class, code);
+ dev_scsi->kernel, sense_class, code);
}
out_buffer[j++] = ' ';
}
out_buffer[j] = '\0';
- info("%s: sense dump:", dev_scsi->kernel_name);
- info("%s: %s", dev_scsi->kernel_name, out_buffer);
+ info("%s: sense dump:", dev_scsi->kernel);
+ info("%s: %s", dev_scsi->kernel, out_buffer);
#endif
return -1;
}
info("%s: sg_io failed status 0x%x 0x%x 0x%x 0x%x",
- dev_scsi->kernel_name, io->driver_status, io->host_status, io->msg_status, io->status);
+ dev_scsi->kernel, io->driver_status, io->host_status, io->msg_status, io->status);
if (io->status == SCSI_CHECK_CONDITION)
return scsi_dump_sense(dev_scsi, io);
else
}
resend:
- dbg("%s evpd %d, page 0x%x\n", dev_scsi->kernel_name, evpd, page);
+ dbg("%s evpd %d, page 0x%x\n", dev_scsi->kernel, evpd, page);
memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
io_hdr.interface_id = 'S';
io_hdr.timeout = DEF_TIMEOUT;
if (ioctl(fd, SG_IO, &io_hdr) < 0) {
- info("%s: ioctl failed: %s", dev_scsi->kernel_name, strerror(errno));
+ info("%s: ioctl failed: %s", dev_scsi->kernel, strerror(errno));
retval = -1;
goto error;
}
retval = buflen;
} else if (retval > 0) {
if (--retry > 0) {
- dbg("%s: Retrying ...\n", dev_scsi->kernel_name);
+ dbg("%s: Retrying ...\n", dev_scsi->kernel);
goto resend;
}
retval = -1;
error:
if (retval < 0)
info("%s: Unable to get INQUIRY vpd %d page 0x%x.",
- dev_scsi->kernel_name, evpd, page);
+ dev_scsi->kernel, evpd, page);
return retval;
}
return 1;
if (buffer[1] != 0) {
- info("%s: page 0 not available.", dev_scsi->kernel_name);
+ info("%s: page 0 not available.", dev_scsi->kernel);
return 1;
}
if (buffer[3] > len) {
- info("%s: page 0 buffer too long %d", dev_scsi->kernel_name, buffer[3]);
+ info("%s: page 0 buffer too long %d", dev_scsi->kernel, buffer[3]);
return 1;
}
*/
vendor = sysfs_attr_get_value(dev_scsi->devpath, "vendor");
if (!vendor) {
- info("%s: cannot get model attribute", dev_scsi->kernel_name);
+ info("%s: cannot get model attribute", dev_scsi->kernel);
return 1;
}
if (!strncmp((char *)&buffer[VENDOR_LENGTH], vendor, VENDOR_LENGTH)) {
- info("%s: invalid page0 data", dev_scsi->kernel_name);
+ info("%s: invalid page0 data", dev_scsi->kernel);
return 1;
}
}
attr = sysfs_attr_get_value(dev_scsi->devpath, "vendor");
if (!attr) {
- info("%s: cannot get vendor attribute", dev_scsi->kernel_name);
+ info("%s: cannot get vendor attribute", dev_scsi->kernel);
return 1;
}
strncpy(serial, attr, VENDOR_LENGTH);
attr = sysfs_attr_get_value(dev_scsi->devpath, "model");
if (!attr) {
- info("%s: cannot get model attribute", dev_scsi->kernel_name);
+ info("%s: cannot get model attribute", dev_scsi->kernel);
return 1;
}
strncat(serial, attr, MODEL_LENGTH);
*/
if (ind != (VENDOR_LENGTH + MODEL_LENGTH)) {
info("%s: expected length %d, got length %d",
- dev_scsi->kernel_name, (VENDOR_LENGTH + MODEL_LENGTH), ind);
+ dev_scsi->kernel, (VENDOR_LENGTH + MODEL_LENGTH), ind);
return 1;
}
return ind;
if (max_len < len) {
info("%s: length %d too short - need %d",
- dev_scsi->kernel_name, max_len, len);
+ dev_scsi->kernel, max_len, len);
return 1;
}
serial[j++] = hex_str[(page_83[4+i] & 0xf0) >> 4];
serial[j++] = hex_str[ page_83[4+i] & 0x0f];
}
- dbg("using pre-spc3-83 for %s.\n", dev_scsi->kernel_name);
+ dbg("using pre-spc3-83 for %s.\n", dev_scsi->kernel);
return 0;
}
return 1;
if (page_83[1] != PAGE_83) {
- info("%s: Invalid page 0x83", dev_scsi->kernel_name);
+ info("%s: Invalid page 0x83", dev_scsi->kernel);
return 1;
}
retval = check_fill_0x83_id(dev_scsi, &page_83[j],
&id_search_list[id_ind],
serial, len);
- dbg("%s id desc %d/%d/%d\n", dev_scsi->kernel_name,
+ dbg("%s id desc %d/%d/%d\n", dev_scsi->kernel,
id_search_list[id_ind].id_type,
id_search_list[id_ind].naa_type,
id_search_list[id_ind].code_set);
return 1;
if (page_83[1] != PAGE_83) {
- info("%s: Invalid page 0x83", dev_scsi->kernel_name);
+ info("%s: Invalid page 0x83", dev_scsi->kernel);
return 1;
}
/*
serial[j++] = hex_str[page_83[i] & 0x0f];
i++;
}
- dbg("using pre-spc3-83 for %s.\n", dev_scsi->kernel_name);
+ dbg("using pre-spc3-83 for %s.\n", dev_scsi->kernel);
return 0;
}
return retval;
if (buf[1] != PAGE_80) {
- info("%s: Invalid page 0x80", dev_scsi->kernel_name);
+ info("%s: Invalid page 0x80", dev_scsi->kernel);
return 1;
}
len = 1 + VENDOR_LENGTH + MODEL_LENGTH + buf[3];
if (max_len < len) {
info("%s: length %d too short - need %d",
- dev_scsi->kernel_name, max_len, len);
+ dev_scsi->kernel, max_len, len);
return 1;
}
/*
fd = open(devname, O_RDONLY | O_NONBLOCK);
if (fd < 0) {
info("%s: cannot open %s: %s",
- dev_scsi->kernel_name, devname, strerror(errno));
+ dev_scsi->kernel, devname, strerror(errno));
return 1;
}
goto completed;
}
} else if (page_code != 0x00) {
- info("%s: unsupported page code 0x%d", dev_scsi->kernel_name, page_code);
+ info("%s: unsupported page code 0x%d", dev_scsi->kernel, page_code);
return 1;
}
goto completed;
}
- dbg("%s: Checking page0\n", dev_scsi->kernel_name);
+ dbg("%s: Checking page0\n", dev_scsi->kernel);
for (ind = 4; ind <= page0[3] + 3; ind++)
if (page0[ind] == PAGE_83)
retval = 1;
completed:
if (close(fd) < 0)
- info("%s: close failed: %s", dev_scsi->kernel_name, strerror(errno));
+ info("%s: close failed: %s", dev_scsi->kernel, strerror(errno));
return retval;
}
if_class = sysfs_attr_get_value(dev_interface->devpath, "bInterfaceClass");
if (!if_class) {
- info("%s: cannot get bInterfaceClass attribute", dev_interface->kernel_name);
+ info("%s: cannot get bInterfaceClass attribute", dev_interface->kernel);
return 1;
}
if_class_num = strtoul(if_class, NULL, 16);
/* Generic SPC-2 device */
scsi_vendor = sysfs_attr_get_value(dev_scsi->devpath, "vendor");
if (!scsi_vendor) {
- info("%s: cannot get SCSI vendor attribute", dev_scsi->kernel_name);
+ info("%s: cannot get SCSI vendor attribute", dev_scsi->kernel);
goto fallback;
}
set_str(vendor_str, scsi_vendor, sizeof(vendor_str)-1);
scsi_model = sysfs_attr_get_value(dev_scsi->devpath, "model");
if (!scsi_model) {
- info("%s: cannot get SCSI model attribute", dev_scsi->kernel_name);
+ info("%s: cannot get SCSI model attribute", dev_scsi->kernel);
goto fallback;
}
set_str(model_str, scsi_model, sizeof(model_str)-1);
scsi_type = sysfs_attr_get_value(dev_scsi->devpath, "type");
if (!scsi_type) {
- info("%s: cannot get SCSI type attribute", dev_scsi->kernel_name);
+ info("%s: cannot get SCSI type attribute", dev_scsi->kernel);
goto fallback;
}
set_scsi_type(type_str, scsi_type, sizeof(type_str)-1);
scsi_rev = sysfs_attr_get_value(dev_scsi->devpath, "rev");
if (!scsi_rev) {
- info("%s: cannot get SCSI revision attribute", dev_scsi->kernel_name);
+ info("%s: cannot get SCSI revision attribute", dev_scsi->kernel);
goto fallback;
}
set_str(revision_str, scsi_rev, sizeof(revision_str)-1);
EOF
},
{
- desc => "DRIVER match test",
+ desc => "DRIVERS match test",
subsys => "block",
devpath => "/block/sda",
exp_name => "node",
rules => <<EOF
-BUS=="scsi", KERNEL=="sda", NAME="should_not_match", DRIVER=="sd-wrong"
-BUS=="scsi", KERNEL=="sda", NAME="node", DRIVER=="sd"
+BUS=="scsi", KERNEL=="sda", NAME="should_not_match", DRIVERS=="sd-wrong"
+BUS=="scsi", KERNEL=="sda", NAME="node", DRIVERS=="sd"
EOF
},
{
\fBACTION\fR
Match the name of the event action.
.TP 3n
-\fBKERNEL\fR
-Match the name of the device.
-.TP 3n
\fBDEVPATH\fR
-Match the devpath of the device.
+Match the devpath of the event device.
+.TP 3n
+\fBKERNEL\fR
+Match the name of the event device.
.TP 3n
\fBSUBSYSTEM\fR
-Match the subsystem of the device.
+Match the subsystem of the event device.
+.TP 3n
+\fBATTR{\fR\fB\fIfilename\fR\fR\fB}\fR
+Match sysfs attribute values of the event device. Up to five
+\fBATTR\fR
+keys can be specified per rule. Trailing whitespace in the attribute values is ignored, if the specified match value does not contain trailing whitespace itself.
.TP 3n
-\fBBUS\fR
+\fBKERNELS\fR
+Search the devpath upwards for a matching device name.
+.TP 3n
+\fBSUBSYSTEMS\fR
Search the devpath upwards for a matching device subsystem name.
.TP 3n
-\fBDRIVER\fR
+\fBDRIVERS\fR
Search the devpath upwards for a matching device driver name.
.TP 3n
-\fBID\fR
-Search the devpath upwards for a matching device name.
-.TP 3n
-\fBSYSFS{\fR\fB\fIfilename\fR\fR\fB}\fR
+\fBATTRS{\fR\fB\fIfilename\fR\fR\fB}\fR
Search the devpath upwards for a device with matching sysfs attribute values. Up to five
-\fBSYSFS\fR
+\fBATTRS\fR
keys can be specified per rule. All attributes must match on the same device. Trailing whitespace in the attribute values is ignored, if the specified match value does not contain trailing whitespace itself.
.TP 3n
\fBENV{\fR\fB\fIkey\fR\fR\fB}\fR
.TP 3n
\fB$id\fR, \fB%b\fR
The name of the device matched while searching the devpath upwards for
-\fBBUS\fR,
-\fBID\fR
-\fBDRIVER\fR
+\fBSUBSYSTEMS\fR,
+\fBKERNELS\fR
+\fBDRIVERS\fR
and
-\fBSYSFS\fR.
+\fBATTRS\fR.
.TP 3n
-\fB$sysfs{\fR\fB\fIfile\fR\fR\fB}\fR, \fB%s{\fR\fB\fIfile\fR\fR\fB}\fR
+\fB$attr{\fR\fB\fIfile\fR\fR\fB}\fR, \fB%s{\fR\fB\fIfile\fR\fR\fB}\fR
The value of a sysfs attribute found at the current or a parent device.
.TP 3n
\fB$env{\fR\fB\fIkey\fR\fR\fB}\fR, \fB%E{\fR\fB\fIkey\fR\fR\fB}\fR
struct list_head node; /* for device cache */
struct sysfs_device *parent; /* already cached parent*/
char devpath[PATH_SIZE];
- char subsystem[NAME_SIZE]; /* $class/$bus/"drivers" */
- char kernel_name[NAME_SIZE]; /* device instance name */
+ char subsystem[NAME_SIZE]; /* $class, $bus, drivers, module */
+ char kernel[NAME_SIZE]; /* device instance name */
char kernel_number[NAME_SIZE];
char driver[NAME_SIZE]; /* device driver name */
};
</varlistentry>
<varlistentry>
- <term><option>KERNEL</option></term>
+ <term><option>DEVPATH</option></term>
<listitem>
- <para>Match the name of the device.</para>
+ <para>Match the devpath of the event device.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>DEVPATH</option></term>
+ <term><option>KERNEL</option></term>
<listitem>
- <para>Match the devpath of the device.</para>
+ <para>Match the name of the event device.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>SUBSYSTEM</option></term>
<listitem>
- <para>Match the subsystem of the device.</para>
+ <para>Match the subsystem of the event device.</para>
+ </listitem>
+ </varlistentry>
+<!--
+ <varlistentry>
+ <term><option>DRIVER</option></term>
+ <listitem>
+ <para>Match the driver name of the event device. Only set for devices created by a bus driver.</para>
+ </listitem>
+ </varlistentry>
+-->
+ <varlistentry>
+ <term><option>ATTR{<replaceable>filename</replaceable>}</option></term>
+ <listitem>
+ <para>Match sysfs attribute values of the event device. Up to five
+ <option>ATTR</option> keys can be specified per rule. Trailing
+ whitespace in the attribute values is ignored, if the specified match
+ value does not contain trailing whitespace itself.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>BUS</option></term>
+ <term><option>KERNELS</option></term>
<listitem>
- <para>Search the devpath upwards for a matching device subsystem name.</para>
+ <para>Search the devpath upwards for a matching device name.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>DRIVER</option></term>
+ <term><option>SUBSYSTEMS</option></term>
<listitem>
- <para>Search the devpath upwards for a matching device driver name.</para>
+ <para>Search the devpath upwards for a matching device subsystem name.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>ID</option></term>
+ <term><option>DRIVERS</option></term>
<listitem>
- <para>Search the devpath upwards for a matching device name.</para>
+ <para>Search the devpath upwards for a matching device driver name.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>SYSFS{<replaceable>filename</replaceable>}</option></term>
+ <term><option>ATTRS{<replaceable>filename</replaceable>}</option></term>
<listitem>
<para>Search the devpath upwards for a device with matching sysfs attribute values.
- Up to five <option>SYSFS</option> keys can be specified per rule. All attributes
+ Up to five <option>ATTRS</option> keys can be specified per rule. All attributes
must match on the same device. Trailing whitespace in the attribute values is ignored,
if the specified match value does not contain trailing whitespace itself.</para>
</listitem>
<term><option>$id</option>, <option>%b</option></term>
<listitem>
<para>The name of the device matched while searching the devpath upwards for
- <option>BUS</option>, <option>ID</option> <option>DRIVER</option> and <option>SYSFS</option>.
+ <option>SUBSYSTEMS</option>, <option>KERNELS</option> <option>DRIVERS</option> and <option>ATTRS</option>.
</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>$sysfs{<replaceable>file</replaceable>}</option>, <option>%s{<replaceable>file</replaceable>}</option></term>
+ <term><option>$attr{<replaceable>file</replaceable>}</option>, <option>%s{<replaceable>file</replaceable>}</option></term>
<listitem>
<para>The value of a sysfs attribute found at the current or a parent device.</para>
</listitem>
* create only a symlink with the name as the target
* if we don't have any interesting data to remember
*/
- if (strcmp(udev->name, udev->dev->kernel_name) == 0 &&
+ if (strcmp(udev->name, udev->dev->kernel) == 0 &&
list_empty(&udev->symlink_list) && list_empty(&udev->env_list) &&
!udev->partitions && !udev->ignore_remove) {
dbg("nothing interesting to store, create symlink");
struct ifreq ifr;
int retval;
- info("changing net interface name from '%s' to '%s'", udev->dev->kernel_name, udev->name);
+ info("changing net interface name from '%s' to '%s'", udev->dev->kernel, udev->name);
if (udev->test_run)
return 0;
}
memset(&ifr, 0x00, sizeof(struct ifreq));
- strlcpy(ifr.ifr_name, udev->dev->kernel_name, IFNAMSIZ);
+ strlcpy(ifr.ifr_name, udev->dev->kernel, IFNAMSIZ);
strlcpy(ifr.ifr_newname, udev->name, IFNAMSIZ);
retval = ioctl(sk, SIOCSIFNAME, &ifr);
if (retval != 0) {
}
/* free our own name, another process may wait for us */
- strlcpy(ifr.ifr_newname, udev->dev->kernel_name, IFNAMSIZ);
+ strlcpy(ifr.ifr_newname, udev->dev->kernel, IFNAMSIZ);
strlcat(ifr.ifr_newname, "_rename", IFNAMSIZ);
retval = ioctl(sk, SIOCSIFNAME, &ifr);
if (retval != 0) {
}
/* look if we want to change the name of the netif */
- if (strcmp(udev->name, udev->dev->kernel_name) != 0) {
+ if (strcmp(udev->name, udev->dev->kernel) != 0) {
char *pos;
retval = rename_netif(udev);
info("renamed netif to '%s'", udev->name);
/* export old name */
- setenv("INTERFACE_OLD", udev->dev->kernel_name, 1);
+ setenv("INTERFACE_OLD", udev->dev->kernel, 1);
/* now fake the devpath, because the kernel name changed silently */
pos = strrchr(udev->dev->devpath, '/');
if (pos != NULL) {
pos[1] = '\0';
strlcat(udev->dev->devpath, udev->name, sizeof(udev->dev->devpath));
- strlcpy(udev->dev->kernel_name, udev->name, sizeof(udev->dev->kernel_name));
+ strlcpy(udev->dev->kernel, udev->name, sizeof(udev->dev->kernel));
setenv("DEVPATH", udev->dev->devpath, 1);
setenv("INTERFACE", udev->name, 1);
}
list_for_each_entry(name_loop, &udev->env_list, node)
putenv(name_loop->name);
} else {
- dbg("'%s' not found in database, using kernel name '%s'", udev->dev->devpath, udev->dev->kernel_name);
- strlcpy(udev->name, udev->dev->kernel_name, sizeof(udev->name));
+ dbg("'%s' not found in database, using kernel name '%s'", udev->dev->devpath, udev->dev->kernel);
+ strlcpy(udev->name, udev->dev->kernel, sizeof(udev->name));
}
udev_rules_get_run(rules, udev);
/* preserve node with already correct numbers, to prevent changing the inode number */
if ((stats.st_mode & S_IFMT) == (mode & S_IFMT) && (stats.st_rdev == devt)) {
info("preserve file '%s', because it has correct dev_t", file);
- selinux_setfilecon(file, udev->dev->kernel_name, stats.st_mode);
+ selinux_setfilecon(file, udev->dev->kernel, stats.st_mode);
goto perms;
}
dbg("already present file '%s' unlinked", file);
create:
- selinux_setfscreatecon(file, udev->dev->kernel_name, mode);
+ selinux_setfscreatecon(file, udev->dev->kernel, mode);
retval = mknod(file, mode, devt);
selinux_resetfscreatecon();
if (retval != 0) {
enum subst_type {
SUBST_UNKNOWN,
SUBST_DEVPATH,
+ SUBST_KERNEL,
SUBST_KERNEL_NUMBER,
- SUBST_KERNEL_NAME,
SUBST_ID,
SUBST_MAJOR,
SUBST_MINOR,
SUBST_RESULT,
- SUBST_SYSFS,
+ SUBST_ATTR,
SUBST_PARENT,
SUBST_TEMP_NODE,
SUBST_ROOT,
char fmt;
enum subst_type type;
} map[] = {
- { .name = "devpath", .fmt = 'p', .type = SUBST_DEVPATH },
- { .name = "number", .fmt = 'n', .type = SUBST_KERNEL_NUMBER },
- { .name = "kernel", .fmt = 'k', .type = SUBST_KERNEL_NAME },
- { .name = "id", .fmt = 'b', .type = SUBST_ID },
- { .name = "major", .fmt = 'M', .type = SUBST_MAJOR },
- { .name = "minor", .fmt = 'm', .type = SUBST_MINOR },
- { .name = "result", .fmt = 'c', .type = SUBST_RESULT },
- { .name = "sysfs", .fmt = 's', .type = SUBST_SYSFS },
- { .name = "parent", .fmt = 'P', .type = SUBST_PARENT },
- { .name = "tempnode", .fmt = 'N', .type = SUBST_TEMP_NODE },
- { .name = "root", .fmt = 'r', .type = SUBST_ROOT },
- { .name = "env", .fmt = 'E', .type = SUBST_ENV },
+ { .name = "devpath", .fmt = 'p', .type = SUBST_DEVPATH },
+ { .name = "number", .fmt = 'n', .type = SUBST_KERNEL_NUMBER },
+ { .name = "kernel", .fmt = 'k', .type = SUBST_KERNEL },
+ { .name = "id", .fmt = 'b', .type = SUBST_ID },
+ { .name = "major", .fmt = 'M', .type = SUBST_MAJOR },
+ { .name = "minor", .fmt = 'm', .type = SUBST_MINOR },
+ { .name = "result", .fmt = 'c', .type = SUBST_RESULT },
+ { .name = "attr", .fmt = 's', .type = SUBST_ATTR },
+ { .name = "sysfs", .fmt = 's', .type = SUBST_ATTR },
+ { .name = "parent", .fmt = 'P', .type = SUBST_PARENT },
+ { .name = "tempnode", .fmt = 'N', .type = SUBST_TEMP_NODE },
+ { .name = "root", .fmt = 'r', .type = SUBST_ROOT },
+ { .name = "env", .fmt = 'E', .type = SUBST_ENV },
{ NULL, '\0', 0 }
};
enum subst_type type;
strlcat(string, udev->dev->devpath, maxsize);
dbg("substitute devpath '%s'", udev->dev->devpath);
break;
- case SUBST_KERNEL_NAME:
- strlcat(string, udev->dev->kernel_name, maxsize);
- dbg("substitute kernel name '%s'", udev->dev->kernel_name);
+ case SUBST_KERNEL:
+ strlcat(string, udev->dev->kernel, maxsize);
+ dbg("substitute kernel name '%s'", udev->dev->kernel);
break;
case SUBST_KERNEL_NUMBER:
strlcat(string, udev->dev->kernel_number, maxsize);
break;
case SUBST_ID:
if (udev->dev_parent != NULL) {
- strlcat(string, udev->dev_parent->kernel_name, maxsize);
- dbg("substitute id '%s'", udev->dev_parent->kernel_name);
+ strlcat(string, udev->dev_parent->kernel, maxsize);
+ dbg("substitute id '%s'", udev->dev_parent->kernel);
}
break;
case SUBST_MAJOR:
dbg("substitute result string '%s'", udev->program_result);
}
break;
- case SUBST_SYSFS:
+ case SUBST_ATTR:
if (attr == NULL) {
dbg("missing attribute");
break;
if (match_key("ACTION", rule, &rule->action, udev->action))
goto nomatch;
- if (match_key("KERNEL", rule, &rule->kernel_name, udev->dev->kernel_name))
+ if (match_key("KERNEL", rule, &rule->kernel, udev->dev->kernel))
goto nomatch;
if (match_key("SUBSYSTEM", rule, &rule->subsystem, udev->dev->subsystem))
if (match_key("DEVPATH", rule, &rule->devpath, udev->dev->devpath))
goto nomatch;
- /* compare NAME against a previously assigned value */
+ if (match_key("DRIVER", rule, &rule->driver, udev->dev->driver))
+ goto nomatch;
+
+ /* match NAME against a value assigned by an earlier rule */
if (match_key("NAME", rule, &rule->name, udev->name))
goto nomatch;
}
}
+ /* check for matching sysfs attrubute pairs */
+ if (rule->attr.count) {
+ dbg("check %i ATTR keys", rule->attr.count);
+ for (i = 0; i < rule->attr.count; i++) {
+ struct key_pair *pair = &rule->attr.keys[i];
+ const char *key_name = key_pair_name(rule, pair);
+ const char *key_value = key_val(rule, &pair->key);
+ const char *value;
+ char val[VALUE_SIZE];
+ size_t len;
+
+ value = sysfs_attr_get_value(udev->dev->devpath, key_name);
+ if (value == NULL)
+ goto nomatch;
+ strlcpy(val, value, sizeof(val));
+
+ /* strip trailing whitespace of value, if not asked to match for it */
+ len = strlen(key_value);
+ if (len > 0 && !isspace(key_value[len-1])) {
+ len = strlen(val);
+ while (len > 0 && isspace(val[len-1]))
+ val[--len] = '\0';
+ dbg("removed %zi trailing whitespace chars from '%s'", strlen(val)-len, val);
+ }
+
+ if (match_key("ATTR", rule, &pair->key, val))
+ goto nomatch;
+ }
+ dbg("all %i ATTR keys matched", rule->attr.count);
+ }
+
/* walk up the chain of parent devices and find a match */
udev->dev_parent = udev->dev;
while (1) {
- /* check for matching driver */
- if (match_key("DRIVER", rule, &rule->driver, udev->dev_parent->driver))
+ /* check for matching kernel device name */
+ if (match_key("KERNELS", rule, &rule->kernels, udev->dev_parent->kernel))
goto try_parent;
- /* check for matching subsystem/bus value */
- if (match_key("BUS", rule, &rule->bus, udev->dev_parent->subsystem))
+ /* check for matching subsystem value */
+ if (match_key("SUBSYSTEMS", rule, &rule->subsystems, udev->dev_parent->subsystem))
goto try_parent;
- /* check for matching bus id (device name) */
- if (match_key("ID", rule, &rule->id, udev->dev_parent->kernel_name))
+ /* check for matching driver */
+ if (match_key("DRIVERS", rule, &rule->drivers, udev->dev_parent->driver))
goto try_parent;
- /* check for matching sysfs pairs */
- if (rule->sysfs.count) {
- dbg("check %i SYSFS keys", rule->sysfs.count);
- for (i = 0; i < rule->sysfs.count; i++) {
- struct key_pair *pair = &rule->sysfs.keys[i];
+ /* check for matching sysfs attrubute pairs */
+ if (rule->attrs.count) {
+ dbg("check %i ATTRS keys", rule->attrs.count);
+ for (i = 0; i < rule->attrs.count; i++) {
+ struct key_pair *pair = &rule->attrs.keys[i];
const char *key_name = key_pair_name(rule, pair);
const char *key_value = key_val(rule, &pair->key);
const char *value;
dbg("removed %zi trailing whitespace chars from '%s'", strlen(val)-len, val);
}
- if (match_key("SYSFS", rule, &pair->key, val))
+ if (match_key("ATTRS", rule, &pair->key, val))
goto try_parent;
}
- dbg("all %i SYSFS keys matched", rule->sysfs.count);
+ dbg("all %i ATTRS keys matched", rule->attrs.count);
}
/* found matching device */
if (udev->dev_parent == NULL)
goto nomatch;
dbg("looking at dev_parent->devpath='%s'", udev->dev_parent->devpath);
- dbg("looking at dev_parent->bus_kernel_name='%s'", udev->dev_parent->kernel_name);
+ dbg("looking at dev_parent->kernel='%s'", udev->dev_parent->kernel);
}
/* execute external program */
int name_set = 0;
dbg("udev->dev->devpath='%s'", udev->dev->devpath);
- dbg("udev->dev->kernel_name='%s'", udev->dev->kernel_name);
+ dbg("udev->dev->kernel='%s'", udev->dev->kernel);
/* look for a matching rule to apply */
udev_rules_iter_init(rules);
if (match_rule(udev, rule) == 0) {
/* apply options */
if (rule->ignore_device) {
- info("rule applied, '%s' is ignored", udev->dev->kernel_name);
+ info("rule applied, '%s' is ignored", udev->dev->kernel);
udev->ignore_device = 1;
return 0;
}
if (rule->mode_operation == KEY_OP_ASSIGN_FINAL)
udev->mode_final = 1;
udev->mode = rule->mode;
- dbg("applied mode=%#o to '%s'", rule->mode, udev->dev->kernel_name);
+ dbg("applied mode=%#o to '%s'", rule->mode, udev->dev->kernel);
}
if (!udev->owner_final && rule->owner.operation != KEY_OP_UNSET) {
if (rule->owner.operation == KEY_OP_ASSIGN_FINAL)
udev->owner_final = 1;
strlcpy(udev->owner, key_val(rule, &rule->owner), sizeof(udev->owner));
udev_rules_apply_format(udev, udev->owner, sizeof(udev->owner));
- dbg("applied owner='%s' to '%s'", udev->owner, udev->dev->kernel_name);
+ dbg("applied owner='%s' to '%s'", udev->owner, udev->dev->kernel);
}
if (!udev->group_final && rule->group.operation != KEY_OP_UNSET) {
if (rule->group.operation == KEY_OP_ASSIGN_FINAL)
udev->group_final = 1;
strlcpy(udev->group, key_val(rule, &rule->group), sizeof(udev->group));
udev_rules_apply_format(udev, udev->group, sizeof(udev->group));
- dbg("applied group='%s' to '%s'", udev->group, udev->dev->kernel_name);
+ dbg("applied group='%s' to '%s'", udev->group, udev->dev->kernel);
}
/* collect symlinks */
if (count)
info("%i untrusted character(s) replaced", count);
- info("rule applied, '%s' becomes '%s'", udev->dev->kernel_name, udev->name);
+ info("rule applied, '%s' becomes '%s'", udev->dev->kernel, udev->name);
if (strcmp(udev->dev->subsystem, "net") != 0)
dbg("name, '%s' is going to have owner='%s', group='%s', mode=%#o partitions=%i",
udev->name, udev->owner, udev->group, udev->mode, udev->partitions);
}
if (!name_set) {
- strlcpy(udev->name, udev->dev->kernel_name, sizeof(udev->name));
+ strlcpy(udev->name, udev->dev->kernel, sizeof(udev->name));
info("no node name set, will use kernel name '%s'", udev->name);
}
{
struct udev_rule *rule;
- dbg("udev->kernel_name='%s'", udev->dev->kernel_name);
+ dbg("udev->kernel='%s'", udev->dev->kernel);
/* look for a matching rule to apply */
udev_rules_iter_init(rules);
if (match_rule(udev, rule) == 0) {
if (rule->ignore_device) {
- info("rule applied, '%s' is ignored", udev->dev->kernel_name);
+ info("rule applied, '%s' is ignored", udev->dev->kernel);
udev->ignore_device = 1;
return 0;
}
};
struct udev_rule {
- struct key label;
- struct key goto_label;
- struct key kernel_name;
- struct key subsystem;
struct key action;
struct key devpath;
- struct key bus;
- struct key id;
+ struct key kernel;
+ struct key subsystem;
struct key driver;
+ struct key_pairs attr;
+
+ struct key kernels;
+ struct key subsystems;
+ struct key drivers;
+ struct key_pairs attrs;
+
+ struct key_pairs env;
struct key program;
struct key result;
struct key import;
enum import_type import_type;
+ struct key run;
struct key wait_for_sysfs;
- struct key_pairs sysfs;
- struct key_pairs env;
+ struct key label;
+ struct key goto_label;
struct key name;
struct key symlink;
- struct key run;
struct key owner;
struct key group;
- enum key_operation mode_operation;
mode_t mode;
+ enum key_operation mode_operation;
unsigned int partitions;
unsigned int last_rule:1,
if (retval)
break;
- if (strcasecmp(key, "LABEL") == 0) {
- add_rule_key(rule, &rule->label, operation, value);
+ if (strcasecmp(key, "ACTION") == 0) {
+ if (operation != KEY_OP_MATCH &&
+ operation != KEY_OP_NOMATCH) {
+ err("invalid ACTION operation");
+ goto invalid;
+ }
+ add_rule_key(rule, &rule->action, operation, value);
valid = 1;
continue;
}
- if (strcasecmp(key, "GOTO") == 0) {
- add_rule_key(rule, &rule->goto_label, operation, value);
+ if (strcasecmp(key, "DEVPATH") == 0) {
+ if (operation != KEY_OP_MATCH &&
+ operation != KEY_OP_NOMATCH) {
+ err("invalid DEVPATH operation");
+ goto invalid;
+ }
+ add_rule_key(rule, &rule->devpath, operation, value);
valid = 1;
continue;
}
err("invalid KERNEL operation");
goto invalid;
}
- add_rule_key(rule, &rule->kernel_name, operation, value);
+ add_rule_key(rule, &rule->kernel, operation, value);
valid = 1;
continue;
}
continue;
}
- if (strcasecmp(key, "ACTION") == 0) {
+ if (strcasecmp(key, "DRIVER") == 0) {
if (operation != KEY_OP_MATCH &&
operation != KEY_OP_NOMATCH) {
- err("invalid ACTION operation");
+ err("invalid DRIVER operation");
goto invalid;
}
- add_rule_key(rule, &rule->action, operation, value);
+ err("DRIVER== will change in a future relase, "
+ "please use DRIVERS== in %s:%u", filename, lineno);
+ /* FIXME: this should be rule->driver to match only the event device */
+ add_rule_key(rule, &rule->drivers, operation, value);
valid = 1;
continue;
}
- if (strcasecmp(key, "DEVPATH") == 0) {
+ if (strncasecmp(key, "ATTR", sizeof("ATTR")-1) == 0) {
if (operation != KEY_OP_MATCH &&
operation != KEY_OP_NOMATCH) {
- err("invalid DEVPATH operation");
+ err("invalid ATTR operation");
goto invalid;
}
- add_rule_key(rule, &rule->devpath, operation, value);
+ attr = get_key_attribute(key + sizeof("ATTR")-1);
+ if (attr == NULL) {
+ err("error parsing ATTR attribute in '%s'", line);
+ continue;
+ }
+ add_rule_key_pair(rule, &rule->attr, operation, attr, value);
valid = 1;
continue;
}
- if (strcasecmp(key, "BUS") == 0) {
+ if (strcasecmp(key, "KERNELS") == 0 ||
+ strcasecmp(key, "ID") == 0) {
if (operation != KEY_OP_MATCH &&
operation != KEY_OP_NOMATCH) {
- err("invalid BUS operation");
+ err("invalid KERNELS operation");
goto invalid;
}
- add_rule_key(rule, &rule->bus, operation, value);
+ add_rule_key(rule, &rule->kernels, operation, value);
valid = 1;
continue;
}
- if (strcasecmp(key, "ID") == 0) {
+ if (strcasecmp(key, "SUBSYTEMS") == 0 ||
+ strcasecmp(key, "BUS") == 0) {
if (operation != KEY_OP_MATCH &&
operation != KEY_OP_NOMATCH) {
- err("invalid ID operation");
+ err("invalid SUBSYSTEMS operation");
goto invalid;
}
- add_rule_key(rule, &rule->id, operation, value);
+ add_rule_key(rule, &rule->subsystems, operation, value);
valid = 1;
continue;
}
- if (strncasecmp(key, "SYSFS", sizeof("SYSFS")-1) == 0) {
+ if (strcasecmp(key, "DRIVERS") == 0) {
if (operation != KEY_OP_MATCH &&
operation != KEY_OP_NOMATCH) {
- err("invalid SYSFS operation");
+ err("invalid DRIVERS operation");
goto invalid;
}
- attr = get_key_attribute(key + sizeof("SYSFS")-1);
- if (attr == NULL) {
- err("error parsing SYSFS attribute in '%s'", line);
- continue;
- }
- add_rule_key_pair(rule, &rule->sysfs, operation, attr, value);
+ add_rule_key(rule, &rule->drivers, operation, value);
valid = 1;
continue;
}
- if (strcasecmp(key, "WAIT_FOR_SYSFS") == 0) {
- add_rule_key(rule, &rule->wait_for_sysfs, operation, value);
+ if (strncasecmp(key, "ATTRS", sizeof("ATTRS")-1) == 0 ||
+ strncasecmp(key, "SYSFS", sizeof("SYSFS")-1) == 0) {
+ if (operation != KEY_OP_MATCH &&
+ operation != KEY_OP_NOMATCH) {
+ err("invalid ATTRSS operation");
+ goto invalid;
+ }
+ attr = get_key_attribute(key + sizeof("ATTRS")-1);
+ if (attr == NULL) {
+ err("error parsing ATTRS attribute in '%s'", line);
+ continue;
+ }
+ add_rule_key_pair(rule, &rule->attrs, operation, attr, value);
valid = 1;
continue;
}
continue;
}
+ if (strcasecmp(key, "PROGRAM") == 0) {
+ add_rule_key(rule, &rule->program, operation, value);
+ valid = 1;
+ continue;
+ }
+
+ if (strcasecmp(key, "RESULT") == 0) {
+ if (operation != KEY_OP_MATCH &&
+ operation != KEY_OP_NOMATCH) {
+ err("invalid RESULT operation");
+ goto invalid;
+ }
+ add_rule_key(rule, &rule->result, operation, value);
+ valid = 1;
+ continue;
+ }
+
if (strncasecmp(key, "IMPORT", sizeof("IMPORT")-1) == 0) {
attr = get_key_attribute(key + sizeof("IMPORT")-1);
if (attr && strstr(attr, "program")) {
continue;
}
- if (strcasecmp(key, "DRIVER") == 0) {
- if (operation != KEY_OP_MATCH &&
- operation != KEY_OP_NOMATCH) {
- err("invalid DRIVER operation");
- goto invalid;
- }
- add_rule_key(rule, &rule->driver, operation, value);
+ if (strcasecmp(key, "RUN") == 0) {
+ add_rule_key(rule, &rule->run, operation, value);
valid = 1;
continue;
}
- if (strcasecmp(key, "RESULT") == 0) {
- if (operation != KEY_OP_MATCH &&
- operation != KEY_OP_NOMATCH) {
- err("invalid RESULT operation");
- goto invalid;
- }
- add_rule_key(rule, &rule->result, operation, value);
+ if (strcasecmp(key, "WAIT_FOR_SYSFS") == 0) {
+ add_rule_key(rule, &rule->wait_for_sysfs, operation, value);
valid = 1;
continue;
}
- if (strcasecmp(key, "PROGRAM") == 0) {
- add_rule_key(rule, &rule->program, operation, value);
+ if (strcasecmp(key, "LABEL") == 0) {
+ add_rule_key(rule, &rule->label, operation, value);
+ valid = 1;
+ continue;
+ }
+
+ if (strcasecmp(key, "GOTO") == 0) {
+ add_rule_key(rule, &rule->goto_label, operation, value);
valid = 1;
continue;
}
continue;
}
- if (strcasecmp(key, "RUN") == 0) {
- add_rule_key(rule, &rule->run, operation, value);
- valid = 1;
- continue;
- }
-
if (strcasecmp(key, "OPTIONS") == 0) {
if (strstr(value, "last_rule") != NULL) {
dbg("last rule to be applied");
if (pos == NULL)
return;
- strlcpy(dev->kernel_name, &pos[1], sizeof(dev->kernel_name));
- dbg("kernel_name='%s'", dev->kernel_name);
+ strlcpy(dev->kernel, &pos[1], sizeof(dev->kernel));
+ dbg("kernel='%s'", dev->kernel);
/* some devices have '!' in their name, change that to '/' */
- pos = dev->kernel_name;
+ pos = dev->kernel;
while (pos[0] != '\0') {
if (pos[0] == '!')
pos[0] = '/';
}
/* get kernel number */
- pos = &dev->kernel_name[strlen(dev->kernel_name)];
+ pos = &dev->kernel[strlen(dev->kernel)];
while (isdigit(pos[-1]))
pos--;
strlcpy(dev->kernel_number, pos, sizeof(dev->kernel_number));
}
#endif
-static void print_all_attributes(const char *devpath)
+static void print_all_attributes(const char *devpath, const char *key)
{
char path[PATH_SIZE];
DIR *dir;
}
replace_untrusted_chars(value);
- printf(" SYSFS{%s}==\"%s\"\n", dent->d_name, value);
+ printf(" %s{%s}==\"%s\"\n", key, dent->d_name, value);
}
}
printf("\n");
return -1;
printf(" looking at device '%s':\n", dev->devpath);
- printf(" KERNEL==\"%s\"\n", dev->kernel_name);
+ printf(" KERNEL==\"%s\"\n", dev->kernel);
printf(" SUBSYSTEM==\"%s\"\n", dev->subsystem);
printf(" DRIVER==\"%s\"\n", dev->driver);
- print_all_attributes(dev->devpath);
+ print_all_attributes(dev->devpath, "ATTR");
/* walk up the chain of devices */
while (1) {
if (dev == NULL)
break;
printf(" looking at parent device '%s':\n", dev->devpath);
- printf(" ID==\"%s\"\n", dev->kernel_name);
- printf(" BUS==\"%s\"\n", dev->subsystem);
- printf(" DRIVER==\"%s\"\n", dev->driver);
+ printf(" KERNELS==\"%s\"\n", dev->kernel);
+ printf(" SUBSYTEMS==\"%s\"\n", dev->subsystem);
+ printf(" DRIVERS==\"%s\"\n", dev->driver);
- print_all_attributes(dev->devpath);
+ print_all_attributes(dev->devpath, "ATTRS");
}
return 0;