mirror of
https://github.com/AuxXxilium/eudev.git
synced 2024-12-16 03:27:49 +07:00
[PATCH] don't rely on field order in namedev_parse
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
This commit is contained in:
parent
600ee7f73e
commit
d94df23242
10
namedev.h
10
namedev.h
@ -49,6 +49,16 @@ enum config_type {
|
||||
#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 {
|
||||
|
289
namedev_parse.c
289
namedev_parse.c
@ -45,7 +45,7 @@ int get_pair(char **orig_string, char **left, char **right)
|
||||
return -ENODEV;
|
||||
|
||||
/* eat any whitespace */
|
||||
while (isspace(*string))
|
||||
while (isspace(*string) || *string == ',')
|
||||
++string;
|
||||
|
||||
/* split based on '=' */
|
||||
@ -71,19 +71,6 @@ int get_pair(char **orig_string, char **left, char **right)
|
||||
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 @@ int namedev_init_rules(void)
|
||||
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 @@ int namedev_init_rules(void)
|
||||
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;
|
||||
goto keys;
|
||||
}
|
||||
|
||||
/* BUS="bus" */
|
||||
retval = get_value("BUS", &temp, &temp3);
|
||||
if (retval)
|
||||
break;
|
||||
strfieldcpy(dev.bus, temp3);
|
||||
if (strcasecmp(temp2, TYPE_NUMBER) == 0) {
|
||||
dev.type = NUMBER;
|
||||
goto keys;
|
||||
}
|
||||
|
||||
/* file="value" */
|
||||
temp2 = strsep(&temp, ",");
|
||||
if (strcasecmp(temp2, TYPE_TOPOLOGY) == 0) {
|
||||
dev.type = TOPOLOGY;
|
||||
goto keys;
|
||||
}
|
||||
|
||||
if (strcasecmp(temp2, TYPE_REPLACE) == 0) {
|
||||
dev.type = REPLACE;
|
||||
goto keys;
|
||||
}
|
||||
|
||||
if (strcasecmp(temp2, TYPE_CALLOUT) == 0) {
|
||||
dev.type = CALLOUT;
|
||||
goto keys;
|
||||
}
|
||||
|
||||
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.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);
|
||||
if (strcasecmp(temp2, FIELD_BUS) == 0) {
|
||||
strfieldcpy(dev.bus, temp3);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* SYMLINK="name" */
|
||||
temp2 = strsep(&temp, ",");
|
||||
retval = get_value("SYMLINK", &temp, &temp3);
|
||||
if (retval == 0)
|
||||
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;
|
||||
}
|
||||
|
||||
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 (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);
|
||||
|
||||
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 (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);
|
||||
|
||||
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 (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);
|
||||
|
||||
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 (strcasecmp(temp2, TYPE_CALLOUT) == 0) {
|
||||
/* number type */
|
||||
dev.type = CALLOUT;
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -8,7 +8,7 @@ export SYSFS_PATH=$PWD/sys/
|
||||
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
|
||||
|
@ -38,7 +38,7 @@ my @tests = (
|
||||
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 @@ EOF
|
||||
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 @@ EOF
|
||||
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 @@ EOF
|
||||
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 @@ EOF
|
||||
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 @@ EOF
|
||||
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 @@ EOF
|
||||
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 @@ EOF
|
||||
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
|
||||
},
|
||||
{
|
||||
|
11
udev.8
11
udev.8
@ -18,7 +18,7 @@ On device creation,
|
||||
.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 @@ The rules for udev to use when naming devices may specified at
|
||||
.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 @@ calling external program, that returns a string to match
|
||||
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 @@ device position on bus, like physical port of USB device
|
||||
.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 @@ If this is not a partition, it will result in 'disc'.
|
||||
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"
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user