linux-hotplug.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Kay Sievers <kay.sievers@vrfy.org>
To: linux-hotplug@vger.kernel.org
Subject: Re: [udev] don't rely on field order in namedev_parse
Date: Tue, 16 Dec 2003 01:36:25 +0000	[thread overview]
Message-ID: <marc-linux-hotplug-107153877206763@msgid-missing> (raw)
In-Reply-To: <marc-linux-hotplug-107152798528161@msgid-missing>

[-- Attachment #1: Type: text/plain, Size: 919 bytes --]

On Mon, Dec 15, 2003 at 04:27:59PM -0800, Greg KH wrote:
> On Tue, Dec 16, 2003 at 01:21:58AM +0100, Kay Sievers wrote:
> > o prepend SYSFS_ to the match, like:
> >   LABEL, BUS="usb", SYSFS_model="Creative Labs WebCam*", NAME="video%n"
> >   This is my favorite. It's close to the current and says clearly what it does.
> 
> Yeah, I like this one too.

Here is a try.
Please have a look at it.

My motto of the day: Try to attach the patch before hitting the 'y'-key :)

Kay


01-remove-field-ordering.diff
  o change the parsing to get a key from the rule and sort it
    into our list of known keys instead of expecting a special order
  o the key to match a sysfs file must be prependend by 'SYSFS_' now
    to match with the new parsing.
    (The config must be changed, but it's a bit more descriptive too.)
  o put names of fields in define's, like the name of the methods
  o update all tests and the man page


[-- Attachment #2: 01-remove-field-ordering.diff --]
[-- Type: text/plain, Size: 14381 bytes --]

diff -Nru a/namedev.h b/namedev.h
--- a/namedev.h	Tue Dec 16 02:26:49 2003
+++ b/namedev.h	Tue Dec 16 02:26:49 2003
@@ -49,6 +49,16 @@
 #define TYPE_TOPOLOGY	"TOPOLOGY"
 #define TYPE_REPLACE	"REPLACE"
 #define TYPE_CALLOUT	"CALLOUT"
+
+#define FIELD_BUS	"BUS"
+#define FIELD_ID	"ID"
+#define FIELD_SYSFS	"SYSFS_"
+#define FIELD_PLACE	"PLACE"
+#define FIELD_PROGRAM	"PROGRAM"
+#define FIELD_KERNEL	"KERNEL"
+#define FIELD_NAME	"NAME"
+#define FIELD_SYMLINK	"SYMLINK"
+
 #define CALLOUT_MAXARG	8
 
 struct config_device {
diff -Nru a/namedev_parse.c b/namedev_parse.c
--- a/namedev_parse.c	Tue Dec 16 02:26:49 2003
+++ b/namedev_parse.c	Tue Dec 16 02:26:49 2003
@@ -45,7 +45,7 @@
 		return -ENODEV;
 
 	/* eat any whitespace */
-	while (isspace(*string))
+	while (isspace(*string) || *string == ',')
 		++string;
 
 	/* split based on '=' */
@@ -71,19 +71,6 @@
 	return 0;
 }
 
-static int get_value(const char *left, char **orig_string, char **ret_string)
-{
-	int retval;
-	char *left_string;
-
-	retval = get_pair(orig_string, &left_string, ret_string);
-	if (retval)
-		return retval;
-	if (strcasecmp(left_string, left) != 0)
-		return -ENODEV;
-	return 0;
-}
-
 void dump_config_dev(struct config_device *dev)
 {
 	switch (dev->type) {
@@ -169,13 +156,8 @@
 		if (temp == NULL)
 			goto exit;
 		lineno++;
-
 		dbg_parse("read '%s'", temp);
 
-		/* eat the whitespace at the beginning of the line */
-		while (isspace(*temp))
-			++temp;
-
 		/* empty line? */
 		if (*temp == 0x00)
 			continue;
@@ -184,199 +166,160 @@
 		if (*temp == COMMENT_CHARACTER)
 			continue;
 
+		/* eat the whitespace */
+		while (isspace(*temp))
+			++temp;
+
 		memset(&dev, 0x00, sizeof(struct config_device));
 
-		/* parse the line */
+		/* get the method */
 		temp2 = strsep(&temp, ",");
+
 		if (strcasecmp(temp2, TYPE_LABEL) == 0) {
-			/* label type */
 			dev.type = LABEL;
-
-			/* BUS="bus" */
-			retval = get_value("BUS", &temp, &temp3);
-			if (retval)
-				break;
-			strfieldcpy(dev.bus, temp3);
-
-			/* file="value" */
-			temp2 = strsep(&temp, ",");
-			retval = get_pair(&temp, &temp2, &temp3);
-			if (retval)
-				break;
-			strfieldcpy(dev.sysfs_file, temp2);
-			strfieldcpy(dev.sysfs_value, temp3);
-
-			/* NAME="new_name" */
-			temp2 = strsep(&temp, ",");
-			retval = get_value("NAME", &temp, &temp3);
-			if (retval)
-				break;
-			strfieldcpy(dev.name, temp3);
-
-			/* SYMLINK="name" */
-			temp2 = strsep(&temp, ",");
-			retval = get_value("SYMLINK", &temp, &temp3);
-			if (retval == 0)
-				strfieldcpy(dev.symlink, temp3);
-
-			dbg_parse("LABEL name='%s', bus='%s', "
-				  "sysfs_file='%s', sysfs_value='%s', symlink='%s'",
-				  dev.name, dev.bus, dev.sysfs_file,
-				  dev.sysfs_value, dev.symlink);
+			goto keys;
 		}
 
 		if (strcasecmp(temp2, TYPE_NUMBER) == 0) {
-			/* number type */
 			dev.type = NUMBER;
-
-			/* BUS="bus" */
-			retval = get_value("BUS", &temp, &temp3);
-			if (retval)
-				break;
-			strfieldcpy(dev.bus, temp3);
-
-			/* ID="id" */
-			temp2 = strsep(&temp, ",");
-			retval = get_value("ID", &temp, &temp3);
-			if (retval)
-				break;
-			strfieldcpy(dev.id, temp3);
-
-			/* NAME="new_name" */
-			temp2 = strsep(&temp, ",");
-			retval = get_value("NAME", &temp, &temp3);
-			if (retval)
-				break;
-			strfieldcpy(dev.name, temp3);
-
-			/* SYMLINK="name" */
-			temp2 = strsep(&temp, ",");
-			retval = get_value("SYMLINK", &temp, &temp3);
-			if (retval == 0)
-				strfieldcpy(dev.symlink, temp3);
-
-			dbg_parse("NUMBER name='%s', bus='%s', id='%s', symlink='%s'",
-				  dev.name, dev.bus, dev.id, dev.symlink);
+			goto keys;
 		}
 
 		if (strcasecmp(temp2, TYPE_TOPOLOGY) == 0) {
-			/* number type */
 			dev.type = TOPOLOGY;
-
-			/* BUS="bus" */
-			retval = get_value("BUS", &temp, &temp3);
-			if (retval)
-				break;
-			strfieldcpy(dev.bus, temp3);
-
-			/* PLACE="place" */
-			temp2 = strsep(&temp, ",");
-			retval = get_value("PLACE", &temp, &temp3);
-			if (retval)
-				break;
-			strfieldcpy(dev.place, temp3);
-
-			/* NAME="new_name" */
-			temp2 = strsep(&temp, ",");
-			retval = get_value("NAME", &temp, &temp3);
-			if (retval)
-				break;
-			strfieldcpy(dev.name, temp3);
-
-			/* SYMLINK="name" */
-			temp2 = strsep(&temp, ",");
-			retval = get_value("SYMLINK", &temp, &temp3);
-			if (retval == 0)
-				strfieldcpy(dev.symlink, temp3);
-
-			dbg_parse("TOPOLOGY name='%s', bus='%s', "
-				  "place='%s', symlink='%s'",
-				  dev.name, dev.bus, dev.place, dev.symlink);
+			goto keys;
 		}
 
 		if (strcasecmp(temp2, TYPE_REPLACE) == 0) {
-			/* number type */
 			dev.type = REPLACE;
-
-			/* KERNEL="kernel_name" */
-			retval = get_value("KERNEL", &temp, &temp3);
-			if (retval)
-				break;
-			strfieldcpy(dev.kernel_name, temp3);
-
-			/* NAME="new_name" */
-			temp2 = strsep(&temp, ",");
-			retval = get_value("NAME", &temp, &temp3);
-			if (retval)
-				break;
-			strfieldcpy(dev.name, temp3);
-
-			/* SYMLINK="name" */
-			temp2 = strsep(&temp, ",");
-			retval = get_value("SYMLINK", &temp, &temp3);
-			if (retval == 0)
-				strfieldcpy(dev.symlink, temp3);
-
-			dbg_parse("REPLACE name='%s', kernel_name='%s', symlink='%s'",
-				  dev.name, dev.kernel_name, dev.symlink);
+			goto keys;
 		}
 
 		if (strcasecmp(temp2, TYPE_CALLOUT) == 0) {
-			/* number type */
 			dev.type = CALLOUT;
+			goto keys;
+		}
 
-			/* BUS="bus" */
-			retval = get_value("BUS", &temp, &temp3);
-			if (retval)
-				break;
-			strfieldcpy(dev.bus, temp3);
-
-			/* PROGRAM="executable" */
-			temp2 = strsep(&temp, ",");
-			retval = get_value("PROGRAM", &temp, &temp3);
-			if (retval)
-				break;
-			strfieldcpy(dev.exec_program, temp3);
-
-			/* ID="id" */
-			temp2 = strsep(&temp, ",");
-			retval = get_value("ID", &temp, &temp3);
+		dbg_parse("unknown type of method '%s'", temp2);
+		goto error;
+keys:
+		/* get all known keys */
+		while (1) {
+			retval = get_pair(&temp, &temp2, &temp3);
 			if (retval)
 				break;
-			strfieldcpy(dev.id, temp3);
 
-			/* NAME="new_name" */
-			temp2 = strsep(&temp, ",");
-			retval = get_value("NAME", &temp, &temp3);
-			if (retval)
-				break;
-			strfieldcpy(dev.name, temp3);
+			if (strcasecmp(temp2, FIELD_BUS) == 0) {
+				strfieldcpy(dev.bus, temp3);
+				continue;
+			}
+
+			if (strcasecmp(temp2, FIELD_ID) == 0) {
+				strfieldcpy(dev.id, temp3);
+				continue;
+			}
+
+			if (strcasecmp(temp2, FIELD_PLACE) == 0) {
+				strfieldcpy(dev.place, temp3);
+				continue;
+			}
+
+			if (strncasecmp(temp2, FIELD_SYSFS, sizeof(FIELD_SYSFS)-1) == 0) {
+				/* remove prepended 'SYSFS_' */
+				strfieldcpy(dev.sysfs_file, temp2 + sizeof(FIELD_SYSFS)-1);
+				strfieldcpy(dev.sysfs_value, temp3);
+				continue;
+			}
+
+			if (strcasecmp(temp2, FIELD_KERNEL) == 0) {
+				strfieldcpy(dev.kernel_name, temp3);
+				continue;
+			}
+
+			if (strcasecmp(temp2, FIELD_PROGRAM) == 0) {
+				strfieldcpy(dev.exec_program, temp3);
+				continue;
+			}
+
+			if (strcasecmp(temp2, FIELD_NAME) == 0) {
+				strfieldcpy(dev.name, temp3);
+				continue;
+			}
 
-			/* SYMLINK="name" */
-			temp2 = strsep(&temp, ",");
-			retval = get_value("SYMLINK", &temp, &temp3);
-			if (retval == 0)
+			if (strcasecmp(temp2, FIELD_SYMLINK) == 0) {
 				strfieldcpy(dev.symlink, temp3);
+				continue;
+			}
+
+			dbg_parse("unknown type of field '%s'", temp2);
+		}
 
+		/* check presence of keys according to method type */
+		switch (dev.type) {
+		case LABEL:
+			dbg_parse("LABEL name='%s', bus='%s', "
+				  "sysfs_file='%s', sysfs_value='%s', symlink='%s'",
+				  dev.name, dev.bus, dev.sysfs_file,
+				  dev.sysfs_value, dev.symlink);
+			if ((*dev.name == '\0') ||
+			    (*dev.bus == '\0') ||
+			    (*dev.sysfs_file == '\0') ||
+			    (*dev.sysfs_value == '\0'))
+				goto error;
+			break;
+		case NUMBER:
+			dbg_parse("NUMBER name='%s', bus='%s', id='%s', symlink='%s'",
+				  dev.name, dev.bus, dev.id, dev.symlink);
+			if ((*dev.name == '\0') ||
+			    (*dev.bus == '\0') ||
+			    (*dev.id == '\0'))
+				goto error;
+			break;
+		case TOPOLOGY:
+			dbg_parse("TOPOLOGY name='%s', bus='%s', "
+				  "place='%s', symlink='%s'",
+				  dev.name, dev.bus, dev.place, dev.symlink);
+			if ((*dev.name == '\0') ||
+			    (*dev.bus == '\0') ||
+			    (*dev.place == '\0'))
+				goto error;
+			break;
+		case REPLACE:
+			dbg_parse("REPLACE name='%s', kernel_name='%s', symlink='%s'",
+				  dev.name, dev.kernel_name, dev.symlink);
+			if ((*dev.name == '\0') ||
+			    (*dev.kernel_name == '\0'))
+				goto error;
+			break;
+		case CALLOUT:
 			dbg_parse("CALLOUT name='%s', bus='%s', program='%s', "
 				  "id='%s', symlink='%s'",
 				  dev.name, dev.bus, dev.exec_program,
 				  dev.id, dev.symlink);
+			if ((*dev.name == '\0') ||
+			    (*dev.bus == '\0') ||
+			    (*dev.id == '\0') ||
+			    (*dev.exec_program == '\0'))
+				goto error;
+			break;
+		default:
+			dbg_parse("xxx default method");
+			goto error;
 		}
 
 		retval = add_config_dev(&dev);
 		if (retval) {
 			dbg("add_config_dev returned with error %d", retval);
-			goto exit;
+			continue;
 		}
 	}
-	dbg_parse("%s:%d:%Zd: error parsing '%s'", udev_rules_filename,
-		  lineno, temp - line, temp);
+error:
+	dbg_parse("%s:%d:%Zd: field missing or parse error", udev_rules_filename,
+		  lineno, temp - line);
 exit:
 	fclose(fd);
 	return retval;
-}	
-
+}
 
 int namedev_init_permissions(void)
 {
diff -Nru a/test/label_test b/test/label_test
--- a/test/label_test	Tue Dec 16 02:26:49 2003
+++ b/test/label_test	Tue Dec 16 02:26:49 2003
@@ -8,7 +8,7 @@
 export UDEV_CONFIG_FILE=$PWD/$CONFIG
 
 cat > $RULES << EOF
-LABEL, BUS="scsi", vendor="IBM-ESXS", NAME="boot_disk%n"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ESXS", NAME="boot_disk%n"
 EOF
 
 cat > $CONFIG << EOF
diff -Nru a/test/udev-test.pl b/test/udev-test.pl
--- a/test/udev-test.pl	Tue Dec 16 02:26:49 2003
+++ b/test/udev-test.pl	Tue Dec 16 02:26:49 2003
@@ -38,7 +38,7 @@
 		devpath  => "block/sda",
 		expected => "boot_disk" ,
 		conf     => <<EOF
-LABEL, BUS="scsi", vendor="IBM-ESXS", NAME="boot_disk%n"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ESXS", NAME="boot_disk%n"
 REPLACE, KERNEL="ttyUSB0", NAME="visor"
 EOF
 	},
@@ -48,7 +48,7 @@
 		devpath  => "block/sda/sda1",
 		expected => "boot_disk1" ,
 		conf     => <<EOF
-LABEL, BUS="scsi", vendor="IBM-ESXS", NAME="boot_disk%n"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ESXS", NAME="boot_disk%n"
 EOF
 	},
 	{
@@ -57,10 +57,10 @@
 		devpath  => "block/sda/sda1",
 		expected => "boot_disk1" ,
 		conf     => <<EOF
-LABEL, BUS="scsi", vendor="?IBM-ESXS", NAME="boot_disk%n-1"
-LABEL, BUS="scsi", vendor="IBM-ESXS?", NAME="boot_disk%n-2"
-LABEL, BUS="scsi", vendor="IBM-ES??", NAME="boot_disk%n"
-LABEL, BUS="scsi", vendor="IBM-ESXSS", NAME="boot_disk%n-3"
+LABEL, BUS="scsi", SYSFS_vendor="?IBM-ESXS", NAME="boot_disk%n-1"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ESXS?", NAME="boot_disk%n-2"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ES??", NAME="boot_disk%n"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ESXSS", NAME="boot_disk%n-3"
 EOF
 	},
 	{
@@ -167,7 +167,7 @@
 		devpath  => "block/sda",
 		expected => "lun0/disc" ,
 		conf     => <<EOF
-LABEL, BUS="scsi", vendor="IBM-ESXS", NAME="lun0/%D"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ESXS", NAME="lun0/%D"
 EOF
 	},
 	{
@@ -176,7 +176,7 @@
 		devpath  => "block/sda/sda2",
 		expected => "lun0/part2" ,
 		conf     => <<EOF
-LABEL, BUS="scsi", vendor="IBM-ESXS", NAME="lun0/%D"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ESXS", NAME="lun0/%D"
 EOF
 	},
 	{
@@ -205,7 +205,7 @@
 		devpath  => "block/sda/sda2",
 		expected => "1/2/a/b/symlink" ,
 		conf     => <<EOF
-LABEL, BUS="scsi", vendor="IBM-ESXS", NAME="1/2/node", SYMLINK="1/2/a/b/symlink"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ESXS", NAME="1/2/node", SYMLINK="1/2/a/b/symlink"
 EOF
 	},
 	{
@@ -214,7 +214,7 @@
 		devpath  => "block/sda/sda2",
 		expected => "1/2/symlink" ,
 		conf     => <<EOF
-LABEL, BUS="scsi", vendor="IBM-ESXS", NAME="1/2/a/b/node", SYMLINK="1/2/symlink"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ESXS", NAME="1/2/a/b/node", SYMLINK="1/2/symlink"
 EOF
 	},
 	{
@@ -223,7 +223,7 @@
 		devpath  => "block/sda/sda2",
 		expected => "1/2/c/d/symlink" ,
 		conf     => <<EOF
-LABEL, BUS="scsi", vendor="IBM-ESXS", NAME="1/2/a/b/node", SYMLINK="1/2/c/d/symlink"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ESXS", NAME="1/2/a/b/node", SYMLINK="1/2/c/d/symlink"
 EOF
 	},
 	{
diff -Nru a/udev.8 b/udev.8
--- a/udev.8	Tue Dec 16 02:26:49 2003
+++ b/udev.8	Tue Dec 16 02:26:49 2003
@@ -18,7 +18,7 @@
 .B udev
 reads the sysfs directory of the given device to collect device attributes
 like label, serial number or bus device number.
-These attributes are treated as a key 
+These attributes are treated as a key
 to determine a unique name for device file creation.
 .B udev
 maintains a database for devices present on the system.
@@ -87,7 +87,7 @@
 .I /etc/udev/udev.rules
 or specified by the
 .I udev_rules
-value in the 
+value in the
 .I /etc/udev/udev.conf
 file.
 .P
@@ -114,8 +114,7 @@
 device label or serial number, like USB serial number, SCSI UUID or
 file system label
 .br
-.RB "keys: " BUS ", "
-.I sysfs_attribute
+.RB "keys: " BUS ", " SYSFS_
 .TP
 .B NUMBER
 device number on the bus, like PCI bus id
@@ -130,7 +129,7 @@
 .B REPLACE
 string replacement of the kernel device name
 .br
-.RB "key: " KERNEL_NAME
+.RB "key: " KERNEL
 .P
 The methods are applied in the following order:
 .BR CALLOUT ", " LABEL ", " NUMBER ", " TOPOLOGY ", " REPLACE "."
@@ -167,7 +166,7 @@
 CALLOUT, BUS="scsi", PROGRAM="/sbin/scsi_id", ID="OEM 0815", NAME="disk1"
 
 # USB printer to be called lp_color
-LABEL, BUS="usb", serial="W09090207101241330", NAME="lp_color"
+LABEL, BUS="usb", SYSFS_serial="W09090207101241330", NAME="lp_color"
 
 # sound card with PCI bus id 00:0b.0 to be called dsp
 NUMBER, BUS="pci", ID="00:0b.0", NAME="dsp"
diff -Nru a/udev.rules.demo b/udev.rules.demo
--- a/udev.rules.demo	Tue Dec 16 02:26:49 2003
+++ b/udev.rules.demo	Tue Dec 16 02:26:49 2003
@@ -1,8 +1,8 @@
 # USB camera from Fuji to be named "camera"
-LABEL, BUS="usb", vendor="FUJIFILM", NAME="camera%n"
+LABEL, BUS="usb", SYSFS_vendor="FUJIFILM", NAME="camera%n"
 
 # USB device plugged into the fourth port of the second hub to be called gps_device
-TOPOLOGY, BUS="usb", place="2.4", NAME="gps_device"
+TOPOLOGY, BUS="usb", PLACE="2.4", NAME="gps_device"
 
 # ttyUSB1 should always be called visor
 REPLACE, KERNEL="ttyUSB1", NAME="visor"

  parent reply	other threads:[~2003-12-16  1:36 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-12-15 22:36 [udev] don't rely on field order in namedev_parse Greg KH
2003-12-16  0:21 ` Kay Sievers
2003-12-16  0:27 ` Greg KH
2003-12-16  1:36 ` Kay Sievers [this message]
2003-12-16 23:40 ` Greg KH
2003-12-17  0:50 ` Kay Sievers
2003-12-17  0:59 ` Greg KH
2003-12-17 17:04 ` Roman Kagan
2003-12-17 18:26 ` Greg KH
  -- strict thread matches above, loose matches on Subject: below --
2003-12-12 19:36 Kay Sievers

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-107153877206763@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).