chiark / gitweb /
replace missing get_attr_value() -> get_sysattr_value()
[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 static int import_property_from_string(struct udev_device *dev, char *line)
194 {
195         struct udev *udev = udev_device_get_udev(dev);
196         char *key;
197         char *val;
198         size_t len;
199
200         /* find key */
201         key = line;
202         while (isspace(key[0]))
203                 key++;
204
205         /* comment or empty line */
206         if (key[0] == '#' || key[0] == '\0')
207                 return -1;
208
209         /* split key/value */
210         val = strchr(key, '=');
211         if (val == NULL)
212                 return -1;
213         val[0] = '\0';
214         val++;
215
216         /* find value */
217         while (isspace(val[0]))
218                 val++;
219
220         /* terminate key */
221         len = strlen(key);
222         if (len == 0)
223                 return -1;
224         while (isspace(key[len-1]))
225                 len--;
226         key[len] = '\0';
227
228         /* terminate value */
229         len = strlen(val);
230         if (len == 0)
231                 return -1;
232         while (isspace(val[len-1]))
233                 len--;
234         val[len] = '\0';
235
236         if (len == 0)
237                 return -1;
238
239         /* unquote */
240         if (val[0] == '"' || val[0] == '\'') {
241                 if (val[len-1] != val[0]) {
242                         info(udev, "inconsistent quoting: '%s', skip\n", line);
243                         return -1;
244                 }
245                 val[len-1] = '\0';
246                 val++;
247         }
248
249         info(udev, "adding '%s'='%s'\n", key, val);
250
251         /* handle device, renamed by external tool, returning new path */
252         if (strcmp(key, "DEVPATH") == 0) {
253                 char syspath[UTIL_PATH_SIZE];
254
255                 info(udev, "updating devpath from '%s' to '%s'\n",
256                      udev_device_get_devpath(dev), val);
257                 util_strlcpy(syspath, udev_get_sys_path(udev), sizeof(syspath));
258                 util_strlcat(syspath, val, sizeof(syspath));
259                 udev_device_set_syspath(dev, syspath);
260         } else {
261                 struct udev_list_entry *entry;
262
263                 entry = udev_device_add_property(dev, key, val);
264                 /* store in db */
265                 udev_list_entry_set_flag(entry, 1);
266         }
267         return 0;
268 }
269
270 static int import_file_into_env(struct udev_device *dev, const char *filename)
271 {
272         FILE *f;
273         char line[UTIL_LINE_SIZE];
274
275         f = fopen(filename, "r");
276         if (f == NULL)
277                 return -1;
278         while (fgets(line, sizeof(line), f) != NULL)
279                 import_property_from_string(dev, line);
280         fclose(f);
281         return 0;
282 }
283
284 static int import_program_into_env(struct udev_device *dev, const char *program)
285 {
286         struct udev *udev = udev_device_get_udev(dev);
287         char **envp;
288         char result[2048];
289         size_t reslen;
290         char *line;
291
292         envp = udev_device_get_properties_envp(dev);
293         if (util_run_program(udev, program, envp, result, sizeof(result), &reslen) != 0)
294                 return -1;
295
296         line = result;
297         while (line != NULL) {
298                 char *pos;
299
300                 pos = strchr(line, '\n');
301                 if (pos != NULL) {
302                         pos[0] = '\0';
303                         pos = &pos[1];
304                 }
305                 import_property_from_string(dev, line);
306                 line = pos;
307         }
308         return 0;
309 }
310
311 static int import_parent_into_env(struct udev_device *dev, const char *filter)
312 {
313         struct udev *udev = udev_device_get_udev(dev);
314         struct udev_device *dev_parent;
315         struct udev_list_entry *list_entry;
316
317         dev_parent = udev_device_get_parent(dev);
318         if (dev_parent == NULL)
319                 return -1;
320
321         dbg(udev, "found parent '%s', get the node name\n", udev_device_get_syspath(dev_parent));
322         udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(dev_parent)) {
323                 const char *key = udev_list_entry_get_name(list_entry);
324                 const char *val = udev_list_entry_get_value(list_entry);
325
326                 if (fnmatch(filter, key, 0) == 0) {
327                         struct udev_list_entry *entry;
328
329                         dbg(udev, "import key '%s=%s'\n", key, val);
330                         entry = udev_device_add_property(dev, key, val);
331                         /* store in db */
332                         udev_list_entry_set_flag(entry, 1);
333                 }
334         }
335         return 0;
336 }
337
338 #define WAIT_LOOP_PER_SECOND            50
339 static int wait_for_file(struct udev_event *event, const char *file, int timeout)
340 {
341         char filepath[UTIL_PATH_SIZE];
342         char devicepath[UTIL_PATH_SIZE] = "";
343         struct stat stats;
344         int loop = timeout * WAIT_LOOP_PER_SECOND;
345
346         /* a relative path is a device attribute */
347         if (file[0] != '/') {
348                 util_strlcpy(devicepath, udev_get_sys_path(event->udev), sizeof(devicepath));
349                 util_strlcat(devicepath, udev_device_get_devpath(event->dev), sizeof(devicepath));
350
351                 util_strlcpy(filepath, devicepath, sizeof(filepath));
352                 util_strlcat(filepath, "/", sizeof(filepath));
353                 util_strlcat(filepath, file, sizeof(filepath));
354                 file = filepath;
355         }
356
357         dbg(event->udev, "will wait %i sec for '%s'\n", timeout, file);
358         while (--loop) {
359                 /* lookup file */
360                 if (stat(file, &stats) == 0) {
361                         info(event->udev, "file '%s' appeared after %i loops\n", file, (timeout * WAIT_LOOP_PER_SECOND) - loop-1);
362                         return 0;
363                 }
364                 /* make sure, the device did not disappear in the meantime */
365                 if (devicepath[0] != '\0' && stat(devicepath, &stats) != 0) {
366                         info(event->udev, "device disappeared while waiting for '%s'\n", file);
367                         return -2;
368                 }
369                 info(event->udev, "wait for '%s' for %i mseconds\n", file, 1000 / WAIT_LOOP_PER_SECOND);
370                 usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
371         }
372         info(event->udev, "waiting for '%s' failed\n", file);
373         return -1;
374 }
375
376 static int attr_subst_subdir(char *attr, size_t len)
377 {
378         char *pos;
379         int found = 0;
380
381         pos = strstr(attr, "/*/");
382         if (pos != NULL) {
383                 char str[UTIL_PATH_SIZE];
384                 DIR *dir;
385
386                 pos[1] = '\0';
387                 util_strlcpy(str, &pos[2], sizeof(str));
388                 dir = opendir(attr);
389                 if (dir != NULL) {
390                         struct dirent *dent;
391
392                         for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
393                                 struct stat stats;
394
395                                 if (dent->d_name[0] == '.')
396                                         continue;
397                                 util_strlcat(attr, dent->d_name, len);
398                                 util_strlcat(attr, str, len);
399                                 if (stat(attr, &stats) == 0) {
400                                         found = 1;
401                                         break;
402                                 }
403                                 pos[1] = '\0';
404                         }
405                         closedir(dir);
406                 }
407                 if (!found)
408                         util_strlcat(attr, str, len);
409         }
410
411         return found;
412 }
413
414 static char *key_val(struct udev_rule *rule, struct key *key)
415 {
416         return rule->buf + key->val_off;
417 }
418
419 static char *key_pair_name(struct udev_rule *rule, struct key_pair *pair)
420 {
421         return rule->buf + pair->key_name_off;
422 }
423
424 static int match_key(struct udev *udev, const char *key_name, struct udev_rule *rule, struct key *key, const char *val)
425 {
426         char value[UTIL_PATH_SIZE];
427         char *key_value;
428         char *pos;
429         int match = 0;
430
431         if (key->operation != KEY_OP_MATCH &&
432             key->operation != KEY_OP_NOMATCH)
433                 return 0;
434
435         if (val == NULL)
436                 val = "";
437
438         /* look for a matching string, parts are separated by '|' */
439         util_strlcpy(value, rule->buf + key->val_off, sizeof(value));
440         key_value = value;
441         dbg(udev, "key %s value='%s'\n", key_name, key_value);
442         while (key_value != NULL) {
443                 pos = strchr(key_value, '|');
444                 if (pos != NULL) {
445                         pos[0] = '\0';
446                         pos = &pos[1];
447                 }
448
449                 dbg(udev, "match %s '%s' <-> '%s'\n", key_name, key_value, val);
450                 match = (fnmatch(key_value, val, 0) == 0);
451                 if (match)
452                         break;
453
454                 key_value = pos;
455         }
456
457         if (match && (key->operation == KEY_OP_MATCH)) {
458                 dbg(udev, "%s is true (matching value)\n", key_name);
459                 return 0;
460         }
461         if (!match && (key->operation == KEY_OP_NOMATCH)) {
462                 dbg(udev, "%s is true (non-matching value)\n", key_name);
463                 return 0;
464         }
465         return -1;
466 }
467
468 /* match a single rule against a given device and possibly its parent devices */
469 static int match_rule(struct udev_event *event, struct udev_rule *rule)
470 {
471         struct udev_device *dev = event->dev;
472         int i;
473
474         if (match_key(event->udev, "ACTION", rule, &rule->action, udev_device_get_action(dev)))
475                 goto nomatch;
476
477         if (match_key(event->udev, "KERNEL", rule, &rule->kernel, udev_device_get_sysname(dev)))
478                 goto nomatch;
479
480         if (match_key(event->udev, "SUBSYSTEM", rule, &rule->subsystem, udev_device_get_subsystem(dev)))
481                 goto nomatch;
482
483         if (match_key(event->udev, "DEVPATH", rule, &rule->devpath, udev_device_get_devpath(dev)))
484                 goto nomatch;
485
486         if (match_key(event->udev, "DRIVER", rule, &rule->driver, udev_device_get_driver(dev)))
487                 goto nomatch;
488
489         /* match NAME against a value assigned by an earlier rule */
490         if (match_key(event->udev, "NAME", rule, &rule->name, event->name))
491                 goto nomatch;
492
493         /* match against current list of symlinks */
494         if (rule->symlink_match.operation == KEY_OP_MATCH ||
495             rule->symlink_match.operation == KEY_OP_NOMATCH) {
496                 size_t devlen = strlen(udev_get_dev_path(event->udev))+1;
497                 struct udev_list_entry *list_entry;
498                 int match = 0;
499
500                 udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) {
501                         const char *devlink;
502
503                         devlink =  &udev_list_entry_get_name(list_entry)[devlen];
504                         if (match_key(event->udev, "SYMLINK", rule, &rule->symlink_match, devlink) == 0) {
505                                 match = 1;
506                                 break;
507                         }
508                 }
509                 if (!match)
510                         goto nomatch;
511         }
512
513         for (i = 0; i < rule->env.count; i++) {
514                 struct key_pair *pair = &rule->env.keys[i];
515
516                 /* we only check for matches, assignments will be handled later */
517                 if (pair->key.operation == KEY_OP_MATCH ||
518                     pair->key.operation == KEY_OP_NOMATCH) {
519                         struct udev_list_entry *list_entry;
520                         const char *key_name = key_pair_name(rule, pair);
521                         const char *value;
522
523                         list_entry = udev_device_get_properties_list_entry(event->dev);
524                         list_entry = udev_list_entry_get_by_name(list_entry, key_name);
525                         value = udev_list_entry_get_value(list_entry);
526                         if (value == NULL) {
527                                 dbg(event->udev, "ENV{%s} is not set, treat as empty\n", key_name);
528                                 value = "";
529                         }
530                         if (match_key(event->udev, "ENV", rule, &pair->key, value))
531                                 goto nomatch;
532                 }
533         }
534
535         if (rule->test.operation == KEY_OP_MATCH ||
536             rule->test.operation == KEY_OP_NOMATCH) {
537                 char filename[UTIL_PATH_SIZE];
538                 struct stat statbuf;
539                 int match;
540
541                 util_strlcpy(filename, key_val(rule, &rule->test), sizeof(filename));
542                 udev_event_apply_format(event, filename, sizeof(filename));
543                 if (udev_event_apply_subsys_kernel(event, NULL, filename, sizeof(filename), 0) != 0)
544                         if (filename[0] != '/') {
545                                 char tmp[UTIL_PATH_SIZE];
546
547                                 util_strlcpy(tmp, udev_device_get_syspath(dev), sizeof(tmp));
548                                 util_strlcat(tmp, "/", sizeof(tmp));
549                                 util_strlcat(tmp, filename, sizeof(tmp));
550                                 util_strlcpy(filename, tmp, sizeof(filename));
551                         }
552
553                 attr_subst_subdir(filename, sizeof(filename));
554
555                 match = (stat(filename, &statbuf) == 0);
556                 info(event->udev, "'%s' %s", filename, match ? "exists\n" : "does not exist\n");
557                 if (match && rule->test_mode_mask > 0) {
558                         match = ((statbuf.st_mode & rule->test_mode_mask) > 0);
559                         info(event->udev, "'%s' has mode=%#o and %s %#o\n", filename, statbuf.st_mode,
560                              match ? "matches" : "does not match",
561                              rule->test_mode_mask);
562                 }
563                 if (match && rule->test.operation == KEY_OP_NOMATCH)
564                         goto nomatch;
565                 if (!match && rule->test.operation == KEY_OP_MATCH)
566                         goto nomatch;
567                 dbg(event->udev, "TEST key is true\n");
568         }
569
570         if (rule->wait_for.operation != KEY_OP_UNSET) {
571                 char filename[UTIL_PATH_SIZE];
572                 int found;
573
574                 util_strlcpy(filename, key_val(rule, &rule->wait_for), sizeof(filename));
575                 udev_event_apply_format(event, filename, sizeof(filename));
576                 found = (wait_for_file(event, filename, 10) == 0);
577                 if (!found && (rule->wait_for.operation != KEY_OP_NOMATCH))
578                         goto nomatch;
579         }
580
581         /* check for matching sysfs attribute pairs */
582         for (i = 0; i < rule->attr.count; i++) {
583                 struct key_pair *pair = &rule->attr.keys[i];
584
585                 if (pair->key.operation == KEY_OP_MATCH ||
586                     pair->key.operation == KEY_OP_NOMATCH) {
587                         char attr[UTIL_PATH_SIZE];
588                         const char *key_name = key_pair_name(rule, pair);
589                         const char *key_value = key_val(rule, &pair->key);
590                         char value[UTIL_NAME_SIZE] = "";
591                         size_t len;
592
593                         util_strlcpy(attr, key_name, sizeof(attr));
594                         udev_event_apply_subsys_kernel(event, attr, value, sizeof(value), 1);
595
596                         if (value[0]=='\0') {
597                                 const char *val;
598
599                                 val = udev_device_get_sysattr_value(dev, key_name);
600                                 if (val != NULL)
601                                         util_strlcpy(value, val, sizeof(value));
602                         }
603
604                         if (value[0]=='\0')
605                                 goto nomatch;
606
607                         /* strip trailing whitespace of value, if not asked to match for it */
608                         len = strlen(key_value);
609                         if (len > 0 && !isspace(key_value[len-1])) {
610                                 len = strlen(value);
611                                 while (len > 0 && isspace(value[--len]))
612                                         value[len] = '\0';
613                                 dbg(event->udev, "removed trailing whitespace from '%s'\n", value);
614                         }
615
616                         if (match_key(event->udev, "ATTR", rule, &pair->key, value))
617                                 goto nomatch;
618                 }
619         }
620
621         /* walk up the chain of parent devices and find a match */
622         event->dev_parent = dev;
623         while (1) {
624                 /* check for matching kernel device name */
625                 if (match_key(event->udev, "KERNELS", rule,
626                               &rule->kernels, udev_device_get_sysname(event->dev_parent)))
627                         goto try_parent;
628
629                 /* check for matching subsystem value */
630                 if (match_key(event->udev, "SUBSYSTEMS", rule,
631                               &rule->subsystems, udev_device_get_subsystem(event->dev_parent)))
632                         goto try_parent;
633
634                 /* check for matching driver */
635                 if (match_key(event->udev, "DRIVERS", rule,
636                               &rule->drivers, udev_device_get_driver(event->dev_parent)))
637                         goto try_parent;
638
639                 /* check for matching sysfs attribute pairs */
640                 for (i = 0; i < rule->attrs.count; i++) {
641                         struct key_pair *pair = &rule->attrs.keys[i];
642
643                         if (pair->key.operation == KEY_OP_MATCH ||
644                             pair->key.operation == KEY_OP_NOMATCH) {
645                                 const char *key_name = key_pair_name(rule, pair);
646                                 const char *key_value = key_val(rule, &pair->key);
647                                 const char *val;
648                                 char value[UTIL_NAME_SIZE];
649                                 size_t len;
650
651                                 val = udev_device_get_sysattr_value(event->dev_parent, key_name);
652                                 if (val == NULL)
653                                         val = udev_device_get_sysattr_value(dev, key_name);
654                                 if (val == NULL)
655                                         goto try_parent;
656                                 util_strlcpy(value, val, sizeof(value));
657
658                                 /* strip trailing whitespace of value, if not asked to match for it */
659                                 len = strlen(key_value);
660                                 if (len > 0 && !isspace(key_value[len-1])) {
661                                         len = strlen(value);
662                                         while (len > 0 && isspace(value[--len]))
663                                                 value[len] = '\0';
664                                         dbg(event->udev, "removed trailing whitespace from '%s'\n", value);
665                                 }
666
667                                 if (match_key(event->udev, "ATTRS", rule, &pair->key, value))
668                                         goto try_parent;
669                         }
670                 }
671
672                 /* found matching device  */
673                 break;
674 try_parent:
675                 /* move to parent device */
676                 dbg(event->udev, "try parent sysfs device\n");
677                 event->dev_parent = udev_device_get_parent(event->dev_parent);
678                 if (event->dev_parent == NULL)
679                         goto nomatch;
680                 dbg(event->udev, "looking at dev_parent->devpath='%s'\n",
681                     udev_device_get_syspath(event->dev_parent));
682         }
683
684         /* execute external program */
685         if (rule->program.operation != KEY_OP_UNSET) {
686                 char program[UTIL_PATH_SIZE];
687                 char **envp;
688                 char result[UTIL_PATH_SIZE];
689
690                 util_strlcpy(program, key_val(rule, &rule->program), sizeof(program));
691                 udev_event_apply_format(event, program, sizeof(program));
692                 envp = udev_device_get_properties_envp(dev);
693                 if (util_run_program(event->udev, program, envp, result, sizeof(result), NULL) != 0) {
694                         dbg(event->udev, "PROGRAM is false\n");
695                         event->program_result[0] = '\0';
696                         if (rule->program.operation != KEY_OP_NOMATCH)
697                                 goto nomatch;
698                 } else {
699                         int count;
700
701                         dbg(event->udev, "PROGRAM matches\n");
702                         util_remove_trailing_chars(result, '\n');
703                         if (rule->string_escape == ESCAPE_UNSET ||
704                             rule->string_escape == ESCAPE_REPLACE) {
705                                 count = util_replace_chars(result, ALLOWED_CHARS_INPUT);
706                                 if (count > 0)
707                                         info(event->udev, "%i character(s) replaced\n" , count);
708                         }
709                         dbg(event->udev, "result is '%s'\n", result);
710                         util_strlcpy(event->program_result, result, sizeof(event->program_result));
711                         dbg(event->udev, "PROGRAM returned successful\n");
712                         if (rule->program.operation == KEY_OP_NOMATCH)
713                                 goto nomatch;
714                 }
715                 dbg(event->udev, "PROGRAM key is true\n");
716         }
717
718         /* check for matching result of external program */
719         if (match_key(event->udev, "RESULT", rule, &rule->result, event->program_result))
720                 goto nomatch;
721
722         /* import variables returned from program or or file into properties */
723         if (rule->import.operation != KEY_OP_UNSET) {
724                 char import[UTIL_PATH_SIZE];
725                 int rc = -1;
726
727                 util_strlcpy(import, key_val(rule, &rule->import), sizeof(import));
728                 udev_event_apply_format(event, import, sizeof(import));
729                 dbg(event->udev, "check for IMPORT import='%s'\n", import);
730                 if (rule->import_type == IMPORT_PROGRAM) {
731                         rc = import_program_into_env(event->dev, import);
732                 } else if (rule->import_type == IMPORT_FILE) {
733                         dbg(event->udev, "import file import='%s'\n", import);
734                         rc = import_file_into_env(event->dev, import);
735                 } else if (rule->import_type == IMPORT_PARENT) {
736                         dbg(event->udev, "import parent import='%s'\n", import);
737                         rc = import_parent_into_env(event->dev, import);
738                 }
739                 if (rc != 0) {
740                         dbg(event->udev, "IMPORT failed\n");
741                         if (rule->import.operation != KEY_OP_NOMATCH)
742                                 goto nomatch;
743                 } else
744                         dbg(event->udev, "IMPORT '%s' imported\n", key_val(rule, &rule->import));
745                 dbg(event->udev, "IMPORT key is true\n");
746         }
747
748         /* rule matches, if we have ENV assignments export it */
749         for (i = 0; i < rule->env.count; i++) {
750                 struct key_pair *pair = &rule->env.keys[i];
751
752                 if (pair->key.operation == KEY_OP_ASSIGN) {
753                         char temp_value[UTIL_NAME_SIZE];
754                         const char *key_name = key_pair_name(rule, pair);
755                         const char *value = key_val(rule, &pair->key);
756
757                         /* make sure we don't write to the same string we possibly read from */
758                         util_strlcpy(temp_value, value, sizeof(temp_value));
759                         udev_event_apply_format(event, temp_value, sizeof(temp_value));
760
761                         if (temp_value[0] != '\0') {
762                                 struct udev_list_entry *entry;
763
764                                 info(event->udev, "set ENV '%s=%s'\n", key_name, temp_value);
765                                 entry = udev_device_add_property(dev, key_name, temp_value);
766                                 /* store in db */
767                                 udev_list_entry_set_flag(entry, 1);
768                         }
769                 }
770         }
771
772         /* if we have ATTR assignments, write value to sysfs file */
773         for (i = 0; i < rule->attr.count; i++) {
774                 struct key_pair *pair = &rule->attr.keys[i];
775
776                 if (pair->key.operation == KEY_OP_ASSIGN) {
777                         const char *key_name = key_pair_name(rule, pair);
778                         char attr[UTIL_PATH_SIZE];
779                         char value[UTIL_NAME_SIZE];
780                         FILE *f;
781
782                         util_strlcpy(attr, key_name, sizeof(attr));
783                         if (udev_event_apply_subsys_kernel(event, key_name, attr, sizeof(attr), 0) != 0) {
784                                 util_strlcpy(attr, udev_device_get_syspath(dev), sizeof(attr));
785                                 util_strlcat(attr, "/", sizeof(attr));
786                                 util_strlcat(attr, key_name, sizeof(attr));
787                         }
788
789                         attr_subst_subdir(attr, sizeof(attr));
790
791                         util_strlcpy(value, key_val(rule, &pair->key), sizeof(value));
792                         udev_event_apply_format(event, value, sizeof(value));
793                         info(event->udev, "writing '%s' to sysfs file '%s'\n", value, attr);
794                         f = fopen(attr, "w");
795                         if (f != NULL) {
796                                 if (!event->test)
797                                         if (fprintf(f, "%s", value) <= 0)
798                                                 err(event->udev, "error writing ATTR{%s}: %m\n", attr);
799                                 fclose(f);
800                         } else
801                                 err(event->udev, "error opening ATTR{%s} for writing: %m\n", attr);
802                 }
803         }
804         return 0;
805
806 nomatch:
807         return -1;
808 }
809
810 int udev_rules_get_name(struct udev_rules *rules, struct udev_event *event)
811 {
812         struct udev_device *dev = event->dev;
813         struct udev_rules_iter iter;
814         struct udev_rule *rule;
815         int name_set = 0;
816
817         dbg(event->udev, "device: '%s'\n", udev_device_get_syspath(dev));
818
819         /* look for a matching rule to apply */
820         udev_rules_iter_init(&iter, rules);
821         while (1) {
822                 rule = udev_rules_iter_next(&iter);
823                 if (rule == NULL)
824                         break;
825
826                 if (name_set &&
827                     (rule->name.operation == KEY_OP_ASSIGN ||
828                      rule->name.operation == KEY_OP_ASSIGN_FINAL ||
829                      rule->name.operation == KEY_OP_ADD)) {
830                         dbg(event->udev, "node name already set, rule ignored\n");
831                         continue;
832                 }
833
834                 dbg(event->udev, "process rule\n");
835                 if (match_rule(event, rule) == 0) {
836                         /* apply options */
837                         if (rule->ignore_device) {
838                                 info(event->udev, "rule applied, '%s' is ignored\n", udev_device_get_sysname(dev));
839                                 event->ignore_device = 1;
840                                 return 0;
841                         }
842                         if (rule->ignore_remove) {
843                                 udev_device_set_ignore_remove(dev, 1);
844                                 dbg(event->udev, "remove event should be ignored\n");
845                         }
846                         if (rule->link_priority != 0) {
847                                 udev_device_set_devlink_priority(dev, rule->link_priority);
848                                 info(event->udev, "devlink_priority=%i\n", rule->link_priority);
849                         }
850                         if (rule->event_timeout >= 0) {
851                                 udev_device_set_event_timeout(dev, rule->event_timeout);
852                                 info(event->udev, "event_timeout=%i\n", rule->event_timeout);
853                         }
854                         /* apply all_partitions option only at a disk device */
855                         if (rule->partitions > 0 &&
856                             strcmp(udev_device_get_subsystem(dev), "block") == 0 &&
857                             udev_device_get_sysnum(dev) == NULL) {
858                                 udev_device_set_num_fake_partitions(dev, rule->partitions);
859                                 dbg(event->udev, "creation of partition nodes requested\n");
860                         }
861
862                         /* apply permissions */
863                         if (!event->mode_final && rule->mode.operation != KEY_OP_UNSET) {
864                                 if (rule->mode.operation == KEY_OP_ASSIGN_FINAL)
865                                         event->mode_final = 1;
866                                 char buf[20];
867                                 util_strlcpy(buf, key_val(rule, &rule->mode), sizeof(buf));
868                                 udev_event_apply_format(event, buf, sizeof(buf));
869                                 event->mode = strtol(buf, NULL, 8);
870                                 dbg(event->udev, "applied mode=%#o to '%s'\n",
871                                     event->mode, udev_device_get_sysname(dev));
872                         }
873                         if (!event->owner_final && rule->owner.operation != KEY_OP_UNSET) {
874                                 if (rule->owner.operation == KEY_OP_ASSIGN_FINAL)
875                                         event->owner_final = 1;
876                                 util_strlcpy(event->owner, key_val(rule, &rule->owner), sizeof(event->owner));
877                                 udev_event_apply_format(event, event->owner, sizeof(event->owner));
878                                 dbg(event->udev, "applied owner='%s' to '%s'\n",
879                                     event->owner, udev_device_get_sysname(dev));
880                         }
881                         if (!event->group_final && rule->group.operation != KEY_OP_UNSET) {
882                                 if (rule->group.operation == KEY_OP_ASSIGN_FINAL)
883                                         event->group_final = 1;
884                                 util_strlcpy(event->group, key_val(rule, &rule->group), sizeof(event->group));
885                                 udev_event_apply_format(event, event->group, sizeof(event->group));
886                                 dbg(event->udev, "applied group='%s' to '%s'\n",
887                                     event->group, udev_device_get_sysname(dev));
888                         }
889
890                         /* collect symlinks */
891                         if (!event->devlink_final &&
892                             (rule->symlink.operation == KEY_OP_ASSIGN ||
893                              rule->symlink.operation == KEY_OP_ASSIGN_FINAL ||
894                              rule->symlink.operation == KEY_OP_ADD)) {
895                                 char temp[UTIL_PATH_SIZE];
896                                 char filename[UTIL_PATH_SIZE];
897                                 char *pos, *next;
898                                 int count = 0;
899
900                                 if (rule->symlink.operation == KEY_OP_ASSIGN_FINAL)
901                                         event->devlink_final = 1;
902                                 if (rule->symlink.operation == KEY_OP_ASSIGN ||
903                                     rule->symlink.operation == KEY_OP_ASSIGN_FINAL) {
904                                         info(event->udev, "reset symlink list\n");
905                                         udev_device_cleanup_devlinks_list(dev);
906                                 }
907                                 /* allow  multiple symlinks separated by spaces */
908                                 util_strlcpy(temp, key_val(rule, &rule->symlink), sizeof(temp));
909                                 udev_event_apply_format(event, temp, sizeof(temp));
910                                 if (rule->string_escape == ESCAPE_UNSET)
911                                         count = util_replace_chars(temp, ALLOWED_CHARS_FILE " ");
912                                 else if (rule->string_escape == ESCAPE_REPLACE)
913                                         count = util_replace_chars(temp, ALLOWED_CHARS_FILE);
914                                 if (count > 0)
915                                         info(event->udev, "%i character(s) replaced\n" , count);
916                                 dbg(event->udev, "rule applied, added symlink(s) '%s'\n", temp);
917                                 pos = temp;
918                                 while (isspace(pos[0]))
919                                         pos++;
920                                 next = strchr(pos, ' ');
921                                 while (next) {
922                                         next[0] = '\0';
923                                         info(event->udev, "add symlink '%s'\n", pos);
924                                         util_strlcpy(filename, udev_get_dev_path(event->udev), sizeof(filename));
925                                         util_strlcat(filename, "/", sizeof(filename));
926                                         util_strlcat(filename, pos, sizeof(filename));
927                                         udev_device_add_devlink(dev, filename);
928                                         while (isspace(next[1]))
929                                                 next++;
930                                         pos = &next[1];
931                                         next = strchr(pos, ' ');
932                                 }
933                                 if (pos[0] != '\0') {
934                                         info(event->udev, "add symlink '%s'\n", pos);
935                                         util_strlcpy(filename, udev_get_dev_path(event->udev), sizeof(filename));
936                                         util_strlcat(filename, "/", sizeof(filename));
937                                         util_strlcat(filename, pos, sizeof(filename));
938                                         udev_device_add_devlink(dev, filename);
939                                 }
940                         }
941
942                         /* set name, later rules with name set will be ignored */
943                         if (rule->name.operation == KEY_OP_ASSIGN ||
944                             rule->name.operation == KEY_OP_ASSIGN_FINAL ||
945                             rule->name.operation == KEY_OP_ADD) {
946                                 int count;
947
948                                 name_set = 1;
949                                 util_strlcpy(event->name, key_val(rule, &rule->name), sizeof(event->name));
950                                 udev_event_apply_format(event, event->name, sizeof(event->name));
951                                 if (rule->string_escape == ESCAPE_UNSET ||
952                                     rule->string_escape == ESCAPE_REPLACE) {
953                                         count = util_replace_chars(event->name, ALLOWED_CHARS_FILE);
954                                         if (count > 0)
955                                                 info(event->udev, "%i character(s) replaced\n", count);
956                                 }
957
958                                 info(event->udev, "rule applied, '%s' becomes '%s'\n",
959                                      udev_device_get_sysname(dev), event->name);
960                                 if (strcmp(udev_device_get_subsystem(dev), "net") != 0)
961                                         dbg(event->udev, "'%s' owner='%s', group='%s', mode=%#o partitions=%i\n",
962                                             event->name, event->owner, event->group, event->mode,
963                                             udev_device_get_num_fake_partitions(dev));
964                         }
965
966                         if (!event->run_final && rule->run.operation != KEY_OP_UNSET) {
967                                 struct udev_list_entry *list_entry;
968
969                                 if (rule->run.operation == KEY_OP_ASSIGN_FINAL)
970                                         event->run_final = 1;
971                                 if (rule->run.operation == KEY_OP_ASSIGN || rule->run.operation == KEY_OP_ASSIGN_FINAL) {
972                                         info(event->udev, "reset run list\n");
973                                         udev_list_cleanup_entries(event->udev, &event->run_list);
974                                 }
975                                 dbg(event->udev, "add run '%s'\n", key_val(rule, &rule->run));
976                                 list_entry = udev_list_entry_add(event->udev, &event->run_list,
977                                                                  key_val(rule, &rule->run), NULL, 1, 0);
978                                 if (rule->run_ignore_error && list_entry != NULL)
979                                         udev_list_entry_set_flag(list_entry, 1);
980                         }
981
982                         if (rule->last_rule) {
983                                 dbg(event->udev, "last rule to be applied\n");
984                                 break;
985                         }
986
987                         if (rule->goto_label.operation != KEY_OP_UNSET) {
988                                 dbg(event->udev, "moving forward to label '%s'\n", key_val(rule, &rule->goto_label));
989                                 udev_rules_iter_goto(&iter, rule->goto_rule_off);
990                         }
991                 }
992         }
993
994         if (!name_set) {
995                 info(event->udev, "no node name set, will use kernel name '%s'\n",
996                      udev_device_get_sysname(dev));
997                 util_strlcpy(event->name, udev_device_get_sysname(dev), sizeof(event->name));
998         }
999
1000         if (event->tmp_node[0] != '\0') {
1001                 dbg(event->udev, "removing temporary device node\n");
1002                 util_unlink_secure(event->udev, event->tmp_node);
1003                 event->tmp_node[0] = '\0';
1004         }
1005         return 0;
1006 }
1007
1008 int udev_rules_get_run(struct udev_rules *rules, struct udev_event *event)
1009 {
1010         struct udev_device *dev = event->dev;
1011         struct udev_rules_iter iter;
1012         struct udev_rule *rule;
1013
1014         dbg(event->udev, "sysname: '%s'\n", udev_device_get_sysname(dev));
1015
1016         /* look for a matching rule to apply */
1017         udev_rules_iter_init(&iter, rules);
1018         while (1) {
1019                 rule = udev_rules_iter_next(&iter);
1020                 if (rule == NULL)
1021                         break;
1022
1023                 dbg(event->udev, "process rule\n");
1024                 if (rule->name.operation == KEY_OP_ASSIGN ||
1025                     rule->name.operation == KEY_OP_ASSIGN_FINAL ||
1026                     rule->name.operation == KEY_OP_ADD ||
1027                     rule->symlink.operation == KEY_OP_ASSIGN ||
1028                     rule->symlink.operation == KEY_OP_ASSIGN_FINAL ||
1029                     rule->symlink.operation == KEY_OP_ADD ||
1030                     rule->mode.operation != KEY_OP_UNSET ||
1031                     rule->owner.operation != KEY_OP_UNSET || rule->group.operation != KEY_OP_UNSET) {
1032                         dbg(event->udev, "skip rule that names a device\n");
1033                         continue;
1034                 }
1035
1036                 if (match_rule(event, rule) == 0) {
1037                         if (rule->ignore_device) {
1038                                 info(event->udev, "rule applied, '%s' is ignored\n", udev_device_get_sysname(dev));
1039                                 event->ignore_device = 1;
1040                                 return 0;
1041                         }
1042                         if (rule->ignore_remove) {
1043                                 udev_device_set_ignore_remove(dev, 1);
1044                                 dbg(event->udev, "remove event should be ignored\n");
1045                         }
1046
1047                         if (!event->run_final && rule->run.operation != KEY_OP_UNSET) {
1048                                 struct udev_list_entry *list_entry;
1049
1050                                 if (rule->run.operation == KEY_OP_ASSIGN ||
1051                                     rule->run.operation == KEY_OP_ASSIGN_FINAL) {
1052                                         info(event->udev, "reset run list\n");
1053                                         udev_list_cleanup_entries(event->udev, &event->run_list);
1054                                 }
1055                                 dbg(event->udev, "add run '%s'\n", key_val(rule, &rule->run));
1056                                 list_entry = udev_list_entry_add(event->udev, &event->run_list,
1057                                                                  key_val(rule, &rule->run), NULL, 1, 0);
1058                                 if (rule->run_ignore_error && list_entry != NULL)
1059                                         udev_list_entry_set_flag(list_entry, 1);
1060                                 if (rule->run.operation == KEY_OP_ASSIGN_FINAL)
1061                                         break;
1062                         }
1063
1064                         if (rule->last_rule) {
1065                                 dbg(event->udev, "last rule to be applied\n");
1066                                 break;
1067                         }
1068
1069                         if (rule->goto_label.operation != KEY_OP_UNSET) {
1070                                 dbg(event->udev, "moving forward to label '%s'\n", key_val(rule, &rule->goto_label));
1071                                 udev_rules_iter_goto(&iter, rule->goto_rule_off);
1072                         }
1073                 }
1074         }
1075
1076         return 0;
1077 }
1078
1079 static int get_key(struct udev_rules *rules, char **line, char **key, enum key_operation *operation, char **value)
1080 {
1081         char *linepos;
1082         char *temp;
1083
1084         linepos = *line;
1085         if (linepos == NULL && linepos[0] == '\0')
1086                 return -1;
1087
1088         /* skip whitespace */
1089         while (isspace(linepos[0]) || linepos[0] == ',')
1090                 linepos++;
1091
1092         /* get the key */
1093         if (linepos[0] == '\0')
1094                 return -1;
1095         *key = linepos;
1096
1097         while (1) {
1098                 linepos++;
1099                 if (linepos[0] == '\0')
1100                         return -1;
1101                 if (isspace(linepos[0]))
1102                         break;
1103                 if (linepos[0] == '=')
1104                         break;
1105                 if ((linepos[0] == '+') || (linepos[0] == '!') || (linepos[0] == ':'))
1106                         if (linepos[1] == '=')
1107                                 break;
1108         }
1109
1110         /* remember end of key */
1111         temp = linepos;
1112
1113         /* skip whitespace after key */
1114         while (isspace(linepos[0]))
1115                 linepos++;
1116         if (linepos[0] == '\0')
1117                 return -1;
1118
1119         /* get operation type */
1120         if (linepos[0] == '=' && linepos[1] == '=') {
1121                 *operation = KEY_OP_MATCH;
1122                 linepos += 2;
1123                 dbg(rules->udev, "match:\n");
1124         } else if (linepos[0] == '!' && linepos[1] == '=') {
1125                 *operation = KEY_OP_NOMATCH;
1126                 linepos += 2;
1127                 dbg(rules->udev, "nomatch:\n");
1128         } else if (linepos[0] == '+' && linepos[1] == '=') {
1129                 *operation = KEY_OP_ADD;
1130                 linepos += 2;
1131                 dbg(rules->udev, "add:\n");
1132         } else if (linepos[0] == '=') {
1133                 *operation = KEY_OP_ASSIGN;
1134                 linepos++;
1135                 dbg(rules->udev, "assign:\n");
1136         } else if (linepos[0] == ':' && linepos[1] == '=') {
1137                 *operation = KEY_OP_ASSIGN_FINAL;
1138                 linepos += 2;
1139                 dbg(rules->udev, "assign_final:\n");
1140         } else
1141                 return -1;
1142
1143         /* terminate key */
1144         temp[0] = '\0';
1145
1146         /* skip whitespace after operator */
1147         while (isspace(linepos[0]))
1148                 linepos++;
1149         if (linepos[0] == '\0')
1150                 return -1;
1151
1152         /* get the value*/
1153         if (linepos[0] == '"')
1154                 linepos++;
1155         else
1156                 return -1;
1157         *value = linepos;
1158
1159         temp = strchr(linepos, '"');
1160         if (!temp)
1161                 return -1;
1162         temp[0] = '\0';
1163         temp++;
1164         dbg(rules->udev, "'%s'-'%s'\n", *key, *value);
1165
1166         /* move line to next key */
1167         *line = temp;
1168         return 0;
1169 }
1170
1171 /* extract possible KEY{attr} */
1172 static char *get_key_attribute(struct udev_rules *rules, char *str)
1173 {
1174         char *pos;
1175         char *attr;
1176
1177         attr = strchr(str, '{');
1178         if (attr != NULL) {
1179                 attr++;
1180                 pos = strchr(attr, '}');
1181                 if (pos == NULL) {
1182                         err(rules->udev, "missing closing brace for format\n");
1183                         return NULL;
1184                 }
1185                 pos[0] = '\0';
1186                 dbg(rules->udev, "attribute='%s'\n", attr);
1187                 return attr;
1188         }
1189
1190         return NULL;
1191 }
1192
1193 static int add_rule_key(struct udev_rule *rule, struct key *key,
1194                         enum key_operation operation, const char *value)
1195 {
1196         size_t val_len = strnlen(value, UTIL_PATH_SIZE);
1197
1198         key->operation = operation;
1199
1200         key->val_off = rule->bufsize;
1201         util_strlcpy(rule->buf + rule->bufsize, value, val_len+1);
1202         rule->bufsize += val_len+1;
1203
1204         return 0;
1205 }
1206
1207 static int add_rule_key_pair(struct udev_rules *rules, struct udev_rule *rule, struct key_pairs *pairs,
1208                              enum key_operation operation, const char *key, const char *value)
1209 {
1210         size_t key_len = strnlen(key, UTIL_PATH_SIZE);
1211
1212         if (pairs->count >= PAIRS_MAX) {
1213                 err(rules->udev, "skip, too many keys of the same type in a single rule\n");
1214                 return -1;
1215         }
1216
1217         add_rule_key(rule, &pairs->keys[pairs->count].key, operation, value);
1218
1219         /* add the key-name of the pair */
1220         pairs->keys[pairs->count].key_name_off = rule->bufsize;
1221         util_strlcpy(rule->buf + rule->bufsize, key, key_len+1);
1222         rule->bufsize += key_len+1;
1223
1224         pairs->count++;
1225
1226         return 0;
1227 }
1228
1229 static int add_to_rules(struct udev_rules *rules, char *line, const char *filename, unsigned int lineno)
1230 {
1231         char buf[sizeof(struct udev_rule) + UTIL_LINE_SIZE];
1232         struct udev_rule *rule;
1233         size_t rule_size;
1234         int valid;
1235         char *linepos;
1236         char *attr;
1237         size_t padding;
1238         int physdev = 0;
1239
1240         memset(buf, 0x00, sizeof(buf));
1241         rule = (struct udev_rule *) buf;
1242         rule->event_timeout = -1;
1243         linepos = line;
1244         valid = 0;
1245
1246         /* get all the keys */
1247         while (1) {
1248                 char *key;
1249                 char *value;
1250                 enum key_operation operation = KEY_OP_UNSET;
1251
1252                 if (get_key(rules, &linepos, &key, &operation, &value) != 0)
1253                         break;
1254
1255                 if (strcasecmp(key, "ACTION") == 0) {
1256                         if (operation != KEY_OP_MATCH &&
1257                             operation != KEY_OP_NOMATCH) {
1258                                 err(rules->udev, "invalid ACTION operation\n");
1259                                 goto invalid;
1260                         }
1261                         add_rule_key(rule, &rule->action, operation, value);
1262                         valid = 1;
1263                         continue;
1264                 }
1265
1266                 if (strcasecmp(key, "DEVPATH") == 0) {
1267                         if (operation != KEY_OP_MATCH &&
1268                             operation != KEY_OP_NOMATCH) {
1269                                 err(rules->udev, "invalid DEVPATH operation\n");
1270                                 goto invalid;
1271                         }
1272                         add_rule_key(rule, &rule->devpath, operation, value);
1273                         valid = 1;
1274                         continue;
1275                 }
1276
1277                 if (strcasecmp(key, "KERNEL") == 0) {
1278                         if (operation != KEY_OP_MATCH &&
1279                             operation != KEY_OP_NOMATCH) {
1280                                 err(rules->udev, "invalid KERNEL operation\n");
1281                                 goto invalid;
1282                         }
1283                         add_rule_key(rule, &rule->kernel, operation, value);
1284                         valid = 1;
1285                         continue;
1286                 }
1287
1288                 if (strcasecmp(key, "SUBSYSTEM") == 0) {
1289                         if (operation != KEY_OP_MATCH &&
1290                             operation != KEY_OP_NOMATCH) {
1291                                 err(rules->udev, "invalid SUBSYSTEM operation\n");
1292                                 goto invalid;
1293                         }
1294                         /* bus, class, subsystem events should all be the same */
1295                         if (strcmp(value, "subsystem") == 0 ||
1296                             strcmp(value, "bus") == 0 ||
1297                             strcmp(value, "class") == 0) {
1298                                 if (strcmp(value, "bus") == 0 || strcmp(value, "class") == 0)
1299                                         err(rules->udev, "'%s' must be specified as 'subsystem' \n"
1300                                             "please fix it in %s:%u", value, filename, lineno);
1301                                 add_rule_key(rule, &rule->subsystem, operation, "subsystem|class|bus");
1302                         } else
1303                                 add_rule_key(rule, &rule->subsystem, operation, value);
1304                         valid = 1;
1305                         continue;
1306                 }
1307
1308                 if (strcasecmp(key, "DRIVER") == 0) {
1309                         if (operation != KEY_OP_MATCH &&
1310                             operation != KEY_OP_NOMATCH) {
1311                                 err(rules->udev, "invalid DRIVER operation\n");
1312                                 goto invalid;
1313                         }
1314                         add_rule_key(rule, &rule->driver, operation, value);
1315                         valid = 1;
1316                         continue;
1317                 }
1318
1319                 if (strncasecmp(key, "ATTR{", sizeof("ATTR{")-1) == 0) {
1320                         attr = get_key_attribute(rules, key + sizeof("ATTR")-1);
1321                         if (attr == NULL) {
1322                                 err(rules->udev, "error parsing ATTR attribute\n");
1323                                 goto invalid;
1324                         }
1325                         if (add_rule_key_pair(rules, rule, &rule->attr, operation, attr, value) != 0)
1326                                 goto invalid;
1327                         valid = 1;
1328                         continue;
1329                 }
1330
1331                 if (strcasecmp(key, "KERNELS") == 0 ||
1332                     strcasecmp(key, "ID") == 0) {
1333                         if (operation != KEY_OP_MATCH &&
1334                             operation != KEY_OP_NOMATCH) {
1335                                 err(rules->udev, "invalid KERNELS operation\n");
1336                                 goto invalid;
1337                         }
1338                         add_rule_key(rule, &rule->kernels, operation, value);
1339                         valid = 1;
1340                         continue;
1341                 }
1342
1343                 if (strcasecmp(key, "SUBSYSTEMS") == 0 ||
1344                     strcasecmp(key, "BUS") == 0) {
1345                         if (operation != KEY_OP_MATCH &&
1346                             operation != KEY_OP_NOMATCH) {
1347                                 err(rules->udev, "invalid SUBSYSTEMS operation\n");
1348                                 goto invalid;
1349                         }
1350                         add_rule_key(rule, &rule->subsystems, operation, value);
1351                         valid = 1;
1352                         continue;
1353                 }
1354
1355                 if (strcasecmp(key, "DRIVERS") == 0) {
1356                         if (operation != KEY_OP_MATCH &&
1357                             operation != KEY_OP_NOMATCH) {
1358                                 err(rules->udev, "invalid DRIVERS operation\n");
1359                                 goto invalid;
1360                         }
1361                         add_rule_key(rule, &rule->drivers, operation, value);
1362                         valid = 1;
1363                         continue;
1364                 }
1365
1366                 if (strncasecmp(key, "ATTRS{", sizeof("ATTRS{")-1) == 0 ||
1367                     strncasecmp(key, "SYSFS{", sizeof("SYSFS{")-1) == 0) {
1368                         if (operation != KEY_OP_MATCH &&
1369                             operation != KEY_OP_NOMATCH) {
1370                                 err(rules->udev, "invalid ATTRS operation\n");
1371                                 goto invalid;
1372                         }
1373                         attr = get_key_attribute(rules, key + sizeof("ATTRS")-1);
1374                         if (attr == NULL) {
1375                                 err(rules->udev, "error parsing ATTRS attribute\n");
1376                                 goto invalid;
1377                         }
1378                         if (strncmp(attr, "device/", 7) == 0)
1379                                 err(rules->udev, "the 'device' link may not be available in a future kernel, "
1380                                     "please fix it in %s:%u", filename, lineno);
1381                         else if (strstr(attr, "../") != NULL)
1382                                 err(rules->udev, "do not reference parent sysfs directories directly, "
1383                                     "it may break with a future kernel, please fix it in %s:%u", filename, lineno);
1384                         if (add_rule_key_pair(rules, rule, &rule->attrs, operation, attr, value) != 0)
1385                                 goto invalid;
1386                         valid = 1;
1387                         continue;
1388                 }
1389
1390                 if (strncasecmp(key, "ENV{", sizeof("ENV{")-1) == 0) {
1391                         attr = get_key_attribute(rules, key + sizeof("ENV")-1);
1392                         if (attr == NULL) {
1393                                 err(rules->udev, "error parsing ENV attribute\n");
1394                                 goto invalid;
1395                         }
1396                         if (strncmp(attr, "PHYSDEV", 7) == 0)
1397                                 physdev = 1;
1398                         if (add_rule_key_pair(rules, rule, &rule->env, operation, attr, value) != 0)
1399                                 goto invalid;
1400                         valid = 1;
1401                         continue;
1402                 }
1403
1404                 if (strcasecmp(key, "PROGRAM") == 0) {
1405                         add_rule_key(rule, &rule->program, operation, value);
1406                         valid = 1;
1407                         continue;
1408                 }
1409
1410                 if (strcasecmp(key, "RESULT") == 0) {
1411                         if (operation != KEY_OP_MATCH &&
1412                             operation != KEY_OP_NOMATCH) {
1413                                 err(rules->udev, "invalid RESULT operation\n");
1414                                 goto invalid;
1415                         }
1416                         add_rule_key(rule, &rule->result, operation, value);
1417                         valid = 1;
1418                         continue;
1419                 }
1420
1421                 if (strncasecmp(key, "IMPORT", sizeof("IMPORT")-1) == 0) {
1422                         attr = get_key_attribute(rules, key + sizeof("IMPORT")-1);
1423                         if (attr != NULL && strstr(attr, "program")) {
1424                                 dbg(rules->udev, "IMPORT will be executed\n");
1425                                 rule->import_type  = IMPORT_PROGRAM;
1426                         } else if (attr != NULL && strstr(attr, "file")) {
1427                                 dbg(rules->udev, "IMPORT will be included as file\n");
1428                                 rule->import_type  = IMPORT_FILE;
1429                         } else if (attr != NULL && strstr(attr, "parent")) {
1430                                 dbg(rules->udev, "IMPORT will include the parent values\n");
1431                                 rule->import_type = IMPORT_PARENT;
1432                         } else {
1433                                 /* figure it out if it is executable */
1434                                 char file[UTIL_PATH_SIZE];
1435                                 char *pos;
1436                                 struct stat statbuf;
1437
1438                                 util_strlcpy(file, value, sizeof(file));
1439                                 pos = strchr(file, ' ');
1440                                 if (pos)
1441                                         pos[0] = '\0';
1442
1443                                 /* allow programs in /lib/udev called without the path */
1444                                 if (strchr(file, '/') == NULL) {
1445                                         util_strlcpy(file, UDEV_PREFIX "/lib/udev/", sizeof(file));
1446                                         util_strlcat(file, value, sizeof(file));
1447                                         pos = strchr(file, ' ');
1448                                         if (pos)
1449                                                 pos[0] = '\0';
1450                                 }
1451
1452                                 dbg(rules->udev, "IMPORT auto mode for '%s'\n", file);
1453                                 if (!lstat(file, &statbuf) && (statbuf.st_mode & S_IXUSR)) {
1454                                         dbg(rules->udev, "IMPORT is executable, will be executed (autotype)\n");
1455                                         rule->import_type  = IMPORT_PROGRAM;
1456                                 } else {
1457                                         dbg(rules->udev, "IMPORT is not executable, will be included as file (autotype)\n");
1458                                         rule->import_type  = IMPORT_FILE;
1459                                 }
1460                         }
1461                         add_rule_key(rule, &rule->import, operation, value);
1462                         valid = 1;
1463                         continue;
1464                 }
1465
1466                 if (strncasecmp(key, "TEST", sizeof("TEST")-1) == 0) {
1467                         if (operation != KEY_OP_MATCH &&
1468                             operation != KEY_OP_NOMATCH) {
1469                                 err(rules->udev, "invalid TEST operation\n");
1470                                 goto invalid;
1471                         }
1472                         attr = get_key_attribute(rules, key + sizeof("TEST")-1);
1473                         if (attr != NULL)
1474                                 rule->test_mode_mask = strtol(attr, NULL, 8);
1475                         add_rule_key(rule, &rule->test, operation, value);
1476                         valid = 1;
1477                         continue;
1478                 }
1479
1480                 if (strncasecmp(key, "RUN", sizeof("RUN")-1) == 0) {
1481                         attr = get_key_attribute(rules, key + sizeof("RUN")-1);
1482                         if (attr != NULL) {
1483                                 if (strstr(attr, "ignore_error"))
1484                                         rule->run_ignore_error = 1;
1485                         }
1486                         add_rule_key(rule, &rule->run, operation, value);
1487                         valid = 1;
1488                         continue;
1489                 }
1490
1491                 if (strcasecmp(key, "WAIT_FOR") == 0 || strcasecmp(key, "WAIT_FOR_SYSFS") == 0) {
1492                         add_rule_key(rule, &rule->wait_for, operation, value);
1493                         valid = 1;
1494                         continue;
1495                 }
1496
1497                 if (strcasecmp(key, "LABEL") == 0) {
1498                         add_rule_key(rule, &rule->label, operation, value);
1499                         valid = 1;
1500                         continue;
1501                 }
1502
1503                 if (strcasecmp(key, "GOTO") == 0) {
1504                         add_rule_key(rule, &rule->goto_label, operation, value);
1505                         valid = 1;
1506                         continue;
1507                 }
1508
1509                 if (strncasecmp(key, "NAME", sizeof("NAME")-1) == 0) {
1510                         attr = get_key_attribute(rules, key + sizeof("NAME")-1);
1511                         if (attr != NULL) {
1512                                 if (strstr(attr, "all_partitions") != NULL) {
1513                                         dbg(rules->udev, "creation of partition nodes requested\n");
1514                                         rule->partitions = DEFAULT_FAKE_PARTITIONS_COUNT;
1515                                 }
1516                                 if (strstr(attr, "ignore_remove") != NULL) {
1517                                         dbg(rules->udev, "remove event should be ignored\n");
1518                                         rule->ignore_remove = 1;
1519                                 }
1520                         }
1521                         if (value[0] == '\0')
1522                                 dbg(rules->udev, "name empty, node creation supressed\n");
1523                         add_rule_key(rule, &rule->name, operation, value);
1524                         continue;
1525                 }
1526
1527                 if (strcasecmp(key, "SYMLINK") == 0) {
1528                         if (operation == KEY_OP_MATCH ||
1529                             operation == KEY_OP_NOMATCH)
1530                                 add_rule_key(rule, &rule->symlink_match, operation, value);
1531                         else
1532                                 add_rule_key(rule, &rule->symlink, operation, value);
1533                         valid = 1;
1534                         continue;
1535                 }
1536
1537                 if (strcasecmp(key, "OWNER") == 0) {
1538                         valid = 1;
1539                         if (rules->resolve_names && (!strchr(value, '$') && !strchr(value, '%'))) {
1540                                 char *endptr;
1541                                 strtoul(value, &endptr, 10);
1542                                 if (endptr[0] != '\0') {
1543                                         char owner[32];
1544                                         uid_t uid = util_lookup_user(rules->udev, value);
1545                                         dbg(rules->udev, "replacing username='%s' by id=%i\n", value, uid);
1546                                         sprintf(owner, "%u", (unsigned int) uid);
1547                                         add_rule_key(rule, &rule->owner, operation, owner);
1548                                         continue;
1549                                 }
1550                         }
1551
1552                         add_rule_key(rule, &rule->owner, operation, value);
1553                         continue;
1554                 }
1555
1556                 if (strcasecmp(key, "GROUP") == 0) {
1557                         valid = 1;
1558                         if (rules->resolve_names && (!strchr(value, '$') && !strchr(value, '%'))) {
1559                                 char *endptr;
1560                                 strtoul(value, &endptr, 10);
1561                                 if (endptr[0] != '\0') {
1562                                         char group[32];
1563                                         gid_t gid = util_lookup_group(rules->udev, value);
1564                                         dbg(rules->udev, "replacing groupname='%s' by id=%i\n", value, gid);
1565                                         sprintf(group, "%u", (unsigned int) gid);
1566                                         add_rule_key(rule, &rule->group, operation, group);
1567                                         continue;
1568                                 }
1569                         }
1570
1571                         add_rule_key(rule, &rule->group, operation, value);
1572                         continue;
1573                 }
1574
1575                 if (strcasecmp(key, "MODE") == 0) {
1576                         add_rule_key(rule, &rule->mode, operation, value);
1577                         valid = 1;
1578                         continue;
1579                 }
1580
1581                 if (strcasecmp(key, "OPTIONS") == 0) {
1582                         const char *pos;
1583
1584                         if (strstr(value, "last_rule") != NULL) {
1585                                 dbg(rules->udev, "last rule to be applied\n");
1586                                 rule->last_rule = 1;
1587                         }
1588                         if (strstr(value, "ignore_device") != NULL) {
1589                                 dbg(rules->udev, "device should be ignored\n");
1590                                 rule->ignore_device = 1;
1591                         }
1592                         if (strstr(value, "ignore_remove") != NULL) {
1593                                 dbg(rules->udev, "remove event should be ignored\n");
1594                                 rule->ignore_remove = 1;
1595                         }
1596                         pos = strstr(value, "link_priority=");
1597                         if (pos != NULL) {
1598                                 rule->link_priority = atoi(&pos[strlen("link_priority=")]);
1599                                 dbg(rules->udev, "link priority=%i\n", rule->link_priority);
1600                         }
1601                         pos = strstr(value, "event_timeout=");
1602                         if (pos != NULL) {
1603                                 rule->event_timeout = atoi(&pos[strlen("event_timeout=")]);
1604                                 dbg(rules->udev, "event timout=%i\n", rule->event_timeout);
1605                         }
1606                         pos = strstr(value, "string_escape=");
1607                         if (pos != NULL) {
1608                                 pos = &pos[strlen("string_escape=")];
1609                                 if (strncmp(pos, "none", strlen("none")) == 0)
1610                                         rule->string_escape = ESCAPE_NONE;
1611                                 else if (strncmp(pos, "replace", strlen("replace")) == 0)
1612                                         rule->string_escape = ESCAPE_REPLACE;
1613                         }
1614                         if (strstr(value, "all_partitions") != NULL) {
1615                                 dbg(rules->udev, "creation of partition nodes requested\n");
1616                                 rule->partitions = DEFAULT_FAKE_PARTITIONS_COUNT;
1617                         }
1618                         valid = 1;
1619                         continue;
1620                 }
1621
1622                 err(rules->udev, "unknown key '%s' in %s:%u\n", key, filename, lineno);
1623         }
1624
1625         if (physdev && rule->wait_for.operation == KEY_OP_UNSET)
1626                 err(rules->udev, "PHYSDEV* values are deprecated and will be removed from a future kernel, \n"
1627                     "please fix it in %s:%u", filename, lineno);
1628
1629         /* skip line if not any valid key was found */
1630         if (!valid)
1631                 goto invalid;
1632
1633         /* grow buffer and add rule */
1634         rule_size = sizeof(struct udev_rule) + rule->bufsize;
1635         padding = (sizeof(size_t) - rule_size % sizeof(size_t)) % sizeof(size_t);
1636         dbg(rules->udev, "add %zi padding bytes\n", padding);
1637         rule_size += padding;
1638         rule->bufsize += padding;
1639
1640         rules->buf = realloc(rules->buf, rules->bufsize + rule_size);
1641         if (!rules->buf) {
1642                 err(rules->udev, "realloc failed\n");
1643                 goto exit;
1644         }
1645         dbg(rules->udev, "adding rule to offset %zi\n", rules->bufsize);
1646         memcpy(rules->buf + rules->bufsize, rule, rule_size);
1647         rules->bufsize += rule_size;
1648 exit:
1649         return 0;
1650
1651 invalid:
1652         err(rules->udev, "invalid rule '%s:%u'\n", filename, lineno);
1653         return -1;
1654 }
1655
1656 static int parse_file(struct udev_rules *rules, const char *filename)
1657 {
1658         FILE *f;
1659         char line[UTIL_LINE_SIZE];
1660         size_t start;
1661         struct udev_rule *rule;
1662         struct udev_rules_iter iter;
1663
1664         start = rules->bufsize;
1665         info(rules->udev, "reading '%s' as rules file\n", filename);
1666
1667         f = fopen(filename, "r");
1668         if (f == NULL)
1669                 return -1;
1670
1671         while(fgets(line, sizeof(line), f) != NULL) {
1672                 int line_nr = 0;
1673                 char *key;
1674                 size_t len;
1675
1676                 /* skip whitespace */
1677                 line_nr++;
1678                 key = line;
1679                 while (isspace(key[0]))
1680                         key++;
1681
1682                 /* comment */
1683                 if (key[0] == '#')
1684                         continue;
1685
1686                 len = strlen(line);
1687                 if (len < 3)
1688                         continue;
1689
1690                 /* continue reading if backslash+newline is found */
1691                 while (line[len-2] == '\\') {
1692                         if (fgets(&line[len-2], (sizeof(line)-len)+2, f) == NULL)
1693                                 break;
1694                         line_nr++;
1695                         len = strlen(line);
1696                 }
1697
1698                 if (len+1 >= sizeof(line)) {
1699                         err(rules->udev, "line too long '%s':%u, ignored\n", filename, line_nr);
1700                         continue;
1701                 }
1702                 add_to_rules(rules, key, filename, line_nr);
1703         }
1704         fclose(f);
1705
1706         /* compute all goto targets within this file */
1707         udev_rules_iter_init(&iter, rules);
1708         udev_rules_iter_goto(&iter, start);
1709         while((rule = udev_rules_iter_next(&iter))) {
1710                 if (rule->goto_label.operation != KEY_OP_UNSET) {
1711                         char *goto_label = &rule->buf[rule->goto_label.val_off];
1712
1713                         dbg(rules->udev, "resolving goto label '%s'\n", goto_label);
1714                         rule->goto_rule_off = find_label(&iter, goto_label);
1715                         if (rule->goto_rule_off == 0) {
1716                                 err(rules->udev, "ignore goto to nonexistent label '%s' in '%s'\n",
1717                                     goto_label, filename);
1718                                 rule->goto_rule_off = iter.current;
1719                         }
1720                 }
1721         }
1722         return 0;
1723 }
1724
1725 static int add_matching_files(struct udev *udev, struct udev_list_node *file_list, const char *dirname, const char *suffix)
1726 {
1727         struct dirent *ent;
1728         DIR *dir;
1729         char filename[UTIL_PATH_SIZE];
1730
1731         dbg(udev, "open directory '%s'\n", dirname);
1732         dir = opendir(dirname);
1733         if (dir == NULL) {
1734                 err(udev, "unable to open '%s': %m\n", dirname);
1735                 return -1;
1736         }
1737
1738         while (1) {
1739                 ent = readdir(dir);
1740                 if (ent == NULL || ent->d_name[0] == '\0')
1741                         break;
1742
1743                 if ((ent->d_name[0] == '.') || (ent->d_name[0] == '#'))
1744                         continue;
1745
1746                 /* look for file matching with specified suffix */
1747                 if (suffix != NULL) {
1748                         const char *ext;
1749
1750                         ext = strrchr(ent->d_name, '.');
1751                         if (ext == NULL)
1752                                 continue;
1753                         if (strcmp(ext, suffix) != 0)
1754                                 continue;
1755                 }
1756                 dbg(udev, "put file '%s/%s' into list\n", dirname, ent->d_name);
1757
1758                 snprintf(filename, sizeof(filename), "%s/%s", dirname, ent->d_name);
1759                 filename[sizeof(filename)-1] = '\0';
1760                 udev_list_entry_add(udev, file_list, filename, NULL, 1, 1);
1761         }
1762
1763         closedir(dir);
1764         return 0;
1765 }
1766
1767 struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names)
1768 {
1769         struct udev_rules *rules;
1770         struct stat statbuf;
1771         char filename[PATH_MAX];
1772         struct udev_list_node file_list;
1773         struct udev_list_entry *file_loop, *file_tmp;
1774
1775         rules = malloc(sizeof(struct udev_rules));
1776         if (rules == NULL)
1777                 return rules;
1778         memset(rules, 0x00, sizeof(struct udev_rules));
1779         rules->udev = udev;
1780         rules->resolve_names = resolve_names;
1781         udev_list_init(&file_list);
1782
1783         if (udev_get_rules_path(udev) != NULL) {
1784                 /* custom rules location for testing */
1785                 add_matching_files(udev, &file_list, udev_get_rules_path(udev), ".rules");
1786         } else {
1787                 struct udev_list_node sort_list;
1788                 struct udev_list_entry *sort_loop, *sort_tmp;
1789
1790                 /* read user/custom rules */
1791                 add_matching_files(udev, &file_list, SYSCONFDIR "/udev/rules.d", ".rules");
1792
1793                 /* read dynamic/temporary rules */
1794                 util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename));
1795                 util_strlcat(filename, "/.udev/rules.d", sizeof(filename));
1796                 if (stat(filename, &statbuf) != 0) {
1797                         util_create_path(udev, filename);
1798                         udev_selinux_setfscreatecon(udev, filename, S_IFDIR|0755);
1799                         mkdir(filename, 0755);
1800                         udev_selinux_resetfscreatecon(udev);
1801                 }
1802                 udev_list_init(&sort_list);
1803                 add_matching_files(udev, &sort_list, filename, ".rules");
1804
1805                 /* read default rules */
1806                 add_matching_files(udev, &sort_list, UDEV_PREFIX "/lib/udev/rules.d", ".rules");
1807
1808                 /* sort all rules files by basename into list of files */
1809                 udev_list_entry_foreach_safe(sort_loop, sort_tmp, udev_list_get_entry(&sort_list)) {
1810                         const char *sort_name = udev_list_entry_get_name(sort_loop);
1811                         const char *sort_base = strrchr(sort_name, '/');
1812
1813                         if (sort_base == NULL)
1814                                 continue;
1815
1816                         udev_list_entry_foreach_safe(file_loop, file_tmp, udev_list_get_entry(&file_list)) {
1817                                 const char *file_name = udev_list_entry_get_name(file_loop);
1818                                 const char *file_base = strrchr(file_name, '/');
1819
1820                                 if (file_base == NULL)
1821                                         continue;
1822                                 if (strcmp(file_base, sort_base) == 0) {
1823                                         info(udev, "rule file basename '%s' already added, ignoring '%s'\n",
1824                                              file_name, sort_name);
1825                                         udev_list_entry_remove(sort_loop);
1826                                         sort_loop = NULL;
1827                                         break;
1828                                 }
1829                                 if (strcmp(file_base, sort_base) > 0)
1830                                         break;
1831                         }
1832                         if (sort_loop != NULL)
1833                                 udev_list_entry_move_before(sort_loop, file_loop);
1834                 }
1835         }
1836
1837         /* parse list of files */
1838         udev_list_entry_foreach_safe(file_loop, file_tmp, udev_list_get_entry(&file_list)) {
1839                 const char *file_name = udev_list_entry_get_name(file_loop);
1840
1841                 if (stat(file_name, &statbuf) == 0 && statbuf.st_size > 0)
1842                         parse_file(rules, file_name);
1843                 else
1844                         info(udev, "can not read '%s'\n", file_name);
1845                 udev_list_entry_remove(file_loop);
1846         }
1847         return rules;
1848 }
1849
1850 void udev_rules_unref(struct udev_rules *rules)
1851 {
1852         if (rules == NULL)
1853                 return;
1854         if (rules->buf) {
1855                 free(rules->buf);
1856                 rules->buf = NULL;
1857         }
1858         free(rules);
1859 }