chiark / gitweb /
change parameter order of udev_db_search_name()
[elogind.git] / udev_rules.c
index 7ecca9468e05a65a28ad87317c39b4428aed7359..8db7fd377ab83ec19cafa3a1385e08da4b597bc1 100644 (file)
@@ -270,28 +270,31 @@ static int import_parent_into_env(struct udevice *udev, struct sysfs_class_devic
 /* finds the lowest positive N such that <name>N isn't present in the udevdb
  * if <name> doesn't exist, 0 is returned, N otherwise
  */
-static int find_free_number(const char *name)
+static int find_free_number(const char *name, const char *devpath)
 {
-       char devpath[PATH_SIZE];
+       char db_devpath[PATH_SIZE];
        char filename[PATH_SIZE];
        int num = 0;
 
        strlcpy(filename, name, sizeof(filename));
        while (1) {
                dbg("look for existing node '%s'", filename);
-               if (udev_db_search_name(devpath, sizeof(devpath), filename) != 0) {
+               if (udev_db_search_name(filename, db_devpath, sizeof(db_devpath)) != 0) {
                        dbg("free num=%d", num);
-                       return num;
+                       break;
                }
 
                num++;
-               if (num > 1000) {
-                       info("find_free_number gone crazy (num=%d), aborted", num);
-                       return -1;
+               if (num > 100000) {
+                       err("find_free_number aborted at num=%d", num);
+                       num = -1;
+                       break;
                }
                snprintf(filename, sizeof(filename), "%s%d", name, num);
                filename[sizeof(filename)-1] = '\0';
        }
+
+       return num;
 }
 
 static int find_sysfs_attribute(struct sysfs_class_device *class_dev, struct sysfs_device *sysfs_device,
@@ -546,7 +549,7 @@ found:
                        dbg("substitute sysfs value '%s'", temp2);
                        break;
                case SUBST_ENUM:
-                       next_free_number = find_free_number(string);
+                       next_free_number = find_free_number(string, udev->devpath);
                        if (next_free_number > 0) {
                                sprintf(temp2, "%d", next_free_number);
                                strlcat(string, temp2, maxsize);
@@ -667,6 +670,7 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule,
                      struct sysfs_class_device *class_dev, struct sysfs_device *sysfs_device)
 {
        struct sysfs_device *parent_device = sysfs_device;
+       int i;
 
        if (match_key("ACTION", rule, &rule->action, udev->action))
                goto exit;
@@ -691,23 +695,21 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule,
                        goto exit;
        }
 
-       if (rule->env.count) {
-               int i;
+       for (i = 0; i < rule->env.count; i++) {
+               struct key_pair *pair = &rule->env.keys[i];
 
-               dbg("check %i ENV keys", rule->env.count);
-               for (i = 0; i < rule->env.count; i++) {
-                       struct key_pair *pair = &rule->env.keys[i];
+               /* we only check for matches, assignments will be handled later */
+               if (pair->key.operation != KEY_OP_ASSIGN) {
                        const char *key_name = key_pair_name(rule, pair);
                        const char *value = getenv(key_name);
 
                        if (!value) {
-                               dbg("ENV{'%s'} is not set", key_name);
+                               dbg("ENV{'%s'} is not set, treat as empty", key_name);
                                value = "";
                        }
                        if (match_key("ENV", rule, &pair->key, value))
                                goto exit;
                }
-               dbg("all %i ENV keys matched", rule->env.count);
        }
 
        if (rule->wait_for_sysfs.operation != KEY_OP_UNSET) {
@@ -760,8 +762,6 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule,
 
                /* check for matching sysfs pairs */
                if (rule->sysfs.count) {
-                       int i;
-
                        dbg("check %i SYSFS keys", rule->sysfs.count);
                        for (i = 0; i < rule->sysfs.count; i++) {
                                struct key_pair *pair = &rule->sysfs.keys[i];
@@ -799,32 +799,6 @@ try_parent:
                dbg("look at sysfs_device->bus_id='%s'", parent_device->bus_id);
        }
 
-       /* import variables from file into environment */
-       if (rule->import.operation != KEY_OP_UNSET) {
-               char import[PATH_SIZE];
-               int rc = -1;
-
-               strlcpy(import, key_val(rule, &rule->import), sizeof(import));
-               apply_format(udev, import, sizeof(import), class_dev, sysfs_device);
-               dbg("check for IMPORT import='%s'", import);
-               if (rule->import_type == IMPORT_PROGRAM) {
-                       rc = import_program_into_env(udev, import);
-               } else if (rule->import_type == IMPORT_FILE) {
-                       dbg("import file import='%s'", import);
-                       rc = import_file_into_env(udev, import);
-               } else if (rule->import_type == IMPORT_PARENT && class_dev) {
-                       dbg("import parent import='%s'", import);
-                       rc = import_parent_into_env(udev, class_dev, import);
-               }
-               if (rc) {
-                       dbg("IMPORT failed");
-                       if (rule->import.operation != KEY_OP_NOMATCH)
-                               goto exit;
-               } else
-                       dbg("IMPORT '%s' imported", key_val(rule, &rule->import));
-               dbg("IMPORT key is true");
-       }
-
        /* execute external program */
        if (rule->program.operation != KEY_OP_UNSET) {
                char program[PATH_SIZE];
@@ -854,7 +828,46 @@ try_parent:
        if (match_key("RESULT", rule, &rule->result, udev->program_result))
                goto exit;
 
-       /* rule matches */
+       /* import variables returned from program or or file into environment */
+       if (rule->import.operation != KEY_OP_UNSET) {
+               char import[PATH_SIZE];
+               int rc = -1;
+
+               strlcpy(import, key_val(rule, &rule->import), sizeof(import));
+               apply_format(udev, import, sizeof(import), class_dev, sysfs_device);
+               dbg("check for IMPORT import='%s'", import);
+               if (rule->import_type == IMPORT_PROGRAM) {
+                       rc = import_program_into_env(udev, import);
+               } else if (rule->import_type == IMPORT_FILE) {
+                       dbg("import file import='%s'", import);
+                       rc = import_file_into_env(udev, import);
+               } else if (rule->import_type == IMPORT_PARENT && class_dev) {
+                       dbg("import parent import='%s'", import);
+                       rc = import_parent_into_env(udev, class_dev, import);
+               }
+               if (rc) {
+                       dbg("IMPORT failed");
+                       if (rule->import.operation != KEY_OP_NOMATCH)
+                               goto exit;
+               } else
+                       dbg("IMPORT '%s' imported", key_val(rule, &rule->import));
+               dbg("IMPORT key is true");
+       }
+
+       /* rule matches, if we have ENV assignments export it */
+       for (i = 0; i < rule->env.count; i++) {
+               struct key_pair *pair = &rule->env.keys[i];
+
+               if (pair->key.operation == KEY_OP_ASSIGN) {
+                       const char *key_name = key_pair_name(rule, pair);
+                       const char *value = key_val(rule, &pair->key);
+
+                       name_list_key_add(&udev->env_list, key_name, value);
+                       setenv(key_name, value, 1);
+                       dbg("export ENV '%s=%s'", key_name, value);
+               }
+       }
+
        return 0;
 
 exit: