From: Andy Wingo Date: Sun, 19 Apr 2015 11:28:46 +0000 (+0200) Subject: Remove src/libudev X-Git-Tag: v219.0~113 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=e3b3286f2220835c297504af1eafe1801972d30b Remove src/libudev --- diff --git a/src/libudev/.gitignore b/src/libudev/.gitignore deleted file mode 100644 index 0c8a5d523..000000000 --- a/src/libudev/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/libudev.pc diff --git a/src/libudev/Makefile b/src/libudev/Makefile deleted file mode 120000 index d0b0e8e00..000000000 --- a/src/libudev/Makefile +++ /dev/null @@ -1 +0,0 @@ -../Makefile \ No newline at end of file diff --git a/src/libudev/libudev-device-internal.h b/src/libudev/libudev-device-internal.h deleted file mode 100644 index 18ae7a93f..000000000 --- a/src/libudev/libudev-device-internal.h +++ /dev/null @@ -1,62 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2008-2012 Kay Sievers - Copyright 2015 Tom Gundersen - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#pragma once - -#include "libudev.h" -#include "sd-device.h" - -/** - * udev_device: - * - * Opaque object representing one kernel sys device. - */ -struct udev_device { - struct udev *udev; - - /* real device object */ - sd_device *device; - - /* legacy */ - int refcount; - - struct udev_device *parent; - bool parent_set; - - struct udev_list properties; - uint64_t properties_generation; - struct udev_list tags; - uint64_t tags_generation; - struct udev_list devlinks; - uint64_t devlinks_generation; - struct udev_list sysattrs; - bool sysattrs_read; -}; - -struct udev_device *udev_device_new(struct udev *udev); - -#define assert_return_errno(expr, r, err) \ - do { \ - if (_unlikely_(!(expr))) { \ - log_assert_failed_return(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \ - errno = err; \ - return (r); \ - } \ - } while (false) diff --git a/src/libudev/libudev-device-private.c b/src/libudev/libudev-device-private.c deleted file mode 100644 index bb4d7e6da..000000000 --- a/src/libudev/libudev-device-private.c +++ /dev/null @@ -1,409 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2008-2012 Kay Sievers - Copyright 2015 Tom Gundersen - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include "libudev.h" -#include "libudev-private.h" -#include "libudev-device-internal.h" - -#include "device-private.h" - -int udev_device_tag_index(struct udev_device *udev_device, struct udev_device *udev_device_old, bool add) { - sd_device *device_old = NULL; - int r; - - assert(udev_device); - - if (udev_device_old) - device_old = udev_device_old->device; - - r = device_tag_index(udev_device->device, device_old, add); - if (r < 0) - return r; - - return 0; -} - -int udev_device_update_db(struct udev_device *udev_device) { - int r; - - assert(udev_device); - - r = device_update_db(udev_device->device); - if (r < 0) - return r; - - return 0; -} - -int udev_device_delete_db(struct udev_device *udev_device) { - int r; - - assert(udev_device); - - r = device_delete_db(udev_device->device); - if (r < 0) - return r; - - return 0; -} - -int udev_device_get_ifindex(struct udev_device *udev_device) { - int r, ifindex; - - assert(udev_device); - - r = sd_device_get_ifindex(udev_device->device, &ifindex); - if (r < 0) - return r; - - return ifindex; -} - -const char *udev_device_get_devpath_old(struct udev_device *udev_device) { - const char *devpath_old = NULL; - int r; - - assert(udev_device); - - r = sd_device_get_property_value(udev_device->device, "DEVPATH_OLD", &devpath_old); - if (r < 0 && r != -ENOENT) { - errno = -r; - return NULL; - } - - return devpath_old; -} - -mode_t udev_device_get_devnode_mode(struct udev_device *udev_device) { - mode_t mode; - int r; - - assert(udev_device); - - r = device_get_devnode_mode(udev_device->device, &mode); - if (r < 0) { - errno = -r; - return 0; - } - - return mode; -} - -uid_t udev_device_get_devnode_uid(struct udev_device *udev_device) { - uid_t uid; - int r; - - assert(udev_device); - - r = device_get_devnode_uid(udev_device->device, &uid); - if (r < 0) { - errno = -r; - return 0; - } - - return uid; -} - -gid_t udev_device_get_devnode_gid(struct udev_device *udev_device) { - gid_t gid; - int r; - - assert(udev_device); - - r = device_get_devnode_gid(udev_device->device, &gid); - if (r < 0) { - errno = -r; - return 0; - } - - return gid; -} - -void udev_device_ensure_usec_initialized(struct udev_device *udev_device, struct udev_device *udev_device_old) { - sd_device *device_old = NULL; - - assert(udev_device); - - if (udev_device_old) - device_old = udev_device_old->device; - - device_ensure_usec_initialized(udev_device->device, device_old); -} - -char **udev_device_get_properties_envp(struct udev_device *udev_device) { - char **envp; - int r; - - assert(udev_device); - - r = device_get_properties_strv(udev_device->device, &envp); - if (r < 0) { - errno = -r; - return NULL; - } - - return envp; -} - -ssize_t udev_device_get_properties_monitor_buf(struct udev_device *udev_device, const char **buf) { - const char *nulstr; - size_t len; - int r; - - assert(udev_device); - assert(buf); - - r = device_get_properties_nulstr(udev_device->device, (const uint8_t **)&nulstr, &len); - if (r < 0) - return r; - - *buf = nulstr; - - return len; -} - -int udev_device_get_devlink_priority(struct udev_device *udev_device) { - int priority, r; - - assert(udev_device); - - r = device_get_devlink_priority(udev_device->device, &priority); - if (r < 0) - return r; - - return priority; -} - -int udev_device_get_watch_handle(struct udev_device *udev_device) { - int handle, r; - - assert(udev_device); - - r = device_get_watch_handle(udev_device->device, &handle); - if (r < 0) - return r; - - return handle; -} - -void udev_device_set_is_initialized(struct udev_device *udev_device) { - assert(udev_device); - - device_set_is_initialized(udev_device->device); -} - -int udev_device_rename(struct udev_device *udev_device, const char *name) { - int r; - - assert(udev_device); - - r = device_rename(udev_device->device, name); - if (r < 0) - return r; - - return 0; -} - -struct udev_device *udev_device_shallow_clone(struct udev_device *old_device) { - struct udev_device *device; - int r; - - assert(old_device); - - device = udev_device_new(old_device->udev); - if (!device) - return NULL; - - r = device_shallow_clone(old_device->device, &device->device); - if (r < 0) { - udev_device_unref(device); - errno = -r; - return NULL; - } - - return device; -} - -struct udev_device *udev_device_clone_with_db(struct udev_device *udev_device_old) { - struct udev_device *udev_device; - int r; - - assert(udev_device_old); - - udev_device = udev_device_new(udev_device_old->udev); - if (!udev_device) - return NULL; - - r = device_clone_with_db(udev_device_old->device, &udev_device->device); - if (r < 0) { - udev_device_unref(udev_device); - errno = -r; - return NULL; - } - - return udev_device; -} - -struct udev_device *udev_device_new_from_nulstr(struct udev *udev, char *nulstr, ssize_t buflen) { - struct udev_device *device; - int r; - - device = udev_device_new(udev); - if (!device) - return NULL; - - r = device_new_from_nulstr(&device->device, (uint8_t*)nulstr, buflen); - if (r < 0) { - udev_device_unref(device); - errno = -r; - return NULL; - } - - return device; -} - -struct udev_device *udev_device_new_from_synthetic_event(struct udev *udev, const char *syspath, const char *action) { - struct udev_device *device; - int r; - - device = udev_device_new(udev); - if (!device) - return NULL; - - r = device_new_from_synthetic_event(&device->device, syspath, action); - if (r < 0) { - udev_device_unref(device); - errno = -r; - return NULL; - } - - return device; -} - -int udev_device_copy_properties(struct udev_device *udev_device_dst, struct udev_device *udev_device_src) { - int r; - - assert(udev_device_dst); - assert(udev_device_src); - - r = device_copy_properties(udev_device_dst->device, udev_device_src->device); - if (r < 0) - return r; - - return 0; -} - -const char *udev_device_get_id_filename(struct udev_device *udev_device) { - const char *filename; - int r; - - assert(udev_device); - - r = device_get_id_filename(udev_device->device, &filename); - if (r < 0) { - errno = -r; - return NULL; - } - - return filename; -} - -int udev_device_set_watch_handle(struct udev_device *udev_device, int handle) { - - assert(udev_device); - - device_set_watch_handle(udev_device->device, handle); - - return 0; -} - -void udev_device_set_db_persist(struct udev_device *udev_device) { - assert(udev_device); - - device_set_db_persist(udev_device->device); -} - -int udev_device_set_devlink_priority(struct udev_device *udev_device, int priority) { - assert(udev_device); - - device_set_devlink_priority(udev_device->device, priority); - - return 0; -} - -int udev_device_add_devlink(struct udev_device *udev_device, const char *devlink) { - int r; - - assert(udev_device); - - r = device_add_devlink(udev_device->device, devlink); - if (r < 0) - return r; - - return 0; -} - -int udev_device_add_property(struct udev_device *udev_device, const char *property, const char *value) { - int r; - - assert(udev_device); - - r = device_add_property(udev_device->device, property, value); - if (r < 0) - return r; - - return 0; -} - -int udev_device_add_tag(struct udev_device *udev_device, const char *tag) { - int r; - - assert(udev_device); - - r = device_add_tag(udev_device->device, tag); - if (r < 0) - return r; - - return 0; -} - -void udev_device_remove_tag(struct udev_device *udev_device, const char *tag) { - assert(udev_device); - - device_remove_tag(udev_device->device, tag); -} - -void udev_device_cleanup_tags_list(struct udev_device *udev_device) { - assert(udev_device); - - device_cleanup_tags(udev_device->device); -} - -void udev_device_cleanup_devlinks_list(struct udev_device *udev_device) { - assert(udev_device); - - device_cleanup_devlinks(udev_device->device); -} - -void udev_device_set_info_loaded(struct udev_device *udev_device) { - assert(udev_device); - - device_seal(udev_device->device); -} diff --git a/src/libudev/libudev-device.c b/src/libudev/libudev-device.c deleted file mode 100644 index a55cd258f..000000000 --- a/src/libudev/libudev-device.c +++ /dev/null @@ -1,949 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2008-2012 Kay Sievers - Copyright 2015 Tom Gundersen - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sd-device.h" -#include "device-util.h" -#include "device-private.h" - -#include "libudev.h" -#include "libudev-private.h" -#include "libudev-device-internal.h" - -/** - * SECTION:libudev-device - * @short_description: kernel sys devices - * - * Representation of kernel sys devices. Devices are uniquely identified - * by their syspath, every device has exactly one path in the kernel sys - * filesystem. Devices usually belong to a kernel subsystem, and have - * a unique name inside that subsystem. - */ - -/** - * udev_device_get_seqnum: - * @udev_device: udev device - * - * This is only valid if the device was received through a monitor. Devices read from - * sys do not have a sequence number. - * - * Returns: the kernel event sequence number, or 0 if there is no sequence number available. - **/ -_public_ unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device) -{ - const char *seqnum; - unsigned long long ret; - int r; - - assert_return_errno(udev_device, 0, EINVAL); - - r = sd_device_get_property_value(udev_device->device, "SEQNUM", &seqnum); - if (r == -ENOENT) - return 0; - else if (r < 0) { - errno = -r; - return 0; - } - - r = safe_atollu(seqnum, &ret); - if (r < 0) { - errno = -r; - return 0; - } - - return ret; -} - -/** - * udev_device_get_devnum: - * @udev_device: udev device - * - * Get the device major/minor number. - * - * Returns: the dev_t number. - **/ -_public_ dev_t udev_device_get_devnum(struct udev_device *udev_device) -{ - dev_t devnum; - int r; - - assert_return_errno(udev_device, makedev(0, 0), EINVAL); - - r = sd_device_get_devnum(udev_device->device, &devnum); - if (r < 0) { - errno = -r; - return makedev(0, 0); - } - - return devnum; -} - -/** - * udev_device_get_driver: - * @udev_device: udev device - * - * Get the kernel driver name. - * - * Returns: the driver name string, or #NULL if there is no driver attached. - **/ -_public_ const char *udev_device_get_driver(struct udev_device *udev_device) -{ - const char *driver; - int r; - - assert_return_errno(udev_device, NULL, EINVAL); - - r = sd_device_get_driver(udev_device->device, &driver); - if (r < 0) { - errno = -r; - return NULL; - } - - return driver; -} - -/** - * udev_device_get_devtype: - * @udev_device: udev device - * - * Retrieve the devtype string of the udev device. - * - * Returns: the devtype name of the udev device, or #NULL if it can not be determined - **/ -_public_ const char *udev_device_get_devtype(struct udev_device *udev_device) -{ - const char *devtype; - int r; - - assert_return_errno(udev_device, NULL, EINVAL); - - r = sd_device_get_devtype(udev_device->device, &devtype); - if (r < 0) { - errno = -r; - return NULL; - } - - return devtype; -} - -/** - * udev_device_get_subsystem: - * @udev_device: udev device - * - * Retrieve the subsystem string of the udev device. The string does not - * contain any "/". - * - * Returns: the subsystem name of the udev device, or #NULL if it can not be determined - **/ -_public_ const char *udev_device_get_subsystem(struct udev_device *udev_device) -{ - const char *subsystem; - int r; - - assert_return_errno(udev_device, NULL, EINVAL); - - r = sd_device_get_subsystem(udev_device->device, &subsystem); - if (r < 0) { - errno = -r; - return NULL; - } - - return subsystem; -} - -/** - * udev_device_get_property_value: - * @udev_device: udev device - * @key: property name - * - * Get the value of a given property. - * - * Returns: the property string, or #NULL if there is no such property. - **/ -_public_ const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key) -{ - const char *value = NULL; - int r; - - assert_return_errno(udev_device && key, NULL, EINVAL); - - r = sd_device_get_property_value(udev_device->device, key, &value); - if (r < 0) { - errno = -r; - return NULL; - } - - return value; -} - -struct udev_device *udev_device_new(struct udev *udev) { - struct udev_device *udev_device; - - assert_return_errno(udev, NULL, EINVAL); - - udev_device = new0(struct udev_device, 1); - if (!udev_device) { - errno = ENOMEM; - return NULL; - } - udev_device->refcount = 1; - udev_device->udev = udev; - udev_list_init(udev, &udev_device->properties, true); - udev_list_init(udev, &udev_device->tags, true); - udev_list_init(udev, &udev_device->sysattrs, true); - udev_list_init(udev, &udev_device->devlinks, true); - - return udev_device; -} - -/** - * udev_device_new_from_syspath: - * @udev: udev library context - * @syspath: sys device path including sys directory - * - * Create new udev device, and fill in information from the sys - * device and the udev database entry. The syspath is the absolute - * path to the device, including the sys mount point. - * - * The initial refcount is 1, and needs to be decremented to - * release the resources of the udev device. - * - * Returns: a new udev device, or #NULL, if it does not exist - **/ -_public_ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) { - struct udev_device *udev_device; - int r; - - udev_device = udev_device_new(udev); - if (!udev_device) - return NULL; - - r = sd_device_new_from_syspath(&udev_device->device, syspath); - if (r < 0) { - errno = -r; - udev_device_unref(udev_device); - return NULL; - } - - return udev_device; -} - -/** - * udev_device_new_from_devnum: - * @udev: udev library context - * @type: char or block device - * @devnum: device major/minor number - * - * Create new udev device, and fill in information from the sys - * device and the udev database entry. The device is looked-up - * by its major/minor number and type. Character and block device - * numbers are not unique across the two types. - * - * The initial refcount is 1, and needs to be decremented to - * release the resources of the udev device. - * - * Returns: a new udev device, or #NULL, if it does not exist - **/ -_public_ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum) -{ - struct udev_device *udev_device; - int r; - - udev_device = udev_device_new(udev); - if (!udev_device) - return NULL; - - r = sd_device_new_from_devnum(&udev_device->device, type, devnum); - if (r < 0) { - errno = -r; - udev_device_unref(udev_device); - return NULL; - } - - return udev_device; -} - -/** - * udev_device_new_from_device_id: - * @udev: udev library context - * @id: text string identifying a kernel device - * - * Create new udev device, and fill in information from the sys - * device and the udev database entry. The device is looked-up - * by a special string: - * b8:2 - block device major:minor - * c128:1 - char device major:minor - * n3 - network device ifindex - * +sound:card29 - kernel driver core subsystem:device name - * - * The initial refcount is 1, and needs to be decremented to - * release the resources of the udev device. - * - * Returns: a new udev device, or #NULL, if it does not exist - **/ -_public_ struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id) -{ - struct udev_device *udev_device; - int r; - - udev_device = udev_device_new(udev); - if (!udev_device) - return NULL; - - r = sd_device_new_from_device_id(&udev_device->device, id); - if (r < 0) { - errno = -r; - udev_device_unref(udev_device); - return NULL; - } - - return udev_device; -} - -/** - * udev_device_new_from_subsystem_sysname: - * @udev: udev library context - * @subsystem: the subsystem of the device - * @sysname: the name of the device - * - * Create new udev device, and fill in information from the sys device - * and the udev database entry. The device is looked up by the subsystem - * and name string of the device, like "mem" / "zero", or "block" / "sda". - * - * The initial refcount is 1, and needs to be decremented to - * release the resources of the udev device. - * - * Returns: a new udev device, or #NULL, if it does not exist - **/ -_public_ struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname) -{ - struct udev_device *udev_device; - int r; - - udev_device = udev_device_new(udev); - if (!udev_device) - return NULL; - - r = sd_device_new_from_subsystem_sysname(&udev_device->device, subsystem, sysname); - if (r < 0) { - errno = -r; - udev_device_unref(udev_device); - return NULL; - } - - return udev_device; -} - -/** - * udev_device_new_from_environment - * @udev: udev library context - * - * Create new udev device, and fill in information from the - * current process environment. This only works reliable if - * the process is called from a udev rule. It is usually used - * for tools executed from IMPORT= rules. - * - * The initial refcount is 1, and needs to be decremented to - * release the resources of the udev device. - * - * Returns: a new udev device, or #NULL, if it does not exist - **/ -_public_ struct udev_device *udev_device_new_from_environment(struct udev *udev) -{ - struct udev_device *udev_device; - int r; - - udev_device = udev_device_new(udev); - if (!udev_device) - return NULL; - - r = device_new_from_strv(&udev_device->device, environ); - if (r < 0) { - errno = -r; - udev_device_unref(udev_device); - return NULL; - } - - return udev_device; -} - -static struct udev_device *device_new_from_parent(struct udev_device *child) -{ - struct udev_device *parent; - int r; - - assert_return_errno(child, NULL, EINVAL); - - parent = udev_device_new(child->udev); - if (!parent) - return NULL; - - r = sd_device_get_parent(child->device, &parent->device); - if (r < 0) { - errno = -r; - udev_device_unref(parent); - return NULL; - } - - /* the parent is unref'ed with the child, so take a ref from libudev as well */ - sd_device_ref(parent->device); - - return parent; -} - -/** - * udev_device_get_parent: - * @udev_device: the device to start searching from - * - * Find the next parent device, and fill in information from the sys - * device and the udev database entry. - * - * Returned device is not referenced. It is attached to the child - * device, and will be cleaned up when the child device is cleaned up. - * - * It is not necessarily just the upper level directory, empty or not - * recognized sys directories are ignored. - * - * It can be called as many times as needed, without caring about - * references. - * - * Returns: a new udev device, or #NULL, if it no parent exist. - **/ -_public_ struct udev_device *udev_device_get_parent(struct udev_device *udev_device) -{ - assert_return_errno(udev_device, NULL, EINVAL); - - if (!udev_device->parent_set) { - udev_device->parent_set = true; - udev_device->parent = device_new_from_parent(udev_device); - } - - /* TODO: errno will differ here in case parent == NULL */ - return udev_device->parent; -} - -/** - * udev_device_get_parent_with_subsystem_devtype: - * @udev_device: udev device to start searching from - * @subsystem: the subsystem of the device - * @devtype: the type (DEVTYPE) of the device - * - * Find the next parent device, with a matching subsystem and devtype - * value, and fill in information from the sys device and the udev - * database entry. - * - * If devtype is #NULL, only subsystem is checked, and any devtype will - * match. - * - * Returned device is not referenced. It is attached to the child - * device, and will be cleaned up when the child device is cleaned up. - * - * It can be called as many times as needed, without caring about - * references. - * - * Returns: a new udev device, or #NULL if no matching parent exists. - **/ -_public_ struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype) -{ - sd_device *parent; - int r; - - assert_return_errno(udev_device, NULL, EINVAL); - - /* this relies on the fact that finding the subdevice of a parent or the - parent of a subdevice commute */ - - /* first find the correct sd_device */ - r = sd_device_get_parent_with_subsystem_devtype(udev_device->device, subsystem, devtype, &parent); - if (r < 0) { - errno = -r; - return NULL; - } - - /* then walk the chain of udev_device parents until the correspanding - one is found */ - while ((udev_device = udev_device_get_parent(udev_device))) { - if (udev_device->device == parent) - return udev_device; - } - - errno = ENOENT; - return NULL; -} - -/** - * udev_device_get_udev: - * @udev_device: udev device - * - * Retrieve the udev library context the device was created with. - * - * Returns: the udev library context - **/ -_public_ struct udev *udev_device_get_udev(struct udev_device *udev_device) -{ - assert_return_errno(udev_device, NULL, EINVAL); - - return udev_device->udev; -} - -/** - * udev_device_ref: - * @udev_device: udev device - * - * Take a reference of a udev device. - * - * Returns: the passed udev device - **/ -_public_ struct udev_device *udev_device_ref(struct udev_device *udev_device) -{ - if (udev_device) - udev_device->refcount++; - - return udev_device; -} - -/** - * udev_device_unref: - * @udev_device: udev device - * - * Drop a reference of a udev device. If the refcount reaches zero, - * the resources of the device will be released. - * - * Returns: #NULL - **/ -_public_ struct udev_device *udev_device_unref(struct udev_device *udev_device) -{ - if (udev_device && (-- udev_device->refcount) == 0) { - sd_device_unref(udev_device->device); - udev_device_unref(udev_device->parent); - - udev_list_cleanup(&udev_device->properties); - udev_list_cleanup(&udev_device->sysattrs); - udev_list_cleanup(&udev_device->tags); - udev_list_cleanup(&udev_device->devlinks); - - free(udev_device); - } - - return NULL; -} - -/** - * udev_device_get_devpath: - * @udev_device: udev device - * - * Retrieve the kernel devpath value of the udev device. The path - * does not contain the sys mount point, and starts with a '/'. - * - * Returns: the devpath of the udev device - **/ -_public_ const char *udev_device_get_devpath(struct udev_device *udev_device) -{ - const char *devpath; - int r; - - assert_return_errno(udev_device, NULL, EINVAL); - - r = sd_device_get_devpath(udev_device->device, &devpath); - if (r < 0) { - errno = -r; - return NULL; - } - - return devpath; -} - -/** - * udev_device_get_syspath: - * @udev_device: udev device - * - * Retrieve the sys path of the udev device. The path is an - * absolute path and starts with the sys mount point. - * - * Returns: the sys path of the udev device - **/ -_public_ const char *udev_device_get_syspath(struct udev_device *udev_device) -{ - const char *syspath; - int r; - - assert_return_errno(udev_device, NULL, EINVAL); - - r = sd_device_get_syspath(udev_device->device, &syspath); - if (r < 0) { - errno = -r; - return NULL; - } - - return syspath; -} - -/** - * udev_device_get_sysname: - * @udev_device: udev device - * - * Get the kernel device name in /sys. - * - * Returns: the name string of the device device - **/ -_public_ const char *udev_device_get_sysname(struct udev_device *udev_device) -{ - const char *sysname; - int r; - - assert_return_errno(udev_device, NULL, EINVAL); - - r = sd_device_get_sysname(udev_device->device, &sysname); - if (r < 0) { - errno = -r; - return NULL; - } - - return sysname; -} - -/** - * udev_device_get_sysnum: - * @udev_device: udev device - * - * Get the instance number of the device. - * - * Returns: the trailing number string of the device name - **/ -_public_ const char *udev_device_get_sysnum(struct udev_device *udev_device) -{ - const char *sysnum; - int r; - - assert_return_errno(udev_device, NULL, EINVAL); - - r = sd_device_get_sysnum(udev_device->device, &sysnum); - if (r < 0) { - errno = -r; - return NULL; - } - - return sysnum; -} - -/** - * udev_device_get_devnode: - * @udev_device: udev device - * - * Retrieve the device node file name belonging to the udev device. - * The path is an absolute path, and starts with the device directory. - * - * Returns: the device node file name of the udev device, or #NULL if no device node exists - **/ -_public_ const char *udev_device_get_devnode(struct udev_device *udev_device) -{ - const char *devnode; - int r; - - assert_return_errno(udev_device, NULL, EINVAL); - - r = sd_device_get_devname(udev_device->device, &devnode); - if (r < 0) { - errno = -r; - return NULL; - } - - return devnode; -} - -/** - * udev_device_get_devlinks_list_entry: - * @udev_device: udev device - * - * Retrieve the list of device links pointing to the device file of - * the udev device. The next list entry can be retrieved with - * udev_list_entry_get_next(), which returns #NULL if no more entries exist. - * The devlink path can be retrieved from the list entry by - * udev_list_entry_get_name(). The path is an absolute path, and starts with - * the device directory. - * - * Returns: the first entry of the device node link list - **/ -_public_ struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device) -{ - assert_return_errno(udev_device, NULL, EINVAL); - - if (device_get_devlinks_generation(udev_device->device) != udev_device->devlinks_generation) { - const char *devlink; - - udev_list_cleanup(&udev_device->devlinks); - - FOREACH_DEVICE_DEVLINK(udev_device->device, devlink) - udev_list_entry_add(&udev_device->devlinks, devlink, NULL); - - udev_device->devlinks_generation = device_get_devlinks_generation(udev_device->device); - } - - return udev_list_get_entry(&udev_device->devlinks); -} - -/** - * udev_device_get_event_properties_entry: - * @udev_device: udev device - * - * Retrieve the list of key/value device properties of the udev - * device. The next list entry can be retrieved with udev_list_entry_get_next(), - * which returns #NULL if no more entries exist. The property name - * can be retrieved from the list entry by udev_list_entry_get_name(), - * the property value by udev_list_entry_get_value(). - * - * Returns: the first entry of the property list - **/ -_public_ struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device) -{ - assert_return_errno(udev_device, NULL, EINVAL); - - if (device_get_properties_generation(udev_device->device) != udev_device->properties_generation) { - const char *key, *value; - - udev_list_cleanup(&udev_device->properties); - - FOREACH_DEVICE_PROPERTY(udev_device->device, key, value) - udev_list_entry_add(&udev_device->properties, key, value); - - udev_device->properties_generation = device_get_properties_generation(udev_device->device); - } - - return udev_list_get_entry(&udev_device->properties); -} - -/** - * udev_device_get_action: - * @udev_device: udev device - * - * This is only valid if the device was received through a monitor. Devices read from - * sys do not have an action string. Usual actions are: add, remove, change, online, - * offline. - * - * Returns: the kernel action value, or #NULL if there is no action value available. - **/ -_public_ const char *udev_device_get_action(struct udev_device *udev_device) { - const char *action = NULL; - int r; - - assert_return_errno(udev_device, NULL, EINVAL); - - r = sd_device_get_property_value(udev_device->device, "ACTION", &action); - if (r < 0 && r != -ENOENT) { - errno = -r; - return NULL; - } - - return action; -} - -/** - * udev_device_get_usec_since_initialized: - * @udev_device: udev device - * - * Return the number of microseconds passed since udev set up the - * device for the first time. - * - * This is only implemented for devices with need to store properties - * in the udev database. All other devices return 0 here. - * - * Returns: the number of microseconds since the device was first seen. - **/ -_public_ unsigned long long int udev_device_get_usec_since_initialized(struct udev_device *udev_device) -{ - usec_t ts; - int r; - - assert_return(udev_device, -EINVAL); - - r = sd_device_get_usec_since_initialized(udev_device->device, &ts); - if (r < 0) { - errno = EINVAL; - return 0; - } - - return ts; -} - -/** - * udev_device_get_sysattr_value: - * @udev_device: udev device - * @sysattr: attribute name - * - * The retrieved value is cached in the device. Repeated calls will return the same - * value and not open the attribute again. - * - * Returns: the content of a sys attribute file, or #NULL if there is no sys attribute value. - **/ -_public_ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr) -{ - const char *value; - int r; - - assert_return_errno(udev_device, NULL, EINVAL); - - r = sd_device_get_sysattr_value(udev_device->device, sysattr, &value); - if (r < 0) { - errno = -r; - return NULL; - } - - return value; -} - -/** - * udev_device_set_sysattr_value: - * @udev_device: udev device - * @sysattr: attribute name - * @value: new value to be set - * - * Update the contents of the sys attribute and the cached value of the device. - * - * Returns: Negative error code on failure or 0 on success. - **/ -_public_ int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, char *value) -{ - int r; - - assert_return(udev_device, -EINVAL); - - r = sd_device_set_sysattr_value(udev_device->device, sysattr, value); - if (r < 0) - return r; - - return 0; -} - -/** - * udev_device_get_sysattr_list_entry: - * @udev_device: udev device - * - * Retrieve the list of available sysattrs, with value being empty; - * This just return all available sysfs attributes for a particular - * device without reading their values. - * - * Returns: the first entry of the property list - **/ -_public_ struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device) -{ - assert_return_errno(udev_device, NULL, EINVAL); - - if (!udev_device->sysattrs_read) { - const char *sysattr; - - udev_list_cleanup(&udev_device->sysattrs); - - FOREACH_DEVICE_SYSATTR(udev_device->device, sysattr) - udev_list_entry_add(&udev_device->properties, sysattr, NULL); - - udev_device->sysattrs_read = true; - } - - return udev_list_get_entry(&udev_device->sysattrs); -} - -/** - * udev_device_get_is_initialized: - * @udev_device: udev device - * - * Check if udev has already handled the device and has set up - * device node permissions and context, or has renamed a network - * device. - * - * This is only implemented for devices with a device node - * or network interfaces. All other devices return 1 here. - * - * Returns: 1 if the device is set up. 0 otherwise. - **/ -_public_ int udev_device_get_is_initialized(struct udev_device *udev_device) -{ - int r, initialized; - - assert_return(udev_device, -EINVAL); - - r = sd_device_get_is_initialized(udev_device->device, &initialized); - if (r < 0) { - errno = -r; - - return 0; - } - - return initialized; -} - -/** - * udev_device_get_tags_list_entry: - * @udev_device: udev device - * - * Retrieve the list of tags attached to the udev device. The next - * list entry can be retrieved with udev_list_entry_get_next(), - * which returns #NULL if no more entries exist. The tag string - * can be retrieved from the list entry by udev_list_entry_get_name(). - * - * Returns: the first entry of the tag list - **/ -_public_ struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device) -{ - assert_return_errno(udev_device, NULL, EINVAL); - - if (device_get_tags_generation(udev_device->device) != udev_device->tags_generation) { - const char *tag; - - udev_list_cleanup(&udev_device->tags); - - FOREACH_DEVICE_TAG(udev_device->device, tag) - udev_list_entry_add(&udev_device->tags, tag, NULL); - - udev_device->tags_generation = device_get_tags_generation(udev_device->device); - } - - return udev_list_get_entry(&udev_device->tags); -} - -/** - * udev_device_has_tag: - * @udev_device: udev device - * @tag: tag name - * - * Check if a given device has a certain tag associated. - * - * Returns: 1 if the tag is found. 0 otherwise. - **/ -_public_ int udev_device_has_tag(struct udev_device *udev_device, const char *tag) -{ - assert_return(udev_device, 0); - - return sd_device_has_tag(udev_device->device, tag); -} diff --git a/src/libudev/libudev-enumerate.c b/src/libudev/libudev-enumerate.c deleted file mode 100644 index 4e6e47cde..000000000 --- a/src/libudev/libudev-enumerate.c +++ /dev/null @@ -1,968 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2008-2012 Kay Sievers - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libudev.h" -#include "libudev-private.h" - -/** - * SECTION:libudev-enumerate - * @short_description: lookup and sort sys devices - * - * Lookup devices in the sys filesystem, filter devices by properties, - * and return a sorted list of devices. - */ - -struct syspath { - char *syspath; - size_t len; -}; - -/** - * udev_enumerate: - * - * Opaque object representing one device lookup/sort context. - */ -struct udev_enumerate { - struct udev *udev; - int refcount; - struct udev_list sysattr_match_list; - struct udev_list sysattr_nomatch_list; - struct udev_list subsystem_match_list; - struct udev_list subsystem_nomatch_list; - struct udev_list sysname_match_list; - struct udev_list properties_match_list; - struct udev_list tags_match_list; - struct udev_device *parent_match; - struct udev_list devices_list; - struct syspath *devices; - unsigned int devices_cur; - unsigned int devices_max; - bool devices_uptodate:1; - bool match_is_initialized; -}; - -/** - * udev_enumerate_new: - * @udev: udev library context - * - * Create an enumeration context to scan /sys. - * - * Returns: an enumeration context. - **/ -_public_ struct udev_enumerate *udev_enumerate_new(struct udev *udev) -{ - struct udev_enumerate *udev_enumerate; - - if (udev == NULL) - return NULL; - udev_enumerate = new0(struct udev_enumerate, 1); - if (udev_enumerate == NULL) - return NULL; - udev_enumerate->refcount = 1; - udev_enumerate->udev = udev; - udev_list_init(udev, &udev_enumerate->sysattr_match_list, false); - udev_list_init(udev, &udev_enumerate->sysattr_nomatch_list, false); - udev_list_init(udev, &udev_enumerate->subsystem_match_list, true); - udev_list_init(udev, &udev_enumerate->subsystem_nomatch_list, true); - udev_list_init(udev, &udev_enumerate->sysname_match_list, true); - udev_list_init(udev, &udev_enumerate->properties_match_list, false); - udev_list_init(udev, &udev_enumerate->tags_match_list, true); - udev_list_init(udev, &udev_enumerate->devices_list, false); - return udev_enumerate; -} - -/** - * udev_enumerate_ref: - * @udev_enumerate: context - * - * Take a reference of a enumeration context. - * - * Returns: the passed enumeration context - **/ -_public_ struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate) -{ - if (udev_enumerate == NULL) - return NULL; - udev_enumerate->refcount++; - return udev_enumerate; -} - -/** - * udev_enumerate_unref: - * @udev_enumerate: context - * - * Drop a reference of an enumeration context. If the refcount reaches zero, - * all resources of the enumeration context will be released. - * - * Returns: #NULL - **/ -_public_ struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate) -{ - unsigned int i; - - if (udev_enumerate == NULL) - return NULL; - udev_enumerate->refcount--; - if (udev_enumerate->refcount > 0) - return NULL; - udev_list_cleanup(&udev_enumerate->sysattr_match_list); - udev_list_cleanup(&udev_enumerate->sysattr_nomatch_list); - udev_list_cleanup(&udev_enumerate->subsystem_match_list); - udev_list_cleanup(&udev_enumerate->subsystem_nomatch_list); - udev_list_cleanup(&udev_enumerate->sysname_match_list); - udev_list_cleanup(&udev_enumerate->properties_match_list); - udev_list_cleanup(&udev_enumerate->tags_match_list); - udev_device_unref(udev_enumerate->parent_match); - udev_list_cleanup(&udev_enumerate->devices_list); - for (i = 0; i < udev_enumerate->devices_cur; i++) - free(udev_enumerate->devices[i].syspath); - free(udev_enumerate->devices); - free(udev_enumerate); - return NULL; -} - -/** - * udev_enumerate_get_udev: - * @udev_enumerate: context - * - * Get the udev library context. - * - * Returns: a pointer to the context. - */ -_public_ struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate) -{ - if (udev_enumerate == NULL) - return NULL; - return udev_enumerate->udev; -} - -static int syspath_add(struct udev_enumerate *udev_enumerate, const char *syspath) -{ - char *path; - struct syspath *entry; - - /* double array size if needed */ - if (udev_enumerate->devices_cur >= udev_enumerate->devices_max) { - struct syspath *buf; - unsigned int add; - - add = udev_enumerate->devices_max; - if (add < 1024) - add = 1024; - buf = realloc(udev_enumerate->devices, (udev_enumerate->devices_max + add) * sizeof(struct syspath)); - if (buf == NULL) - return -ENOMEM; - udev_enumerate->devices = buf; - udev_enumerate->devices_max += add; - } - - path = strdup(syspath); - if (path == NULL) - return -ENOMEM; - entry = &udev_enumerate->devices[udev_enumerate->devices_cur]; - entry->syspath = path; - entry->len = strlen(path); - udev_enumerate->devices_cur++; - udev_enumerate->devices_uptodate = false; - return 0; -} - -static int syspath_cmp(const void *p1, const void *p2) -{ - const struct syspath *path1 = p1; - const struct syspath *path2 = p2; - size_t len; - int ret; - - len = MIN(path1->len, path2->len); - ret = memcmp(path1->syspath, path2->syspath, len); - if (ret == 0) { - if (path1->len < path2->len) - ret = -1; - else if (path1->len > path2->len) - ret = 1; - } - return ret; -} - -/* For devices that should be moved to the absolute end of the list */ -static bool devices_delay_end(struct udev *udev, const char *syspath) -{ - static const char *delay_device_list[] = { - "/block/md", - "/block/dm-", - NULL - }; - int i; - - for (i = 0; delay_device_list[i] != NULL; i++) { - if (strstr(syspath + strlen("/sys"), delay_device_list[i]) != NULL) - return true; - } - return false; -} - -/* For devices that should just be moved a little bit later, just - * before the point where some common path prefix changes. Returns the - * number of characters that make up that common prefix */ -static size_t devices_delay_later(struct udev *udev, const char *syspath) -{ - const char *c; - - /* For sound cards the control device must be enumerated last - * to make sure it's the final device node that gets ACLs - * applied. Applications rely on this fact and use ACL changes - * on the control node as an indicator that the ACL change of - * the entire sound card completed. The kernel makes this - * guarantee when creating those devices, and hence we should - * too when enumerating them. */ - - if ((c = strstr(syspath, "/sound/card"))) { - c += 11; - c += strcspn(c, "/"); - - if (startswith(c, "/controlC")) - return c - syspath + 1; - } - - return 0; -} - -/** - * udev_enumerate_get_list_entry: - * @udev_enumerate: context - * - * Get the first entry of the sorted list of device paths. - * - * Returns: a udev_list_entry. - */ -_public_ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate) -{ - if (udev_enumerate == NULL) - return NULL; - if (!udev_enumerate->devices_uptodate) { - unsigned int i; - int move_later = -1; - unsigned int max; - struct syspath *prev = NULL; - size_t move_later_prefix = 0; - - udev_list_cleanup(&udev_enumerate->devices_list); - qsort_safe(udev_enumerate->devices, udev_enumerate->devices_cur, sizeof(struct syspath), syspath_cmp); - - max = udev_enumerate->devices_cur; - for (i = 0; i < max; i++) { - struct syspath *entry = &udev_enumerate->devices[i]; - - /* skip duplicated entries */ - if (prev != NULL && - entry->len == prev->len && - memcmp(entry->syspath, prev->syspath, entry->len) == 0) - continue; - prev = entry; - - /* skip to be delayed devices, and add them to the end of the list */ - if (devices_delay_end(udev_enumerate->udev, entry->syspath)) { - syspath_add(udev_enumerate, entry->syspath); - /* need to update prev here for the case realloc() gives a different address */ - prev = &udev_enumerate->devices[i]; - continue; - } - - /* skip to be delayed devices, and move the to - * the point where the prefix changes. We can - * only move one item at a time. */ - if (move_later == -1) { - move_later_prefix = devices_delay_later(udev_enumerate->udev, entry->syspath); - - if (move_later_prefix > 0) { - move_later = i; - continue; - } - } - - if ((move_later >= 0) && - !strneq(entry->syspath, udev_enumerate->devices[move_later].syspath, move_later_prefix)) { - - udev_list_entry_add(&udev_enumerate->devices_list, - udev_enumerate->devices[move_later].syspath, NULL); - move_later = -1; - } - - udev_list_entry_add(&udev_enumerate->devices_list, entry->syspath, NULL); - } - - if (move_later >= 0) - udev_list_entry_add(&udev_enumerate->devices_list, - udev_enumerate->devices[move_later].syspath, NULL); - - /* add and cleanup delayed devices from end of list */ - for (i = max; i < udev_enumerate->devices_cur; i++) { - struct syspath *entry = &udev_enumerate->devices[i]; - - udev_list_entry_add(&udev_enumerate->devices_list, entry->syspath, NULL); - free(entry->syspath); - } - udev_enumerate->devices_cur = max; - - udev_enumerate->devices_uptodate = true; - } - return udev_list_get_entry(&udev_enumerate->devices_list); -} - -/** - * udev_enumerate_add_match_subsystem: - * @udev_enumerate: context - * @subsystem: filter for a subsystem of the device to include in the list - * - * Match only devices belonging to a certain kernel subsystem. - * - * Returns: 0 on success, otherwise a negative error value. - */ -_public_ int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) -{ - if (udev_enumerate == NULL) - return -EINVAL; - if (subsystem == NULL) - return 0; - if (udev_list_entry_add(&udev_enumerate->subsystem_match_list, subsystem, NULL) == NULL) - return -ENOMEM; - return 0; -} - -/** - * udev_enumerate_add_nomatch_subsystem: - * @udev_enumerate: context - * @subsystem: filter for a subsystem of the device to exclude from the list - * - * Match only devices not belonging to a certain kernel subsystem. - * - * Returns: 0 on success, otherwise a negative error value. - */ -_public_ int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) -{ - if (udev_enumerate == NULL) - return -EINVAL; - if (subsystem == NULL) - return 0; - if (udev_list_entry_add(&udev_enumerate->subsystem_nomatch_list, subsystem, NULL) == NULL) - return -ENOMEM; - return 0; -} - -/** - * udev_enumerate_add_match_sysattr: - * @udev_enumerate: context - * @sysattr: filter for a sys attribute at the device to include in the list - * @value: optional value of the sys attribute - * - * Match only devices with a certain /sys device attribute. - * - * Returns: 0 on success, otherwise a negative error value. - */ -_public_ int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) -{ - if (udev_enumerate == NULL) - return -EINVAL; - if (sysattr == NULL) - return 0; - if (udev_list_entry_add(&udev_enumerate->sysattr_match_list, sysattr, value) == NULL) - return -ENOMEM; - return 0; -} - -/** - * udev_enumerate_add_nomatch_sysattr: - * @udev_enumerate: context - * @sysattr: filter for a sys attribute at the device to exclude from the list - * @value: optional value of the sys attribute - * - * Match only devices not having a certain /sys device attribute. - * - * Returns: 0 on success, otherwise a negative error value. - */ -_public_ int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) -{ - if (udev_enumerate == NULL) - return -EINVAL; - if (sysattr == NULL) - return 0; - if (udev_list_entry_add(&udev_enumerate->sysattr_nomatch_list, sysattr, value) == NULL) - return -ENOMEM; - return 0; -} - -static int match_sysattr_value(struct udev_device *dev, const char *sysattr, const char *match_val) -{ - const char *val = NULL; - bool match = false; - - val = udev_device_get_sysattr_value(dev, sysattr); - if (val == NULL) - goto exit; - if (match_val == NULL) { - match = true; - goto exit; - } - if (fnmatch(match_val, val, 0) == 0) { - match = true; - goto exit; - } -exit: - return match; -} - -/** - * udev_enumerate_add_match_property: - * @udev_enumerate: context - * @property: filter for a property of the device to include in the list - * @value: value of the property - * - * Match only devices with a certain property. - * - * Returns: 0 on success, otherwise a negative error value. - */ -_public_ int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value) -{ - if (udev_enumerate == NULL) - return -EINVAL; - if (property == NULL) - return 0; - if (udev_list_entry_add(&udev_enumerate->properties_match_list, property, value) == NULL) - return -ENOMEM; - return 0; -} - -/** - * udev_enumerate_add_match_tag: - * @udev_enumerate: context - * @tag: filter for a tag of the device to include in the list - * - * Match only devices with a certain tag. - * - * Returns: 0 on success, otherwise a negative error value. - */ -_public_ int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag) -{ - if (udev_enumerate == NULL) - return -EINVAL; - if (tag == NULL) - return 0; - if (udev_list_entry_add(&udev_enumerate->tags_match_list, tag, NULL) == NULL) - return -ENOMEM; - return 0; -} - -/** - * udev_enumerate_add_match_parent: - * @udev_enumerate: context - * @parent: parent device where to start searching - * - * Return the devices on the subtree of one given device. The parent - * itself is included in the list. - * - * A reference for the device is held until the udev_enumerate context - * is cleaned up. - * - * Returns: 0 on success, otherwise a negative error value. - */ -_public_ int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent) -{ - if (udev_enumerate == NULL) - return -EINVAL; - if (parent == NULL) - return 0; - if (udev_enumerate->parent_match != NULL) - udev_device_unref(udev_enumerate->parent_match); - udev_enumerate->parent_match = udev_device_ref(parent); - return 0; -} - -/** - * udev_enumerate_add_match_is_initialized: - * @udev_enumerate: context - * - * Match only devices which udev has set up already. This makes - * sure, that the device node permissions and context are properly set - * and that network devices are fully renamed. - * - * Usually, devices which are found in the kernel but not already - * handled by udev, have still pending events. Services should subscribe - * to monitor events and wait for these devices to become ready, instead - * of using uninitialized devices. - * - * For now, this will not affect devices which do not have a device node - * and are not network interfaces. - * - * Returns: 0 on success, otherwise a negative error value. - */ -_public_ int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate) -{ - if (udev_enumerate == NULL) - return -EINVAL; - udev_enumerate->match_is_initialized = true; - return 0; -} - -/** - * udev_enumerate_add_match_sysname: - * @udev_enumerate: context - * @sysname: filter for the name of the device to include in the list - * - * Match only devices with a given /sys device name. - * - * Returns: 0 on success, otherwise a negative error value. - */ -_public_ int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname) -{ - if (udev_enumerate == NULL) - return -EINVAL; - if (sysname == NULL) - return 0; - if (udev_list_entry_add(&udev_enumerate->sysname_match_list, sysname, NULL) == NULL) - return -ENOMEM; - return 0; -} - -static bool match_sysattr(struct udev_enumerate *udev_enumerate, struct udev_device *dev) -{ - struct udev_list_entry *list_entry; - - /* skip list */ - udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->sysattr_nomatch_list)) { - if (match_sysattr_value(dev, udev_list_entry_get_name(list_entry), - udev_list_entry_get_value(list_entry))) - return false; - } - /* include list */ - if (udev_list_get_entry(&udev_enumerate->sysattr_match_list) != NULL) { - udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->sysattr_match_list)) { - /* anything that does not match, will make it FALSE */ - if (!match_sysattr_value(dev, udev_list_entry_get_name(list_entry), - udev_list_entry_get_value(list_entry))) - return false; - } - return true; - } - return true; -} - -static bool match_property(struct udev_enumerate *udev_enumerate, struct udev_device *dev) -{ - struct udev_list_entry *list_entry; - bool match = false; - - /* no match always matches */ - if (udev_list_get_entry(&udev_enumerate->properties_match_list) == NULL) - return true; - - /* loop over matches */ - udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->properties_match_list)) { - const char *match_key = udev_list_entry_get_name(list_entry); - const char *match_value = udev_list_entry_get_value(list_entry); - struct udev_list_entry *property_entry; - - /* loop over device properties */ - udev_list_entry_foreach(property_entry, udev_device_get_properties_list_entry(dev)) { - const char *dev_key = udev_list_entry_get_name(property_entry); - const char *dev_value = udev_list_entry_get_value(property_entry); - - if (fnmatch(match_key, dev_key, 0) != 0) - continue; - if (match_value == NULL && dev_value == NULL) { - match = true; - goto out; - } - if (match_value == NULL || dev_value == NULL) - continue; - if (fnmatch(match_value, dev_value, 0) == 0) { - match = true; - goto out; - } - } - } -out: - return match; -} - -static bool match_tag(struct udev_enumerate *udev_enumerate, struct udev_device *dev) -{ - struct udev_list_entry *list_entry; - - /* no match always matches */ - if (udev_list_get_entry(&udev_enumerate->tags_match_list) == NULL) - return true; - - /* loop over matches */ - udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->tags_match_list)) - if (!udev_device_has_tag(dev, udev_list_entry_get_name(list_entry))) - return false; - - return true; -} - -static bool match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *dev) -{ - if (udev_enumerate->parent_match == NULL) - return true; - - return startswith(udev_device_get_devpath(dev), udev_device_get_devpath(udev_enumerate->parent_match)); -} - -static bool match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname) -{ - struct udev_list_entry *list_entry; - - if (udev_list_get_entry(&udev_enumerate->sysname_match_list) == NULL) - return true; - - udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->sysname_match_list)) { - if (fnmatch(udev_list_entry_get_name(list_entry), sysname, 0) != 0) - continue; - return true; - } - return false; -} - -static int scan_dir_and_add_devices(struct udev_enumerate *udev_enumerate, - const char *basedir, const char *subdir1, const char *subdir2) -{ - char path[UTIL_PATH_SIZE]; - size_t l; - char *s; - DIR *dir; - struct dirent *dent; - - s = path; - l = strpcpyl(&s, sizeof(path), "/sys/", basedir, NULL); - if (subdir1 != NULL) - l = strpcpyl(&s, l, "/", subdir1, NULL); - if (subdir2 != NULL) - strpcpyl(&s, l, "/", subdir2, NULL); - dir = opendir(path); - if (dir == NULL) - return -ENOENT; - for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { - char syspath[UTIL_PATH_SIZE]; - struct udev_device *dev; - - if (dent->d_name[0] == '.') - continue; - - if (!match_sysname(udev_enumerate, dent->d_name)) - continue; - - strscpyl(syspath, sizeof(syspath), path, "/", dent->d_name, NULL); - dev = udev_device_new_from_syspath(udev_enumerate->udev, syspath); - if (dev == NULL) - continue; - - if (udev_enumerate->match_is_initialized) { - /* - * All devices with a device node or network interfaces - * possibly need udev to adjust the device node permission - * or context, or rename the interface before it can be - * reliably used from other processes. - * - * For now, we can only check these types of devices, we - * might not store a database, and have no way to find out - * for all other types of devices. - */ - if (!udev_device_get_is_initialized(dev) && - (major(udev_device_get_devnum(dev)) > 0 || udev_device_get_ifindex(dev) > 0)) - goto nomatch; - } - if (!match_parent(udev_enumerate, dev)) - goto nomatch; - if (!match_tag(udev_enumerate, dev)) - goto nomatch; - if (!match_property(udev_enumerate, dev)) - goto nomatch; - if (!match_sysattr(udev_enumerate, dev)) - goto nomatch; - - syspath_add(udev_enumerate, udev_device_get_syspath(dev)); -nomatch: - udev_device_unref(dev); - } - closedir(dir); - return 0; -} - -static bool match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) -{ - struct udev_list_entry *list_entry; - - if (!subsystem) - return false; - - udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->subsystem_nomatch_list)) { - if (fnmatch(udev_list_entry_get_name(list_entry), subsystem, 0) == 0) - return false; - } - - if (udev_list_get_entry(&udev_enumerate->subsystem_match_list) != NULL) { - udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->subsystem_match_list)) { - if (fnmatch(udev_list_entry_get_name(list_entry), subsystem, 0) == 0) - return true; - } - return false; - } - - return true; -} - -static int scan_dir(struct udev_enumerate *udev_enumerate, const char *basedir, const char *subdir, const char *subsystem) -{ - char path[UTIL_PATH_SIZE]; - DIR *dir; - struct dirent *dent; - - strscpyl(path, sizeof(path), "/sys/", basedir, NULL); - dir = opendir(path); - if (dir == NULL) - return -1; - for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { - if (dent->d_name[0] == '.') - continue; - if (!match_subsystem(udev_enumerate, subsystem != NULL ? subsystem : dent->d_name)) - continue; - scan_dir_and_add_devices(udev_enumerate, basedir, dent->d_name, subdir); - } - closedir(dir); - return 0; -} - -/** - * udev_enumerate_add_syspath: - * @udev_enumerate: context - * @syspath: path of a device - * - * Add a device to the list of devices, to retrieve it back sorted in dependency order. - * - * Returns: 0 on success, otherwise a negative error value. - */ -_public_ int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath) -{ - struct udev_device *udev_device; - - if (udev_enumerate == NULL) - return -EINVAL; - if (syspath == NULL) - return 0; - /* resolve to real syspath */ - udev_device = udev_device_new_from_syspath(udev_enumerate->udev, syspath); - if (udev_device == NULL) - return -EINVAL; - syspath_add(udev_enumerate, udev_device_get_syspath(udev_device)); - udev_device_unref(udev_device); - return 0; -} - -static int scan_devices_tags(struct udev_enumerate *udev_enumerate) -{ - struct udev_list_entry *list_entry; - - /* scan only tagged devices, use tags reverse-index, instead of searching all devices in /sys */ - udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->tags_match_list)) { - DIR *dir; - struct dirent *dent; - char path[UTIL_PATH_SIZE]; - - strscpyl(path, sizeof(path), "/run/udev/tags/", udev_list_entry_get_name(list_entry), NULL); - dir = opendir(path); - if (dir == NULL) - continue; - for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { - struct udev_device *dev; - - if (dent->d_name[0] == '.') - continue; - - dev = udev_device_new_from_device_id(udev_enumerate->udev, dent->d_name); - if (dev == NULL) - continue; - - if (!match_subsystem(udev_enumerate, udev_device_get_subsystem(dev))) - goto nomatch; - if (!match_sysname(udev_enumerate, udev_device_get_sysname(dev))) - goto nomatch; - if (!match_parent(udev_enumerate, dev)) - goto nomatch; - if (!match_property(udev_enumerate, dev)) - goto nomatch; - if (!match_sysattr(udev_enumerate, dev)) - goto nomatch; - - syspath_add(udev_enumerate, udev_device_get_syspath(dev)); -nomatch: - udev_device_unref(dev); - } - closedir(dir); - } - return 0; -} - -static int parent_add_child(struct udev_enumerate *enumerate, const char *path) -{ - struct udev_device *dev; - int r = 0; - - dev = udev_device_new_from_syspath(enumerate->udev, path); - if (dev == NULL) - return -ENODEV; - - if (!match_subsystem(enumerate, udev_device_get_subsystem(dev))) - goto nomatch; - if (!match_sysname(enumerate, udev_device_get_sysname(dev))) - goto nomatch; - if (!match_property(enumerate, dev)) - goto nomatch; - if (!match_sysattr(enumerate, dev)) - goto nomatch; - - syspath_add(enumerate, udev_device_get_syspath(dev)); - r = 1; - -nomatch: - udev_device_unref(dev); - return r; -} - -static int parent_crawl_children(struct udev_enumerate *enumerate, const char *path, int maxdepth) -{ - DIR *d; - struct dirent *dent; - - d = opendir(path); - if (d == NULL) - return -errno; - - for (dent = readdir(d); dent != NULL; dent = readdir(d)) { - char *child; - - if (dent->d_name[0] == '.') - continue; - if (dent->d_type != DT_DIR) - continue; - if (asprintf(&child, "%s/%s", path, dent->d_name) < 0) - continue; - parent_add_child(enumerate, child); - if (maxdepth > 0) - parent_crawl_children(enumerate, child, maxdepth-1); - free(child); - } - - closedir(d); - return 0; -} - -static int scan_devices_children(struct udev_enumerate *enumerate) -{ - const char *path; - - path = udev_device_get_syspath(enumerate->parent_match); - parent_add_child(enumerate, path); - return parent_crawl_children(enumerate, path, 256); -} - -static int scan_devices_all(struct udev_enumerate *udev_enumerate) -{ - struct stat statbuf; - - if (stat("/sys/subsystem", &statbuf) == 0) { - /* we have /subsystem/, forget all the old stuff */ - scan_dir(udev_enumerate, "subsystem", "devices", NULL); - } else { - scan_dir(udev_enumerate, "bus", "devices", NULL); - scan_dir(udev_enumerate, "class", NULL, NULL); - } - return 0; -} - -/** - * udev_enumerate_scan_devices: - * @udev_enumerate: udev enumeration context - * - * Scan /sys for all devices which match the given filters. No matches - * will return all currently available devices. - * - * Returns: 0 on success, otherwise a negative error value. - **/ -_public_ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) -{ - if (udev_enumerate == NULL) - return -EINVAL; - - /* efficiently lookup tags only, we maintain a reverse-index */ - if (udev_list_get_entry(&udev_enumerate->tags_match_list) != NULL) - return scan_devices_tags(udev_enumerate); - - /* walk the subtree of one parent device only */ - if (udev_enumerate->parent_match != NULL) - return scan_devices_children(udev_enumerate); - - /* scan devices of all subsystems */ - return scan_devices_all(udev_enumerate); -} - -/** - * udev_enumerate_scan_subsystems: - * @udev_enumerate: udev enumeration context - * - * Scan /sys for all kernel subsystems, including buses, classes, drivers. - * - * Returns: 0 on success, otherwise a negative error value. - **/ -_public_ int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate) -{ - struct stat statbuf; - const char *subsysdir; - - if (udev_enumerate == NULL) - return -EINVAL; - - /* all kernel modules */ - if (match_subsystem(udev_enumerate, "module")) - scan_dir_and_add_devices(udev_enumerate, "module", NULL, NULL); - - if (stat("/sys/subsystem", &statbuf) == 0) - subsysdir = "subsystem"; - else - subsysdir = "bus"; - - /* all subsystems (only buses support coldplug) */ - if (match_subsystem(udev_enumerate, "subsystem")) - scan_dir_and_add_devices(udev_enumerate, subsysdir, NULL, NULL); - - /* all subsystem drivers */ - if (match_subsystem(udev_enumerate, "drivers")) - scan_dir(udev_enumerate, subsysdir, "drivers", "drivers"); - return 0; -} diff --git a/src/libudev/libudev-hwdb.c b/src/libudev/libudev-hwdb.c deleted file mode 100644 index 98951fb85..000000000 --- a/src/libudev/libudev-hwdb.c +++ /dev/null @@ -1,144 +0,0 @@ -/*** - This file is part of systemd. - - Copyright Tom Gundersen - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include "libudev-private.h" -#include "sd-hwdb.h" -#include "hwdb-util.h" - -/** - * SECTION:libudev-hwdb - * @short_description: retrieve properties from the hardware database - * - * Libudev hardware database interface. - */ - -/** - * udev_hwdb: - * - * Opaque object representing the hardware database. - */ -struct udev_hwdb { - struct udev *udev; - int refcount; - - sd_hwdb *hwdb; - - struct udev_list properties_list; -}; - -/** - * udev_hwdb_new: - * @udev: udev library context - * - * Create a hardware database context to query properties for devices. - * - * Returns: a hwdb context. - **/ -_public_ struct udev_hwdb *udev_hwdb_new(struct udev *udev) { - _cleanup_hwdb_unref_ sd_hwdb *hwdb_internal = NULL; - struct udev_hwdb *hwdb; - int r; - - assert_return(udev, NULL); - - r = sd_hwdb_new(&hwdb_internal); - if (r < 0) - return NULL; - - hwdb = new0(struct udev_hwdb, 1); - if (!hwdb) - return NULL; - - hwdb->refcount = 1; - hwdb->hwdb = hwdb_internal; - hwdb_internal = NULL; - - udev_list_init(udev, &hwdb->properties_list, true); - - return hwdb; -} - -/** - * udev_hwdb_ref: - * @hwdb: context - * - * Take a reference of a hwdb context. - * - * Returns: the passed enumeration context - **/ -_public_ struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb) { - if (!hwdb) - return NULL; - hwdb->refcount++; - return hwdb; -} - -/** - * udev_hwdb_unref: - * @hwdb: context - * - * Drop a reference of a hwdb context. If the refcount reaches zero, - * all resources of the hwdb context will be released. - * - * Returns: #NULL - **/ -_public_ struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb) { - if (!hwdb) - return NULL; - hwdb->refcount--; - if (hwdb->refcount > 0) - return NULL; - sd_hwdb_unref(hwdb->hwdb); - udev_list_cleanup(&hwdb->properties_list); - free(hwdb); - return NULL; -} - -/** - * udev_hwdb_get_properties_list_entry: - * @hwdb: context - * @modalias: modalias string - * @flags: (unused) - * - * Lookup a matching device in the hardware database. The lookup key is a - * modalias string, whose formats are defined for the Linux kernel modules. - * Examples are: pci:v00008086d00001C2D*, usb:v04F2pB221*. The first entry - * of a list of retrieved properties is returned. - * - * Returns: a udev_list_entry. - */ -_public_ struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags) { - const char *key, *value; - - if (!hwdb || !modalias) { - errno = EINVAL; - return NULL; - } - - udev_list_cleanup(&hwdb->properties_list); - - SD_HWDB_FOREACH_PROPERTY(hwdb->hwdb, modalias, key, value) { - if (udev_list_entry_add(&hwdb->properties_list, key, value) == NULL) { - errno = ENOMEM; - return NULL; - } - } - - return udev_list_get_entry(&hwdb->properties_list); -} diff --git a/src/libudev/libudev-list.c b/src/libudev/libudev-list.c deleted file mode 100644 index 044ee3a0c..000000000 --- a/src/libudev/libudev-list.c +++ /dev/null @@ -1,352 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2008-2012 Kay Sievers - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include -#include -#include - -#include "libudev-private.h" - -/** - * SECTION:libudev-list - * @short_description: list operation - * - * Libudev list operations. - */ - -/** - * udev_list_entry: - * - * Opaque object representing one entry in a list. An entry contains - * contains a name, and optionally a value. - */ -struct udev_list_entry { - struct udev_list_node node; - struct udev_list *list; - char *name; - char *value; - int num; -}; - -/* the list's head points to itself if empty */ -void udev_list_node_init(struct udev_list_node *list) -{ - list->next = list; - list->prev = list; -} - -int udev_list_node_is_empty(struct udev_list_node *list) -{ - return list->next == list; -} - -static void udev_list_node_insert_between(struct udev_list_node *new, - struct udev_list_node *prev, - struct udev_list_node *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -void udev_list_node_append(struct udev_list_node *new, struct udev_list_node *list) -{ - udev_list_node_insert_between(new, list->prev, list); -} - -void udev_list_node_remove(struct udev_list_node *entry) -{ - struct udev_list_node *prev = entry->prev; - struct udev_list_node *next = entry->next; - - next->prev = prev; - prev->next = next; - - entry->prev = NULL; - entry->next = NULL; -} - -/* return list entry which embeds this node */ -static inline struct udev_list_entry *list_node_to_entry(struct udev_list_node *node) -{ - return container_of(node, struct udev_list_entry, node); -} - -void udev_list_init(struct udev *udev, struct udev_list *list, bool unique) -{ - memzero(list, sizeof(struct udev_list)); - list->udev = udev; - list->unique = unique; - udev_list_node_init(&list->node); -} - -/* insert entry into a list as the last element */ -static void udev_list_entry_append(struct udev_list_entry *new, struct udev_list *list) -{ - /* inserting before the list head make the node the last node in the list */ - udev_list_node_insert_between(&new->node, list->node.prev, &list->node); - new->list = list; -} - -/* insert entry into a list, before a given existing entry */ -static void udev_list_entry_insert_before(struct udev_list_entry *new, struct udev_list_entry *entry) -{ - udev_list_node_insert_between(&new->node, entry->node.prev, &entry->node); - new->list = entry->list; -} - -/* binary search in sorted array */ -static int list_search(struct udev_list *list, const char *name) -{ - unsigned int first, last; - - first = 0; - last = list->entries_cur; - while (first < last) { - unsigned int i; - int cmp; - - i = (first + last)/2; - cmp = strcmp(name, list->entries[i]->name); - if (cmp < 0) - last = i; - else if (cmp > 0) - first = i+1; - else - return i; - } - - /* not found, return negative insertion-index+1 */ - return -(first+1); -} - -struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char *name, const char *value) -{ - struct udev_list_entry *entry; - int i = 0; - - if (list->unique) { - /* lookup existing name or insertion-index */ - i = list_search(list, name); - if (i >= 0) { - entry = list->entries[i]; - - free(entry->value); - if (value == NULL) { - entry->value = NULL; - return entry; - } - entry->value = strdup(value); - if (entry->value == NULL) - return NULL; - return entry; - } - } - - /* add new name */ - entry = new0(struct udev_list_entry, 1); - if (entry == NULL) - return NULL; - entry->name = strdup(name); - if (entry->name == NULL) { - free(entry); - return NULL; - } - if (value != NULL) { - entry->value = strdup(value); - if (entry->value == NULL) { - free(entry->name); - free(entry); - return NULL; - } - } - - if (list->unique) { - /* allocate or enlarge sorted array if needed */ - if (list->entries_cur >= list->entries_max) { - struct udev_list_entry **entries; - unsigned int add; - - add = list->entries_max; - if (add < 1) - add = 64; - entries = realloc(list->entries, (list->entries_max + add) * sizeof(struct udev_list_entry *)); - if (entries == NULL) { - free(entry->name); - free(entry->value); - free(entry); - return NULL; - } - list->entries = entries; - list->entries_max += add; - } - - /* the negative i returned the insertion index */ - i = (-i)-1; - - /* insert into sorted list */ - if ((unsigned int)i < list->entries_cur) - udev_list_entry_insert_before(entry, list->entries[i]); - else - udev_list_entry_append(entry, list); - - /* insert into sorted array */ - memmove(&list->entries[i+1], &list->entries[i], - (list->entries_cur - i) * sizeof(struct udev_list_entry *)); - list->entries[i] = entry; - list->entries_cur++; - } else { - udev_list_entry_append(entry, list); - } - - return entry; -} - -void udev_list_entry_delete(struct udev_list_entry *entry) -{ - if (entry->list->entries != NULL) { - int i; - struct udev_list *list = entry->list; - - /* remove entry from sorted array */ - i = list_search(list, entry->name); - if (i >= 0) { - memmove(&list->entries[i], &list->entries[i+1], - ((list->entries_cur-1) - i) * sizeof(struct udev_list_entry *)); - list->entries_cur--; - } - } - - udev_list_node_remove(&entry->node); - free(entry->name); - free(entry->value); - free(entry); -} - -void udev_list_cleanup(struct udev_list *list) -{ - struct udev_list_entry *entry_loop; - struct udev_list_entry *entry_tmp; - - free(list->entries); - list->entries = NULL; - list->entries_cur = 0; - list->entries_max = 0; - udev_list_entry_foreach_safe(entry_loop, entry_tmp, udev_list_get_entry(list)) - udev_list_entry_delete(entry_loop); -} - -struct udev_list_entry *udev_list_get_entry(struct udev_list *list) -{ - if (udev_list_node_is_empty(&list->node)) - return NULL; - return list_node_to_entry(list->node.next); -} - -/** - * udev_list_entry_get_next: - * @list_entry: current entry - * - * Get the next entry from the list. - * - * Returns: udev_list_entry, #NULL if no more entries are available. - */ -_public_ struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry) -{ - struct udev_list_node *next; - - if (list_entry == NULL) - return NULL; - next = list_entry->node.next; - /* empty list or no more entries */ - if (next == &list_entry->list->node) - return NULL; - return list_node_to_entry(next); -} - -/** - * udev_list_entry_get_by_name: - * @list_entry: current entry - * @name: name string to match - * - * Lookup an entry in the list with a certain name. - * - * Returns: udev_list_entry, #NULL if no matching entry is found. - */ -_public_ struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name) -{ - int i; - - if (list_entry == NULL) - return NULL; - - if (!list_entry->list->unique) - return NULL; - - i = list_search(list_entry->list, name); - if (i < 0) - return NULL; - return list_entry->list->entries[i]; -} - -/** - * udev_list_entry_get_name: - * @list_entry: current entry - * - * Get the name of a list entry. - * - * Returns: the name string of this entry. - */ -_public_ const char *udev_list_entry_get_name(struct udev_list_entry *list_entry) -{ - if (list_entry == NULL) - return NULL; - return list_entry->name; -} - -/** - * udev_list_entry_get_value: - * @list_entry: current entry - * - * Get the value of list entry. - * - * Returns: the value string of this entry. - */ -_public_ const char *udev_list_entry_get_value(struct udev_list_entry *list_entry) -{ - if (list_entry == NULL) - return NULL; - return list_entry->value; -} - -int udev_list_entry_get_num(struct udev_list_entry *list_entry) -{ - if (list_entry == NULL) - return -EINVAL; - return list_entry->num; -} - -void udev_list_entry_set_num(struct udev_list_entry *list_entry, int num) -{ - if (list_entry == NULL) - return; - list_entry->num = num; -} diff --git a/src/libudev/libudev-monitor.c b/src/libudev/libudev-monitor.c deleted file mode 100644 index c48ac7890..000000000 --- a/src/libudev/libudev-monitor.c +++ /dev/null @@ -1,832 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2008-2012 Kay Sievers - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libudev.h" -#include "libudev-private.h" -#include "socket-util.h" -#include "missing.h" - -/** - * SECTION:libudev-monitor - * @short_description: device event source - * - * Connects to a device event source. - */ - -/** - * udev_monitor: - * - * Opaque object handling an event source. - */ -struct udev_monitor { - struct udev *udev; - int refcount; - int sock; - union sockaddr_union snl; - union sockaddr_union snl_trusted_sender; - union sockaddr_union snl_destination; - socklen_t addrlen; - struct udev_list filter_subsystem_list; - struct udev_list filter_tag_list; - bool bound; -}; - -enum udev_monitor_netlink_group { - UDEV_MONITOR_NONE, - UDEV_MONITOR_KERNEL, - UDEV_MONITOR_UDEV, -}; - -#define UDEV_MONITOR_MAGIC 0xfeedcafe -struct udev_monitor_netlink_header { - /* "libudev" prefix to distinguish libudev and kernel messages */ - char prefix[8]; - /* - * magic to protect against daemon <-> library message format mismatch - * used in the kernel from socket filter rules; needs to be stored in network order - */ - unsigned int magic; - /* total length of header structure known to the sender */ - unsigned int header_size; - /* properties string buffer */ - unsigned int properties_off; - unsigned int properties_len; - /* - * hashes of primary device properties strings, to let libudev subscribers - * use in-kernel socket filters; values need to be stored in network order - */ - unsigned int filter_subsystem_hash; - unsigned int filter_devtype_hash; - unsigned int filter_tag_bloom_hi; - unsigned int filter_tag_bloom_lo; -}; - -static struct udev_monitor *udev_monitor_new(struct udev *udev) -{ - struct udev_monitor *udev_monitor; - - udev_monitor = new0(struct udev_monitor, 1); - if (udev_monitor == NULL) - return NULL; - udev_monitor->refcount = 1; - udev_monitor->udev = udev; - udev_list_init(udev, &udev_monitor->filter_subsystem_list, false); - udev_list_init(udev, &udev_monitor->filter_tag_list, true); - return udev_monitor; -} - -/* we consider udev running when /dev is on devtmpfs */ -static bool udev_has_devtmpfs(struct udev *udev) { - - union file_handle_union h = FILE_HANDLE_INIT; - _cleanup_fclose_ FILE *f = NULL; - char line[LINE_MAX], *e; - int mount_id; - int r; - - r = name_to_handle_at(AT_FDCWD, "/dev", &h.handle, &mount_id, 0); - if (r < 0) { - if (errno != EOPNOTSUPP) - log_debug_errno(errno, "name_to_handle_at on /dev: %m"); - return false; - } - - f = fopen("/proc/self/mountinfo", "re"); - if (!f) - return false; - - FOREACH_LINE(line, f, return false) { - int mid; - - if (sscanf(line, "%i", &mid) != 1) - continue; - - if (mid != mount_id) - continue; - - e = strstr(line, " - "); - if (!e) - continue; - - /* accept any name that starts with the currently expected type */ - if (startswith(e + 3, "devtmpfs")) - return true; - } - - return false; -} - -struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const char *name, int fd) -{ - struct udev_monitor *udev_monitor; - unsigned int group; - - if (udev == NULL) - return NULL; - - if (name == NULL) - group = UDEV_MONITOR_NONE; - else if (streq(name, "udev")) { - /* - * We do not support subscribing to uevents if no instance of - * udev is running. Uevents would otherwise broadcast the - * processing data of the host into containers, which is not - * desired. - * - * Containers will currently not get any udev uevents, until - * a supporting infrastructure is available. - * - * We do not set a netlink multicast group here, so the socket - * will not receive any messages. - */ - if (access("/run/udev/control", F_OK) < 0 && !udev_has_devtmpfs(udev)) { - log_debug("the udev service seems not to be active, disable the monitor"); - group = UDEV_MONITOR_NONE; - } else - group = UDEV_MONITOR_UDEV; - } else if (streq(name, "kernel")) - group = UDEV_MONITOR_KERNEL; - else - return NULL; - - udev_monitor = udev_monitor_new(udev); - if (udev_monitor == NULL) - return NULL; - - if (fd < 0) { - udev_monitor->sock = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT); - if (udev_monitor->sock == -1) { - log_debug_errno(errno, "error getting socket: %m"); - free(udev_monitor); - return NULL; - } - } else { - udev_monitor->bound = true; - udev_monitor->sock = fd; - } - - udev_monitor->snl.nl.nl_family = AF_NETLINK; - udev_monitor->snl.nl.nl_groups = group; - - /* default destination for sending */ - udev_monitor->snl_destination.nl.nl_family = AF_NETLINK; - udev_monitor->snl_destination.nl.nl_groups = UDEV_MONITOR_UDEV; - - return udev_monitor; -} - -/** - * udev_monitor_new_from_netlink: - * @udev: udev library context - * @name: name of event source - * - * Create new udev monitor and connect to a specified event - * source. Valid sources identifiers are "udev" and "kernel". - * - * Applications should usually not connect directly to the - * "kernel" events, because the devices might not be useable - * at that time, before udev has configured them, and created - * device nodes. Accessing devices at the same time as udev, - * might result in unpredictable behavior. The "udev" events - * are sent out after udev has finished its event processing, - * all rules have been processed, and needed device nodes are - * created. - * - * The initial refcount is 1, and needs to be decremented to - * release the resources of the udev monitor. - * - * Returns: a new udev monitor, or #NULL, in case of an error - **/ -_public_ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name) -{ - return udev_monitor_new_from_netlink_fd(udev, name, -1); -} - -static inline void bpf_stmt(struct sock_filter *inss, unsigned int *i, - unsigned short code, unsigned int data) -{ - struct sock_filter *ins = &inss[*i]; - - ins->code = code; - ins->k = data; - (*i)++; -} - -static inline void bpf_jmp(struct sock_filter *inss, unsigned int *i, - unsigned short code, unsigned int data, - unsigned short jt, unsigned short jf) -{ - struct sock_filter *ins = &inss[*i]; - - ins->code = code; - ins->jt = jt; - ins->jf = jf; - ins->k = data; - (*i)++; -} - -/** - * udev_monitor_filter_update: - * @udev_monitor: monitor - * - * Update the installed socket filter. This is only needed, - * if the filter was removed or changed. - * - * Returns: 0 on success, otherwise a negative error value. - */ -_public_ int udev_monitor_filter_update(struct udev_monitor *udev_monitor) -{ - struct sock_filter ins[512]; - struct sock_fprog filter; - unsigned int i; - struct udev_list_entry *list_entry; - int err; - - if (udev_list_get_entry(&udev_monitor->filter_subsystem_list) == NULL && - udev_list_get_entry(&udev_monitor->filter_tag_list) == NULL) - return 0; - - memzero(ins, sizeof(ins)); - i = 0; - - /* load magic in A */ - bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(struct udev_monitor_netlink_header, magic)); - /* jump if magic matches */ - bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, UDEV_MONITOR_MAGIC, 1, 0); - /* wrong magic, pass packet */ - bpf_stmt(ins, &i, BPF_RET|BPF_K, 0xffffffff); - - if (udev_list_get_entry(&udev_monitor->filter_tag_list) != NULL) { - int tag_matches; - - /* count tag matches, to calculate end of tag match block */ - tag_matches = 0; - udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_monitor->filter_tag_list)) - tag_matches++; - - /* add all tags matches */ - udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_monitor->filter_tag_list)) { - uint64_t tag_bloom_bits = util_string_bloom64(udev_list_entry_get_name(list_entry)); - uint32_t tag_bloom_hi = tag_bloom_bits >> 32; - uint32_t tag_bloom_lo = tag_bloom_bits & 0xffffffff; - - /* load device bloom bits in A */ - bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(struct udev_monitor_netlink_header, filter_tag_bloom_hi)); - /* clear bits (tag bits & bloom bits) */ - bpf_stmt(ins, &i, BPF_ALU|BPF_AND|BPF_K, tag_bloom_hi); - /* jump to next tag if it does not match */ - bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, tag_bloom_hi, 0, 3); - - /* load device bloom bits in A */ - bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(struct udev_monitor_netlink_header, filter_tag_bloom_lo)); - /* clear bits (tag bits & bloom bits) */ - bpf_stmt(ins, &i, BPF_ALU|BPF_AND|BPF_K, tag_bloom_lo); - /* jump behind end of tag match block if tag matches */ - tag_matches--; - bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, tag_bloom_lo, 1 + (tag_matches * 6), 0); - } - - /* nothing matched, drop packet */ - bpf_stmt(ins, &i, BPF_RET|BPF_K, 0); - } - - /* add all subsystem matches */ - if (udev_list_get_entry(&udev_monitor->filter_subsystem_list) != NULL) { - udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_monitor->filter_subsystem_list)) { - unsigned int hash = util_string_hash32(udev_list_entry_get_name(list_entry)); - - /* load device subsystem value in A */ - bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(struct udev_monitor_netlink_header, filter_subsystem_hash)); - if (udev_list_entry_get_value(list_entry) == NULL) { - /* jump if subsystem does not match */ - bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 1); - } else { - /* jump if subsystem does not match */ - bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 3); - - /* load device devtype value in A */ - bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(struct udev_monitor_netlink_header, filter_devtype_hash)); - /* jump if value does not match */ - hash = util_string_hash32(udev_list_entry_get_value(list_entry)); - bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 1); - } - - /* matched, pass packet */ - bpf_stmt(ins, &i, BPF_RET|BPF_K, 0xffffffff); - - if (i+1 >= ELEMENTSOF(ins)) - return -E2BIG; - } - - /* nothing matched, drop packet */ - bpf_stmt(ins, &i, BPF_RET|BPF_K, 0); - } - - /* matched, pass packet */ - bpf_stmt(ins, &i, BPF_RET|BPF_K, 0xffffffff); - - /* install filter */ - memzero(&filter, sizeof(filter)); - filter.len = i; - filter.filter = ins; - err = setsockopt(udev_monitor->sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)); - return err < 0 ? -errno : 0; -} - -int udev_monitor_allow_unicast_sender(struct udev_monitor *udev_monitor, struct udev_monitor *sender) -{ - udev_monitor->snl_trusted_sender.nl.nl_pid = sender->snl.nl.nl_pid; - return 0; -} -/** - * udev_monitor_enable_receiving: - * @udev_monitor: the monitor which should receive events - * - * Binds the @udev_monitor socket to the event source. - * - * Returns: 0 on success, otherwise a negative error value. - */ -_public_ int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) -{ - int err = 0; - const int on = 1; - - udev_monitor_filter_update(udev_monitor); - - if (!udev_monitor->bound) { - err = bind(udev_monitor->sock, - &udev_monitor->snl.sa, sizeof(struct sockaddr_nl)); - if (err == 0) - udev_monitor->bound = true; - } - - if (err >= 0) { - union sockaddr_union snl; - socklen_t addrlen; - - /* - * get the address the kernel has assigned us - * it is usually, but not necessarily the pid - */ - addrlen = sizeof(struct sockaddr_nl); - err = getsockname(udev_monitor->sock, &snl.sa, &addrlen); - if (err == 0) - udev_monitor->snl.nl.nl_pid = snl.nl.nl_pid; - } else { - log_debug_errno(errno, "bind failed: %m"); - return -errno; - } - - /* enable receiving of sender credentials */ - err = setsockopt(udev_monitor->sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); - if (err < 0) - log_debug_errno(errno, "setting SO_PASSCRED failed: %m"); - - return 0; -} - -/** - * udev_monitor_set_receive_buffer_size: - * @udev_monitor: the monitor which should receive events - * @size: the size in bytes - * - * Set the size of the kernel socket buffer. This call needs the - * appropriate privileges to succeed. - * - * Returns: 0 on success, otherwise -1 on error. - */ -_public_ int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size) -{ - if (udev_monitor == NULL) - return -EINVAL; - return setsockopt(udev_monitor->sock, SOL_SOCKET, SO_RCVBUFFORCE, &size, sizeof(size)); -} - -int udev_monitor_disconnect(struct udev_monitor *udev_monitor) -{ - int err; - - err = close(udev_monitor->sock); - udev_monitor->sock = -1; - return err < 0 ? -errno : 0; -} - -/** - * udev_monitor_ref: - * @udev_monitor: udev monitor - * - * Take a reference of a udev monitor. - * - * Returns: the passed udev monitor - **/ -_public_ struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor) -{ - if (udev_monitor == NULL) - return NULL; - udev_monitor->refcount++; - return udev_monitor; -} - -/** - * udev_monitor_unref: - * @udev_monitor: udev monitor - * - * Drop a reference of a udev monitor. If the refcount reaches zero, - * the bound socket will be closed, and the resources of the monitor - * will be released. - * - * Returns: #NULL - **/ -_public_ struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor) -{ - if (udev_monitor == NULL) - return NULL; - udev_monitor->refcount--; - if (udev_monitor->refcount > 0) - return NULL; - if (udev_monitor->sock >= 0) - close(udev_monitor->sock); - udev_list_cleanup(&udev_monitor->filter_subsystem_list); - udev_list_cleanup(&udev_monitor->filter_tag_list); - free(udev_monitor); - return NULL; -} - -/** - * udev_monitor_get_udev: - * @udev_monitor: udev monitor - * - * Retrieve the udev library context the monitor was created with. - * - * Returns: the udev library context - **/ -_public_ struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor) -{ - if (udev_monitor == NULL) - return NULL; - return udev_monitor->udev; -} - -/** - * udev_monitor_get_fd: - * @udev_monitor: udev monitor - * - * Retrieve the socket file descriptor associated with the monitor. - * - * Returns: the socket file descriptor - **/ -_public_ int udev_monitor_get_fd(struct udev_monitor *udev_monitor) -{ - if (udev_monitor == NULL) - return -EINVAL; - return udev_monitor->sock; -} - -static int passes_filter(struct udev_monitor *udev_monitor, struct udev_device *udev_device) -{ - struct udev_list_entry *list_entry; - - if (udev_list_get_entry(&udev_monitor->filter_subsystem_list) == NULL) - goto tag; - udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_monitor->filter_subsystem_list)) { - const char *subsys = udev_list_entry_get_name(list_entry); - const char *dsubsys = udev_device_get_subsystem(udev_device); - const char *devtype; - const char *ddevtype; - - if (!streq(dsubsys, subsys)) - continue; - - devtype = udev_list_entry_get_value(list_entry); - if (devtype == NULL) - goto tag; - ddevtype = udev_device_get_devtype(udev_device); - if (ddevtype == NULL) - continue; - if (streq(ddevtype, devtype)) - goto tag; - } - return 0; - -tag: - if (udev_list_get_entry(&udev_monitor->filter_tag_list) == NULL) - return 1; - udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_monitor->filter_tag_list)) { - const char *tag = udev_list_entry_get_name(list_entry); - - if (udev_device_has_tag(udev_device, tag)) - return 1; - } - return 0; -} - -/** - * udev_monitor_receive_device: - * @udev_monitor: udev monitor - * - * Receive data from the udev monitor socket, allocate a new udev - * device, fill in the received data, and return the device. - * - * Only socket connections with uid=0 are accepted. - * - * The monitor socket is by default set to NONBLOCK. A variant of poll() on - * the file descriptor returned by udev_monitor_get_fd() should to be used to - * wake up when new devices arrive, or alternatively the file descriptor - * switched into blocking mode. - * - * The initial refcount is 1, and needs to be decremented to - * release the resources of the udev device. - * - * Returns: a new udev device, or #NULL, in case of an error - **/ -_public_ struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor) -{ - struct udev_device *udev_device; - struct msghdr smsg; - struct iovec iov; - char cred_msg[CMSG_SPACE(sizeof(struct ucred))]; - struct cmsghdr *cmsg; - union sockaddr_union snl; - struct ucred *cred; - union { - struct udev_monitor_netlink_header nlh; - char raw[8192]; - } buf; - ssize_t buflen; - ssize_t bufpos; - bool is_initialized = false; - -retry: - if (udev_monitor == NULL) - return NULL; - iov.iov_base = &buf; - iov.iov_len = sizeof(buf); - memzero(&smsg, sizeof(struct msghdr)); - smsg.msg_iov = &iov; - smsg.msg_iovlen = 1; - smsg.msg_control = cred_msg; - smsg.msg_controllen = sizeof(cred_msg); - smsg.msg_name = &snl; - smsg.msg_namelen = sizeof(snl); - - buflen = recvmsg(udev_monitor->sock, &smsg, 0); - if (buflen < 0) { - if (errno != EINTR) - log_debug("unable to receive message"); - return NULL; - } - - if (buflen < 32 || (smsg.msg_flags & MSG_TRUNC)) { - log_debug("invalid message length"); - return NULL; - } - - if (snl.nl.nl_groups == 0) { - /* unicast message, check if we trust the sender */ - if (udev_monitor->snl_trusted_sender.nl.nl_pid == 0 || - snl.nl.nl_pid != udev_monitor->snl_trusted_sender.nl.nl_pid) { - log_debug("unicast netlink message ignored"); - return NULL; - } - } else if (snl.nl.nl_groups == UDEV_MONITOR_KERNEL) { - if (snl.nl.nl_pid > 0) { - log_debug("multicast kernel netlink message from PID %"PRIu32" ignored", - snl.nl.nl_pid); - return NULL; - } - } - - cmsg = CMSG_FIRSTHDR(&smsg); - if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) { - log_debug("no sender credentials received, message ignored"); - return NULL; - } - - cred = (struct ucred *)CMSG_DATA(cmsg); - if (cred->uid != 0) { - log_debug("sender uid="UID_FMT", message ignored", cred->uid); - return NULL; - } - - if (memcmp(buf.raw, "libudev", 8) == 0) { - /* udev message needs proper version magic */ - if (buf.nlh.magic != htonl(UDEV_MONITOR_MAGIC)) { - log_debug("unrecognized message signature (%x != %x)", - buf.nlh.magic, htonl(UDEV_MONITOR_MAGIC)); - return NULL; - } - if (buf.nlh.properties_off+32 > (size_t)buflen) { - log_debug("message smaller than expected (%u > %zd)", - buf.nlh.properties_off+32, buflen); - return NULL; - } - - bufpos = buf.nlh.properties_off; - - /* devices received from udev are always initialized */ - is_initialized = true; - } else { - /* kernel message with header */ - bufpos = strlen(buf.raw) + 1; - if ((size_t)bufpos < sizeof("a@/d") || bufpos >= buflen) { - log_debug("invalid message length"); - return NULL; - } - - /* check message header */ - if (strstr(buf.raw, "@/") == NULL) { - log_debug("unrecognized message header"); - return NULL; - } - } - - udev_device = udev_device_new_from_nulstr(udev_monitor->udev, &buf.raw[bufpos], buflen - bufpos); - if (!udev_device) { - log_debug("could not create device: %m"); - return NULL; - } - - if (is_initialized) - udev_device_set_is_initialized(udev_device); - - /* skip device, if it does not pass the current filter */ - if (!passes_filter(udev_monitor, udev_device)) { - struct pollfd pfd[1]; - int rc; - - udev_device_unref(udev_device); - - /* if something is queued, get next device */ - pfd[0].fd = udev_monitor->sock; - pfd[0].events = POLLIN; - rc = poll(pfd, 1, 0); - if (rc > 0) - goto retry; - return NULL; - } - - return udev_device; -} - -int udev_monitor_send_device(struct udev_monitor *udev_monitor, - struct udev_monitor *destination, struct udev_device *udev_device) -{ - const char *buf, *val; - ssize_t blen, count; - struct udev_monitor_netlink_header nlh = { - .prefix = "libudev", - .magic = htonl(UDEV_MONITOR_MAGIC), - .header_size = sizeof nlh, - }; - struct iovec iov[2] = { - { .iov_base = &nlh, .iov_len = sizeof nlh }, - }; - struct msghdr smsg = { - .msg_iov = iov, - .msg_iovlen = 2, - }; - struct udev_list_entry *list_entry; - uint64_t tag_bloom_bits; - - blen = udev_device_get_properties_monitor_buf(udev_device, &buf); - if (blen < 32) { - log_debug("device buffer is too small to contain a valid device"); - return -EINVAL; - } - - /* fill in versioned header */ - val = udev_device_get_subsystem(udev_device); - nlh.filter_subsystem_hash = htonl(util_string_hash32(val)); - - val = udev_device_get_devtype(udev_device); - if (val != NULL) - nlh.filter_devtype_hash = htonl(util_string_hash32(val)); - - /* add tag bloom filter */ - tag_bloom_bits = 0; - udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(udev_device)) - tag_bloom_bits |= util_string_bloom64(udev_list_entry_get_name(list_entry)); - if (tag_bloom_bits > 0) { - nlh.filter_tag_bloom_hi = htonl(tag_bloom_bits >> 32); - nlh.filter_tag_bloom_lo = htonl(tag_bloom_bits & 0xffffffff); - } - - /* add properties list */ - nlh.properties_off = iov[0].iov_len; - nlh.properties_len = blen; - iov[1].iov_base = (char *)buf; - iov[1].iov_len = blen; - - /* - * Use custom address for target, or the default one. - * - * If we send to a multicast group, we will get - * ECONNREFUSED, which is expected. - */ - if (destination) - smsg.msg_name = &destination->snl; - else - smsg.msg_name = &udev_monitor->snl_destination; - smsg.msg_namelen = sizeof(struct sockaddr_nl); - count = sendmsg(udev_monitor->sock, &smsg, 0); - if (count < 0) { - if (!destination && errno == ECONNREFUSED) { - log_debug("passed unknown number of bytes to netlink monitor %p", udev_monitor); - return 0; - } else - return -errno; - } - - log_debug("passed %zi bytes to netlink monitor %p", count, udev_monitor); - return count; -} - -/** - * udev_monitor_filter_add_match_subsystem_devtype: - * @udev_monitor: the monitor - * @subsystem: the subsystem value to match the incoming devices against - * @devtype: the devtype value to match the incoming devices against - * - * This filter is efficiently executed inside the kernel, and libudev subscribers - * will usually not be woken up for devices which do not match. - * - * The filter must be installed before the monitor is switched to listening mode. - * - * Returns: 0 on success, otherwise a negative error value. - */ -_public_ int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor, const char *subsystem, const char *devtype) -{ - if (udev_monitor == NULL) - return -EINVAL; - if (subsystem == NULL) - return -EINVAL; - if (udev_list_entry_add(&udev_monitor->filter_subsystem_list, subsystem, devtype) == NULL) - return -ENOMEM; - return 0; -} - -/** - * udev_monitor_filter_add_match_tag: - * @udev_monitor: the monitor - * @tag: the name of a tag - * - * This filter is efficiently executed inside the kernel, and libudev subscribers - * will usually not be woken up for devices which do not match. - * - * The filter must be installed before the monitor is switched to listening mode. - * - * Returns: 0 on success, otherwise a negative error value. - */ -_public_ int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag) -{ - if (udev_monitor == NULL) - return -EINVAL; - if (tag == NULL) - return -EINVAL; - if (udev_list_entry_add(&udev_monitor->filter_tag_list, tag, NULL) == NULL) - return -ENOMEM; - return 0; -} - -/** - * udev_monitor_filter_remove: - * @udev_monitor: monitor - * - * Remove all filters from monitor. - * - * Returns: 0 on success, otherwise a negative error value. - */ -_public_ int udev_monitor_filter_remove(struct udev_monitor *udev_monitor) -{ - static struct sock_fprog filter = { 0, NULL }; - - udev_list_cleanup(&udev_monitor->filter_subsystem_list); - return setsockopt(udev_monitor->sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)); -} diff --git a/src/libudev/libudev-private.h b/src/libudev/libudev-private.h deleted file mode 100644 index 32c5e19a1..000000000 --- a/src/libudev/libudev-private.h +++ /dev/null @@ -1,151 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2008-2012 Kay Sievers - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#ifndef _LIBUDEV_PRIVATE_H_ -#define _LIBUDEV_PRIVATE_H_ - -#include -#include -#include - -#include "libudev.h" -#include "macro.h" -#include "util.h" -#include "mkdir.h" -#include "strxcpyx.h" - -#define READ_END 0 -#define WRITE_END 1 - -/* libudev.c */ -int udev_get_rules_path(struct udev *udev, char **path[], usec_t *ts_usec[]); - -/* libudev-device.c */ -struct udev_device *udev_device_new_from_nulstr(struct udev *udev, char *nulstr, ssize_t buflen); -struct udev_device *udev_device_new_from_synthetic_event(struct udev *udev, const char *syspath, const char *action); -struct udev_device *udev_device_shallow_clone(struct udev_device *old_device); -struct udev_device *udev_device_clone_with_db(struct udev_device *old_device); -int udev_device_copy_properties(struct udev_device *dst, struct udev_device *src); -mode_t udev_device_get_devnode_mode(struct udev_device *udev_device); -uid_t udev_device_get_devnode_uid(struct udev_device *udev_device); -gid_t udev_device_get_devnode_gid(struct udev_device *udev_device); -int udev_device_rename(struct udev_device *udev_device, const char *new_name); -int udev_device_add_devlink(struct udev_device *udev_device, const char *devlink); -void udev_device_cleanup_devlinks_list(struct udev_device *udev_device); -int udev_device_add_property(struct udev_device *udev_device, const char *key, const char *value); -char **udev_device_get_properties_envp(struct udev_device *udev_device); -ssize_t udev_device_get_properties_monitor_buf(struct udev_device *udev_device, const char **buf); -const char *udev_device_get_devpath_old(struct udev_device *udev_device); -const char *udev_device_get_id_filename(struct udev_device *udev_device); -void udev_device_set_is_initialized(struct udev_device *udev_device); -int udev_device_add_tag(struct udev_device *udev_device, const char *tag); -void udev_device_remove_tag(struct udev_device *udev_device, const char *tag); -void udev_device_cleanup_tags_list(struct udev_device *udev_device); -usec_t udev_device_get_usec_initialized(struct udev_device *udev_device); -void udev_device_ensure_usec_initialized(struct udev_device *udev_device, struct udev_device *old_device); -int udev_device_get_devlink_priority(struct udev_device *udev_device); -int udev_device_set_devlink_priority(struct udev_device *udev_device, int prio); -int udev_device_get_watch_handle(struct udev_device *udev_device); -int udev_device_set_watch_handle(struct udev_device *udev_device, int handle); -int udev_device_get_ifindex(struct udev_device *udev_device); -void udev_device_set_info_loaded(struct udev_device *device); -bool udev_device_get_db_persist(struct udev_device *udev_device); -void udev_device_set_db_persist(struct udev_device *udev_device); - -/* libudev-device-private.c */ -int udev_device_update_db(struct udev_device *udev_device); -int udev_device_delete_db(struct udev_device *udev_device); -int udev_device_tag_index(struct udev_device *dev, struct udev_device *dev_old, bool add); - -/* libudev-monitor.c - netlink/unix socket communication */ -int udev_monitor_disconnect(struct udev_monitor *udev_monitor); -int udev_monitor_allow_unicast_sender(struct udev_monitor *udev_monitor, struct udev_monitor *sender); -int udev_monitor_send_device(struct udev_monitor *udev_monitor, - struct udev_monitor *destination, struct udev_device *udev_device); -struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const char *name, int fd); - -/* libudev-list.c */ -struct udev_list_node { - struct udev_list_node *next, *prev; -}; -struct udev_list { - struct udev *udev; - struct udev_list_node node; - struct udev_list_entry **entries; - unsigned int entries_cur; - unsigned int entries_max; - bool unique; -}; -#define UDEV_LIST(list) struct udev_list_node list = { &(list), &(list) } -void udev_list_node_init(struct udev_list_node *list); -int udev_list_node_is_empty(struct udev_list_node *list); -void udev_list_node_append(struct udev_list_node *new, struct udev_list_node *list); -void udev_list_node_remove(struct udev_list_node *entry); -#define udev_list_node_foreach(node, list) \ - for (node = (list)->next; \ - node != list; \ - node = (node)->next) -#define udev_list_node_foreach_safe(node, tmp, list) \ - for (node = (list)->next, tmp = (node)->next; \ - node != list; \ - node = tmp, tmp = (tmp)->next) -void udev_list_init(struct udev *udev, struct udev_list *list, bool unique); -void udev_list_cleanup(struct udev_list *list); -struct udev_list_entry *udev_list_get_entry(struct udev_list *list); -struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char *name, const char *value); -void udev_list_entry_delete(struct udev_list_entry *entry); -int udev_list_entry_get_num(struct udev_list_entry *list_entry); -void udev_list_entry_set_num(struct udev_list_entry *list_entry, int num); -#define udev_list_entry_foreach_safe(entry, tmp, first) \ - for (entry = first, tmp = udev_list_entry_get_next(entry); \ - entry != NULL; \ - entry = tmp, tmp = udev_list_entry_get_next(tmp)) - -/* libudev-queue.c */ -unsigned long long int udev_get_kernel_seqnum(struct udev *udev); -int udev_queue_read_seqnum(FILE *queue_file, unsigned long long int *seqnum); -ssize_t udev_queue_read_devpath(FILE *queue_file, char *devpath, size_t size); -ssize_t udev_queue_skip_devpath(FILE *queue_file); - -/* libudev-queue-private.c */ -struct udev_queue_export *udev_queue_export_new(struct udev *udev); -struct udev_queue_export *udev_queue_export_unref(struct udev_queue_export *udev_queue_export); -void udev_queue_export_cleanup(struct udev_queue_export *udev_queue_export); -int udev_queue_export_device_queued(struct udev_queue_export *udev_queue_export, struct udev_device *udev_device); -int udev_queue_export_device_finished(struct udev_queue_export *udev_queue_export, struct udev_device *udev_device); - -/* libudev-util.c */ -#define UTIL_PATH_SIZE 1024 -#define UTIL_NAME_SIZE 512 -#define UTIL_LINE_SIZE 16384 -#define UDEV_ALLOWED_CHARS_INPUT "/ $%?," -ssize_t util_get_sys_core_link_value(struct udev *udev, const char *slink, const char *syspath, char *value, size_t size); -int util_resolve_sys_link(struct udev *udev, char *syspath, size_t size); -int util_log_priority(const char *priority); -size_t util_path_encode(const char *src, char *dest, size_t size); -void util_remove_trailing_chars(char *path, char c); -int util_replace_whitespace(const char *str, char *to, size_t len); -int util_replace_chars(char *str, const char *white); -unsigned int util_string_hash32(const char *key); -uint64_t util_string_bloom64(const char *str); - -/* libudev-util-private.c */ -int util_resolve_subsys_kernel(struct udev *udev, const char *string, char *result, size_t maxsize, int read_value); - -#endif diff --git a/src/libudev/libudev-queue.c b/src/libudev/libudev-queue.c deleted file mode 100644 index 11e15d13e..000000000 --- a/src/libudev/libudev-queue.c +++ /dev/null @@ -1,265 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2008-2012 Kay Sievers - Copyright 2009 Alan Jenkins - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include -#include -#include -#include - -#include "libudev-private.h" - -/** - * SECTION:libudev-queue - * @short_description: access to currently active events - * - * This exports the current state of the udev processing queue. - */ - -/** - * udev_queue: - * - * Opaque object representing the current event queue in the udev daemon. - */ -struct udev_queue { - struct udev *udev; - int refcount; - int fd; -}; - -/** - * udev_queue_new: - * @udev: udev library context - * - * The initial refcount is 1, and needs to be decremented to - * release the resources of the udev queue context. - * - * Returns: the udev queue context, or #NULL on error. - **/ -_public_ struct udev_queue *udev_queue_new(struct udev *udev) -{ - struct udev_queue *udev_queue; - - if (udev == NULL) - return NULL; - - udev_queue = new0(struct udev_queue, 1); - if (udev_queue == NULL) - return NULL; - - udev_queue->refcount = 1; - udev_queue->udev = udev; - udev_queue->fd = -1; - return udev_queue; -} - -/** - * udev_queue_ref: - * @udev_queue: udev queue context - * - * Take a reference of a udev queue context. - * - * Returns: the same udev queue context. - **/ -_public_ struct udev_queue *udev_queue_ref(struct udev_queue *udev_queue) -{ - if (udev_queue == NULL) - return NULL; - - udev_queue->refcount++; - return udev_queue; -} - -/** - * udev_queue_unref: - * @udev_queue: udev queue context - * - * Drop a reference of a udev queue context. If the refcount reaches zero, - * the resources of the queue context will be released. - * - * Returns: #NULL - **/ -_public_ struct udev_queue *udev_queue_unref(struct udev_queue *udev_queue) -{ - if (udev_queue == NULL) - return NULL; - - udev_queue->refcount--; - if (udev_queue->refcount > 0) - return NULL; - - safe_close(udev_queue->fd); - - free(udev_queue); - return NULL; -} - -/** - * udev_queue_get_udev: - * @udev_queue: udev queue context - * - * Retrieve the udev library context the queue context was created with. - * - * Returns: the udev library context. - **/ -_public_ struct udev *udev_queue_get_udev(struct udev_queue *udev_queue) -{ - if (udev_queue == NULL) - return NULL; - return udev_queue->udev; -} - -/** - * udev_queue_get_kernel_seqnum: - * @udev_queue: udev queue context - * - * This function is deprecated. - * - * Returns: 0. - **/ -_public_ unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue) -{ - return 0; -} - -/** - * udev_queue_get_udev_seqnum: - * @udev_queue: udev queue context - * - * This function is deprecated. - * - * Returns: 0. - **/ -_public_ unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue) -{ - return 0; -} - -/** - * udev_queue_get_udev_is_active: - * @udev_queue: udev queue context - * - * Check if udev is active on the system. - * - * Returns: a flag indicating if udev is active. - **/ -_public_ int udev_queue_get_udev_is_active(struct udev_queue *udev_queue) -{ - return access("/run/udev/control", F_OK) >= 0; -} - -/** - * udev_queue_get_queue_is_empty: - * @udev_queue: udev queue context - * - * Check if udev is currently processing any events. - * - * Returns: a flag indicating if udev is currently handling events. - **/ -_public_ int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue) -{ - return access("/run/udev/queue", F_OK) < 0; -} - -/** - * udev_queue_get_seqnum_sequence_is_finished: - * @udev_queue: udev queue context - * @start: first event sequence number - * @end: last event sequence number - * - * This function is deprecated, it just returns the result of - * udev_queue_get_queue_is_empty(). - * - * Returns: a flag indicating if udev is currently handling events. - **/ -_public_ int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue, - unsigned long long int start, unsigned long long int end) -{ - return udev_queue_get_queue_is_empty(udev_queue); -} - -/** - * udev_queue_get_seqnum_is_finished: - * @udev_queue: udev queue context - * @seqnum: sequence number - * - * This function is deprecated, it just returns the result of - * udev_queue_get_queue_is_empty(). - * - * Returns: a flag indicating if udev is currently handling events. - **/ -_public_ int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum) -{ - return udev_queue_get_queue_is_empty(udev_queue); -} - -/** - * udev_queue_get_queued_list_entry: - * @udev_queue: udev queue context - * - * This function is deprecated. - * - * Returns: NULL. - **/ -_public_ struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) -{ - return NULL; -} - -/** - * udev_queue_get_fd: - * @udev_queue: udev queue context - * - * Returns: a file descriptor to watch for a queue to become empty. - */ -_public_ int udev_queue_get_fd(struct udev_queue *udev_queue) { - int fd; - int r; - - if (udev_queue->fd >= 0) - return udev_queue->fd; - - fd = inotify_init1(IN_CLOEXEC); - if (fd < 0) - return -errno; - - r = inotify_add_watch(fd, "/run/udev" , IN_DELETE); - if (r < 0) { - r = -errno; - close(fd); - return r; - } - - udev_queue->fd = fd; - return fd; -} - -/** - * udev_queue_flush: - * @udev_queue: udev queue context - * - * Returns: the result of clearing the watch for queue changes. - */ -_public_ int udev_queue_flush(struct udev_queue *udev_queue) { - if (udev_queue->fd < 0) - return -EINVAL; - - return flush_fd(udev_queue->fd); -} diff --git a/src/libudev/libudev-util.c b/src/libudev/libudev-util.c deleted file mode 100644 index 0f8f634ca..000000000 --- a/src/libudev/libudev-util.c +++ /dev/null @@ -1,312 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2008-2012 Kay Sievers - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include -#include -#include -#include -#include - -#include "device-nodes.h" -#include "libudev.h" -#include "libudev-private.h" -#include "utf8.h" -#include "MurmurHash2.h" - -/** - * SECTION:libudev-util - * @short_description: utils - * - * Utilities useful when dealing with devices and device node names. - */ - -/* handle "[/]" format */ -int util_resolve_subsys_kernel(struct udev *udev, const char *string, - char *result, size_t maxsize, int read_value) -{ - char temp[UTIL_PATH_SIZE]; - char *subsys; - char *sysname; - struct udev_device *dev; - char *attr; - - if (string[0] != '[') - return -1; - - strscpy(temp, sizeof(temp), string); - - subsys = &temp[1]; - - sysname = strchr(subsys, '/'); - if (sysname == NULL) - return -1; - sysname[0] = '\0'; - sysname = &sysname[1]; - - attr = strchr(sysname, ']'); - if (attr == NULL) - return -1; - attr[0] = '\0'; - attr = &attr[1]; - if (attr[0] == '/') - attr = &attr[1]; - if (attr[0] == '\0') - attr = NULL; - - if (read_value && attr == NULL) - return -1; - - dev = udev_device_new_from_subsystem_sysname(udev, subsys, sysname); - if (dev == NULL) - return -1; - - if (read_value) { - const char *val; - - val = udev_device_get_sysattr_value(dev, attr); - if (val != NULL) - strscpy(result, maxsize, val); - else - result[0] = '\0'; - log_debug("value '[%s/%s]%s' is '%s'", subsys, sysname, attr, result); - } else { - size_t l; - char *s; - - s = result; - l = strpcpyl(&s, maxsize, udev_device_get_syspath(dev), NULL); - if (attr != NULL) - strpcpyl(&s, l, "/", attr, NULL); - log_debug("path '[%s/%s]%s' is '%s'", subsys, sysname, attr, result); - } - udev_device_unref(dev); - return 0; -} - -ssize_t util_get_sys_core_link_value(struct udev *udev, const char *slink, const char *syspath, char *value, size_t size) -{ - char path[UTIL_PATH_SIZE]; - char target[UTIL_PATH_SIZE]; - ssize_t len; - const char *pos; - - strscpyl(path, sizeof(path), syspath, "/", slink, NULL); - len = readlink(path, target, sizeof(target)); - if (len <= 0 || len == (ssize_t)sizeof(target)) - return -1; - target[len] = '\0'; - pos = strrchr(target, '/'); - if (pos == NULL) - return -1; - pos = &pos[1]; - return strscpy(value, size, pos); -} - -int util_resolve_sys_link(struct udev *udev, char *syspath, size_t size) -{ - char link_target[UTIL_PATH_SIZE]; - - ssize_t len; - int i; - int back; - char *base = NULL; - - len = readlink(syspath, link_target, sizeof(link_target)); - if (len <= 0 || len == (ssize_t)sizeof(link_target)) - return -1; - link_target[len] = '\0'; - - for (back = 0; startswith(&link_target[back * 3], "../"); back++) - ; - for (i = 0; i <= back; i++) { - base = strrchr(syspath, '/'); - if (base == NULL) - return -EINVAL; - base[0] = '\0'; - } - - strscpyl(base, size - (base - syspath), "/", &link_target[back * 3], NULL); - return 0; -} - -int util_log_priority(const char *priority) -{ - char *endptr; - int prio; - - prio = strtoul(priority, &endptr, 10); - if (endptr[0] == '\0' || isspace(endptr[0])) { - if (prio >= 0 && prio <= 7) - return prio; - else - return -ERANGE; - } - - return log_level_from_string(priority); -} - -size_t util_path_encode(const char *src, char *dest, size_t size) -{ - size_t i, j; - - for (i = 0, j = 0; src[i] != '\0'; i++) { - if (src[i] == '/') { - if (j+4 >= size) { - j = 0; - break; - } - memcpy(&dest[j], "\\x2f", 4); - j += 4; - } else if (src[i] == '\\') { - if (j+4 >= size) { - j = 0; - break; - } - memcpy(&dest[j], "\\x5c", 4); - j += 4; - } else { - if (j+1 >= size) { - j = 0; - break; - } - dest[j] = src[i]; - j++; - } - } - dest[j] = '\0'; - return j; -} - -void util_remove_trailing_chars(char *path, char c) -{ - size_t len; - - if (path == NULL) - return; - len = strlen(path); - while (len > 0 && path[len-1] == c) - path[--len] = '\0'; -} - -int util_replace_whitespace(const char *str, char *to, size_t len) -{ - size_t i, j; - - /* strip trailing whitespace */ - len = strnlen(str, len); - while (len && isspace(str[len-1])) - len--; - - /* strip leading whitespace */ - i = 0; - while (isspace(str[i]) && (i < len)) - i++; - - j = 0; - while (i < len) { - /* substitute multiple whitespace with a single '_' */ - if (isspace(str[i])) { - while (isspace(str[i])) - i++; - to[j++] = '_'; - } - to[j++] = str[i++]; - } - to[j] = '\0'; - return 0; -} - -/* allow chars in whitelist, plain ascii, hex-escaping and valid utf8 */ -int util_replace_chars(char *str, const char *white) -{ - size_t i = 0; - int replaced = 0; - - while (str[i] != '\0') { - int len; - - if (whitelisted_char_for_devnode(str[i], white)) { - i++; - continue; - } - - /* accept hex encoding */ - if (str[i] == '\\' && str[i+1] == 'x') { - i += 2; - continue; - } - - /* accept valid utf8 */ - len = utf8_encoded_valid_unichar(&str[i]); - if (len > 1) { - i += len; - continue; - } - - /* if space is allowed, replace whitespace with ordinary space */ - if (isspace(str[i]) && white != NULL && strchr(white, ' ') != NULL) { - str[i] = ' '; - i++; - replaced++; - continue; - } - - /* everything else is replaced with '_' */ - str[i] = '_'; - i++; - replaced++; - } - return replaced; -} - -/** - * udev_util_encode_string: - * @str: input string to be encoded - * @str_enc: output string to store the encoded input string - * @len: maximum size of the output string, which may be - * four times as long as the input string - * - * Encode all potentially unsafe characters of a string to the - * corresponding 2 char hex value prefixed by '\x'. - * - * Returns: 0 if the entire string was copied, non-zero otherwise. - **/ -_public_ int udev_util_encode_string(const char *str, char *str_enc, size_t len) -{ - return encode_devnode_name(str, str_enc, len); -} - -unsigned int util_string_hash32(const char *str) -{ - return MurmurHash2(str, strlen(str), 0); -} - -/* get a bunch of bit numbers out of the hash, and set the bits in our bit field */ -uint64_t util_string_bloom64(const char *str) -{ - uint64_t bits = 0; - unsigned int hash = util_string_hash32(str); - - bits |= 1LLU << (hash & 63); - bits |= 1LLU << ((hash >> 6) & 63); - bits |= 1LLU << ((hash >> 12) & 63); - bits |= 1LLU << ((hash >> 18) & 63); - return bits; -} diff --git a/src/libudev/libudev.c b/src/libudev/libudev.c deleted file mode 100644 index ec15d2576..000000000 --- a/src/libudev/libudev.c +++ /dev/null @@ -1,249 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2008-2014 Kay Sievers - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include -#include -#include -#include -#include - -#include "libudev.h" -#include "libudev-private.h" -#include "missing.h" - -/** - * SECTION:libudev - * @short_description: libudev context - * - * The context contains the default values read from the udev config file, - * and is passed to all library operations. - */ - -/** - * udev: - * - * Opaque object representing the library context. - */ -struct udev { - int refcount; - void (*log_fn)(struct udev *udev, - int priority, const char *file, int line, const char *fn, - const char *format, va_list args); - void *userdata; -}; - -/** - * udev_get_userdata: - * @udev: udev library context - * - * Retrieve stored data pointer from library context. This might be useful - * to access from callbacks. - * - * Returns: stored userdata - **/ -_public_ void *udev_get_userdata(struct udev *udev) { - if (udev == NULL) - return NULL; - return udev->userdata; -} - -/** - * udev_set_userdata: - * @udev: udev library context - * @userdata: data pointer - * - * Store custom @userdata in the library context. - **/ -_public_ void udev_set_userdata(struct udev *udev, void *userdata) { - if (udev == NULL) - return; - udev->userdata = userdata; -} - -/** - * udev_new: - * - * Create udev library context. This reads the udev configuration - * file, and fills in the default values. - * - * The initial refcount is 1, and needs to be decremented to - * release the resources of the udev library context. - * - * Returns: a new udev library context - **/ -_public_ struct udev *udev_new(void) { - struct udev *udev; - _cleanup_fclose_ FILE *f = NULL; - - udev = new0(struct udev, 1); - if (udev == NULL) - return NULL; - udev->refcount = 1; - - f = fopen("/etc/udev/udev.conf", "re"); - if (f != NULL) { - char line[UTIL_LINE_SIZE]; - unsigned line_nr = 0; - - while (fgets(line, sizeof(line), f)) { - size_t len; - char *key; - char *val; - - line_nr++; - - /* find key */ - key = line; - while (isspace(key[0])) - key++; - - /* comment or empty line */ - if (key[0] == '#' || key[0] == '\0') - continue; - - /* split key/value */ - val = strchr(key, '='); - if (val == NULL) { - log_debug("/etc/udev/udev.conf:%u: missing assignment, skipping line.", line_nr); - continue; - } - val[0] = '\0'; - val++; - - /* find value */ - while (isspace(val[0])) - val++; - - /* terminate key */ - len = strlen(key); - if (len == 0) - continue; - while (isspace(key[len-1])) - len--; - key[len] = '\0'; - - /* terminate value */ - len = strlen(val); - if (len == 0) - continue; - while (isspace(val[len-1])) - len--; - val[len] = '\0'; - - if (len == 0) - continue; - - /* unquote */ - if (val[0] == '"' || val[0] == '\'') { - if (val[len-1] != val[0]) { - log_debug("/etc/udev/udev.conf:%u: inconsistent quoting, skipping line.", line_nr); - continue; - } - val[len-1] = '\0'; - val++; - } - - if (streq(key, "udev_log")) { - int prio; - - prio = util_log_priority(val); - if (prio < 0) - log_debug("/etc/udev/udev.conf:%u: invalid log level '%s', ignoring.", line_nr, val); - else - log_set_max_level(prio); - continue; - } - } - } - - return udev; -} - -/** - * udev_ref: - * @udev: udev library context - * - * Take a reference of the udev library context. - * - * Returns: the passed udev library context - **/ -_public_ struct udev *udev_ref(struct udev *udev) { - if (udev == NULL) - return NULL; - udev->refcount++; - return udev; -} - -/** - * udev_unref: - * @udev: udev library context - * - * Drop a reference of the udev library context. If the refcount - * reaches zero, the resources of the context will be released. - * - * Returns: the passed udev library context if it has still an active reference, or #NULL otherwise. - **/ -_public_ struct udev *udev_unref(struct udev *udev) { - if (udev == NULL) - return NULL; - udev->refcount--; - if (udev->refcount > 0) - return udev; - free(udev); - return NULL; -} - -/** - * udev_set_log_fn: - * @udev: udev library context - * @log_fn: function to be called for log messages - * - * This function is deprecated. - * - **/ -_public_ void udev_set_log_fn(struct udev *udev, - void (*log_fn)(struct udev *udev, - int priority, const char *file, int line, const char *fn, - const char *format, va_list args)) { - return; -} - -/** - * udev_get_log_priority: - * @udev: udev library context - * - * This function is deprecated. - * - **/ -_public_ int udev_get_log_priority(struct udev *udev) { - return log_get_max_level(); -} - -/** - * udev_set_log_priority: - * @udev: udev library context - * @priority: the new log priority - * - * This function is deprecated. - * - **/ -_public_ void udev_set_log_priority(struct udev *udev, int priority) { - log_set_max_level(priority); -} diff --git a/src/libudev/libudev.h b/src/libudev/libudev.h deleted file mode 100644 index eb58740d2..000000000 --- a/src/libudev/libudev.h +++ /dev/null @@ -1,206 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2008-2012 Kay Sievers - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#ifndef _LIBUDEV_H_ -#define _LIBUDEV_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * udev - library context - * - * reads the udev config and system environment - * allows custom logging - */ -struct udev; -struct udev *udev_ref(struct udev *udev); -struct udev *udev_unref(struct udev *udev); -struct udev *udev_new(void); -void udev_set_log_fn(struct udev *udev, - void (*log_fn)(struct udev *udev, - int priority, const char *file, int line, const char *fn, - const char *format, va_list args)) __attribute__ ((deprecated)); -int udev_get_log_priority(struct udev *udev) __attribute__ ((deprecated)); -void udev_set_log_priority(struct udev *udev, int priority) __attribute__ ((deprecated)); -void *udev_get_userdata(struct udev *udev); -void udev_set_userdata(struct udev *udev, void *userdata); - -/* - * udev_list - * - * access to libudev generated lists - */ -struct udev_list_entry; -struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry); -struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name); -const char *udev_list_entry_get_name(struct udev_list_entry *list_entry); -const char *udev_list_entry_get_value(struct udev_list_entry *list_entry); -/** - * udev_list_entry_foreach: - * @list_entry: entry to store the current position - * @first_entry: first entry to start with - * - * Helper to iterate over all entries of a list. - */ -#define udev_list_entry_foreach(list_entry, first_entry) \ - for (list_entry = first_entry; \ - list_entry != NULL; \ - list_entry = udev_list_entry_get_next(list_entry)) - -/* - * udev_device - * - * access to sysfs/kernel devices - */ -struct udev_device; -struct udev_device *udev_device_ref(struct udev_device *udev_device); -struct udev_device *udev_device_unref(struct udev_device *udev_device); -struct udev *udev_device_get_udev(struct udev_device *udev_device); -struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath); -struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum); -struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname); -struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id); -struct udev_device *udev_device_new_from_environment(struct udev *udev); -/* udev_device_get_parent_*() does not take a reference on the returned device, it is automatically unref'd with the parent */ -struct udev_device *udev_device_get_parent(struct udev_device *udev_device); -struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, - const char *subsystem, const char *devtype); -/* retrieve device properties */ -const char *udev_device_get_devpath(struct udev_device *udev_device); -const char *udev_device_get_subsystem(struct udev_device *udev_device); -const char *udev_device_get_devtype(struct udev_device *udev_device); -const char *udev_device_get_syspath(struct udev_device *udev_device); -const char *udev_device_get_sysname(struct udev_device *udev_device); -const char *udev_device_get_sysnum(struct udev_device *udev_device); -const char *udev_device_get_devnode(struct udev_device *udev_device); -int udev_device_get_is_initialized(struct udev_device *udev_device); -struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device); -struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device); -struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device); -struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device); -const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key); -const char *udev_device_get_driver(struct udev_device *udev_device); -dev_t udev_device_get_devnum(struct udev_device *udev_device); -const char *udev_device_get_action(struct udev_device *udev_device); -unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device); -unsigned long long int udev_device_get_usec_since_initialized(struct udev_device *udev_device); -const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr); -int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, char *value); -int udev_device_has_tag(struct udev_device *udev_device, const char *tag); - -/* - * udev_monitor - * - * access to kernel uevents and udev events - */ -struct udev_monitor; -struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor); -struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor); -struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor); -/* kernel and udev generated events over netlink */ -struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name); -/* bind socket */ -int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor); -int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size); -int udev_monitor_get_fd(struct udev_monitor *udev_monitor); -struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor); -/* in-kernel socket filters to select messages that get delivered to a listener */ -int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor, - const char *subsystem, const char *devtype); -int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag); -int udev_monitor_filter_update(struct udev_monitor *udev_monitor); -int udev_monitor_filter_remove(struct udev_monitor *udev_monitor); - -/* - * udev_enumerate - * - * search sysfs for specific devices and provide a sorted list - */ -struct udev_enumerate; -struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate); -struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate); -struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate); -struct udev_enumerate *udev_enumerate_new(struct udev *udev); -/* device properties filter */ -int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem); -int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem); -int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value); -int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value); -int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value); -int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname); -int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag); -int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent); -int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate); -int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath); -/* run enumeration with active filters */ -int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate); -int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate); -/* return device list */ -struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate); - -/* - * udev_queue - * - * access to the currently running udev events - */ -struct udev_queue; -struct udev_queue *udev_queue_ref(struct udev_queue *udev_queue); -struct udev_queue *udev_queue_unref(struct udev_queue *udev_queue); -struct udev *udev_queue_get_udev(struct udev_queue *udev_queue); -struct udev_queue *udev_queue_new(struct udev *udev); -unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue) __attribute__ ((deprecated)); -unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue) __attribute__ ((deprecated)); -int udev_queue_get_udev_is_active(struct udev_queue *udev_queue); -int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue); -int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum) __attribute__ ((deprecated)); -int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue, - unsigned long long int start, unsigned long long int end) __attribute__ ((deprecated)); -int udev_queue_get_fd(struct udev_queue *udev_queue); -int udev_queue_flush(struct udev_queue *udev_queue); -struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) __attribute__ ((deprecated)); - -/* - * udev_hwdb - * - * access to the static hardware properties database - */ -struct udev_hwdb; -struct udev_hwdb *udev_hwdb_new(struct udev *udev); -struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb); -struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb); -struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags); - -/* - * udev_util - * - * udev specific utilities - */ -int udev_util_encode_string(const char *str, char *str_enc, size_t len); - - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/src/libudev/libudev.pc.in b/src/libudev/libudev.pc.in deleted file mode 100644 index a0f3f524e..000000000 --- a/src/libudev/libudev.pc.in +++ /dev/null @@ -1,17 +0,0 @@ -# This file is part of systemd. -# -# systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. - -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: libudev -Description: Library to access udev device information -Version: @VERSION@ -Libs: -L${libdir} -ludev -Cflags: -I${includedir} diff --git a/src/libudev/libudev.sym b/src/libudev/libudev.sym deleted file mode 100644 index 76726fca7..000000000 --- a/src/libudev/libudev.sym +++ /dev/null @@ -1,120 +0,0 @@ -/*** - This file is part of systemd. - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. -***/ - -LIBUDEV_183 { -global: - udev_device_get_action; - udev_device_get_devlinks_list_entry; - udev_device_get_devnode; - udev_device_get_devnum; - udev_device_get_devpath; - udev_device_get_devtype; - udev_device_get_driver; - udev_device_get_is_initialized; - udev_device_get_parent; - udev_device_get_parent_with_subsystem_devtype; - udev_device_get_properties_list_entry; - udev_device_get_property_value; - udev_device_get_seqnum; - udev_device_get_subsystem; - udev_device_get_sysattr_list_entry; - udev_device_get_sysattr_value; - udev_device_get_sysname; - udev_device_get_sysnum; - udev_device_get_syspath; - udev_device_get_tags_list_entry; - udev_device_get_udev; - udev_device_get_usec_since_initialized; - udev_device_has_tag; - udev_device_new_from_devnum; - udev_device_new_from_environment; - udev_device_new_from_subsystem_sysname; - udev_device_new_from_syspath; - udev_device_ref; - udev_device_unref; - udev_enumerate_add_match_is_initialized; - udev_enumerate_add_match_parent; - udev_enumerate_add_match_property; - udev_enumerate_add_match_subsystem; - udev_enumerate_add_match_sysattr; - udev_enumerate_add_match_sysname; - udev_enumerate_add_match_tag; - udev_enumerate_add_nomatch_subsystem; - udev_enumerate_add_nomatch_sysattr; - udev_enumerate_add_syspath; - udev_enumerate_get_list_entry; - udev_enumerate_get_udev; - udev_enumerate_new; - udev_enumerate_ref; - udev_enumerate_scan_devices; - udev_enumerate_scan_subsystems; - udev_enumerate_unref; - udev_get_log_priority; - udev_get_userdata; - udev_list_entry_get_by_name; - udev_list_entry_get_name; - udev_list_entry_get_next; - udev_list_entry_get_value; - udev_monitor_enable_receiving; - udev_monitor_filter_add_match_subsystem_devtype; - udev_monitor_filter_add_match_tag; - udev_monitor_filter_remove; - udev_monitor_filter_update; - udev_monitor_get_fd; - udev_monitor_get_udev; - udev_monitor_new_from_netlink; - udev_monitor_receive_device; - udev_monitor_ref; - udev_monitor_set_receive_buffer_size; - udev_monitor_unref; - udev_new; - udev_queue_get_kernel_seqnum; - udev_queue_get_queue_is_empty; - udev_queue_get_queued_list_entry; - udev_queue_get_seqnum_is_finished; - udev_queue_get_seqnum_sequence_is_finished; - udev_queue_get_udev; - udev_queue_get_udev_is_active; - udev_queue_get_udev_seqnum; - udev_queue_new; - udev_queue_ref; - udev_queue_unref; - udev_ref; - udev_set_log_fn; - udev_set_log_priority; - udev_set_userdata; - udev_unref; - udev_util_encode_string; -local: - *; -}; - -LIBUDEV_189 { -global: - udev_device_new_from_device_id; -} LIBUDEV_183; - -LIBUDEV_196 { -global: - udev_hwdb_new; - udev_hwdb_ref; - udev_hwdb_unref; - udev_hwdb_get_properties_list_entry; -} LIBUDEV_189; - -LIBUDEV_199 { -global: - udev_device_set_sysattr_value; -} LIBUDEV_196; - -LIBUDEV_215 { -global: - udev_queue_flush; - udev_queue_get_fd; -} LIBUDEV_199;