2 * Copyright (c) 2010 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Alex Hornung <ahornung@gmail.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/types.h>
35 #include <sys/device.h>
37 #include <sys/socket.h>
38 #include <sys/ioctl.h>
40 #include <sys/queue.h>
56 #include <libprop/proplib.h>
58 #define LIBDEVATTR_INTERNAL
62 struct udev
*udev_ctx
;
65 int user_socket
; /* maybe... one day... */
70 udev_monitor_new(struct udev
*udev_ctx
)
72 struct udev_monitor
*udev_monitor
;
75 ret
= conn_local_server(LISTEN_SOCKET_FILE
, SOCK_STREAM
, 0, &s
);
79 udev_monitor
= malloc(sizeof(struct udev_monitor
));
80 if (udev_monitor
== NULL
)
83 udev_monitor
->refs
= 1;
84 udev_monitor
->ev_filt
= NULL
;
85 udev_monitor
->socket
= s
;
86 udev_monitor
->user_socket
= 1;
87 udev_monitor
->udev_ctx
= udev_ref(udev_ctx
);
94 udev_monitor_ref(struct udev_monitor
*udev_monitor
)
96 atomic_add_int(&udev_monitor
->refs
, 1);
102 udev_monitor_unref(struct udev_monitor
*udev_monitor
)
106 refcount
= atomic_fetchadd_int(&udev_monitor
->refs
, -1);
109 atomic_subtract_int(&udev_monitor
->refs
, 0x400); /* in destruction */
110 if (udev_monitor
->ev_filt
!= NULL
)
111 prop_object_release(udev_monitor
->ev_filt
);
113 if (udev_monitor
->socket
!= -1)
114 close(udev_monitor
->socket
);
115 if (udev_monitor
->user_socket
!= -1)
116 close(udev_monitor
->user_socket
);
118 udev_unref(udev_monitor
->udev_ctx
);
124 udev_monitor_get_udev(struct udev_monitor
*udev_monitor
)
126 return udev_monitor
->udev_ctx
;
130 udev_monitor_get_fd(struct udev_monitor
*udev_monitor
)
132 return udev_monitor
->socket
;
136 udev_monitor_receive_device(struct udev_monitor
*udev_monitor
)
138 struct udev_device
*udev_dev
;
139 prop_dictionary_t dict
, evdict
;
144 if ((n
= read_xml(udev_monitor
->socket
, &xml
)) <= 0)
148 dict
= prop_dictionary_internalize(xml
);
153 pn
= prop_dictionary_get(dict
, "evtype");
155 prop_object_release(dict
);
159 evdict
= prop_dictionary_get(dict
, "evdict");
160 if (evdict
== NULL
) {
161 prop_object_release(dict
);
165 udev_dev
= udev_device_new_from_dictionary(udev_monitor
->udev_ctx
, evdict
);
166 if (udev_dev
== NULL
) {
167 prop_object_release(dict
);
171 udev_device_set_action(udev_dev
, prop_number_integer_value(pn
));
173 prop_object_release(dict
);
178 udev_monitor_enable_receiving(struct udev_monitor
*udev_monitor
)
180 prop_dictionary_t dict
;
183 /* ->socket, ->user_socket, ->ev_filt */
185 dict
= udevd_get_command_dict(__DECONST(char *, "monitor"));
189 /* Add event filters to message, if available */
190 if (udev_monitor
->ev_filt
!= NULL
) {
191 if (prop_dictionary_set(dict
, "filters",
192 udev_monitor
->ev_filt
) == false) {
193 prop_object_release(dict
);
198 xml
= prop_dictionary_externalize(dict
);
199 prop_object_release(dict
);
203 n
= send_xml(udev_monitor
->socket
, xml
);
212 udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor
*udev_monitor
,
213 const char *subsystem
,
214 const char *devtype __unused
)
218 ret
= _udev_monitor_filter_add_match_gen(udev_monitor
,
219 EVENT_FILTER_TYPE_WILDCARD
,
222 __DECONST(char *, subsystem
));
228 udev_monitor_filter_add_match_expr(struct udev_monitor
*udev_monitor
,
234 ret
= _udev_monitor_filter_add_match_gen(udev_monitor
,
235 EVENT_FILTER_TYPE_WILDCARD
,
244 udev_monitor_filter_add_nomatch_expr(struct udev_monitor
*udev_monitor
,
250 ret
= _udev_monitor_filter_add_match_gen(udev_monitor
,
251 EVENT_FILTER_TYPE_WILDCARD
,
260 udev_monitor_filter_add_match_regex(struct udev_monitor
*udev_monitor
,
266 ret
= _udev_monitor_filter_add_match_gen(udev_monitor
,
267 EVENT_FILTER_TYPE_REGEX
,
276 udev_monitor_filter_add_nomatch_regex(struct udev_monitor
*udev_monitor
,
282 ret
= _udev_monitor_filter_add_match_gen(udev_monitor
,
283 EVENT_FILTER_TYPE_REGEX
,
292 _udev_filter_add_match_gen(prop_array_t filters
,
298 prop_dictionary_t dict
;
306 dict
= prop_dictionary_create();
310 error
= _udev_dict_set_cstr(dict
, "key", __DECONST(char *, key
));
313 error
= _udev_dict_set_int(dict
, "type", type
);
316 error
= _udev_dict_set_cstr(dict
, "expr", expr
);
321 error
= _udev_dict_set_int(dict
, "negative", 1);
326 if (prop_array_add(filters
, dict
) == false)
332 prop_object_release(dict
);
337 _udev_monitor_filter_add_match_gen(struct udev_monitor
*udev_monitor
,
346 if (udev_monitor
->ev_filt
== NULL
) {
347 pa
= prop_array_create_with_capacity(5);
351 udev_monitor
->ev_filt
= pa
;
354 error
= _udev_filter_add_match_gen(udev_monitor
->ev_filt
, type
, neg
, key
, expr
);