chiark / gitweb /
udevd: create /dev/.udev/rules.d/ before watching it wit inotify
[elogind.git] / udev / udev-rules.c
index 20ec2706bdfa99cf24bdf8c1b391804713f7df75..092ddcdc25360cf30f2d591715736748ebec3533 100644 (file)
@@ -164,7 +164,6 @@ enum token_type {
        TK_A_ATTR,                      /* val, attr */
        TK_A_RUN,                       /* val, bool */
        TK_A_GOTO,                      /* size_t */
-       TK_A_LAST_RULE,
 
        TK_END,
 };
@@ -190,7 +189,8 @@ struct token {
                        unsigned int value_off;
                        union {
                                unsigned int attr_off;
-                               int ignore_error;
+                               int devlink_unique;
+                               int fail_on_error;
                                unsigned int rule_goto;
                                mode_t  mode;
                                uid_t uid;
@@ -295,7 +295,6 @@ static const char *token_str(enum token_type type)
                [TK_A_ATTR] =                   "A ATTR",
                [TK_A_RUN] =                    "A RUN",
                [TK_A_GOTO] =                   "A GOTO",
-               [TK_A_LAST_RULE] =              "A LAST_RULE",
 
                [TK_END] =                      "END",
        };
@@ -361,7 +360,6 @@ static void dump_token(struct udev_rules *rules, struct token *token)
        case TK_A_IGNORE_DEVICE:
        case TK_A_STRING_ESCAPE_NONE:
        case TK_A_STRING_ESCAPE_REPLACE:
-       case TK_A_LAST_RULE:
        case TK_A_IGNORE_REMOVE:
                dbg(rules->udev, "%s\n", token_str(type));
                break;
@@ -1011,7 +1009,6 @@ static int rule_add_key(struct rule_tmp *rule_tmp, enum token_type type,
        case TK_A_GROUP:
        case TK_A_MODE:
        case TK_A_NAME:
-       case TK_A_DEVLINK:
        case TK_A_GOTO:
                token->key.value_off = add_string(rule_tmp->rules, value);
                break;
@@ -1024,6 +1021,10 @@ static int rule_add_key(struct rule_tmp *rule_tmp, enum token_type type,
                token->key.value_off = add_string(rule_tmp->rules, value);
                token->key.attr_off = add_string(rule_tmp->rules, attr);
                break;
+       case TK_A_DEVLINK:
+               token->key.value_off = add_string(rule_tmp->rules, value);
+               token->key.devlink_unique = *(int *)data;
+               break;
        case TK_M_TEST:
                token->key.value_off = add_string(rule_tmp->rules, value);
                if (data != NULL)
@@ -1033,11 +1034,10 @@ static int rule_add_key(struct rule_tmp *rule_tmp, enum token_type type,
        case TK_A_STRING_ESCAPE_NONE:
        case TK_A_STRING_ESCAPE_REPLACE:
        case TK_A_IGNORE_REMOVE:
-       case TK_A_LAST_RULE:
                break;
        case TK_A_RUN:
                token->key.value_off = add_string(rule_tmp->rules, value);
-               token->key.ignore_error = *(int *)data;
+               token->key.fail_on_error = *(int *)data;
                break;
        case TK_A_INOTIFY_WATCH:
        case TK_A_NUM_FAKE_PART:
@@ -1127,7 +1127,7 @@ static int sort_token(struct udev_rules *rules, struct rule_tmp *rule_tmp)
 
        for (i = 0; i < rule_tmp->token_cur; i++) {
                enum token_type next_val = TK_UNSET;
-               unsigned int next_idx;
+               unsigned int next_idx = 0;
                unsigned int j;
 
                /* find smallest value */
@@ -1431,11 +1431,17 @@ static int add_rule(struct udev_rules *rules, char *line,
                        continue;
                }
 
-               if (strcmp(key, "SYMLINK") == 0) {
-                       if (op < OP_MATCH_MAX)
+               if (strncmp(key, "SYMLINK", sizeof("SYMLINK")-1) == 0) {
+                       if (op < OP_MATCH_MAX) {
                                rule_add_key(&rule_tmp, TK_M_DEVLINK, op, value, NULL);
-                       else
-                               rule_add_key(&rule_tmp, TK_A_DEVLINK, op, value, NULL);
+                       } else {
+                               int flag = 0;
+
+                               attr = get_key_attribute(rules->udev, key + sizeof("SYMLINK")-1);
+                               if (attr != NULL && strstr(attr, "unique") != NULL)
+                                       flag = 1;
+                               rule_add_key(&rule_tmp, TK_A_DEVLINK, op, value, &flag);
+                       }
                        rule_tmp.rule.rule.flags = 1;
                        continue;
                }
@@ -1490,10 +1496,6 @@ static int add_rule(struct udev_rules *rules, char *line,
                if (strcmp(key, "OPTIONS") == 0) {
                        const char *pos;
 
-                       if (strstr(value, "last_rule") != NULL) {
-                               dbg(rules->udev, "last rule to be applied\n");
-                               rule_add_key(&rule_tmp, TK_A_LAST_RULE, 0, NULL, NULL);
-                       }
                        if (strstr(value, "ignore_device") != NULL) {
                                dbg(rules->udev, "device should be ignored\n");
                                rule_add_key(&rule_tmp, TK_A_IGNORE_DEVICE, 0, NULL, NULL);
@@ -1581,7 +1583,7 @@ static int parse_file(struct udev_rules *rules, const char *filename, unsigned s
 
        first_token = rules->token_cur;
 
-       while(fgets(line, sizeof(line), f) != NULL) {
+       while (fgets(line, sizeof(line), f) != NULL) {
                char *key;
                size_t len;
 
@@ -1734,12 +1736,6 @@ struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names)
 
                /* read dynamic/temporary rules */
                util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/rules.d", NULL);
-               if (stat(filename, &statbuf) != 0) {
-                       util_create_path(udev, filename);
-                       udev_selinux_setfscreatecon(udev, filename, S_IFDIR|0755);
-                       mkdir(filename, 0755);
-                       udev_selinux_resetfscreatecon(udev);
-               }
                udev_list_init(&sort_list);
                add_matching_files(udev, &sort_list, filename, ".rules");
 
@@ -2445,26 +2441,22 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
                                while (isspace(pos[0]))
                                        pos++;
                                next = strchr(pos, ' ');
-                               while (next) {
+                               while (next != NULL) {
                                        next[0] = '\0';
-                                       info(event->udev, "LINK '%s' %s:%u\n",
-                                            pos,
-                                            &rules->buf[rule->rule.filename_off],
-                                            rule->rule.filename_line);
+                                       info(event->udev, "LINK '%s' %s:%u\n", pos,
+                                            &rules->buf[rule->rule.filename_off], rule->rule.filename_line);
                                        util_strscpyl(filename, sizeof(filename), udev_get_dev_path(event->udev), "/", pos, NULL);
-                                       udev_device_add_devlink(event->dev, filename);
+                                       udev_device_add_devlink(event->dev, filename, cur->key.devlink_unique);
                                        while (isspace(next[1]))
                                                next++;
                                        pos = &next[1];
                                        next = strchr(pos, ' ');
                                }
                                if (pos[0] != '\0') {
-                                       info(event->udev, "LINK '%s' %s:%u\n",
-                                            pos,
-                                            &rules->buf[rule->rule.filename_off],
-                                            rule->rule.filename_line);
+                                       info(event->udev, "LINK '%s' %s:%u\n", pos,
+                                            &rules->buf[rule->rule.filename_off], rule->rule.filename_line);
                                        util_strscpyl(filename, sizeof(filename), udev_get_dev_path(event->udev), "/", pos, NULL);
-                                       udev_device_add_devlink(event->dev, filename);
+                                       udev_device_add_devlink(event->dev, filename, cur->key.devlink_unique);
                                }
                        }
                        break;
@@ -2511,7 +2503,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
                                     rule->rule.filename_line);
                                list_entry = udev_list_entry_add(event->udev, &event->run_list,
                                                                 &rules->buf[cur->key.value_off], NULL, 1, 0);
-                               if (cur->key.ignore_error)
+                               if (cur->key.fail_on_error)
                                        udev_list_entry_set_flag(list_entry, 1);
                                break;
                        }
@@ -2520,7 +2512,6 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
                                break;
                        cur = &rules->tokens[cur->key.rule_goto];
                        continue;
-               case TK_A_LAST_RULE:
                case TK_END:
                        return 0;