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