From: kay.sievers@vrfy.org Date: Tue, 13 Jan 2004 05:39:05 +0000 (-0800) Subject: [PATCH] udev - drop all methods :) X-Git-Tag: 013~22 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ac28b86d631f23b5df74dbeb33e76a2b3f5d88bb;p=systemd [PATCH] udev - drop all methods :) > Hi, > as promised yesterday, here is a patch that drops the explicit methods > given in the udev config and implement only one type of rule. > > A rule now consists only of a number of keys to match. All known keys > are valid in any combination. The former configs should work with a few > changes: > > o the ", " at the beginning of the line should be removed > > o the result of the externel program is matched with RESULT= instead if ID= > the PROGRAM= key is only valid if the program exits with zero > (just exit with nozero in a script if the rule should not match) > > o rules are processed in order they appear in the file, no priority > > o if NAME="" is given, udev is instructed to ignore this device, > no node will be created > > > EXAMPLE: > > # combined BUS, SYSFS and KERNEL > BUS="usb", KERNEL="video*", SYSFS_model="Creative Labs WebCam*", NAME="test/webcam%n" > > # exec script only for the first ide drive (hda), all other will be skipped > BUS="ide", KERNEL="hda*", PROGRAM="/home/kay/src/udev.kay/extras/ide-devfs.sh %k %b %n", RESULT="hd*", NAME="%1c", SYMLINK="%2c %3c" > > > The udev-test.pl and test.block works fine here. > Please adapt your config and give it a try. > Here is a slightly better version of the patch. After a conversation with Patrick, we are now able to execute the PROGRAM and also match in all following rules with the RESULT value from this exec. EXAMPLE: We have 7 rules with RESULT and 2 with PROGRAM. Only the 5th rule matches with the callout result from the exec in the 4th rule. RULES: PROGRAM="/bin/echo abc", RESULT="no_match", NAME="web-no-2" KERNEL="video*", RESULT="123", NAME="web-no-3" KERNEL="video*", RESULT="123", NAME="web-no-4" PROGRAM="/bin/echo 123", RESULT="no_match", NAME="web-no-5" KERNEL="video*", RESULT="123", NAME="web-yes" RESULT: Jan 11 23:36:52 pim udev[26050]: namedev_name_device: process rule Jan 11 23:36:52 pim udev[26050]: namedev_name_device: check PROGRAM Jan 11 23:36:52 pim udev[26050]: execute_program: executing '/bin/echo abc' Jan 11 23:36:52 pim udev[26050]: execute_program: result is 'abc' Jan 11 23:36:52 pim udev[26050]: namedev_name_device: PROGRAM returned successful Jan 11 23:36:52 pim udev[26050]: namedev_name_device: check for RESULT dev->result='no_match', udev->program_result='abc' Jan 11 23:36:52 pim udev[26050]: namedev_name_device: RESULT is not matching Jan 11 23:36:52 pim udev[26050]: namedev_name_device: process rule Jan 11 23:36:52 pim udev[26050]: namedev_name_device: check for KERNEL dev->kernel='video*' class_dev->name='video0' Jan 11 23:36:52 pim udev[26050]: namedev_name_device: KERNEL matches Jan 11 23:36:52 pim udev[26050]: namedev_name_device: check for RESULT dev->result='123', udev->program_result='abc' Jan 11 23:36:52 pim udev[26050]: namedev_name_device: RESULT is not matching Jan 11 23:36:52 pim udev[26050]: namedev_name_device: process rule Jan 11 23:36:52 pim udev[26050]: namedev_name_device: check for KERNEL dev->kernel='video*' class_dev->name='video0' Jan 11 23:36:52 pim udev[26050]: namedev_name_device: KERNEL matches Jan 11 23:36:52 pim udev[26050]: namedev_name_device: check for RESULT dev->result='123', udev->program_result='abc' Jan 11 23:36:52 pim udev[26050]: namedev_name_device: RESULT is not matching Jan 11 23:36:52 pim udev[26050]: namedev_name_device: process rule Jan 11 23:36:52 pim udev[26050]: namedev_name_device: check PROGRAM Jan 11 23:36:52 pim udev[26050]: execute_program: executing '/bin/echo 123' Jan 11 23:36:52 pim udev[26050]: execute_program: result is '123' Jan 11 23:36:52 pim udev[26050]: namedev_name_device: PROGRAM returned successful Jan 11 23:36:52 pim udev[26050]: namedev_name_device: check for RESULT dev->result='no_match', udev->program_result='123' Jan 11 23:36:52 pim udev[26050]: namedev_name_device: RESULT is not matching Jan 11 23:36:52 pim udev[26050]: namedev_name_device: process rule Jan 11 23:36:52 pim udev[26050]: namedev_name_device: check for KERNEL dev->kernel='video*' class_dev->name='video0' Jan 11 23:36:52 pim udev[26050]: namedev_name_device: KERNEL matches Jan 11 23:36:52 pim udev[26050]: namedev_name_device: check for RESULT dev->result='123', udev->program_result='123' Jan 11 23:36:52 pim udev[26050]: namedev_name_device: RESULT matches Jan 11 23:36:52 pim udev[26050]: namedev_name_device: found matching rule, 'video*' becomes '' Jan 11 23:36:52 pim udev[26050]: namedev_name_device: name, 'web-yes' is going to have owner='', group='', mode = 0600 --- diff --git a/namedev.c b/namedev.c index e502ba1a..41fefc4b 100644 --- a/namedev.c +++ b/namedev.c @@ -213,27 +213,27 @@ static void apply_format(struct udevice *udev, unsigned char *string) dbg("substitute major number '%u'", udev->major); break; case 'c': - if (strlen(udev->callout_value) == 0) + if (strlen(udev->program_result) == 0) break; if (num) { /* get part of return string */ - strncpy(temp, udev->callout_value, sizeof(temp)); + strncpy(temp, udev->program_result, sizeof(temp)); pos2 = temp; while (num) { num--; pos3 = strsep(&pos2, " "); if (pos3 == NULL) { - dbg("requested part of callout string not found"); + dbg("requested part of result string not found"); break; } } if (pos3) { strcat(pos, pos3); - dbg("substitute partial callout output '%s'", pos3); + dbg("substitute part of result string '%s'", pos3); } } else { - strcat(pos, udev->callout_value); - dbg("substitute callout output '%s'", udev->callout_value); + strcat(pos, udev->program_result); + dbg("substitute result string '%s'", udev->program_result); } break; default: @@ -298,28 +298,7 @@ exit: return; /* here to prevent compiler warning... */ } -static int do_ignore(struct sysfs_class_device *class_dev, struct udevice *udev, struct sysfs_device *sysfs_device) -{ - struct config_device *dev; - struct list_head *tmp; - - list_for_each(tmp, &config_device_list) { - dev = list_entry(tmp, struct config_device, node); - if (dev->type != IGNORE) - continue; - - dbg("compare name '%s' with '%s'", dev->kernel_name, class_dev->name); - if (strcmp_pattern(dev->kernel_name, class_dev->name) != 0) - continue; - - dbg("found name, '%s' will be ignored", dev->kernel_name); - - return 0; - } - return -ENODEV; -} - -static int exec_program(char *path, char *value, int len) +static int execute_program(char *path, char *value, int len) { int retval; int res; @@ -332,7 +311,7 @@ static int exec_program(char *path, char *value, int len) char *args[CALLOUT_MAXARG]; int i; - dbg("callout to '%s'", path); + dbg("executing '%s'", path); retval = pipe(fds); if (retval != 0) { dbg("pipe failed"); @@ -349,7 +328,7 @@ static int exec_program(char *path, char *value, int len) close(STDOUT_FILENO); dup(fds[1]); /* dup write side of pipe to STDOUT */ if (strchr(path, ' ')) { - /* callout with arguments */ + /* exec with arguments */ pos = path; for (i=0; i < CALLOUT_MAXARG-1; i++) { args[i] = strsep(&pos, " "); @@ -379,11 +358,11 @@ static int exec_program(char *path, char *value, int len) break; buffer[res] = '\0'; if (res > len) { - dbg("callout len %d too short", len); + dbg("result len %d too short", len); retval = -1; } if (value_set) { - dbg("callout value already set"); + dbg("result value already set"); retval = -1; } else { value_set = 1; @@ -391,7 +370,7 @@ static int exec_program(char *path, char *value, int len) pos = value + strlen(value)-1; if (pos[0] == '\n') pos[0] = '\0'; - dbg("callout returned '%s'", value); + dbg("result is '%s'", value); } } close(fds[0]); @@ -402,46 +381,14 @@ static int exec_program(char *path, char *value, int len) } if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) { - dbg("callout program status 0x%x", status); + dbg("exec program status 0x%x", status); retval = -1; } } return retval; } -static int do_callout(struct sysfs_class_device *class_dev, struct udevice *udev, struct sysfs_device *sysfs_device) -{ - struct config_device *dev; - - list_for_each_entry(dev, &config_device_list, node) { - if (dev->type != CALLOUT) - continue; - - if (dev->bus[0] != '\0') { - /* as the user specified a bus, we must match it up */ - if (!sysfs_device) - continue; - dbg("dev->bus='%s' sysfs_device->bus='%s'", dev->bus, sysfs_device->bus); - if (strcasecmp(dev->bus, sysfs_device->bus) != 0) - continue; - } - - /* substitute anything that needs to be in the program name */ - apply_format(udev, dev->exec_program); - if (exec_program(dev->exec_program, udev->callout_value, NAME_SIZE)) - continue; - if (strcmp_pattern(dev->id, udev->callout_value) != 0) - continue; - strfieldcpy(udev->name, dev->name); - strfieldcpy(udev->symlink, dev->symlink); - dbg("callout returned matching value '%s', '%s' becomes '%s'", - dev->id, class_dev->name, udev->name); - return 0; - } - return -ENODEV; -} - -static int match_pair(struct sysfs_class_device *class_dev, struct sysfs_device *sysfs_device, struct sysfs_pair *pair) +static int compare_sysfs_attribute(struct sysfs_class_device *class_dev, struct sysfs_device *sysfs_device, struct sysfs_pair *pair) { struct sysfs_attribute *tmpattr = NULL; char *c; @@ -461,7 +408,6 @@ static int match_pair(struct sysfs_class_device *class_dev, struct sysfs_device if (tmpattr) goto label_found; } - return -ENODEV; label_found: @@ -478,53 +424,26 @@ label_found: return 0; } -static int do_label(struct sysfs_class_device *class_dev, struct udevice *udev, struct sysfs_device *sysfs_device) +static int match_sysfs_pairs(struct config_device *dev, struct sysfs_class_device *class_dev, struct sysfs_device *sysfs_device) { struct sysfs_pair *pair; - struct config_device *dev; int i; - int match; - - list_for_each_entry(dev, &config_device_list, node) { - if (dev->type != LABEL) - continue; - - if (dev->bus[0] != '\0') { - /* as the user specified a bus, we must match it up */ - if (!sysfs_device) - continue; - dbg("dev->bus='%s' sysfs_device->bus='%s'", dev->bus, sysfs_device->bus); - if (strcasecmp(dev->bus, sysfs_device->bus) != 0) - continue; - } - match = 1; - for (i = 0; i < MAX_SYSFS_PAIRS; ++i) { - pair = &dev->sysfs_pair[i]; - if ((pair->file[0] == '\0') || (pair->value[0] == '\0')) - break; - if (match_pair(class_dev, sysfs_device, pair) != 0) { - match = 0; - break; - } + for (i = 0; i < MAX_SYSFS_PAIRS; ++i) { + pair = &dev->sysfs_pair[i]; + if ((pair->file[0] == '\0') || (pair->value[0] == '\0')) + break; + if (compare_sysfs_attribute(class_dev, sysfs_device, pair) != 0) { + dbg("sysfs attribute doesn't match"); + return -ENODEV; } - if (match == 0) - continue; - - /* found match */ - strfieldcpy(udev->name, dev->name); - strfieldcpy(udev->symlink, dev->symlink); - dbg("found matching attribute, '%s' becomes '%s' ", - class_dev->name, udev->name); - - return 0; } - return -ENODEV; + + return 0; } -static int do_number(struct sysfs_class_device *class_dev, struct udevice *udev, struct sysfs_device *sysfs_device) +static int match_id(struct config_device *dev, struct sysfs_class_device *class_dev, struct sysfs_device *sysfs_device) { - struct config_device *dev; char path[SYSFS_PATH_MAX]; int found; char *temp = NULL; @@ -533,107 +452,56 @@ static int do_number(struct sysfs_class_device *class_dev, struct udevice *udev, if (!sysfs_device) return -ENODEV; - list_for_each_entry(dev, &config_device_list, node) { - if (dev->type != NUMBER) - continue; - - dbg("dev->bus='%s' sysfs_device->bus='%s'", dev->bus, sysfs_device->bus); - if (strcasecmp(dev->bus, sysfs_device->bus) != 0) - continue; - - found = 0; - strfieldcpy(path, sysfs_device->path); + found = 0; + strfieldcpy(path, sysfs_device->path); + temp = strrchr(path, '/'); + dbg("search '%s' in '%s', path='%s'", dev->id, temp, path); + if (strstr(temp, dev->id) != NULL) { + found = 1; + } else { + *temp = 0x00; temp = strrchr(path, '/'); dbg("search '%s' in '%s', path='%s'", dev->id, temp, path); - if (strstr(temp, dev->id) != NULL) { + if (strstr(temp, dev->id) != NULL) found = 1; - } else { - *temp = 0x00; - temp = strrchr(path, '/'); - dbg("search '%s' in '%s', path='%s'", dev->id, temp, path); - if (strstr(temp, dev->id) != NULL) - found = 1; - } - if (!found) - continue; - strfieldcpy(udev->name, dev->name); - strfieldcpy(udev->symlink, dev->symlink); - dbg("found matching id '%s', '%s' becomes '%s'", - dev->id, class_dev->name, udev->name); - return 0; } - return -ENODEV; + if (!found) { + dbg("id doesn't match"); + return -ENODEV; + } + + return 0; } -static int do_topology(struct sysfs_class_device *class_dev, struct udevice *udev, struct sysfs_device *sysfs_device) +static int match_place(struct config_device *dev, struct sysfs_class_device *class_dev, struct sysfs_device *sysfs_device) { - struct config_device *dev; char path[SYSFS_PATH_MAX]; int found; char *temp = NULL; - /* we have to have a sysfs device for TOPOLOGY to work */ + /* we have to have a sysfs device for NUMBER to work */ if (!sysfs_device) return -ENODEV; - list_for_each_entry(dev, &config_device_list, node) { - if (dev->type != TOPOLOGY) - continue; - - dbg("dev->bus='%s' sysfs_device->bus='%s'", dev->bus, sysfs_device->bus); - if (strcasecmp(dev->bus, sysfs_device->bus) != 0) - continue; - - found = 0; - strfieldcpy(path, sysfs_device->path); + found = 0; + strfieldcpy(path, sysfs_device->path); + temp = strrchr(path, '/'); + dbg("search '%s' in '%s', path='%s'", dev->place, temp, path); + if (strstr(temp, dev->place) != NULL) { + found = 1; + } else { + *temp = 0x00; temp = strrchr(path, '/'); dbg("search '%s' in '%s', path='%s'", dev->place, temp, path); - if (strstr(temp, dev->place) != NULL) { + if (strstr(temp, dev->place) != NULL) found = 1; - } else { - *temp = 0x00; - temp = strrchr(path, '/'); - dbg("search '%s' in '%s', path='%s'", dev->place, temp, path); - if (strstr(temp, dev->place) != NULL) - found = 1; - } - if (!found) - continue; - - strfieldcpy(udev->name, dev->name); - strfieldcpy(udev->symlink, dev->symlink); - dbg("found matching place '%s', '%s' becomes '%s'", - dev->place, class_dev->name, udev->name); - return 0; } - return -ENODEV; -} - -static int do_replace(struct sysfs_class_device *class_dev, struct udevice *udev, struct sysfs_device *sysfs_device) -{ - struct config_device *dev; - - list_for_each_entry(dev, &config_device_list, node) { - if (dev->type != REPLACE) - continue; - - dbg("compare name '%s' with '%s'", dev->kernel_name, class_dev->name); - if (strcmp_pattern(dev->kernel_name, class_dev->name) != 0) - continue; - - strfieldcpy(udev->name, dev->name); - strfieldcpy(udev->symlink, dev->symlink); - dbg("found name, '%s' becomes '%s'", dev->kernel_name, udev->name); - - return 0; + if (!found) { + dbg("place doesn't match"); + return -ENODEV; } - return -ENODEV; -} -static void do_kernelname(struct sysfs_class_device *class_dev, struct udevice *udev) -{ - /* heh, this is pretty simple... */ - strfieldcpy(udev->name, class_dev->name); + return 0; } static struct sysfs_device *get_sysfs_device(struct sysfs_class_device *class_dev) @@ -725,7 +593,7 @@ exit: int namedev_name_device(struct sysfs_class_device *class_dev, struct udevice *udev) { struct sysfs_device *sysfs_device = NULL; - int retval = 0; + struct config_device *dev; struct perm_device *perm; char *pos; @@ -752,34 +620,109 @@ int namedev_name_device(struct sysfs_class_device *class_dev, struct udevice *ud strfieldcpy(udev->kernel_number, pos); dbg("kernel_number='%s'", udev->kernel_number); - /* rules are looked at in priority order */ - retval = do_ignore(class_dev, udev, sysfs_device); - if (retval == 0) { - dbg("name, '%s' is being ignored", class_dev->name); - return 1; - } + /* look for a matching rule to apply */ + list_for_each_entry(dev, &config_device_list, node) { + dbg("process rule"); - retval = do_callout(class_dev, udev, sysfs_device); - if (retval == 0) - goto found; + /* check for matching bus value */ + if (dev->bus[0] != '\0') { + if (sysfs_device == NULL) { + dbg("device has no bus"); + continue; + } + dbg("check for " FIELD_BUS " dev->bus='%s' sysfs_device->bus='%s'", dev->bus, sysfs_device->bus); + if (strcmp_pattern(dev->bus, sysfs_device->bus) != 0) { + dbg(FIELD_BUS " is not matching"); + continue; + } else { + dbg(FIELD_BUS " matches"); + } + } - retval = do_label(class_dev, udev, sysfs_device); - if (retval == 0) - goto found; + /* check for matching kernel name*/ + if (dev->kernel[0] != '\0') { + dbg("check for " FIELD_KERNEL " dev->kernel='%s' class_dev->name='%s'", dev->kernel, class_dev->name); + if (strcmp_pattern(dev->kernel, class_dev->name) != 0) { + dbg(FIELD_KERNEL " is not matching"); + continue; + } else { + dbg(FIELD_KERNEL " matches"); + } + } - retval = do_number(class_dev, udev, sysfs_device); - if (retval == 0) - goto found; + /* check for matching bus id */ + if (dev->id[0] != '\0') { + dbg("check " FIELD_ID); + if (match_id(dev, class_dev, sysfs_device) != 0) { + dbg(FIELD_ID " is not matching"); + continue; + } else { + dbg(FIELD_ID " matches"); + } + } - retval = do_topology(class_dev, udev, sysfs_device); - if (retval == 0) - goto found; + /* check for matching place of device */ + if (dev->place[0] != '\0') { + dbg("check " FIELD_PLACE); + if (match_place(dev, class_dev, sysfs_device) != 0) { + dbg(FIELD_PLACE " is not matching"); + continue; + } else { + dbg(FIELD_PLACE " matches"); + } + } - retval = do_replace(class_dev, udev, sysfs_device); - if (retval == 0) + /* check for matching sysfs pairs */ + if (dev->sysfs_pair[0].file[0] != '\0') { + dbg("check " FIELD_SYSFS " pairs"); + if (match_sysfs_pairs(dev, class_dev, sysfs_device) != 0) { + dbg(FIELD_SYSFS " is not matching"); + continue; + } else { + dbg(FIELD_SYSFS " matches"); + } + } + + /* execute external program */ + if (dev->program[0] != '\0') { + dbg("check " FIELD_PROGRAM); + apply_format(udev, dev->program); + if (execute_program(dev->program, udev->program_result, NAME_SIZE) != 0) { + dbg(FIELD_PROGRAM " returned nozero"); + continue; + } else { + dbg(FIELD_PROGRAM " returned successful"); + } + } + + /* check for matching result of external program */ + if (dev->result[0] != '\0') { + dbg("check for " FIELD_RESULT + " dev->result='%s', udev->program_result='%s'", + dev->result, udev->program_result); + if (strcmp_pattern(dev->result, udev->program_result) != 0) { + dbg(FIELD_RESULT " is not matching"); + continue; + } else { + dbg(FIELD_RESULT " matches"); + } + } + + /* check if we are instructed to ignore this device */ + if (dev->name[0] == '\0') { + dbg("instructed to ignore this device"); + return -1; + } + + /* Yup, this rule belongs to us! */ + dbg("found matching rule, '%s' becomes '%s'", dev->kernel, udev->name); + strfieldcpy(udev->name, dev->name); + strfieldcpy(udev->symlink, dev->symlink); goto found; + } - do_kernelname(class_dev, udev); + /* no rule was found so we use the kernel name */ + strfieldcpy(udev->name, class_dev->name); goto done; found: diff --git a/namedev.h b/namedev.h index f1e77027..4e75db64 100644 --- a/namedev.h +++ b/namedev.h @@ -28,17 +28,6 @@ struct sysfs_class_device; - -enum config_type { - KERNEL_NAME = 0, /* must be 0 to let memset() default to this value */ - LABEL = 1, - NUMBER = 2, - TOPOLOGY = 3, - REPLACE = 4, - CALLOUT = 5, - IGNORE = 6, -}; - #define BUS_SIZE 30 #define FILE_SIZE 50 #define VALUE_SIZE 100 @@ -46,23 +35,17 @@ enum config_type { #define PLACE_SIZE 50 #define PROGRAM_SIZE 100 -#define TYPE_LABEL "LABEL" -#define TYPE_NUMBER "NUMBER" -#define TYPE_TOPOLOGY "TOPOLOGY" -#define TYPE_REPLACE "REPLACE" -#define TYPE_CALLOUT "CALLOUT" -#define TYPE_IGNORE "IGNORE" - #define FIELD_BUS "BUS" -#define FIELD_ID "ID" #define FIELD_SYSFS "SYSFS_" +#define FIELD_ID "ID" #define FIELD_PLACE "PLACE" #define FIELD_PROGRAM "PROGRAM" +#define FIELD_RESULT "RESULT" #define FIELD_KERNEL "KERNEL" #define FIELD_NAME "NAME" #define FIELD_SYMLINK "SYMLINK" -#define CALLOUT_MAXARG 8 +#define CALLOUT_MAXARG 10 #define MAX_SYSFS_PAIRS 5 struct sysfs_pair { @@ -73,12 +56,12 @@ struct sysfs_pair { struct config_device { struct list_head node; - enum config_type type; char bus[BUS_SIZE]; char id[ID_SIZE]; char place[PLACE_SIZE]; - char kernel_name[NAME_SIZE]; - char exec_program[PROGRAM_SIZE]; + char kernel[NAME_SIZE]; + char program[PROGRAM_SIZE]; + char result[PROGRAM_SIZE]; char name[NAME_SIZE]; char symlink[NAME_SIZE]; struct sysfs_pair sysfs_pair[MAX_SYSFS_PAIRS]; diff --git a/namedev_parse.c b/namedev_parse.c index 5b5a5b3b..98e822df 100644 --- a/namedev_parse.c +++ b/namedev_parse.c @@ -86,37 +86,13 @@ int get_pair(char **orig_string, char **left, char **right) void dump_config_dev(struct config_device *dev) { - switch (dev->type) { - case KERNEL_NAME: - dbg_parse("KERNEL name='%s'", dev->name); - break; - case LABEL: - dbg_parse("LABEL name='%s', bus='%s', sysfs_file[0]='%s', sysfs_value[0]='%s'", - dev->name, dev->bus, dev->sysfs_pair[0].file, dev->sysfs_pair[0].value); - break; - case NUMBER: - dbg_parse("NUMBER name='%s', bus='%s', id='%s'", - dev->name, dev->bus, dev->id); - break; - case TOPOLOGY: - dbg_parse("TOPOLOGY name='%s', bus='%s', place='%s'", - dev->name, dev->bus, dev->place); - break; - case REPLACE: - dbg_parse("REPLACE name='%s', kernel_name='%s'", - dev->name, dev->kernel_name); - break; - case CALLOUT: - dbg_parse("CALLOUT name='%s', bus='%s', program='%s', id='%s'", - dev->name, dev->bus, dev->exec_program, dev->id); - break; - case IGNORE: - dbg_parse("IGNORE name='%s', kernel_name='%s'", - dev->name, dev->kernel_name); - break; - default: - dbg_parse("unknown type of method"); - } + /*FIXME dump all sysfs's */ + dbg_parse("name='%s', symlink='%s', bus='%s', place='%s', id='%s', " + "sysfs_file[0]='%s', sysfs_value[0]='%s', " + "kernel='%s', program='%s', result='%s'", + dev->name, dev->symlink, dev->bus, dev->place, dev->id, + dev->sysfs_pair[0].file, dev->sysfs_pair[0].value, + dev->kernel, dev->program, dev->result); } void dump_config_dev_list(void) @@ -150,6 +126,7 @@ int namedev_init_rules(void) char *temp2; char *temp3; FILE *fd; + int program_given = 0; int retval = 0; struct config_device dev; @@ -185,42 +162,6 @@ int namedev_init_rules(void) memset(&dev, 0x00, sizeof(struct config_device)); - /* get the method */ - temp2 = strsep(&temp, ","); - - if (strcasecmp(temp2, TYPE_LABEL) == 0) { - dev.type = LABEL; - goto keys; - } - - if (strcasecmp(temp2, TYPE_NUMBER) == 0) { - dev.type = NUMBER; - goto keys; - } - - 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; - } - - if (strcasecmp(temp2, TYPE_IGNORE) == 0) { - dev.type = IGNORE; - 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); @@ -264,12 +205,18 @@ keys: } if (strcasecmp(temp2, FIELD_KERNEL) == 0) { - strfieldcpy(dev.kernel_name, temp3); + strfieldcpy(dev.kernel, temp3); continue; } if (strcasecmp(temp2, FIELD_PROGRAM) == 0) { - strfieldcpy(dev.exec_program, temp3); + program_given = 1; + strfieldcpy(dev.program, temp3); + continue; + } + + if (strcasecmp(temp2, FIELD_RESULT) == 0) { + strfieldcpy(dev.result, temp3); continue; } @@ -286,60 +233,15 @@ keys: dbg_parse("unknown type of field '%s'", temp2); } - /* check presence of keys according to method type */ - switch (dev.type) { - case LABEL: - dbg_parse(TYPE_LABEL " name='%s', bus='%s', " - "sysfs_file[0]='%s', sysfs_value[0]='%s', symlink='%s'", - dev.name, dev.bus, dev.sysfs_pair[0].file, - dev.sysfs_pair[0].value, dev.symlink); - if ((*dev.name == '\0') || - (*dev.sysfs_pair[0].file == '\0') || - (*dev.sysfs_pair[0].value == '\0')) - goto error; - break; - case NUMBER: - dbg_parse(TYPE_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(TYPE_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(TYPE_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(TYPE_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.id == '\0') || - (*dev.exec_program == '\0')) - goto error; - break; - case IGNORE: - dbg_parse(TYPE_IGNORE "name='%s', kernel_name='%s'", - dev.name, dev.kernel_name); - if ((*dev.kernel_name == '\0')) - goto error; - break; - default: - dbg_parse("unknown type of method"); + /* simple plausibility check for given keys */ + if ((dev.sysfs_pair[0].file[0] == '\0') ^ + (dev.sysfs_pair[0].value[0] == '\0')) { + dbg("inconsistency in SYSFS_ key"); + goto error; + } + + if ((dev.result[0] != '\0') && (program_given == 0)) { + dbg("RESULT is only useful when PROGRAM called in any rule before"); goto error; } @@ -347,11 +249,11 @@ keys: if (retval) { dbg("add_config_dev returned with error %d", retval); continue; +error: + dbg("%s:%d:%Zd: parse error, rule skipped", + udev_rules_filename, lineno, temp - line); } } -error: - dbg_parse("%s:%d:%Zd: field missing or parse error", udev_rules_filename, - lineno, temp - line); exit: fclose(fd); return retval; diff --git a/test/udev-test.pl b/test/udev-test.pl index 97c00949..ab27c74c 100644 --- a/test/udev-test.pl +++ b/test/udev-test.pl @@ -38,8 +38,8 @@ my @tests = ( devpath => "block/sda", expected => "boot_disk" , conf => < "block/sda/sda1", expected => "boot_disk1" , conf => < "block/sda/sda1", expected => "boot_disk1" , conf => < "block/sda/sda1", expected => "boot_disk1" , conf => < "block/sda/sda1", expected => "boot_disk1" , conf => < "class/tty/ttyUSB0", expected => "visor/0" , conf => < "class/tty/ttyUSB0", expected => "visor/0" , conf => < "class/tty/ttyUSB0", expected => "visor/0" , conf => < "class/tty/ttyUSB0", expected => "visor" , conf => < "visor" , conf => < "visor" , conf => < "visor" , conf => < "class/tty/ttyUSB0", expected => "sub/direct/ory/visor" , conf => < "block/sda/sda3", expected => "first_disk3" , conf => < "block/sda/sda3", expected => "Major:8:minor:3:kernelnumber:3:bus:0:0:0:0" , conf => < "callout result substitution", + desc => "program result substitution", subsys => "block", devpath => "block/sda/sda3", expected => "special-device-3" , conf => < "callout program substitution", + desc => "program result substitution", subsys => "block", devpath => "block/sda/sda3", expected => "test-0:0:0:0" , conf => < "callout program substitution (numbered part of)", + desc => "program result substitution (numbered part of)", subsys => "block", devpath => "block/sda/sda3", expected => "link1" , conf => < "invalid callout for device with no bus", + desc => "invalid program for device with no bus", subsys => "tty", devpath => "class/tty/console", expected => "TTY" , conf => < "valid callout for device with no bus", + desc => "valid program for device with no bus", subsys => "tty", devpath => "class/tty/console", expected => "foo" , conf => < "class/tty/console", expected => "TTY" , conf => < "class/tty/console", expected => "foo" , conf => < "block/sda", expected => "lun0/disc" , conf => < "block/sda/sda2", expected => "lun0/part2" , conf => < "callout bus type", + desc => "program and bus type match", subsys => "block", devpath => "block/sda", expected => "scsi-0:0:0:0" , conf => < "class/tty/ttyUSB0", expected => "visor0" , conf => < "block/sda/sda2", expected => "1/2/a/b/symlink" , conf => < "block/sda/sda2", expected => "1/2/symlink" , conf => < "block/sda/sda2", expected => "1/2/c/d/symlink" , conf => < "class/tty/ttyUSB0", expected => "second-0" , conf => <{conf} =~ m/([A-Z]+)\s*,/; - my $method = $1; - print "TEST: $config->{desc}\n"; - print "method \'$method\' for \'$config->{devpath}\' expecting node \'$config->{expected}\'\n"; + print "device \'$config->{devpath}\' expecting node \'$config->{expected}\'\n"; udev("add", $config->{subsys}, $config->{devpath}, \$config->{conf}); if (-e "$PWD/$udev_root$config->{expected}") { diff --git a/udev.h b/udev.h index 656c1b7d..678731c7 100644 --- a/udev.h +++ b/udev.h @@ -68,7 +68,7 @@ struct udevice { /* fields that help us in building strings */ unsigned char bus_id[SYSFS_NAME_LEN]; - unsigned char callout_value[NAME_SIZE]; + unsigned char program_result[NAME_SIZE]; unsigned char kernel_number[NAME_SIZE]; unsigned char kernel_name[NAME_SIZE];