X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=udev%2Fudev-rules.c;h=56a258d8adb920638ccd511f4ec5b1579f697215;hb=325293609392d0feba7a31ca9ed0940c8509c2ea;hp=c24da0c4974e151922eb0e9a571b21308ca90fd4;hpb=38932b9fbac17969721289f2101e9bd1af272112;p=elogind.git diff --git a/udev/udev-rules.c b/udev/udev-rules.c index c24da0c49..56a258d8a 100644 --- a/udev/udev-rules.c +++ b/udev/udev-rules.c @@ -136,6 +136,7 @@ enum token_type { TK_M_SUBSYSTEMS, /* val */ TK_M_DRIVERS, /* val */ TK_M_ATTRS, /* val, attr */ + TK_M_TAGS, /* val */ TK_M_PARENTS_MAX, TK_M_TEST, /* val, mode_t */ @@ -271,6 +272,7 @@ static const char *token_str(enum token_type type) [TK_M_SUBSYSTEMS] = "M SUBSYSTEMS", [TK_M_DRIVERS] = "M DRIVERS", [TK_M_ATTRS] = "M ATTRS", + [TK_M_TAGS] = "M TAGS", [TK_M_PARENTS_MAX] = "M PARENTS_MAX", [TK_M_TEST] = "M TEST", @@ -342,6 +344,7 @@ static void dump_token(struct udev_rules *rules, struct token *token) case TK_M_KERNELS: case TK_M_SUBSYSTEMS: case TK_M_DRIVERS: + case TK_M_TAGS: case TK_M_PROGRAM: case TK_M_IMPORT_FILE: case TK_M_IMPORT_PROG: @@ -1013,6 +1016,7 @@ static int rule_add_key(struct rule_tmp *rule_tmp, enum token_type type, case TK_M_KERNELS: case TK_M_SUBSYSTEMS: case TK_M_DRIVERS: + case TK_M_TAGS: case TK_M_PROGRAM: case TK_M_IMPORT_FILE: case TK_M_IMPORT_PROG: @@ -1342,6 +1346,15 @@ static int add_rule(struct udev_rules *rules, char *line, continue; } + if (strcmp(key, "TAGS") == 0) { + if (op > OP_MATCH_MAX) { + err(rules->udev, "invalid TAGS operation\n"); + goto invalid; + } + rule_add_key(&rule_tmp, TK_M_TAGS, op, value, NULL); + continue; + } + if (strncmp(key, "SYSFS{", sizeof("SYSFS{")-1) == 0) { if (!sysfs_warn) { sysfs_warn = true; @@ -2165,7 +2178,8 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event case TK_M_KERNELS: case TK_M_SUBSYSTEMS: case TK_M_DRIVERS: - case TK_M_ATTRS: { + case TK_M_ATTRS: + case TK_M_TAGS: { struct token *next; /* get whole sequence of parent matches */ @@ -2199,13 +2213,21 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event if (match_attr(rules, event->dev_parent, event, key) != 0) goto try_parent; break; + case TK_M_TAGS: { + bool match = udev_device_has_tag(event->dev_parent, &rules->buf[cur->key.value_off]); + + if (match && key->key.op == OP_NOMATCH) + goto try_parent; + if (!match && key->key.op == OP_MATCH) + goto try_parent; + break; + } default: goto nomatch; } dbg(event->udev, "parent key matched\n"); } dbg(event->udev, "all parent keys matched\n"); - /* all keys matched */ break; try_parent: @@ -2504,11 +2526,15 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event } break; } - case TK_A_TAG: + case TK_A_TAG: { + char tag[UTIL_PATH_SIZE]; + + udev_event_apply_format(event, &rules->buf[cur->key.value_off], tag, sizeof(tag)); if (cur->key.op == OP_ASSIGN || cur->key.op == OP_ASSIGN_FINAL) udev_device_cleanup_tags_list(event->dev); - udev_device_add_tag(event->dev, &rules->buf[cur->key.value_off]); + udev_device_add_tag(event->dev, tag); break; + } case TK_A_NAME: { const char *name = &rules->buf[cur->key.value_off]; char name_str[UTIL_PATH_SIZE]; @@ -2683,8 +2709,9 @@ void udev_rules_apply_static_dev_perms(struct udev_rules *rules) case TK_A_STATIC_NODE: { char filename[UTIL_PATH_SIZE]; struct stat stats; + /* we assure, that the permissions tokens are sorted before the static token */ - if (mode == 0 && uid == 0 && gid == 0) + if (uid == 0 && gid == 0) goto next; util_strscpyl(filename, sizeof(filename), udev_get_dev_path(rules->udev), "/", &rules->buf[cur->key.value_off], NULL); @@ -2692,14 +2719,19 @@ void udev_rules_apply_static_dev_perms(struct udev_rules *rules) goto next; if (!S_ISBLK(stats.st_mode) && !S_ISCHR(stats.st_mode)) goto next; - if (mode != 0 && mode != (stats.st_mode & 0777)) { + + if (mode == 0 && gid > 0) + mode = 0660; + if (mode != (stats.st_mode & 0777)) { chmod(filename, mode); info(rules->udev, "chmod '%s' %#o\n", filename, mode); } + if ((uid != 0 && uid != stats.st_uid) || (gid != 0 && gid != stats.st_gid)) { chown(filename, uid, gid); info(rules->udev, "chown '%s' %u %u\n", filename, uid, gid); } + utimensat(AT_FDCWD, filename, NULL, 0); break; }