chiark / gitweb /
978581fb502a0b21ba84420eaf58a9eae31b2beb
[elogind.git] / udev / udev-rules.c
1 /*
2  * Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
3  * Copyright (C) 2003-2008 Kay Sievers <kay.sievers@vrfy.org>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <stddef.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <fcntl.h>
24 #include <ctype.h>
25 #include <unistd.h>
26 #include <errno.h>
27 #include <dirent.h>
28 #include <fnmatch.h>
29
30 #include "udev.h"
31
32 struct udev_rules {
33         struct udev *udev;
34         char *buf;
35         size_t bufsize;
36         int resolve_names;
37 };
38
39 struct udev_rules_iter {
40         struct udev_rules *rules;
41         size_t current;
42 };
43
44 enum key_operation {
45         KEY_OP_UNSET,
46         KEY_OP_MATCH,
47         KEY_OP_NOMATCH,
48         KEY_OP_ADD,
49         KEY_OP_ASSIGN,
50         KEY_OP_ASSIGN_FINAL,
51 };
52
53 struct key {
54         enum key_operation operation;
55         size_t val_off;
56 };
57
58 struct key_pair {
59         struct key key;
60         size_t key_name_off;
61 };
62
63 #define PAIRS_MAX               5
64 struct key_pairs {
65         int count;
66         struct key_pair keys[PAIRS_MAX];
67 };
68
69 enum import_type {
70         IMPORT_UNSET,
71         IMPORT_PROGRAM,
72         IMPORT_FILE,
73         IMPORT_PARENT,
74 };
75
76 enum escape_type {
77         ESCAPE_UNSET,
78         ESCAPE_NONE,
79         ESCAPE_REPLACE,
80 };
81
82 struct udev_rule {
83         struct key action;
84         struct key devpath;
85         struct key kernel;
86         struct key subsystem;
87         struct key driver;
88         struct key_pairs attr;
89
90         struct key kernels;
91         struct key subsystems;
92         struct key drivers;
93         struct key_pairs attrs;
94
95         struct key_pairs env;
96         struct key program;
97         struct key result;
98         struct key import;
99         enum import_type import_type;
100         struct key test;
101         mode_t test_mode_mask;
102         struct key run;
103         struct key wait_for;
104         struct key label;
105         struct key goto_label;
106         size_t goto_rule_off;
107
108         struct key name;
109         struct key symlink;
110         struct key symlink_match;
111         struct key owner;
112         struct key group;
113         struct key mode;
114         enum escape_type string_escape;
115
116         unsigned int link_priority;
117         int event_timeout;
118         unsigned int partitions;
119         unsigned int last_rule:1,
120                      run_ignore_error:1,
121                      ignore_device:1,
122                      ignore_remove:1;
123
124         size_t bufsize;
125         char buf[];
126 };
127
128 static void udev_rules_iter_init(struct udev_rules_iter *iter, struct udev_rules *rules)
129 {
130         dbg(rules->udev, "bufsize=%zi\n", rules->bufsize);
131         iter->rules = rules;
132         iter->current = 0;
133 }
134
135 static struct udev_rule *udev_rules_iter_next(struct udev_rules_iter *iter)
136 {
137         struct udev_rules *rules;
138         struct udev_rule *rule;
139
140         rules = iter->rules;
141         if (!rules)
142                 return NULL;
143
144         dbg(rules->udev, "current=%zi\n", iter->current);
145         if (iter->current >= rules->bufsize) {
146                 dbg(rules->udev, "no more rules\n");
147                 return NULL;
148         }
149
150         /* get next rule */
151         rule = (struct udev_rule *) (rules->buf + iter->current);
152         iter->current += sizeof(struct udev_rule) + rule->bufsize;
153
154         return rule;
155 }
156
157 static struct udev_rule *udev_rules_iter_goto(struct udev_rules_iter *iter, size_t rule_off)
158 {
159         struct udev_rules *rules = iter->rules;
160         struct udev_rule *rule;
161
162         dbg(rules->udev, "current=%zi\n", iter->current);
163         iter->current = rule_off;
164         rule = (struct udev_rule *) (rules->buf + iter->current);
165
166         return rule;
167 }
168
169 static size_t find_label(const struct udev_rules_iter *iter, const char *label)
170 {
171         struct udev_rule *rule;
172         struct udev_rules *rules = iter->rules;
173         size_t current = iter->current;
174
175 next:
176         dbg(rules->udev, "current=%zi\n", current);
177         if (current >= rules->bufsize) {
178                 dbg(rules->udev, "LABEL='%s' not found\n", label);
179                 return 0;
180         }
181         rule = (struct udev_rule *) (rules->buf + current);
182
183         if (strcmp(&rule->buf[rule->label.val_off], label) != 0) {
184                 dbg(rules->udev, "moving forward, looking for label '%s'\n", label);
185                 current += sizeof(struct udev_rule) + rule->bufsize;
186                 goto next;
187         }
188
189         dbg(rules->udev, "found label '%s'\n", label);
190         return current;
191 }
192
193 /* extract possible {attr} and move str behind it */
194 static char *get_format_attribute(struct udev *udev, char **str)
195 {
196         char *pos;
197         char *attr = NULL;
198
199         if (*str[0] == '{') {
200                 pos = strchr(*str, '}');
201                 if (pos == NULL) {
202                         err(udev, "missing closing brace for format\n");
203                         return NULL;
204                 }
205                 pos[0] = '\0';
206                 attr = *str+1;
207                 *str = pos+1;
208                 dbg(udev, "attribute='%s', str='%s'\n", attr, *str);
209         }
210         return attr;
211 }
212
213 /* extract possible format length and move str behind it*/
214 static int get_format_len(struct udev *udev, char **str)
215 {
216         int num;
217         char *tail;
218
219         if (isdigit(*str[0])) {
220                 num = (int) strtoul(*str, &tail, 10);
221                 if (num > 0) {
222                         *str = tail;
223                         dbg(udev, "format length=%i\n", num);
224                         return num;
225                 } else {
226                         err(udev, "format parsing error '%s'\n", *str);
227                 }
228         }
229         return -1;
230 }
231
232 static int import_property_from_string(struct udev_device *dev, char *line)
233 {
234         struct udev *udev = udev_device_get_udev(dev);
235         char *key;
236         char *val;
237         size_t len;
238
239         /* find key */
240         key = line;
241         while (isspace(key[0]))
242                 key++;
243
244         /* comment or empty line */
245         if (key[0] == '#' || key[0] == '\0')
246                 return -1;
247
248         /* split key/value */
249         val = strchr(key, '=');
250         if (val == NULL)
251                 return -1;
252         val[0] = '\0';
253         val++;
254
255         /* find value */
256         while (isspace(val[0]))
257                 val++;
258
259         /* terminate key */
260         len = strlen(key);
261         if (len == 0)
262                 return -1;
263         while (isspace(key[len-1]))
264                 len--;
265         key[len] = '\0';
266
267         /* terminate value */
268         len = strlen(val);
269         if (len == 0)
270                 return -1;
271         while (isspace(val[len-1]))
272                 len--;
273         val[len] = '\0';
274
275         if (len == 0)
276                 return -1;
277
278         /* unquote */
279         if (val[0] == '"' || val[0] == '\'') {
280                 if (val[len-1] != val[0]) {
281                         info(udev, "inconsistent quoting: '%s', skip\n", line);
282                         return -1;
283                 }
284                 val[len-1] = '\0';
285                 val++;
286         }
287
288         info(udev, "adding '%s'='%s'\n", key, val);
289
290         /* handle device, renamed by external tool, returning new path */
291         if (strcmp(key, "DEVPATH") == 0) {
292                 char syspath[UTIL_PATH_SIZE];
293
294                 info(udev, "updating devpath from '%s' to '%s'\n",
295                      udev_device_get_devpath(dev), val);
296                 util_strlcpy(syspath, udev_get_sys_path(udev), sizeof(syspath));
297                 util_strlcat(syspath, val, sizeof(syspath));
298                 udev_device_set_syspath(dev, syspath);
299         } else {
300                 struct udev_list_entry *entry;
301
302                 entry = udev_device_add_property(dev, key, val);
303                 /* store in db */
304                 udev_list_entry_set_flag(entry, 1);
305         }
306         return 0;
307 }
308
309 static int import_file_into_env(struct udev_device *dev, const char *filename)
310 {
311         FILE *f;
312         char line[UTIL_LINE_SIZE];
313
314         f = fopen(filename, "r");
315         if (f == NULL)
316                 return -1;
317         while (fgets(line, sizeof(line), f) != NULL)
318                 import_property_from_string(dev, line);
319         fclose(f);
320         return 0;
321 }
322
323 static int import_program_into_env(struct udev_device *dev, const char *program)
324 {
325         struct udev *udev = udev_device_get_udev(dev);
326         char **envp;
327         char result[2048];
328         size_t reslen;
329         char *line;
330
331         envp = udev_device_get_properties_envp(dev);
332         if (run_program(udev, program, envp, result, sizeof(result), &reslen) != 0)
333                 return -1;
334
335         line = result;
336         while (line != NULL) {
337                 char *pos;
338
339                 pos = strchr(line, '\n');
340                 if (pos != NULL) {
341                         pos[0] = '\0';
342                         pos = &pos[1];
343                 }
344                 import_property_from_string(dev, line);
345                 line = pos;
346         }
347         return 0;
348 }
349
350 static int import_parent_into_env(struct udev_device *dev, const char *filter)
351 {
352         struct udev *udev = udev_device_get_udev(dev);
353         struct udev_device *dev_parent;
354         struct udev_list_entry *list_entry;
355
356         dev_parent = udev_device_get_parent(dev);
357         if (dev_parent == NULL)
358                 return -1;
359
360         dbg(udev, "found parent '%s', get the node name\n", udev_device_get_syspath(dev_parent));
361         udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(dev_parent)) {
362                 const char *key = udev_list_entry_get_name(list_entry);
363                 const char *val = udev_list_entry_get_value(list_entry);
364
365                 if (fnmatch(filter, key, 0) == 0) {
366                         struct udev_list_entry *entry;
367
368                         dbg(udev, "import key '%s=%s'\n", key, val);
369                         entry = udev_device_add_property(dev, key, val);
370                         /* store in db */
371                         udev_list_entry_set_flag(entry, 1);
372                 }
373         }
374         return 0;
375 }
376
377 #define WAIT_LOOP_PER_SECOND            50
378 static int wait_for_file(struct udev_event *event, const char *file, int timeout)
379 {
380         char filepath[UTIL_PATH_SIZE];
381         char devicepath[UTIL_PATH_SIZE] = "";
382         struct stat stats;
383         int loop = timeout * WAIT_LOOP_PER_SECOND;
384
385         /* a relative path is a device attribute */
386         if (file[0] != '/') {
387                 util_strlcpy(devicepath, udev_get_sys_path(event->udev), sizeof(devicepath));
388                 util_strlcat(devicepath, udev_device_get_devpath(event->dev), sizeof(devicepath));
389
390                 util_strlcpy(filepath, devicepath, sizeof(filepath));
391                 util_strlcat(filepath, "/", sizeof(filepath));
392                 util_strlcat(filepath, file, sizeof(filepath));
393                 file = filepath;
394         }
395
396         dbg(event->udev, "will wait %i sec for '%s'\n", timeout, file);
397         while (--loop) {
398                 /* lookup file */
399                 if (stat(file, &stats) == 0) {
400                         info(event->udev, "file '%s' appeared after %i loops\n", file, (timeout * WAIT_LOOP_PER_SECOND) - loop-1);
401                         return 0;
402                 }
403                 /* make sure, the device did not disappear in the meantime */
404                 if (devicepath[0] != '\0' && stat(devicepath, &stats) != 0) {
405                         info(event->udev, "device disappeared while waiting for '%s'\n", file);
406                         return -2;
407                 }
408                 info(event->udev, "wait for '%s' for %i mseconds\n", file, 1000 / WAIT_LOOP_PER_SECOND);
409                 usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
410         }
411         info(event->udev, "waiting for '%s' failed\n", file);
412         return -1;
413 }
414
415 /* handle "[$SUBSYSTEM/$KERNEL]<attribute>" lookup */
416 static int split_subsys_sysname(struct udev *udev, char *attrstr, char **subsys, char **sysname, char **attr)
417 {
418         char *pos;
419
420         if (attrstr[0] != '[')
421                 return -1;
422
423         *subsys = &attrstr[1];
424         pos = strchr(*subsys, ']');
425         if (pos == NULL)
426                 return -1;
427         pos[0] = '\0';
428         pos = &pos[1];
429
430         if (pos[0] == '/')
431                 pos = &pos[1];
432         if (pos[0] != '\0')
433                 *attr = pos;
434         else
435                 *attr = NULL;
436
437         pos = strchr(*subsys, '/');
438         if (pos == NULL)
439                 return -1;
440         pos[0] = '\0';
441         *sysname = &pos[1];
442         return 0;
443 }
444
445 static int attr_subst_subdir(char *attr, size_t len)
446 {
447         char *pos;
448         int found = 0;
449
450         pos = strstr(attr, "/*/");
451         if (pos != NULL) {
452                 char str[UTIL_PATH_SIZE];
453                 DIR *dir;
454
455                 pos[1] = '\0';
456                 util_strlcpy(str, &pos[2], sizeof(str));
457                 dir = opendir(attr);
458                 if (dir != NULL) {
459                         struct dirent *dent;
460
461                         for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
462                                 struct stat stats;
463
464                                 if (dent->d_name[0] == '.')
465                                         continue;
466                                 util_strlcat(attr, dent->d_name, len);
467                                 util_strlcat(attr, str, len);
468                                 if (stat(attr, &stats) == 0) {
469                                         found = 1;
470                                         break;
471                                 }
472                                 pos[1] = '\0';
473                         }
474                         closedir(dir);
475                 }
476                 if (!found)
477                         util_strlcat(attr, str, len);
478         }
479
480         return found;
481 }
482
483 void udev_rules_apply_format(struct udev_event *event, char *string, size_t maxsize)
484 {
485         struct udev_device *dev = event->dev;
486         char temp[UTIL_PATH_SIZE];
487         char temp2[UTIL_PATH_SIZE];
488         char *head, *tail, *cpos, *attr, *rest;
489         int len;
490         int i;
491         int count;
492         enum subst_type {
493                 SUBST_UNKNOWN,
494                 SUBST_DEVPATH,
495                 SUBST_KERNEL,
496                 SUBST_KERNEL_NUMBER,
497                 SUBST_ID,
498                 SUBST_DRIVER,
499                 SUBST_MAJOR,
500                 SUBST_MINOR,
501                 SUBST_RESULT,
502                 SUBST_ATTR,
503                 SUBST_PARENT,
504                 SUBST_TEMP_NODE,
505                 SUBST_NAME,
506                 SUBST_LINKS,
507                 SUBST_ROOT,
508                 SUBST_SYS,
509                 SUBST_ENV,
510         };
511         static const struct subst_map {
512                 char *name;
513                 char fmt;
514                 enum subst_type type;
515         } map[] = {
516                 { .name = "devpath",    .fmt = 'p',     .type = SUBST_DEVPATH },
517                 { .name = "number",     .fmt = 'n',     .type = SUBST_KERNEL_NUMBER },
518                 { .name = "kernel",     .fmt = 'k',     .type = SUBST_KERNEL },
519                 { .name = "id",         .fmt = 'b',     .type = SUBST_ID },
520                 { .name = "driver",     .fmt = 'd',     .type = SUBST_DRIVER },
521                 { .name = "major",      .fmt = 'M',     .type = SUBST_MAJOR },
522                 { .name = "minor",      .fmt = 'm',     .type = SUBST_MINOR },
523                 { .name = "result",     .fmt = 'c',     .type = SUBST_RESULT },
524                 { .name = "attr",       .fmt = 's',     .type = SUBST_ATTR },
525                 { .name = "sysfs",      .fmt = 's',     .type = SUBST_ATTR },
526                 { .name = "parent",     .fmt = 'P',     .type = SUBST_PARENT },
527                 { .name = "tempnode",   .fmt = 'N',     .type = SUBST_TEMP_NODE },
528                 { .name = "name",       .fmt = 'D',     .type = SUBST_NAME },
529                 { .name = "links",      .fmt = 'L',     .type = SUBST_LINKS },
530                 { .name = "root",       .fmt = 'r',     .type = SUBST_ROOT },
531                 { .name = "sys",        .fmt = 'S',     .type = SUBST_SYS },
532                 { .name = "env",        .fmt = 'E',     .type = SUBST_ENV },
533                 { NULL, '\0', 0 }
534         };
535         enum subst_type type;
536         const struct subst_map *subst;
537
538         head = string;
539         while (1) {
540                 len = -1;
541                 while (head[0] != '\0') {
542                         if (head[0] == '$') {
543                                 /* substitute named variable */
544                                 if (head[1] == '\0')
545                                         break;
546                                 if (head[1] == '$') {
547                                         util_strlcpy(temp, head+2, sizeof(temp));
548                                         util_strlcpy(head+1, temp, maxsize);
549                                         head++;
550                                         continue;
551                                 }
552                                 head[0] = '\0';
553                                 for (subst = map; subst->name; subst++) {
554                                         if (strncasecmp(&head[1], subst->name, strlen(subst->name)) == 0) {
555                                                 type = subst->type;
556                                                 tail = head + strlen(subst->name)+1;
557                                                 dbg(event->udev, "will substitute format name '%s'\n", subst->name);
558                                                 goto found;
559                                         }
560                                 }
561                                 head[0] = '$';
562                                 err(event->udev, "unknown format variable '%s'\n", head);
563                         } else if (head[0] == '%') {
564                                 /* substitute format char */
565                                 if (head[1] == '\0')
566                                         break;
567                                 if (head[1] == '%') {
568                                         util_strlcpy(temp, head+2, sizeof(temp));
569                                         util_strlcpy(head+1, temp, maxsize);
570                                         head++;
571                                         continue;
572                                 }
573                                 head[0] = '\0';
574                                 tail = head+1;
575                                 len = get_format_len(event->udev, &tail);
576                                 for (subst = map; subst->name; subst++) {
577                                         if (tail[0] == subst->fmt) {
578                                                 type = subst->type;
579                                                 tail++;
580                                                 dbg(event->udev, "will substitute format char '%c'\n", subst->fmt);
581                                                 goto found;
582                                         }
583                                 }
584                                 head[0] = '%';
585                                 err(event->udev, "unknown format char '%c'\n", tail[0]);
586                         }
587                         head++;
588                 }
589                 break;
590 found:
591                 attr = get_format_attribute(event->udev, &tail);
592                 util_strlcpy(temp, tail, sizeof(temp));
593                 dbg(event->udev, "format=%i, string='%s', tail='%s'\n", type ,string, tail);
594
595                 switch (type) {
596                 case SUBST_DEVPATH:
597                         util_strlcat(string, udev_device_get_devpath(dev), maxsize);
598                         dbg(event->udev, "substitute devpath '%s'\n", udev_device_get_devpath(dev));
599                         break;
600                 case SUBST_KERNEL:
601                         util_strlcat(string, udev_device_get_sysname(dev), maxsize);
602                         dbg(event->udev, "substitute kernel name '%s'\n", udev_device_get_sysname(dev));
603                         break;
604                 case SUBST_KERNEL_NUMBER:
605                         if (udev_device_get_sysnum(dev) == NULL)
606                                 break;
607                         util_strlcat(string, udev_device_get_sysnum(dev), maxsize);
608                         dbg(event->udev, "substitute kernel number '%s'\n", udev_device_get_sysnum(dev));
609                         break;
610                 case SUBST_ID:
611                         if (event->dev_parent != NULL) {
612                                 util_strlcat(string, udev_device_get_sysname(event->dev_parent), maxsize);
613                                 dbg(event->udev, "substitute id '%s'\n", udev_device_get_sysname(event->dev_parent));
614                         }
615                         break;
616                 case SUBST_DRIVER:
617                         if (event->dev_parent != NULL) {
618                                 const char *driver = udev_device_get_driver(event->dev_parent);
619
620                                 if (driver == NULL)
621                                         break;
622                                 util_strlcat(string, driver, maxsize);
623                                 dbg(event->udev, "substitute driver '%s'\n", driver);
624                         }
625                         break;
626                 case SUBST_MAJOR:
627                         sprintf(temp2, "%d", major(udev_device_get_devnum(dev)));
628                         util_strlcat(string, temp2, maxsize);
629                         dbg(event->udev, "substitute major number '%s'\n", temp2);
630                         break;
631                 case SUBST_MINOR:
632                         sprintf(temp2, "%d", minor(udev_device_get_devnum(dev)));
633                         util_strlcat(string, temp2, maxsize);
634                         dbg(event->udev, "substitute minor number '%s'\n", temp2);
635                         break;
636                 case SUBST_RESULT:
637                         if (event->program_result[0] == '\0')
638                                 break;
639                         /* get part part of the result string */
640                         i = 0;
641                         if (attr != NULL)
642                                 i = strtoul(attr, &rest, 10);
643                         if (i > 0) {
644                                 dbg(event->udev, "request part #%d of result string\n", i);
645                                 cpos = event->program_result;
646                                 while (--i) {
647                                         while (cpos[0] != '\0' && !isspace(cpos[0]))
648                                                 cpos++;
649                                         while (isspace(cpos[0]))
650                                                 cpos++;
651                                 }
652                                 if (i > 0) {
653                                         err(event->udev, "requested part of result string not found\n");
654                                         break;
655                                 }
656                                 util_strlcpy(temp2, cpos, sizeof(temp2));
657                                 /* %{2+}c copies the whole string from the second part on */
658                                 if (rest[0] != '+') {
659                                         cpos = strchr(temp2, ' ');
660                                         if (cpos)
661                                                 cpos[0] = '\0';
662                                 }
663                                 util_strlcat(string, temp2, maxsize);
664                                 dbg(event->udev, "substitute part of result string '%s'\n", temp2);
665                         } else {
666                                 util_strlcat(string, event->program_result, maxsize);
667                                 dbg(event->udev, "substitute result string '%s'\n", event->program_result);
668                         }
669                         break;
670                 case SUBST_ATTR:
671                         if (attr == NULL)
672                                 err(event->udev, "missing file parameter for attr\n");
673                         else {
674                                 char *subsys;
675                                 char *sysname;
676                                 char *attrib;
677                                 char value[UTIL_NAME_SIZE] = "";
678                                 size_t size;
679
680                                 if (split_subsys_sysname(event->udev, attr, &subsys, &sysname, &attrib) == 0) {
681                                         struct udev_device *d;
682                                         const char *val;
683
684                                         if (attrib == NULL)
685                                                 break;
686                                         d = udev_device_new_from_subsystem_sysname(event->udev, subsys, sysname);
687                                         if (d == NULL)
688                                                 break;
689                                         val = udev_device_get_attr_value(d, attrib);
690                                         if (val != NULL)
691                                                 util_strlcpy(value, val, sizeof(value));
692                                         udev_device_unref(d);
693                                 }
694
695                                 /* try the current device, other matches may have selected */
696                                 if (value[0]=='\0' && event->dev_parent != NULL && event->dev_parent != event->dev) {
697                                         const char *val;
698
699                                         val = udev_device_get_attr_value(event->dev_parent, attr);
700                                         if (val != NULL)
701                                                 util_strlcpy(value, val, sizeof(value));
702                                 }
703
704                                 /* look at all devices along the chain of parents */
705                                 if (value[0]=='\0') {
706                                         struct udev_device *dev_parent = dev;
707                                         const char *val;
708
709                                         do {
710                                                 dbg(event->udev, "looking at '%s'\n", udev_device_get_syspath(dev_parent));
711                                                 val = udev_device_get_attr_value(dev_parent, attr);
712                                                 if (val != NULL) {
713                                                         util_strlcpy(value, val, sizeof(value));
714                                                         break;
715                                                 }
716                                                 dev_parent = udev_device_get_parent(dev_parent);
717                                         } while (dev_parent != NULL);
718                                 }
719
720                                 if (value[0]=='\0')
721                                         break;
722
723                                 /* strip trailing whitespace, and replace unwanted characters */
724                                 size = strlen(value);
725                                 while (size > 0 && isspace(value[--size]))
726                                         value[size] = '\0';
727                                 count = util_replace_chars(value, ALLOWED_CHARS_INPUT);
728                                 if (count > 0)
729                                         info(event->udev, "%i character(s) replaced\n" , count);
730                                 util_strlcat(string, value, maxsize);
731                                 dbg(event->udev, "substitute sysfs value '%s'\n", value);
732                         }
733                         break;
734                 case SUBST_PARENT:
735                         {
736                                 struct udev_device *dev_parent;
737                                 const char *devnode;
738
739                                 dev_parent = udev_device_get_parent(event->dev);
740                                 if (dev_parent == NULL)
741                                         break;
742                                 devnode = udev_device_get_devnode(dev_parent);
743                                 if (devnode != NULL) {
744                                         size_t devlen = strlen(udev_get_dev_path(event->udev))+1;
745
746                                         util_strlcat(string, &devnode[devlen], maxsize);
747                                         dbg(event->udev, "found parent '%s', got node name '%s'\n",
748                                             udev_device_get_syspath(dev_parent), &devnode[devlen]);
749                                 }
750                         }
751                         break;
752                 case SUBST_TEMP_NODE:
753                         if (event->tmp_node[0] == '\0' && major(udev_device_get_devnum(dev)) > 0) {
754                                 dbg(event->udev, "create temporary device node for callout\n");
755                                 snprintf(event->tmp_node, sizeof(event->tmp_node), "%s/.tmp-%u-%u",
756                                          udev_get_dev_path(event->udev),
757                                          major(udev_device_get_devnum(dev)), minor(udev_device_get_devnum(dev)));
758                                 udev_node_mknod(dev, event->tmp_node, makedev(0,0), 0600, 0, 0);
759                         }
760                         util_strlcat(string, event->tmp_node, maxsize);
761                         dbg(event->udev, "substitute temporary device node name '%s'\n", event->tmp_node);
762                         break;
763                 case SUBST_NAME:
764                         if (event->name != NULL) {
765                                 util_strlcat(string, event->name, maxsize);
766                                 dbg(event->udev, "substitute name '%s'\n", event->name);
767                         } else {
768                                 util_strlcat(string, udev_device_get_sysname(dev), maxsize);
769                                 dbg(event->udev, "substitute sysname '%s'\n", udev_device_get_sysname(dev));
770                         }
771                         break;
772                 case SUBST_LINKS:
773                         {
774                                 struct udev_list_entry *list_entry;
775
776                                 list_entry = udev_device_get_properties_list_entry(dev);
777                                 util_strlcpy(string, udev_list_entry_get_name(list_entry), maxsize);
778                                 udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry)) {
779                                         util_strlcat(string, " ", maxsize);
780                                         util_strlcat(string, udev_list_entry_get_name(list_entry), maxsize);
781                                 }
782                         }
783                         break;
784                 case SUBST_ROOT:
785                         util_strlcat(string, udev_get_dev_path(event->udev), maxsize);
786                         dbg(event->udev, "substitute udev_root '%s'\n", udev_get_dev_path(event->udev));
787                         break;
788                 case SUBST_SYS:
789                         util_strlcat(string, udev_get_sys_path(event->udev), maxsize);
790                         dbg(event->udev, "substitute sys_path '%s'\n", udev_get_sys_path(event->udev));
791                         break;
792                 case SUBST_ENV:
793                         if (attr == NULL) {
794                                 dbg(event->udev, "missing attribute\n");
795                                 break;
796                         } else {
797                                 struct udev_list_entry *list_entry;
798                                 const char *value;
799
800                                 list_entry = udev_device_get_properties_list_entry(event->dev);
801                                 list_entry = udev_list_entry_get_by_name(list_entry, attr);
802                                 if (list_entry == NULL)
803                                         break;
804                                 value = udev_list_entry_get_value(list_entry);
805                                 dbg(event->udev, "substitute env '%s=%s'\n", attr, value);
806                                 util_strlcat(string, value, maxsize);
807                                 break;
808                         }
809                 default:
810                         err(event->udev, "unknown substitution type=%i\n", type);
811                         break;
812                 }
813                 /* possibly truncate to format-char specified length */
814                 if (len >= 0 && len < (int)strlen(head)) {
815                         head[len] = '\0';
816                         dbg(event->udev, "truncate to %i chars, subtitution string becomes '%s'\n", len, head);
817                 }
818                 util_strlcat(string, temp, maxsize);
819         }
820 }
821
822 static char *key_val(struct udev_rule *rule, struct key *key)
823 {
824         return rule->buf + key->val_off;
825 }
826
827 static char *key_pair_name(struct udev_rule *rule, struct key_pair *pair)
828 {
829         return rule->buf + pair->key_name_off;
830 }
831
832 static int match_key(struct udev *udev, const char *key_name, struct udev_rule *rule, struct key *key, const char *val)
833 {
834         char value[UTIL_PATH_SIZE];
835         char *key_value;
836         char *pos;
837         int match = 0;
838
839         if (key->operation != KEY_OP_MATCH &&
840             key->operation != KEY_OP_NOMATCH)
841                 return 0;
842
843         if (val == NULL)
844                 val = "";
845
846         /* look for a matching string, parts are separated by '|' */
847         util_strlcpy(value, rule->buf + key->val_off, sizeof(value));
848         key_value = value;
849         dbg(udev, "key %s value='%s'\n", key_name, key_value);
850         while (key_value != NULL) {
851                 pos = strchr(key_value, '|');
852                 if (pos != NULL) {
853                         pos[0] = '\0';
854                         pos = &pos[1];
855                 }
856
857                 dbg(udev, "match %s '%s' <-> '%s'\n", key_name, key_value, val);
858                 match = (fnmatch(key_value, val, 0) == 0);
859                 if (match)
860                         break;
861
862                 key_value = pos;
863         }
864
865         if (match && (key->operation == KEY_OP_MATCH)) {
866                 dbg(udev, "%s is true (matching value)\n", key_name);
867                 return 0;
868         }
869         if (!match && (key->operation == KEY_OP_NOMATCH)) {
870                 dbg(udev, "%s is true (non-matching value)\n", key_name);
871                 return 0;
872         }
873         return -1;
874 }
875
876 /* match a single rule against a given device and possibly its parent devices */
877 static int match_rule(struct udev_event *event, struct udev_rule *rule)
878 {
879         struct udev_device *dev = event->dev;
880         int i;
881
882         if (match_key(event->udev, "ACTION", rule, &rule->action, udev_device_get_action(dev)))
883                 goto nomatch;
884
885         if (match_key(event->udev, "KERNEL", rule, &rule->kernel, udev_device_get_sysname(dev)))
886                 goto nomatch;
887
888         if (match_key(event->udev, "SUBSYSTEM", rule, &rule->subsystem, udev_device_get_subsystem(dev)))
889                 goto nomatch;
890
891         if (match_key(event->udev, "DEVPATH", rule, &rule->devpath, udev_device_get_devpath(dev)))
892                 goto nomatch;
893
894         if (match_key(event->udev, "DRIVER", rule, &rule->driver, udev_device_get_driver(dev)))
895                 goto nomatch;
896
897         /* match NAME against a value assigned by an earlier rule */
898         if (match_key(event->udev, "NAME", rule, &rule->name, event->name))
899                 goto nomatch;
900
901         /* match against current list of symlinks */
902         if (rule->symlink_match.operation == KEY_OP_MATCH ||
903             rule->symlink_match.operation == KEY_OP_NOMATCH) {
904                 size_t devlen = strlen(udev_get_dev_path(event->udev))+1;
905                 struct udev_list_entry *list_entry;
906                 int match = 0;
907
908                 udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) {
909                         const char *devlink;
910
911                         devlink =  &udev_list_entry_get_name(list_entry)[devlen];
912                         if (match_key(event->udev, "SYMLINK", rule, &rule->symlink_match, devlink) == 0) {
913                                 match = 1;
914                                 break;
915                         }
916                 }
917                 if (!match)
918                         goto nomatch;
919         }
920
921         for (i = 0; i < rule->env.count; i++) {
922                 struct key_pair *pair = &rule->env.keys[i];
923
924                 /* we only check for matches, assignments will be handled later */
925                 if (pair->key.operation == KEY_OP_MATCH ||
926                     pair->key.operation == KEY_OP_NOMATCH) {
927                         struct udev_list_entry *list_entry;
928                         const char *key_name = key_pair_name(rule, pair);
929                         const char *value;
930
931                         list_entry = udev_device_get_properties_list_entry(event->dev);
932                         list_entry = udev_list_entry_get_by_name(list_entry, key_name);
933                         value = udev_list_entry_get_value(list_entry);
934                         if (value == NULL) {
935                                 dbg(event->udev, "ENV{%s} is not set, treat as empty\n", key_name);
936                                 value = "";
937                         }
938                         if (match_key(event->udev, "ENV", rule, &pair->key, value))
939                                 goto nomatch;
940                 }
941         }
942
943         if (rule->test.operation == KEY_OP_MATCH ||
944             rule->test.operation == KEY_OP_NOMATCH) {
945                 char filename[UTIL_PATH_SIZE];
946                 char *subsys;
947                 char *sysname;
948                 char *attrib;
949                 struct stat statbuf;
950                 int match;
951
952                 util_strlcpy(filename, key_val(rule, &rule->test), sizeof(filename));
953                 udev_rules_apply_format(event, filename, sizeof(filename));
954
955                 if (split_subsys_sysname(event->udev, filename, &subsys, &sysname, &attrib) == 0) {
956                         struct udev_device *d;
957                         d = udev_device_new_from_subsystem_sysname(event->udev, subsys, sysname);
958                         if (d != NULL) {
959                                 util_strlcpy(filename, udev_device_get_syspath(d), sizeof(filename));
960                                 if (attrib != NULL) {
961                                         util_strlcat(filename, "/", sizeof(filename));
962                                         util_strlcat(filename, attrib, sizeof(filename));
963                                 }
964                                 udev_device_unref(d);
965                         }
966                 } else if (filename[0] != '/') {
967                         char tmp[UTIL_PATH_SIZE];
968
969                         util_strlcpy(tmp, udev_device_get_syspath(dev), sizeof(tmp));
970                         util_strlcat(tmp, "/", sizeof(tmp));
971                         util_strlcat(tmp, filename, sizeof(tmp));
972                         util_strlcpy(filename, tmp, sizeof(filename));
973                 }
974
975                 attr_subst_subdir(filename, sizeof(filename));
976
977                 match = (stat(filename, &statbuf) == 0);
978                 info(event->udev, "'%s' %s", filename, match ? "exists\n" : "does not exist\n");
979                 if (match && rule->test_mode_mask > 0) {
980                         match = ((statbuf.st_mode & rule->test_mode_mask) > 0);
981                         info(event->udev, "'%s' has mode=%#o and %s %#o\n", filename, statbuf.st_mode,
982                              match ? "matches" : "does not match",
983                              rule->test_mode_mask);
984                 }
985                 if (match && rule->test.operation == KEY_OP_NOMATCH)
986                         goto nomatch;
987                 if (!match && rule->test.operation == KEY_OP_MATCH)
988                         goto nomatch;
989                 dbg(event->udev, "TEST key is true\n");
990         }
991
992         if (rule->wait_for.operation != KEY_OP_UNSET) {
993                 char filename[UTIL_PATH_SIZE];
994                 int found;
995
996                 util_strlcpy(filename, key_val(rule, &rule->wait_for), sizeof(filename));
997                 udev_rules_apply_format(event, filename, sizeof(filename));
998                 found = (wait_for_file(event, filename, 10) == 0);
999                 if (!found && (rule->wait_for.operation != KEY_OP_NOMATCH))
1000                         goto nomatch;
1001         }
1002
1003         /* check for matching sysfs attribute pairs */
1004         for (i = 0; i < rule->attr.count; i++) {
1005                 struct key_pair *pair = &rule->attr.keys[i];
1006
1007                 if (pair->key.operation == KEY_OP_MATCH ||
1008                     pair->key.operation == KEY_OP_NOMATCH) {
1009                         char attr[UTIL_PATH_SIZE];
1010                         const char *key_name = key_pair_name(rule, pair);
1011                         const char *key_value = key_val(rule, &pair->key);
1012                         char *subsys;
1013                         char *sysname;
1014                         char *attrib;
1015                         char value[UTIL_NAME_SIZE] = "";
1016                         size_t len;
1017
1018                         util_strlcpy(attr, key_name, sizeof(attr));
1019                         if (split_subsys_sysname(event->udev, attr, &subsys, &sysname, &attrib) == 0) {
1020                                 struct udev_device *d;
1021                                 const char *val;
1022
1023                                 if (attrib == NULL)
1024                                         goto nomatch;
1025                                 d = udev_device_new_from_subsystem_sysname(event->udev, subsys, sysname);
1026                                 if (d == NULL)
1027                                         goto nomatch;
1028                                 val = udev_device_get_attr_value(d, attrib);
1029                                 if (val != NULL)
1030                                         util_strlcpy(value, val, sizeof(value));
1031                                 udev_device_unref(d);
1032                         }
1033
1034                         if (value[0]=='\0') {
1035                                 const char *val;
1036
1037                                 val = udev_device_get_attr_value(dev, key_name);
1038                                 if (val != NULL)
1039                                         util_strlcpy(value, val, sizeof(value));
1040                         }
1041
1042                         if (value[0]=='\0')
1043                                 goto nomatch;
1044
1045                         /* strip trailing whitespace of value, if not asked to match for it */
1046                         len = strlen(key_value);
1047                         if (len > 0 && !isspace(key_value[len-1])) {
1048                                 len = strlen(value);
1049                                 while (len > 0 && isspace(value[--len]))
1050                                         value[len] = '\0';
1051                                 dbg(event->udev, "removed trailing whitespace from '%s'\n", value);
1052                         }
1053
1054                         if (match_key(event->udev, "ATTR", rule, &pair->key, value))
1055                                 goto nomatch;
1056                 }
1057         }
1058
1059         /* walk up the chain of parent devices and find a match */
1060         event->dev_parent = dev;
1061         while (1) {
1062                 /* check for matching kernel device name */
1063                 if (match_key(event->udev, "KERNELS", rule,
1064                               &rule->kernels, udev_device_get_sysname(event->dev_parent)))
1065                         goto try_parent;
1066
1067                 /* check for matching subsystem value */
1068                 if (match_key(event->udev, "SUBSYSTEMS", rule,
1069                               &rule->subsystems, udev_device_get_subsystem(event->dev_parent)))
1070                         goto try_parent;
1071
1072                 /* check for matching driver */
1073                 if (match_key(event->udev, "DRIVERS", rule,
1074                               &rule->drivers, udev_device_get_driver(event->dev_parent)))
1075                         goto try_parent;
1076
1077                 /* check for matching sysfs attribute pairs */
1078                 for (i = 0; i < rule->attrs.count; i++) {
1079                         struct key_pair *pair = &rule->attrs.keys[i];
1080
1081                         if (pair->key.operation == KEY_OP_MATCH ||
1082                             pair->key.operation == KEY_OP_NOMATCH) {
1083                                 const char *key_name = key_pair_name(rule, pair);
1084                                 const char *key_value = key_val(rule, &pair->key);
1085                                 const char *val;
1086                                 char value[UTIL_NAME_SIZE];
1087                                 size_t len;
1088
1089                                 val = udev_device_get_attr_value(event->dev_parent, key_name);
1090                                 if (val == NULL)
1091                                         val = udev_device_get_attr_value(dev, key_name);
1092                                 if (val == NULL)
1093                                         goto try_parent;
1094                                 util_strlcpy(value, val, sizeof(value));
1095
1096                                 /* strip trailing whitespace of value, if not asked to match for it */
1097                                 len = strlen(key_value);
1098                                 if (len > 0 && !isspace(key_value[len-1])) {
1099                                         len = strlen(value);
1100                                         while (len > 0 && isspace(value[--len]))
1101                                                 value[len] = '\0';
1102                                         dbg(event->udev, "removed trailing whitespace from '%s'\n", value);
1103                                 }
1104
1105                                 if (match_key(event->udev, "ATTRS", rule, &pair->key, value))
1106                                         goto try_parent;
1107                         }
1108                 }
1109
1110                 /* found matching device  */
1111                 break;
1112 try_parent:
1113                 /* move to parent device */
1114                 dbg(event->udev, "try parent sysfs device\n");
1115                 event->dev_parent = udev_device_get_parent(event->dev_parent);
1116                 if (event->dev_parent == NULL)
1117                         goto nomatch;
1118                 dbg(event->udev, "looking at dev_parent->devpath='%s'\n",
1119                     udev_device_get_syspath(event->dev_parent));
1120         }
1121
1122         /* execute external program */
1123         if (rule->program.operation != KEY_OP_UNSET) {
1124                 char program[UTIL_PATH_SIZE];
1125                 char **envp;
1126                 char result[UTIL_PATH_SIZE];
1127
1128                 util_strlcpy(program, key_val(rule, &rule->program), sizeof(program));
1129                 udev_rules_apply_format(event, program, sizeof(program));
1130                 envp = udev_device_get_properties_envp(dev);
1131                 if (run_program(event->udev, program, envp, result, sizeof(result), NULL) != 0) {
1132                         dbg(event->udev, "PROGRAM is false\n");
1133                         event->program_result[0] = '\0';
1134                         if (rule->program.operation != KEY_OP_NOMATCH)
1135                                 goto nomatch;
1136                 } else {
1137                         int count;
1138
1139                         dbg(event->udev, "PROGRAM matches\n");
1140                         util_remove_trailing_chars(result, '\n');
1141                         if (rule->string_escape == ESCAPE_UNSET ||
1142                             rule->string_escape == ESCAPE_REPLACE) {
1143                                 count = util_replace_chars(result, ALLOWED_CHARS_INPUT);
1144                                 if (count > 0)
1145                                         info(event->udev, "%i character(s) replaced\n" , count);
1146                         }
1147                         dbg(event->udev, "result is '%s'\n", result);
1148                         util_strlcpy(event->program_result, result, sizeof(event->program_result));
1149                         dbg(event->udev, "PROGRAM returned successful\n");
1150                         if (rule->program.operation == KEY_OP_NOMATCH)
1151                                 goto nomatch;
1152                 }
1153                 dbg(event->udev, "PROGRAM key is true\n");
1154         }
1155
1156         /* check for matching result of external program */
1157         if (match_key(event->udev, "RESULT", rule, &rule->result, event->program_result))
1158                 goto nomatch;
1159
1160         /* import variables returned from program or or file into properties */
1161         if (rule->import.operation != KEY_OP_UNSET) {
1162                 char import[UTIL_PATH_SIZE];
1163                 int rc = -1;
1164
1165                 util_strlcpy(import, key_val(rule, &rule->import), sizeof(import));
1166                 udev_rules_apply_format(event, import, sizeof(import));
1167                 dbg(event->udev, "check for IMPORT import='%s'\n", import);
1168                 if (rule->import_type == IMPORT_PROGRAM) {
1169                         rc = import_program_into_env(event->dev, import);
1170                 } else if (rule->import_type == IMPORT_FILE) {
1171                         dbg(event->udev, "import file import='%s'\n", import);
1172                         rc = import_file_into_env(event->dev, import);
1173                 } else if (rule->import_type == IMPORT_PARENT) {
1174                         dbg(event->udev, "import parent import='%s'\n", import);
1175                         rc = import_parent_into_env(event->dev, import);
1176                 }
1177                 if (rc != 0) {
1178                         dbg(event->udev, "IMPORT failed\n");
1179                         if (rule->import.operation != KEY_OP_NOMATCH)
1180                                 goto nomatch;
1181                 } else
1182                         dbg(event->udev, "IMPORT '%s' imported\n", key_val(rule, &rule->import));
1183                 dbg(event->udev, "IMPORT key is true\n");
1184         }
1185
1186         /* rule matches, if we have ENV assignments export it */
1187         for (i = 0; i < rule->env.count; i++) {
1188                 struct key_pair *pair = &rule->env.keys[i];
1189
1190                 if (pair->key.operation == KEY_OP_ASSIGN) {
1191                         char temp_value[UTIL_NAME_SIZE];
1192                         const char *key_name = key_pair_name(rule, pair);
1193                         const char *value = key_val(rule, &pair->key);
1194
1195                         /* make sure we don't write to the same string we possibly read from */
1196                         util_strlcpy(temp_value, value, sizeof(temp_value));
1197                         udev_rules_apply_format(event, temp_value, sizeof(temp_value));
1198
1199                         if (temp_value[0] != '\0') {
1200                                 struct udev_list_entry *entry;
1201
1202                                 info(event->udev, "set ENV '%s=%s'\n", key_name, temp_value);
1203                                 entry = udev_device_add_property(dev, key_name, temp_value);
1204                                 /* store in db */
1205                                 udev_list_entry_set_flag(entry, 1);
1206                         }
1207                 }
1208         }
1209
1210         /* if we have ATTR assignments, write value to sysfs file */
1211         for (i = 0; i < rule->attr.count; i++) {
1212                 struct key_pair *pair = &rule->attr.keys[i];
1213
1214                 if (pair->key.operation == KEY_OP_ASSIGN) {
1215                         const char *key_name = key_pair_name(rule, pair);
1216                         char *subsys;
1217                         char *sysname;
1218                         char *attrib;
1219                         char attr[UTIL_PATH_SIZE];
1220                         char value[UTIL_NAME_SIZE];
1221                         FILE *f;
1222
1223                         util_strlcpy(attr, key_name, sizeof(attr));
1224                         if (split_subsys_sysname(event->udev, attr, &subsys, &sysname, &attrib) == 0) {
1225                                 struct udev_device *d;
1226
1227                                 d = udev_device_new_from_subsystem_sysname(event->udev, subsys, sysname);
1228                                 if (d != NULL) {
1229                                         util_strlcpy(attr, udev_device_get_syspath(d), sizeof(attr));
1230                                         if (attrib != NULL) {
1231                                                 util_strlcat(attr, "/", sizeof(attr));
1232                                                 util_strlcat(attr, attrib, sizeof(attr));
1233                                         }
1234                                         udev_device_unref(d);
1235                                 }
1236                         } else {
1237                                 util_strlcpy(attr, udev_device_get_syspath(dev), sizeof(attr));
1238                                 util_strlcat(attr, "/", sizeof(attr));
1239                                 util_strlcat(attr, key_name, sizeof(attr));
1240                         }
1241
1242                         attr_subst_subdir(attr, sizeof(attr));
1243
1244                         util_strlcpy(value, key_val(rule, &pair->key), sizeof(value));
1245                         udev_rules_apply_format(event, value, sizeof(value));
1246                         info(event->udev, "writing '%s' to sysfs file '%s'\n", value, attr);
1247                         f = fopen(attr, "w");
1248                         if (f != NULL) {
1249                                 if (!event->test)
1250                                         if (fprintf(f, "%s", value) <= 0)
1251                                                 err(event->udev, "error writing ATTR{%s}: %m\n", attr);
1252                                 fclose(f);
1253                         } else
1254                                 err(event->udev, "error opening ATTR{%s} for writing: %m\n", attr);
1255                 }
1256         }
1257         return 0;
1258
1259 nomatch:
1260         return -1;
1261 }
1262
1263 int udev_rules_get_name(struct udev_rules *rules, struct udev_event *event)
1264 {
1265         struct udev_device *dev = event->dev;
1266         struct udev_rules_iter iter;
1267         struct udev_rule *rule;
1268         int name_set = 0;
1269
1270         dbg(event->udev, "device: '%s'\n", udev_device_get_syspath(dev));
1271
1272         /* look for a matching rule to apply */
1273         udev_rules_iter_init(&iter, rules);
1274         while (1) {
1275                 rule = udev_rules_iter_next(&iter);
1276                 if (rule == NULL)
1277                         break;
1278
1279                 if (name_set &&
1280                     (rule->name.operation == KEY_OP_ASSIGN ||
1281                      rule->name.operation == KEY_OP_ASSIGN_FINAL ||
1282                      rule->name.operation == KEY_OP_ADD)) {
1283                         dbg(event->udev, "node name already set, rule ignored\n");
1284                         continue;
1285                 }
1286
1287                 dbg(event->udev, "process rule\n");
1288                 if (match_rule(event, rule) == 0) {
1289                         /* apply options */
1290                         if (rule->ignore_device) {
1291                                 info(event->udev, "rule applied, '%s' is ignored\n", udev_device_get_sysname(dev));
1292                                 event->ignore_device = 1;
1293                                 return 0;
1294                         }
1295                         if (rule->ignore_remove) {
1296                                 udev_device_set_ignore_remove(dev, 1);
1297                                 dbg(event->udev, "remove event should be ignored\n");
1298                         }
1299                         if (rule->link_priority != 0) {
1300                                 udev_device_set_devlink_priority(dev, rule->link_priority);
1301                                 info(event->udev, "devlink_priority=%i\n", rule->link_priority);
1302                         }
1303                         if (rule->event_timeout >= 0) {
1304                                 udev_device_set_event_timeout(dev, rule->event_timeout);
1305                                 info(event->udev, "event_timeout=%i\n", rule->event_timeout);
1306                         }
1307                         /* apply all_partitions option only at a disk device */
1308                         if (rule->partitions > 0 &&
1309                             strcmp(udev_device_get_subsystem(dev), "block") == 0 &&
1310                             udev_device_get_sysnum(dev) == NULL) {
1311                                 udev_device_set_num_fake_partitions(dev, rule->partitions);
1312                                 dbg(event->udev, "creation of partition nodes requested\n");
1313                         }
1314
1315                         /* apply permissions */
1316                         if (!event->mode_final && rule->mode.operation != KEY_OP_UNSET) {
1317                                 if (rule->mode.operation == KEY_OP_ASSIGN_FINAL)
1318                                         event->mode_final = 1;
1319                                 char buf[20];
1320                                 util_strlcpy(buf, key_val(rule, &rule->mode), sizeof(buf));
1321                                 udev_rules_apply_format(event, buf, sizeof(buf));
1322                                 event->mode = strtol(buf, NULL, 8);
1323                                 dbg(event->udev, "applied mode=%#o to '%s'\n",
1324                                     event->mode, udev_device_get_sysname(dev));
1325                         }
1326                         if (!event->owner_final && rule->owner.operation != KEY_OP_UNSET) {
1327                                 if (rule->owner.operation == KEY_OP_ASSIGN_FINAL)
1328                                         event->owner_final = 1;
1329                                 util_strlcpy(event->owner, key_val(rule, &rule->owner), sizeof(event->owner));
1330                                 udev_rules_apply_format(event, event->owner, sizeof(event->owner));
1331                                 dbg(event->udev, "applied owner='%s' to '%s'\n",
1332                                     event->owner, udev_device_get_sysname(dev));
1333                         }
1334                         if (!event->group_final && rule->group.operation != KEY_OP_UNSET) {
1335                                 if (rule->group.operation == KEY_OP_ASSIGN_FINAL)
1336                                         event->group_final = 1;
1337                                 util_strlcpy(event->group, key_val(rule, &rule->group), sizeof(event->group));
1338                                 udev_rules_apply_format(event, event->group, sizeof(event->group));
1339                                 dbg(event->udev, "applied group='%s' to '%s'\n",
1340                                     event->group, udev_device_get_sysname(dev));
1341                         }
1342
1343                         /* collect symlinks */
1344                         if (!event->devlink_final &&
1345                             (rule->symlink.operation == KEY_OP_ASSIGN ||
1346                              rule->symlink.operation == KEY_OP_ASSIGN_FINAL ||
1347                              rule->symlink.operation == KEY_OP_ADD)) {
1348                                 char temp[UTIL_PATH_SIZE];
1349                                 char filename[UTIL_PATH_SIZE];
1350                                 char *pos, *next;
1351                                 int count = 0;
1352
1353                                 if (rule->symlink.operation == KEY_OP_ASSIGN_FINAL)
1354                                         event->devlink_final = 1;
1355                                 if (rule->symlink.operation == KEY_OP_ASSIGN ||
1356                                     rule->symlink.operation == KEY_OP_ASSIGN_FINAL) {
1357                                         info(event->udev, "reset symlink list\n");
1358                                         udev_device_cleanup_devlinks_list(dev);
1359                                 }
1360                                 /* allow  multiple symlinks separated by spaces */
1361                                 util_strlcpy(temp, key_val(rule, &rule->symlink), sizeof(temp));
1362                                 udev_rules_apply_format(event, temp, sizeof(temp));
1363                                 if (rule->string_escape == ESCAPE_UNSET)
1364                                         count = util_replace_chars(temp, ALLOWED_CHARS_FILE " ");
1365                                 else if (rule->string_escape == ESCAPE_REPLACE)
1366                                         count = util_replace_chars(temp, ALLOWED_CHARS_FILE);
1367                                 if (count > 0)
1368                                         info(event->udev, "%i character(s) replaced\n" , count);
1369                                 dbg(event->udev, "rule applied, added symlink(s) '%s'\n", temp);
1370                                 pos = temp;
1371                                 while (isspace(pos[0]))
1372                                         pos++;
1373                                 next = strchr(pos, ' ');
1374                                 while (next) {
1375                                         next[0] = '\0';
1376                                         info(event->udev, "add symlink '%s'\n", pos);
1377                                         util_strlcpy(filename, udev_get_dev_path(event->udev), sizeof(filename));
1378                                         util_strlcat(filename, "/", sizeof(filename));
1379                                         util_strlcat(filename, pos, sizeof(filename));
1380                                         udev_device_add_devlink(dev, filename);
1381                                         while (isspace(next[1]))
1382                                                 next++;
1383                                         pos = &next[1];
1384                                         next = strchr(pos, ' ');
1385                                 }
1386                                 if (pos[0] != '\0') {
1387                                         info(event->udev, "add symlink '%s'\n", pos);
1388                                         util_strlcpy(filename, udev_get_dev_path(event->udev), sizeof(filename));
1389                                         util_strlcat(filename, "/", sizeof(filename));
1390                                         util_strlcat(filename, pos, sizeof(filename));
1391                                         udev_device_add_devlink(dev, filename);
1392                                 }
1393                         }
1394
1395                         /* set name, later rules with name set will be ignored */
1396                         if (rule->name.operation == KEY_OP_ASSIGN ||
1397                             rule->name.operation == KEY_OP_ASSIGN_FINAL ||
1398                             rule->name.operation == KEY_OP_ADD) {
1399                                 int count;
1400
1401                                 name_set = 1;
1402                                 util_strlcpy(event->name, key_val(rule, &rule->name), sizeof(event->name));
1403                                 udev_rules_apply_format(event, event->name, sizeof(event->name));
1404                                 if (rule->string_escape == ESCAPE_UNSET ||
1405                                     rule->string_escape == ESCAPE_REPLACE) {
1406                                         count = util_replace_chars(event->name, ALLOWED_CHARS_FILE);
1407                                         if (count > 0)
1408                                                 info(event->udev, "%i character(s) replaced\n", count);
1409                                 }
1410
1411                                 info(event->udev, "rule applied, '%s' becomes '%s'\n",
1412                                      udev_device_get_sysname(dev), event->name);
1413                                 if (strcmp(udev_device_get_subsystem(dev), "net") != 0)
1414                                         dbg(event->udev, "'%s' owner='%s', group='%s', mode=%#o partitions=%i\n",
1415                                             event->name, event->owner, event->group, event->mode,
1416                                             udev_device_get_num_fake_partitions(dev));
1417                         }
1418
1419                         if (!event->run_final && rule->run.operation != KEY_OP_UNSET) {
1420                                 struct udev_list_entry *list_entry;
1421
1422                                 if (rule->run.operation == KEY_OP_ASSIGN_FINAL)
1423                                         event->run_final = 1;
1424                                 if (rule->run.operation == KEY_OP_ASSIGN || rule->run.operation == KEY_OP_ASSIGN_FINAL) {
1425                                         info(event->udev, "reset run list\n");
1426                                         udev_list_cleanup(event->udev, &event->run_list);
1427                                 }
1428                                 dbg(event->udev, "add run '%s'\n", key_val(rule, &rule->run));
1429                                 list_entry = udev_list_entry_add(event->udev, &event->run_list,
1430                                                                  key_val(rule, &rule->run), NULL, 1, 0);
1431                                 if (rule->run_ignore_error && list_entry != NULL)
1432                                         udev_list_entry_set_flag(list_entry, 1);
1433                         }
1434
1435                         if (rule->last_rule) {
1436                                 dbg(event->udev, "last rule to be applied\n");
1437                                 break;
1438                         }
1439
1440                         if (rule->goto_label.operation != KEY_OP_UNSET) {
1441                                 dbg(event->udev, "moving forward to label '%s'\n", key_val(rule, &rule->goto_label));
1442                                 udev_rules_iter_goto(&iter, rule->goto_rule_off);
1443                         }
1444                 }
1445         }
1446
1447         if (!name_set) {
1448                 info(event->udev, "no node name set, will use kernel name '%s'\n",
1449                      udev_device_get_sysname(dev));
1450                 util_strlcpy(event->name, udev_device_get_sysname(dev), sizeof(event->name));
1451         }
1452
1453         if (event->tmp_node[0] != '\0') {
1454                 dbg(event->udev, "removing temporary device node\n");
1455                 unlink_secure(event->udev, event->tmp_node);
1456                 event->tmp_node[0] = '\0';
1457         }
1458         return 0;
1459 }
1460
1461 int udev_rules_get_run(struct udev_rules *rules, struct udev_event *event)
1462 {
1463         struct udev_device *dev = event->dev;
1464         struct udev_rules_iter iter;
1465         struct udev_rule *rule;
1466
1467         dbg(event->udev, "sysname: '%s'\n", udev_device_get_sysname(dev));
1468
1469         /* look for a matching rule to apply */
1470         udev_rules_iter_init(&iter, rules);
1471         while (1) {
1472                 rule = udev_rules_iter_next(&iter);
1473                 if (rule == NULL)
1474                         break;
1475
1476                 dbg(event->udev, "process rule\n");
1477                 if (rule->name.operation == KEY_OP_ASSIGN ||
1478                     rule->name.operation == KEY_OP_ASSIGN_FINAL ||
1479                     rule->name.operation == KEY_OP_ADD ||
1480                     rule->symlink.operation == KEY_OP_ASSIGN ||
1481                     rule->symlink.operation == KEY_OP_ASSIGN_FINAL ||
1482                     rule->symlink.operation == KEY_OP_ADD ||
1483                     rule->mode.operation != KEY_OP_UNSET ||
1484                     rule->owner.operation != KEY_OP_UNSET || rule->group.operation != KEY_OP_UNSET) {
1485                         dbg(event->udev, "skip rule that names a device\n");
1486                         continue;
1487                 }
1488
1489                 if (match_rule(event, rule) == 0) {
1490                         if (rule->ignore_device) {
1491                                 info(event->udev, "rule applied, '%s' is ignored\n", udev_device_get_sysname(dev));
1492                                 event->ignore_device = 1;
1493                                 return 0;
1494                         }
1495                         if (rule->ignore_remove) {
1496                                 udev_device_set_ignore_remove(dev, 1);
1497                                 dbg(event->udev, "remove event should be ignored\n");
1498                         }
1499
1500                         if (!event->run_final && rule->run.operation != KEY_OP_UNSET) {
1501                                 struct udev_list_entry *list_entry;
1502
1503                                 if (rule->run.operation == KEY_OP_ASSIGN ||
1504                                     rule->run.operation == KEY_OP_ASSIGN_FINAL) {
1505                                         info(event->udev, "reset run list\n");
1506                                         udev_list_cleanup(event->udev, &event->run_list);
1507                                 }
1508                                 dbg(event->udev, "add run '%s'\n", key_val(rule, &rule->run));
1509                                 list_entry = udev_list_entry_add(event->udev, &event->run_list,
1510                                                                  key_val(rule, &rule->run), NULL, 1, 0);
1511                                 if (rule->run_ignore_error && list_entry != NULL)
1512                                         udev_list_entry_set_flag(list_entry, 1);
1513                                 if (rule->run.operation == KEY_OP_ASSIGN_FINAL)
1514                                         break;
1515                         }
1516
1517                         if (rule->last_rule) {
1518                                 dbg(event->udev, "last rule to be applied\n");
1519                                 break;
1520                         }
1521
1522                         if (rule->goto_label.operation != KEY_OP_UNSET) {
1523                                 dbg(event->udev, "moving forward to label '%s'\n", key_val(rule, &rule->goto_label));
1524                                 udev_rules_iter_goto(&iter, rule->goto_rule_off);
1525                         }
1526                 }
1527         }
1528
1529         return 0;
1530 }
1531
1532 static int get_key(struct udev_rules *rules, char **line, char **key, enum key_operation *operation, char **value)
1533 {
1534         char *linepos;
1535         char *temp;
1536
1537         linepos = *line;
1538         if (linepos == NULL && linepos[0] == '\0')
1539                 return -1;
1540
1541         /* skip whitespace */
1542         while (isspace(linepos[0]) || linepos[0] == ',')
1543                 linepos++;
1544
1545         /* get the key */
1546         if (linepos[0] == '\0')
1547                 return -1;
1548         *key = linepos;
1549
1550         while (1) {
1551                 linepos++;
1552                 if (linepos[0] == '\0')
1553                         return -1;
1554                 if (isspace(linepos[0]))
1555                         break;
1556                 if (linepos[0] == '=')
1557                         break;
1558                 if ((linepos[0] == '+') || (linepos[0] == '!') || (linepos[0] == ':'))
1559                         if (linepos[1] == '=')
1560                                 break;
1561         }
1562
1563         /* remember end of key */
1564         temp = linepos;
1565
1566         /* skip whitespace after key */
1567         while (isspace(linepos[0]))
1568                 linepos++;
1569         if (linepos[0] == '\0')
1570                 return -1;
1571
1572         /* get operation type */
1573         if (linepos[0] == '=' && linepos[1] == '=') {
1574                 *operation = KEY_OP_MATCH;
1575                 linepos += 2;
1576                 dbg(rules->udev, "match:\n");
1577         } else if (linepos[0] == '!' && linepos[1] == '=') {
1578                 *operation = KEY_OP_NOMATCH;
1579                 linepos += 2;
1580                 dbg(rules->udev, "nomatch:\n");
1581         } else if (linepos[0] == '+' && linepos[1] == '=') {
1582                 *operation = KEY_OP_ADD;
1583                 linepos += 2;
1584                 dbg(rules->udev, "add:\n");
1585         } else if (linepos[0] == '=') {
1586                 *operation = KEY_OP_ASSIGN;
1587                 linepos++;
1588                 dbg(rules->udev, "assign:\n");
1589         } else if (linepos[0] == ':' && linepos[1] == '=') {
1590                 *operation = KEY_OP_ASSIGN_FINAL;
1591                 linepos += 2;
1592                 dbg(rules->udev, "assign_final:\n");
1593         } else
1594                 return -1;
1595
1596         /* terminate key */
1597         temp[0] = '\0';
1598
1599         /* skip whitespace after operator */
1600         while (isspace(linepos[0]))
1601                 linepos++;
1602         if (linepos[0] == '\0')
1603                 return -1;
1604
1605         /* get the value*/
1606         if (linepos[0] == '"')
1607                 linepos++;
1608         else
1609                 return -1;
1610         *value = linepos;
1611
1612         temp = strchr(linepos, '"');
1613         if (!temp)
1614                 return -1;
1615         temp[0] = '\0';
1616         temp++;
1617         dbg(rules->udev, "'%s'-'%s'\n", *key, *value);
1618
1619         /* move line to next key */
1620         *line = temp;
1621         return 0;
1622 }
1623
1624 /* extract possible KEY{attr} */
1625 static char *get_key_attribute(struct udev_rules *rules, char *str)
1626 {
1627         char *pos;
1628         char *attr;
1629
1630         attr = strchr(str, '{');
1631         if (attr != NULL) {
1632                 attr++;
1633                 pos = strchr(attr, '}');
1634                 if (pos == NULL) {
1635                         err(rules->udev, "missing closing brace for format\n");
1636                         return NULL;
1637                 }
1638                 pos[0] = '\0';
1639                 dbg(rules->udev, "attribute='%s'\n", attr);
1640                 return attr;
1641         }
1642
1643         return NULL;
1644 }
1645
1646 static int add_rule_key(struct udev_rule *rule, struct key *key,
1647                         enum key_operation operation, const char *value)
1648 {
1649         size_t val_len = strnlen(value, UTIL_PATH_SIZE);
1650
1651         key->operation = operation;
1652
1653         key->val_off = rule->bufsize;
1654         util_strlcpy(rule->buf + rule->bufsize, value, val_len+1);
1655         rule->bufsize += val_len+1;
1656
1657         return 0;
1658 }
1659
1660 static int add_rule_key_pair(struct udev_rules *rules, struct udev_rule *rule, struct key_pairs *pairs,
1661                              enum key_operation operation, const char *key, const char *value)
1662 {
1663         size_t key_len = strnlen(key, UTIL_PATH_SIZE);
1664
1665         if (pairs->count >= PAIRS_MAX) {
1666                 err(rules->udev, "skip, too many keys of the same type in a single rule\n");
1667                 return -1;
1668         }
1669
1670         add_rule_key(rule, &pairs->keys[pairs->count].key, operation, value);
1671
1672         /* add the key-name of the pair */
1673         pairs->keys[pairs->count].key_name_off = rule->bufsize;
1674         util_strlcpy(rule->buf + rule->bufsize, key, key_len+1);
1675         rule->bufsize += key_len+1;
1676
1677         pairs->count++;
1678
1679         return 0;
1680 }
1681
1682 static int add_to_rules(struct udev_rules *rules, char *line, const char *filename, unsigned int lineno)
1683 {
1684         char buf[sizeof(struct udev_rule) + UTIL_LINE_SIZE];
1685         struct udev_rule *rule;
1686         size_t rule_size;
1687         int valid;
1688         char *linepos;
1689         char *attr;
1690         size_t padding;
1691         int physdev = 0;
1692
1693         memset(buf, 0x00, sizeof(buf));
1694         rule = (struct udev_rule *) buf;
1695         rule->event_timeout = -1;
1696         linepos = line;
1697         valid = 0;
1698
1699         /* get all the keys */
1700         while (1) {
1701                 char *key;
1702                 char *value;
1703                 enum key_operation operation = KEY_OP_UNSET;
1704
1705                 if (get_key(rules, &linepos, &key, &operation, &value) != 0)
1706                         break;
1707
1708                 if (strcasecmp(key, "ACTION") == 0) {
1709                         if (operation != KEY_OP_MATCH &&
1710                             operation != KEY_OP_NOMATCH) {
1711                                 err(rules->udev, "invalid ACTION operation\n");
1712                                 goto invalid;
1713                         }
1714                         add_rule_key(rule, &rule->action, operation, value);
1715                         valid = 1;
1716                         continue;
1717                 }
1718
1719                 if (strcasecmp(key, "DEVPATH") == 0) {
1720                         if (operation != KEY_OP_MATCH &&
1721                             operation != KEY_OP_NOMATCH) {
1722                                 err(rules->udev, "invalid DEVPATH operation\n");
1723                                 goto invalid;
1724                         }
1725                         add_rule_key(rule, &rule->devpath, operation, value);
1726                         valid = 1;
1727                         continue;
1728                 }
1729
1730                 if (strcasecmp(key, "KERNEL") == 0) {
1731                         if (operation != KEY_OP_MATCH &&
1732                             operation != KEY_OP_NOMATCH) {
1733                                 err(rules->udev, "invalid KERNEL operation\n");
1734                                 goto invalid;
1735                         }
1736                         add_rule_key(rule, &rule->kernel, operation, value);
1737                         valid = 1;
1738                         continue;
1739                 }
1740
1741                 if (strcasecmp(key, "SUBSYSTEM") == 0) {
1742                         if (operation != KEY_OP_MATCH &&
1743                             operation != KEY_OP_NOMATCH) {
1744                                 err(rules->udev, "invalid SUBSYSTEM operation\n");
1745                                 goto invalid;
1746                         }
1747                         /* bus, class, subsystem events should all be the same */
1748                         if (strcmp(value, "subsystem") == 0 ||
1749                             strcmp(value, "bus") == 0 ||
1750                             strcmp(value, "class") == 0) {
1751                                 if (strcmp(value, "bus") == 0 || strcmp(value, "class") == 0)
1752                                         err(rules->udev, "'%s' must be specified as 'subsystem' \n"
1753                                             "please fix it in %s:%u", value, filename, lineno);
1754                                 add_rule_key(rule, &rule->subsystem, operation, "subsystem|class|bus");
1755                         } else
1756                                 add_rule_key(rule, &rule->subsystem, operation, value);
1757                         valid = 1;
1758                         continue;
1759                 }
1760
1761                 if (strcasecmp(key, "DRIVER") == 0) {
1762                         if (operation != KEY_OP_MATCH &&
1763                             operation != KEY_OP_NOMATCH) {
1764                                 err(rules->udev, "invalid DRIVER operation\n");
1765                                 goto invalid;
1766                         }
1767                         add_rule_key(rule, &rule->driver, operation, value);
1768                         valid = 1;
1769                         continue;
1770                 }
1771
1772                 if (strncasecmp(key, "ATTR{", sizeof("ATTR{")-1) == 0) {
1773                         attr = get_key_attribute(rules, key + sizeof("ATTR")-1);
1774                         if (attr == NULL) {
1775                                 err(rules->udev, "error parsing ATTR attribute\n");
1776                                 goto invalid;
1777                         }
1778                         if (add_rule_key_pair(rules, rule, &rule->attr, operation, attr, value) != 0)
1779                                 goto invalid;
1780                         valid = 1;
1781                         continue;
1782                 }
1783
1784                 if (strcasecmp(key, "KERNELS") == 0 ||
1785                     strcasecmp(key, "ID") == 0) {
1786                         if (operation != KEY_OP_MATCH &&
1787                             operation != KEY_OP_NOMATCH) {
1788                                 err(rules->udev, "invalid KERNELS operation\n");
1789                                 goto invalid;
1790                         }
1791                         add_rule_key(rule, &rule->kernels, operation, value);
1792                         valid = 1;
1793                         continue;
1794                 }
1795
1796                 if (strcasecmp(key, "SUBSYSTEMS") == 0 ||
1797                     strcasecmp(key, "BUS") == 0) {
1798                         if (operation != KEY_OP_MATCH &&
1799                             operation != KEY_OP_NOMATCH) {
1800                                 err(rules->udev, "invalid SUBSYSTEMS operation\n");
1801                                 goto invalid;
1802                         }
1803                         add_rule_key(rule, &rule->subsystems, operation, value);
1804                         valid = 1;
1805                         continue;
1806                 }
1807
1808                 if (strcasecmp(key, "DRIVERS") == 0) {
1809                         if (operation != KEY_OP_MATCH &&
1810                             operation != KEY_OP_NOMATCH) {
1811                                 err(rules->udev, "invalid DRIVERS operation\n");
1812                                 goto invalid;
1813                         }
1814                         add_rule_key(rule, &rule->drivers, operation, value);
1815                         valid = 1;
1816                         continue;
1817                 }
1818
1819                 if (strncasecmp(key, "ATTRS{", sizeof("ATTRS{")-1) == 0 ||
1820                     strncasecmp(key, "SYSFS{", sizeof("SYSFS{")-1) == 0) {
1821                         if (operation != KEY_OP_MATCH &&
1822                             operation != KEY_OP_NOMATCH) {
1823                                 err(rules->udev, "invalid ATTRS operation\n");
1824                                 goto invalid;
1825                         }
1826                         attr = get_key_attribute(rules, key + sizeof("ATTRS")-1);
1827                         if (attr == NULL) {
1828                                 err(rules->udev, "error parsing ATTRS attribute\n");
1829                                 goto invalid;
1830                         }
1831                         if (strncmp(attr, "device/", 7) == 0)
1832                                 err(rules->udev, "the 'device' link may not be available in a future kernel, "
1833                                     "please fix it in %s:%u", filename, lineno);
1834                         else if (strstr(attr, "../") != NULL)
1835                                 err(rules->udev, "do not reference parent sysfs directories directly, "
1836                                     "it may break with a future kernel, please fix it in %s:%u", filename, lineno);
1837                         if (add_rule_key_pair(rules, rule, &rule->attrs, operation, attr, value) != 0)
1838                                 goto invalid;
1839                         valid = 1;
1840                         continue;
1841                 }
1842
1843                 if (strncasecmp(key, "ENV{", sizeof("ENV{")-1) == 0) {
1844                         attr = get_key_attribute(rules, key + sizeof("ENV")-1);
1845                         if (attr == NULL) {
1846                                 err(rules->udev, "error parsing ENV attribute\n");
1847                                 goto invalid;
1848                         }
1849                         if (strncmp(attr, "PHYSDEV", 7) == 0)
1850                                 physdev = 1;
1851                         if (add_rule_key_pair(rules, rule, &rule->env, operation, attr, value) != 0)
1852                                 goto invalid;
1853                         valid = 1;
1854                         continue;
1855                 }
1856
1857                 if (strcasecmp(key, "PROGRAM") == 0) {
1858                         add_rule_key(rule, &rule->program, operation, value);
1859                         valid = 1;
1860                         continue;
1861                 }
1862
1863                 if (strcasecmp(key, "RESULT") == 0) {
1864                         if (operation != KEY_OP_MATCH &&
1865                             operation != KEY_OP_NOMATCH) {
1866                                 err(rules->udev, "invalid RESULT operation\n");
1867                                 goto invalid;
1868                         }
1869                         add_rule_key(rule, &rule->result, operation, value);
1870                         valid = 1;
1871                         continue;
1872                 }
1873
1874                 if (strncasecmp(key, "IMPORT", sizeof("IMPORT")-1) == 0) {
1875                         attr = get_key_attribute(rules, key + sizeof("IMPORT")-1);
1876                         if (attr != NULL && strstr(attr, "program")) {
1877                                 dbg(rules->udev, "IMPORT will be executed\n");
1878                                 rule->import_type  = IMPORT_PROGRAM;
1879                         } else if (attr != NULL && strstr(attr, "file")) {
1880                                 dbg(rules->udev, "IMPORT will be included as file\n");
1881                                 rule->import_type  = IMPORT_FILE;
1882                         } else if (attr != NULL && strstr(attr, "parent")) {
1883                                 dbg(rules->udev, "IMPORT will include the parent values\n");
1884                                 rule->import_type = IMPORT_PARENT;
1885                         } else {
1886                                 /* figure it out if it is executable */
1887                                 char file[UTIL_PATH_SIZE];
1888                                 char *pos;
1889                                 struct stat statbuf;
1890
1891                                 util_strlcpy(file, value, sizeof(file));
1892                                 pos = strchr(file, ' ');
1893                                 if (pos)
1894                                         pos[0] = '\0';
1895
1896                                 /* allow programs in /lib/udev called without the path */
1897                                 if (strchr(file, '/') == NULL) {
1898                                         util_strlcpy(file, UDEV_PREFIX "/lib/udev/", sizeof(file));
1899                                         util_strlcat(file, value, sizeof(file));
1900                                         pos = strchr(file, ' ');
1901                                         if (pos)
1902                                                 pos[0] = '\0';
1903                                 }
1904
1905                                 dbg(rules->udev, "IMPORT auto mode for '%s'\n", file);
1906                                 if (!lstat(file, &statbuf) && (statbuf.st_mode & S_IXUSR)) {
1907                                         dbg(rules->udev, "IMPORT is executable, will be executed (autotype)\n");
1908                                         rule->import_type  = IMPORT_PROGRAM;
1909                                 } else {
1910                                         dbg(rules->udev, "IMPORT is not executable, will be included as file (autotype)\n");
1911                                         rule->import_type  = IMPORT_FILE;
1912                                 }
1913                         }
1914                         add_rule_key(rule, &rule->import, operation, value);
1915                         valid = 1;
1916                         continue;
1917                 }
1918
1919                 if (strncasecmp(key, "TEST", sizeof("TEST")-1) == 0) {
1920                         if (operation != KEY_OP_MATCH &&
1921                             operation != KEY_OP_NOMATCH) {
1922                                 err(rules->udev, "invalid TEST operation\n");
1923                                 goto invalid;
1924                         }
1925                         attr = get_key_attribute(rules, key + sizeof("TEST")-1);
1926                         if (attr != NULL)
1927                                 rule->test_mode_mask = strtol(attr, NULL, 8);
1928                         add_rule_key(rule, &rule->test, operation, value);
1929                         valid = 1;
1930                         continue;
1931                 }
1932
1933                 if (strncasecmp(key, "RUN", sizeof("RUN")-1) == 0) {
1934                         attr = get_key_attribute(rules, key + sizeof("RUN")-1);
1935                         if (attr != NULL) {
1936                                 if (strstr(attr, "ignore_error"))
1937                                         rule->run_ignore_error = 1;
1938                         }
1939                         add_rule_key(rule, &rule->run, operation, value);
1940                         valid = 1;
1941                         continue;
1942                 }
1943
1944                 if (strcasecmp(key, "WAIT_FOR") == 0 || strcasecmp(key, "WAIT_FOR_SYSFS") == 0) {
1945                         add_rule_key(rule, &rule->wait_for, operation, value);
1946                         valid = 1;
1947                         continue;
1948                 }
1949
1950                 if (strcasecmp(key, "LABEL") == 0) {
1951                         add_rule_key(rule, &rule->label, operation, value);
1952                         valid = 1;
1953                         continue;
1954                 }
1955
1956                 if (strcasecmp(key, "GOTO") == 0) {
1957                         add_rule_key(rule, &rule->goto_label, operation, value);
1958                         valid = 1;
1959                         continue;
1960                 }
1961
1962                 if (strncasecmp(key, "NAME", sizeof("NAME")-1) == 0) {
1963                         attr = get_key_attribute(rules, key + sizeof("NAME")-1);
1964                         if (attr != NULL) {
1965                                 if (strstr(attr, "all_partitions") != NULL) {
1966                                         dbg(rules->udev, "creation of partition nodes requested\n");
1967                                         rule->partitions = DEFAULT_FAKE_PARTITIONS_COUNT;
1968                                 }
1969                                 if (strstr(attr, "ignore_remove") != NULL) {
1970                                         dbg(rules->udev, "remove event should be ignored\n");
1971                                         rule->ignore_remove = 1;
1972                                 }
1973                         }
1974                         if (value[0] == '\0')
1975                                 dbg(rules->udev, "name empty, node creation supressed\n");
1976                         add_rule_key(rule, &rule->name, operation, value);
1977                         continue;
1978                 }
1979
1980                 if (strcasecmp(key, "SYMLINK") == 0) {
1981                         if (operation == KEY_OP_MATCH ||
1982                             operation == KEY_OP_NOMATCH)
1983                                 add_rule_key(rule, &rule->symlink_match, operation, value);
1984                         else
1985                                 add_rule_key(rule, &rule->symlink, operation, value);
1986                         valid = 1;
1987                         continue;
1988                 }
1989
1990                 if (strcasecmp(key, "OWNER") == 0) {
1991                         valid = 1;
1992                         if (rules->resolve_names && (!strchr(value, '$') && !strchr(value, '%'))) {
1993                                 char *endptr;
1994                                 strtoul(value, &endptr, 10);
1995                                 if (endptr[0] != '\0') {
1996                                         char owner[32];
1997                                         uid_t uid = lookup_user(rules->udev, value);
1998                                         dbg(rules->udev, "replacing username='%s' by id=%i\n", value, uid);
1999                                         sprintf(owner, "%u", (unsigned int) uid);
2000                                         add_rule_key(rule, &rule->owner, operation, owner);
2001                                         continue;
2002                                 }
2003                         }
2004
2005                         add_rule_key(rule, &rule->owner, operation, value);
2006                         continue;
2007                 }
2008
2009                 if (strcasecmp(key, "GROUP") == 0) {
2010                         valid = 1;
2011                         if (rules->resolve_names && (!strchr(value, '$') && !strchr(value, '%'))) {
2012                                 char *endptr;
2013                                 strtoul(value, &endptr, 10);
2014                                 if (endptr[0] != '\0') {
2015                                         char group[32];
2016                                         gid_t gid = lookup_group(rules->udev, value);
2017                                         dbg(rules->udev, "replacing groupname='%s' by id=%i\n", value, gid);
2018                                         sprintf(group, "%u", (unsigned int) gid);
2019                                         add_rule_key(rule, &rule->group, operation, group);
2020                                         continue;
2021                                 }
2022                         }
2023
2024                         add_rule_key(rule, &rule->group, operation, value);
2025                         continue;
2026                 }
2027
2028                 if (strcasecmp(key, "MODE") == 0) {
2029                         add_rule_key(rule, &rule->mode, operation, value);
2030                         valid = 1;
2031                         continue;
2032                 }
2033
2034                 if (strcasecmp(key, "OPTIONS") == 0) {
2035                         const char *pos;
2036
2037                         if (strstr(value, "last_rule") != NULL) {
2038                                 dbg(rules->udev, "last rule to be applied\n");
2039                                 rule->last_rule = 1;
2040                         }
2041                         if (strstr(value, "ignore_device") != NULL) {
2042                                 dbg(rules->udev, "device should be ignored\n");
2043                                 rule->ignore_device = 1;
2044                         }
2045                         if (strstr(value, "ignore_remove") != NULL) {
2046                                 dbg(rules->udev, "remove event should be ignored\n");
2047                                 rule->ignore_remove = 1;
2048                         }
2049                         pos = strstr(value, "link_priority=");
2050                         if (pos != NULL) {
2051                                 rule->link_priority = atoi(&pos[strlen("link_priority=")]);
2052                                 dbg(rules->udev, "link priority=%i\n", rule->link_priority);
2053                         }
2054                         pos = strstr(value, "event_timeout=");
2055                         if (pos != NULL) {
2056                                 rule->event_timeout = atoi(&pos[strlen("event_timeout=")]);
2057                                 dbg(rules->udev, "event timout=%i\n", rule->event_timeout);
2058                         }
2059                         pos = strstr(value, "string_escape=");
2060                         if (pos != NULL) {
2061                                 pos = &pos[strlen("string_escape=")];
2062                                 if (strncmp(pos, "none", strlen("none")) == 0)
2063                                         rule->string_escape = ESCAPE_NONE;
2064                                 else if (strncmp(pos, "replace", strlen("replace")) == 0)
2065                                         rule->string_escape = ESCAPE_REPLACE;
2066                         }
2067                         if (strstr(value, "all_partitions") != NULL) {
2068                                 dbg(rules->udev, "creation of partition nodes requested\n");
2069                                 rule->partitions = DEFAULT_FAKE_PARTITIONS_COUNT;
2070                         }
2071                         valid = 1;
2072                         continue;
2073                 }
2074
2075                 err(rules->udev, "unknown key '%s' in %s:%u\n", key, filename, lineno);
2076         }
2077
2078         if (physdev && rule->wait_for.operation == KEY_OP_UNSET)
2079                 err(rules->udev, "PHYSDEV* values are deprecated and will be removed from a future kernel, \n"
2080                     "please fix it in %s:%u", filename, lineno);
2081
2082         /* skip line if not any valid key was found */
2083         if (!valid)
2084                 goto invalid;
2085
2086         /* grow buffer and add rule */
2087         rule_size = sizeof(struct udev_rule) + rule->bufsize;
2088         padding = (sizeof(size_t) - rule_size % sizeof(size_t)) % sizeof(size_t);
2089         dbg(rules->udev, "add %zi padding bytes\n", padding);
2090         rule_size += padding;
2091         rule->bufsize += padding;
2092
2093         rules->buf = realloc(rules->buf, rules->bufsize + rule_size);
2094         if (!rules->buf) {
2095                 err(rules->udev, "realloc failed\n");
2096                 goto exit;
2097         }
2098         dbg(rules->udev, "adding rule to offset %zi\n", rules->bufsize);
2099         memcpy(rules->buf + rules->bufsize, rule, rule_size);
2100         rules->bufsize += rule_size;
2101 exit:
2102         return 0;
2103
2104 invalid:
2105         err(rules->udev, "invalid rule '%s:%u'\n", filename, lineno);
2106         return -1;
2107 }
2108
2109 static int parse_file(struct udev_rules *rules, const char *filename)
2110 {
2111         FILE *f;
2112         char line[UTIL_LINE_SIZE];
2113         size_t start;
2114         struct udev_rule *rule;
2115         struct udev_rules_iter iter;
2116
2117         start = rules->bufsize;
2118         info(rules->udev, "reading '%s' as rules file\n", filename);
2119
2120         f = fopen(filename, "r");
2121         if (f == NULL)
2122                 return -1;
2123
2124         while(fgets(line, sizeof(line), f) != NULL) {
2125                 int line_nr = 0;
2126                 char *key;
2127                 size_t len;
2128
2129                 /* skip whitespace */
2130                 line_nr++;
2131                 key = line;
2132                 while (isspace(key[0]))
2133                         key++;
2134
2135                 /* comment */
2136                 if (key[0] == '#')
2137                         continue;
2138
2139                 len = strlen(line);
2140                 if (len < 3)
2141                         continue;
2142
2143                 /* continue reading if backslash+newline is found */
2144                 while (line[len-2] == '\\') {
2145                         if (fgets(&line[len-2], (sizeof(line)-len)+2, f) == NULL)
2146                                 break;
2147                         line_nr++;
2148                         len = strlen(line);
2149                 }
2150
2151                 if (len+1 >= sizeof(line)) {
2152                         err(rules->udev, "line too long '%s':%u, ignored\n", filename, line_nr);
2153                         continue;
2154                 }
2155                 add_to_rules(rules, key, filename, line_nr);
2156         }
2157         fclose(f);
2158
2159         /* compute all goto targets within this file */
2160         udev_rules_iter_init(&iter, rules);
2161         udev_rules_iter_goto(&iter, start);
2162         while((rule = udev_rules_iter_next(&iter))) {
2163                 if (rule->goto_label.operation != KEY_OP_UNSET) {
2164                         char *goto_label = &rule->buf[rule->goto_label.val_off];
2165
2166                         dbg(rules->udev, "resolving goto label '%s'\n", goto_label);
2167                         rule->goto_rule_off = find_label(&iter, goto_label);
2168                         if (rule->goto_rule_off == 0) {
2169                                 err(rules->udev, "ignore goto to nonexistent label '%s' in '%s'\n",
2170                                     goto_label, filename);
2171                                 rule->goto_rule_off = iter.current;
2172                         }
2173                 }
2174         }
2175         return 0;
2176 }
2177
2178 static int add_matching_files(struct udev *udev, struct udev_list_node *file_list, const char *dirname, const char *suffix)
2179 {
2180         struct dirent *ent;
2181         DIR *dir;
2182         char filename[UTIL_PATH_SIZE];
2183
2184         dbg(udev, "open directory '%s'\n", dirname);
2185         dir = opendir(dirname);
2186         if (dir == NULL) {
2187                 err(udev, "unable to open '%s': %m\n", dirname);
2188                 return -1;
2189         }
2190
2191         while (1) {
2192                 ent = readdir(dir);
2193                 if (ent == NULL || ent->d_name[0] == '\0')
2194                         break;
2195
2196                 if ((ent->d_name[0] == '.') || (ent->d_name[0] == '#'))
2197                         continue;
2198
2199                 /* look for file matching with specified suffix */
2200                 if (suffix != NULL) {
2201                         const char *ext;
2202
2203                         ext = strrchr(ent->d_name, '.');
2204                         if (ext == NULL)
2205                                 continue;
2206                         if (strcmp(ext, suffix) != 0)
2207                                 continue;
2208                 }
2209                 dbg(udev, "put file '%s/%s' into list\n", dirname, ent->d_name);
2210
2211                 snprintf(filename, sizeof(filename), "%s/%s", dirname, ent->d_name);
2212                 filename[sizeof(filename)-1] = '\0';
2213                 udev_list_entry_add(udev, file_list, filename, NULL, 1, 1);
2214         }
2215
2216         closedir(dir);
2217         return 0;
2218 }
2219
2220 struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names)
2221 {
2222         struct udev_rules *rules;
2223         struct stat statbuf;
2224         char filename[PATH_MAX];
2225         struct udev_list_node file_list;
2226         struct udev_list_entry *file_loop, *file_tmp;
2227
2228         rules = malloc(sizeof(struct udev_rules));
2229         if (rules == NULL)
2230                 return rules;
2231         memset(rules, 0x00, sizeof(struct udev_rules));
2232         rules->udev = udev;
2233         rules->resolve_names = resolve_names;
2234         udev_list_init(&file_list);
2235
2236         if (udev_get_rules_path(udev) != NULL) {
2237                 /* custom rules location for testing */
2238                 add_matching_files(udev, &file_list, udev_get_rules_path(udev), ".rules");
2239         } else {
2240                 struct udev_list_node sort_list;
2241                 struct udev_list_entry *sort_loop, *sort_tmp;
2242
2243                 /* read user/custom rules */
2244                 add_matching_files(udev, &file_list, SYSCONFDIR "/udev/rules.d", ".rules");
2245
2246                 /* read dynamic/temporary rules */
2247                 util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename));
2248                 util_strlcat(filename, "/.udev/rules.d", sizeof(filename));
2249                 if (stat(filename, &statbuf) != 0) {
2250                         create_path(udev, filename);
2251                         udev_selinux_setfscreatecon(udev, filename, S_IFDIR|0755);
2252                         mkdir(filename, 0755);
2253                         udev_selinux_resetfscreatecon(udev);
2254                 }
2255                 udev_list_init(&sort_list);
2256                 add_matching_files(udev, &sort_list, filename, ".rules");
2257
2258                 /* read default rules */
2259                 add_matching_files(udev, &sort_list, UDEV_PREFIX "/lib/udev/rules.d", ".rules");
2260
2261                 /* sort all rules files by basename into list of files */
2262                 udev_list_entry_foreach_safe(sort_loop, sort_tmp, udev_list_get_entry(&sort_list)) {
2263                         const char *sort_name = udev_list_entry_get_name(sort_loop);
2264                         const char *sort_base = strrchr(sort_name, '/');
2265
2266                         if (sort_base == NULL)
2267                                 continue;
2268
2269                         udev_list_entry_foreach_safe(file_loop, file_tmp, udev_list_get_entry(&file_list)) {
2270                                 const char *file_name = udev_list_entry_get_name(file_loop);
2271                                 const char *file_base = strrchr(file_name, '/');
2272
2273                                 if (file_base == NULL)
2274                                         continue;
2275                                 if (strcmp(file_base, sort_base) == 0) {
2276                                         info(udev, "rule file basename '%s' already added, ignoring '%s'\n",
2277                                              file_name, sort_name);
2278                                         udev_list_entry_remove(sort_loop);
2279                                         sort_loop = NULL;
2280                                         break;
2281                                 }
2282                                 if (strcmp(file_base, sort_base) > 0)
2283                                         break;
2284                         }
2285                         if (sort_loop != NULL)
2286                                 udev_list_entry_move_before(sort_loop, file_loop);
2287                 }
2288         }
2289
2290         /* parse list of files */
2291         udev_list_entry_foreach_safe(file_loop, file_tmp, udev_list_get_entry(&file_list)) {
2292                 const char *file_name = udev_list_entry_get_name(file_loop);
2293
2294                 if (stat(file_name, &statbuf) == 0 && statbuf.st_size > 0)
2295                         parse_file(rules, file_name);
2296                 else
2297                         info(udev, "can not read '%s'\n", file_name);
2298                 udev_list_entry_remove(file_loop);
2299         }
2300         return rules;
2301 }
2302
2303 void udev_rules_unref(struct udev_rules *rules)
2304 {
2305         if (rules == NULL)
2306                 return;
2307         if (rules->buf) {
2308                 free(rules->buf);
2309                 rules->buf = NULL;
2310         }
2311         free(rules);
2312 }