udev.h (4911B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /* 8 * This file defines a wrapper around libudev so we can avoid 9 * linking directly to it and use dlopen instead. 10 */ 11 12 #ifndef HAL_LINUX_UDEV_H_ 13 #define HAL_LINUX_UDEV_H_ 14 15 #include <dlfcn.h> 16 17 namespace mozilla { 18 19 struct udev; 20 struct udev_device; 21 struct udev_enumerate; 22 struct udev_list_entry; 23 struct udev_monitor; 24 25 class udev_lib { 26 public: 27 udev_lib() : lib(nullptr), udev(nullptr) { 28 // Be careful about ABI compat! 0 -> 1 didn't change any 29 // symbols this code relies on, per: 30 // https://lists.fedoraproject.org/pipermail/devel/2012-June/168227.html 31 const char* lib_names[] = {"libudev.so.0", "libudev.so.1"}; 32 // Check whether a library is already loaded so we don't load two 33 // conflicting libs. 34 for (unsigned i = 0; i < std::size(lib_names); i++) { 35 lib = dlopen(lib_names[i], RTLD_NOLOAD | RTLD_LAZY | RTLD_GLOBAL); 36 if (lib) { 37 break; 38 } 39 } 40 // If nothing loads the first time through, it means no version of libudev 41 // was already loaded. 42 if (!lib) { 43 for (unsigned i = 0; i < std::size(lib_names); i++) { 44 lib = dlopen(lib_names[i], RTLD_LAZY | RTLD_GLOBAL); 45 if (lib) { 46 break; 47 } 48 } 49 } 50 if (lib && LoadSymbols()) { 51 udev = udev_new(); 52 } 53 } 54 55 ~udev_lib() { 56 if (udev) { 57 udev_unref(udev); 58 } 59 60 if (lib) { 61 dlclose(lib); 62 } 63 } 64 65 explicit operator bool() { return udev; } 66 67 private: 68 #define DLSYM(s) \ 69 do { \ 70 (s) = (decltype(s))dlsym(lib, #s); \ 71 if (!(s)) return false; \ 72 } while (0) 73 74 bool LoadSymbols() { 75 DLSYM(udev_new); 76 DLSYM(udev_unref); 77 DLSYM(udev_device_unref); 78 DLSYM(udev_device_new_from_syspath); 79 DLSYM(udev_device_get_devnode); 80 DLSYM(udev_device_get_parent_with_subsystem_devtype); 81 DLSYM(udev_device_get_property_value); 82 DLSYM(udev_device_get_action); 83 DLSYM(udev_device_get_sysattr_value); 84 DLSYM(udev_enumerate_new); 85 DLSYM(udev_enumerate_unref); 86 DLSYM(udev_enumerate_add_match_subsystem); 87 DLSYM(udev_enumerate_scan_devices); 88 DLSYM(udev_enumerate_get_list_entry); 89 DLSYM(udev_list_entry_get_next); 90 DLSYM(udev_list_entry_get_name); 91 DLSYM(udev_monitor_new_from_netlink); 92 DLSYM(udev_monitor_filter_add_match_subsystem_devtype); 93 DLSYM(udev_monitor_enable_receiving); 94 DLSYM(udev_monitor_get_fd); 95 DLSYM(udev_monitor_receive_device); 96 DLSYM(udev_monitor_unref); 97 98 return true; 99 } 100 101 #undef DLSYM 102 103 void* lib; 104 105 public: 106 struct udev* udev; 107 108 // Function pointers returned from dlsym. 109 struct udev* (*udev_new)(void); 110 void (*udev_unref)(struct udev*); 111 112 void (*udev_device_unref)(struct udev_device*); 113 struct udev_device* (*udev_device_new_from_syspath)(struct udev*, 114 const char*); 115 const char* (*udev_device_get_devnode)(struct udev_device*); 116 struct udev_device* (*udev_device_get_parent_with_subsystem_devtype)( 117 struct udev_device*, const char*, const char*); 118 const char* (*udev_device_get_property_value)(struct udev_device*, 119 const char*); 120 const char* (*udev_device_get_action)(struct udev_device*); 121 const char* (*udev_device_get_sysattr_value)(struct udev_device*, 122 const char*); 123 124 struct udev_enumerate* (*udev_enumerate_new)(struct udev*); 125 void (*udev_enumerate_unref)(struct udev_enumerate*); 126 int (*udev_enumerate_add_match_subsystem)(struct udev_enumerate*, 127 const char*); 128 int (*udev_enumerate_scan_devices)(struct udev_enumerate*); 129 struct udev_list_entry* (*udev_enumerate_get_list_entry)( 130 struct udev_enumerate*); 131 132 struct udev_list_entry* (*udev_list_entry_get_next)(struct udev_list_entry*); 133 const char* (*udev_list_entry_get_name)(struct udev_list_entry*); 134 135 struct udev_monitor* (*udev_monitor_new_from_netlink)(struct udev*, 136 const char*); 137 int (*udev_monitor_filter_add_match_subsystem_devtype)(struct udev_monitor*, 138 const char*, 139 const char*); 140 int (*udev_monitor_enable_receiving)(struct udev_monitor*); 141 int (*udev_monitor_get_fd)(struct udev_monitor*); 142 struct udev_device* (*udev_monitor_receive_device)(struct udev_monitor*); 143 void (*udev_monitor_unref)(struct udev_monitor*); 144 }; 145 146 } // namespace mozilla 147 148 #endif // HAL_LINUX_UDEV_H_