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