chiark / gitweb /
unify/cleanup event handling
[elogind.git] / udev / udev-rules.c
index 422e14ce234bfea9f8f792dfcc16bff5bdf6a30b..60daad520afdf55e4fb8193e420512034b9caba4 100644 (file)
@@ -19,6 +19,7 @@
 #include <stddef.h>
 #include <limits.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <string.h>
 #include <stdio.h>
 #include <fcntl.h>
@@ -144,7 +145,6 @@ enum token_type {
        TK_M_RESULT,                    /* val */
        TK_M_MAX,
 
-       TK_A_IGNORE_DEVICE,
        TK_A_STRING_ESCAPE_NONE,
        TK_A_STRING_ESCAPE_REPLACE,
        TK_A_INOTIFY_WATCH,             /* int */
@@ -275,7 +275,6 @@ static const char *token_str(enum token_type type)
                [TK_M_RESULT] =                 "M RESULT",
                [TK_M_MAX] =                    "M MAX",
 
-               [TK_A_IGNORE_DEVICE] =          "A IGNORE_DEVICE",
                [TK_A_STRING_ESCAPE_NONE] =     "A STRING_ESCAPE_NONE",
                [TK_A_STRING_ESCAPE_REPLACE] =  "A STRING_ESCAPE_REPLACE",
                [TK_A_INOTIFY_WATCH] =          "A INOTIFY_WATCH",
@@ -357,7 +356,6 @@ static void dump_token(struct udev_rules *rules, struct token *token)
                dbg(rules->udev, "%s %s '%s' '%s'(%s)\n",
                    token_str(type), operation_str(op), attr, value, string_glob_str(glob));
                break;
-       case TK_A_IGNORE_DEVICE:
        case TK_A_STRING_ESCAPE_NONE:
        case TK_A_STRING_ESCAPE_REPLACE:
        case TK_A_IGNORE_REMOVE:
@@ -719,7 +717,7 @@ static int import_property_from_string(struct udev_device *dev, char *line)
                entry = udev_device_add_property(dev, key, val);
                /* store in db, skip private keys */
                if (key[0] != '.')
-                       udev_list_entry_set_flag(entry, 1);
+                       udev_list_entry_set_flags(entry, 1);
        }
        return 0;
 }
@@ -787,7 +785,7 @@ static int import_parent_into_properties(struct udev_device *dev, const char *fi
                        entry = udev_device_add_property(dev, key, val);
                        /* store in db, skip private keys */
                        if (key[0] != '.')
-                               udev_list_entry_set_flag(entry, 1);
+                               udev_list_entry_set_flags(entry, 1);
                }
        }
        return 0;
