chiark / gitweb /
udev: allow final assignments :=
authorKay Sievers <kay.sievers@suse.de>
Sun, 5 Jun 2005 02:57:03 +0000 (04:57 +0200)
committerKay Sievers <kay.sievers@suse.de>
Sun, 5 Jun 2005 02:57:03 +0000 (04:57 +0200)
The use of KEY:=<value> will make the key unchangeable by later rules.

Signed-off-by: Kay Sievers <kay.sievers@suse.de>
test/udev-test.pl
udev.h
udev_rules.c
udev_rules.h
udev_rules_parse.c

index 3172d33..27fe354 100755 (executable)
@@ -1306,6 +1306,29 @@ KERNEL=="sda", ACTION=="remove", RUN+="/bin/rm -f %r/testsymlink2"
 KERNEL=="sda", NAME="not-ok2"
 EOF
        },
+       {
+               desc            => "final assignment",
+               subsys          => "block",
+               devpath         => "/block/sda",
+               exp_name        => "ok",
+               exp_perms       => "root:nobody:0640",
+               rules           => <<EOF
+KERNEL=="sda", GROUP:="nobody"
+KERNEL=="sda", GROUP="not-ok", MODE="0640", NAME="ok"
+EOF
+       },
+       {
+               desc            => "final assignment",
+               subsys          => "block",
+               devpath         => "/block/sda",
+               exp_name        => "ok",
+               exp_perms       => "root:nobody:0640",
+               rules           => <<EOF
+KERNEL=="sda", GROUP:="nobody"
+SUBSYSTEM=="block", MODE:="640"
+KERNEL=="sda", GROUP="not-ok", MODE="0666", NAME="ok"
+EOF
+       },
 );
 
 # set env
