]>
Commit | Line | Data |
---|---|---|
70267fa6 TP |
1 | #define _GNU_SOURCE |
2 | #include <libudev.h> | |
3 | #include <linux/netlink.h> | |
4 | #include <netinet/in.h> | |
5 | ||
6 | #include <stdio.h> | |
7 | #include <stdlib.h> | |
8 | #include <string.h> | |
9 | #include <unistd.h> | |
10 | ||
11 | #ifndef SOCK_CLOEXEC | |
12 | #define SOCK_CLOEXEC 0 | |
13 | #endif | |
14 | ||
15 | #define MONITOR_BUF_SIZE 4096 | |
16 | #define UDEV_MONITOR_MAGIC 0xfeedcafe | |
17 | struct udev_monitor_netlink_header { | |
18 | /* "libudev" prefix to distinguish libudev and kernel messages */ | |
19 | char prefix[8]; | |
20 | /* | |
21 | * magic to protect against daemon <-> library message format mismatch | |
22 | * used in the kernel from socket filter rules; needs to be stored in network order | |
23 | */ | |
24 | unsigned int magic; | |
25 | /* total length of header structure known to the sender */ | |
26 | unsigned int header_size; | |
27 | /* properties string buffer */ | |
28 | unsigned int properties_off; | |
29 | unsigned int properties_len; | |
30 | /* | |
31 | * hashes of primary device properties strings, to let libudev subscribers | |
32 | * use in-kernel socket filters; values need to be stored in network order | |
33 | */ | |
34 | unsigned int filter_subsystem_hash; | |
35 | unsigned int filter_devtype_hash; | |
36 | unsigned int filter_tag_bloom_hi; | |
37 | unsigned int filter_tag_bloom_lo; | |
38 | }; | |
39 | ||
40 | int main() { | |
41 | int sock=socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT); | |
42 | struct msghdr msg; | |
43 | struct iovec iov[2]; | |
44 | char val[MONITOR_BUF_SIZE]; | |
45 | ssize_t i; | |
46 | struct udev_monitor_netlink_header nlh; | |
47 | struct udev *udev; | |
48 | struct udev_enumerate *enumerate; | |
49 | struct udev_list_entry *devices, *dev_list_entry; | |
50 | struct udev_device *dev; | |
51 | struct sockaddr_nl dst; | |
52 | ||
53 | memset(&dst, 0 ,sizeof(dst)); | |
54 | dst.nl_family= AF_NETLINK; | |
55 | dst.nl_pad=0; | |
56 | dst.nl_pid=1; | |
57 | dst.nl_groups=2; | |
58 | ||
59 | memset(&msg,0,sizeof(msg)); | |
60 | msg.msg_iov = iov; | |
61 | msg.msg_iovlen = 2; | |
62 | msg.msg_name = &dst; | |
63 | msg.msg_namelen = sizeof(dst); | |
64 | ||
65 | memset(&nlh, 0, sizeof(nlh)); | |
66 | memcpy(nlh.prefix, "libudev", 8); | |
67 | nlh.magic = htonl(UDEV_MONITOR_MAGIC); | |
68 | nlh.header_size = sizeof(nlh); | |
69 | iov[0].iov_base = &nlh; | |
70 | iov[0].iov_len = sizeof(nlh); | |
71 | nlh.properties_off = iov[0].iov_len; | |
72 | nlh.filter_tag_bloom_hi = htonl(0xffffffff); | |
73 | nlh.filter_tag_bloom_lo = htonl(0xffffffff); | |
74 | ||
75 | udev = udev_new(); | |
76 | enumerate = udev_enumerate_new(udev); | |
77 | // udev_enumerate_add_match_subsystem(enumerate, "block"); | |
78 | udev_enumerate_scan_devices(enumerate); | |
79 | devices = udev_enumerate_get_list_entry(enumerate); | |
80 | udev_list_entry_foreach(dev_list_entry, devices) { | |
81 | const char *path; | |
82 | path = udev_list_entry_get_name(dev_list_entry); | |
83 | dev = udev_device_new_from_syspath(udev, path); | |
84 | if(udev_device_get_devnum(dev)==0) continue; | |
85 | char *tmp; | |
86 | int l; | |
87 | i=0; | |
88 | l=asprintf(&tmp,"ACTION=add"); strcpy(val+i,tmp); i+=l+1; free(tmp); | |
89 | l=asprintf(&tmp,"DEVNAME=%s",udev_device_get_devnode(dev)); strcpy(val+i,tmp); i+=l+1; free(tmp); | |
90 | l=asprintf(&tmp,"DEVPATH=%s",udev_device_get_devpath(dev)); strcpy(val+i,tmp); i+=l+1; free(tmp); | |
91 | l=asprintf(&tmp,"DEVTYPE=%s",udev_device_get_devtype(dev)); strcpy(val+i,tmp); i+=l+1; free(tmp); | |
92 | l=asprintf(&tmp,"MAJOR=%u",major(udev_device_get_devnum(dev))); strcpy(val+i,tmp); i+=l+1; free(tmp); | |
93 | l=asprintf(&tmp,"MINOR=%u",minor(udev_device_get_devnum(dev))); strcpy(val+i,tmp); i+=l+1; free(tmp); | |
94 | l=asprintf(&tmp,"SEQNUM=%lld",udev_device_get_seqnum(dev)); strcpy(val+i,tmp); i+=l+1; free(tmp); | |
95 | l=asprintf(&tmp,"SUBSYSTEM=%s",udev_device_get_subsystem(dev)); strcpy(val+i,tmp); i+=l+1; free(tmp); | |
96 | l=asprintf(&tmp,"TAGS=:systemd:"); strcpy(val+i,tmp); i+=l+1; free(tmp); | |
97 | l=asprintf(&tmp,"UDEV_LOG=%u",udev_get_log_priority(udev)); strcpy(val+i,tmp); i+=l+1; free(tmp); | |
98 | l=asprintf(&tmp,"USEC_INITIALIZED=%lld",udev_device_get_usec_since_initialized(dev)); strcpy(val+i,tmp); i+=l+1; free(tmp); | |
99 | udev_device_unref(dev); | |
100 | iov[1].iov_base = val; | |
101 | iov[1].iov_len = i; | |
102 | nlh.properties_len = i; | |
103 | sendmsg(sock, &msg, 0); | |
104 | } | |
105 | udev_enumerate_unref(enumerate); | |
106 | udev_unref(udev); | |
107 | ||
108 | close(sock); | |
109 | return EXIT_SUCCESS; | |
110 | } |