1/*
2 * Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
3 * Copyright (C) 2003-2006 Kay Sievers <kay.sievers@vrfy.org>
4 *
5 *	This program is free software; you can redistribute it and/or modify it
6 *	under the terms of the GNU General Public License as published by the
7 *	Free Software Foundation version 2 of the License.
8 *
9 *	This program is distributed in the hope that it will be useful, but
10 *	WITHOUT ANY WARRANTY; without even the implied warranty of
11 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 *	General Public License for more details.
13 *
14 *	You should have received a copy of the GNU General Public License along
15 *	with this program; if not, write to the Free Software Foundation, Inc.,
16 *	51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 *
18 */
19
20#include <stddef.h>
21#include <stdlib.h>
22#include <string.h>
23#include <stdio.h>
24#include <fcntl.h>
25#include <ctype.h>
26#include <unistd.h>
27#include <errno.h>
28#include <syslog.h>
29#include <fnmatch.h>
30#include <sys/wait.h>
31#include <sys/stat.h>
32
33#include "udev.h"
34#include "udev_rules.h"
35
36
37/* extract possible {attr} and move str behind it */
38static char *get_format_attribute(char **str)
39{
40	char *pos;
41	char *attr = NULL;
42
43	if (*str[0] == '{') {
44		pos = strchr(*str, '}');
45		if (pos == NULL) {
46			err("missing closing brace for format");
47			return NULL;
48		}
49		pos[0] = '\0';
50		attr = *str+1;
51		*str = pos+1;
52		dbg("attribute='%s', str='%s'", attr, *str);
53	}
54	return attr;
55}
56
57/* extract possible format length and move str behind it*/
58static int get_format_len(char **str)
59{
60	int num;
61	char *tail;
62
63	if (isdigit(*str[0])) {
64		num = (int) strtoul(*str, &tail, 10);
65		if (num > 0) {
66			*str = tail;
67			dbg("format length=%i", num);
68			return num;
69		} else {
70			err("format parsing error '%s'", *str);
71		}
72	}
73	return -1;
74}
75
76static int get_key(char **line, char **key, char **value)
77{
78	char *linepos;
79	char *temp;
80
81	linepos = *line;
82	if (linepos == NULL)
83		return -1;
84
85	/* skip whitespace */
86	while (isspace(linepos[0]))
87		linepos++;
88
89	/* get the key */
90	temp = strchr(linepos, '=');
91	if (temp == NULL || temp == linepos)
92		return -1;
93	temp[0] = '\0';
94	*key = linepos;
95	linepos = &temp[1];
96
97	/* get a quoted value */
98	if (linepos[0] == '"' || linepos[0] == '\'') {
99		temp = strchr(&linepos[1], linepos[0]);
100		if (temp != NULL) {
101			temp[0] = '\0';
102			*value = &linepos[1];
103			goto out;
104		}
105	}
106
107	/* get the value*/
108	temp = strchr(linepos, '\n');
109	if (temp != NULL)
110		temp[0] = '\0';
111	*value = linepos;
112out:
113	return 0;
114}
115
116static int import_keys_into_env(struct udevice *udev, const char *buf, size_t bufsize)
117{
118	char line[LINE_SIZE];
119	const char *bufline;
120	char *linepos;
121	char *variable;
122	char *value;
123	size_t cur;
124	size_t count;
125	int lineno;
126
127	/* loop through the whole buffer */
128	lineno = 0;
129	cur = 0;
130	while (cur < bufsize) {
131		count = buf_get_line(buf, bufsize, cur);
132		bufline = &buf[cur];
133		cur += count+1;
134		lineno++;
135
136		if (count >= sizeof(line)) {
137			err("line too long, conf line skipped %s, line %d", udev_config_filename, lineno);
138			continue;
139		}
140
141		/* eat the whitespace */
142		while ((count > 0) && isspace(bufline[0])) {
143			bufline++;
144			count--;
145		}
146		if (count == 0)
147			continue;
148
149		/* see if this is a comment */
150		if (bufline[0] == COMMENT_CHARACTER)
151			continue;
152
153		memcpy(line, bufline, count);
154		line[count] = '\0';
155
156		linepos = line;
157		if (get_key(&linepos, &variable, &value) == 0) {
158			dbg("import '%s=%s'", variable, value);
159
160			/* handle device, renamed by external tool, returning new path */
161			if (strcmp(variable, "DEVPATH") == 0) {
162				info("updating devpath from '%s' to '%s'", udev->dev->devpath, value);
163				sysfs_device_set_values(udev->dev, value, NULL, NULL);
164			} else
165				name_list_key_add(&udev->env_list, variable, value);
166			setenv(variable, value, 1);
167		}
168	}
169
170	return 0;
171}
172
173static int import_file_into_env(struct udevice *udev, const char *filename)
174{
175	char *buf;
176	size_t bufsize;
177
178	if (file_map(filename, &buf, &bufsize) != 0) {
179		err("can't open '%s': %s", filename, strerror(errno));
180		return -1;
181	}
182	import_keys_into_env(udev, buf, bufsize);
183	file_unmap(buf, bufsize);
184
185	return 0;
186}
187
188static int import_program_into_env(struct udevice *udev, const char *program)
189{
190	char result[2048];
191	size_t reslen;
192
193	if (run_program(program, udev->dev->subsystem, result, sizeof(result), &reslen, (udev_log_priority >= LOG_INFO)) != 0)
194		return -1;
195	return import_keys_into_env(udev, result, reslen);
196}
197
198static int import_parent_into_env(struct udevice *udev, const char *filter)
199{
200	struct sysfs_device *dev_parent;
201	int rc = -1;
202
203	dev_parent = sysfs_device_get_parent(udev->dev);
204	if (dev_parent != NULL) {
205		struct udevice *udev_parent;
206		struct name_entry *name_loop;
207
208		dbg("found parent '%s', get the node name", dev_parent->devpath);
209		udev_parent = udev_device_init(NULL);
210		if (udev_parent == NULL)
211			return -1;
212		/* import the udev_db of the parent */
213		if (udev_db_get_device(udev_parent, dev_parent->devpath) == 0) {
214			dbg("import stored parent env '%s'", udev_parent->name);
215			list_for_each_entry(name_loop, &udev_parent->env_list, node) {
216				char name[NAME_SIZE];
217				char *pos;
218
219				strlcpy(name, name_loop->name, sizeof(name));
220				pos = strchr(name, '=');
221				if (pos) {
222					pos[0] = '\0';
223					pos++;
224					if (fnmatch(filter, name, 0) == 0) {
225						dbg("import key '%s'", name_loop->name);
226						name_list_add(&udev->env_list, name_loop->name, 0);
227						setenv(name, pos, 1);
228					} else
229						dbg("skip key '%s'", name_loop->name);
230				}
231			}
232			rc = 0;
233		} else
234			dbg("parent not found in database");
235		udev_device_cleanup(udev_parent);
236	}
237
238	return rc;
239}
240
241#define WAIT_LOOP_PER_SECOND		50
242static int wait_for_sysfs(struct udevice *udev, const char *file, int timeout)
243{
244	char devicepath[PATH_SIZE];
245	char filepath[PATH_SIZE];
246	struct stat stats;
247	int loop = timeout * WAIT_LOOP_PER_SECOND;
248
249	strlcpy(devicepath, sysfs_path, sizeof(devicepath));
250	strlcat(devicepath, udev->dev->devpath, sizeof(devicepath));
251	strlcpy(filepath, devicepath, sizeof(filepath));
252	strlcat(filepath, "/", sizeof(filepath));
253	strlcat(filepath, file, sizeof(filepath));
254
255	dbg("will wait %i sec for '%s'", timeout, filepath);
256	while (--loop) {
257		/* lookup file */
258		if (stat(filepath, &stats) == 0) {
259			info("file '%s' appeared after %i loops", filepath, (timeout * WAIT_LOOP_PER_SECOND) - loop-1);
260			return 0;
261		}
262		/* make sure, the device did not disappear in the meantime */
263		if (stat(devicepath, &stats) != 0) {
264			info("device disappeared while waiting for '%s'", filepath);
265			return -2;
266		}
267		info("wait for '%s' for %i mseconds", filepath, 1000 / WAIT_LOOP_PER_SECOND);
268		usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
269	}
270	info("waiting for '%s' failed", filepath);
271	return -1;
272}
273
274/* handle "[$SUBSYSTEM/$KERNEL]<attribute>" lookup */
275static int attr_get_by_subsys_id(const char *attrstr, char *devpath, size_t len, char **attr)
276{
277	char subsys[NAME_SIZE];
278	char *attrib;
279	char *id;
280	int found = 0;
281
282	if (attrstr[0] != '[')
283		goto out;
284
285	strlcpy(subsys, &attrstr[1], sizeof(subsys));
286
287	attrib = strchr(subsys, ']');
288	if (attrib == NULL)
289		goto out;
290	attrib[0] = '\0';
291	attrib = &attrib[1];
292
293	id = strchr(subsys, '/');
294	if (id == NULL)
295		goto out;
296	id[0] = '\0';
297	id = &id[1];
298
299	if (sysfs_lookup_devpath_by_subsys_id(devpath, len, subsys, id)) {
300		if (attr != NULL) {
301			if (attrib[0] != '\0')
302				*attr = attrib;
303			else
304				*attr = NULL;
305		}
306		found = 1;
307	}
308out:
309	return found;
310}
311
312void udev_rules_apply_format(struct udevice *udev, char *string, size_t maxsize)
313{
314	char temp[PATH_SIZE];
315	char temp2[PATH_SIZE];
316	char *head, *tail, *pos, *cpos, *attr, *rest;
317	int len;
318	int i;
319	int count;
320	enum subst_type {
321		SUBST_UNKNOWN,
322		SUBST_DEVPATH,
323		SUBST_KERNEL,
324		SUBST_KERNEL_NUMBER,
325		SUBST_ID,
326		SUBST_MAJOR,
327		SUBST_MINOR,
328		SUBST_RESULT,
329		SUBST_ATTR,
330		SUBST_PARENT,
331		SUBST_TEMP_NODE,
332		SUBST_ROOT,
333		SUBST_SYS,
334		SUBST_ENV,
335	};
336	static const struct subst_map {
337		char *name;
338		char fmt;
339		enum subst_type type;
340	} map[] = {
341		{ .name = "devpath",	.fmt = 'p',	.type = SUBST_DEVPATH },
342		{ .name = "number",	.fmt = 'n',	.type = SUBST_KERNEL_NUMBER },
343		{ .name = "kernel",	.fmt = 'k',	.type = SUBST_KERNEL },
344		{ .name = "id",		.fmt = 'b',	.type = SUBST_ID },
345		{ .name = "major",	.fmt = 'M',	.type = SUBST_MAJOR },
346		{ .name = "minor",	.fmt = 'm',	.type = SUBST_MINOR },
347		{ .name = "result",	.fmt = 'c',	.type = SUBST_RESULT },
348		{ .name = "attr",	.fmt = 's',	.type = SUBST_ATTR },
349		{ .name = "sysfs",	.fmt = 's',	.type = SUBST_ATTR },
350		{ .name = "parent",	.fmt = 'P',	.type = SUBST_PARENT },
351		{ .name = "tempnode",	.fmt = 'N',	.type = SUBST_TEMP_NODE },
352		{ .name = "root",	.fmt = 'r',	.type = SUBST_ROOT },
353		{ .name = "sys",	.fmt = 'S',	.type = SUBST_SYS },
354		{ .name = "env",	.fmt = 'E',	.type = SUBST_ENV },
355		{ NULL, '\0', 0 }
356	};
357	enum subst_type type;
358	const struct subst_map *subst;
359
360	head = string;
361	while (1) {
362		len = -1;
363		while (head[0] != '\0') {
364			if (head[0] == '$') {
365				/* substitute named variable */
366				if (head[1] == '\0')
367					break;
368				if (head[1] == '$') {
369					strlcpy(temp, head+2, sizeof(temp));
370					strlcpy(head+1, temp, maxsize);
371					head++;
372					continue;
373				}
374				head[0] = '\0';
375				for (subst = map; subst->name; subst++) {
376					if (strncasecmp(&head[1], subst->name, strlen(subst->name)) == 0) {
377						type = subst->type;
378						tail = head + strlen(subst->name)+1;
379						dbg("will substitute format name '%s'", subst->name);
380						goto found;
381					}
382				}
383				head[0] = '$';
384				err("unknown format variable '%s'", head);
385			} else if (head[0] == '%') {
386				/* substitute format char */
387				if (head[1] == '\0')
388					break;
389				if (head[1] == '%') {
390					strlcpy(temp, head+2, sizeof(temp));
391					strlcpy(head+1, temp, maxsize);
392					head++;
393					continue;
394				}
395				head[0] = '\0';
396				tail = head+1;
397				len = get_format_len(&tail);
398				for (subst = map; subst->name; subst++) {
399					if (tail[0] == subst->fmt) {
400						type = subst->type;
401						tail++;
402						dbg("will substitute format char '%c'", subst->fmt);
403						goto found;
404					}
405				}
406				head[0] = '%';
407				err("unknown format char '%c'", tail[0]);
408			}
409			head++;
410		}
411		break;
412found:
413		attr = get_format_attribute(&tail);
414		strlcpy(temp, tail, sizeof(temp));
415		dbg("format=%i, string='%s', tail='%s'", type ,string, tail);
416
417		switch (type) {
418		case SUBST_DEVPATH:
419			strlcat(string, udev->dev->devpath, maxsize);
420			dbg("substitute devpath '%s'", udev->dev->devpath);
421			break;
422		case SUBST_KERNEL:
423			strlcat(string, udev->dev->kernel, maxsize);
424			dbg("substitute kernel name '%s'", udev->dev->kernel);
425			break;
426		case SUBST_KERNEL_NUMBER:
427			strlcat(string, udev->dev->kernel_number, maxsize);
428			dbg("substitute kernel number '%s'", udev->dev->kernel_number);
429			break;
430		case SUBST_ID:
431			if (udev->dev_parent != NULL) {
432				strlcat(string, udev->dev_parent->kernel, maxsize);
433				dbg("substitute id '%s'", udev->dev_parent->kernel);
434			}
435			break;
436		case SUBST_MAJOR:
437			sprintf(temp2, "%d", major(udev->devt));
438			strlcat(string, temp2, maxsize);
439			dbg("substitute major number '%s'", temp2);
440			break;
441		case SUBST_MINOR:
442			sprintf(temp2, "%d", minor(udev->devt));
443			strlcat(string, temp2, maxsize);
444			dbg("substitute minor number '%s'", temp2);
445			break;
446		case SUBST_RESULT:
447			if (udev->program_result[0] == '\0')
448				break;
449			/* get part part of the result string */
450			i = 0;
451			if (attr != NULL)
452				i = strtoul(attr, &rest, 10);
453			if (i > 0) {
454				dbg("request part #%d of result string", i);
455				cpos = udev->program_result;
456				while (--i) {
457					while (cpos[0] != '\0' && !isspace(cpos[0]))
458						cpos++;
459					while (isspace(cpos[0]))
460						cpos++;
461				}
462				if (i > 0) {
463					err("requested part of result string not found");
464					break;
465				}
466				strlcpy(temp2, cpos, sizeof(temp2));
467				/* %{2+}c copies the whole string from the second part on */
468				if (rest[0] != '+') {
469					cpos = strchr(temp2, ' ');
470					if (cpos)
471						cpos[0] = '\0';
472				}
473				strlcat(string, temp2, maxsize);
474				dbg("substitute part of result string '%s'", temp2);
475			} else {
476				strlcat(string, udev->program_result, maxsize);
477				dbg("substitute result string '%s'", udev->program_result);
478			}
479			break;
480		case SUBST_ATTR:
481			if (attr == NULL)
482				err("missing file parameter for attr");
483			else {
484				char devpath[PATH_SIZE];
485				char *attrib;
486				const char *value = NULL;
487				size_t size;
488
489				if (attr_get_by_subsys_id(attr, devpath, sizeof(devpath), &attrib)) {
490					if (attrib != NULL)
491						value = sysfs_attr_get_value(devpath, attrib);
492					else
493						break;
494				}
495
496				/* try the current device, other matches may have selected */
497				if (value == NULL && udev->dev_parent != NULL && udev->dev_parent != udev->dev)
498					value = sysfs_attr_get_value(udev->dev_parent->devpath, attr);
499
500				/* look at all devices along the chain of parents */
501				if (value == NULL) {
502					struct sysfs_device *dev_parent = udev->dev;
503
504					do {
505						dbg("looking at '%s'", dev_parent->devpath);
506						value = sysfs_attr_get_value(dev_parent->devpath, attr);
507						if (value != NULL) {
508							strlcpy(temp2, value, sizeof(temp2));
509							break;
510						}
511						dev_parent = sysfs_device_get_parent(dev_parent);
512					} while (dev_parent != NULL);
513				}
514
515				if (value == NULL)
516					break;
517
518				/* strip trailing whitespace, and replace unwanted characters */
519				size = strlcpy(temp2, value, sizeof(temp2));
520				if (size >= sizeof(temp2))
521					size = sizeof(temp2)-1;
522				while (size > 0 && isspace(temp2[size-1]))
523					temp2[--size] = '\0';
524				count = replace_chars(temp2, ALLOWED_CHARS_INPUT);
525				if (count > 0)
526					info("%i character(s) replaced" , count);
527				strlcat(string, temp2, maxsize);
528				dbg("substitute sysfs value '%s'", temp2);
529			}
530			break;
531		case SUBST_PARENT:
532			{
533				struct sysfs_device *dev_parent;
534
535				dev_parent = sysfs_device_get_parent(udev->dev);
536				if (dev_parent != NULL) {
537					struct udevice *udev_parent;
538
539					dbg("found parent '%s', get the node name", dev_parent->devpath);
540					udev_parent = udev_device_init(NULL);
541					if (udev_parent != NULL) {
542						/* lookup the name in the udev_db with the DEVPATH of the parent */
543						if (udev_db_get_device(udev_parent, dev_parent->devpath) == 0) {
544							strlcat(string, udev_parent->name, maxsize);
545							dbg("substitute parent node name'%s'", udev_parent->name);
546						} else
547							dbg("parent not found in database");
548						udev_device_cleanup(udev_parent);
549					}
550				}
551			}
552			break;
553		case SUBST_TEMP_NODE:
554			if (udev->tmp_node[0] == '\0' && major(udev->devt) > 0) {
555				dbg("create temporary device node for callout");
556				snprintf(udev->tmp_node, sizeof(udev->tmp_node), "%s/.tmp-%u-%u",
557					 udev_root, major(udev->devt), minor(udev->devt));
558				udev->tmp_node[sizeof(udev->tmp_node)-1] = '\0';
559				udev_node_mknod(udev, udev->tmp_node, udev->devt, 0600, 0, 0);
560			}
561			strlcat(string, udev->tmp_node, maxsize);
562			dbg("substitute temporary device node name '%s'", udev->tmp_node);
563			break;
564		case SUBST_ROOT:
565			strlcat(string, udev_root, maxsize);
566			dbg("substitute udev_root '%s'", udev_root);
567			break;
568		case SUBST_SYS:
569			strlcat(string, sysfs_path, maxsize);
570			dbg("substitute sysfs_path '%s'", sysfs_path);
571			break;
572		case SUBST_ENV:
573			if (attr == NULL) {
574				dbg("missing attribute");
575				break;
576			}
577			pos = getenv(attr);
578			if (pos == NULL) {
579				dbg("env '%s' not available", attr);
580				break;
581			}
582			dbg("substitute env '%s=%s'", attr, pos);
583			strlcat(string, pos, maxsize);
584			break;
585		default:
586			err("unknown substitution type=%i", type);
587			break;
588		}
589		/* possibly truncate to format-char specified length */
590		if (len >= 0 && len < (int)strlen(head)) {
591			head[len] = '\0';
592			dbg("truncate to %i chars, subtitution string becomes '%s'", len, head);
593		}
594		strlcat(string, temp, maxsize);
595	}
596}
597
598static char *key_val(struct udev_rule *rule, struct key *key)
599{
600	return rule->buf + key->val_off;
601}
602
603static char *key_pair_name(struct udev_rule *rule, struct key_pair *pair)
604{
605	return rule->buf + pair->key_name_off;
606}
607
608static int match_key(const char *key_name, struct udev_rule *rule, struct key *key, const char *val)
609{
610	char value[PATH_SIZE];
611	char *key_value;
612	char *pos;
613	int match = 0;
614
615	if (key->operation != KEY_OP_MATCH &&
616	    key->operation != KEY_OP_NOMATCH)
617		return 0;
618
619	/* look for a matching string, parts are separated by '|' */
620	strlcpy(value, rule->buf + key->val_off, sizeof(value));
621	key_value = value;
622	dbg("key %s value='%s'", key_name, key_value);
623	while (key_value) {
624		pos = strchr(key_value, '|');
625		if (pos) {
626			pos[0] = '\0';
627			pos++;
628		}
629
630		dbg("match %s '%s' <-> '%s'", key_name, key_value, val);
631		match = (fnmatch(key_value, val, 0) == 0);
632		if (match)
633			break;
634
635		key_value = pos;
636	}
637
638	if (match && (key->operation == KEY_OP_MATCH)) {
639		dbg("%s is true (matching value)", key_name);
640		return 0;
641	}
642	if (!match && (key->operation == KEY_OP_NOMATCH)) {
643		dbg("%s is true (non-matching value)", key_name);
644		return 0;
645	}
646	return -1;
647}
648
649/* match a single rule against a given device and possibly its parent devices */
650static int match_rule(struct udevice *udev, struct udev_rule *rule)
651{
652	int i;
653
654	if (match_key("ACTION", rule, &rule->action, udev->action))
655		goto nomatch;
656
657	if (match_key("KERNEL", rule, &rule->kernel, udev->dev->kernel))
658		goto nomatch;
659
660	if (match_key("SUBSYSTEM", rule, &rule->subsystem, udev->dev->subsystem))
661		goto nomatch;
662
663	if (match_key("DEVPATH", rule, &rule->devpath, udev->dev->devpath))
664		goto nomatch;
665
666	if (match_key("DRIVER", rule, &rule->driver, udev->dev->driver))
667		goto nomatch;
668
669	/* match NAME against a value assigned by an earlier rule */
670	if (match_key("NAME", rule, &rule->name, udev->name))
671		goto nomatch;
672
673	for (i = 0; i < rule->env.count; i++) {
674		struct key_pair *pair = &rule->env.keys[i];
675
676		/* we only check for matches, assignments will be handled later */
677		if (pair->key.operation == KEY_OP_MATCH ||
678		    pair->key.operation == KEY_OP_NOMATCH) {
679			const char *key_name = key_pair_name(rule, pair);
680			const char *value = getenv(key_name);
681
682			if (!value) {
683				dbg("ENV{'%s'} is not set, treat as empty", key_name);
684				value = "";
685			}
686			if (match_key("ENV", rule, &pair->key, value))
687				goto nomatch;
688		}
689	}
690
691	if (rule->test.operation != KEY_OP_UNSET) {
692		char filename[PATH_SIZE];
693		char devpath[PATH_SIZE];
694		char *attr;
695		struct stat statbuf;
696		int match;
697
698		strlcpy(filename, key_val(rule, &rule->test), sizeof(filename));
699		udev_rules_apply_format(udev, filename, sizeof(filename));
700
701		if (attr_get_by_subsys_id(filename, devpath, sizeof(devpath), &attr)) {
702			strlcpy(filename, sysfs_path, sizeof(filename));
703			strlcat(filename, devpath, sizeof(filename));
704			if (attr != NULL) {
705				strlcat(filename, "/", sizeof(filename));
706				strlcat(filename, attr, sizeof(filename));
707			}
708		}
709
710		match = (stat(filename, &statbuf) == 0);
711		info("'%s' %s", filename, match ? "exists" : "does not exist");
712		if (match && rule->test_mode_mask > 0) {
713			match = ((statbuf.st_mode & rule->test_mode_mask) > 0);
714			info("'%s' has mode=%#o and %s %#o", filename, statbuf.st_mode,
715			     match ? "matches" : "does not match",
716			     rule->test_mode_mask);
717		}
718		if (match && rule->test.operation == KEY_OP_NOMATCH)
719			goto nomatch;
720		if (!match && rule->test.operation == KEY_OP_MATCH)
721			goto nomatch;
722		dbg("TEST key is true");
723	}
724
725	if (rule->wait_for_sysfs.operation != KEY_OP_UNSET) {
726		int found;
727
728		found = (wait_for_sysfs(udev, key_val(rule, &rule->wait_for_sysfs), 3) == 0);
729		if (!found && (rule->wait_for_sysfs.operation != KEY_OP_NOMATCH))
730			goto nomatch;
731	}
732
733	/* check for matching sysfs attribute pairs */
734	for (i = 0; i < rule->attr.count; i++) {
735		struct key_pair *pair = &rule->attr.keys[i];
736
737		if (pair->key.operation == KEY_OP_MATCH ||
738		    pair->key.operation == KEY_OP_NOMATCH) {
739			const char *key_name = key_pair_name(rule, pair);
740			const char *key_value = key_val(rule, &pair->key);
741			char devpath[PATH_SIZE];
742			char *attrib;
743			const char *value = NULL;
744			char val[VALUE_SIZE];
745			size_t len;
746
747			if (attr_get_by_subsys_id(key_name, devpath, sizeof(devpath), &attrib)) {
748				if (attrib != NULL)
749					value = sysfs_attr_get_value(devpath, attrib);
750				else
751					goto nomatch;
752			}
753			if (value == NULL)
754				value = sysfs_attr_get_value(udev->dev->devpath, key_name);
755			if (value == NULL)
756				goto nomatch;
757			strlcpy(val, value, sizeof(val));
758
759			/* strip trailing whitespace of value, if not asked to match for it */
760			len = strlen(key_value);
761			if (len > 0 && !isspace(key_value[len-1])) {
762				len = strlen(val);
763				while (len > 0 && isspace(val[len-1]))
764					val[--len] = '\0';
765				dbg("removed %zi trailing whitespace chars from '%s'", strlen(val)-len, val);
766			}
767
768			if (match_key("ATTR", rule, &pair->key, val))
769				goto nomatch;
770		}
771	}
772
773	/* walk up the chain of parent devices and find a match */
774	udev->dev_parent = udev->dev;
775	while (1) {
776		/* check for matching kernel device name */
777		if (match_key("KERNELS", rule, &rule->kernels, udev->dev_parent->kernel))
778			goto try_parent;
779
780		/* check for matching subsystem value */
781		if (match_key("SUBSYSTEMS", rule, &rule->subsystems, udev->dev_parent->subsystem))
782			goto try_parent;
783
784		/* check for matching driver */
785		if (match_key("DRIVERS", rule, &rule->drivers, udev->dev_parent->driver))
786			goto try_parent;
787
788		/* check for matching sysfs attribute pairs */
789		for (i = 0; i < rule->attrs.count; i++) {
790			struct key_pair *pair = &rule->attrs.keys[i];
791
792			if (pair->key.operation == KEY_OP_MATCH ||
793			    pair->key.operation == KEY_OP_NOMATCH) {
794				const char *key_name = key_pair_name(rule, pair);
795				const char *key_value = key_val(rule, &pair->key);
796				const char *value;
797				char val[VALUE_SIZE];
798				size_t len;
799
800				value = sysfs_attr_get_value(udev->dev_parent->devpath, key_name);
801				if (value == NULL)
802					value = sysfs_attr_get_value(udev->dev->devpath, key_name);
803				if (value == NULL)
804					goto try_parent;
805				strlcpy(val, value, sizeof(val));
806
807				/* strip trailing whitespace of value, if not asked to match for it */
808				len = strlen(key_value);
809				if (len > 0 && !isspace(key_value[len-1])) {
810					len = strlen(val);
811					while (len > 0 && isspace(val[len-1]))
812						val[--len] = '\0';
813					dbg("removed %zi trailing whitespace chars from '%s'", strlen(val)-len, val);
814				}
815
816				if (match_key("ATTRS", rule, &pair->key, val))
817					goto try_parent;
818			}
819		}
820
821		/* found matching device  */
822		break;
823try_parent:
824		/* move to parent device */
825		dbg("try parent sysfs device");
826		udev->dev_parent = sysfs_device_get_parent(udev->dev_parent);
827		if (udev->dev_parent == NULL)
828			goto nomatch;
829		dbg("looking at dev_parent->devpath='%s'", udev->dev_parent->devpath);
830		dbg("looking at dev_parent->kernel='%s'", udev->dev_parent->kernel);
831	}
832
833	/* execute external program */
834	if (rule->program.operation != KEY_OP_UNSET) {
835		char program[PATH_SIZE];
836		char result[PATH_SIZE];
837
838		strlcpy(program, key_val(rule, &rule->program), sizeof(program));
839		udev_rules_apply_format(udev, program, sizeof(program));
840		if (run_program(program, udev->dev->subsystem, result, sizeof(result),
841				NULL, (udev_log_priority >= LOG_INFO)) != 0) {
842			dbg("PROGRAM is false");
843			udev->program_result[0] = '\0';
844			if (rule->program.operation != KEY_OP_NOMATCH)
845				goto nomatch;
846		} else {
847			int count;
848
849			dbg("PROGRAM matches");
850			remove_trailing_chars(result, '\n');
851			if (rule->string_escape == ESCAPE_UNSET ||
852			    rule->string_escape == ESCAPE_REPLACE) {
853				count = replace_chars(result, ALLOWED_CHARS_INPUT);
854				if (count > 0)
855					info("%i character(s) replaced" , count);
856			}
857			dbg("result is '%s'", result);
858			strlcpy(udev->program_result, result, sizeof(udev->program_result));
859			dbg("PROGRAM returned successful");
860			if (rule->program.operation == KEY_OP_NOMATCH)
861				goto nomatch;
862		}
863		dbg("PROGRAM key is true");
864	}
865
866	/* check for matching result of external program */
867	if (match_key("RESULT", rule, &rule->result, udev->program_result))
868		goto nomatch;
869
870	/* import variables returned from program or or file into environment */
871	if (rule->import.operation != KEY_OP_UNSET) {
872		char import[PATH_SIZE];
873		int rc = -1;
874
875		strlcpy(import, key_val(rule, &rule->import), sizeof(import));
876		udev_rules_apply_format(udev, import, sizeof(import));
877		dbg("check for IMPORT import='%s'", import);
878		if (rule->import_type == IMPORT_PROGRAM) {
879			rc = import_program_into_env(udev, import);
880		} else if (rule->import_type == IMPORT_FILE) {
881			dbg("import file import='%s'", import);
882			rc = import_file_into_env(udev, import);
883		} else if (rule->import_type == IMPORT_PARENT) {
884			dbg("import parent import='%s'", import);
885			rc = import_parent_into_env(udev, import);
886		}
887		if (rc != 0) {
888			dbg("IMPORT failed");
889			if (rule->import.operation != KEY_OP_NOMATCH)
890				goto nomatch;
891		} else
892			dbg("IMPORT '%s' imported", key_val(rule, &rule->import));
893		dbg("IMPORT key is true");
894	}
895
896	/* rule matches, if we have ENV assignments export it */
897	for (i = 0; i < rule->env.count; i++) {
898		struct key_pair *pair = &rule->env.keys[i];
899
900		if (pair->key.operation == KEY_OP_ASSIGN) {
901			char temp_value[NAME_SIZE];
902			const char *key_name = key_pair_name(rule, pair);
903			const char *value = key_val(rule, &pair->key);
904
905			/* make sure we don't write to the same string we possibly read from */
906			strlcpy(temp_value, value, sizeof(temp_value));
907			udev_rules_apply_format(udev, temp_value, NAME_SIZE);
908
909			if (temp_value[0] == '\0') {
910				name_list_key_remove(&udev->env_list, key_name);
911				unsetenv(key_name);
912				info("unset ENV '%s'", key_name);
913			} else {
914				char *key_value = name_list_key_add(&udev->env_list, key_name, temp_value);
915
916				if (key_value == NULL)
917					break;
918				putenv(key_value);
919				info("set ENV '%s'", key_value);
920			}
921		}
922	}
923
924	/* if we have ATTR assignments, write value to sysfs file */
925	for (i = 0; i < rule->attr.count; i++) {
926		struct key_pair *pair = &rule->attr.keys[i];
927
928		if (pair->key.operation == KEY_OP_ASSIGN) {
929			const char *key_name = key_pair_name(rule, pair);
930			char devpath[PATH_SIZE];
931			char *attrib;
932			char attr[PATH_SIZE] = "";
933			char value[NAME_SIZE];
934			FILE *f;
935
936			if (attr_get_by_subsys_id(key_name, devpath, sizeof(devpath), &attrib)) {
937				if (attrib != NULL) {
938					strlcpy(attr, sysfs_path, sizeof(attr));
939					strlcat(attr, devpath, sizeof(attr));
940					strlcat(attr, "/", sizeof(attr));
941					strlcat(attr, attrib, sizeof(attr));
942				}
943			}
944
945			if (attr[0] == '\0') {
946				strlcpy(attr, sysfs_path, sizeof(attr));
947				strlcat(attr, udev->dev->devpath, sizeof(attr));
948				strlcat(attr, "/", sizeof(attr));
949				strlcat(attr, key_name, sizeof(attr));
950			}
951
952			strlcpy(value, key_val(rule, &pair->key), sizeof(value));
953			udev_rules_apply_format(udev, value, sizeof(value));
954			info("writing '%s' to sysfs file '%s'", value, attr);
955			f = fopen(attr, "w");
956			if (f != NULL) {
957				if (!udev->test_run)
958					if (fprintf(f, "%s", value) <= 0)
959						err("error writing ATTR{%s}: %s", attr, strerror(errno));
960				fclose(f);
961			} else
962				err("error opening ATTR{%s} for writing: %s", attr, strerror(errno));
963		}
964	}
965	return 0;
966
967nomatch:
968	return -1;
969}
970
971int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev)
972{
973	struct udev_rule *rule;
974	int name_set = 0;
975
976	dbg("udev->dev->devpath='%s'", udev->dev->devpath);
977	dbg("udev->dev->kernel='%s'", udev->dev->kernel);
978
979	/* look for a matching rule to apply */
980	udev_rules_iter_init(rules);
981	while (1) {
982		rule = udev_rules_iter_next(rules);
983		if (rule == NULL)
984			break;
985
986		if (name_set &&
987		    (rule->name.operation == KEY_OP_ASSIGN ||
988		     rule->name.operation == KEY_OP_ASSIGN_FINAL ||
989		     rule->name.operation == KEY_OP_ADD)) {
990			dbg("node name already set, rule ignored");
991			continue;
992		}
993
994		dbg("process rule");
995		if (match_rule(udev, rule) == 0) {
996			/* apply options */
997			if (rule->ignore_device) {
998				info("rule applied, '%s' is ignored", udev->dev->kernel);
999				udev->ignore_device = 1;
1000				return 0;
1001			}
1002			if (rule->ignore_remove) {
1003				udev->ignore_remove = 1;
1004				dbg("remove event should be ignored");
1005			}
1006			if (rule->link_priority != 0) {
1007				udev->link_priority = rule->link_priority;
1008				info("link_priority=%i", udev->link_priority);
1009			}
1010			/* apply all_partitions option only at a main block device */
1011			if (rule->partitions &&
1012			    strcmp(udev->dev->subsystem, "block") == 0 && udev->dev->kernel_number[0] == '\0') {
1013				udev->partitions = rule->partitions;
1014				dbg("creation of partition nodes requested");
1015			}
1016
1017			/* apply permissions */
1018			if (!udev->mode_final && rule->mode != 0000) {
1019				if (rule->mode_operation == KEY_OP_ASSIGN_FINAL)
1020					udev->mode_final = 1;
1021				udev->mode = rule->mode;
1022				dbg("applied mode=%#o to '%s'", rule->mode, udev->dev->kernel);
1023			}
1024			if (!udev->owner_final && rule->owner.operation != KEY_OP_UNSET) {
1025				if (rule->owner.operation == KEY_OP_ASSIGN_FINAL)
1026					udev->owner_final = 1;
1027				strlcpy(udev->owner, key_val(rule, &rule->owner), sizeof(udev->owner));
1028				udev_rules_apply_format(udev, udev->owner, sizeof(udev->owner));
1029				dbg("applied owner='%s' to '%s'", udev->owner, udev->dev->kernel);
1030			}
1031			if (!udev->group_final && rule->group.operation != KEY_OP_UNSET) {
1032				if (rule->group.operation == KEY_OP_ASSIGN_FINAL)
1033					udev->group_final = 1;
1034				strlcpy(udev->group, key_val(rule, &rule->group), sizeof(udev->group));
1035				udev_rules_apply_format(udev, udev->group, sizeof(udev->group));
1036				dbg("applied group='%s' to '%s'", udev->group, udev->dev->kernel);
1037			}
1038
1039			/* collect symlinks */
1040			if (!udev->symlink_final && rule->symlink.operation != KEY_OP_UNSET) {
1041				char temp[PATH_SIZE];
1042				char *pos, *next;
1043				int count;
1044
1045				if (rule->symlink.operation == KEY_OP_ASSIGN_FINAL)
1046					udev->symlink_final = 1;
1047				if (rule->symlink.operation == KEY_OP_ASSIGN || rule->symlink.operation == KEY_OP_ASSIGN_FINAL) {
1048					info("reset symlink list");
1049					name_list_cleanup(&udev->symlink_list);
1050				}
1051				/* allow  multiple symlinks separated by spaces */
1052				strlcpy(temp, key_val(rule, &rule->symlink), sizeof(temp));
1053				udev_rules_apply_format(udev, temp, sizeof(temp));
1054				if (rule->string_escape == ESCAPE_UNSET ||
1055				    rule->string_escape == ESCAPE_REPLACE) {
1056					count = replace_chars(temp, ALLOWED_CHARS_FILE " ");
1057					if (count > 0)
1058						info("%i character(s) replaced" , count);
1059				}
1060				dbg("rule applied, added symlink(s) '%s'", temp);
1061				pos = temp;
1062				while (isspace(pos[0]))
1063					pos++;
1064				next = strchr(pos, ' ');
1065				while (next) {
1066					next[0] = '\0';
1067					info("add symlink '%s'", pos);
1068					name_list_add(&udev->symlink_list, pos, 0);
1069					while (isspace(next[1]))
1070						next++;
1071					pos = &next[1];
1072					next = strchr(pos, ' ');
1073				}
1074				if (pos[0] != '\0') {
1075					info("add symlink '%s'", pos);
1076					name_list_add(&udev->symlink_list, pos, 0);
1077				}
1078			}
1079
1080			/* set name, later rules with name set will be ignored */
1081			if (rule->name.operation == KEY_OP_ASSIGN ||
1082			    rule->name.operation == KEY_OP_ASSIGN_FINAL ||
1083			    rule->name.operation == KEY_OP_ADD) {
1084				int count;
1085
1086				name_set = 1;
1087				strlcpy(udev->name, key_val(rule, &rule->name), sizeof(udev->name));
1088				udev_rules_apply_format(udev, udev->name, sizeof(udev->name));
1089				if (rule->string_escape == ESCAPE_UNSET ||
1090				    rule->string_escape == ESCAPE_REPLACE) {
1091					count = replace_chars(udev->name, ALLOWED_CHARS_FILE);
1092					if (count > 0)
1093						info("%i character(s) replaced", count);
1094				}
1095
1096				info("rule applied, '%s' becomes '%s'", udev->dev->kernel, udev->name);
1097				if (strcmp(udev->dev->subsystem, "net") != 0)
1098					dbg("name, '%s' is going to have owner='%s', group='%s', mode=%#o partitions=%i",
1099					    udev->name, udev->owner, udev->group, udev->mode, udev->partitions);
1100			}
1101
1102			if (!udev->run_final && rule->run.operation != KEY_OP_UNSET) {
1103				if (rule->run.operation == KEY_OP_ASSIGN_FINAL)
1104					udev->run_final = 1;
1105				if (rule->run.operation == KEY_OP_ASSIGN || rule->run.operation == KEY_OP_ASSIGN_FINAL) {
1106					info("reset run list");
1107					name_list_cleanup(&udev->run_list);
1108				}
1109				dbg("add run '%s'", key_val(rule, &rule->run));
1110				name_list_add(&udev->run_list, key_val(rule, &rule->run), 0);
1111			}
1112
1113			if (rule->last_rule) {
1114				dbg("last rule to be applied");
1115				break;
1116			}
1117
1118			if (rule->goto_label.operation != KEY_OP_UNSET) {
1119				dbg("moving forward to label '%s'", key_val(rule, &rule->goto_label));
1120				udev_rules_iter_label(rules, key_val(rule, &rule->goto_label));
1121			}
1122		}
1123	}
1124
1125	if (!name_set) {
1126		strlcpy(udev->name, udev->dev->kernel, sizeof(udev->name));
1127		info("no node name set, will use kernel name '%s'", udev->name);
1128	}
1129
1130	if (udev->tmp_node[0] != '\0') {
1131		dbg("removing temporary device node");
1132		unlink_secure(udev->tmp_node);
1133		udev->tmp_node[0] = '\0';
1134	}
1135
1136	return 0;
1137}
1138
1139int udev_rules_get_run(struct udev_rules *rules, struct udevice *udev)
1140{
1141	struct udev_rule *rule;
1142
1143	dbg("udev->kernel='%s'", udev->dev->kernel);
1144
1145	/* look for a matching rule to apply */
1146	udev_rules_iter_init(rules);
1147	while (1) {
1148		rule = udev_rules_iter_next(rules);
1149		if (rule == NULL)
1150			break;
1151
1152		dbg("process rule");
1153		if (rule->name.operation != KEY_OP_UNSET || rule->symlink.operation != KEY_OP_UNSET ||
1154		    rule->mode_operation != KEY_OP_UNSET || rule->owner.operation != KEY_OP_UNSET ||
1155		    rule->group.operation != KEY_OP_UNSET) {
1156			dbg("skip rule that names a device");
1157			continue;
1158		}
1159
1160		if (match_rule(udev, rule) == 0) {
1161			if (rule->ignore_device) {
1162				info("rule applied, '%s' is ignored", udev->dev->kernel);
1163				udev->ignore_device = 1;
1164				return 0;
1165			}
1166
1167			if (!udev->run_final && rule->run.operation != KEY_OP_UNSET) {
1168				if (rule->run.operation == KEY_OP_ASSIGN ||
1169				    rule->run.operation == KEY_OP_ASSIGN_FINAL) {
1170					info("reset run list");
1171					name_list_cleanup(&udev->run_list);
1172				}
1173				dbg("add run '%s'", key_val(rule, &rule->run));
1174				name_list_add(&udev->run_list, key_val(rule, &rule->run), 0);
1175				if (rule->run.operation == KEY_OP_ASSIGN_FINAL)
1176					break;
1177			}
1178
1179			if (rule->last_rule) {
1180				dbg("last rule to be applied");
1181				break;
1182			}
1183
1184			if (rule->goto_label.operation != KEY_OP_UNSET) {
1185				dbg("moving forward to label '%s'", key_val(rule, &rule->goto_label));
1186				udev_rules_iter_label(rules, key_val(rule, &rule->goto_label));
1187			}
1188		}
1189	}
1190
1191	return 0;
1192}
1193