Merge branch 'bugfix/git-https' into experimental
[tails-test.git] / config / chroot_local-includes / usr / src / udev-watchdog.c
blob22ba89b3f4305a5f7aca17bac213e4124e8519b1
1 /*
2 * Copyright (C) 2004-2009 Kay Sievers <kay.sievers@vrfy.org>
4 * + Trimmed from udev-149. Fixed passing of devtype parameter.
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #ifndef _POSIX_C_SOURCE
21 #define _POSIX_C_SOURCE 1
22 #ifndef _BSD_SOURCE
23 #define _BSD_SOURCE
24 #endif
25 #endif
27 #include <unistd.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <stddef.h>
31 #include <string.h>
32 #include <fcntl.h>
33 #include <errno.h>
34 #include <signal.h>
35 #include <getopt.h>
36 #include <sys/time.h>
37 #include <sys/socket.h>
38 #include <sys/un.h>
39 #include <sys/select.h>
40 #include <linux/types.h>
41 #include <linux/netlink.h>
42 #include <libudev.h>
44 static volatile sig_atomic_t udev_exit;
46 static void sig_handler(int signum)
48 if (signum == SIGINT || signum == SIGTERM)
49 udev_exit = 2;
52 static int print_device(struct udev_device *device, const char *f_action, const char *f_devsuffix)
54 struct timeval tv;
56 const char *action = udev_device_get_action(device);
57 const char *devpath = udev_device_get_devpath(device);
58 size_t f_len, d_len;
60 gettimeofday(&tv, NULL);
61 printf("%lu.%06u %s %s\n",
62 (unsigned long) tv.tv_sec, (unsigned int) tv.tv_usec,
63 action, devpath);
65 if (! strcmp(f_action, action)) {
66 f_len = strlen(f_devsuffix);
67 d_len = strlen(devpath);
69 if (d_len >= f_len && !strcmp(devpath+(d_len-f_len), f_devsuffix))
70 return 1;
73 return 0;
76 int main(int argc, char *argv[])
78 int rc = 0;
80 struct udev *udev;
82 struct sigaction act;
83 sigset_t mask;
84 struct udev_monitor *kernel_monitor = NULL;
85 fd_set readfds;
87 const char *filter_subsys = "block";
88 /* const char *filter_devtype = "partition"; */
89 const char *filter_devsuffix;
90 const char *filter_devtype;
91 const char *filter_action;
93 udev = udev_new();
94 if (udev == NULL)
95 goto out2;
97 if (argc != 3)
98 goto out2;
100 filter_devsuffix = argv[1];
101 filter_devtype = argv[2];
103 if (strcmp(filter_devtype, "cd") == 0) {
104 filter_action = "change";
105 } else if (strcmp(filter_devtype, "disk") == 0) {
106 filter_action = "remove";
109 /* set signal handlers */
110 memset(&act, 0x00, sizeof(struct sigaction));
111 act.sa_handler = sig_handler;
112 sigemptyset(&act.sa_mask);
113 act.sa_flags = SA_RESTART;
114 sigaction(SIGINT, &act, NULL);
115 sigaction(SIGTERM, &act, NULL);
116 sigemptyset(&mask);
117 sigaddset(&mask, SIGINT);
118 sigaddset(&mask, SIGTERM);
119 sigprocmask(SIG_UNBLOCK, &mask, NULL);
121 kernel_monitor = udev_monitor_new_from_netlink(udev, "kernel");
122 if (kernel_monitor == NULL) {
123 fprintf(stderr, "error: unable to create netlink socket\n");
124 rc = 3;
125 goto out;
128 if (udev_monitor_filter_add_match_subsystem_devtype(kernel_monitor, filter_subsys, NULL /* filter_devtype */) < 0)
129 fprintf(stderr, "error: unable to apply subsystem filter '%s:%s'\n", filter_subsys, "NULL" /* filter_devtype */);
131 if (udev_monitor_enable_receiving(kernel_monitor) < 0) {
132 fprintf(stderr, "error: unable to subscribe to kernel events\n");
133 rc = 4;
134 goto out;
137 while (!udev_exit) {
138 int fdcount;
140 FD_ZERO(&readfds);
141 if (kernel_monitor != NULL)
142 FD_SET(udev_monitor_get_fd(kernel_monitor), &readfds);
144 fdcount = select(udev_monitor_get_fd(kernel_monitor)+1,
145 &readfds, NULL, NULL, NULL);
146 if (fdcount < 0) {
147 if (errno != EINTR)
148 fprintf(stderr, "error receiving uevent message: %s\n", strerror(errno));
149 continue;
152 if ((kernel_monitor != NULL) && FD_ISSET(udev_monitor_get_fd(kernel_monitor), &readfds)) {
153 struct udev_device *device;
155 device = udev_monitor_receive_device(kernel_monitor);
156 if (device == NULL)
157 continue;
158 if (print_device(device, filter_action, filter_devsuffix))
159 udev_exit = 1;
161 udev_device_unref(device);
165 out:
166 udev_monitor_unref(kernel_monitor);
168 out2:
169 udev_unref(udev);
171 if (udev_exit == 2)
172 rc = 1;
174 return rc;