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.
13 #include <libnotify/notify.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
) {
33 struct udev_device
* dev
;
35 struct udev_monitor
* mon
= NULL
;
39 unsigned short int i
, major
, minor
;
42 char * notification
= NULL
;
44 NotifyNotification
* netlink
;
45 NotifyNotification
*** netlinkref
;
47 blkid_cache cache
= NULL
;
49 blkid_tag_iterate iter
;
50 const char *type
, *value
, *devname
;
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]);
64 fprintf(stderr
, "%s: Can't create udev.\n", argv
[0]);
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
++)
75 maxminor
= malloc(256 * sizeof(short int));
76 for(i
= 0; i
< 256; i
++)
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
);
89 device
= (char *) udev_device_get_sysname(dev
);
90 devnum
= udev_device_get_devnum(dev
);
92 minor
= devnum
- (major
* 256);
94 switch(udev_device_get_action(dev
)[0]) {
97 notification
= (char *) malloc(strlen(TEXT_ADD
) + strlen(device
));
98 sprintf(notification
, TEXT_ADD
, device
, major
, minor
);
103 notification
= (char *) malloc(strlen(TEXT_REMOVE
) + strlen(device
));
104 sprintf(notification
, TEXT_REMOVE
, device
, major
, minor
);
109 notification
= (char *) malloc(strlen(TEXT_MOVE
) + strlen(device
));
110 sprintf(notification
, TEXT_MOVE
, device
, major
, minor
);
115 notification
= (char *) malloc(strlen(TEXT_CHANGE
) + strlen(device
));
116 sprintf(notification
, TEXT_CHANGE
, device
, major
, minor
);
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
);
126 blkid_get_cache(&cache
, read
);
127 blkdev
= blkid_get_dev(cache
, udev_device_get_devnode(dev
), BLKID_DEV_NORMAL
);
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
;
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
);
167 if(!notify_init("Udev-Block-Notification")) {
168 fprintf(stderr
, "%s: Can't create notify.\n", argv
[0]);
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. ;)