chiark / gitweb /
udev: remove SYMLINK "unique" option
[elogind.git] / src / udev / udev-rules.c
index 22b91c67974cc6004aec3381fa4e4870daa1e2ef..b3b42fe98958611d98768327b95cb836b116ee30 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2010 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2003-2012 Kay Sievers <kay.sievers@vrfy.org>
  * Copyright (C) 2008 Alan Jenkins <alan-jenkins@tuffmail.co.uk>
  *
  * This program is free software: you can redistribute it and/or modify
@@ -31,6 +31,8 @@
 #include <time.h>
 
 #include "udev.h"
+#include "path-util.h"
+#include "conf-files.h"
 
 #define PREALLOC_TOKEN          2048
 #define PREALLOC_STRBUF         32 * 1024
@@ -200,7 +202,6 @@ struct token {
                         unsigned int value_off;
                         union {
                                 unsigned int attr_off;
-                                int devlink_unique;
                                 unsigned int rule_goto;
                                 mode_t  mode;
                                 uid_t uid;
@@ -743,7 +744,7 @@ static int import_file_into_properties(struct udev_device *dev, const char *file
         FILE *f;
         char line[UTIL_LINE_SIZE];
 
-        f = fopen(filename, "r");
+        f = fopen(filename, "re");
         if (f == NULL)
                 return -1;
         while (fgets(line, sizeof(line), f) != NULL)
@@ -1018,6 +1019,7 @@ static int rule_add_key(struct rule_tmp *rule_tmp, enum token_type type,
         case TK_A_OWNER:
         case TK_A_GROUP:
         case TK_A_MODE:
+        case TK_A_DEVLINK:
         case TK_A_NAME:
         case TK_A_GOTO:
         case TK_M_TAG:
@@ -1037,10 +1039,6 @@ 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)
@@ -1494,17 +1492,11 @@ static int add_rule(struct udev_rules *rules, char *line,
                         continue;
                 }
 
-                if (startswith(key, "SYMLINK")) {
-                        if (op < OP_MATCH_MAX) {
+                if (streq(key, "SYMLINK")) {
+                        if (op < OP_MATCH_MAX)
                                 rule_add_key(&rule_tmp, TK_M_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);
-                        }
+                        else
+                                rule_add_key(&rule_tmp, TK_A_DEVLINK, op, value, NULL);
                         rule_tmp.rule.rule.can_set_name = true;
                         continue;
                 }
@@ -1643,7 +1635,7 @@ static int parse_file(struct udev_rules *rules, const char *filename)
         }
         log_debug("read rules file: %s\n", filename);
 
-        f = fopen(filename, "r");
+        f = fopen(filename, "re");
         if (f == NULL)
                 return -1;
 
@@ -1726,54 +1718,53 @@ struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names)
 
         /* init token array and string buffer */
         rules->tokens = malloc(PREALLOC_TOKEN * sizeof(struct token));
-        if (rules->tokens == NULL) {
-                free(rules);
-                return NULL;
-        }
+        if (rules->tokens == NULL)
+                return udev_rules_unref(rules);
+
         rules->token_max = PREALLOC_TOKEN;
 
         rules->buf = malloc(PREALLOC_STRBUF);
-        if (rules->buf == NULL) {
-                free(rules->tokens);
-                free(rules);
-                return NULL;
-        }
+        if (rules->buf == NULL)
+                return udev_rules_unref(rules);
+
         rules->buf_max = PREALLOC_STRBUF;
         /* offset 0 is always '\0' */
         rules->buf[0] = '\0';
         rules->buf_cur = 1;
 
         rules->trie_nodes = malloc(PREALLOC_TRIE * sizeof(struct trie_node));
-        if (rules->trie_nodes == NULL) {
-                free(rules->buf);
-                free(rules->tokens);
-                free(rules);
-                return NULL;
-        }
+        if (rules->trie_nodes == NULL)
+                return udev_rules_unref(rules);
+
         rules->trie_nodes_max = PREALLOC_TRIE;
         /* offset 0 is the trie root, with an empty string */
         memset(rules->trie_nodes, 0x00, sizeof(struct trie_node));
         rules->trie_nodes_cur = 1;
 
-        rules->dirs = strv_new(TEST_PREFIX SYSCONFDIR "/udev/rules.d",
-                               TEST_PREFIX "/run/udev/rules.d",
-                               TEST_PREFIX UDEVLIBEXECDIR "/rules.d",
+        rules->dirs = strv_new(SYSCONFDIR "/udev/rules.d",
+                               "/run/udev/rules.d",
+                               UDEVLIBEXECDIR "/rules.d",
                                NULL);
         if (!rules->dirs) {
                 log_error("failed to build config directory array");
-                return NULL;
+                return udev_rules_unref(rules);
         }
-        if (!strv_path_canonicalize(rules->dirs)) {
+        if (!path_strv_canonicalize(rules->dirs)) {
                 log_error("failed to canonicalize config directories\n");
-                return NULL;
+                return udev_rules_unref(rules);
         }
         strv_uniq(rules->dirs);
+
+        rules->dirs_ts_usec = calloc(strv_length(rules->dirs), sizeof(long long));
+        if(!rules->dirs_ts_usec)
+                return udev_rules_unref(rules);
+        udev_rules_check_timestamp(rules);
+
         r = conf_files_list_strv(&files, ".rules", (const char **)rules->dirs);
         if (r < 0) {
                 log_error("failed to enumerate rules files: %s\n", strerror(-r));
-                return NULL;
+                return udev_rules_unref(rules);
         }
-        rules->dirs_ts_usec = calloc(strv_length(rules->dirs), sizeof(long long));
 
         /*
          * The offset value in the rules strct is limited; add all
@@ -1856,6 +1847,9 @@ bool udev_rules_check_timestamp(struct udev_rules *rules)
         unsigned int i;
         bool changed = false;
 
+        if (rules == NULL)
+                goto out;
+
         for (i = 0; rules->dirs[i]; i++) {
                 struct stat stats;
 
@@ -1874,7 +1868,7 @@ bool udev_rules_check_timestamp(struct udev_rules *rules)
                 /* update timestamp */
                 rules->dirs_ts_usec[i] = ts_usec(&stats.st_mtim);
         }
-
+out:
         return changed;
 }
 
@@ -2054,7 +2048,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
                         udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(event->dev)) {
                                 const char *devlink;
 
-                                devlink =  udev_list_entry_get_name(list_entry) + strlen(TEST_PREFIX "/dev/");
+                                devlink =  udev_list_entry_get_name(list_entry) + strlen("/dev/");
                                 if (match_key(rules, cur, devlink) == 0) {
                                         match = true;
                                         break;
@@ -2317,7 +2311,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
                         FILE *f;
                         bool imported = false;
 
-                        f = fopen("/proc/cmdline", "r");
+                        f = fopen("/proc/cmdline", "re");
                         if (f != NULL) {
                                 char cmdline[4096];
 
@@ -2528,7 +2522,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
                                         log_debug("%i character(s) replaced\n", count);
                         }
                         if (major(udev_device_get_devnum(event->dev)) &&
-                            (!streq(name_str, udev_device_get_devnode(event->dev) + strlen(TEST_PREFIX "/dev/")))) {
+                            (!streq(name_str, udev_device_get_devnode(event->dev) + strlen("/dev/")))) {
                                 log_error("NAME=\"%s\" ignored, kernel device nodes "
                                     "can not be renamed; please fix it in %s:%u\n", name,
                                     &rules->buf[rule->rule.filename_off], rule->rule.filename_line);
@@ -2573,8 +2567,8 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
                                 next[0] = '\0';
                                 log_debug("LINK '%s' %s:%u\n", pos,
                                           &rules->buf[rule->rule.filename_off], rule->rule.filename_line);
-                                util_strscpyl(filename, sizeof(filename), TEST_PREFIX "/dev/", pos, NULL);
-                                udev_device_add_devlink(event->dev, filename, cur->key.devlink_unique);
+                                util_strscpyl(filename, sizeof(filename), "/dev/", pos, NULL);
+                                udev_device_add_devlink(event->dev, filename);
                                 while (isspace(next[1]))
                                         next++;
                                 pos = &next[1];
@@ -2583,8 +2577,8 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
                         if (pos[0] != '\0') {
                                 log_debug("LINK '%s' %s:%u\n", pos,
                                           &rules->buf[rule->rule.filename_off], rule->rule.filename_line);
-                                util_strscpyl(filename, sizeof(filename), TEST_PREFIX "/dev/", pos, NULL);
-                                udev_device_add_devlink(event->dev, filename, cur->key.devlink_unique);
+                                util_strscpyl(filename, sizeof(filename), "/dev/", pos, NULL);
+                                udev_device_add_devlink(event->dev, filename);
                         }
                         break;
                 }
@@ -2602,7 +2596,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
                         log_debug("ATTR '%s' writing '%s' %s:%u\n", attr, value,
                                   &rules->buf[rule->rule.filename_off],
                                   rule->rule.filename_line);
-                        f = fopen(attr, "w");
+                        f = fopen(attr, "we");
                         if (f != NULL) {
                                 if (fprintf(f, "%s", value) <= 0)
                                         log_error("error writing ATTR{%s}: %m\n", attr);
@@ -2693,7 +2687,7 @@ void udev_rules_apply_static_dev_perms(struct udev_rules *rules)
                         /* we assure, that the permissions tokens are sorted before the static token */
                         if (mode == 0 && uid == 0 && gid == 0)
                                 goto next;
-                        util_strscpyl(filename, sizeof(filename), TEST_PREFIX "/dev/",
+                        util_strscpyl(filename, sizeof(filename), "/dev/",
                                       &rules->buf[cur->key.value_off], NULL);
                         if (stat(filename, &stats) != 0)
                                 goto next;