PageRenderTime 46ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/libdevattr/devattr_monitor.c

https://gitlab.com/HowTheStoryEnds/freebsd11-psm-port
C | 360 lines | 264 code | 61 blank | 35 comment | 50 complexity | 25f9380ff9deb2aeacb0485097ee8f50 MD5 | raw file
  1. /*
  2. * Copyright (c) 2010 The DragonFly Project. All rights reserved.
  3. *
  4. * This code is derived from software contributed to The DragonFly Project
  5. * by Alex Hornung <ahornung@gmail.com>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  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
  16. * distribution.
  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.
  20. *
  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
  32. * SUCH DAMAGE.
  33. */
  34. #include <sys/types.h>
  35. #include <sys/device.h>
  36. #include <sys/wait.h>
  37. #include <sys/socket.h>
  38. #include <sys/ioctl.h>
  39. #include <sys/poll.h>
  40. #include <sys/queue.h>
  41. #include <sys/un.h>
  42. #include <cpu/inttypes.h>
  43. #include <err.h>
  44. #include <errno.h>
  45. #include <fcntl.h>
  46. #include <libgen.h>
  47. #include <regex.h>
  48. #include <signal.h>
  49. #include <stdarg.h>
  50. #include <stdio.h>
  51. #include <stdlib.h>
  52. #include <string.h>
  53. #include <syslog.h>
  54. #include <unistd.h>
  55. #include <pthread.h>
  56. #include <libprop/proplib.h>
  57. #include <sys/udev.h>
  58. #define LIBDEVATTR_INTERNAL
  59. #include "devattr.h"
  60. struct udev_monitor {
  61. struct udev *udev_ctx;
  62. prop_array_t ev_filt;
  63. int socket;
  64. int user_socket; /* maybe... one day... */
  65. int refs;
  66. };
  67. struct udev_monitor *
  68. udev_monitor_new(struct udev *udev_ctx)
  69. {
  70. struct udev_monitor *udev_monitor;
  71. int ret, s;
  72. ret = conn_local_server(LISTEN_SOCKET_FILE, SOCK_STREAM, 0, &s);
  73. if (ret < 0)
  74. return NULL;
  75. udev_monitor = malloc(sizeof(struct udev_monitor));
  76. if (udev_monitor == NULL)
  77. return NULL;
  78. udev_monitor->refs = 1;
  79. udev_monitor->ev_filt = NULL;
  80. udev_monitor->socket = s;
  81. udev_monitor->user_socket = 1;
  82. udev_monitor->udev_ctx = udev_ref(udev_ctx);
  83. return udev_monitor;
  84. }
  85. struct udev_monitor *
  86. udev_monitor_ref(struct udev_monitor *udev_monitor)
  87. {
  88. atomic_add_int(&udev_monitor->refs, 1);
  89. return udev_monitor;
  90. }
  91. void
  92. udev_monitor_unref(struct udev_monitor *udev_monitor)
  93. {
  94. int refcount;
  95. refcount = atomic_fetchadd_int(&udev_monitor->refs, -1);
  96. if (refcount == 1) {
  97. atomic_subtract_int(&udev_monitor->refs, 0x400); /* in destruction */
  98. if (udev_monitor->ev_filt != NULL)
  99. prop_object_release(udev_monitor->ev_filt);
  100. if (udev_monitor->socket != -1)
  101. close(udev_monitor->socket);
  102. if (udev_monitor->user_socket != -1)
  103. close(udev_monitor->user_socket);
  104. udev_unref(udev_monitor->udev_ctx);
  105. free(udev_monitor);
  106. }
  107. }
  108. struct udev *
  109. udev_monitor_get_udev(struct udev_monitor *udev_monitor)
  110. {
  111. return udev_monitor->udev_ctx;
  112. }
  113. int
  114. udev_monitor_get_fd(struct udev_monitor *udev_monitor)
  115. {
  116. return udev_monitor->socket;
  117. }
  118. struct udev_device *
  119. udev_monitor_receive_device(struct udev_monitor *udev_monitor)
  120. {
  121. struct udev_device *udev_dev;
  122. prop_dictionary_t dict, evdict;
  123. prop_number_t pn;
  124. char *xml;
  125. int n;
  126. if ((n = read_xml(udev_monitor->socket, &xml)) <= 0)
  127. return NULL;
  128. xml[n+1] = '\0';
  129. dict = prop_dictionary_internalize(xml);
  130. free(xml);
  131. if (dict == NULL)
  132. return NULL;
  133. pn = prop_dictionary_get(dict, "evtype");
  134. if (pn == NULL) {
  135. prop_object_release(dict);
  136. return NULL;
  137. }
  138. evdict = prop_dictionary_get(dict, "evdict");
  139. if (evdict == NULL) {
  140. prop_object_release(dict);
  141. return NULL;
  142. }
  143. udev_dev = udev_device_new_from_dictionary(udev_monitor->udev_ctx, evdict);
  144. if (udev_dev == NULL) {
  145. prop_object_release(dict);
  146. return NULL;
  147. }
  148. udev_device_set_action(udev_dev, prop_number_integer_value(pn));
  149. prop_object_release(dict);
  150. return udev_dev;
  151. }
  152. int
  153. udev_monitor_enable_receiving(struct udev_monitor *udev_monitor)
  154. {
  155. prop_dictionary_t dict;
  156. char *xml;
  157. int n;
  158. /* ->socket, ->user_socket, ->ev_filt */
  159. dict = udevd_get_command_dict(__DECONST(char *, "monitor"));
  160. if (dict == NULL)
  161. return -1;
  162. /* Add event filters to message, if available */
  163. if (udev_monitor->ev_filt != NULL) {
  164. if (prop_dictionary_set(dict, "filters",
  165. udev_monitor->ev_filt) == false) {
  166. prop_object_release(dict);
  167. return -1;
  168. }
  169. }
  170. xml = prop_dictionary_externalize(dict);
  171. prop_object_release(dict);
  172. if (xml == NULL)
  173. return -1;
  174. n = send_xml(udev_monitor->socket, xml);
  175. free(xml);
  176. if (n <= 0)
  177. return -1;
  178. return 0;
  179. }
  180. int
  181. udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor,
  182. const char *subsystem,
  183. const char *devtype __unused)
  184. {
  185. int ret;
  186. ret = _udev_monitor_filter_add_match_gen(udev_monitor,
  187. EVENT_FILTER_TYPE_WILDCARD,
  188. 0,
  189. "subsystem",
  190. __DECONST(char *, subsystem));
  191. return ret;
  192. }
  193. int
  194. udev_monitor_filter_add_match_expr(struct udev_monitor *udev_monitor,
  195. const char *key,
  196. char *expr)
  197. {
  198. int ret;
  199. ret = _udev_monitor_filter_add_match_gen(udev_monitor,
  200. EVENT_FILTER_TYPE_WILDCARD,
  201. 0,
  202. key,
  203. expr);
  204. return ret;
  205. }
  206. int
  207. udev_monitor_filter_add_nomatch_expr(struct udev_monitor *udev_monitor,
  208. const char *key,
  209. char *expr)
  210. {
  211. int ret;
  212. ret = _udev_monitor_filter_add_match_gen(udev_monitor,
  213. EVENT_FILTER_TYPE_WILDCARD,
  214. 1,
  215. key,
  216. expr);
  217. return ret;
  218. }
  219. int
  220. udev_monitor_filter_add_match_regex(struct udev_monitor *udev_monitor,
  221. const char *key,
  222. char *expr)
  223. {
  224. int ret;
  225. ret = _udev_monitor_filter_add_match_gen(udev_monitor,
  226. EVENT_FILTER_TYPE_REGEX,
  227. 0,
  228. key,
  229. expr);
  230. return ret;
  231. }
  232. int
  233. udev_monitor_filter_add_nomatch_regex(struct udev_monitor *udev_monitor,
  234. const char *key,
  235. char *expr)
  236. {
  237. int ret;
  238. ret = _udev_monitor_filter_add_match_gen(udev_monitor,
  239. EVENT_FILTER_TYPE_REGEX,
  240. 1,
  241. key,
  242. expr);
  243. return ret;
  244. }
  245. int
  246. _udev_filter_add_match_gen(prop_array_t filters,
  247. int type,
  248. int neg,
  249. const char *key,
  250. char *expr)
  251. {
  252. prop_dictionary_t dict;
  253. int error;
  254. if (key == NULL)
  255. return -1;
  256. if (expr == NULL)
  257. return -1;
  258. dict = prop_dictionary_create();
  259. if (dict == NULL)
  260. return -1;
  261. error = _udev_dict_set_cstr(dict, "key", __DECONST(char *, key));
  262. if (error != 0)
  263. goto error_out;
  264. error = _udev_dict_set_int(dict, "type", type);
  265. if (error != 0)
  266. goto error_out;
  267. error = _udev_dict_set_cstr(dict, "expr", expr);
  268. if (error != 0)
  269. goto error_out;
  270. if (neg) {
  271. error = _udev_dict_set_int(dict, "negative", 1);
  272. if (error != 0)
  273. goto error_out;
  274. }
  275. if (prop_array_add(filters, dict) == false)
  276. goto error_out;
  277. return 0;
  278. error_out:
  279. prop_object_release(dict);
  280. return -1;
  281. }
  282. int
  283. _udev_monitor_filter_add_match_gen(struct udev_monitor *udev_monitor,
  284. int type,
  285. int neg,
  286. const char *key,
  287. char *expr)
  288. {
  289. prop_array_t pa;
  290. int error;
  291. if (udev_monitor->ev_filt == NULL) {
  292. pa = prop_array_create_with_capacity(5);
  293. if (pa == NULL)
  294. return -1;
  295. udev_monitor->ev_filt = pa;
  296. }
  297. error = _udev_filter_add_match_gen(udev_monitor->ev_filt, type, neg, key, expr);
  298. return error;
  299. }