From 95776dc6ec174f47fa4dd4d8abf5d457223e5dd4 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Sat, 19 Aug 2006 16:06:25 +0200 Subject: [PATCH] consistent key naming to match only the event device or include all parent devices This scheme is more consistent and makes it obvious if a match happens against the event device only, or the full chain of parent devices. The old key names are now: BUS -> SUBSYSTEMS ID -> KERNELS SYSFS -> ATTRS DRIVER -> DRIVERS Match keys for the event device: KERNEL SUBSYSTEM ATTR DRIVER (in a future release, for now the same as DRIVERS) Match keys for all devices along the parent device chain: KERNELS SUBSYSTEMS ATTRS DRIVERS ID, BUS, SYSFS are no longer mentioned in the man page but still work. DRIVER must be converted to DRIVERS to match the new scheme. For now, an error is logged, if DRIVER is used. In a future release, the DRIVER key behaviour will change. --- extras/scsi_id/scsi_id.c | 2 +- extras/scsi_id/scsi_serial.c | 70 +++++++++---------- extras/usb_id/usb_id.c | 10 +-- test/udev-test.pl | 6 +- udev.7 | 39 ++++++----- udev.h | 4 +- udev.xml | 47 +++++++++---- udev_db.c | 2 +- udev_device.c | 16 ++--- udev_node.c | 4 +- udev_rules.c | 125 +++++++++++++++++++++------------ udev_rules.h | 24 ++++--- udev_rules_parse.c | 131 ++++++++++++++++++++++------------- udev_sysfs.c | 8 +-- udevinfo.c | 16 ++--- 15 files changed, 299 insertions(+), 205 deletions(-) diff --git a/extras/scsi_id/scsi_id.c b/extras/scsi_id/scsi_id.c index 446df7094..c64e203af 100644 --- a/extras/scsi_id/scsi_id.c +++ b/extras/scsi_id/scsi_id.c @@ -679,7 +679,7 @@ static int scsi_id(const char *devpath, char *maj_min_dev) 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); diff --git a/extras/scsi_id/scsi_serial.c b/extras/scsi_id/scsi_serial.c index 0ecfebe1b..a0a3ae97d 100644 --- a/extras/scsi_id/scsi_serial.c +++ b/extras/scsi_id/scsi_serial.c @@ -179,7 +179,7 @@ static int scsi_dump_sense(struct sysfs_device *dev_scsi, struct sg_io_hdr *io) 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; } @@ -194,7 +194,7 @@ static int scsi_dump_sense(struct sysfs_device *dev_scsi, struct sg_io_hdr *io) 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)) { @@ -205,7 +205,7 @@ static int scsi_dump_sense(struct sysfs_device *dev_scsi, struct sg_io_hdr *io) * Possible? */ info("%s: sense result too" " small %d bytes", - dev_scsi->kernel_name, s); + dev_scsi->kernel, s); return -1; } asc = sense_buffer[12]; @@ -217,25 +217,25 @@ static int scsi_dump_sense(struct sysfs_device *dev_scsi, struct sg_io_hdr *io) 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); } @@ -247,8 +247,8 @@ static int scsi_dump_sense(struct sysfs_device *dev_scsi, struct sg_io_hdr *io) 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; @@ -266,7 +266,7 @@ static int scsi_dump(struct sysfs_device *dev_scsi, struct sg_io_hdr *io) } 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 @@ -290,7 +290,7 @@ static int scsi_inquiry(struct sysfs_device *dev_scsi, int fd, } 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'; @@ -304,7 +304,7 @@ resend: 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; } @@ -328,7 +328,7 @@ resend: 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; @@ -337,7 +337,7 @@ resend: 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; } @@ -355,11 +355,11 @@ static int do_scsi_page0_inquiry(struct sysfs_device *dev_scsi, int fd, 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; } @@ -377,11 +377,11 @@ static int do_scsi_page0_inquiry(struct sysfs_device *dev_scsi, int fd, */ 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; } } @@ -399,7 +399,7 @@ static int prepend_vendor_model(struct sysfs_device *dev_scsi, char *serial) 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); @@ -407,7 +407,7 @@ static int prepend_vendor_model(struct sysfs_device *dev_scsi, char *serial) 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); @@ -420,7 +420,7 @@ static int prepend_vendor_model(struct sysfs_device *dev_scsi, char *serial) */ 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; @@ -478,7 +478,7 @@ static int check_fill_0x83_id(struct sysfs_device *dev_scsi, 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; } @@ -534,7 +534,7 @@ static int check_fill_0x83_prespc3(struct sysfs_device *dev_scsi, 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; } @@ -554,7 +554,7 @@ static int do_scsi_page83_inquiry(struct sysfs_device *dev_scsi, int fd, 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; } @@ -605,7 +605,7 @@ static int do_scsi_page83_inquiry(struct sysfs_device *dev_scsi, int fd, 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); @@ -643,7 +643,7 @@ static int do_scsi_page83_prespc3_inquiry(struct sysfs_device *dev_scsi, int fd, 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; } /* @@ -687,7 +687,7 @@ static int do_scsi_page83_prespc3_inquiry(struct sysfs_device *dev_scsi, int fd, 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; } @@ -707,14 +707,14 @@ static int do_scsi_page80_inquiry(struct sysfs_device *dev_scsi, int fd, 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; } /* @@ -744,7 +744,7 @@ int scsi_get_serial (struct sysfs_device *dev_scsi, const char *devname, 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; } @@ -790,7 +790,7 @@ int scsi_get_serial (struct sysfs_device *dev_scsi, const char *devname, 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; } @@ -808,7 +808,7 @@ int scsi_get_serial (struct sysfs_device *dev_scsi, const char *devname, 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) @@ -834,6 +834,6 @@ int scsi_get_serial (struct sysfs_device *dev_scsi, const char *devname, 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; } diff --git a/extras/usb_id/usb_id.c b/extras/usb_id/usb_id.c index 85c6beda4..ba8bfdf8c 100644 --- a/extras/usb_id/usb_id.c +++ b/extras/usb_id/usb_id.c @@ -255,7 +255,7 @@ static int usb_id(const char *devpath) 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); @@ -289,28 +289,28 @@ static int usb_id(const char *devpath) /* 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); diff --git a/test/udev-test.pl b/test/udev-test.pl index 63715ac09..c1c5302ca 100755 --- a/test/udev-test.pl +++ b/test/udev-test.pl @@ -1075,13 +1075,13 @@ BUS=="scsi", KERNEL=="sda", NAME="should_not_match2", SUBSYSTEM=="vc" EOF }, { - desc => "DRIVER match test", + desc => "DRIVERS match test", subsys => "block", devpath => "/block/sda", exp_name => "node", rules => < - + - Match the name of the device. + Match the devpath of the event device. - + - Match the devpath of the device. + Match the name of the event device. - Match the subsystem of the device. + Match the subsystem of the event device. + + + + + + + Match sysfs attribute values of the event device. Up to five + 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. - + - Search the devpath upwards for a matching device subsystem name. + Search the devpath upwards for a matching device name. - + - Search the devpath upwards for a matching device driver name. + Search the devpath upwards for a matching device subsystem name. - + - Search the devpath upwards for a matching device name. + Search the devpath upwards for a matching device driver name. - + Search the devpath upwards for a device with matching sysfs attribute values. - Up to five keys can be specified per rule. All attributes + Up to five 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. @@ -378,13 +395,13 @@ , The name of the device matched while searching the devpath upwards for - , and . + , and . - , + , The value of a sysfs attribute found at the current or a parent device. diff --git a/udev_db.c b/udev_db.c index b058351d2..c3034f503 100644 --- a/udev_db.c +++ b/udev_db.c @@ -81,7 +81,7 @@ int udev_db_add_device(struct udevice *udev) * 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"); diff --git a/udev_device.c b/udev_device.c index 87f90c767..b680246bf 100644 --- a/udev_device.c +++ b/udev_device.c @@ -87,7 +87,7 @@ static int rename_netif(struct udevice *udev) 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; @@ -98,7 +98,7 @@ static int rename_netif(struct udevice *udev) } 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) { @@ -111,7 +111,7 @@ static int rename_netif(struct udevice *udev) } /* 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) { @@ -211,7 +211,7 @@ int udev_device_event(struct udev_rules *rules, struct udevice *udev) } /* 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); @@ -220,14 +220,14 @@ int udev_device_event(struct udev_rules *rules, struct udevice *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); } @@ -250,8 +250,8 @@ int udev_device_event(struct udev_rules *rules, struct udevice *udev) 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); diff --git a/udev_node.c b/udev_node.c index 12a738e4e..4ba1c26c5 100644 --- a/udev_node.c +++ b/udev_node.c @@ -51,7 +51,7 @@ int udev_node_mknod(struct udevice *udev, const char *file, dev_t devt, mode_t m /* 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; } @@ -61,7 +61,7 @@ int udev_node_mknod(struct udevice *udev, const char *file, dev_t devt, mode_t m 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) { diff --git a/udev_rules.c b/udev_rules.c index 979b81d82..49306295f 100644 --- a/udev_rules.c +++ b/udev_rules.c @@ -307,13 +307,13 @@ void udev_rules_apply_format(struct udevice *udev, char *string, size_t maxsize) 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, @@ -324,18 +324,19 @@ void udev_rules_apply_format(struct udevice *udev, char *string, size_t maxsize) 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; @@ -399,9 +400,9 @@ found: 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); @@ -409,8 +410,8 @@ found: 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: @@ -457,7 +458,7 @@ found: dbg("substitute result string '%s'", udev->program_result); } break; - case SUBST_SYSFS: + case SUBST_ATTR: if (attr == NULL) { dbg("missing attribute"); break; @@ -605,7 +606,7 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule) 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)) @@ -614,7 +615,10 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule) 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; @@ -646,26 +650,57 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule) } } + /* 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; @@ -688,10 +723,10 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule) 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 */ @@ -703,7 +738,7 @@ try_parent: 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 */ @@ -794,7 +829,7 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev) 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); @@ -815,7 +850,7 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev) 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; } @@ -835,21 +870,21 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev) 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 */ @@ -904,7 +939,7 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev) 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); @@ -934,7 +969,7 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev) } 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); } @@ -951,7 +986,7 @@ int udev_rules_get_run(struct udev_rules *rules, struct udevice *udev) { 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); @@ -969,7 +1004,7 @@ int udev_rules_get_run(struct udev_rules *rules, struct udevice *udev) 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; } diff --git a/udev_rules.h b/udev_rules.h index 2c956fccc..dac0dfcbb 100644 --- a/udev_rules.h +++ b/udev_rules.h @@ -60,30 +60,34 @@ enum import_type { }; 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, diff --git a/udev_rules_parse.c b/udev_rules_parse.c index 8d69e7486..5e93e60d4 100644 --- a/udev_rules_parse.c +++ b/udev_rules_parse.c @@ -263,14 +263,24 @@ static int add_to_rules(struct udev_rules *rules, char *line, const char *filena 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; } @@ -281,7 +291,7 @@ static int add_to_rules(struct udev_rules *rules, char *line, const char *filena 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; } @@ -297,68 +307,84 @@ static int add_to_rules(struct udev_rules *rules, char *line, const char *filena 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; } @@ -374,6 +400,23 @@ static int add_to_rules(struct udev_rules *rules, char *line, const char *filena 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")) { @@ -419,30 +462,26 @@ static int add_to_rules(struct udev_rules *rules, char *line, const char *filena 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; } @@ -516,12 +555,6 @@ static int add_to_rules(struct udev_rules *rules, char *line, const char *filena 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"); diff --git a/udev_sysfs.c b/udev_sysfs.c index 85ea4d15e..c4afe0cff 100644 --- a/udev_sysfs.c +++ b/udev_sysfs.c @@ -95,11 +95,11 @@ void sysfs_device_set_values(struct sysfs_device *dev, const char *devpath, 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] = '/'; @@ -107,7 +107,7 @@ void sysfs_device_set_values(struct sysfs_device *dev, const char *devpath, } /* 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)); diff --git a/udevinfo.c b/udevinfo.c index 1a10f9ad0..d6f564079 100644 --- a/udevinfo.c +++ b/udevinfo.c @@ -45,7 +45,7 @@ void log_message (int priority, const char *format, ...) } #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; @@ -80,7 +80,7 @@ static void print_all_attributes(const char *devpath) } 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"); @@ -103,10 +103,10 @@ static int print_device_chain(const char *devpath) 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) { @@ -114,11 +114,11 @@ static int print_device_chain(const char *devpath) 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; -- 2.30.2