diff --git a/udev.h b/udev.h
index f7a65c6..c6f26b3 100644 (file)
--- a/udev.h
+++ b/udev.h
@@ -64,11 +64,16 @@ struct udevice {
        char name[PATH_SIZE];
        char devname[PATH_SIZE];
        struct list_head symlink_list;
+       int symlink_final;
        char owner[USER_SIZE];
+       int owner_final;
        char group[USER_SIZE];
+       int group_final;
        mode_t mode;
+       int mode_final;
        dev_t devt;
        struct list_head run_list;
+       int run_final;
 
        char tmp_node[PATH_SIZE];
        int partitions;
index 6f82fac..42509f1 100644 (file)
@@ -754,26 +754,34 @@ int udev_rules_get_name(struct udevice *udev, struct sysfs_class_device *class_d
                        }
 
                        /* apply permissions */
-                       if (rule->mode != 0000) {
+                       if (!udev->mode_final && rule->mode != 0000) {
+                               if (rule->mode_operation == KEY_OP_ASSIGN_FINAL)
+                                       udev->mode_final = 1;
                                udev->mode = rule->mode;
                                dbg("applied mode=%#o to '%s'", udev->mode, udev->kernel_name);
                        }
-                       if (rule->owner[0] != '\0') {
+                       if (!udev->owner_final && rule->owner[0] != '\0') {
+                               if (rule->owner_operation == KEY_OP_ASSIGN_FINAL)
+                                       udev->owner_final = 1;
                                strlcpy(udev->owner, rule->owner, sizeof(udev->owner));
                                apply_format(udev, udev->owner, sizeof(udev->owner), class_dev, sysfs_device);
                                dbg("applied owner='%s' to '%s'", udev->owner, udev->kernel_name);
                        }
-                       if (rule->group[0] != '\0') {
+                       if (!udev->group_final && rule->group[0] != '\0') {
+                               if (rule->group_operation == KEY_OP_ASSIGN_FINAL)
+                                       udev->group_final = 1;
                                strlcpy(udev->group, rule->group, sizeof(udev->group));
                                apply_format(udev, udev->group, sizeof(udev->group), class_dev, sysfs_device);
                                dbg("applied group='%s' to '%s'", udev->group, udev->kernel_name);
                        }
 
                        /* collect symlinks */
-                       if (rule->symlink[0] != '\0') {
+                       if (!udev->symlink_final && rule->symlink[0] != '\0') {
                                char temp[PATH_SIZE];
                                char *pos, *next;
 
+                               if (rule->symlink_operation == KEY_OP_ASSIGN_FINAL)
+                                       udev->symlink_final = 1;
                                info("configured rule in '%s[%i]' applied, added symlink '%s'",
                                     rule->config_file, rule->config_line, rule->symlink);
                                strlcpy(temp, rule->symlink, sizeof(temp));
@@ -808,9 +816,11 @@ int udev_rules_get_name(struct udevice *udev, struct sysfs_class_device *class_d
                                            udev->name, udev->owner, udev->group, udev->mode, udev->partitions);
                        }
 
-                       if (rule->run[0] != '\0') {
+                       if (!udev->run_final && rule->run[0] != '\0') {
                                char program[PATH_SIZE];
 
+                               if (rule->run_operation == KEY_OP_ASSIGN_FINAL)
+                                       udev->run_final = 1;
                                strlcpy(program, rule->run, sizeof(program));
                                apply_format(udev, program, sizeof(program), class_dev, sysfs_device);
                                dbg("add run '%s'", program);
index 5fba2d5..f4a74bb 100644 (file)
@@ -62,6 +62,7 @@ enum key_operation {
        KEY_OP_NOMATCH,
        KEY_OP_ADD,
        KEY_OP_ASSIGN,
+       KEY_OP_ASSIGN_FINAL,
 };
 
 struct key_pair {
@@ -96,10 +97,15 @@ struct udev_rule {
 
        char name[PATH_SIZE];
        char symlink[PATH_SIZE];
+       enum key_operation symlink_operation;
        char owner[USER_SIZE];
+       enum key_operation owner_operation;
        char group[USER_SIZE];
+       enum key_operation group_operation;
        mode_t mode;
+       enum key_operation mode_operation;
        char run[PATH_SIZE];
+       enum key_operation run_operation;
 
        int last_rule;
        int ignore_device;
index e665957..3f07521 100644 (file)
@@ -89,6 +89,8 @@ static int get_key(char **line, char **key, enum key_operation *operation, char
                        break;
                if (linepos[0] == '!')
                        break;
+               if (linepos[0] == ':')
+                       break;
        }
 
        /* remember end of key */
@@ -115,6 +117,10 @@ static int get_key(char **line, char **key, enum key_operation *operation, char
                *operation = KEY_OP_ASSIGN;
                linepos++;
                dbg("operator=assign");
+       } else if (linepos[0] == ':' && linepos[1] == '=') {
+               *operation = KEY_OP_ASSIGN_FINAL;
+               linepos += 2;
+               dbg("operator=assign_final");
        } else
                return -1;
 
@@ -364,30 +370,35 @@ static int rules_parse(const char *filename)
 
                        if (strcasecmp(key, KEY_SYMLINK) == 0) {
                                strlcpy(rule.symlink, value, sizeof(rule.symlink));
+                               rule.symlink_operation = operation;
                                valid = 1;
                                continue;
                        }
 
                        if (strcasecmp(key, KEY_OWNER) == 0) {
                                strlcpy(rule.owner, value, sizeof(rule.owner));
+                               rule.owner_operation = operation;
                                valid = 1;
                                continue;
                        }
 
                        if (strcasecmp(key, KEY_GROUP) == 0) {
                                strlcpy(rule.group, value, sizeof(rule.group));
+                               rule.group_operation = operation;
                                valid = 1;
                                continue;
                        }
 
                        if (strcasecmp(key, KEY_MODE) == 0) {
                                rule.mode = strtol(value, NULL, 8);
+                               rule.mode_operation = operation;
                                valid = 1;
                                continue;
                        }
 
                        if (strcasecmp(key, KEY_RUN) == 0) {
                                strlcpy(rule.run, value, sizeof(rule.run));
+                               rule.run_operation = operation;
                                valid = 1;
                                continue;
                        }