@@ -1030,7 +1028,6 @@ static int rule_add_key(struct rule_tmp *rule_tmp, enum token_type type,
                if (data != NULL)
                        token->key.mode = *(mode_t *)data;
                break;
-       case TK_A_IGNORE_DEVICE:
        case TK_A_STRING_ESCAPE_NONE:
        case TK_A_STRING_ESCAPE_REPLACE:
        case TK_A_IGNORE_REMOVE:
@@ -1160,6 +1157,9 @@ static int add_rule(struct udev_rules *rules, char *line,
        char *linepos;
        char *attr;
        struct rule_tmp rule_tmp;
+       bool bus_warn = false;
+       bool sysfs_warn = false;
+       bool id_warn = false;
 
        memset(&rule_tmp, 0x00, sizeof(struct rule_tmp));
        rule_tmp.rules = rules;
@@ -1244,8 +1244,7 @@ static int add_rule(struct udev_rules *rules, char *line,
                        continue;
                }
 
-               if (strcmp(key, "KERNELS") == 0 ||
-                   strcmp(key, "ID") == 0) {
+               if (strcmp(key, "KERNELS") == 0) {
                        if (op > OP_MATCH_MAX) {
                                err(rules->udev, "invalid KERNELS operation\n");
                                goto invalid;
@@ -1254,8 +1253,37 @@ static int add_rule(struct udev_rules *rules, char *line,
                        continue;
                }
 
-               if (strcmp(key, "SUBSYSTEMS") == 0 ||
-                   strcmp(key, "BUS") == 0) {
+               if (strcmp(key, "ID") == 0) {
+                       if (!id_warn) {
+                               id_warn = true;
+                               err(rules->udev, "ID= will be removed in a future udev version, "
+                                   "please use KERNEL= to match the event device, or KERNELS= "
+                                   "to match a parent device, in %s:%u\n", filename, lineno);
+                       }
+                       if (op > OP_MATCH_MAX) {
+                               err(rules->udev, "invalid KERNELS operation\n");
+                               goto invalid;
+                       }
+                       rule_add_key(&rule_tmp, TK_M_KERNELS, op, value, NULL);
+                       continue;
+               }
+
+               if (strcmp(key, "SUBSYSTEMS") == 0) {
+                       if (op > OP_MATCH_MAX) {
+                               err(rules->udev, "invalid SUBSYSTEMS operation\n");
+                               goto invalid;
+                       }
+                       rule_add_key(&rule_tmp, TK_M_SUBSYSTEMS, op, value, NULL);
+                       continue;
+               }
+
+               if (strcmp(key, "BUS") == 0) {
+                       if (!bus_warn) {
+                               bus_warn = true;
+                               err(rules->udev, "BUS= will be removed in a future udev version, "
+                                   "please use SUBSYSTEM= to match the event device, or SUBSYSTEMS= "
+                                   "to match a parent device, in %s:%u\n", filename, lineno);
+                       }
                        if (op > OP_MATCH_MAX) {
                                err(rules->udev, "invalid SUBSYSTEMS operation\n");
                                goto invalid;
@@ -1273,8 +1301,7 @@ static int add_rule(struct udev_rules *rules, char *line,
                        continue;
                }
 
-               if (strncmp(key, "ATTRS{", sizeof("ATTRS{")-1) == 0 ||
-                   strncmp(key, "SYSFS{", sizeof("SYSFS{")-1) == 0) {
+               if (strncmp(key, "ATTRS{", sizeof("ATTRS{")-1) == 0) {
                        if (op > OP_MATCH_MAX) {
                                err(rules->udev, "invalid ATTRS operation\n");
                                goto invalid;
@@ -1294,6 +1321,26 @@ static int add_rule(struct udev_rules *rules, char *line,
                        continue;
                }
 
+               if (strncmp(key, "SYSFS{", sizeof("SYSFS{")-1) == 0) {
+                       if (!sysfs_warn) {
+                               sysfs_warn = true;
+                               err(rules->udev, "SYSFS{}= will be removed in a future udev version, "
+                                   "please use ATTR{}= to match the event device, or ATTRS{}= "
+                                   "to match a parent device, in %s:%u\n", filename, lineno);
+                       }
+                       if (op > OP_MATCH_MAX) {
+                               err(rules->udev, "invalid ATTRS operation\n");
+                               goto invalid;
+                       }
+                       attr = get_key_attribute(rules->udev, key + sizeof("ATTRS")-1);
+                       if (attr == NULL) {
+                               err(rules->udev, "error parsing ATTRS attribute\n");
+                               goto invalid;
+                       }
+                       rule_add_key(&rule_tmp, TK_M_ATTRS, op, value, attr);
+                       continue;
+               }
+
                if (strncmp(key, "ENV{", sizeof("ENV{")-1) == 0) {
                        attr = get_key_attribute(rules->udev, key + sizeof("ENV")-1);
                        if (attr == NULL) {
@@ -1496,10 +1543,6 @@ static int add_rule(struct udev_rules *rules, char *line,
                if (strcmp(key, "OPTIONS") == 0) {
                        const char *pos;
 
-                       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);
-                       }
                        if (strstr(value, "ignore_remove") != NULL) {
                                dbg(rules->udev, "remove event should be ignored\n");
                                rule_add_key(&rule_tmp, TK_A_IGNORE_REMOVE, 0, NULL, NULL);
@@ -1736,12 +1779,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");
 
@@ -1794,13 +1831,13 @@ struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names)
                filename_off = add_string(rules, filename);
                /* the offset in the rule is limited to unsigned short */
                if (filename_off < USHRT_MAX)
-                       udev_list_entry_set_flag(file_loop, filename_off);
+                       udev_list_entry_set_flags(file_loop, filename_off);
        }
 
        /* parse list of files */
        udev_list_entry_foreach_safe(file_loop, file_tmp, udev_list_get_entry(&file_list)) {
                const char *filename = udev_list_entry_get_name(file_loop);
-               unsigned int filename_off = udev_list_entry_get_flag(file_loop);
+               unsigned int filename_off = udev_list_entry_get_flags(file_loop);
 
                if (stat(filename, &statbuf) == 0 && statbuf.st_size > 0)
                        parse_file(rules, filename, filename_off);
@@ -2265,11 +2302,6 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
                        if (match_key(rules, cur, event->program_result) != 0)
                                goto nomatch;
                        break;
-
-               case TK_A_IGNORE_DEVICE:
-                       event->ignore_device = 1;
-                       return 0;
-                       break;
                case TK_A_STRING_ESCAPE_NONE:
                        esc = ESCAPE_NONE;
                        break;
@@ -2388,7 +2420,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
                                        entry = udev_device_add_property(event->dev, name, temp_value);
                                        /* store in db, skip private keys */
                                        if (name[0] != '.')
-                                               udev_list_entry_set_flag(entry, 1);
+                                               udev_list_entry_set_flags(entry, 1);
                                } else {
                                        udev_device_add_property(event->dev, name, NULL);
                                }
@@ -2510,7 +2542,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
                                list_entry = udev_list_entry_add(event->udev, &event->run_list,
                                                                 &rules->buf[cur->key.value_off], NULL, 1, 0);
                                if (cur->key.fail_on_error)
-                                       udev_list_entry_set_flag(list_entry, 1);
+                                       udev_list_entry_set_flags(list_entry, 1);
                                break;
                        }
                case TK_A_GOTO: