diff options
| author | Kay Sievers <kay@vrfy.org> | 2015-03-11 11:15:53 +0100 | 
|---|---|---|
| committer | Kay Sievers <kay@vrfy.org> | 2015-03-11 11:15:53 +0100 | 
| commit | f4cf2e5b2f19d6dadb8c046dc545d222280ffafb (patch) | |
| tree | d6da719825f2d5168e265a749823830bfd9fbf8a /src | |
| parent | 88a60da054759f763e2be7bb88c7f88919c6d46f (diff) | |
udev: add SYSCTL{} support
Diffstat (limited to 'src')
| -rw-r--r-- | src/udev/udev-rules.c | 61 | 
1 files changed, 59 insertions, 2 deletions
| diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index e8387d793a..4262119886 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -35,6 +35,7 @@  #include "strbuf.h"  #include "strv.h"  #include "util.h" +#include "sysctl-util.h"  #define PREALLOC_TOKEN          2048 @@ -128,6 +129,7 @@ enum token_type {          TK_M_DRIVER,                    /* val */          TK_M_WAITFOR,                   /* val */          TK_M_ATTR,                      /* val, attr */ +        TK_M_SYSCTL,                    /* val, attr */          TK_M_PARENTS_MIN,          TK_M_KERNELS,                   /* val */ @@ -166,6 +168,7 @@ enum token_type {          TK_A_NAME,                      /* val */          TK_A_DEVLINK,                   /* val */          TK_A_ATTR,                      /* val, attr */ +        TK_A_SYSCTL,                    /* val, attr */          TK_A_RUN_BUILTIN,               /* val, bool */          TK_A_RUN_PROGRAM,               /* val, bool */          TK_A_GOTO,                      /* size_t */ @@ -262,6 +265,7 @@ static const char *token_str(enum token_type type) {                  [TK_M_DRIVER] =                 "M DRIVER",                  [TK_M_WAITFOR] =                "M WAITFOR",                  [TK_M_ATTR] =                   "M ATTR", +                [TK_M_SYSCTL] =                 "M SYSCTL",                  [TK_M_PARENTS_MIN] =            "M PARENTS_MIN",                  [TK_M_KERNELS] =                "M KERNELS", @@ -300,6 +304,7 @@ static const char *token_str(enum token_type type) {                  [TK_A_NAME] =                   "A NAME",                  [TK_A_DEVLINK] =                "A DEVLINK",                  [TK_A_ATTR] =                   "A ATTR", +                [TK_A_SYSCTL] =                 "A SYSCTL",                  [TK_A_RUN_BUILTIN] =            "A RUN_BUILTIN",                  [TK_A_RUN_PROGRAM] =            "A RUN_PROGRAM",                  [TK_A_GOTO] =                   "A GOTO", @@ -363,9 +368,11 @@ static void dump_token(struct udev_rules *rules, struct token *token) {                  log_debug("%s %i '%s'", token_str(type), token->key.builtin_cmd, value);                  break;          case TK_M_ATTR: +        case TK_M_SYSCTL:          case TK_M_ATTRS:          case TK_M_ENV:          case TK_A_ATTR: +        case TK_A_SYSCTL:          case TK_A_ENV:                  log_debug("%s %s '%s' '%s'(%s)",                            token_str(type), operation_str(op), attr, value, string_glob_str(glob)); @@ -897,8 +904,10 @@ static int rule_add_key(struct rule_tmp *rule_tmp, enum token_type type,                  break;          case TK_M_ENV:          case TK_M_ATTR: +        case TK_M_SYSCTL:          case TK_M_ATTRS:          case TK_A_ATTR: +        case TK_A_SYSCTL:          case TK_A_ENV:          case TK_A_SECLABEL:                  attr = data; @@ -1135,11 +1144,27 @@ static int add_rule(struct udev_rules *rules, char *line,                                  log_error("invalid ATTR operation");                                  goto invalid;                          } -                        if (op < OP_MATCH_MAX) { +                        if (op < OP_MATCH_MAX)                                  rule_add_key(&rule_tmp, TK_M_ATTR, op, value, attr); -                        } else { +                        else                                  rule_add_key(&rule_tmp, TK_A_ATTR, op, value, attr); +                        continue; +                } + +                if (startswith(key, "SYSCTL{")) { +                        attr = get_key_attribute(rules->udev, key + strlen("SYSCTL")); +                        if (attr == NULL) { +                                log_error("error parsing SYSCTL attribute"); +                                goto invalid; +                        } +                        if (op == OP_REMOVE) { +                                log_error("invalid SYSCTL operation"); +                                goto invalid;                          } +                        if (op < OP_MATCH_MAX) +                                rule_add_key(&rule_tmp, TK_M_SYSCTL, op, value, attr); +                        else +                                rule_add_key(&rule_tmp, TK_A_SYSCTL, op, value, attr);                          continue;                  } @@ -1986,6 +2011,23 @@ int udev_rules_apply_to_event(struct udev_rules *rules,                          if (match_attr(rules, event->dev, event, cur) != 0)                                  goto nomatch;                          break; +                case TK_M_SYSCTL: { +                        char filename[UTIL_PATH_SIZE]; +                        _cleanup_free_ char *value = NULL; +                        size_t len; + +                        udev_event_apply_format(event, rules_str(rules, cur->key.attr_off), filename, sizeof(filename)); +                        sysctl_normalize(filename); +                        if (sysctl_read(filename, &value) < 0) +                                goto nomatch; + +                        len = strlen(value); +                        while (len > 0 && isspace(value[--len])) +                                value[len] = '\0'; +                        if (match_key(rules, cur, value) != 0) +                                goto nomatch; +                        break; +                }                  case TK_M_KERNELS:                  case TK_M_SUBSYSTEMS:                  case TK_M_DRIVERS: @@ -2522,6 +2564,21 @@ int udev_rules_apply_to_event(struct udev_rules *rules,                          }                          break;                  } +                case TK_A_SYSCTL: { +                        char filename[UTIL_PATH_SIZE]; +                        char value[UTIL_NAME_SIZE]; +                        int r; + +                        udev_event_apply_format(event, rules_str(rules, cur->key.attr_off), filename, sizeof(filename)); +                        sysctl_normalize(filename); +                        udev_event_apply_format(event, rules_str(rules, cur->key.value_off), value, sizeof(value)); +                        log_debug("SYSCTL '%s' writing '%s' %s:%u", filename, value, +                                  rules_str(rules, rule->rule.filename_off), rule->rule.filename_line); +                        r = sysctl_write(filename, value); +                        if (r < 0) +                                log_error("error writing SYSCTL{%s}='%s': %s", filename, value, strerror(-r)); +                        break; +                }                  case TK_A_RUN_BUILTIN:                  case TK_A_RUN_PROGRAM: {                          struct udev_list_entry *entry; | 
