updated on Thu Jan 26 16:09:46 UTC 2012
[aur-mirror.git] / udev-block-notify / udev-block-notify.c
blob75e2709bee822e801f214803f86f727b8fe205b3
1 /*
2 * (C) 2011 by Christian Hesse <mail@eworm.de>
4 * This software may be used and distributed according to the terms
5 * of the GNU General Public License, incorporated herein by reference.
6 */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <string.h>
13 #include <libnotify/notify.h>
14 #include <libudev.h>
15 #include <blkid.h>
17 #define NOTIFICATION_TIMEOUT 10000
19 #define ICON_ADD "media-flash"
20 #define ICON_REMOVE "media-flash"
21 #define ICON_MOVE "media-flash"
22 #define ICON_CHANGE "media-flash"
23 #define ICON_DEFAULT "media-flash"
25 #define TEXT_ADD "<b>Device %s (%i:%i) appeared</b>."
26 #define TEXT_REMOVE "<b>Device %s (%i:%i) disappeared</b>."
27 #define TEXT_MOVE "<b>Device %s (%i:%i) was renamed</b>."
28 #define TEXT_CHANGE "<b>Device %s (%i:%i) media changed</b>."
29 #define TEXT_DEFAULT "<b>Anything happend to %s (%i:%i)...</b> Don't know.\n"
31 int main (int argc, char ** argv) {
32 struct udev * udev;
33 struct udev_device * dev;
34 char * device = NULL;
35 struct udev_monitor * mon = NULL;
36 fd_set readfds;
37 int fdcount;
38 int devnum;
39 unsigned short int i, major, minor;
40 short int * maxminor;
42 char * notification = NULL;
43 char * icon = NULL;
44 NotifyNotification * netlink;
45 NotifyNotification *** netlinkref;
47 blkid_cache cache = NULL;
48 char *read = NULL;
49 blkid_tag_iterate iter;
50 const char *type, *value, *devname;
51 blkid_dev blkdev;
53 GError * error = NULL;
55 printf("%s: %s v%s (compiled: %s)\n", argv[0], PROGNAME, VERSION, DATE);
57 if(!notify_init("Udev-Block-Notification")) {
58 fprintf(stderr, "%s: Can't create notify.\n", argv[0]);
59 exit(EXIT_FAILURE);
62 udev = udev_new();
63 if(!udev) {
64 fprintf(stderr, "%s: Can't create udev.\n", argv[0]);
65 exit(EXIT_FAILURE);
68 mon = udev_monitor_new_from_netlink(udev, "udev");
69 udev_monitor_filter_add_match_subsystem_devtype(mon, "block", NULL);
70 udev_monitor_enable_receiving(mon);
72 netlinkref = malloc(256 * sizeof(size_t));
73 for(i = 0; i < 256; i++)
74 netlinkref[i] = NULL;
75 maxminor = malloc(256 * sizeof(short int));
76 for(i = 0; i < 256; i++)
77 maxminor[i] = -1;
79 while (1) {
80 FD_ZERO(&readfds);
81 if (mon != NULL)
82 FD_SET(udev_monitor_get_fd(mon), &readfds);
84 fdcount = select(udev_monitor_get_fd(mon) + 1, &readfds, NULL, NULL, NULL);
86 if ((mon != NULL) && FD_ISSET(udev_monitor_get_fd(mon), &readfds)) {
87 dev = udev_monitor_receive_device(mon);
88 if(dev) {
89 device = (char *) udev_device_get_sysname(dev);
90 devnum = udev_device_get_devnum(dev);
91 major = devnum / 256;
92 minor = devnum - (major * 256);
94 switch(udev_device_get_action(dev)[0]) {
95 case 'a':
96 // a: add
97 notification = (char *) malloc(strlen(TEXT_ADD) + strlen(device));
98 sprintf(notification, TEXT_ADD, device, major, minor);
99 icon = ICON_ADD;
100 break;
101 case 'r':
102 // r: remove
103 notification = (char *) malloc(strlen(TEXT_REMOVE) + strlen(device));
104 sprintf(notification, TEXT_REMOVE, device, major, minor);
105 icon = ICON_REMOVE;
106 break;
107 case 'm':
108 // m: move
109 notification = (char *) malloc(strlen(TEXT_MOVE) + strlen(device));
110 sprintf(notification, TEXT_MOVE, device, major, minor);
111 icon = ICON_MOVE;
112 break;
113 case 'c':
114 // c: change
115 notification = (char *) malloc(strlen(TEXT_CHANGE) + strlen(device));
116 sprintf(notification, TEXT_CHANGE, device, major, minor);
117 icon = ICON_CHANGE;
118 break;
119 default:
120 // we should never get here I think...
121 notification = (char *) malloc(strlen(TEXT_DEFAULT) + strlen(device));
122 sprintf(notification, TEXT_CHANGE, device, major, minor);
123 icon = ICON_DEFAULT;
126 blkid_get_cache(&cache, read);
127 blkdev = blkid_get_dev(cache, udev_device_get_devnode(dev), BLKID_DEV_NORMAL);
129 if (blkdev) {
130 iter = blkid_tag_iterate_begin(blkdev);
132 while (blkid_tag_next(iter, &type, &value) == 0) {
133 notification = (char *) realloc(notification, strlen(notification) + strlen(type) + strlen(value) + 4);
134 sprintf(notification, "%s\n%s: %s", notification, type, value);
137 blkid_tag_iterate_end(iter);
138 blkid_put_cache(cache);
141 printf("%s: %s\n", argv[0], notification);
143 if (maxminor[major] < minor) {
144 netlinkref[major] = realloc(netlinkref[major], (minor + 1) * sizeof(size_t));
145 while(maxminor[major] < minor)
146 netlinkref[major][++maxminor[major]] = NULL;
149 if (netlinkref[major][minor] == NULL) {
150 netlink = notify_notification_new("Udev-Block", notification, icon);
151 netlinkref[major][minor] = netlink;
152 } else {
153 netlink = netlinkref[major][minor];
154 notify_notification_update(netlink, "Udev-Block", notification, icon);
157 notify_notification_set_timeout(netlink, NOTIFICATION_TIMEOUT);
158 notify_notification_set_category(netlink, "Udev-Block");
159 notify_notification_set_urgency (netlink, NOTIFY_URGENCY_NORMAL);
161 while(!notify_notification_show(netlink, &error)) {
162 g_printerr("%s: Error \"%s\" while trying to show notification. Trying to reconnect.\n", argv[0], error->message);
163 g_error_free(error);
164 error = NULL;
166 notify_uninit();
167 if(!notify_init("Udev-Block-Notification")) {
168 fprintf(stderr, "%s: Can't create notify.\n", argv[0]);
169 exit(EXIT_FAILURE);
173 free(notification);
174 udev_device_unref(dev);
177 // This is not really needed... But we want to make shure not to eat 100% CPU if anything breaks. ;)
178 usleep(500 * 1000);
182 udev_unref(udev);
183 return EXIT_SUCCESS;