diff options
author | kay.sievers@vrfy.org <kay.sievers@vrfy.org> | 2003-12-03 06:22:53 -0800 |
---|---|---|
committer | Greg KH <gregkh@suse.de> | 2005-04-26 21:13:05 -0700 |
commit | 9f1da3613897346b6a45e1f7a706d2315bc0f420 (patch) | |
tree | fceae25269b8a8b2ffe19c74700a9166e0810197 | |
parent | 4865de442901cefebb7be889aa61233d8777b413 (diff) |
[PATCH] pattern matching for namedev
As promised yesterday, here is a patch to implement a more advanced
pattern matching instead of the simple '*'.
We can remove the "tty"="tty" line from udev.rules now and
replace "tty*" by "tty[0-9]*" to catch only the vc's.
implement pattern matching in namedev
'*' - to match zero or more chars
'?' - to match exactly one char
'[]' - character classes with ranges '[0-9]'and negation [!A]
-rw-r--r-- | namedev.c | 67 | ||||
-rw-r--r-- | test/udev-test.pl | 26 |
2 files changed, 77 insertions, 16 deletions
@@ -40,17 +40,56 @@ LIST_HEAD(config_device_list); -/* s2 may end with '*' to match everything */ -static int strncmp_wildcard(char *s1, char *s2, int max) +/* compare string with pattern (supports * ? [0-9] [!A-Z]) */ +static int strcmp_pattern(const char *p, const char *s) { - int len = strlen(s2); - if (len > max) - len = max; - if (s2[len-1] == '*') - len--; - else - len = max; - return strncmp(s1, s2, len); + if (*s == '\0') { + while (*p == '*') + p++; + return (*p != '\0'); + } + switch (*p) { + case '[': + { + int not = 0; + p++; + if (*p == '!') { + not = 1; + p++; + } + while (*p && (*p != ']')) { + int match = 0; + if (p[1] == '-') { + if ((*s >= *p) && (*s <= p[2])) + match = 1; + p += 3; + } else { + match = (*p == *s); + p++; + } + if (match ^ not) { + while (*p && (*p != ']')) + p++; + return strcmp_pattern(p+1, s+1); + } + } + } + break; + case '*': + if (strcmp_pattern(p, s+1)) + return strcmp_pattern(p+1, s); + return 0; + case '\0': + if (*s == '\0') { + return 0; + } + break; + default: + if ((*p == *s) || (*p == '?')) + return strcmp_pattern(p+1, s+1); + break; + } + return 1; } #define copy_var(a, b, var) \ @@ -69,7 +108,7 @@ int add_config_dev(struct config_device *new_dev) /* update the values if we already have the device */ list_for_each(tmp, &config_device_list) { struct config_device *dev = list_entry(tmp, struct config_device, node); - if (strncmp_wildcard(dev->name, new_dev->name, sizeof(dev->name))) + if (strcmp_pattern(new_dev->name, dev->name)) continue; if (strncmp(dev->bus, new_dev->bus, sizeof(dev->name))) continue; @@ -282,7 +321,7 @@ static int do_callout(struct sysfs_class_device *class_dev, struct udevice *udev apply_format(udev, dev->exec_program); if (exec_callout(dev, udev->callout_value, NAME_SIZE)) continue; - if (strncmp_wildcard(udev->callout_value, dev->id, NAME_SIZE) != 0) + if (strcmp_pattern(dev->id, udev->callout_value) != 0) continue; strfieldcpy(udev->name, dev->name); if (dev->mode != 0) { @@ -468,7 +507,7 @@ static int do_replace(struct sysfs_class_device *class_dev, struct udevice *udev continue; dbg("compare name '%s' with '%s'", dev->kernel_name, class_dev->name); - if (strncmp_wildcard(class_dev->name, dev->kernel_name, NAME_SIZE) != 0) + if (strcmp_pattern(dev->kernel_name, class_dev->name) != 0) continue; strfieldcpy(udev->name, dev->name); @@ -498,7 +537,7 @@ static void do_kernelname(struct sysfs_class_device *class_dev, struct udevice * list_for_each(tmp, &config_device_list) { dev = list_entry(tmp, struct config_device, node); len = strlen(dev->name); - if (strncmp_wildcard(class_dev->name, dev->name, sizeof(dev->name))) + if (strcmp_pattern(dev->name, class_dev->name)) continue; if (dev->mode != 0) { dbg("found permissions for '%s'", class_dev->name); diff --git a/test/udev-test.pl b/test/udev-test.pl index 8af09a027b..47190f6e5d 100644 --- a/test/udev-test.pl +++ b/test/udev-test.pl @@ -51,7 +51,7 @@ LABEL, BUS="scsi", vendor="IBM-ESXS", NAME="boot_disk%n" EOF }, { - desc => "catch device by wildcard", + desc => "catch device by *", subsys => "tty", devpath => "class/tty/ttyUSB0", expected => "visor/0" , @@ -60,6 +60,28 @@ REPLACE, KERNEL="ttyUSB*", NAME="visor/%n" EOF }, { + desc => "catch device by ?", + subsys => "tty", + devpath => "class/tty/ttyUSB0", + expected => "visor/0" , + conf => <<EOF +REPLACE, KERNEL="ttyUSB??*", NAME="visor/%n-1" +REPLACE, KERNEL="ttyUSB??", NAME="visor/%n-2" +REPLACE, KERNEL="ttyUSB?", NAME="visor/%n" +EOF + }, + { + desc => "catch device by character class", + subsys => "tty", + devpath => "class/tty/ttyUSB0", + expected => "visor/0" , + conf => <<EOF +REPLACE, KERNEL="ttyUSB[A-Z]*", NAME="visor/%n-1" +REPLACE, KERNEL="ttyUSB?[0-9]", NAME="visor/%n-2" +REPLACE, KERNEL="ttyUSB[0-9]*", NAME="visor/%n" +EOF + }, + { desc => "replace kernel name", subsys => "tty", devpath => "class/tty/ttyUSB0", @@ -96,7 +118,7 @@ TOPOLOGY, BUS="scsi", PLACE="0:0:0:0", NAME="Major:%M:minor:%m:kernelnumber:%n:b EOF }, { - desc => "callout result substitution, only last should match", + desc => "callout result substitution", subsys => "block", devpath => "block/sda/sda3", expected => "special-device-3" , |