]>
git.ipfire.org Git - thirdparty/systemd.git/blob - udev_rules.c
4 * Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
5 * Copyright (C) 2003-2006 Kay Sievers <kay.sievers@vrfy.org>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation version 2 of the License.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 675 Mass Ave, Cambridge, MA 02139, USA.
35 #include "udev_rules.h"
38 /* extract possible {attr} and move str behind it */
39 static char *get_format_attribute(char **str
)
45 pos
= strchr(*str
, '}');
47 err("missing closing brace for format");
53 dbg("attribute='%s', str='%s'", attr
, *str
);
58 /* extract possible format length and move str behind it*/
59 static int get_format_len(char **str
)
64 if (isdigit(*str
[0])) {
65 num
= (int) strtoul(*str
, &tail
, 10);
68 dbg("format length=%i", num
);
71 err("format parsing error '%s'", *str
);
77 static int get_key(char **line
, char **key
, char **value
)
86 if (strchr(linepos
, '\\')) {
87 dbg("escaped characters are not supported, skip");
92 while (isspace(linepos
[0]))
99 if (linepos
[0] == '\0')
101 if (isspace(linepos
[0]))
103 if (linepos
[0] == '=')
111 /* skip whitespace */
112 while (isspace(linepos
[0]))
116 if (linepos
[0] == '"') {
118 temp
= strchr(linepos
, '"');
120 dbg("missing closing quote");
123 dbg("value is quoted");
125 } else if (linepos
[0] == '\'') {
127 temp
= strchr(linepos
, '\'');
129 dbg("missing closing quote");
132 dbg("value is quoted");
134 } else if (linepos
[0] == '\0') {
135 dbg("value is empty");
138 while (temp
[0] && !isspace(temp
[0]))
147 static int import_keys_into_env(struct udevice
*udev
, const char *buf
, size_t bufsize
)
149 char line
[LINE_SIZE
];
158 /* loop through the whole buffer */
161 while (cur
< bufsize
) {
162 count
= buf_get_line(buf
, bufsize
, cur
);
167 if (count
>= sizeof(line
)) {
168 err("line too long, conf line skipped %s, line %d", udev_config_filename
, lineno
);
172 /* eat the whitespace */
173 while ((count
> 0) && isspace(bufline
[0])) {
180 /* see if this is a comment */
181 if (bufline
[0] == COMMENT_CHARACTER
)
184 memcpy(line
, bufline
, count
);
188 if (get_key(&linepos
, &variable
, &value
) == 0) {
189 dbg("import '%s=%s'", variable
, value
);
190 name_list_key_add(&udev
->env_list
, variable
, value
);
191 setenv(variable
, value
, 1);
198 static int import_file_into_env(struct udevice
*udev
, const char *filename
)
203 if (file_map(filename
, &buf
, &bufsize
) != 0) {
204 err("can't open '%s': %s", filename
, strerror(errno
));
207 import_keys_into_env(udev
, buf
, bufsize
);
208 file_unmap(buf
, bufsize
);
213 static int import_program_into_env(struct udevice
*udev
, const char *program
)
218 if (run_program(program
, udev
->dev
->subsystem
, result
, sizeof(result
), &reslen
, (udev_log_priority
>= LOG_INFO
)) != 0)
220 return import_keys_into_env(udev
, result
, reslen
);
223 static int import_parent_into_env(struct udevice
*udev
, const char *filter
)
225 struct sysfs_device
*dev_parent
;
228 dev_parent
= sysfs_device_get_parent(udev
->dev
);
229 if (dev_parent
!= NULL
) {
230 struct udevice
*udev_parent
;
231 struct name_entry
*name_loop
;
233 dbg("found parent '%s', get the node name", dev_parent
->devpath
);
234 udev_parent
= udev_device_init();
235 if (udev_parent
== NULL
)
237 /* import the udev_db of the parent */
238 if (udev_db_get_device(udev_parent
, dev_parent
->devpath
) == 0) {
239 dbg("import stored parent env '%s'", udev_parent
->name
);
240 list_for_each_entry(name_loop
, &udev_parent
->env_list
, node
) {
241 char name
[NAME_SIZE
];
244 strlcpy(name
, name_loop
->name
, sizeof(name
));
245 pos
= strchr(name
, '=');
249 if (strcmp_pattern(filter
, name
) == 0) {
250 dbg("import key '%s'", name_loop
->name
);
251 name_list_add(&udev
->env_list
, name_loop
->name
, 0);
252 setenv(name
, pos
, 1);
254 dbg("skip key '%s'", name_loop
->name
);
259 dbg("parent not found in database");
260 udev_device_cleanup(udev_parent
);
266 static int match_name_and_get_number(const char *base
, const char *devname
)
272 baselen
= strlen(base
);
273 if (strncmp(base
, devname
, baselen
) != 0)
275 if (devname
[baselen
] == '\0')
277 if (!isdigit(devname
[baselen
]))
279 num
= strtoul(&devname
[baselen
], &endptr
, 10);
280 if (endptr
[0] != '\0')
285 /* finds the lowest positive device number such that <name>N isn't present in the udevdb
286 * if <name> doesn't exist, 0 is returned, N otherwise */
287 static int find_free_number(const char *base
, const char *devpath
)
289 char db_devpath
[PATH_SIZE
];
290 char filename
[PATH_SIZE
];
291 struct udevice
*udev_db
;
296 err("%%e is deprecated, will be removed and is unlikely to work correctly. Don't use it.");
300 /* check if the device already owns a matching name */
301 udev_db
= udev_device_init();
304 if (udev_db_get_device(udev_db
, devpath
) == 0) {
305 struct name_entry
*name_loop
;
308 devnum
= match_name_and_get_number(base
, udev_db
->name
);
311 dbg("device '%s', already has the node '%s' with num %u, use it", devpath
, base
, num
);
314 list_for_each_entry(name_loop
, &udev_db
->symlink_list
, node
) {
315 devnum
= match_name_and_get_number(base
, name_loop
->name
);
318 dbg("device '%s', already has a symlink '%s' with num %u, use it", devpath
, base
, num
);
324 /* just search the database again and again until a free name is found */
325 strlcpy(filename
, base
, sizeof(filename
));
327 dbg("look for existing node '%s'", filename
);
328 if (udev_db_lookup_name(filename
, db_devpath
, sizeof(db_devpath
)) != 0) {
329 dbg("free num=%d", num
);
335 err("find_free_number aborted at num=%d", num
);
339 snprintf(filename
, sizeof(filename
), "%s%d", base
, num
);
340 filename
[sizeof(filename
)-1] = '\0';
344 udev_device_cleanup(udev_db
);
348 #define WAIT_LOOP_PER_SECOND 50
349 static int wait_for_sysfs(struct udevice
*udev
, const char *file
, int timeout
)
351 char devicepath
[PATH_SIZE
];
352 char filepath
[PATH_SIZE
];
354 int loop
= timeout
* WAIT_LOOP_PER_SECOND
;
356 strlcpy(devicepath
, sysfs_path
, sizeof(devicepath
));
357 strlcat(devicepath
, udev
->dev
->devpath
, sizeof(devicepath
));
358 strlcpy(filepath
, devicepath
, sizeof(filepath
));
359 strlcat(filepath
, "/", sizeof(filepath
));
360 strlcat(filepath
, file
, sizeof(filepath
));
362 dbg("will wait %i sec for '%s'", timeout
, filepath
);
365 if (stat(filepath
, &stats
) == 0) {
366 info("file '%s' appeared after %i loops", filepath
, (timeout
* WAIT_LOOP_PER_SECOND
) - loop
-1);
369 /* make sure the device does not have disappeared in the meantime */
370 if (stat(devicepath
, &stats
) != 0) {
371 info("device disappeared while waiting for '%s'", filepath
);
374 info("wait for '%s' for %i mseconds", filepath
, 1000 / WAIT_LOOP_PER_SECOND
);
375 usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND
);
377 err("waiting for '%s' failed", filepath
);
381 void udev_rules_apply_format(struct udevice
*udev
, char *string
, size_t maxsize
)
383 char temp
[PATH_SIZE
];
384 char temp2
[PATH_SIZE
];
385 char *head
, *tail
, *pos
, *cpos
, *attr
, *rest
;
389 unsigned int next_free_number
;
407 static const struct subst_map
{
410 enum subst_type type
;
412 { .name
= "devpath", .fmt
= 'p', .type
= SUBST_DEVPATH
},
413 { .name
= "number", .fmt
= 'n', .type
= SUBST_KERNEL_NUMBER
},
414 { .name
= "kernel", .fmt
= 'k', .type
= SUBST_KERNEL_NAME
},
415 { .name
= "id", .fmt
= 'b', .type
= SUBST_ID
},
416 { .name
= "major", .fmt
= 'M', .type
= SUBST_MAJOR
},
417 { .name
= "minor", .fmt
= 'm', .type
= SUBST_MINOR
},
418 { .name
= "result", .fmt
= 'c', .type
= SUBST_RESULT
},
419 { .name
= "sysfs", .fmt
= 's', .type
= SUBST_SYSFS
},
420 { .name
= "enum", .fmt
= 'e', .type
= SUBST_ENUM
},
421 { .name
= "parent", .fmt
= 'P', .type
= SUBST_PARENT
},
422 { .name
= "tempnode", .fmt
= 'N', .type
= SUBST_TEMP_NODE
},
423 { .name
= "root", .fmt
= 'r', .type
= SUBST_ROOT
},
424 { .name
= "modalias", .fmt
= 'A', .type
= SUBST_MODALIAS
},
425 { .name
= "env", .fmt
= 'E', .type
= SUBST_ENV
},
428 enum subst_type type
;
429 const struct subst_map
*subst
;
434 while (head
[0] != '\0') {
435 if (head
[0] == '$') {
436 /* substitute named variable */
439 if (head
[1] == '$') {
440 strlcpy(temp
, head
+2, sizeof(temp
));
441 strlcpy(head
+1, temp
, maxsize
);
446 for (subst
= map
; subst
->name
; subst
++) {
447 if (strncasecmp(&head
[1], subst
->name
, strlen(subst
->name
)) == 0) {
449 tail
= head
+ strlen(subst
->name
)+1;
450 dbg("will substitute format name '%s'", subst
->name
);
454 } else if (head
[0] == '%') {
455 /* substitute format char */
458 if (head
[1] == '%') {
459 strlcpy(temp
, head
+2, sizeof(temp
));
460 strlcpy(head
+1, temp
, maxsize
);
466 len
= get_format_len(&tail
);
467 for (subst
= map
; subst
->name
; subst
++) {
468 if (tail
[0] == subst
->fmt
) {
471 dbg("will substitute format char '%c'", subst
->fmt
);
480 attr
= get_format_attribute(&tail
);
481 strlcpy(temp
, tail
, sizeof(temp
));
482 dbg("format=%i, string='%s', tail='%s'", type
,string
, tail
);
486 strlcat(string
, udev
->dev
->devpath
, maxsize
);
487 dbg("substitute devpath '%s'", udev
->dev
->devpath
);
489 case SUBST_KERNEL_NAME
:
490 strlcat(string
, udev
->dev
->kernel_name
, maxsize
);
491 dbg("substitute kernel name '%s'", udev
->dev
->kernel_name
);
493 case SUBST_KERNEL_NUMBER
:
494 strlcat(string
, udev
->dev
->kernel_number
, maxsize
);
495 dbg("substitute kernel number '%s'", udev
->dev
->kernel_number
);
498 if (udev
->dev_parent
!= NULL
) {
499 strlcat(string
, udev
->dev_parent
->kernel_name
, maxsize
);
500 dbg("substitute id '%s'", udev
->dev_parent
->kernel_name
);
504 sprintf(temp2
, "%d", major(udev
->devt
));
505 strlcat(string
, temp2
, maxsize
);
506 dbg("substitute major number '%s'", temp2
);
509 sprintf(temp2
, "%d", minor(udev
->devt
));
510 strlcat(string
, temp2
, maxsize
);
511 dbg("substitute minor number '%s'", temp2
);
514 if (udev
->program_result
[0] == '\0')
516 /* get part part of the result string */
519 i
= strtoul(attr
, &rest
, 10);
521 dbg("request part #%d of result string", i
);
522 cpos
= udev
->program_result
;
524 while (cpos
[0] != '\0' && !isspace(cpos
[0]))
526 while (isspace(cpos
[0]))
530 err("requested part of result string not found");
533 strlcpy(temp2
, cpos
, sizeof(temp2
));
534 /* %{2+}c copies the whole string from the second part on */
535 if (rest
[0] != '+') {
536 cpos
= strchr(temp2
, ' ');
540 strlcat(string
, temp2
, maxsize
);
541 dbg("substitute part of result string '%s'", temp2
);
543 strlcat(string
, udev
->program_result
, maxsize
);
544 dbg("substitute result string '%s'", udev
->program_result
);
549 dbg("missing attribute");
552 struct sysfs_device
*dev_parent
;
555 dev_parent
= udev
->dev
;
557 dbg("looking at '%s'", dev_parent
->devpath
);
558 value
= sysfs_attr_get_value(dev_parent
->devpath
, attr
);
560 strlcpy(temp2
, value
, sizeof(temp2
));
563 dev_parent
= sysfs_device_get_parent(dev_parent
);
564 } while (dev_parent
!= NULL
);
566 /* strip trailing whitespace of sysfs value */
568 while (i
> 0 && isspace(temp2
[i
-1]))
570 count
= replace_untrusted_chars(temp2
);
572 info("%i untrusted character(s) replaced" , count
);
573 strlcat(string
, temp2
, maxsize
);
574 dbg("substitute sysfs value '%s'", temp2
);
578 next_free_number
= find_free_number(string
, udev
->dev
->devpath
);
579 if (next_free_number
> 0) {
580 sprintf(temp2
, "%d", next_free_number
);
581 strlcat(string
, temp2
, maxsize
);
586 struct sysfs_device
*dev_parent
;
588 dev_parent
= sysfs_device_get_parent(udev
->dev
);
589 if (dev_parent
!= NULL
) {
590 struct udevice
*udev_parent
;
592 dbg("found parent '%s', get the node name", dev_parent
->devpath
);
593 udev_parent
= udev_device_init();
594 if (udev_parent
!= NULL
) {
595 /* lookup the name in the udev_db with the DEVPATH of the parent */
596 if (udev_db_get_device(udev_parent
, dev_parent
->devpath
) == 0) {
597 strlcat(string
, udev_parent
->name
, maxsize
);
598 dbg("substitute parent node name'%s'", udev_parent
->name
);
600 dbg("parent not found in database");
601 udev_device_cleanup(udev_parent
);
606 case SUBST_TEMP_NODE
:
607 if (udev
->tmp_node
[0] == '\0') {
608 dbg("create temporary device node for callout");
609 snprintf(udev
->tmp_node
, sizeof(udev
->tmp_node
), "%s/.tmp-%u-%u",
610 udev_root
, major(udev
->devt
), minor(udev
->devt
));
611 udev
->tmp_node
[sizeof(udev
->tmp_node
)-1] = '\0';
612 udev_node_mknod(udev
, udev
->tmp_node
, udev
->devt
, 0600, 0, 0);
614 strlcat(string
, udev
->tmp_node
, maxsize
);
615 dbg("substitute temporary device node name '%s'", udev
->tmp_node
);
618 strlcat(string
, udev_root
, maxsize
);
619 dbg("substitute udev_root '%s'", udev_root
);
627 err("$modalias is deprecated, use $env{MODALIAS} or "
628 "$sysfs{modalias} instead.");
632 value
= sysfs_attr_get_value(udev
->dev
->devpath
, "modalias");
634 strlcat(string
, value
, maxsize
);
635 dbg("substitute MODALIAS '%s'", temp2
);
641 dbg("missing attribute");
646 dbg("env '%s' not available", attr
);
649 dbg("substitute env '%s=%s'", attr
, pos
);
650 strlcat(string
, pos
, maxsize
);
653 err("unknown substitution type=%i", type
);
656 /* possibly truncate to format-char specified length */
659 dbg("truncate to %i chars, subtitution string becomes '%s'", len
, head
);
661 strlcat(string
, temp
, maxsize
);
665 static char *key_val(struct udev_rule
*rule
, struct key
*key
)
667 return rule
->buf
+ key
->val_off
;
670 static char *key_pair_name(struct udev_rule
*rule
, struct key_pair
*pair
)
672 return rule
->buf
+ pair
->key_name_off
;
675 static int match_key(const char *key_name
, struct udev_rule
*rule
, struct key
*key
, const char *val
)
678 char value
[PATH_SIZE
];
682 if (key
->operation
!= KEY_OP_MATCH
&&
683 key
->operation
!= KEY_OP_NOMATCH
)
686 strlcpy(value
, rule
->buf
+ key
->val_off
, sizeof(value
));
689 dbg("key %s value='%s'", key_name
, key_value
);
691 pos
= strchr(key_value
, '|');
696 dbg("match %s '%s' <-> '%s'", key_name
, key_value
, val
);
697 match
= (strcmp_pattern(key_value
, val
) == 0);
698 if (match
&& (key
->operation
!= KEY_OP_NOMATCH
)) {
699 dbg("%s is true (matching value)", key_name
);
702 if (!match
&& (key
->operation
== KEY_OP_NOMATCH
)) {
703 dbg("%s is true (non-matching value)", key_name
);
708 dbg("%s is false", key_name
);
712 /* match a single rule against a given device and possibly its parent devices */
713 static int match_rule(struct udevice
*udev
, struct udev_rule
*rule
)
717 if (match_key("ACTION", rule
, &rule
->action
, udev
->action
))
720 if (match_key("KERNEL", rule
, &rule
->kernel_name
, udev
->dev
->kernel_name
))
723 if (match_key("SUBSYSTEM", rule
, &rule
->subsystem
, udev
->dev
->subsystem
))
726 if (match_key("DEVPATH", rule
, &rule
->devpath
, udev
->dev
->devpath
))
729 /* compare NAME against a previously assigned value */
730 if (match_key("NAME", rule
, &rule
->name
, udev
->name
))
733 if (rule
->modalias
.operation
!= KEY_OP_UNSET
) {
738 err("MODALIAS is deprecated, use ENV{MODALIAS} or SYSFS{modalias} instead.");
742 value
= sysfs_attr_get_value(udev
->dev
->devpath
, "modalias");
744 dbg("MODALIAS value not found");
747 if (match_key("MODALIAS", rule
, &rule
->modalias
, value
))
751 for (i
= 0; i
< rule
->env
.count
; i
++) {
752 struct key_pair
*pair
= &rule
->env
.keys
[i
];
754 /* we only check for matches, assignments will be handled later */
755 if (pair
->key
.operation
== KEY_OP_MATCH
||
756 pair
->key
.operation
== KEY_OP_NOMATCH
) {
757 const char *key_name
= key_pair_name(rule
, pair
);
758 const char *value
= getenv(key_name
);
761 dbg("ENV{'%s'} is not set, treat as empty", key_name
);
764 if (match_key("ENV", rule
, &pair
->key
, value
))
769 if (rule
->wait_for_sysfs
.operation
!= KEY_OP_UNSET
) {
772 found
= (wait_for_sysfs(udev
, key_val(rule
, &rule
->wait_for_sysfs
), 3) == 0);
773 if (!found
&& (rule
->wait_for_sysfs
.operation
!= KEY_OP_NOMATCH
)) {
774 dbg("WAIT_FOR_SYSFS failed");
779 /* walk up the chain of parent devices and find a match */
780 udev
->dev_parent
= udev
->dev
;
782 /* check for matching driver */
783 if (match_key("DRIVER", rule
, &rule
->driver
, udev
->dev_parent
->driver
))
786 /* check for matching subsystem/bus value */
787 if (match_key("BUS", rule
, &rule
->bus
, udev
->dev_parent
->subsystem
))
790 /* check for matching bus id (device name) */
791 if (match_key("ID", rule
, &rule
->id
, udev
->dev_parent
->kernel_name
))
794 /* check for matching sysfs pairs */
795 if (rule
->sysfs
.count
) {
796 dbg("check %i SYSFS keys", rule
->sysfs
.count
);
797 for (i
= 0; i
< rule
->sysfs
.count
; i
++) {
798 struct key_pair
*pair
= &rule
->sysfs
.keys
[i
];
799 const char *key_name
= key_pair_name(rule
, pair
);
800 const char *key_value
= key_val(rule
, &pair
->key
);
802 char val
[VALUE_SIZE
];
805 value
= sysfs_attr_get_value(udev
->dev_parent
->devpath
, key_name
);
807 value
= sysfs_attr_get_value(udev
->dev
->devpath
, key_name
);
810 strlcpy(val
, value
, sizeof(val
));
812 /* strip trailing whitespace of value, if not asked to match for it */
813 len
= strlen(key_value
);
814 if (len
> 0 && !isspace(key_value
[len
-1])) {
816 while (len
> 0 && isspace(val
[len
-1]))
818 dbg("removed %zi trailing whitespace chars from '%s'", strlen(val
)-len
, val
);
821 if (match_key("SYSFS", rule
, &pair
->key
, val
))
824 dbg("all %i SYSFS keys matched", rule
->sysfs
.count
);
827 /* found matching device */
830 /* move to parent device */
831 dbg("try parent sysfs device");
832 udev
->dev_parent
= sysfs_device_get_parent(udev
->dev_parent
);
833 if (udev
->dev_parent
== NULL
)
835 dbg("looking at dev_parent->devpath='%s'", udev
->dev_parent
->devpath
);
836 dbg("looking at dev_parent->bus_kernel_name='%s'", udev
->dev_parent
->kernel_name
);
839 /* execute external program */
840 if (rule
->program
.operation
!= KEY_OP_UNSET
) {
841 char program
[PATH_SIZE
];
842 char result
[PATH_SIZE
];
844 strlcpy(program
, key_val(rule
, &rule
->program
), sizeof(program
));
845 udev_rules_apply_format(udev
, program
, sizeof(program
));
846 if (run_program(program
, udev
->dev
->subsystem
, result
, sizeof(result
), NULL
, (udev_log_priority
>= LOG_INFO
)) != 0) {
847 dbg("PROGRAM is false");
848 udev
->program_result
[0] = '\0';
849 if (rule
->program
.operation
!= KEY_OP_NOMATCH
)
854 dbg("PROGRAM matches");
855 remove_trailing_chars(result
, '\n');
856 count
= replace_untrusted_chars(result
);
858 info("%i untrusted character(s) replaced" , count
);
859 dbg("result is '%s'", result
);
860 strlcpy(udev
->program_result
, result
, sizeof(udev
->program_result
));
861 dbg("PROGRAM returned successful");
862 if (rule
->program
.operation
== KEY_OP_NOMATCH
)
865 dbg("PROGRAM key is true");
868 /* check for matching result of external program */
869 if (match_key("RESULT", rule
, &rule
->result
, udev
->program_result
))
872 /* import variables returned from program or or file into environment */
873 if (rule
->import
.operation
!= KEY_OP_UNSET
) {
874 char import
[PATH_SIZE
];
877 strlcpy(import
, key_val(rule
, &rule
->import
), sizeof(import
));
878 udev_rules_apply_format(udev
, import
, sizeof(import
));
879 dbg("check for IMPORT import='%s'", import
);
880 if (rule
->import_type
== IMPORT_PROGRAM
) {
881 rc
= import_program_into_env(udev
, import
);
882 } else if (rule
->import_type
== IMPORT_FILE
) {
883 dbg("import file import='%s'", import
);
884 rc
= import_file_into_env(udev
, import
);
885 } else if (rule
->import_type
== IMPORT_PARENT
) {
886 dbg("import parent import='%s'", import
);
887 rc
= import_parent_into_env(udev
, import
);
890 dbg("IMPORT failed");
891 if (rule
->import
.operation
!= KEY_OP_NOMATCH
)
894 dbg("IMPORT '%s' imported", key_val(rule
, &rule
->import
));
895 dbg("IMPORT key is true");
898 /* rule matches, if we have ENV assignments export it */
899 for (i
= 0; i
< rule
->env
.count
; i
++) {
900 struct key_pair
*pair
= &rule
->env
.keys
[i
];
902 if (pair
->key
.operation
== KEY_OP_ASSIGN
) {
903 const char *key_name
= key_pair_name(rule
, pair
);
904 const char *value
= key_val(rule
, &pair
->key
);
905 char *key_value
= name_list_key_add(&udev
->env_list
, key_name
, value
);
906 if (key_value
== NULL
)
909 udev_rules_apply_format(udev
, key_value
, NAME_SIZE
);
911 dbg("export ENV '%s'", key_value
);
921 int udev_rules_get_name(struct udev_rules
*rules
, struct udevice
*udev
)
923 struct udev_rule
*rule
;
926 dbg("udev->dev->devpath='%s'", udev
->dev
->devpath
);
927 dbg("udev->dev->kernel_name='%s'", udev
->dev
->kernel_name
);
929 /* look for a matching rule to apply */
930 udev_rules_iter_init(rules
);
932 rule
= udev_rules_iter_next(rules
);
937 (rule
->name
.operation
== KEY_OP_ASSIGN
||
938 rule
->name
.operation
== KEY_OP_ASSIGN_FINAL
||
939 rule
->name
.operation
== KEY_OP_ADD
)) {
940 dbg("node name already set, rule ignored");
945 if (match_rule(udev
, rule
) == 0) {
947 if (rule
->ignore_device
) {
948 info("rule applied, '%s' is ignored", udev
->dev
->kernel_name
);
949 udev
->ignore_device
= 1;
952 if (rule
->ignore_remove
) {
953 udev
->ignore_remove
= 1;
954 dbg("remove event should be ignored");
956 /* apply all_partitions option only at a main block device */
957 if (rule
->partitions
&&
958 strcmp(udev
->dev
->subsystem
, "block") == 0 && udev
->dev
->kernel_number
[0] == '\0') {
959 udev
->partitions
= rule
->partitions
;
960 dbg("creation of partition nodes requested");
963 /* apply permissions */
964 if (!udev
->mode_final
&& rule
->mode
!= 0000) {
965 if (rule
->mode_operation
== KEY_OP_ASSIGN_FINAL
)
966 udev
->mode_final
= 1;
967 udev
->mode
= rule
->mode
;
968 dbg("applied mode=%#o to '%s'", rule
->mode
, udev
->dev
->kernel_name
);
970 if (!udev
->owner_final
&& rule
->owner
.operation
!= KEY_OP_UNSET
) {
971 if (rule
->owner
.operation
== KEY_OP_ASSIGN_FINAL
)
972 udev
->owner_final
= 1;
973 strlcpy(udev
->owner
, key_val(rule
, &rule
->owner
), sizeof(udev
->owner
));
974 udev_rules_apply_format(udev
, udev
->owner
, sizeof(udev
->owner
));
975 dbg("applied owner='%s' to '%s'", udev
->owner
, udev
->dev
->kernel_name
);
977 if (!udev
->group_final
&& rule
->group
.operation
!= KEY_OP_UNSET
) {
978 if (rule
->group
.operation
== KEY_OP_ASSIGN_FINAL
)
979 udev
->group_final
= 1;
980 strlcpy(udev
->group
, key_val(rule
, &rule
->group
), sizeof(udev
->group
));
981 udev_rules_apply_format(udev
, udev
->group
, sizeof(udev
->group
));
982 dbg("applied group='%s' to '%s'", udev
->group
, udev
->dev
->kernel_name
);
985 /* collect symlinks */
986 if (!udev
->symlink_final
&& rule
->symlink
.operation
!= KEY_OP_UNSET
) {
987 char temp
[PATH_SIZE
];
991 if (rule
->symlink
.operation
== KEY_OP_ASSIGN_FINAL
)
992 udev
->symlink_final
= 1;
993 if (rule
->symlink
.operation
== KEY_OP_ASSIGN
|| rule
->symlink
.operation
== KEY_OP_ASSIGN_FINAL
) {
994 info("reset symlink list");
995 name_list_cleanup(&udev
->symlink_list
);
997 strlcpy(temp
, key_val(rule
, &rule
->symlink
), sizeof(temp
));
998 udev_rules_apply_format(udev
, temp
, sizeof(temp
));
999 count
= replace_untrusted_chars(temp
);
1001 info("%i untrusted character(s) replaced" , count
);
1002 dbg("rule applied, added symlink(s) '%s'", temp
);
1004 /* add multiple symlinks separated by spaces */
1006 while (isspace(pos
[0]))
1008 next
= strchr(pos
, ' ');
1011 info("add symlink '%s'", pos
);
1012 name_list_add(&udev
->symlink_list
, pos
, 0);
1013 while (isspace(next
[1]))
1016 next
= strchr(pos
, ' ');
1018 if (pos
[0] != '\0') {
1019 info("add symlink '%s'", pos
);
1020 name_list_add(&udev
->symlink_list
, pos
, 0);
1024 /* set name, later rules with name set will be ignored */
1025 if (rule
->name
.operation
== KEY_OP_ASSIGN
||
1026 rule
->name
.operation
== KEY_OP_ASSIGN_FINAL
||
1027 rule
->name
.operation
== KEY_OP_ADD
) {
1031 strlcpy(udev
->name
, key_val(rule
, &rule
->name
), sizeof(udev
->name
));
1032 udev_rules_apply_format(udev
, udev
->name
, sizeof(udev
->name
));
1033 count
= replace_untrusted_chars(udev
->name
);
1035 info("%i untrusted character(s) replaced", count
);
1037 info("rule applied, '%s' becomes '%s'", udev
->dev
->kernel_name
, udev
->name
);
1038 if (strcmp(udev
->dev
->subsystem
, "net") != 0)
1039 dbg("name, '%s' is going to have owner='%s', group='%s', mode=%#o partitions=%i",
1040 udev
->name
, udev
->owner
, udev
->group
, udev
->mode
, udev
->partitions
);
1043 if (!udev
->run_final
&& rule
->run
.operation
!= KEY_OP_UNSET
) {
1044 if (rule
->run
.operation
== KEY_OP_ASSIGN_FINAL
)
1045 udev
->run_final
= 1;
1046 if (rule
->run
.operation
== KEY_OP_ASSIGN
|| rule
->run
.operation
== KEY_OP_ASSIGN_FINAL
) {
1047 info("reset run list");
1048 name_list_cleanup(&udev
->run_list
);
1050 dbg("add run '%s'", key_val(rule
, &rule
->run
));
1051 name_list_add(&udev
->run_list
, key_val(rule
, &rule
->run
), 0);
1054 if (rule
->last_rule
) {
1055 dbg("last rule to be applied");
1059 if (rule
->goto_label
.operation
!= KEY_OP_UNSET
) {
1060 dbg("moving forward to label '%s'", key_val(rule
, &rule
->goto_label
));
1061 udev_rules_iter_label(rules
, key_val(rule
, &rule
->goto_label
));
1067 strlcpy(udev
->name
, udev
->dev
->kernel_name
, sizeof(udev
->name
));
1068 info("no node name set, will use kernel name '%s'", udev
->name
);
1071 if (udev
->tmp_node
[0] != '\0') {
1072 dbg("removing temporary device node");
1073 unlink_secure(udev
->tmp_node
);
1074 udev
->tmp_node
[0] = '\0';
1080 int udev_rules_get_run(struct udev_rules
*rules
, struct udevice
*udev
)
1082 struct udev_rule
*rule
;
1084 dbg("udev->kernel_name='%s'", udev
->dev
->kernel_name
);
1086 /* look for a matching rule to apply */
1087 udev_rules_iter_init(rules
);
1089 rule
= udev_rules_iter_next(rules
);
1093 dbg("process rule");
1094 if (rule
->name
.operation
!= KEY_OP_UNSET
|| rule
->symlink
.operation
!= KEY_OP_UNSET
||
1095 rule
->mode_operation
!= KEY_OP_UNSET
|| rule
->owner
.operation
!= KEY_OP_UNSET
|| rule
->group
.operation
!= KEY_OP_UNSET
) {
1096 dbg("skip rule that names a device");
1100 if (match_rule(udev
, rule
) == 0) {
1101 if (rule
->ignore_device
) {
1102 info("rule applied, '%s' is ignored", udev
->dev
->kernel_name
);
1103 udev
->ignore_device
= 1;
1107 if (!udev
->run_final
&& rule
->run
.operation
!= KEY_OP_UNSET
) {
1108 if (rule
->run
.operation
== KEY_OP_ASSIGN
|| rule
->run
.operation
== KEY_OP_ASSIGN_FINAL
) {
1109 info("reset run list");
1110 name_list_cleanup(&udev
->run_list
);
1112 dbg("add run '%s'", key_val(rule
, &rule
->run
));
1113 name_list_add(&udev
->run_list
, key_val(rule
, &rule
->run
), 0);
1114 if (rule
->run
.operation
== KEY_OP_ASSIGN_FINAL
)
1118 if (rule
->last_rule
) {
1119 dbg("last rule to be applied");
1123 if (rule
->goto_label
.operation
!= KEY_OP_UNSET
) {
1124 dbg("moving forward to label '%s'", key_val(rule
, &rule
->goto_label
));
1125 udev_rules_iter_label(rules
, key_val(rule
, &rule
->goto_label
));