tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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_