chiark / gitweb /
udevd: use libudev
[elogind.git] / udev / udev_rules.c
1 /*
2  * Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
3  * Copyright (C) 2003-2008 Kay Sievers <kay.sievers@vrfy.org>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <stddef.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <fcntl.h>
24 #include <ctype.h>
25 #include <unistd.h>
26 #include <errno.h>
27 #include <syslog.h>
28 #include <dirent.h>
29 #include <fnmatch.h>
30 #include <sys/socket.h>
31 #include <sys/un.h>
32 #include <sys/wait.h>
33 #include <sys/stat.h>
34
35 #include "udev.h"
36 #include "udev_rules.h"
37
38 extern char **environ;
39
40 /* extract possible {attr} and move str behind it */
41 static char *get_format_attribute(struct udev *udev, char **str)
42 {
43         char *pos;
44         char *attr = NULL;
45
46         if (*str[0] == '{') {
47                 pos = strchr(*str, '}');
48                 if (pos == NULL) {
49                         err(udev, "missing closing brace for format\n");
50                         return NULL;
51                 }
52                 pos[0] = '\0';
53                 attr = *str+1;
54                 *str = pos+1;
55                 dbg(udev, "attribute='%s', str='%s'\n", attr, *str);
56         }
57         return attr;
58 }
59
60 /* extract possible format length and move str behind it*/
61 static int get_format_len(struct udev *udev, char **str)
62 {
63         int num;
64         char *tail;
65
66         if (isdigit(*str[0])) {
67                 num = (int) strtoul(*str, &tail, 10);
68                 if (num > 0) {
69                         *str = tail;
70                         dbg(udev, "format length=%i\n", num);
71                         return num;
72                 } else {
73                         err(udev, "format parsing error '%s'\n", *str);
74                 }
75         }
76         return -1;
77 }
78
79 static int get_key(char **line, char **key, char **value)
80 {
81         char *linepos;
82         char *temp;
83
84         linepos = *line;
85         if (linepos == NULL)
86                 return -1;
87
88         /* skip whitespace */
89         while (isspace(linepos[0]))
90                 linepos++;
91
92         /* get the key */
93         temp = strchr(linepos, '=');
94         if (temp == NULL || temp == linepos)
95                 return -1;
96         temp[0] = '\0';
97         *key = linepos;
98         linepos = &temp[1];
99
100         /* get a quoted value */
101         if (linepos[0] == '"' || linepos[0] == '\'') {
102                 temp = strchr(&linepos[1], linepos[0]);
103                 if (temp != NULL) {
104                         temp[0] = '\0';
105                         *value = &linepos[1];
106                         goto out;
107                 }
108         }
109
110         /* get the value*/
111         temp = strchr(linepos, '\n');
112         if (temp != NULL)
113                 temp[0] = '\0';
114         *value = linepos;
115 out:
116         return 0;
117 }
118
119 static int run_program(struct udev_device *dev, const char *command,
120                        char *result, size_t ressize, size_t *reslen)
121 {
122         struct udev *udev = udev_device_get_udev(dev);
123         int status;
124         char **envp;
125         int outpipe[2] = {-1, -1};
126         int errpipe[2] = {-1, -1};
127         pid_t pid;
128         char arg[UTIL_PATH_SIZE];
129         char program[UTIL_PATH_SIZE];
130         char *argv[(sizeof(arg) / 2) + 1];
131         int devnull;
132         int i;
133         int err = 0;
134
135         /* build argv from command */
136         util_strlcpy(arg, command, sizeof(arg));
137         i = 0;
138         if (strchr(arg, ' ') != NULL) {
139                 char *pos = arg;
140
141                 while (pos != NULL) {
142                         if (pos[0] == '\'') {
143                                 /* don't separate if in apostrophes */
144                                 pos++;
145                                 argv[i] = strsep(&pos, "\'");
146                                 while (pos != NULL && pos[0] == ' ')
147                                         pos++;
148                         } else {
149                                 argv[i] = strsep(&pos, " ");
150                         }
151                         dbg(udev, "arg[%i] '%s'\n", i, argv[i]);
152                         i++;
153                 }
154                 argv[i] = NULL;
155         } else {
156                 argv[0] = arg;
157                 argv[1] = NULL;
158         }
159         info(udev, "'%s'\n", command);
160
161         /* prepare pipes from child to parent */
162         if (result != NULL || udev_get_log_priority(udev) >= LOG_INFO) {
163                 if (pipe(outpipe) != 0) {
164                         err(udev, "pipe failed: %m\n");
165                         return -1;
166                 }
167         }
168         if (udev_get_log_priority(udev) >= LOG_INFO) {
169                 if (pipe(errpipe) != 0) {
170                         err(udev, "pipe failed: %m\n");
171                         return -1;
172                 }
173         }
174
175         /* allow programs in /lib/udev/ to be called without the path */
176         if (strchr(argv[0], '/') == NULL) {
177                 util_strlcpy(program, UDEV_PREFIX "/lib/udev/", sizeof(program));
178                 util_strlcat(program, argv[0], sizeof(program));
179                 argv[0] = program;
180         }
181
182         envp = udev_device_get_properties_envp(dev);
183
184         pid = fork();
185         switch(pid) {
186         case 0:
187                 /* child closes parent ends of pipes */
188                 if (outpipe[READ_END] > 0)
189                         close(outpipe[READ_END]);
190                 if (errpipe[READ_END] > 0)
191                         close(errpipe[READ_END]);
192
193                 /* discard child output or connect to pipe */
194                 devnull = open("/dev/null", O_RDWR);
195                 if (devnull > 0) {
196                         dup2(devnull, STDIN_FILENO);
197                         if (outpipe[WRITE_END] < 0)
198                                 dup2(devnull, STDOUT_FILENO);
199                         if (errpipe[WRITE_END] < 0)
200                                 dup2(devnull, STDERR_FILENO);
201                         close(devnull);
202                 } else
203                         err(udev, "open /dev/null failed: %m\n");
204                 if (outpipe[WRITE_END] > 0) {
205                         dup2(outpipe[WRITE_END], STDOUT_FILENO);
206                         close(outpipe[WRITE_END]);
207                 }
208                 if (errpipe[WRITE_END] > 0) {
209                         dup2(errpipe[WRITE_END], STDERR_FILENO);
210                         close(errpipe[WRITE_END]);
211                 }
212                 execve(argv[0], argv, envp);
213                 if (errno == ENOENT || errno == ENOTDIR) {
214                         /* may be on a filesytem which is not mounted right now */
215                         info(udev, "program '%s' not found\n", argv[0]);
216                 } else {
217                         /* other problems */
218                         err(udev, "exec of program '%s' failed\n", argv[0]);
219                 }
220                 _exit(1);
221         case -1:
222                 err(udev, "fork of '%s' failed: %m\n", argv[0]);
223                 return -1;
224         default:
225                 /* read from child if requested */
226                 if (outpipe[READ_END] > 0 || errpipe[READ_END] > 0) {
227                         ssize_t count;
228                         size_t respos = 0;
229
230                         /* parent closes child ends of pipes */
231                         if (outpipe[WRITE_END] > 0)
232                                 close(outpipe[WRITE_END]);
233                         if (errpipe[WRITE_END] > 0)
234                                 close(errpipe[WRITE_END]);
235
236                         /* read child output */
237                         while (outpipe[READ_END] > 0 || errpipe[READ_END] > 0) {
238                                 int fdcount;
239                                 fd_set readfds;
240
241                                 FD_ZERO(&readfds);
242                                 if (outpipe[READ_END] > 0)
243                                         FD_SET(outpipe[READ_END], &readfds);
244                                 if (errpipe[READ_END] > 0)
245                                         FD_SET(errpipe[READ_END], &readfds);
246                                 fdcount = select(UDEV_MAX(outpipe[READ_END], errpipe[READ_END])+1, &readfds, NULL, NULL, NULL);
247                                 if (fdcount < 0) {
248                                         if (errno == EINTR)
249                                                 continue;
250                                         err = -1;
251                                         break;
252                                 }
253
254                                 /* get stdout */
255                                 if (outpipe[READ_END] > 0 && FD_ISSET(outpipe[READ_END], &readfds)) {
256                                         char inbuf[1024];
257                                         char *pos;
258                                         char *line;
259
260                                         count = read(outpipe[READ_END], inbuf, sizeof(inbuf)-1);
261                                         if (count <= 0) {
262                                                 close(outpipe[READ_END]);
263                                                 outpipe[READ_END] = -1;
264                                                 if (count < 0) {
265                                                         err(udev, "stdin read failed: %m\n");
266                                                         err = -1;
267                                                 }
268                                                 continue;
269                                         }
270                                         inbuf[count] = '\0';
271
272                                         /* store result for rule processing */
273                                         if (result) {
274                                                 if (respos + count < ressize) {
275                                                         memcpy(&result[respos], inbuf, count);
276                                                         respos += count;
277                                                 } else {
278                                                         err(udev, "ressize %ld too short\n", (long)ressize);
279                                                         err = -1;
280                                                 }
281                                         }
282                                         pos = inbuf;
283                                         while ((line = strsep(&pos, "\n")))
284                                                 if (pos || line[0] != '\0')
285                                                         info(udev, "'%s' (stdout) '%s'\n", argv[0], line);
286                                 }
287
288                                 /* get stderr */
289                                 if (errpipe[READ_END] > 0 && FD_ISSET(errpipe[READ_END], &readfds)) {
290                                         char errbuf[1024];
291                                         char *pos;
292                                         char *line;
293
294                                         count = read(errpipe[READ_END], errbuf, sizeof(errbuf)-1);
295                                         if (count <= 0) {
296                                                 close(errpipe[READ_END]);
297                                                 errpipe[READ_END] = -1;
298                                                 if (count < 0)
299                                                         err(udev, "stderr read failed: %m\n");
300                                                 continue;
301                                         }
302                                         errbuf[count] = '\0';
303                                         pos = errbuf;
304                                         while ((line = strsep(&pos, "\n")))
305                                                 if (pos || line[0] != '\0')
306                                                         info(udev, "'%s' (stderr) '%s'\n", argv[0], line);
307                                 }
308                         }
309                         if (outpipe[READ_END] > 0)
310                                 close(outpipe[READ_END]);
311                         if (errpipe[READ_END] > 0)
312                                 close(errpipe[READ_END]);
313
314                         /* return the childs stdout string */
315                         if (result) {
316                                 result[respos] = '\0';
317                                 dbg(udev, "result='%s'\n", result);
318                                 if (reslen)
319                                         *reslen = respos;
320                         }
321                 }
322                 waitpid(pid, &status, 0);
323                 if (WIFEXITED(status)) {
324                         info(udev, "'%s' returned with status %i\n", argv[0], WEXITSTATUS(status));
325                         if (WEXITSTATUS(status) != 0)
326                                 err = -1;
327                 } else {
328                         err(udev, "'%s' abnormal exit\n", argv[0]);
329                         err = -1;
330                 }
331         }
332
333         return err;
334 }
335
336 static int import_keys_into_env(struct udev_event *event, const char *buf, size_t bufsize)
337 {
338         struct udev_device *dev = event->dev;
339         char line[UTIL_LINE_SIZE];
340         const char *bufline;
341         char *linepos;
342         char *variable;
343         char *value;
344         size_t cur;
345         size_t count;
346         int lineno;
347
348         /* loop through the whole buffer */
349         lineno = 0;
350         cur = 0;
351         while (cur < bufsize) {
352                 count = buf_get_line(buf, bufsize, cur);
353                 bufline = &buf[cur];
354                 cur += count+1;
355                 lineno++;
356
357                 /* eat the whitespace */
358                 while ((count > 0) && isspace(bufline[0])) {
359                         bufline++;
360                         count--;
361                 }
362                 if (count == 0)
363                         continue;
364
365                 /* see if this is a comment */
366                 if (bufline[0] == '#')
367                         continue;
368
369                 if (count >= sizeof(line)) {
370                         err(event->udev, "line too long, skipped\n");
371                         continue;
372                 }
373
374                 memcpy(line, bufline, count);
375                 line[count] = '\0';
376
377                 linepos = line;
378                 if (get_key(&linepos, &variable, &value) == 0) {
379                         char syspath[UTIL_PATH_SIZE];
380
381                         dbg(event->udev, "import '%s=%s'\n", variable, value);
382                         /* handle device, renamed by external tool, returning new path */
383                         if (strcmp(variable, "DEVPATH") == 0) {
384                                 info(event->udev, "updating devpath from '%s' to '%s'\n",
385                                      udev_device_get_devpath(dev), value);
386                                 util_strlcpy(syspath, udev_get_sys_path(event->udev), sizeof(syspath));
387                                 util_strlcat(syspath, value, sizeof(syspath));
388                                 udev_device_set_syspath(dev, syspath);
389                         } else {
390                                 struct udev_list_entry *entry;
391
392                                 entry = udev_device_add_property(dev, variable, value);
393                                 /* store in db */
394                                 udev_list_entry_set_flag(entry, 1);
395                         }
396                 }
397         }
398         return 0;
399 }
400
401 static int import_file_into_env(struct udev_event *event, const char *filename)
402 {
403         char *buf;
404         size_t bufsize;
405
406         if (file_map(filename, &buf, &bufsize) != 0) {
407                 err(event->udev, "can't open '%s': %m\n", filename);
408                 return -1;
409         }
410         import_keys_into_env(event, buf, bufsize);
411         file_unmap(buf, bufsize);
412
413         return 0;
414 }
415
416 static int import_program_into_env(struct udev_event *event, const char *program)
417 {
418         char result[2048];
419         size_t reslen;
420
421         if (run_program(event->dev, program, result, sizeof(result), &reslen) != 0)
422                 return -1;
423         return import_keys_into_env(event, result, reslen);
424 }
425
426 static int import_parent_into_env(struct udev_event *event, const char *filter)
427 {
428         struct udev_device *dev_parent;
429         struct udev_list_entry *list_entry;
430
431         dev_parent = udev_device_get_parent(event->dev);
432         if (dev_parent == NULL)
433                 return -1;
434
435         dbg(event->udev, "found parent '%s', get the node name\n", udev_device_get_syspath(dev_parent));
436         udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(dev_parent)) {
437                 const char *key = udev_list_entry_get_name(list_entry);
438                 const char *val = udev_list_entry_get_value(list_entry);
439
440                 if (fnmatch(filter, key, 0) == 0) {
441                         struct udev_list_entry *entry;
442
443                         dbg(event->udev, "import key '%s=%s'\n", key, val);
444                         entry = udev_device_add_property(event->dev, key, val);
445                         /* store in db */
446                         udev_list_entry_set_flag(entry, 1);
447                 }
448         }
449         return 0;
450 }
451
452 int udev_rules_run(struct udev_event *event)
453 {
454         struct udev_list_entry *list_entry;
455         int err = 0;
456
457         dbg(event->udev, "executing run list\n");
458         udev_list_entry_foreach(list_entry, udev_list_get_entry(&event->run_list)) {
459                 const char *cmd = udev_list_entry_get_name(list_entry);
460
461                 if (strncmp(cmd, "socket:", strlen("socket:")) == 0) {
462                         struct udev_monitor *monitor;
463
464                         monitor = udev_monitor_new_from_socket(event->udev, &cmd[strlen("socket:")]);
465                         if (monitor == NULL)
466                                 continue;
467                         udev_monitor_send_device(monitor, event->dev);
468                         udev_monitor_unref(monitor);
469                 } else {
470                         char program[UTIL_PATH_SIZE];
471
472                         util_strlcpy(program, cmd, sizeof(program));
473                         udev_rules_apply_format(event, program, sizeof(program));
474                         if (run_program(event->dev, program, NULL, 0, NULL) != 0) {
475                                 if (!udev_list_entry_get_flag(list_entry))
476                                         err = -1;
477                         }
478                 }
479         }
480         return err;
481 }
482
483 #define WAIT_LOOP_PER_SECOND            50
484 static int wait_for_file(struct udev_event *event, const char *file, int timeout)
485 {
486         char filepath[UTIL_PATH_SIZE];
487         char devicepath[UTIL_PATH_SIZE] = "";
488         struct stat stats;
489         int loop = timeout * WAIT_LOOP_PER_SECOND;
490
491         /* a relative path is a device attribute */
492         if (file[0] != '/') {
493                 util_strlcpy(devicepath, udev_get_sys_path(event->udev), sizeof(devicepath));
494                 util_strlcat(devicepath, udev_device_get_devpath(event->dev), sizeof(devicepath));
495
496                 util_strlcpy(filepath, devicepath, sizeof(filepath));
497                 util_strlcat(filepath, "/", sizeof(filepath));
498                 util_strlcat(filepath, file, sizeof(filepath));
499                 file = filepath;
500         }
501
502         dbg(event->udev, "will wait %i sec for '%s'\n", timeout, file);
503         while (--loop) {
504                 /* lookup file */
505                 if (stat(file, &stats) == 0) {
506                         info(event->udev, "file '%s' appeared after %i loops\n", file, (timeout * WAIT_LOOP_PER_SECOND) - loop-1);
507                         return 0;
508                 }
509                 /* make sure, the device did not disappear in the meantime */
510                 if (devicepath[0] != '\0' && stat(devicepath, &stats) != 0) {
511                         info(event->udev, "device disappeared while waiting for '%s'\n", file);
512                         return -2;
513                 }
514                 info(event->udev, "wait for '%s' for %i mseconds\n", file, 1000 / WAIT_LOOP_PER_SECOND);
515                 usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
516         }
517         info(event->udev, "waiting for '%s' failed\n", file);
518         return -1;
519 }
520
521 /* handle "[$SUBSYSTEM/$KERNEL]<attribute>" lookup */
522 static int split_subsys_sysname(struct udev *udev, char *attrstr, char **subsys, char **sysname, char **attr)
523 {
524         char *pos;
525
526         if (attrstr[0] != '[')
527                 return -1;
528
529         *subsys = &attrstr[1];
530         pos = strchr(*subsys, ']');
531         if (pos == NULL)
532                 return -1;
533         pos[0] = '\0';
534         pos = &pos[1];
535
536         if (pos[0] == '/')
537                 pos = &pos[1];
538         if (pos[0] != '\0')
539                 *attr = pos;
540         else
541                 *attr = NULL;
542
543         pos = strchr(*subsys, '/');
544         if (pos == NULL)
545                 return -1;
546         pos[0] = '\0';
547         *sysname = &pos[1];
548         return 0;
549 }
550
551 static int attr_subst_subdir(char *attr, size_t len)
552 {
553         char *pos;
554         int found = 0;
555
556         pos = strstr(attr, "/*/");
557         if (pos != NULL) {
558                 char str[UTIL_PATH_SIZE];
559                 DIR *dir;
560
561                 pos[1] = '\0';
562                 util_strlcpy(str, &pos[2], sizeof(str));
563                 dir = opendir(attr);
564                 if (dir != NULL) {
565                         struct dirent *dent;
566
567                         for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
568                                 struct stat stats;
569
570                                 if (dent->d_name[0] == '.')
571                                         continue;
572                                 util_strlcat(attr, dent->d_name, len);
573                                 util_strlcat(attr, str, len);
574                                 if (stat(attr, &stats) == 0) {
575                                         found = 1;
576                                         break;
577                                 }
578                                 pos[1] = '\0';
579                         }
580                         closedir(dir);
581                 }
582                 if (!found)
583                         util_strlcat(attr, str, len);
584         }
585
586         return found;
587 }
588
589 void udev_rules_apply_format(struct udev_event *event, char *string, size_t maxsize)
590 {
591         struct udev_device *dev = event->dev;
592         char temp[UTIL_PATH_SIZE];
593         char temp2[UTIL_PATH_SIZE];
594         char *head, *tail, *cpos, *attr, *rest;
595         int len;
596         int i;
597         int count;
598         enum subst_type {
599                 SUBST_UNKNOWN,
600                 SUBST_DEVPATH,
601                 SUBST_KERNEL,
602                 SUBST_KERNEL_NUMBER,
603                 SUBST_ID,
604                 SUBST_DRIVER,
605                 SUBST_MAJOR,
606                 SUBST_MINOR,
607                 SUBST_RESULT,
608                 SUBST_ATTR,
609                 SUBST_PARENT,
610                 SUBST_TEMP_NODE,
611                 SUBST_NAME,
612                 SUBST_LINKS,
613                 SUBST_ROOT,
614                 SUBST_SYS,
615                 SUBST_ENV,
616         };
617         static const struct subst_map {
618                 char *name;
619                 char fmt;
620                 enum subst_type type;
621         } map[] = {
622                 { .name = "devpath",    .fmt = 'p',     .type = SUBST_DEVPATH },
623                 { .name = "number",     .fmt = 'n',     .type = SUBST_KERNEL_NUMBER },
624                 { .name = "kernel",     .fmt = 'k',     .type = SUBST_KERNEL },
625                 { .name = "id",         .fmt = 'b',     .type = SUBST_ID },
626                 { .name = "driver",     .fmt = 'd',     .type = SUBST_DRIVER },
627                 { .name = "major",      .fmt = 'M',     .type = SUBST_MAJOR },
628                 { .name = "minor",      .fmt = 'm',     .type = SUBST_MINOR },
629                 { .name = "result",     .fmt = 'c',     .type = SUBST_RESULT },
630                 { .name = "attr",       .fmt = 's',     .type = SUBST_ATTR },
631                 { .name = "sysfs",      .fmt = 's',     .type = SUBST_ATTR },
632                 { .name = "parent",     .fmt = 'P',     .type = SUBST_PARENT },
633                 { .name = "tempnode",   .fmt = 'N',     .type = SUBST_TEMP_NODE },
634                 { .name = "name",       .fmt = 'D',     .type = SUBST_NAME },
635                 { .name = "links",      .fmt = 'L',     .type = SUBST_LINKS },
636                 { .name = "root",       .fmt = 'r',     .type = SUBST_ROOT },
637                 { .name = "sys",        .fmt = 'S',     .type = SUBST_SYS },
638                 { .name = "env",        .fmt = 'E',     .type = SUBST_ENV },
639                 { NULL, '\0', 0 }
640         };
641         enum subst_type type;
642         const struct subst_map *subst;
643
644         head = string;
645         while (1) {
646                 len = -1;
647                 while (head[0] != '\0') {
648                         if (head[0] == '$') {
649                                 /* substitute named variable */
650                                 if (head[1] == '\0')
651                                         break;
652                                 if (head[1] == '$') {
653                                         util_strlcpy(temp, head+2, sizeof(temp));
654                                         util_strlcpy(head+1, temp, maxsize);
655                                         head++;
656                                         continue;
657                                 }
658                                 head[0] = '\0';
659                                 for (subst = map; subst->name; subst++) {
660                                         if (strncasecmp(&head[1], subst->name, strlen(subst->name)) == 0) {
661                                                 type = subst->type;
662                                                 tail = head + strlen(subst->name)+1;
663                                                 dbg(event->udev, "will substitute format name '%s'\n", subst->name);
664                                                 goto found;
665                                         }
666                                 }
667                                 head[0] = '$';
668                                 err(event->udev, "unknown format variable '%s'\n", head);
669                         } else if (head[0] == '%') {
670                                 /* substitute format char */
671                                 if (head[1] == '\0')
672                                         break;
673                                 if (head[1] == '%') {
674                                         util_strlcpy(temp, head+2, sizeof(temp));
675                                         util_strlcpy(head+1, temp, maxsize);
676                                         head++;
677                                         continue;
678                                 }
679                                 head[0] = '\0';
680                                 tail = head+1;
681                                 len = get_format_len(event->udev, &tail);
682                                 for (subst = map; subst->name; subst++) {
683                                         if (tail[0] == subst->fmt) {
684                                                 type = subst->type;
685                                                 tail++;
686                                                 dbg(event->udev, "will substitute format char '%c'\n", subst->fmt);
687                                                 goto found;
688                                         }
689                                 }
690                                 head[0] = '%';
691                                 err(event->udev, "unknown format char '%c'\n", tail[0]);
692                         }
693                         head++;
694                 }
695                 break;
696 found:
697                 attr = get_format_attribute(event->udev, &tail);
698                 util_strlcpy(temp, tail, sizeof(temp));
699                 dbg(event->udev, "format=%i, string='%s', tail='%s'\n", type ,string, tail);
700
701                 switch (type) {
702                 case SUBST_DEVPATH:
703                         util_strlcat(string, udev_device_get_devpath(dev), maxsize);
704                         dbg(event->udev, "substitute devpath '%s'\n", udev_device_get_devpath(dev));
705                         break;
706                 case SUBST_KERNEL:
707                         util_strlcat(string, udev_device_get_sysname(dev), maxsize);
708                         dbg(event->udev, "substitute kernel name '%s'\n", udev_device_get_sysname(dev));
709                         break;
710                 case SUBST_KERNEL_NUMBER:
711                         if (udev_device_get_sysnum(dev) == NULL)
712                                 break;
713                         util_strlcat(string, udev_device_get_sysnum(dev), maxsize);
714                         dbg(event->udev, "substitute kernel number '%s'\n", udev_device_get_sysnum(dev));
715                         break;
716                 case SUBST_ID:
717                         if (event->dev_parent != NULL) {
718                                 util_strlcat(string, udev_device_get_sysname(event->dev_parent), maxsize);
719                                 dbg(event->udev, "substitute id '%s'\n", udev_device_get_sysname(event->dev_parent));
720                         }
721                         break;
722                 case SUBST_DRIVER:
723                         if (event->dev_parent != NULL) {
724                                 const char *driver = udev_device_get_driver(event->dev_parent);
725
726                                 if (driver == NULL)
727                                         break;
728                                 util_strlcat(string, driver, maxsize);
729                                 dbg(event->udev, "substitute driver '%s'\n", driver);
730                         }
731                         break;
732                 case SUBST_MAJOR:
733                         sprintf(temp2, "%d", major(udev_device_get_devnum(dev)));
734                         util_strlcat(string, temp2, maxsize);
735                         dbg(event->udev, "substitute major number '%s'\n", temp2);
736                         break;
737                 case SUBST_MINOR:
738                         sprintf(temp2, "%d", minor(udev_device_get_devnum(dev)));
739                         util_strlcat(string, temp2, maxsize);
740                         dbg(event->udev, "substitute minor number '%s'\n", temp2);
741                         break;
742                 case SUBST_RESULT:
743                         if (event->program_result[0] == '\0')
744                                 break;
745                         /* get part part of the result string */
746                         i = 0;
747                         if (attr != NULL)
748                                 i = strtoul(attr, &rest, 10);
749                         if (i > 0) {
750                                 dbg(event->udev, "request part #%d of result string\n", i);
751                                 cpos = event->program_result;
752                                 while (--i) {
753                                         while (cpos[0] != '\0' && !isspace(cpos[0]))
754                                                 cpos++;
755                                         while (isspace(cpos[0]))
756                                                 cpos++;
757                                 }
758                                 if (i > 0) {
759                                         err(event->udev, "requested part of result string not found\n");
760                                         break;
761                                 }
762                                 util_strlcpy(temp2, cpos, sizeof(temp2));
763                                 /* %{2+}c copies the whole string from the second part on */
764                                 if (rest[0] != '+') {
765                                         cpos = strchr(temp2, ' ');
766                                         if (cpos)
767                                                 cpos[0] = '\0';
768                                 }
769                                 util_strlcat(string, temp2, maxsize);
770                                 dbg(event->udev, "substitute part of result string '%s'\n", temp2);
771                         } else {
772                                 util_strlcat(string, event->program_result, maxsize);
773                                 dbg(event->udev, "substitute result string '%s'\n", event->program_result);
774                         }
775                         break;
776                 case SUBST_ATTR:
777                         if (attr == NULL)
778                                 err(event->udev, "missing file parameter for attr\n");
779                         else {
780                                 char *subsys;
781                                 char *sysname;
782                                 char *attrib;
783                                 char value[UTIL_NAME_SIZE] = "";
784                                 size_t size;
785
786                                 if (split_subsys_sysname(event->udev, attr, &subsys, &sysname, &attrib) == 0) {
787                                         struct udev_device *d;
788                                         const char *val;
789
790                                         if (attrib == NULL)
791                                                 break;
792                                         d = udev_device_new_from_subsystem_sysname(event->udev, subsys, sysname);
793                                         if (d == NULL)
794                                                 break;
795                                         val = udev_device_get_attr_value(d, attrib);
796                                         if (val != NULL)
797                                                 util_strlcpy(value, val, sizeof(value));
798                                         udev_device_unref(d);
799                                 }
800
801                                 /* try the current device, other matches may have selected */
802                                 if (value[0]=='\0' && event->dev_parent != NULL && event->dev_parent != event->dev) {
803                                         const char *val;
804
805                                         val = udev_device_get_attr_value(event->dev_parent, attr);
806                                         if (val != NULL)
807                                                 util_strlcpy(value, val, sizeof(value));
808                                 }
809
810                                 /* look at all devices along the chain of parents */
811                                 if (value[0]=='\0') {
812                                         struct udev_device *dev_parent = dev;
813                                         const char *val;
814
815                                         do {
816                                                 dbg(event->udev, "looking at '%s'\n", udev_device_get_syspath(dev_parent));
817                                                 val = udev_device_get_attr_value(dev_parent, attr);
818                                                 if (val != NULL) {
819                                                         util_strlcpy(value, val, sizeof(value));
820                                                         break;
821                                                 }
822                                                 dev_parent = udev_device_get_parent(dev_parent);
823                                         } while (dev_parent != NULL);
824                                 }
825
826                                 if (value[0]=='\0')
827                                         break;
828
829                                 /* strip trailing whitespace, and replace unwanted characters */
830                                 size = strlen(value);
831                                 while (size > 0 && isspace(value[--size]))
832                                         value[size] = '\0';
833                                 count = util_replace_chars(value, ALLOWED_CHARS_INPUT);
834                                 if (count > 0)
835                                         info(event->udev, "%i character(s) replaced\n" , count);
836                                 util_strlcat(string, value, maxsize);
837                                 dbg(event->udev, "substitute sysfs value '%s'\n", value);
838                         }
839                         break;
840                 case SUBST_PARENT:
841                         {
842                                 struct udev_device *dev_parent;
843                                 const char *devnode;
844
845                                 dev_parent = udev_device_get_parent(event->dev);
846                                 if (dev_parent == NULL)
847                                         break;
848                                 devnode = udev_device_get_devnode(dev_parent);
849                                 if (devnode != NULL) {
850                                         size_t devlen = strlen(udev_get_dev_path(event->udev))+1;
851
852                                         util_strlcat(string, &devnode[devlen], maxsize);
853                                         dbg(event->udev, "found parent '%s', got node name '%s'\n",
854                                             udev_device_get_syspath(dev_parent), &devnode[devlen]);
855                                 }
856                         }
857                         break;
858                 case SUBST_TEMP_NODE:
859                         if (event->tmp_node[0] == '\0' && major(udev_device_get_devnum(dev)) > 0) {
860                                 dbg(event->udev, "create temporary device node for callout\n");
861                                 snprintf(event->tmp_node, sizeof(event->tmp_node), "%s/.tmp-%u-%u",
862                                          udev_get_dev_path(event->udev),
863                                          major(udev_device_get_devnum(dev)), minor(udev_device_get_devnum(dev)));
864                                 udev_node_mknod(dev, event->tmp_node, makedev(0,0), 0600, 0, 0);
865                         }
866                         util_strlcat(string, event->tmp_node, maxsize);
867                         dbg(event->udev, "substitute temporary device node name '%s'\n", event->tmp_node);
868                         break;
869                 case SUBST_NAME:
870                         if (event->name != NULL) {
871                                 util_strlcat(string, event->name, maxsize);
872                                 dbg(event->udev, "substitute name '%s'\n", event->name);
873                         } else {
874                                 util_strlcat(string, udev_device_get_sysname(dev), maxsize);
875                                 dbg(event->udev, "substitute sysname '%s'\n", udev_device_get_sysname(dev));
876                         }
877                         break;
878                 case SUBST_LINKS:
879                         {
880                                 struct udev_list_entry *list_entry;
881
882                                 list_entry = udev_device_get_properties_list_entry(dev);
883                                 util_strlcpy(string, udev_list_entry_get_name(list_entry), maxsize);
884                                 udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry)) {
885                                         util_strlcat(string, " ", maxsize);
886                                         util_strlcat(string, udev_list_entry_get_name(list_entry), maxsize);
887                                 }
888                         }
889                         break;
890                 case SUBST_ROOT:
891                         util_strlcat(string, udev_get_dev_path(event->udev), maxsize);
892                         dbg(event->udev, "substitute udev_root '%s'\n", udev_get_dev_path(event->udev));
893                         break;
894                 case SUBST_SYS:
895                         util_strlcat(string, udev_get_sys_path(event->udev), maxsize);
896                         dbg(event->udev, "substitute sys_path '%s'\n", udev_get_sys_path(event->udev));
897                         break;
898                 case SUBST_ENV:
899                         if (attr == NULL) {
900                                 dbg(event->udev, "missing attribute\n");
901                                 break;
902                         } else {
903                                 struct udev_list_entry *list_entry;
904                                 const char *value;
905
906                                 list_entry = udev_device_get_properties_list_entry(event->dev);
907                                 list_entry = udev_list_entry_get_by_name(list_entry, attr);
908                                 if (list_entry == NULL)
909                                         break;
910                                 value = udev_list_entry_get_value(list_entry);
911                                 dbg(event->udev, "substitute env '%s=%s'\n", attr, value);
912                                 util_strlcat(string, value, maxsize);
913                                 break;
914                         }
915                 default:
916                         err(event->udev, "unknown substitution type=%i\n", type);
917                         break;
918                 }
919                 /* possibly truncate to format-char specified length */
920                 if (len >= 0 && len < (int)strlen(head)) {
921                         head[len] = '\0';
922                         dbg(event->udev, "truncate to %i chars, subtitution string becomes '%s'\n", len, head);
923                 }
924                 util_strlcat(string, temp, maxsize);
925         }
926 }
927
928 static char *key_val(struct udev_rule *rule, struct key *key)
929 {
930         return rule->buf + key->val_off;
931 }
932
933 static char *key_pair_name(struct udev_rule *rule, struct key_pair *pair)
934 {
935         return rule->buf + pair->key_name_off;
936 }
937
938 static int match_key(struct udev *udev, const char *key_name, struct udev_rule *rule, struct key *key, const char *val)
939 {
940         char value[UTIL_PATH_SIZE];
941         char *key_value;
942         char *pos;
943         int match = 0;
944
945         if (key->operation != KEY_OP_MATCH &&
946             key->operation != KEY_OP_NOMATCH)
947                 return 0;
948
949         if (val == NULL)
950                 val = "";
951
952         /* look for a matching string, parts are separated by '|' */
953         util_strlcpy(value, rule->buf + key->val_off, sizeof(value));
954         key_value = value;
955         dbg(udev, "key %s value='%s'\n", key_name, key_value);
956         while (key_value != NULL) {
957                 pos = strchr(key_value, '|');
958                 if (pos != NULL) {
959                         pos[0] = '\0';
960                         pos = &pos[1];
961                 }
962
963                 dbg(udev, "match %s '%s' <-> '%s'\n", key_name, key_value, val);
964                 match = (fnmatch(key_value, val, 0) == 0);
965                 if (match)
966                         break;
967
968                 key_value = pos;
969         }
970
971         if (match && (key->operation == KEY_OP_MATCH)) {
972                 dbg(udev, "%s is true (matching value)\n", key_name);
973                 return 0;
974         }
975         if (!match && (key->operation == KEY_OP_NOMATCH)) {
976                 dbg(udev, "%s is true (non-matching value)\n", key_name);
977                 return 0;
978         }
979         return -1;
980 }
981
982 /* match a single rule against a given device and possibly its parent devices */
983 static int match_rule(struct udev_event *event, struct udev_rule *rule)
984 {
985         struct udev_device *dev = event->dev;
986         int i;
987
988         if (match_key(event->udev, "ACTION", rule, &rule->action, udev_device_get_action(dev)))
989                 goto nomatch;
990
991         if (match_key(event->udev, "KERNEL", rule, &rule->kernel, udev_device_get_sysname(dev)))
992                 goto nomatch;
993
994         if (match_key(event->udev, "SUBSYSTEM", rule, &rule->subsystem, udev_device_get_subsystem(dev)))
995                 goto nomatch;
996
997         if (match_key(event->udev, "DEVPATH", rule, &rule->devpath, udev_device_get_devpath(dev)))
998                 goto nomatch;
999
1000         if (match_key(event->udev, "DRIVER", rule, &rule->driver, udev_device_get_driver(dev)))
1001                 goto nomatch;
1002
1003         /* match NAME against a value assigned by an earlier rule */
1004         if (match_key(event->udev, "NAME", rule, &rule->name, event->name))
1005                 goto nomatch;
1006
1007         /* match against current list of symlinks */
1008         if (rule->symlink_match.operation == KEY_OP_MATCH ||
1009             rule->symlink_match.operation == KEY_OP_NOMATCH) {
1010                 size_t devlen = strlen(udev_get_dev_path(event->udev))+1;
1011                 struct udev_list_entry *list_entry;
1012                 int match = 0;
1013
1014                 udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) {
1015                         const char *devlink;
1016
1017                         devlink =  &udev_list_entry_get_name(list_entry)[devlen];
1018                         if (match_key(event->udev, "SYMLINK", rule, &rule->symlink_match, devlink) == 0) {
1019                                 match = 1;
1020                                 break;
1021                         }
1022                 }
1023                 if (!match)
1024                         goto nomatch;
1025         }
1026
1027         for (i = 0; i < rule->env.count; i++) {
1028                 struct key_pair *pair = &rule->env.keys[i];
1029
1030                 /* we only check for matches, assignments will be handled later */
1031                 if (pair->key.operation == KEY_OP_MATCH ||
1032                     pair->key.operation == KEY_OP_NOMATCH) {
1033                         struct udev_list_entry *list_entry;
1034                         const char *key_name = key_pair_name(rule, pair);
1035                         const char *value;
1036
1037                         list_entry = udev_device_get_properties_list_entry(event->dev);
1038                         list_entry = udev_list_entry_get_by_name(list_entry, key_name);
1039                         value = udev_list_entry_get_value(list_entry);
1040                         if (value == NULL) {
1041                                 dbg(event->udev, "ENV{%s} is not set, treat as empty\n", key_name);
1042                                 value = "";
1043                         }
1044                         if (match_key(event->udev, "ENV", rule, &pair->key, value))
1045                                 goto nomatch;
1046                 }
1047         }
1048
1049         if (rule->test.operation == KEY_OP_MATCH ||
1050             rule->test.operation == KEY_OP_NOMATCH) {
1051                 char filename[UTIL_PATH_SIZE];
1052                 char *subsys;
1053                 char *sysname;
1054                 char *attrib;
1055                 struct stat statbuf;
1056                 int match;
1057
1058                 util_strlcpy(filename, key_val(rule, &rule->test), sizeof(filename));
1059                 udev_rules_apply_format(event, filename, sizeof(filename));
1060
1061                 if (split_subsys_sysname(event->udev, filename, &subsys, &sysname, &attrib) == 0) {
1062                         struct udev_device *d;
1063                         d = udev_device_new_from_subsystem_sysname(event->udev, subsys, sysname);
1064                         if (d != NULL) {
1065                                 util_strlcpy(filename, udev_device_get_syspath(d), sizeof(filename));
1066                                 if (attrib != NULL) {
1067                                         util_strlcat(filename, "/", sizeof(filename));
1068                                         util_strlcat(filename, attrib, sizeof(filename));
1069                                 }
1070                                 udev_device_unref(d);
1071                         }
1072                 } else if (filename[0] != '/') {
1073                         char tmp[UTIL_PATH_SIZE];
1074
1075                         util_strlcpy(tmp, udev_device_get_syspath(dev), sizeof(tmp));
1076                         util_strlcat(tmp, "/", sizeof(tmp));
1077                         util_strlcat(tmp, filename, sizeof(tmp));
1078                         util_strlcpy(filename, tmp, sizeof(filename));
1079                 }
1080
1081                 attr_subst_subdir(filename, sizeof(filename));
1082
1083                 match = (stat(filename, &statbuf) == 0);
1084                 info(event->udev, "'%s' %s", filename, match ? "exists\n" : "does not exist\n");
1085                 if (match && rule->test_mode_mask > 0) {
1086                         match = ((statbuf.st_mode & rule->test_mode_mask) > 0);
1087                         info(event->udev, "'%s' has mode=%#o and %s %#o\n", filename, statbuf.st_mode,
1088                              match ? "matches" : "does not match",
1089                              rule->test_mode_mask);
1090                 }
1091                 if (match && rule->test.operation == KEY_OP_NOMATCH)
1092                         goto nomatch;
1093                 if (!match && rule->test.operation == KEY_OP_MATCH)
1094                         goto nomatch;
1095                 dbg(event->udev, "TEST key is true\n");
1096         }
1097
1098         if (rule->wait_for.operation != KEY_OP_UNSET) {
1099                 char filename[UTIL_PATH_SIZE];
1100                 int found;
1101
1102                 util_strlcpy(filename, key_val(rule, &rule->wait_for), sizeof(filename));
1103                 udev_rules_apply_format(event, filename, sizeof(filename));
1104                 found = (wait_for_file(event, filename, 10) == 0);
1105                 if (!found && (rule->wait_for.operation != KEY_OP_NOMATCH))
1106                         goto nomatch;
1107         }
1108
1109         /* check for matching sysfs attribute pairs */
1110         for (i = 0; i < rule->attr.count; i++) {
1111                 struct key_pair *pair = &rule->attr.keys[i];
1112
1113                 if (pair->key.operation == KEY_OP_MATCH ||
1114                     pair->key.operation == KEY_OP_NOMATCH) {
1115                         char attr[UTIL_PATH_SIZE];
1116                         const char *key_name = key_pair_name(rule, pair);
1117                         const char *key_value = key_val(rule, &pair->key);
1118                         char *subsys;
1119                         char *sysname;
1120                         char *attrib;
1121                         char value[UTIL_NAME_SIZE] = "";
1122                         size_t len;
1123
1124                         util_strlcpy(attr, key_name, sizeof(attr));
1125                         if (split_subsys_sysname(event->udev, attr, &subsys, &sysname, &attrib) == 0) {
1126                                 struct udev_device *d;
1127                                 const char *val;
1128
1129                                 if (attrib == NULL)
1130                                         goto nomatch;
1131                                 d = udev_device_new_from_subsystem_sysname(event->udev, subsys, sysname);
1132                                 if (d == NULL)
1133                                         goto nomatch;
1134                                 val = udev_device_get_attr_value(d, attrib);
1135                                 if (val != NULL)
1136                                         util_strlcpy(value, val, sizeof(value));
1137                                 udev_device_unref(d);
1138                         }
1139
1140                         if (value[0]=='\0') {
1141                                 const char *val;
1142
1143                                 val = udev_device_get_attr_value(dev, key_name);
1144                                 if (val != NULL)
1145                                         util_strlcpy(value, val, sizeof(value));
1146                         }
1147
1148                         if (value[0]=='\0')
1149                                 goto nomatch;
1150
1151                         /* strip trailing whitespace of value, if not asked to match for it */
1152                         len = strlen(key_value);
1153                         if (len > 0 && !isspace(key_value[len-1])) {
1154                                 len = strlen(value);
1155                                 while (len > 0 && isspace(value[--len]))
1156                                         value[len] = '\0';
1157                                 dbg(event->udev, "removed trailing whitespace from '%s'\n", value);
1158                         }
1159
1160                         if (match_key(event->udev, "ATTR", rule, &pair->key, value))
1161                                 goto nomatch;
1162                 }
1163         }
1164
1165         /* walk up the chain of parent devices and find a match */
1166         event->dev_parent = dev;
1167         while (1) {
1168                 /* check for matching kernel device name */
1169                 if (match_key(event->udev, "KERNELS", rule,
1170                               &rule->kernels, udev_device_get_sysname(event->dev_parent)))
1171                         goto try_parent;
1172
1173                 /* check for matching subsystem value */
1174                 if (match_key(event->udev, "SUBSYSTEMS", rule,
1175                               &rule->subsystems, udev_device_get_subsystem(event->dev_parent)))
1176                         goto try_parent;
1177
1178                 /* check for matching driver */
1179                 if (match_key(event->udev, "DRIVERS", rule,
1180                               &rule->drivers, udev_device_get_driver(event->dev_parent)))
1181                         goto try_parent;
1182
1183                 /* check for matching sysfs attribute pairs */
1184                 for (i = 0; i < rule->attrs.count; i++) {
1185                         struct key_pair *pair = &rule->attrs.keys[i];
1186
1187                         if (pair->key.operation == KEY_OP_MATCH ||
1188                             pair->key.operation == KEY_OP_NOMATCH) {
1189                                 const char *key_name = key_pair_name(rule, pair);
1190                                 const char *key_value = key_val(rule, &pair->key);
1191                                 const char *val;
1192                                 char value[UTIL_NAME_SIZE];
1193                                 size_t len;
1194
1195                                 val = udev_device_get_attr_value(event->dev_parent, key_name);
1196                                 if (val == NULL)
1197                                         val = udev_device_get_attr_value(dev, key_name);
1198                                 if (val == NULL)
1199                                         goto try_parent;
1200                                 util_strlcpy(value, val, sizeof(value));
1201
1202                                 /* strip trailing whitespace of value, if not asked to match for it */
1203                                 len = strlen(key_value);
1204                                 if (len > 0 && !isspace(key_value[len-1])) {
1205                                         len = strlen(value);
1206                                         while (len > 0 && isspace(value[--len]))
1207                                                 value[len] = '\0';
1208                                         dbg(event->udev, "removed trailing whitespace from '%s'\n", value);
1209                                 }
1210
1211                                 if (match_key(event->udev, "ATTRS", rule, &pair->key, value))
1212                                         goto try_parent;
1213                         }
1214                 }
1215
1216                 /* found matching device  */
1217                 break;
1218 try_parent:
1219                 /* move to parent device */
1220                 dbg(event->udev, "try parent sysfs device\n");
1221                 event->dev_parent = udev_device_get_parent(event->dev_parent);
1222                 if (event->dev_parent == NULL)
1223                         goto nomatch;
1224                 dbg(event->udev, "looking at dev_parent->devpath='%s'\n",
1225                     udev_device_get_syspath(event->dev_parent));
1226         }
1227
1228         /* execute external program */
1229         if (rule->program.operation != KEY_OP_UNSET) {
1230                 char program[UTIL_PATH_SIZE];
1231                 char result[UTIL_PATH_SIZE];
1232
1233                 util_strlcpy(program, key_val(rule, &rule->program), sizeof(program));
1234                 udev_rules_apply_format(event, program, sizeof(program));
1235                 if (run_program(event->dev, program, result, sizeof(result), NULL) != 0) {
1236                         dbg(event->udev, "PROGRAM is false\n");
1237                         event->program_result[0] = '\0';
1238                         if (rule->program.operation != KEY_OP_NOMATCH)
1239                                 goto nomatch;
1240                 } else {
1241                         int count;
1242
1243                         dbg(event->udev, "PROGRAM matches\n");
1244                         util_remove_trailing_chars(result, '\n');
1245                         if (rule->string_escape == ESCAPE_UNSET ||
1246                             rule->string_escape == ESCAPE_REPLACE) {
1247                                 count = util_replace_chars(result, ALLOWED_CHARS_INPUT);
1248                                 if (count > 0)
1249                                         info(event->udev, "%i character(s) replaced\n" , count);
1250                         }
1251                         dbg(event->udev, "result is '%s'\n", result);
1252                         util_strlcpy(event->program_result, result, sizeof(event->program_result));
1253                         dbg(event->udev, "PROGRAM returned successful\n");
1254                         if (rule->program.operation == KEY_OP_NOMATCH)
1255                                 goto nomatch;
1256                 }
1257                 dbg(event->udev, "PROGRAM key is true\n");
1258         }
1259
1260         /* check for matching result of external program */
1261         if (match_key(event->udev, "RESULT", rule, &rule->result, event->program_result))
1262                 goto nomatch;
1263
1264         /* import variables returned from program or or file into environment */
1265         if (rule->import.operation != KEY_OP_UNSET) {
1266                 char import[UTIL_PATH_SIZE];
1267                 int rc = -1;
1268
1269                 util_strlcpy(import, key_val(rule, &rule->import), sizeof(import));
1270                 udev_rules_apply_format(event, import, sizeof(import));
1271                 dbg(event->udev, "check for IMPORT import='%s'\n", import);
1272                 if (rule->import_type == IMPORT_PROGRAM) {
1273                         rc = import_program_into_env(event, import);
1274                 } else if (rule->import_type == IMPORT_FILE) {
1275                         dbg(event->udev, "import file import='%s'\n", import);
1276                         rc = import_file_into_env(event, import);
1277                 } else if (rule->import_type == IMPORT_PARENT) {
1278                         dbg(event->udev, "import parent import='%s'\n", import);
1279                         rc = import_parent_into_env(event, import);
1280                 }
1281                 if (rc != 0) {
1282                         dbg(event->udev, "IMPORT failed\n");
1283                         if (rule->import.operation != KEY_OP_NOMATCH)
1284                                 goto nomatch;
1285                 } else
1286                         dbg(event->udev, "IMPORT '%s' imported\n", key_val(rule, &rule->import));
1287                 dbg(event->udev, "IMPORT key is true\n");
1288         }
1289
1290         /* rule matches, if we have ENV assignments export it */
1291         for (i = 0; i < rule->env.count; i++) {
1292                 struct key_pair *pair = &rule->env.keys[i];
1293
1294                 if (pair->key.operation == KEY_OP_ASSIGN) {
1295                         char temp_value[UTIL_NAME_SIZE];
1296                         const char *key_name = key_pair_name(rule, pair);
1297                         const char *value = key_val(rule, &pair->key);
1298
1299                         /* make sure we don't write to the same string we possibly read from */
1300                         util_strlcpy(temp_value, value, sizeof(temp_value));
1301                         udev_rules_apply_format(event, temp_value, sizeof(temp_value));
1302
1303                         if (temp_value[0] != '\0') {
1304                                 struct udev_list_entry *entry;
1305
1306                                 info(event->udev, "set ENV '%s=%s'\n", key_name, temp_value);
1307                                 entry = udev_device_add_property(dev, key_name, temp_value);
1308                                 /* store in db */
1309                                 udev_list_entry_set_flag(entry, 1);
1310                         }
1311                 }
1312         }
1313
1314         /* if we have ATTR assignments, write value to sysfs file */
1315         for (i = 0; i < rule->attr.count; i++) {
1316                 struct key_pair *pair = &rule->attr.keys[i];
1317
1318                 if (pair->key.operation == KEY_OP_ASSIGN) {
1319                         const char *key_name = key_pair_name(rule, pair);
1320                         char *subsys;
1321                         char *sysname;
1322                         char *attrib;
1323                         char attr[UTIL_PATH_SIZE];
1324                         char value[UTIL_NAME_SIZE];
1325                         FILE *f;
1326
1327                         util_strlcpy(attr, key_name, sizeof(attr));
1328                         if (split_subsys_sysname(event->udev, attr, &subsys, &sysname, &attrib) == 0) {
1329                                 struct udev_device *d;
1330
1331                                 d = udev_device_new_from_subsystem_sysname(event->udev, subsys, sysname);
1332                                 if (d != NULL) {
1333                                         util_strlcpy(attr, udev_device_get_syspath(d), sizeof(attr));
1334                                         if (attrib != NULL) {
1335                                                 util_strlcat(attr, "/", sizeof(attr));
1336                                                 util_strlcat(attr, attrib, sizeof(attr));
1337                                         }
1338                                         udev_device_unref(d);
1339                                 }
1340                         } else {
1341                                 util_strlcpy(attr, udev_device_get_syspath(dev), sizeof(attr));
1342                                 util_strlcat(attr, "/", sizeof(attr));
1343                                 util_strlcat(attr, key_name, sizeof(attr));
1344                         }
1345
1346                         attr_subst_subdir(attr, sizeof(attr));
1347
1348                         util_strlcpy(value, key_val(rule, &pair->key), sizeof(value));
1349                         udev_rules_apply_format(event, value, sizeof(value));
1350                         info(event->udev, "writing '%s' to sysfs file '%s'\n", value, attr);
1351                         f = fopen(attr, "w");
1352                         if (f != NULL) {
1353                                 if (!event->test)
1354                                         if (fprintf(f, "%s", value) <= 0)
1355                                                 err(event->udev, "error writing ATTR{%s}: %m\n", attr);
1356                                 fclose(f);
1357                         } else
1358                                 err(event->udev, "error opening ATTR{%s} for writing: %m\n", attr);
1359                 }
1360         }
1361         return 0;
1362
1363 nomatch:
1364         return -1;
1365 }
1366
1367 int udev_rules_get_name(struct udev_rules *rules, struct udev_event *event)
1368 {
1369         struct udev_device *dev = event->dev;
1370         struct udev_rules_iter iter;
1371         struct udev_rule *rule;
1372         int name_set = 0;
1373
1374         dbg(event->udev, "device: '%s'\n", udev_device_get_syspath(dev));
1375
1376         /* look for a matching rule to apply */
1377         udev_rules_iter_init(&iter, rules);
1378         while (1) {
1379                 rule = udev_rules_iter_next(&iter);
1380                 if (rule == NULL)
1381                         break;
1382
1383                 if (name_set &&
1384                     (rule->name.operation == KEY_OP_ASSIGN ||
1385                      rule->name.operation == KEY_OP_ASSIGN_FINAL ||
1386                      rule->name.operation == KEY_OP_ADD)) {
1387                         dbg(event->udev, "node name already set, rule ignored\n");
1388                         continue;
1389                 }
1390
1391                 dbg(event->udev, "process rule\n");
1392                 if (match_rule(event, rule) == 0) {
1393                         /* apply options */
1394                         if (rule->ignore_device) {
1395                                 info(event->udev, "rule applied, '%s' is ignored\n", udev_device_get_sysname(dev));
1396                                 event->ignore_device = 1;
1397                                 return 0;
1398                         }
1399                         if (rule->ignore_remove) {
1400                                 udev_device_set_ignore_remove(dev, 1);
1401                                 dbg(event->udev, "remove event should be ignored\n");
1402                         }
1403                         if (rule->link_priority != 0) {
1404                                 udev_device_set_devlink_priority(dev, rule->link_priority);
1405                                 info(event->udev, "devlink_priority=%i\n", rule->link_priority);
1406                         }
1407                         if (rule->event_timeout >= 0) {
1408                                 udev_device_set_event_timeout(dev, rule->event_timeout);
1409                                 info(event->udev, "event_timeout=%i\n", rule->event_timeout);
1410                         }
1411                         /* apply all_partitions option only at a disk device */
1412                         if (rule->partitions > 0 &&
1413                             strcmp(udev_device_get_subsystem(dev), "block") == 0 &&
1414                             udev_device_get_sysnum(dev) == NULL) {
1415                                 udev_device_set_num_fake_partitions(dev, rule->partitions);
1416                                 dbg(event->udev, "creation of partition nodes requested\n");
1417                         }
1418
1419                         /* apply permissions */
1420                         if (!event->mode_final && rule->mode.operation != KEY_OP_UNSET) {
1421                                 if (rule->mode.operation == KEY_OP_ASSIGN_FINAL)
1422                                         event->mode_final = 1;
1423                                 char buf[20];
1424                                 util_strlcpy(buf, key_val(rule, &rule->mode), sizeof(buf));
1425                                 udev_rules_apply_format(event, buf, sizeof(buf));
1426                                 event->mode = strtol(buf, NULL, 8);
1427                                 dbg(event->udev, "applied mode=%#o to '%s'\n",
1428                                     event->mode, udev_device_get_sysname(dev));
1429                         }
1430                         if (!event->owner_final && rule->owner.operation != KEY_OP_UNSET) {
1431                                 if (rule->owner.operation == KEY_OP_ASSIGN_FINAL)
1432                                         event->owner_final = 1;
1433                                 util_strlcpy(event->owner, key_val(rule, &rule->owner), sizeof(event->owner));
1434                                 udev_rules_apply_format(event, event->owner, sizeof(event->owner));
1435                                 dbg(event->udev, "applied owner='%s' to '%s'\n",
1436                                     event->owner, udev_device_get_sysname(dev));
1437                         }
1438                         if (!event->group_final && rule->group.operation != KEY_OP_UNSET) {
1439                                 if (rule->group.operation == KEY_OP_ASSIGN_FINAL)
1440                                         event->group_final = 1;
1441                                 util_strlcpy(event->group, key_val(rule, &rule->group), sizeof(event->group));
1442                                 udev_rules_apply_format(event, event->group, sizeof(event->group));
1443                                 dbg(event->udev, "applied group='%s' to '%s'\n",
1444                                     event->group, udev_device_get_sysname(dev));
1445                         }
1446
1447                         /* collect symlinks */
1448                         if (!event->devlink_final &&
1449                             (rule->symlink.operation == KEY_OP_ASSIGN ||
1450                              rule->symlink.operation == KEY_OP_ASSIGN_FINAL ||
1451                              rule->symlink.operation == KEY_OP_ADD)) {
1452                                 char temp[UTIL_PATH_SIZE];
1453                                 char filename[UTIL_PATH_SIZE];
1454                                 char *pos, *next;
1455                                 int count = 0;
1456
1457                                 if (rule->symlink.operation == KEY_OP_ASSIGN_FINAL)
1458                                         event->devlink_final = 1;
1459                                 if (rule->symlink.operation == KEY_OP_ASSIGN ||
1460                                     rule->symlink.operation == KEY_OP_ASSIGN_FINAL) {
1461                                         info(event->udev, "reset symlink list\n");
1462                                         udev_device_cleanup_devlinks_list(dev);
1463                                 }
1464                                 /* allow  multiple symlinks separated by spaces */
1465                                 util_strlcpy(temp, key_val(rule, &rule->symlink), sizeof(temp));
1466                                 udev_rules_apply_format(event, temp, sizeof(temp));
1467                                 if (rule->string_escape == ESCAPE_UNSET)
1468                                         count = util_replace_chars(temp, ALLOWED_CHARS_FILE " ");
1469                                 else if (rule->string_escape == ESCAPE_REPLACE)
1470                                         count = util_replace_chars(temp, ALLOWED_CHARS_FILE);
1471                                 if (count > 0)
1472                                         info(event->udev, "%i character(s) replaced\n" , count);
1473                                 dbg(event->udev, "rule applied, added symlink(s) '%s'\n", temp);
1474                                 pos = temp;
1475                                 while (isspace(pos[0]))
1476                                         pos++;
1477                                 next = strchr(pos, ' ');
1478                                 while (next) {
1479                                         next[0] = '\0';
1480                                         info(event->udev, "add symlink '%s'\n", pos);
1481                                         util_strlcpy(filename, udev_get_dev_path(event->udev), sizeof(filename));
1482                                         util_strlcat(filename, "/", sizeof(filename));
1483                                         util_strlcat(filename, pos, sizeof(filename));
1484                                         udev_device_add_devlink(dev, filename);
1485                                         while (isspace(next[1]))
1486                                                 next++;
1487                                         pos = &next[1];
1488                                         next = strchr(pos, ' ');
1489                                 }
1490                                 if (pos[0] != '\0') {
1491                                         info(event->udev, "add symlink '%s'\n", pos);
1492                                         util_strlcpy(filename, udev_get_dev_path(event->udev), sizeof(filename));
1493                                         util_strlcat(filename, "/", sizeof(filename));
1494                                         util_strlcat(filename, pos, sizeof(filename));
1495                                         udev_device_add_devlink(dev, filename);
1496                                 }
1497                         }
1498
1499                         /* set name, later rules with name set will be ignored */
1500                         if (rule->name.operation == KEY_OP_ASSIGN ||
1501                             rule->name.operation == KEY_OP_ASSIGN_FINAL ||
1502                             rule->name.operation == KEY_OP_ADD) {
1503                                 int count;
1504
1505                                 name_set = 1;
1506                                 util_strlcpy(event->name, key_val(rule, &rule->name), sizeof(event->name));
1507                                 udev_rules_apply_format(event, event->name, sizeof(event->name));
1508                                 if (rule->string_escape == ESCAPE_UNSET ||
1509                                     rule->string_escape == ESCAPE_REPLACE) {
1510                                         count = util_replace_chars(event->name, ALLOWED_CHARS_FILE);
1511                                         if (count > 0)
1512                                                 info(event->udev, "%i character(s) replaced\n", count);
1513                                 }
1514
1515                                 info(event->udev, "rule applied, '%s' becomes '%s'\n",
1516                                      udev_device_get_sysname(dev), event->name);
1517                                 if (strcmp(udev_device_get_subsystem(dev), "net") != 0)
1518                                         dbg(event->udev, "'%s' owner='%s', group='%s', mode=%#o partitions=%i\n",
1519                                             event->name, event->owner, event->group, event->mode,
1520                                             udev_device_get_num_fake_partitions(dev));
1521                         }
1522
1523                         if (!event->run_final && rule->run.operation != KEY_OP_UNSET) {
1524                                 struct udev_list_entry *list_entry;
1525
1526                                 if (rule->run.operation == KEY_OP_ASSIGN_FINAL)
1527                                         event->run_final = 1;
1528                                 if (rule->run.operation == KEY_OP_ASSIGN || rule->run.operation == KEY_OP_ASSIGN_FINAL) {
1529                                         info(event->udev, "reset run list\n");
1530                                         udev_list_cleanup(event->udev, &event->run_list);
1531                                 }
1532                                 dbg(event->udev, "add run '%s'\n", key_val(rule, &rule->run));
1533                                 list_entry = udev_list_entry_add(event->udev, &event->run_list,
1534                                                                  key_val(rule, &rule->run), NULL, 1, 0);
1535                                 if (rule->run_ignore_error && list_entry != NULL)
1536                                         udev_list_entry_set_flag(list_entry, 1);
1537                         }
1538
1539                         if (rule->last_rule) {
1540                                 dbg(event->udev, "last rule to be applied\n");
1541                                 break;
1542                         }
1543
1544                         if (rule->goto_label.operation != KEY_OP_UNSET) {
1545                                 dbg(event->udev, "moving forward to label '%s'\n", key_val(rule, &rule->goto_label));
1546                                 udev_rules_iter_goto(&iter, rule->goto_rule_off);
1547                         }
1548                 }
1549         }
1550
1551         if (!name_set) {
1552                 info(event->udev, "no node name set, will use kernel name '%s'\n",
1553                      udev_device_get_sysname(dev));
1554                 util_strlcpy(event->name, udev_device_get_sysname(dev), sizeof(event->name));
1555         }
1556
1557         if (event->tmp_node[0] != '\0') {
1558                 dbg(event->udev, "removing temporary device node\n");
1559                 unlink_secure(event->udev, event->tmp_node);
1560                 event->tmp_node[0] = '\0';
1561         }
1562         return 0;
1563 }
1564
1565 int udev_rules_get_run(struct udev_rules *rules, struct udev_event *event)
1566 {
1567         struct udev_device *dev = event->dev;
1568         struct udev_rules_iter iter;
1569         struct udev_rule *rule;
1570
1571         dbg(event->udev, "sysname: '%s'\n", udev_device_get_sysname(dev));
1572
1573         /* look for a matching rule to apply */
1574         udev_rules_iter_init(&iter, rules);
1575         while (1) {
1576                 rule = udev_rules_iter_next(&iter);
1577                 if (rule == NULL)
1578                         break;
1579
1580                 dbg(event->udev, "process rule\n");
1581                 if (rule->name.operation == KEY_OP_ASSIGN ||
1582                     rule->name.operation == KEY_OP_ASSIGN_FINAL ||
1583                     rule->name.operation == KEY_OP_ADD ||
1584                     rule->symlink.operation == KEY_OP_ASSIGN ||
1585                     rule->symlink.operation == KEY_OP_ASSIGN_FINAL ||
1586                     rule->symlink.operation == KEY_OP_ADD ||
1587                     rule->mode.operation != KEY_OP_UNSET ||
1588                     rule->owner.operation != KEY_OP_UNSET || rule->group.operation != KEY_OP_UNSET) {
1589                         dbg(event->udev, "skip rule that names a device\n");
1590                         continue;
1591                 }
1592
1593                 if (match_rule(event, rule) == 0) {
1594                         if (rule->ignore_device) {
1595                                 info(event->udev, "rule applied, '%s' is ignored\n", udev_device_get_sysname(dev));
1596                                 event->ignore_device = 1;
1597                                 return 0;
1598                         }
1599                         if (rule->ignore_remove) {
1600                                 udev_device_set_ignore_remove(dev, 1);
1601                                 dbg(event->udev, "remove event should be ignored\n");
1602                         }
1603
1604                         if (!event->run_final && rule->run.operation != KEY_OP_UNSET) {
1605                                 struct udev_list_entry *list_entry;
1606
1607                                 if (rule->run.operation == KEY_OP_ASSIGN ||
1608                                     rule->run.operation == KEY_OP_ASSIGN_FINAL) {
1609                                         info(event->udev, "reset run list\n");
1610                                         udev_list_cleanup(event->udev, &event->run_list);
1611                                 }
1612                                 dbg(event->udev, "add run '%s'\n", key_val(rule, &rule->run));
1613                                 list_entry = udev_list_entry_add(event->udev, &event->run_list,
1614                                                                  key_val(rule, &rule->run), NULL, 1, 0);
1615                                 if (rule->run_ignore_error && list_entry != NULL)
1616                                         udev_list_entry_set_flag(list_entry, 1);
1617                                 if (rule->run.operation == KEY_OP_ASSIGN_FINAL)
1618                                         break;
1619                         }
1620
1621                         if (rule->last_rule) {
1622                                 dbg(event->udev, "last rule to be applied\n");
1623                                 break;
1624                         }
1625
1626                         if (rule->goto_label.operation != KEY_OP_UNSET) {
1627                                 dbg(event->udev, "moving forward to label '%s'\n", key_val(rule, &rule->goto_label));
1628                                 udev_rules_iter_goto(&iter, rule->goto_rule_off);
1629                         }
1630                 }
1631         }
1632
1633         return 0;
1634 }