From: Kay Sievers <kay.sievers@vrfy.org>
To: linux-hotplug@vger.kernel.org
Subject: [udev] pattern matching for namedev
Date: Wed, 03 Dec 2003 04:34:35 +0000 [thread overview]
Message-ID: <marc-linux-hotplug-107042613809410@msgid-missing> (raw)
[-- Attachment #1: Type: text/plain, Size: 452 bytes --]
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.
thanks,
Kay
02-the-real-pattern-matching.diff
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]
[-- Attachment #2: 02-the-real-pattern-matching.diff --]
[-- Type: text/plain, Size: 4108 bytes --]
diff -Nru a/namedev.c b/namedev.c
--- a/namedev.c Wed Dec 3 05:12:18 2003
+++ b/namedev.c Wed Dec 3 05:12:18 2003
@@ -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 @@
/* 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 @@
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 @@
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 @@
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 -Nru a/test/udev-test.pl b/test/udev-test.pl
--- a/test/udev-test.pl Wed Dec 3 05:12:18 2003
+++ b/test/udev-test.pl Wed Dec 3 05:12:18 2003
@@ -51,7 +51,7 @@
EOF
},
{
- desc => "catch device by wildcard",
+ desc => "catch device by *",
subsys => "tty",
devpath => "class/tty/ttyUSB0",
expected => "visor/0" ,
@@ -60,6 +60,28 @@
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 @@
EOF
},
{
- desc => "callout result substitution, only last should match",
+ desc => "callout result substitution",
subsys => "block",
devpath => "block/sda/sda3",
expected => "special-device-3" ,
next reply other threads:[~2003-12-03 4:34 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-12-03 4:34 Kay Sievers [this message]
-- strict thread matches above, loose matches on Subject: below --
2003-12-03 6:30 [udev] pattern matching for namedev Greg KH
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=marc-linux-hotplug-107042613809410@msgid-missing \
--to=kay.sievers@vrfy.org \
--cc=linux-hotplug@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.