diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/libudev-legacy/COPYING | 504 | ||||
-rw-r--r-- | src/libudev-legacy/Makefile.am | 40 | ||||
-rw-r--r-- | src/libudev-legacy/libudev-device.c | 1775 | ||||
-rw-r--r-- | src/libudev-legacy/libudev-enumerate.c | 831 | ||||
-rw-r--r-- | src/libudev-legacy/libudev-list.c | 278 | ||||
-rw-r--r-- | src/libudev-legacy/libudev-monitor.c | 876 | ||||
-rw-r--r-- | src/libudev-legacy/libudev-private.h | 253 | ||||
-rw-r--r-- | src/libudev-legacy/libudev-queue.c | 515 | ||||
-rw-r--r-- | src/libudev-legacy/libudev-util.c | 568 | ||||
-rw-r--r-- | src/libudev-legacy/libudev.c | 467 | ||||
-rw-r--r-- | src/libudev-legacy/libudev.h | 180 |
12 files changed, 0 insertions, 6292 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 82732ca4bb..dcf5b54336 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,8 +23,3 @@ if ENABLE_KEYMAP SUBDIRS += \ keymap endif - -if ENABLE_LEGACYLIB -SUBDIRS += \ - libudev-legacy -endif diff --git a/src/libudev-legacy/COPYING b/src/libudev-legacy/COPYING deleted file mode 100644 index 8add30ad59..0000000000 --- a/src/libudev-legacy/COPYING +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - <one line to give the library's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This library 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. - - This library 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 this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - <signature of Ty Coon>, 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/src/libudev-legacy/Makefile.am b/src/libudev-legacy/Makefile.am deleted file mode 100644 index 507282b38b..0000000000 --- a/src/libudev-legacy/Makefile.am +++ /dev/null @@ -1,40 +0,0 @@ -ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} - -define move-legacylib - $(MKDIR_P) $(DESTDIR)$(rootlibdir) && \ - mv $(DESTDIR)$(libdir)/$$libname $(DESTDIR)$(rootlibdir)/libudev.so.0 -endef - -AM_CPPFLAGS = \ - -include $(top_builddir)/config.h \ - -DUDEV_CONF_FILE=\"$(udevconffile)\" - -lib_LTLIBRARIES = \ - libudev-legacy.la - -libudev_legacy_la_SOURCES =\ - libudev.c \ - libudev-list.c \ - libudev-util.c \ - libudev-device.c \ - libudev-enumerate.c \ - libudev-monitor.c \ - libudev-queue.c - -libudev_legacy_la_CFLAGS =\ - $(AM_CFLAGS) \ - -shared - -noinst_HEADERS = \ - libudev.h \ - libudev-private.h - -libudev_legacy_la_LDFLAGS = \ - $(AM_LDFLAGS) \ - -avoid-version - -install-exec-hook: - libname=libudev-legacy.so && $(move-legacylib) - -EXTRA_DIST = \ - COPYING diff --git a/src/libudev-legacy/libudev-device.c b/src/libudev-legacy/libudev-device.c deleted file mode 100644 index 8289acf3a9..0000000000 --- a/src/libudev-legacy/libudev-device.c +++ /dev/null @@ -1,1775 +0,0 @@ -/* - * libudev - interface to udev device information - * - * Copyright (C) 2008-2010 Kay Sievers <kay.sievers@vrfy.org> - * - * This library 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. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <unistd.h> -#include <stdbool.h> -#include <errno.h> -#include <string.h> -#include <dirent.h> -#include <fcntl.h> -#include <ctype.h> -#include <net/if.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <linux/sockios.h> - -#include "libudev.h" -#include "libudev-private.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 and have - * a unique name inside that subsystem. - */ - -/** - * udev_device: - * - * Opaque object representing one kernel sys device. - */ -struct udev_device { - struct udev *udev; - struct udev_device *parent_device; - char *syspath; - const char *devpath; - char *sysname; - const char *sysnum; - char *devnode; - mode_t devnode_mode; - char *subsystem; - char *devtype; - char *driver; - char *action; - char *devpath_old; - char *knodename; - char *id_filename; - char **envp; - char *monitor_buf; - size_t monitor_buf_len; - struct udev_list_node devlinks_list; - struct udev_list_node properties_list; - struct udev_list_node sysattr_value_list; - struct udev_list_node sysattr_list; - struct udev_list_node tags_list; - unsigned long long int seqnum; - unsigned long long int usec_initialized; - int timeout; - int devlink_priority; - int refcount; - dev_t devnum; - int ifindex; - int watch_handle; - int maj, min; - bool parent_set; - bool subsystem_set; - bool devtype_set; - bool devlinks_uptodate; - bool envp_uptodate; - bool tags_uptodate; - bool driver_set; - bool info_loaded; - bool db_loaded; - bool uevent_loaded; - bool is_initialized; - bool sysattr_list_read; - bool db_persist; -}; - -/** - * udev_device_get_devnum: - * @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. - **/ -UDEV_EXPORT unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device) -{ - if (udev_device == NULL) - return 0; - return udev_device->seqnum; -} - -static int udev_device_set_seqnum(struct udev_device *udev_device, unsigned long long int seqnum) -{ - char num[32]; - - udev_device->seqnum = seqnum; - snprintf(num, sizeof(num), "%llu", seqnum); - udev_device_add_property(udev_device, "SEQNUM", num); - return 0; -} - -int udev_device_get_ifindex(struct udev_device *udev_device) -{ - if (!udev_device->info_loaded) - udev_device_read_uevent_file(udev_device); - return udev_device->ifindex; -} - -static int udev_device_set_ifindex(struct udev_device *udev_device, int ifindex) -{ - char num[32]; - - udev_device->ifindex = ifindex; - snprintf(num, sizeof(num), "%u", ifindex); - udev_device_add_property(udev_device, "IFINDEX", num); - return 0; -} - -/** - * udev_device_get_devnum: - * @udev_device: udev device - * - * Returns: the device major/minor number. - **/ -UDEV_EXPORT dev_t udev_device_get_devnum(struct udev_device *udev_device) -{ - if (udev_device == NULL) - return makedev(0, 0); - if (!udev_device->info_loaded) - udev_device_read_uevent_file(udev_device); - return udev_device->devnum; -} - -static int udev_device_set_devnum(struct udev_device *udev_device, dev_t devnum) -{ - char num[32]; - - udev_device->devnum = devnum; - - snprintf(num, sizeof(num), "%u", major(devnum)); - udev_device_add_property(udev_device, "MAJOR", num); - snprintf(num, sizeof(num), "%u", minor(devnum)); - udev_device_add_property(udev_device, "MINOR", num); - return 0; -} - -int udev_device_get_timeout(struct udev_device *udev_device) -{ - return udev_device->timeout; -} - -static int udev_device_set_timeout(struct udev_device *udev_device, int timeout) -{ - char num[32]; - - udev_device->timeout = timeout; - snprintf(num, sizeof(num), "%u", timeout); - udev_device_add_property(udev_device, "TIMEOUT", num); - return 0; -} - -const char *udev_device_get_knodename(struct udev_device *udev_device) -{ - return udev_device->knodename; -} - -static int udev_device_set_knodename(struct udev_device *udev_device, const char *knodename) -{ - free(udev_device->knodename); - udev_device->knodename = strdup(knodename); - if (udev_device->knodename == NULL) - return -ENOMEM; - /* do not overwrite the udev property with the kernel property */ - if (udev_device->devnode == NULL) - udev_device_add_property(udev_device, "DEVNAME", udev_device->knodename); - return 0; -} - -const char *udev_device_get_devpath_old(struct udev_device *udev_device) -{ - return udev_device->devpath_old; -} - -static int udev_device_set_devpath_old(struct udev_device *udev_device, const char *devpath_old) -{ - const char *pos; - - free(udev_device->devpath_old); - udev_device->devpath_old = strdup(devpath_old); - if (udev_device->devpath_old == NULL) - return -ENOMEM; - udev_device_add_property(udev_device, "DEVPATH_OLD", udev_device->devpath_old); - - pos = strrchr(udev_device->devpath_old, '/'); - if (pos == NULL) - return -EINVAL; - return 0; -} - -/** - * udev_device_get_driver: - * @udev_device: udev device - * - * Returns: the driver string, or #NULL if there is no driver attached. - **/ -UDEV_EXPORT const char *udev_device_get_driver(struct udev_device *udev_device) -{ - char driver[UTIL_NAME_SIZE]; - - if (udev_device == NULL) - return NULL; - if (!udev_device->driver_set) { - udev_device->driver_set = true; - if (util_get_sys_driver(udev_device->udev, udev_device->syspath, driver, sizeof(driver)) > 0) - udev_device->driver = strdup(driver); - } - return udev_device->driver; -} - -static int udev_device_set_driver(struct udev_device *udev_device, const char *driver) -{ - free(udev_device->driver); - udev_device->driver = strdup(driver); - if (udev_device->driver == NULL) - return -ENOMEM; - udev_device->driver_set = true; - udev_device_add_property(udev_device, "DRIVER", udev_device->driver); - return 0; -} - -/** - * 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 - **/ -UDEV_EXPORT const char *udev_device_get_devtype(struct udev_device *udev_device) -{ - if (udev_device == NULL) - return NULL; - if (!udev_device->devtype_set) { - udev_device->devtype_set = true; - udev_device_read_uevent_file(udev_device); - } - return udev_device->devtype; -} - -static int udev_device_set_devtype(struct udev_device *udev_device, const char *devtype) -{ - free(udev_device->devtype); - udev_device->devtype = strdup(devtype); - if (udev_device->devtype == NULL) - return -ENOMEM; - udev_device->devtype_set = true; - udev_device_add_property(udev_device, "DEVTYPE", udev_device->devtype); - return 0; -} - -static int udev_device_set_subsystem(struct udev_device *udev_device, const char *subsystem) -{ - free(udev_device->subsystem); - udev_device->subsystem = strdup(subsystem); - if (udev_device->subsystem == NULL) - return -ENOMEM; - udev_device->subsystem_set = true; - udev_device_add_property(udev_device, "SUBSYSTEM", udev_device->subsystem); - return 0; -} - -/** - * 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 - **/ -UDEV_EXPORT const char *udev_device_get_subsystem(struct udev_device *udev_device) -{ - char subsystem[UTIL_NAME_SIZE]; - - if (udev_device == NULL) - return NULL; - if (!udev_device->subsystem_set) { - udev_device->subsystem_set = true; - /* read "subsystem" link */ - if (util_get_sys_subsystem(udev_device->udev, udev_device->syspath, subsystem, sizeof(subsystem)) > 0) { - udev_device_set_subsystem(udev_device, subsystem); - return udev_device->subsystem; - } - /* implicit names */ - if (strncmp(udev_device->devpath, "/module/", 8) == 0) { - udev_device_set_subsystem(udev_device, "module"); - return udev_device->subsystem; - } - if (strstr(udev_device->devpath, "/drivers/") != NULL) { - udev_device_set_subsystem(udev_device, "drivers"); - return udev_device->subsystem; - } - if (strncmp(udev_device->devpath, "/subsystem/", 11) == 0 || - strncmp(udev_device->devpath, "/class/", 7) == 0 || - strncmp(udev_device->devpath, "/bus/", 5) == 0) { - udev_device_set_subsystem(udev_device, "subsystem"); - return udev_device->subsystem; - } - } - return udev_device->subsystem; -} - -mode_t udev_device_get_devnode_mode(struct udev_device *udev_device) -{ - if (!udev_device->info_loaded) - udev_device_read_uevent_file(udev_device); - return udev_device->devnode_mode; -} - -static int udev_device_set_devnode_mode(struct udev_device *udev_device, mode_t mode) -{ - char num[32]; - - udev_device->devnode_mode = mode; - snprintf(num, sizeof(num), "%#o", mode); - udev_device_add_property(udev_device, "DEVMODE", num); - return 0; -} - -struct udev_list_entry *udev_device_add_property(struct udev_device *udev_device, const char *key, const char *value) -{ - udev_device->envp_uptodate = false; - if (value == NULL) { - struct udev_list_entry *list_entry; - - list_entry = udev_device_get_properties_list_entry(udev_device); - list_entry = udev_list_entry_get_by_name(list_entry, key); - if (list_entry != NULL) - udev_list_entry_delete(list_entry); - return NULL; - } - return udev_list_entry_add(udev_device->udev, &udev_device->properties_list, key, value, UDEV_LIST_UNIQUE); -} - -static struct udev_list_entry *udev_device_add_property_from_string(struct udev_device *udev_device, const char *property) -{ - char name[UTIL_LINE_SIZE]; - char *val; - - util_strscpy(name, sizeof(name), property); - val = strchr(name, '='); - if (val == NULL) - return NULL; - val[0] = '\0'; - val = &val[1]; - if (val[0] == '\0') - val = NULL; - return udev_device_add_property(udev_device, name, val); -} - -/* - * parse property string, and if needed, update internal values accordingly - * - * udev_device_add_property_from_string_parse_finish() needs to be - * called after adding properties, and its return value checked - * - * udev_device_set_info_loaded() needs to be set, to avoid trying - * to use a device without a DEVPATH set - */ -void udev_device_add_property_from_string_parse(struct udev_device *udev_device, const char *property) -{ - if (strncmp(property, "DEVPATH=", 8) == 0) { - char path[UTIL_PATH_SIZE]; - - util_strscpyl(path, sizeof(path), udev_get_sys_path(udev_device->udev), &property[8], NULL); - udev_device_set_syspath(udev_device, path); - } else if (strncmp(property, "SUBSYSTEM=", 10) == 0) { - udev_device_set_subsystem(udev_device, &property[10]); - } else if (strncmp(property, "DEVTYPE=", 8) == 0) { - udev_device_set_devtype(udev_device, &property[8]); - } else if (strncmp(property, "DEVNAME=", 8) == 0) { - if (property[8] == '/') - udev_device_set_devnode(udev_device, &property[8]); - else - udev_device_set_knodename(udev_device, &property[8]); - } else if (strncmp(property, "DEVLINKS=", 9) == 0) { - char devlinks[UTIL_PATH_SIZE]; - char *slink; - char *next; - - util_strscpy(devlinks, sizeof(devlinks), &property[9]); - slink = devlinks; - next = strchr(slink, ' '); - while (next != NULL) { - next[0] = '\0'; - udev_device_add_devlink(udev_device, slink, 0); - slink = &next[1]; - next = strchr(slink, ' '); - } - if (slink[0] != '\0') - udev_device_add_devlink(udev_device, slink, 0); - } else if (strncmp(property, "TAGS=", 5) == 0) { - char tags[UTIL_PATH_SIZE]; - char *next; - - util_strscpy(tags, sizeof(tags), &property[5]); - next = strchr(tags, ':'); - if (next != NULL) { - next++; - while (next[0] != '\0') { - char *tag; - - tag = next; - next = strchr(tag, ':'); - if (next == NULL) - break; - next[0] = '\0'; - next++; - udev_device_add_tag(udev_device, tag); - } - } - } else if (strncmp(property, "DRIVER=", 7) == 0) { - udev_device_set_driver(udev_device, &property[7]); - } else if (strncmp(property, "ACTION=", 7) == 0) { - udev_device_set_action(udev_device, &property[7]); - } else if (strncmp(property, "MAJOR=", 6) == 0) { - udev_device->maj = strtoull(&property[6], NULL, 10); - } else if (strncmp(property, "MINOR=", 6) == 0) { - udev_device->min = strtoull(&property[6], NULL, 10); - } else if (strncmp(property, "DEVPATH_OLD=", 12) == 0) { - udev_device_set_devpath_old(udev_device, &property[12]); - } else if (strncmp(property, "SEQNUM=", 7) == 0) { - udev_device_set_seqnum(udev_device, strtoull(&property[7], NULL, 10)); - } else if (strncmp(property, "TIMEOUT=", 8) == 0) { - udev_device_set_timeout(udev_device, strtoull(&property[8], NULL, 10)); - } else if (strncmp(property, "IFINDEX=", 8) == 0) { - udev_device_set_ifindex(udev_device, strtoull(&property[8], NULL, 10)); - } else if (strncmp(property, "DEVMODE=", 8) == 0) { - udev_device_set_devnode_mode(udev_device, strtoul(&property[8], NULL, 8)); - } else { - udev_device_add_property_from_string(udev_device, property); - } -} - -int udev_device_add_property_from_string_parse_finish(struct udev_device *udev_device) -{ - if (udev_device->maj > 0) - udev_device_set_devnum(udev_device, makedev(udev_device->maj, udev_device->min)); - udev_device->maj = 0; - udev_device->min = 0; - - if (udev_device->devpath == NULL || udev_device->subsystem == NULL) - return -EINVAL; - return 0; -} - -/** - * udev_device_get_property_value: - * @udev_device: udev device - * @key: property name - * - * Returns: the value of a device property, or #NULL if there is no such property. - **/ -UDEV_EXPORT const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key) -{ - struct udev_list_entry *list_entry; - - if (udev_device == NULL) - return NULL; - if (key == NULL) - return NULL; - - list_entry = udev_device_get_properties_list_entry(udev_device); - list_entry = udev_list_entry_get_by_name(list_entry, key); - return udev_list_entry_get_value(list_entry); -} - -int udev_device_read_db(struct udev_device *udev_device, const char *dbfile) -{ - char filename[UTIL_PATH_SIZE]; - char line[UTIL_LINE_SIZE]; - FILE *f; - - /* providing a database file will always force-load it */ - if (dbfile == NULL) { - const char *id; - - if (udev_device->db_loaded) - return 0; - udev_device->db_loaded = true; - - id = udev_device_get_id_filename(udev_device); - if (id == NULL) - return -1; - util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev_device->udev), "/data/", id, NULL); - dbfile = filename; - } - - f = fopen(dbfile, "re"); - if (f == NULL) { - info(udev_device->udev, "no db file to read %s: %m\n", dbfile); - return -1; - } - udev_device->is_initialized = true; - - while (fgets(line, sizeof(line), f)) { - ssize_t len; - const char *val; - struct udev_list_entry *entry; - - len = strlen(line); - if (len < 4) - break; - line[len-1] = '\0'; - val = &line[2]; - switch(line[0]) { - case 'N': - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_device->udev), "/", val, NULL); - udev_device_set_devnode(udev_device, filename); - break; - case 'S': - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_device->udev), "/", val, NULL); - udev_device_add_devlink(udev_device, filename, 0); - break; - case 'L': - udev_device_set_devlink_priority(udev_device, atoi(val)); - break; - case 'E': - entry = udev_device_add_property_from_string(udev_device, val); - udev_list_entry_set_num(entry, true); - break; - case 'G': - udev_device_add_tag(udev_device, val); - break; - case 'W': - udev_device_set_watch_handle(udev_device, atoi(val)); - break; - case 'I': - udev_device_set_usec_initialized(udev_device, strtoull(val, NULL, 10)); - break; - } - } - fclose(f); - - info(udev_device->udev, "device %p filled with db file data\n", udev_device); - return 0; -} - -int udev_device_read_uevent_file(struct udev_device *udev_device) -{ - char filename[UTIL_PATH_SIZE]; - FILE *f; - char line[UTIL_LINE_SIZE]; - int maj = 0; - int min = 0; - - if (udev_device->uevent_loaded) - return 0; - - util_strscpyl(filename, sizeof(filename), udev_device->syspath, "/uevent", NULL); - f = fopen(filename, "re"); - if (f == NULL) - return -1; - udev_device->uevent_loaded = true; - - while (fgets(line, sizeof(line), f)) { - char *pos; - - pos = strchr(line, '\n'); - if (pos == NULL) - continue; - pos[0] = '\0'; - - if (strncmp(line, "DEVTYPE=", 8) == 0) - udev_device_set_devtype(udev_device, &line[8]); - else if (strncmp(line, "MAJOR=", 6) == 0) - maj = strtoull(&line[6], NULL, 10); - else if (strncmp(line, "MINOR=", 6) == 0) - min = strtoull(&line[6], NULL, 10); - else if (strncmp(line, "IFINDEX=", 8) == 0) - udev_device_set_ifindex(udev_device, strtoull(&line[8], NULL, 10)); - else if (strncmp(line, "DEVNAME=", 8) == 0) - udev_device_set_knodename(udev_device, &line[8]); - else if (strncmp(line, "DEVMODE=", 8) == 0) - udev_device->devnode_mode = strtoul(&line[8], NULL, 8); - - udev_device_add_property_from_string(udev_device, line); - } - - udev_device->devnum = makedev(maj, min); - fclose(f); - return 0; -} - -void udev_device_set_info_loaded(struct udev_device *device) -{ - device->info_loaded = true; -} - -struct udev_device *udev_device_new(struct udev *udev) -{ - struct udev_device *udev_device; - struct udev_list_entry *list_entry; - - if (udev == NULL) - return NULL; - - udev_device = calloc(1, sizeof(struct udev_device)); - if (udev_device == NULL) - return NULL; - udev_device->refcount = 1; - udev_device->udev = udev; - udev_list_init(&udev_device->devlinks_list); - udev_list_init(&udev_device->properties_list); - udev_list_init(&udev_device->sysattr_value_list); - udev_list_init(&udev_device->sysattr_list); - udev_list_init(&udev_device->tags_list); - udev_device->timeout = -1; - udev_device->watch_handle = -1; - /* copy global properties */ - udev_list_entry_foreach(list_entry, udev_get_properties_list_entry(udev)) - udev_device_add_property(udev_device, - udev_list_entry_get_name(list_entry), - udev_list_entry_get_value(list_entry)); - dbg(udev_device->udev, "udev_device: %p created\n", udev_device); - 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 - **/ -UDEV_EXPORT struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) -{ - size_t len; - const char *subdir; - char path[UTIL_PATH_SIZE]; - char *pos; - struct stat statbuf; - struct udev_device *udev_device; - - if (udev == NULL) - return NULL; - if (syspath == NULL) - return NULL; - - /* path starts in sys */ - len = strlen(udev_get_sys_path(udev)); - if (strncmp(syspath, udev_get_sys_path(udev), len) != 0) { - info(udev, "not in sys :%s\n", syspath); - return NULL; - } - - /* path is not a root directory */ - subdir = &syspath[len+1]; - pos = strrchr(subdir, '/'); - if (pos == NULL || pos[1] == '\0' || pos < &subdir[2]) { - dbg(udev, "not a subdir :%s\n", syspath); - return NULL; - } - - /* resolve possible symlink to real path */ - util_strscpy(path, sizeof(path), syspath); - util_resolve_sys_link(udev, path, sizeof(path)); - - if (strncmp(&path[len], "/devices/", 9) == 0) { - char file[UTIL_PATH_SIZE]; - - /* all "devices" require a "uevent" file */ - util_strscpyl(file, sizeof(file), path, "/uevent", NULL); - if (stat(file, &statbuf) != 0) { - dbg(udev, "not a device: %s\n", syspath); - return NULL; - } - } else { - /* everything else just needs to be a directory */ - if (stat(path, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) { - dbg(udev, "directory not found: %s\n", syspath); - return NULL; - } - } - - udev_device = udev_device_new(udev); - if (udev_device == NULL) - return NULL; - - udev_device_set_syspath(udev_device, path); - info(udev, "device %p has devpath '%s'\n", udev_device, udev_device_get_devpath(udev_device)); - - 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 - **/ -UDEV_EXPORT struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum) -{ - char path[UTIL_PATH_SIZE]; - const char *type_str; - - if (type == 'b') - type_str = "block"; - else if (type == 'c') - type_str = "char"; - else - return NULL; - - /* use /sys/dev/{block,char}/<maj>:<min> link */ - snprintf(path, sizeof(path), "%s/dev/%s/%u:%u", - udev_get_sys_path(udev), type_str, major(devnum), minor(devnum)); - return udev_device_new_from_syspath(udev, path); -} - -struct udev_device *udev_device_new_from_id_filename(struct udev *udev, char *id) -{ - char type; - int maj, min; - char subsys[UTIL_PATH_SIZE]; - char *sysname; - - switch(id[0]) { - case 'b': - case 'c': - if (sscanf(id, "%c%i:%i", &type, &maj, &min) != 3) - return NULL; - return udev_device_new_from_devnum(udev, type, makedev(maj, min)); - case 'n': { - int sk; - struct ifreq ifr; - struct udev_device *dev; - int ifindex; - - ifindex = strtoul(&id[1], NULL, 10); - if (ifindex <= 0) - return NULL; - - sk = socket(PF_INET, SOCK_DGRAM, 0); - if (sk < 0) - return NULL; - memset(&ifr, 0x00, sizeof(struct ifreq)); - ifr.ifr_ifindex = ifindex; - if (ioctl(sk, SIOCGIFNAME, &ifr) != 0) { - close(sk); - return NULL; - } - close(sk); - - dev = udev_device_new_from_subsystem_sysname(udev, "net", ifr.ifr_name); - if (dev == NULL) - return NULL; - if (udev_device_get_ifindex(dev) == ifindex) - return dev; - udev_device_unref(dev); - return NULL; - } - case '+': - util_strscpy(subsys, sizeof(subsys), &id[1]); - sysname = strchr(subsys, ':'); - if (sysname == NULL) - return NULL; - sysname[0] = '\0'; - sysname = &sysname[1]; - return udev_device_new_from_subsystem_sysname(udev, subsys, sysname); - default: - return NULL; - } -} - -/** - * 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 - **/ -UDEV_EXPORT struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname) -{ - char path_full[UTIL_PATH_SIZE]; - char *path; - size_t l; - struct stat statbuf; - - path = path_full; - l = util_strpcpyl(&path, sizeof(path_full), udev_get_sys_path(udev), NULL); - - if (strcmp(subsystem, "subsystem") == 0) { - util_strscpyl(path, l, "/subsystem/", sysname, NULL); - if (stat(path_full, &statbuf) == 0) - goto found; - - util_strscpyl(path, l, "/bus/", sysname, NULL); - if (stat(path_full, &statbuf) == 0) - goto found; - - util_strscpyl(path, l, "/class/", sysname, NULL); - if (stat(path_full, &statbuf) == 0) - goto found; - goto out; - } - - if (strcmp(subsystem, "module") == 0) { - util_strscpyl(path, l, "/module/", sysname, NULL); - if (stat(path_full, &statbuf) == 0) - goto found; - goto out; - } - - if (strcmp(subsystem, "drivers") == 0) { - char subsys[UTIL_NAME_SIZE]; - char *driver; - - util_strscpy(subsys, sizeof(subsys), sysname); - driver = strchr(subsys, ':'); - if (driver != NULL) { - driver[0] = '\0'; - driver = &driver[1]; - - util_strscpyl(path, l, "/subsystem/", subsys, "/drivers/", driver, NULL); - if (stat(path_full, &statbuf) == 0) - goto found; - - util_strscpyl(path, l, "/bus/", subsys, "/drivers/", driver, NULL); - if (stat(path_full, &statbuf) == 0) - goto found; - } - goto out; - } - - util_strscpyl(path, l, "/subsystem/", subsystem, "/devices/", sysname, NULL); - if (stat(path_full, &statbuf) == 0) - goto found; - - util_strscpyl(path, l, "/bus/", subsystem, "/devices/", sysname, NULL); - if (stat(path_full, &statbuf) == 0) - goto found; - - util_strscpyl(path, l, "/class/", subsystem, "/", sysname, NULL); - if (stat(path_full, &statbuf) == 0) - goto found; -out: - return NULL; -found: - return udev_device_new_from_syspath(udev, path_full); -} - -/** - * 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 - **/ -UDEV_EXPORT struct udev_device *udev_device_new_from_environment(struct udev *udev) -{ - int i; - struct udev_device *udev_device; - - udev_device = udev_device_new(udev); - if (udev_device == NULL) - return NULL; - udev_device_set_info_loaded(udev_device); - - for (i = 0; environ[i] != NULL; i++) - udev_device_add_property_from_string_parse(udev_device, environ[i]); - - if (udev_device_add_property_from_string_parse_finish(udev_device) < 0) { - info(udev, "missing values, invalid device\n"); - udev_device_unref(udev_device); - udev_device = NULL; - } - - return udev_device; -} - -static struct udev_device *device_new_from_parent(struct udev_device *udev_device) -{ - struct udev_device *udev_device_parent = NULL; - char path[UTIL_PATH_SIZE]; - const char *subdir; - - util_strscpy(path, sizeof(path), udev_device->syspath); - subdir = &path[strlen(udev_get_sys_path(udev_device->udev))+1]; - for (;;) { - char *pos; - - pos = strrchr(subdir, '/'); - if (pos == NULL || pos < &subdir[2]) - break; - pos[0] = '\0'; - udev_device_parent = udev_device_new_from_syspath(udev_device->udev, path); - if (udev_device_parent != NULL) - return udev_device_parent; - } - return NULL; -} - -/** - * 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. - * - * The returned the 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. - **/ -UDEV_EXPORT struct udev_device *udev_device_get_parent(struct udev_device *udev_device) -{ - if (udev_device == NULL) - return NULL; - if (!udev_device->parent_set) { - udev_device->parent_set = true; - udev_device->parent_device = device_new_from_parent(udev_device); - } - if (udev_device->parent_device != NULL) - dbg(udev_device->udev, "returning existing parent %p\n", udev_device->parent_device); - return udev_device->parent_device; -} - -/** - * 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. - * - * The returned the 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. - **/ -UDEV_EXPORT struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype) -{ - struct udev_device *parent; - - if (subsystem == NULL) - return NULL; - - parent = udev_device_get_parent(udev_device); - while (parent != NULL) { - const char *parent_subsystem; - const char *parent_devtype; - - parent_subsystem = udev_device_get_subsystem(parent); - if (parent_subsystem != NULL && strcmp(parent_subsystem, subsystem) == 0) { - if (devtype == NULL) - break; - parent_devtype = udev_device_get_devtype(parent); - if (parent_devtype != NULL && strcmp(parent_devtype, devtype) == 0) - break; - } - parent = udev_device_get_parent(parent); - } - return parent; -} - -/** - * udev_device_get_udev: - * @udev_device: udev device - * - * Retrieve the udev library context the device was created with. - * - * Returns: the udev library context - **/ -UDEV_EXPORT struct udev *udev_device_get_udev(struct udev_device *udev_device) -{ - if (udev_device == NULL) - return NULL; - return udev_device->udev; -} - -/** - * udev_device_ref: - * @udev_device: udev device - * - * Take a reference of a udev device. - * - * Returns: the passed udev device - **/ -UDEV_EXPORT struct udev_device *udev_device_ref(struct udev_device *udev_device) -{ - if (udev_device == NULL) - return NULL; - 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. - * - **/ -UDEV_EXPORT void udev_device_unref(struct udev_device *udev_device) -{ - if (udev_device == NULL) - return; - udev_device->refcount--; - if (udev_device->refcount > 0) - return; - if (udev_device->parent_device != NULL) - udev_device_unref(udev_device->parent_device); - free(udev_device->syspath); - free(udev_device->sysname); - free(udev_device->devnode); - free(udev_device->subsystem); - free(udev_device->devtype); - udev_list_cleanup_entries(udev_device->udev, &udev_device->devlinks_list); - udev_list_cleanup_entries(udev_device->udev, &udev_device->properties_list); - udev_list_cleanup_entries(udev_device->udev, &udev_device->sysattr_value_list); - udev_list_cleanup_entries(udev_device->udev, &udev_device->sysattr_list); - udev_list_cleanup_entries(udev_device->udev, &udev_device->tags_list); - free(udev_device->action); - free(udev_device->driver); - free(udev_device->devpath_old); - free(udev_device->knodename); - free(udev_device->id_filename); - free(udev_device->envp); - free(udev_device->monitor_buf); - dbg(udev_device->udev, "udev_device: %p released\n", udev_device); - free(udev_device); -} - -/** - * 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 - **/ -UDEV_EXPORT const char *udev_device_get_devpath(struct udev_device *udev_device) -{ - if (udev_device == NULL) - return NULL; - return udev_device->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 - **/ -UDEV_EXPORT const char *udev_device_get_syspath(struct udev_device *udev_device) -{ - if (udev_device == NULL) - return NULL; - return udev_device->syspath; -} - -/** - * udev_device_get_sysname: - * @udev_device: udev device - * - * Returns: the sys name of the device device - **/ -UDEV_EXPORT const char *udev_device_get_sysname(struct udev_device *udev_device) -{ - if (udev_device == NULL) - return NULL; - return udev_device->sysname; -} - -/** - * udev_device_get_sysnum: - * @udev_device: udev device - * - * Returns: the trailing number of of the device name - **/ -UDEV_EXPORT const char *udev_device_get_sysnum(struct udev_device *udev_device) -{ - if (udev_device == NULL) - return NULL; - return udev_device->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 - **/ -UDEV_EXPORT const char *udev_device_get_devnode(struct udev_device *udev_device) -{ - if (udev_device == NULL) - return NULL; - if (!udev_device->info_loaded) { - udev_device_read_uevent_file(udev_device); - udev_device_read_db(udev_device, NULL); - } - - /* we might get called before we handled an event and have a db, use the kernel-provided name */ - if (udev_device->devnode == NULL && udev_device_get_knodename(udev_device) != NULL) { - char filename[UTIL_NAME_SIZE]; - - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_device->udev), "/", - udev_device_get_knodename(udev_device), NULL); - udev_device_set_devnode(udev_device, filename); - return udev_device->devnode; - } - - return udev_device->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_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 - **/ -UDEV_EXPORT struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device) -{ - if (udev_device == NULL) - return NULL; - if (!udev_device->info_loaded) - udev_device_read_db(udev_device, NULL); - return udev_list_get_entry(&udev_device->devlinks_list); -} - -void udev_device_cleanup_devlinks_list(struct udev_device *udev_device) -{ - udev_device->devlinks_uptodate = false; - udev_list_cleanup_entries(udev_device->udev, &udev_device->devlinks_list); -} - -/** - * udev_device_get_properties_list_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_next(), - * which returns #NULL if no more entries exist. The property name - * can be retrieved from the list entry by udev_list_get_name(), - * the property value by udev_list_get_value(). - * - * Returns: the first entry of the property list - **/ -UDEV_EXPORT struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device) -{ - if (udev_device == NULL) - return NULL; - if (!udev_device->info_loaded) { - udev_device_read_uevent_file(udev_device); - udev_device_read_db(udev_device, NULL); - } - if (!udev_device->devlinks_uptodate) { - char symlinks[UTIL_PATH_SIZE]; - struct udev_list_entry *list_entry; - - udev_device->devlinks_uptodate = true; - list_entry = udev_device_get_devlinks_list_entry(udev_device); - if (list_entry != NULL) { - char *s; - size_t l; - - s = symlinks; - l = util_strpcpyl(&s, sizeof(symlinks), udev_list_entry_get_name(list_entry), NULL); - udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry)) - l = util_strpcpyl(&s, l, " ", udev_list_entry_get_name(list_entry), NULL); - udev_device_add_property(udev_device, "DEVLINKS", symlinks); - } - } - if (!udev_device->tags_uptodate) { - udev_device->tags_uptodate = true; - if (udev_device_get_tags_list_entry(udev_device) != NULL) { - char tags[UTIL_PATH_SIZE]; - struct udev_list_entry *list_entry; - char *s; - size_t l; - - s = tags; - l = util_strpcpyl(&s, sizeof(tags), ":", NULL); - udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(udev_device)) - l = util_strpcpyl(&s, l, udev_list_entry_get_name(list_entry), ":", NULL); - udev_device_add_property(udev_device, "TAGS", tags); - } - } - return udev_list_get_entry(&udev_device->properties_list); -} - -/** - * 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. - **/ -UDEV_EXPORT const char *udev_device_get_action(struct udev_device *udev_device) -{ - if (udev_device == NULL) - return NULL; - return udev_device->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. - **/ -UDEV_EXPORT unsigned long long int udev_device_get_usec_since_initialized(struct udev_device *udev_device) -{ - unsigned long long now; - - if (udev_device == NULL) - return 0; - if (!udev_device->info_loaded) - udev_device_read_db(udev_device, NULL); - if (udev_device->usec_initialized == 0) - return 0; - now = now_usec(); - if (now == 0) - return 0; - return now - udev_device->usec_initialized; -} - -unsigned long long udev_device_get_usec_initialized(struct udev_device *udev_device) -{ - return udev_device->usec_initialized; -} - -void udev_device_set_usec_initialized(struct udev_device *udev_device, unsigned long long usec_initialized) -{ - udev_device->usec_initialized = usec_initialized; -} - -/** - * 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. - **/ -UDEV_EXPORT const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr) -{ - struct udev_list_entry *list_entry; - char path[UTIL_PATH_SIZE]; - char value[4096]; - struct stat statbuf; - int fd; - ssize_t size; - const char *val = NULL; - - if (udev_device == NULL) - return NULL; - if (sysattr == NULL) - return NULL; - - /* look for possibly already cached result */ - udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_device->sysattr_value_list)) { - if (strcmp(udev_list_entry_get_name(list_entry), sysattr) == 0) { - dbg(udev_device->udev, "got '%s' (%s) from cache\n", - sysattr, udev_list_entry_get_value(list_entry)); - return udev_list_entry_get_value(list_entry); - } - } - - util_strscpyl(path, sizeof(path), udev_device_get_syspath(udev_device), "/", sysattr, NULL); - if (lstat(path, &statbuf) != 0) { - dbg(udev_device->udev, "no attribute '%s', keep negative entry\n", path); - udev_list_entry_add(udev_device->udev, &udev_device->sysattr_value_list, sysattr, NULL, 0); - goto out; - } - - if (S_ISLNK(statbuf.st_mode)) { - char target[UTIL_NAME_SIZE]; - int len; - char *pos; - - /* some core links return the last element of the target path */ - if (strcmp(sysattr, "driver") != 0 && - strcmp(sysattr, "subsystem") != 0 && - strcmp(sysattr, "module") != 0) - goto out; - - len = readlink(path, target, sizeof(target)); - if (len <= 0 || len == sizeof(target)) - goto out; - target[len] = '\0'; - - pos = strrchr(target, '/'); - if (pos != NULL) { - pos = &pos[1]; - dbg(udev_device->udev, "cache '%s' with link value '%s'\n", sysattr, pos); - list_entry = udev_list_entry_add(udev_device->udev, &udev_device->sysattr_value_list, sysattr, pos, 0); - val = udev_list_entry_get_value(list_entry); - } - - goto out; - } - - /* skip directories */ - if (S_ISDIR(statbuf.st_mode)) - goto out; - - /* skip non-readable files */ - if ((statbuf.st_mode & S_IRUSR) == 0) - goto out; - - /* read attribute value */ - fd = open(path, O_RDONLY|O_CLOEXEC); - if (fd < 0) { - dbg(udev_device->udev, "attribute '%s' can not be opened\n", path); - goto out; - } - size = read(fd, value, sizeof(value)); - close(fd); - if (size < 0) - goto out; - if (size == sizeof(value)) - goto out; - - /* got a valid value, store it in cache and return it */ - value[size] = '\0'; - util_remove_trailing_chars(value, '\n'); - dbg(udev_device->udev, "'%s' has attribute value '%s'\n", path, value); - list_entry = udev_list_entry_add(udev_device->udev, &udev_device->sysattr_value_list, sysattr, value, 0); - val = udev_list_entry_get_value(list_entry); -out: - return val; -} - -static int udev_device_sysattr_list_read(struct udev_device *udev_device) -{ - struct dirent *dent; - DIR *dir; - int num = 0; - - if (udev_device == NULL) - return -1; - if (udev_device->sysattr_list_read) - return 0; - - dir = opendir(udev_device_get_syspath(udev_device)); - if (!dir) { - dbg(udev_device->udev, "sysfs dir '%s' can not be opened\n", - udev_device_get_syspath(udev_device)); - return -1; - } - - for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { - char path[UTIL_PATH_SIZE]; - struct stat statbuf; - - /* only handle symlinks and regular files */ - if (dent->d_type != DT_LNK && dent->d_type != DT_REG) - continue; - - util_strscpyl(path, sizeof(path), udev_device_get_syspath(udev_device), "/", dent->d_name, NULL); - if (lstat(path, &statbuf) != 0) - continue; - if ((statbuf.st_mode & S_IRUSR) == 0) - continue; - - udev_list_entry_add(udev_device->udev, &udev_device->sysattr_list, - dent->d_name, NULL, 0); - num++; - } - - closedir(dir); - dbg(udev_device->udev, "found %d sysattrs for '%s'\n", num, udev_device_get_syspath(udev_device)); - udev_device->sysattr_list_read = true; - - return num; -} - -/** - * 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 - **/ -UDEV_EXPORT struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device) -{ - if (!udev_device->sysattr_list_read) { - int ret; - ret = udev_device_sysattr_list_read(udev_device); - if (0 > ret) - return NULL; - } - - return udev_list_get_entry(&udev_device->sysattr_list); -} - -int udev_device_set_syspath(struct udev_device *udev_device, const char *syspath) -{ - const char *pos; - size_t len; - - free(udev_device->syspath); - udev_device->syspath = strdup(syspath); - if (udev_device->syspath == NULL) - return -ENOMEM; - udev_device->devpath = &udev_device->syspath[strlen(udev_get_sys_path(udev_device->udev))]; - udev_device_add_property(udev_device, "DEVPATH", udev_device->devpath); - - pos = strrchr(udev_device->syspath, '/'); - if (pos == NULL) - return -EINVAL; - udev_device->sysname = strdup(&pos[1]); - if (udev_device->sysname == NULL) - return -ENOMEM; - - /* some devices have '!' in their name, change that to '/' */ - len = 0; - while (udev_device->sysname[len] != '\0') { - if (udev_device->sysname[len] == '!') - udev_device->sysname[len] = '/'; - len++; - } - - /* trailing number */ - while (len > 0 && isdigit(udev_device->sysname[--len])) - udev_device->sysnum = &udev_device->sysname[len]; - - /* sysname is completely numeric */ - if (len == 0) - udev_device->sysnum = NULL; - - return 0; -} - -int udev_device_set_devnode(struct udev_device *udev_device, const char *devnode) -{ - free(udev_device->devnode); - udev_device->devnode = strdup(devnode); - if (udev_device->devnode == NULL) - return -ENOMEM; - udev_device_add_property(udev_device, "DEVNAME", udev_device->devnode); - return 0; -} - -int udev_device_add_devlink(struct udev_device *udev_device, const char *devlink, int unique) -{ - struct udev_list_entry *list_entry; - - udev_device->devlinks_uptodate = false; - list_entry = udev_list_entry_add(udev_device->udev, &udev_device->devlinks_list, devlink, NULL, UDEV_LIST_UNIQUE); - if (list_entry == NULL) - return -ENOMEM; - if (unique) - udev_list_entry_set_num(list_entry, true); - return 0; -} - -const char *udev_device_get_id_filename(struct udev_device *udev_device) -{ - if (udev_device->id_filename == NULL) { - if (udev_device_get_subsystem(udev_device) == NULL) - return NULL; - - if (major(udev_device_get_devnum(udev_device)) > 0) { - /* use dev_t -- b259:131072, c254:0 */ - if (asprintf(&udev_device->id_filename, "%c%u:%u", - strcmp(udev_device_get_subsystem(udev_device), "block") == 0 ? 'b' : 'c', - major(udev_device_get_devnum(udev_device)), - minor(udev_device_get_devnum(udev_device))) < 0) - udev_device->id_filename = NULL; - } else if (udev_device_get_ifindex(udev_device) > 0) { - /* use netdev ifindex -- n3 */ - if (asprintf(&udev_device->id_filename, "n%u", udev_device_get_ifindex(udev_device)) < 0) - udev_device->id_filename = NULL; - } else { - /* - * use $subsys:$syname -- pci:0000:00:1f.2 - * sysname() has '!' translated, get it from devpath - */ - const char *sysname; - sysname = strrchr(udev_device->devpath, '/'); - if (sysname == NULL) - return NULL; - sysname = &sysname[1]; - if (asprintf(&udev_device->id_filename, "+%s:%s", udev_device_get_subsystem(udev_device), sysname) < 0) - udev_device->id_filename = NULL; - } - } - return udev_device->id_filename; -} - -/** - * 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. - **/ -UDEV_EXPORT int udev_device_get_is_initialized(struct udev_device *udev_device) -{ - if (!udev_device->info_loaded) - udev_device_read_db(udev_device, NULL); - return udev_device->is_initialized; -} - -void udev_device_set_is_initialized(struct udev_device *udev_device) -{ - udev_device->is_initialized = true; -} - -int udev_device_add_tag(struct udev_device *udev_device, const char *tag) -{ - if (strchr(tag, ':') != NULL || strchr(tag, ' ') != NULL) - return -EINVAL; - udev_device->tags_uptodate = false; - if (udev_list_entry_add(udev_device->udev, &udev_device->tags_list, tag, NULL, UDEV_LIST_UNIQUE) != NULL) - return 0; - return -ENOMEM; -} - -void udev_device_cleanup_tags_list(struct udev_device *udev_device) -{ - udev_device->tags_uptodate = false; - udev_list_cleanup_entries(udev_device->udev, &udev_device->tags_list); -} - -/** - * 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_next(), - * which returns #NULL if no more entries exist. The tag string - * can be retrieved from the list entry by udev_list_get_name(). - * - * Returns: the first entry of the tag list - **/ -UDEV_EXPORT struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device) -{ - if (udev_device == NULL) - return NULL; - return udev_list_get_entry(&udev_device->tags_list); -} - -int udev_device_has_tag(struct udev_device *udev_device, const char *tag) -{ - struct udev_list_entry *list_entry; - - if (!udev_device->info_loaded) - udev_device_read_db(udev_device, NULL); - list_entry = udev_device_get_tags_list_entry(udev_device); - list_entry = udev_list_entry_get_by_name(list_entry, tag); - if (list_entry != NULL) - return 1; - return 0; -} - -#define ENVP_SIZE 128 -#define MONITOR_BUF_SIZE 4096 -static int update_envp_monitor_buf(struct udev_device *udev_device) -{ - struct udev_list_entry *list_entry; - char *s; - size_t l; - unsigned int i; - - /* monitor buffer of property strings */ - free(udev_device->monitor_buf); - udev_device->monitor_buf_len = 0; - udev_device->monitor_buf = malloc(MONITOR_BUF_SIZE); - if (udev_device->monitor_buf == NULL) - return -ENOMEM; - - /* envp array, strings will point into monitor buffer */ - if (udev_device->envp == NULL) - udev_device->envp = malloc(sizeof(char *) * ENVP_SIZE); - if (udev_device->envp == NULL) - return -ENOMEM; - - i = 0; - s = udev_device->monitor_buf; - l = MONITOR_BUF_SIZE; - udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(udev_device)) { - const char *key; - - key = udev_list_entry_get_name(list_entry); - /* skip private variables */ - if (key[0] == '.') - continue; - - /* add string to envp array */ - udev_device->envp[i++] = s; - if (i+1 >= ENVP_SIZE) - return -EINVAL; - - /* add property string to monitor buffer */ - l = util_strpcpyl(&s, l, key, "=", udev_list_entry_get_value(list_entry), NULL); - if (l == 0) - return -EINVAL; - /* advance past the trailing '\0' that util_strpcpyl() guarantees */ - s++; - l--; - } - udev_device->envp[i] = NULL; - udev_device->monitor_buf_len = s - udev_device->monitor_buf; - udev_device->envp_uptodate = true; - dbg(udev_device->udev, "filled envp/monitor buffer, %u properties, %zu bytes\n", - i, udev_device->monitor_buf_len); - return 0; -} - -char **udev_device_get_properties_envp(struct udev_device *udev_device) -{ - if (!udev_device->envp_uptodate) - if (update_envp_monitor_buf(udev_device) != 0) - return NULL; - return udev_device->envp; -} - -ssize_t udev_device_get_properties_monitor_buf(struct udev_device *udev_device, const char **buf) -{ - if (!udev_device->envp_uptodate) - if (update_envp_monitor_buf(udev_device) != 0) - return -EINVAL; - *buf = udev_device->monitor_buf; - return udev_device->monitor_buf_len; -} - -int udev_device_set_action(struct udev_device *udev_device, const char *action) -{ - free(udev_device->action); - udev_device->action = strdup(action); - if (udev_device->action == NULL) - return -ENOMEM; - udev_device_add_property(udev_device, "ACTION", udev_device->action); - return 0; -} - -int udev_device_get_devlink_priority(struct udev_device *udev_device) -{ - if (!udev_device->info_loaded) - udev_device_read_db(udev_device, NULL); - return udev_device->devlink_priority; -} - -int udev_device_set_devlink_priority(struct udev_device *udev_device, int prio) -{ - udev_device->devlink_priority = prio; - return 0; -} - -int udev_device_get_watch_handle(struct udev_device *udev_device) -{ - if (!udev_device->info_loaded) - udev_device_read_db(udev_device, NULL); - return udev_device->watch_handle; -} - -int udev_device_set_watch_handle(struct udev_device *udev_device, int handle) -{ - udev_device->watch_handle = handle; - return 0; -} - -bool udev_device_get_db_persist(struct udev_device *udev_device) -{ - return udev_device->db_persist; -} - -void udev_device_set_db_persist(struct udev_device *udev_device) -{ - udev_device->db_persist = true; -} diff --git a/src/libudev-legacy/libudev-enumerate.c b/src/libudev-legacy/libudev-enumerate.c deleted file mode 100644 index 6e51726f08..0000000000 --- a/src/libudev-legacy/libudev-enumerate.c +++ /dev/null @@ -1,831 +0,0 @@ -/* - * libudev - interface to udev device information - * - * Copyright (C) 2008-2010 Kay Sievers <kay.sievers@vrfy.org> - * - * This library 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. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <dirent.h> -#include <fnmatch.h> -#include <stdbool.h> -#include <sys/stat.h> -#include <sys/param.h> - -#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_node sysattr_match_list; - struct udev_list_node sysattr_nomatch_list; - struct udev_list_node subsystem_match_list; - struct udev_list_node subsystem_nomatch_list; - struct udev_list_node sysname_match_list; - struct udev_list_node properties_match_list; - struct udev_list_node tags_match_list; - struct udev_list_node 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 - * - * Returns: an enumeration context - **/ -UDEV_EXPORT struct udev_enumerate *udev_enumerate_new(struct udev *udev) -{ - struct udev_enumerate *udev_enumerate; - - udev_enumerate = calloc(1, sizeof(struct udev_enumerate)); - if (udev_enumerate == NULL) - return NULL; - udev_enumerate->refcount = 1; - udev_enumerate->udev = udev; - udev_list_init(&udev_enumerate->sysattr_match_list); - udev_list_init(&udev_enumerate->sysattr_nomatch_list); - udev_list_init(&udev_enumerate->subsystem_match_list); - udev_list_init(&udev_enumerate->subsystem_nomatch_list); - udev_list_init(&udev_enumerate->sysname_match_list); - udev_list_init(&udev_enumerate->properties_match_list); - udev_list_init(&udev_enumerate->tags_match_list); - udev_list_init(&udev_enumerate->devices_list); - return udev_enumerate; -} - -/** - * udev_enumerate_ref: - * @udev_enumerate: context - * - * Take a reference of a enumeration context. - * - * Returns: the passed enumeration context - **/ -UDEV_EXPORT 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. - **/ -UDEV_EXPORT void udev_enumerate_unref(struct udev_enumerate *udev_enumerate) -{ - unsigned int i; - - if (udev_enumerate == NULL) - return; - udev_enumerate->refcount--; - if (udev_enumerate->refcount > 0) - return; - udev_list_cleanup_entries(udev_enumerate->udev, &udev_enumerate->sysattr_match_list); - udev_list_cleanup_entries(udev_enumerate->udev, &udev_enumerate->sysattr_nomatch_list); - udev_list_cleanup_entries(udev_enumerate->udev, &udev_enumerate->subsystem_match_list); - udev_list_cleanup_entries(udev_enumerate->udev, &udev_enumerate->subsystem_nomatch_list); - udev_list_cleanup_entries(udev_enumerate->udev, &udev_enumerate->sysname_match_list); - udev_list_cleanup_entries(udev_enumerate->udev, &udev_enumerate->properties_match_list); - udev_list_cleanup_entries(udev_enumerate->udev, &udev_enumerate->tags_match_list); - udev_list_cleanup_entries(udev_enumerate->udev, &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); -} - -/** - * udev_enumerate_get_udev: - * @udev_enumerate: context - * - * Returns: the udev library context. - */ -UDEV_EXPORT 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 - }; - size_t len; - int i; - - len = strlen(udev_get_sys_path(udev)); - for (i = 0; delay_device_list[i] != NULL; i++) { - if (strstr(&syspath[len], delay_device_list[i]) != NULL) { - dbg(udev, "delaying: %s\n", syspath); - 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 (strncmp(c, "/controlC", 9) == 0) - return c - syspath + 1; - } - - return 0; -} - -/** - * udev_enumerate_get_list_entry: - * @udev_enumerate: context - * - * Returns: the first entry of the sorted list of device paths. - */ -UDEV_EXPORT 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; - unsigned int max; - struct syspath *prev = NULL, *move_later = NULL; - size_t move_later_prefix = 0; - - udev_list_cleanup_entries(udev_enumerate->udev, &udev_enumerate->devices_list); - qsort(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) { - move_later_prefix = devices_delay_later(udev_enumerate->udev, entry->syspath); - - if (move_later_prefix > 0) { - move_later = entry; - continue; - } - } - - if (move_later && - strncmp(entry->syspath, move_later->syspath, move_later_prefix) != 0) { - - udev_list_entry_add(udev_enumerate->udev, &udev_enumerate->devices_list, - move_later->syspath, NULL, 0); - move_later = NULL; - } - - udev_list_entry_add(udev_enumerate->udev, &udev_enumerate->devices_list, - entry->syspath, NULL, 0); - } - - if (move_later) - udev_list_entry_add(udev_enumerate->udev, &udev_enumerate->devices_list, - move_later->syspath, NULL, 0); - - /* 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->udev, &udev_enumerate->devices_list, - entry->syspath, NULL, 0); - 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 - * - * Returns: 0 on success, otherwise a negative error value. - */ -UDEV_EXPORT 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_get_udev(udev_enumerate), - &udev_enumerate->subsystem_match_list, subsystem, NULL, UDEV_LIST_UNIQUE) == 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 - * - * Returns: 0 on success, otherwise a negative error value. - */ -UDEV_EXPORT 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_get_udev(udev_enumerate), - &udev_enumerate->subsystem_nomatch_list, subsystem, NULL, UDEV_LIST_UNIQUE) == 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 - * - * Returns: 0 on success, otherwise a negative error value. - */ -UDEV_EXPORT 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_get_udev(udev_enumerate), - &udev_enumerate->sysattr_match_list, sysattr, value, 0) == 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 - * - * Returns: 0 on success, otherwise a negative error value. - */ -UDEV_EXPORT 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_get_udev(udev_enumerate), - &udev_enumerate->sysattr_nomatch_list, sysattr, value, 0) == 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 - * - * Returns: 0 on success, otherwise a negative error value. - */ -UDEV_EXPORT 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_get_udev(udev_enumerate), - &udev_enumerate->properties_match_list, property, value, 0) == 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 - * - * Returns: 0 on success, otherwise a negative error value. - */ -UDEV_EXPORT 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_get_udev(udev_enumerate), - &udev_enumerate->tags_match_list, tag, NULL, UDEV_LIST_UNIQUE) == NULL) - return -ENOMEM; - 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. - */ -UDEV_EXPORT 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 - * - * Returns: 0 on success, otherwise a negative error value. - */ -UDEV_EXPORT 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_get_udev(udev_enumerate), - &udev_enumerate->sysname_match_list, sysname, NULL, UDEV_LIST_UNIQUE) == 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_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) -{ - struct udev *udev = udev_enumerate_get_udev(udev_enumerate); - char path[UTIL_PATH_SIZE]; - size_t l; - char *s; - DIR *dir; - struct dirent *dent; - - s = path; - l = util_strpcpyl(&s, sizeof(path), udev_get_sys_path(udev), "/", basedir, NULL); - if (subdir1 != NULL) - l = util_strpcpyl(&s, l, "/", subdir1, NULL); - if (subdir2 != NULL) - util_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; - - util_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_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; - - 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) -{ - struct udev *udev = udev_enumerate_get_udev(udev_enumerate); - - char path[UTIL_PATH_SIZE]; - DIR *dir; - struct dirent *dent; - - util_strscpyl(path, sizeof(path), udev_get_sys_path(udev), "/", 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. - */ -UDEV_EXPORT 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; -} - -/** - * udev_enumerate_scan_devices: - * @udev_enumerate: udev enumeration context - * - * Returns: 0 on success, otherwise a negative error value. - **/ -UDEV_EXPORT int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) -{ - struct udev *udev = udev_enumerate_get_udev(udev_enumerate); - char base[UTIL_PATH_SIZE]; - struct stat statbuf; - - if (udev_enumerate == NULL) - return -EINVAL; - - if (udev_list_get_entry(&udev_enumerate->tags_match_list) != NULL) { - 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]; - - util_strscpyl(path, sizeof(path), udev_get_run_path(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_id_filename(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_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); - } - } else { - util_strscpyl(base, sizeof(base), udev_get_sys_path(udev), "/subsystem", NULL); - if (stat(base, &statbuf) == 0) { - /* we have /subsystem/, forget all the old stuff */ - dbg(udev, "searching '/subsystem/*/devices/*' dir\n"); - scan_dir(udev_enumerate, "subsystem", "devices", NULL); - } else { - dbg(udev, "searching '/bus/*/devices/*' dir\n"); - scan_dir(udev_enumerate, "bus", "devices", NULL); - dbg(udev, "searching '/class/*' dir\n"); - scan_dir(udev_enumerate, "class", NULL, NULL); - } - } - - return 0; -} - -/** - * udev_enumerate_scan_subsystems: - * @udev_enumerate: udev enumeration context - * - * Returns: 0 on success, otherwise a negative error value. - **/ -UDEV_EXPORT int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate) -{ - struct udev *udev = udev_enumerate_get_udev(udev_enumerate); - char base[UTIL_PATH_SIZE]; - struct stat statbuf; - const char *subsysdir; - - if (udev_enumerate == NULL) - return -EINVAL; - - util_strscpyl(base, sizeof(base), udev_get_sys_path(udev), "/subsystem", NULL); - if (stat(base, &statbuf) == 0) - subsysdir = "subsystem"; - else - subsysdir = "bus"; - if (match_subsystem(udev_enumerate, "subsystem")) { - dbg(udev, "searching '%s/*' dir\n", subsysdir); - scan_dir_and_add_devices(udev_enumerate, subsysdir, NULL, NULL); - } - if (match_subsystem(udev_enumerate, "drivers")) { - dbg(udev, "searching '%s/*/drivers/*' dir\n", subsysdir); - scan_dir(udev_enumerate, subsysdir, "drivers", "drivers"); - } - return 0; -} diff --git a/src/libudev-legacy/libudev-list.c b/src/libudev-legacy/libudev-list.c deleted file mode 100644 index e828a4e4c6..0000000000 --- a/src/libudev-legacy/libudev-list.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - * libudev - interface to udev device information - * - * Copyright (C) 2008 Kay Sievers <kay.sievers@vrfy.org> - * - * This library 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. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> - -#include "libudev.h" -#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 *udev; - struct udev_list_node *list; - char *name; - char *value; - int num; -}; - -/* the list's head points to itself if empty */ -void udev_list_init(struct udev_list_node *list) -{ - list->next = list; - list->prev = list; -} - -int udev_list_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 struct udev_list_entry *list_node_to_entry(struct udev_list_node *node) -{ - char *list; - - list = (char *)node; - list -= offsetof(struct udev_list_entry, node); - return (struct udev_list_entry *)list; -} - -/* insert entry into a list as the last element */ -void udev_list_entry_append(struct udev_list_entry *new, struct udev_list_node *list) -{ - /* inserting before the list head make the node the last node in the list */ - udev_list_node_insert_between(&new->node, list->prev, list); - new->list = list; -} - -/* remove entry from a list */ -void udev_list_entry_remove(struct udev_list_entry *entry) -{ - udev_list_node_remove(&entry->node); - entry->list = NULL; -} - -/* insert entry into a list, before a given existing entry */ -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; -} - -struct udev_list_entry *udev_list_entry_add(struct udev *udev, struct udev_list_node *list, - const char *name, const char *value, - unsigned int flags) -{ - struct udev_list_entry *entry_loop = NULL; - struct udev_list_entry *entry_new; - - if (flags & UDEV_LIST_UNIQUE) { - udev_list_entry_foreach(entry_loop, udev_list_get_entry(list)) { - if (strcmp(entry_loop->name, name) == 0) { - dbg(udev, "'%s' is already in the list\n", name); - free(entry_loop->value); - if (value == NULL) { - entry_loop->value = NULL; - dbg(udev, "'%s' value unset\n", name); - return entry_loop; - } - entry_loop->value = strdup(value); - if (entry_loop->value == NULL) - return NULL; - dbg(udev, "'%s' value replaced with '%s'\n", name, value); - return entry_loop; - } - } - } - - if (flags & UDEV_LIST_SORT) { - udev_list_entry_foreach(entry_loop, udev_list_get_entry(list)) { - if (strcmp(entry_loop->name, name) > 0) - break; - } - } - - entry_new = malloc(sizeof(struct udev_list_entry)); - if (entry_new == NULL) - return NULL; - memset(entry_new, 0x00, sizeof(struct udev_list_entry)); - entry_new->udev = udev; - entry_new->name = strdup(name); - if (entry_new->name == NULL) { - free(entry_new); - return NULL; - } - - if (value != NULL) { - entry_new->value = strdup(value); - if (entry_new->value == NULL) { - free(entry_new->name); - free(entry_new); - return NULL; - } - } - - if (entry_loop != NULL) - udev_list_entry_insert_before(entry_new, entry_loop); - else - udev_list_entry_append(entry_new, list); - - dbg(udev, "'%s=%s' added\n", entry_new->name, entry_new->value); - return entry_new; -} - -void udev_list_entry_delete(struct udev_list_entry *entry) -{ - udev_list_node_remove(&entry->node); - free(entry->name); - free(entry->value); - free(entry); -} - -void udev_list_cleanup_entries(struct udev *udev, struct udev_list_node *list) -{ - struct udev_list_entry *entry_loop; - struct udev_list_entry *entry_tmp; - - 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_node *list) -{ - if (udev_list_is_empty(list)) - return NULL; - return list_node_to_entry(list->next); -} - -/** - * udev_list_entry_get_next: - * @list_entry: current entry - * - * Returns: the next entry from the list, #NULL is no more entries are found. - */ -UDEV_EXPORT 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) - return NULL; - return list_node_to_entry(next); -} - -/** - * udev_list_entry_get_by_name: - * @list_entry: current entry - * @name: name string to match - * - * Returns: the entry where @name matched, #NULL if no matching entry is found. - */ -UDEV_EXPORT struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name) -{ - struct udev_list_entry *entry; - - udev_list_entry_foreach(entry, list_entry) { - if (strcmp(udev_list_entry_get_name(entry), name) == 0) { - dbg(entry->udev, "found '%s=%s'\n", entry->name, entry->value); - return entry; - } - } - return NULL; -} - -/** - * udev_list_entry_get_name: - * @list_entry: current entry - * - * Returns: the name string of this entry. - */ -UDEV_EXPORT 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 - * - * Returns: the value string of this entry. - */ -UDEV_EXPORT 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-legacy/libudev-monitor.c b/src/libudev-legacy/libudev-monitor.c deleted file mode 100644 index 85ab23bdd4..0000000000 --- a/src/libudev-legacy/libudev-monitor.c +++ /dev/null @@ -1,876 +0,0 @@ -/* - * libudev - interface to udev device information - * - * Copyright (C) 2008-2010 Kay Sievers <kay.sievers@vrfy.org> - * - * This library 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. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <dirent.h> -#include <sys/poll.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <arpa/inet.h> -#include <linux/netlink.h> -#include <linux/filter.h> - -#include "libudev.h" -#include "libudev-private.h" - -/** - * SECTION:libudev-monitor - * @short_description: device event source - * - * Connects to a device event source. - */ - -/** - * udev_monitor: - * - * Opaque object handling one event source. - */ -struct udev_monitor { - struct udev *udev; - int refcount; - int sock; - struct sockaddr_nl snl; - struct sockaddr_nl snl_trusted_sender; - struct sockaddr_nl snl_destination; - struct sockaddr_un sun; - socklen_t addrlen; - struct udev_list_node filter_subsystem_list; - struct udev_list_node 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 = calloc(1, sizeof(struct udev_monitor)); - if (udev_monitor == NULL) - return NULL; - udev_monitor->refcount = 1; - udev_monitor->udev = udev; - udev_list_init(&udev_monitor->filter_subsystem_list); - udev_list_init(&udev_monitor->filter_tag_list); - return udev_monitor; -} - -/** - * udev_monitor_new_from_socket: - * @udev: udev library context - * @socket_path: unix socket path - * - * Create new udev monitor and connect to a specified socket. The - * path to a socket either points to an existing socket file, or if - * the socket path starts with a '@' character, an abstract namespace - * socket will be used. - * - * A socket file will not be created. If it does not already exist, - * it will fall-back and connect to an abstract namespace socket with - * the given path. The permissions adjustment of a socket file, as - * well as the later cleanup, needs to be done by the caller. - * - * 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 - **/ -UDEV_EXPORT struct udev_monitor *udev_monitor_new_from_socket(struct udev *udev, const char *socket_path) -{ - struct udev_monitor *udev_monitor; - struct stat statbuf; - - if (udev == NULL) - return NULL; - if (socket_path == NULL) - return NULL; - udev_monitor = udev_monitor_new(udev); - if (udev_monitor == NULL) - return NULL; - - udev_monitor->sun.sun_family = AF_LOCAL; - if (socket_path[0] == '@') { - /* translate leading '@' to abstract namespace */ - util_strscpy(udev_monitor->sun.sun_path, sizeof(udev_monitor->sun.sun_path), socket_path); - udev_monitor->sun.sun_path[0] = '\0'; - udev_monitor->addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(socket_path); - } else if (stat(socket_path, &statbuf) == 0 && S_ISSOCK(statbuf.st_mode)) { - /* existing socket file */ - util_strscpy(udev_monitor->sun.sun_path, sizeof(udev_monitor->sun.sun_path), socket_path); - udev_monitor->addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(socket_path); - } else { - /* no socket file, assume abstract namespace socket */ - util_strscpy(&udev_monitor->sun.sun_path[1], sizeof(udev_monitor->sun.sun_path)-1, socket_path); - udev_monitor->addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(socket_path)+1; - } - udev_monitor->sock = socket(AF_LOCAL, SOCK_DGRAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0); - if (udev_monitor->sock == -1) { - err(udev, "error getting socket: %m\n"); - free(udev_monitor); - return NULL; - } - - dbg(udev, "monitor %p created with '%s'\n", udev_monitor, socket_path); - return udev_monitor; -} - -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 (strcmp(name, "udev") == 0) - group = UDEV_MONITOR_UDEV; - else if (strcmp(name, "kernel") == 0) - 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) { - err(udev, "error getting socket: %m\n"); - free(udev_monitor); - return NULL; - } - } else { - udev_monitor->bound = true; - udev_monitor->sock = fd; - } - - udev_monitor->snl.nl_family = AF_NETLINK; - udev_monitor->snl.nl_groups = group; - - /* default destination for sending */ - udev_monitor->snl_destination.nl_family = AF_NETLINK; - udev_monitor->snl_destination.nl_groups = UDEV_MONITOR_UDEV; - - dbg(udev, "monitor %p created with NETLINK_KOBJECT_UEVENT (%u)\n", udev_monitor, group); - 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 - **/ -UDEV_EXPORT 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 filter. This might only be needed, if the filter was removed or changed. - * - * Returns: 0 on success, otherwise a negative error value. - */ -UDEV_EXPORT 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; - - memset(ins, 0x00, 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 >= ARRAY_SIZE(ins)) - return -1; - } - - /* 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 */ - memset(&filter, 0x00, sizeof(filter)); - filter.len = i; - filter.filter = ins; - err = setsockopt(udev_monitor->sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)); - return err; -} - -int udev_monitor_allow_unicast_sender(struct udev_monitor *udev_monitor, struct udev_monitor *sender) -{ - udev_monitor->snl_trusted_sender.nl_pid = sender->snl.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. - */ -UDEV_EXPORT int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) -{ - int err = 0; - const int on = 1; - - if (udev_monitor->sun.sun_family != 0) { - if (!udev_monitor->bound) { - err = bind(udev_monitor->sock, - (struct sockaddr *)&udev_monitor->sun, udev_monitor->addrlen); - if (err == 0) - udev_monitor->bound = true; - } - } else if (udev_monitor->snl.nl_family != 0) { - udev_monitor_filter_update(udev_monitor); - if (!udev_monitor->bound) { - err = bind(udev_monitor->sock, - (struct sockaddr *)&udev_monitor->snl, sizeof(struct sockaddr_nl)); - if (err == 0) - udev_monitor->bound = true; - } - if (err == 0) { - struct sockaddr_nl 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, (struct sockaddr *)&snl, &addrlen); - if (err == 0) - udev_monitor->snl.nl_pid = snl.nl_pid; - } - } else { - return -EINVAL; - } - - if (err < 0) { - err(udev_monitor->udev, "bind failed: %m\n"); - return err; - } - - /* enable receiving of sender credentials */ - setsockopt(udev_monitor->sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); - 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. - */ -UDEV_EXPORT int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size) -{ - if (udev_monitor == NULL) - return -1; - 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; -} - -/** - * udev_monitor_ref: - * @udev_monitor: udev monitor - * - * Take a reference of a udev monitor. - * - * Returns: the passed udev monitor - **/ -UDEV_EXPORT 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. - * - **/ -UDEV_EXPORT void udev_monitor_unref(struct udev_monitor *udev_monitor) -{ - if (udev_monitor == NULL) - return; - udev_monitor->refcount--; - if (udev_monitor->refcount > 0) - return; - if (udev_monitor->sock >= 0) - close(udev_monitor->sock); - udev_list_cleanup_entries(udev_monitor->udev, &udev_monitor->filter_subsystem_list); - udev_list_cleanup_entries(udev_monitor->udev, &udev_monitor->filter_tag_list); - dbg(udev_monitor->udev, "monitor %p released\n", udev_monitor); - free(udev_monitor); -} - -/** - * udev_monitor_get_udev: - * @udev_monitor: udev monitor - * - * Retrieve the udev library context the monitor was created with. - * - * Returns: the udev library context - **/ -UDEV_EXPORT 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 - **/ -UDEV_EXPORT int udev_monitor_get_fd(struct udev_monitor *udev_monitor) -{ - if (udev_monitor == NULL) - return -1; - 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 (strcmp(dsubsys, subsys) != 0) - 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 (strcmp(ddevtype, devtype) == 0) - 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 caller - * needs to make sure that there is data to read from the socket. - * The call will block until the socket becomes readable. - * - * 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 - **/ -UDEV_EXPORT 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; - struct sockaddr_nl snl; - struct ucred *cred; - char buf[8192]; - ssize_t buflen; - ssize_t bufpos; - struct udev_monitor_netlink_header *nlh; - -retry: - if (udev_monitor == NULL) - return NULL; - memset(buf, 0x00, sizeof(buf)); - iov.iov_base = &buf; - iov.iov_len = sizeof(buf); - memset (&smsg, 0x00, sizeof(struct msghdr)); - smsg.msg_iov = &iov; - smsg.msg_iovlen = 1; - smsg.msg_control = cred_msg; - smsg.msg_controllen = sizeof(cred_msg); - - if (udev_monitor->snl.nl_family != 0) { - smsg.msg_name = &snl; - smsg.msg_namelen = sizeof(snl); - } - - buflen = recvmsg(udev_monitor->sock, &smsg, 0); - if (buflen < 0) { - if (errno != EINTR) - info(udev_monitor->udev, "unable to receive message\n"); - return NULL; - } - - if (buflen < 32 || (size_t)buflen >= sizeof(buf)) { - info(udev_monitor->udev, "invalid message length\n"); - return NULL; - } - - if (udev_monitor->snl.nl_family != 0) { - if (snl.nl_groups == 0) { - /* unicast message, check if we trust the sender */ - if (udev_monitor->snl_trusted_sender.nl_pid == 0 || - snl.nl_pid != udev_monitor->snl_trusted_sender.nl_pid) { - info(udev_monitor->udev, "unicast netlink message ignored\n"); - return NULL; - } - } else if (snl.nl_groups == UDEV_MONITOR_KERNEL) { - if (snl.nl_pid > 0) { - info(udev_monitor->udev, "multicast kernel netlink message from pid %d ignored\n", - snl.nl_pid); - return NULL; - } - } - } - - cmsg = CMSG_FIRSTHDR(&smsg); - if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) { - info(udev_monitor->udev, "no sender credentials received, message ignored\n"); - return NULL; - } - - cred = (struct ucred *)CMSG_DATA(cmsg); - if (cred->uid != 0) { - info(udev_monitor->udev, "sender uid=%d, message ignored\n", cred->uid); - return NULL; - } - - if (memcmp(buf, "libudev", 8) == 0) { - /* udev message needs proper version magic */ - nlh = (struct udev_monitor_netlink_header *) buf; - if (nlh->magic != htonl(UDEV_MONITOR_MAGIC)) { - err(udev_monitor->udev, "ignored a message from an invalid release of udevadm (%x != %x)\n", - nlh->magic, htonl(UDEV_MONITOR_MAGIC)); - return NULL; - } - if (nlh->properties_off+32 > buflen) - return NULL; - bufpos = nlh->properties_off; - } else { - /* kernel message with header */ - bufpos = strlen(buf) + 1; - if ((size_t)bufpos < sizeof("a@/d") || bufpos >= buflen) { - info(udev_monitor->udev, "invalid message length\n"); - return NULL; - } - - /* check message header */ - if (strstr(buf, "@/") == NULL) { - info(udev_monitor->udev, "unrecognized message header\n"); - return NULL; - } - } - - udev_device = udev_device_new(udev_monitor->udev); - if (udev_device == NULL) - return NULL; - udev_device_set_info_loaded(udev_device); - - while (bufpos < buflen) { - char *key; - size_t keylen; - - key = &buf[bufpos]; - keylen = strlen(key); - if (keylen == 0) - break; - bufpos += keylen + 1; - udev_device_add_property_from_string_parse(udev_device, key); - } - - if (udev_device_add_property_from_string_parse_finish(udev_device) < 0) { - info(udev_monitor->udev, "missing values, invalid device\n"); - udev_device_unref(udev_device); - return NULL; - } - - /* 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; - ssize_t blen; - ssize_t count; - - blen = udev_device_get_properties_monitor_buf(udev_device, &buf); - if (blen < 32) - return -EINVAL; - - if (udev_monitor->sun.sun_family != 0) { - struct msghdr smsg; - struct iovec iov[2]; - const char *action; - char header[2048]; - char *s; - - /* header <action>@<devpath> */ - action = udev_device_get_action(udev_device); - if (action == NULL) - return -EINVAL; - s = header; - if (util_strpcpyl(&s, sizeof(header), action, "@", udev_device_get_devpath(udev_device), NULL) == 0) - return -EINVAL; - iov[0].iov_base = header; - iov[0].iov_len = (s - header)+1; - - /* add properties list */ - iov[1].iov_base = (char *)buf; - iov[1].iov_len = blen; - - memset(&smsg, 0x00, sizeof(struct msghdr)); - smsg.msg_iov = iov; - smsg.msg_iovlen = 2; - smsg.msg_name = &udev_monitor->sun; - smsg.msg_namelen = udev_monitor->addrlen; - count = sendmsg(udev_monitor->sock, &smsg, 0); - info(udev_monitor->udev, "passed %zi bytes to socket monitor %p\n", count, udev_monitor); - return count; - } - - if (udev_monitor->snl.nl_family != 0) { - struct msghdr smsg; - struct iovec iov[2]; - const char *val; - struct udev_monitor_netlink_header nlh; - struct udev_list_entry *list_entry; - uint64_t tag_bloom_bits; - - /* add versioned header */ - memset(&nlh, 0x00, sizeof(struct udev_monitor_netlink_header)); - memcpy(nlh.prefix, "libudev", 8); - nlh.magic = htonl(UDEV_MONITOR_MAGIC); - nlh.header_size = sizeof(struct udev_monitor_netlink_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)); - iov[0].iov_base = &nlh; - iov[0].iov_len = sizeof(struct udev_monitor_netlink_header); - - /* 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; - - memset(&smsg, 0x00, sizeof(struct msghdr)); - smsg.msg_iov = iov; - smsg.msg_iovlen = 2; - /* - * 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 != NULL) - 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); - info(udev_monitor->udev, "passed %zi bytes to netlink monitor %p\n", count, udev_monitor); - return count; - } - - return -EINVAL; -} - -/** - * 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 filer 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. - */ -UDEV_EXPORT 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->udev, - &udev_monitor->filter_subsystem_list, subsystem, devtype, 0) == NULL) - return -ENOMEM; - return 0; -} - -/** - * udev_monitor_filter_add_match_tag: - * @udev_monitor: the monitor - * @tag: the name of a tag - * - * This filer 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. - */ -UDEV_EXPORT 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->udev, - &udev_monitor->filter_tag_list, tag, NULL, 0) == 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. - */ -UDEV_EXPORT int udev_monitor_filter_remove(struct udev_monitor *udev_monitor) -{ - static struct sock_fprog filter = { 0, NULL }; - - udev_list_cleanup_entries(udev_monitor->udev, &udev_monitor->filter_subsystem_list); - return setsockopt(udev_monitor->sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)); -} diff --git a/src/libudev-legacy/libudev-private.h b/src/libudev-legacy/libudev-private.h deleted file mode 100644 index 315ca3d700..0000000000 --- a/src/libudev-legacy/libudev-private.h +++ /dev/null @@ -1,253 +0,0 @@ -/* - * libudev - interface to udev device information - * - * Copyright (C) 2008-2010 Kay Sievers <kay.sievers@vrfy.org> - * - * This library 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. - */ - -#ifndef _LIBUDEV_PRIVATE_H_ -#define _LIBUDEV_PRIVATE_H_ - -#include <syslog.h> -#include <signal.h> -#include <stdint.h> -#include <stdbool.h> -#include "libudev.h" - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) -#define READ_END 0 -#define WRITE_END 1 - -static inline void __attribute__((always_inline, format(printf, 2, 3))) -udev_log_null(struct udev *udev, const char *format, ...) {} - -#define udev_log_cond(udev, prio, arg...) \ - do { \ - if (udev_get_log_priority(udev) >= prio) \ - udev_log(udev, prio, __FILE__, __LINE__, __FUNCTION__, ## arg); \ - } while (0) - -#ifdef ENABLE_LOGGING -# ifdef ENABLE_DEBUG -# define dbg(udev, arg...) udev_log_cond(udev, LOG_DEBUG, ## arg) -# else -# define dbg(udev, arg...) udev_log_null(udev, ## arg) -# endif -# define info(udev, arg...) udev_log_cond(udev, LOG_INFO, ## arg) -# define err(udev, arg...) udev_log_cond(udev, LOG_ERR, ## arg) -#else -# define dbg(udev, arg...) udev_log_null(udev, ## arg) -# define info(udev, arg...) udev_log_null(udev, ## arg) -# define err(udev, arg...) udev_log_null(udev, ## arg) -#endif - -#define UDEV_EXPORT __attribute__ ((visibility("default"))) - -static inline void udev_log_init(const char *program_name) -{ - openlog(program_name, LOG_PID | LOG_CONS, LOG_DAEMON); -} - -static inline void udev_log_close(void) -{ - closelog(); -} - -/* libudev.c */ -void udev_log(struct udev *udev, - int priority, const char *file, int line, const char *fn, - const char *format, ...) - __attribute__((format(printf, 6, 7))); -const char *udev_get_rules_path(struct udev *udev); -const char *udev_get_run_config_path(struct udev *udev); -const char *udev_set_run_path(struct udev *udev, const char *path); -struct udev_list_entry *udev_add_property(struct udev *udev, const char *key, const char *value); -struct udev_list_entry *udev_get_properties_list_entry(struct udev *udev); - -/* libudev-device.c */ -struct udev_device *udev_device_new(struct udev *udev); -struct udev_device *udev_device_new_from_id_filename(struct udev *udev, char *id); -mode_t udev_device_get_devnode_mode(struct udev_device *udev_device); -int udev_device_set_syspath(struct udev_device *udev_device, const char *syspath); -int udev_device_set_devnode(struct udev_device *udev_device, const char *devnode); -int udev_device_add_devlink(struct udev_device *udev_device, const char *devlink, int unique); -void udev_device_cleanup_devlinks_list(struct udev_device *udev_device); -struct udev_list_entry *udev_device_add_property(struct udev_device *udev_device, const char *key, const char *value); -void udev_device_add_property_from_string_parse(struct udev_device *udev_device, const char *property); -int udev_device_add_property_from_string_parse_finish(struct udev_device *udev_device); -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); -int udev_device_read_db(struct udev_device *udev_device, const char *dbfile); -int udev_device_read_uevent_file(struct udev_device *udev_device); -int udev_device_set_action(struct udev_device *udev_device, const char *action); -const char *udev_device_get_devpath_old(struct udev_device *udev_device); -const char *udev_device_get_knodename(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_cleanup_tags_list(struct udev_device *udev_device); -int udev_device_has_tag(struct udev_device *udev_device, const char *tag); -int udev_device_get_timeout(struct udev_device *udev_device); -unsigned long long udev_device_get_usec_initialized(struct udev_device *udev_device); -void udev_device_set_usec_initialized(struct udev_device *udev_device, unsigned long long usec_initialized); -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-ctrl.c - daemon runtime setup */ -struct udev_ctrl; -struct udev_ctrl *udev_ctrl_new_from_socket(struct udev *udev, const char *socket_path); -struct udev_ctrl *udev_ctrl_new_from_socket_fd(struct udev *udev, const char *socket_path, int fd); -int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl); -struct udev_ctrl *udev_ctrl_ref(struct udev_ctrl *uctrl); -struct udev_ctrl *udev_ctrl_unref(struct udev_ctrl *uctrl); -struct udev *udev_ctrl_get_udev(struct udev_ctrl *uctrl); -int udev_ctrl_get_fd(struct udev_ctrl *uctrl); -int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, int timeout); -int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, int timeout); -int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, int timeout); -int udev_ctrl_send_reload_rules(struct udev_ctrl *uctrl, int timeout); -int udev_ctrl_send_ping(struct udev_ctrl *uctrl, int timeout); -int udev_ctrl_send_exit(struct udev_ctrl *uctrl, int timeout); -int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, int timeout); -int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, int timeout); -struct udev_ctrl_connection; -struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl); -struct udev_ctrl_connection *udev_ctrl_connection_ref(struct udev_ctrl_connection *conn); -struct udev_ctrl_connection *udev_ctrl_connection_unref(struct udev_ctrl_connection *conn); -struct udev_ctrl_msg; -struct udev_ctrl_msg *udev_ctrl_receive_msg(struct udev_ctrl_connection *conn); -struct udev_ctrl_msg *udev_ctrl_msg_ref(struct udev_ctrl_msg *ctrl_msg); -struct udev_ctrl_msg *udev_ctrl_msg_unref(struct udev_ctrl_msg *ctrl_msg); -int udev_ctrl_get_set_log_level(struct udev_ctrl_msg *ctrl_msg); -int udev_ctrl_get_stop_exec_queue(struct udev_ctrl_msg *ctrl_msg); -int udev_ctrl_get_start_exec_queue(struct udev_ctrl_msg *ctrl_msg); -int udev_ctrl_get_reload_rules(struct udev_ctrl_msg *ctrl_msg); -int udev_ctrl_get_ping(struct udev_ctrl_msg *ctrl_msg); -int udev_ctrl_get_exit(struct udev_ctrl_msg *ctrl_msg); -const char *udev_ctrl_get_set_env(struct udev_ctrl_msg *ctrl_msg); -int udev_ctrl_get_set_children_max(struct udev_ctrl_msg *ctrl_msg); - -/* libudev-list.c */ -enum udev_list_flags { - UDEV_LIST_NONE = 0, - UDEV_LIST_UNIQUE = 1, - UDEV_LIST_SORT = 1 << 1, -}; -struct udev_list_node { - struct udev_list_node *next, *prev; -}; -#define UDEV_LIST(list) struct udev_list_node list = { &(list), &(list) } -void udev_list_init(struct udev_list_node *list); -int udev_list_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) -struct udev_list_entry *udev_list_entry_add(struct udev *udev, struct udev_list_node *list, - const char *name, const char *value, unsigned int flags); -void udev_list_entry_delete(struct udev_list_entry *entry); -void udev_list_entry_remove(struct udev_list_entry *entry); -void udev_list_entry_insert_before(struct udev_list_entry *new, struct udev_list_entry *entry); -void udev_list_entry_append(struct udev_list_entry *new, struct udev_list_node *list); -void udev_list_cleanup_entries(struct udev *udev, struct udev_list_node *name_list); -struct udev_list_entry *udev_list_get_entry(struct udev_list_node *list); -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); -int udev_queue_export_device_failed(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_subsystem(struct udev *udev, const char *syspath, char *subsystem, size_t size); -ssize_t util_get_sys_driver(struct udev *udev, const char *syspath, char *driver, 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); -size_t util_path_decode(char *s); -void util_remove_trailing_chars(char *path, char c); -size_t util_strpcpy(char **dest, size_t size, const char *src); -size_t util_strpcpyl(char **dest, size_t size, const char *src, ...) __attribute__((sentinel)); -size_t util_strscpy(char *dest, size_t size, const char *src); -size_t util_strscpyl(char *dest, size_t size, const char *src, ...) __attribute__((sentinel)); -int udev_util_replace_whitespace(const char *str, char *to, size_t len); -int udev_util_replace_chars(char *str, const char *white); -int udev_util_encode_string(const char *str, char *str_enc, size_t len); -unsigned int util_string_hash32(const char *key); -uint64_t util_string_bloom64(const char *str); - -/* libudev-util-private.c */ -int util_create_path(struct udev *udev, const char *path); -int util_create_path_selinux(struct udev *udev, const char *path); -int util_delete_path(struct udev *udev, const char *path); -int util_unlink_secure(struct udev *udev, const char *filename); -uid_t util_lookup_user(struct udev *udev, const char *user); -gid_t util_lookup_group(struct udev *udev, const char *group); -int util_resolve_subsys_kernel(struct udev *udev, const char *string, - char *result, size_t maxsize, int read_value); -unsigned long long now_usec(void); - -/* libudev-selinux-private.c */ -#ifndef WITH_SELINUX -static inline void udev_selinux_init(struct udev *udev) {} -static inline void udev_selinux_exit(struct udev *udev) {} -static inline void udev_selinux_lsetfilecon(struct udev *udev, const char *file, unsigned int mode) {} -static inline void udev_selinux_setfscreatecon(struct udev *udev, const char *file, unsigned int mode) {} -static inline void udev_selinux_setfscreateconat(struct udev *udev, int dfd, const char *file, unsigned int mode) {} -static inline void udev_selinux_resetfscreatecon(struct udev *udev) {} -#else -void udev_selinux_init(struct udev *udev); -void udev_selinux_exit(struct udev *udev); -void udev_selinux_lsetfilecon(struct udev *udev, const char *file, unsigned int mode); -void udev_selinux_setfscreatecon(struct udev *udev, const char *file, unsigned int mode); -void udev_selinux_setfscreateconat(struct udev *udev, int dfd, const char *file, unsigned int mode); -void udev_selinux_resetfscreatecon(struct udev *udev); -#endif - -#endif diff --git a/src/libudev-legacy/libudev-queue.c b/src/libudev-legacy/libudev-queue.c deleted file mode 100644 index 73e7fb23aa..0000000000 --- a/src/libudev-legacy/libudev-queue.c +++ /dev/null @@ -1,515 +0,0 @@ -/* - * libudev - interface to udev device information - * - * Copyright (C) 2008 Kay Sievers <kay.sievers@vrfy.org> - * Copyright (C) 2009 Alan Jenkins <alan-jenkins@tuffmail.co.uk> - * - * This library 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. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <dirent.h> -#include <fcntl.h> -#include <limits.h> -#include <sys/stat.h> - -#include "libudev.h" -#include "libudev-private.h" - -/** - * SECTION:libudev-queue - * @short_description: access to currently active events - * - * The udev daemon processes events asynchronously. All events which do not have - * interdependencies run in parallel. This exports the current state of the - * event processing queue, and the current event sequence numbers from the kernel - * and the udev daemon. - */ - -/** - * udev_queue: - * - * Opaque object representing the current event queue in the udev daemon. - */ -struct udev_queue { - struct udev *udev; - int refcount; - struct udev_list_node queue_list; - struct udev_list_node failed_list; -}; - -/** - * 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. - **/ -UDEV_EXPORT struct udev_queue *udev_queue_new(struct udev *udev) -{ - struct udev_queue *udev_queue; - - if (udev == NULL) - return NULL; - - udev_queue = calloc(1, sizeof(struct udev_queue)); - if (udev_queue == NULL) - return NULL; - udev_queue->refcount = 1; - udev_queue->udev = udev; - udev_list_init(&udev_queue->queue_list); - udev_list_init(&udev_queue->failed_list); - 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. - **/ -UDEV_EXPORT 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. - **/ -UDEV_EXPORT void udev_queue_unref(struct udev_queue *udev_queue) -{ - if (udev_queue == NULL) - return; - udev_queue->refcount--; - if (udev_queue->refcount > 0) - return; - udev_list_cleanup_entries(udev_queue->udev, &udev_queue->queue_list); - udev_list_cleanup_entries(udev_queue->udev, &udev_queue->failed_list); - free(udev_queue); -} - -/** - * 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. - **/ -UDEV_EXPORT struct udev *udev_queue_get_udev(struct udev_queue *udev_queue) -{ - if (udev_queue == NULL) - return NULL; - return udev_queue->udev; -} - -unsigned long long int udev_get_kernel_seqnum(struct udev *udev) -{ - char filename[UTIL_PATH_SIZE]; - unsigned long long int seqnum; - int fd; - char buf[32]; - ssize_t len; - - util_strscpyl(filename, sizeof(filename), udev_get_sys_path(udev), "/kernel/uevent_seqnum", NULL); - fd = open(filename, O_RDONLY|O_CLOEXEC); - if (fd < 0) - return 0; - len = read(fd, buf, sizeof(buf)); - close(fd); - if (len <= 2) - return 0; - buf[len-1] = '\0'; - seqnum = strtoull(buf, NULL, 10); - return seqnum; -} - -/** - * udev_queue_get_kernel_seqnum: - * @udev_queue: udev queue context - * - * Returns: the current kernel event sequence number. - **/ -UDEV_EXPORT unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue) -{ - unsigned long long int seqnum; - - if (udev_queue == NULL) - return -EINVAL; - - seqnum = udev_get_kernel_seqnum(udev_queue->udev); - dbg(udev_queue->udev, "seqnum=%llu\n", seqnum); - return seqnum; -} - -int udev_queue_read_seqnum(FILE *queue_file, unsigned long long int *seqnum) -{ - if (fread(seqnum, sizeof(unsigned long long int), 1, queue_file) != 1) - return -1; - - return 0; -} - -ssize_t udev_queue_skip_devpath(FILE *queue_file) -{ - unsigned short int len; - - if (fread(&len, sizeof(unsigned short int), 1, queue_file) == 1) { - char devpath[len]; - - /* use fread to skip, fseek might drop buffered data */ - if (fread(devpath, 1, len, queue_file) == len) - return len; - } - - return -1; -} - -ssize_t udev_queue_read_devpath(FILE *queue_file, char *devpath, size_t size) -{ - unsigned short int read_bytes = 0; - unsigned short int len; - - if (fread(&len, sizeof(unsigned short int), 1, queue_file) != 1) - return -1; - - read_bytes = (len < size - 1) ? len : size - 1; - if (fread(devpath, 1, read_bytes, queue_file) != read_bytes) - return -1; - devpath[read_bytes] = '\0'; - - /* if devpath was too long, skip unread characters */ - if (read_bytes != len) { - unsigned short int skip_bytes = len - read_bytes; - char buf[skip_bytes]; - - if (fread(buf, 1, skip_bytes, queue_file) != skip_bytes) - return -1; - } - - return read_bytes; -} - -static FILE *open_queue_file(struct udev_queue *udev_queue, unsigned long long int *seqnum_start) -{ - char filename[UTIL_PATH_SIZE]; - FILE *queue_file; - - util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev_queue->udev), "/queue.bin", NULL); - queue_file = fopen(filename, "re"); - if (queue_file == NULL) - return NULL; - - if (udev_queue_read_seqnum(queue_file, seqnum_start) < 0) { - err(udev_queue->udev, "corrupt queue file\n"); - fclose(queue_file); - return NULL; - } - - return queue_file; -} - -/** - * udev_queue_get_udev_seqnum: - * @udev_queue: udev queue context - * - * Returns: the last known udev event sequence number. - **/ -UDEV_EXPORT unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue) -{ - unsigned long long int seqnum_udev; - FILE *queue_file; - - queue_file = open_queue_file(udev_queue, &seqnum_udev); - if (queue_file == NULL) - return 0; - - for (;;) { - unsigned long long int seqnum; - ssize_t devpath_len; - - if (udev_queue_read_seqnum(queue_file, &seqnum) < 0) - break; - devpath_len = udev_queue_skip_devpath(queue_file); - if (devpath_len < 0) - break; - if (devpath_len > 0) - seqnum_udev = seqnum; - } - - fclose(queue_file); - return seqnum_udev; -} - -/** - * udev_queue_get_udev_is_active: - * @udev_queue: udev queue context - * - * Returns: a flag indicating if udev is active. - **/ -UDEV_EXPORT int udev_queue_get_udev_is_active(struct udev_queue *udev_queue) -{ - unsigned long long int seqnum_start; - FILE *queue_file; - - queue_file = open_queue_file(udev_queue, &seqnum_start); - if (queue_file == NULL) - return 0; - - fclose(queue_file); - return 1; -} - -/** - * udev_queue_get_queue_is_empty: - * @udev_queue: udev queue context - * - * Returns: a flag indicating if udev is currently handling events. - **/ -UDEV_EXPORT int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue) -{ - unsigned long long int seqnum_kernel; - unsigned long long int seqnum_udev = 0; - int queued = 0; - int is_empty = 0; - FILE *queue_file; - - if (udev_queue == NULL) - return -EINVAL; - queue_file = open_queue_file(udev_queue, &seqnum_udev); - if (queue_file == NULL) - return 1; - - for (;;) { - unsigned long long int seqnum; - ssize_t devpath_len; - - if (udev_queue_read_seqnum(queue_file, &seqnum) < 0) - break; - devpath_len = udev_queue_skip_devpath(queue_file); - if (devpath_len < 0) - break; - - if (devpath_len > 0) { - queued++; - seqnum_udev = seqnum; - } else { - queued--; - } - } - - if (queued > 0) { - dbg(udev_queue->udev, "queue is not empty\n"); - goto out; - } - - seqnum_kernel = udev_queue_get_kernel_seqnum(udev_queue); - if (seqnum_udev < seqnum_kernel) { - dbg(udev_queue->udev, "queue is empty but kernel events still pending [%llu]<->[%llu]\n", - seqnum_kernel, seqnum_udev); - goto out; - } - - dbg(udev_queue->udev, "queue is empty\n"); - is_empty = 1; - -out: - fclose(queue_file); - return is_empty; -} - -/** - * udev_queue_get_seqnum_sequence_is_finished: - * @udev_queue: udev queue context - * @start: first event sequence number - * @end: last event sequence number - * - * Returns: a flag indicating if any of the sequence numbers in the given range is currently active. - **/ -UDEV_EXPORT int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue, - unsigned long long int start, unsigned long long int end) -{ - unsigned long long int seqnum; - ssize_t devpath_len; - int unfinished; - FILE *queue_file; - - if (udev_queue == NULL) - return -EINVAL; - queue_file = open_queue_file(udev_queue, &seqnum); - if (queue_file == NULL) - return 1; - if (start < seqnum) - start = seqnum; - if (start > end) { - fclose(queue_file); - return 1; - } - if (end - start > INT_MAX - 1) { - fclose(queue_file); - return -EOVERFLOW; - } - - /* - * we might start with 0, and handle the initial seqnum - * only when we find an entry in the queue file - **/ - unfinished = end - start; - - do { - if (udev_queue_read_seqnum(queue_file, &seqnum) < 0) - break; - devpath_len = udev_queue_skip_devpath(queue_file); - if (devpath_len < 0) - break; - - /* - * we might start with an empty or re-build queue file, where - * the initial seqnum is not recorded as finished - */ - if (start == seqnum && devpath_len > 0) - unfinished++; - - if (devpath_len == 0) { - if (seqnum >= start && seqnum <= end) - unfinished--; - } - } while (unfinished > 0); - - fclose(queue_file); - - return (unfinished == 0); -} - -/** - * udev_queue_get_seqnum_is_finished: - * @udev_queue: udev queue context - * @seqnum: sequence number - * - * Returns: a flag indicating if the given sequence number is currently active. - **/ -UDEV_EXPORT int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum) -{ - if (!udev_queue_get_seqnum_sequence_is_finished(udev_queue, seqnum, seqnum)) - return 0; - - dbg(udev_queue->udev, "seqnum: %llu finished\n", seqnum); - return 1; -} - -/** - * udev_queue_get_queued_list_entry: - * @udev_queue: udev queue context - * - * Returns: the first entry of the list of queued events. - **/ -UDEV_EXPORT struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) -{ - unsigned long long int seqnum; - FILE *queue_file; - - if (udev_queue == NULL) - return NULL; - udev_list_cleanup_entries(udev_queue->udev, &udev_queue->queue_list); - - queue_file = open_queue_file(udev_queue, &seqnum); - if (queue_file == NULL) - return NULL; - - for (;;) { - char syspath[UTIL_PATH_SIZE]; - char *s; - size_t l; - ssize_t len; - char seqnum_str[32]; - struct udev_list_entry *list_entry; - - if (udev_queue_read_seqnum(queue_file, &seqnum) < 0) - break; - snprintf(seqnum_str, sizeof(seqnum_str), "%llu", seqnum); - - s = syspath; - l = util_strpcpyl(&s, sizeof(syspath), udev_get_sys_path(udev_queue->udev), NULL); - len = udev_queue_read_devpath(queue_file, s, l); - if (len < 0) - break; - - if (len > 0) { - udev_list_entry_add(udev_queue->udev, &udev_queue->queue_list, syspath, seqnum_str, 0); - } else { - udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_queue->queue_list)) { - if (strcmp(seqnum_str, udev_list_entry_get_value(list_entry)) == 0) { - udev_list_entry_delete(list_entry); - break; - } - } - } - } - fclose(queue_file); - - return udev_list_get_entry(&udev_queue->queue_list); -} - -/** - * udev_queue_get_failed_list_entry: - * @udev_queue: udev queue context - * - * Returns: the first entry of the list of recorded failed events. - **/ -UDEV_EXPORT struct udev_list_entry *udev_queue_get_failed_list_entry(struct udev_queue *udev_queue) -{ - char path[UTIL_PATH_SIZE]; - DIR *dir; - struct dirent *dent; - - if (udev_queue == NULL) - return NULL; - udev_list_cleanup_entries(udev_queue->udev, &udev_queue->failed_list); - util_strscpyl(path, sizeof(path), udev_get_run_path(udev_queue->udev), "/failed", NULL); - dir = opendir(path); - if (dir == NULL) - return NULL; - for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { - char filename[UTIL_PATH_SIZE]; - char syspath[UTIL_PATH_SIZE]; - char *s; - size_t l; - ssize_t len; - struct stat statbuf; - - if (dent->d_name[0] == '.') - continue; - s = syspath; - l = util_strpcpyl(&s, sizeof(syspath), udev_get_sys_path(udev_queue->udev), NULL); - len = readlinkat(dirfd(dir), dent->d_name, s, l); - if (len <= 0 || (size_t)len == l) - continue; - s[len] = '\0'; - dbg(udev_queue->udev, "found '%s' [%s]\n", syspath, dent->d_name); - util_strscpyl(filename, sizeof(filename), syspath, "/uevent", NULL); - if (stat(filename, &statbuf) != 0) - continue; - udev_list_entry_add(udev_queue->udev, &udev_queue->failed_list, syspath, NULL, 0); - } - closedir(dir); - return udev_list_get_entry(&udev_queue->failed_list); -} diff --git a/src/libudev-legacy/libudev-util.c b/src/libudev-legacy/libudev-util.c deleted file mode 100644 index 48eea0b898..0000000000 --- a/src/libudev-legacy/libudev-util.c +++ /dev/null @@ -1,568 +0,0 @@ -/* - * libudev - interface to udev device information - * - * Copyright (C) 2008-2009 Kay Sievers <kay.sievers@vrfy.org> - * - * This library 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. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <dirent.h> -#include <ctype.h> -#include <fcntl.h> -#include <time.h> -#include <sys/stat.h> - -#include "libudev.h" -#include "libudev-private.h" - -static ssize_t get_sys_link(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; - - util_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]; - dbg(udev, "resolved link to: '%s'\n", pos); - return util_strscpy(value, size, pos); -} - -ssize_t util_get_sys_subsystem(struct udev *udev, const char *syspath, char *subsystem, size_t size) -{ - return get_sys_link(udev, "subsystem", syspath, subsystem, size); -} - -ssize_t util_get_sys_driver(struct udev *udev, const char *syspath, char *driver, size_t size) -{ - return get_sys_link(udev, "driver", syspath, driver, size); -} - -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; - - len = readlink(syspath, link_target, sizeof(link_target)); - if (len <= 0 || len == (ssize_t)sizeof(link_target)) - return -1; - link_target[len] = '\0'; - dbg(udev, "path link '%s' points to '%s'\n", syspath, link_target); - - for (back = 0; strncmp(&link_target[back * 3], "../", 3) == 0; back++) - ; - dbg(udev, "base '%s', tail '%s', back %i\n", syspath, &link_target[back * 3], back); - for (i = 0; i <= back; i++) { - base = strrchr(syspath, '/'); - if (base == NULL) - return -1; - base[0] = '\0'; - } - dbg(udev, "after moving back '%s'\n", syspath); - util_strscpyl(base, size - (base - syspath), "/", &link_target[back * 3], NULL); - return 0; -} - -int util_log_priority(const char *priority) -{ - char *endptr; - int prio; - - prio = strtol(priority, &endptr, 10); - if (endptr[0] == '\0' || isspace(endptr[0])) - return prio; - if (strncmp(priority, "err", 3) == 0) - return LOG_ERR; - if (strncmp(priority, "info", 4) == 0) - return LOG_INFO; - if (strncmp(priority, "debug", 5) == 0) - return LOG_DEBUG; - return 0; -} - -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; -} - -size_t util_path_decode(char *s) -{ - size_t i, j; - - for (i = 0, j = 0; s[i] != '\0'; j++) { - if (memcmp(&s[i], "\\x2f", 4) == 0) { - s[j] = '/'; - i += 4; - } else if (memcmp(&s[i], "\\x5c", 4) == 0) { - s[j] = '\\'; - i += 4; - } else { - s[j] = s[i]; - i++; - } - } - s[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'; -} - -/* - * Concatenates strings. In any case, terminates in _all_ cases with '\0' - * and moves the @dest pointer forward to the added '\0'. Returns the - * remaining size, and 0 if the string was truncated. - */ -size_t util_strpcpy(char **dest, size_t size, const char *src) -{ - size_t len; - - len = strlen(src); - if (len >= size) { - if (size > 1) - *dest = mempcpy(*dest, src, size-1); - size = 0; - *dest[0] = '\0'; - } else { - if (len > 0) { - *dest = mempcpy(*dest, src, len); - size -= len; - } - *dest[0] = '\0'; - } - return size; -} - -/* concatenates list of strings, moves dest forward */ -size_t util_strpcpyl(char **dest, size_t size, const char *src, ...) -{ - va_list va; - - va_start(va, src); - do { - size = util_strpcpy(dest, size, src); - src = va_arg(va, char *); - } while (src != NULL); - va_end(va); - - return size; -} - -/* copies string */ -size_t util_strscpy(char *dest, size_t size, const char *src) -{ - char *s; - - s = dest; - return util_strpcpy(&s, size, src); -} - -/* concatenates list of strings */ -size_t util_strscpyl(char *dest, size_t size, const char *src, ...) -{ - va_list va; - char *s; - - va_start(va, src); - s = dest; - do { - size = util_strpcpy(&s, size, src); - src = va_arg(va, char *); - } while (src != NULL); - va_end(va); - - return size; -} - -/* count of characters used to encode one unicode char */ -static int utf8_encoded_expected_len(const char *str) -{ - unsigned char c = (unsigned char)str[0]; - - if (c < 0x80) - return 1; - if ((c & 0xe0) == 0xc0) - return 2; - if ((c & 0xf0) == 0xe0) - return 3; - if ((c & 0xf8) == 0xf0) - return 4; - if ((c & 0xfc) == 0xf8) - return 5; - if ((c & 0xfe) == 0xfc) - return 6; - return 0; -} - -/* decode one unicode char */ -static int utf8_encoded_to_unichar(const char *str) -{ - int unichar; - int len; - int i; - - len = utf8_encoded_expected_len(str); - switch (len) { - case 1: - return (int)str[0]; - case 2: - unichar = str[0] & 0x1f; - break; - case 3: - unichar = (int)str[0] & 0x0f; - break; - case 4: - unichar = (int)str[0] & 0x07; - break; - case 5: - unichar = (int)str[0] & 0x03; - break; - case 6: - unichar = (int)str[0] & 0x01; - break; - default: - return -1; - } - - for (i = 1; i < len; i++) { - if (((int)str[i] & 0xc0) != 0x80) - return -1; - unichar <<= 6; - unichar |= (int)str[i] & 0x3f; - } - - return unichar; -} - -/* expected size used to encode one unicode char */ -static int utf8_unichar_to_encoded_len(int unichar) -{ - if (unichar < 0x80) - return 1; - if (unichar < 0x800) - return 2; - if (unichar < 0x10000) - return 3; - if (unichar < 0x200000) - return 4; - if (unichar < 0x4000000) - return 5; - return 6; -} - -/* check if unicode char has a valid numeric range */ -static int utf8_unichar_valid_range(int unichar) -{ - if (unichar > 0x10ffff) - return 0; - if ((unichar & 0xfffff800) == 0xd800) - return 0; - if ((unichar > 0xfdcf) && (unichar < 0xfdf0)) - return 0; - if ((unichar & 0xffff) == 0xffff) - return 0; - return 1; -} - -/* validate one encoded unicode char and return its length */ -static int utf8_encoded_valid_unichar(const char *str) -{ - int len; - int unichar; - int i; - - len = utf8_encoded_expected_len(str); - if (len == 0) - return -1; - - /* ascii is valid */ - if (len == 1) - return 1; - - /* check if expected encoded chars are available */ - for (i = 0; i < len; i++) - if ((str[i] & 0x80) != 0x80) - return -1; - - unichar = utf8_encoded_to_unichar(str); - - /* check if encoded length matches encoded value */ - if (utf8_unichar_to_encoded_len(unichar) != len) - return -1; - - /* check if value has valid range */ - if (!utf8_unichar_valid_range(unichar)) - return -1; - - return len; -} - -int udev_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; -} - -static int is_whitelisted(char c, const char *white) -{ - if ((c >= '0' && c <= '9') || - (c >= 'A' && c <= 'Z') || - (c >= 'a' && c <= 'z') || - strchr("#+-.:=@_", c) != NULL || - (white != NULL && strchr(white, c) != NULL)) - return 1; - return 0; -} - -/* allow chars in whitelist, plain ascii, hex-escaping and valid utf8 */ -int udev_util_replace_chars(char *str, const char *white) -{ - size_t i = 0; - int replaced = 0; - - while (str[i] != '\0') { - int len; - - if (is_whitelisted(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; -} - -/** - * 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 hex value prefixed by '\x'. - * - * Returns: 0 if the entire string was copied, non-zero otherwise. - **/ -int udev_util_encode_string(const char *str, char *str_enc, size_t len) -{ - size_t i, j; - - if (str == NULL || str_enc == NULL) - return -1; - - for (i = 0, j = 0; str[i] != '\0'; i++) { - int seqlen; - - seqlen = utf8_encoded_valid_unichar(&str[i]); - if (seqlen > 1) { - if (len-j < (size_t)seqlen) - goto err; - memcpy(&str_enc[j], &str[i], seqlen); - j += seqlen; - i += (seqlen-1); - } else if (str[i] == '\\' || !is_whitelisted(str[i], NULL)) { - if (len-j < 4) - goto err; - sprintf(&str_enc[j], "\\x%02x", (unsigned char) str[i]); - j += 4; - } else { - if (len-j < 1) - goto err; - str_enc[j] = str[i]; - j++; - } - } - if (len-j < 1) - goto err; - str_enc[j] = '\0'; - return 0; -err: - return -1; -} - -/* - * http://sites.google.com/site/murmurhash/ - * - * All code is released to the public domain. For business purposes, - * Murmurhash is under the MIT license. - * - */ -static unsigned int murmur_hash2(const char *key, int len, unsigned int seed) -{ - /* - * 'm' and 'r' are mixing constants generated offline. - * They're not really 'magic', they just happen to work well. - */ - const unsigned int m = 0x5bd1e995; - const int r = 24; - - /* initialize the hash to a 'random' value */ - unsigned int h = seed ^ len; - - /* mix 4 bytes at a time into the hash */ - const unsigned char * data = (const unsigned char *)key; - - while(len >= 4) { - unsigned int k = *(unsigned int *)data; - - k *= m; - k ^= k >> r; - k *= m; - h *= m; - h ^= k; - - data += 4; - len -= 4; - } - - /* handle the last few bytes of the input array */ - switch(len) { - case 3: - h ^= data[2] << 16; - case 2: - h ^= data[1] << 8; - case 1: - h ^= data[0]; - h *= m; - }; - - /* do a few final mixes of the hash to ensure the last few bytes are well-incorporated */ - h ^= h >> 13; - h *= m; - h ^= h >> 15; - - return h; -} - -unsigned int util_string_hash32(const char *str) -{ - return murmur_hash2(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; -} - -#define USEC_PER_SEC 1000000ULL -#define NSEC_PER_USEC 1000ULL -unsigned long long now_usec(void) -{ - struct timespec ts; - - if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) - return 0; - return (unsigned long long) ts.tv_sec * USEC_PER_SEC + - (unsigned long long) ts.tv_nsec / NSEC_PER_USEC; -} diff --git a/src/libudev-legacy/libudev.c b/src/libudev-legacy/libudev.c deleted file mode 100644 index e131d8cbec..0000000000 --- a/src/libudev-legacy/libudev.c +++ /dev/null @@ -1,467 +0,0 @@ -/* - * libudev - interface to udev device information - * - * Copyright (C) 2008-2010 Kay Sievers <kay.sievers@vrfy.org> - * - * This library 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. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <stdarg.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <ctype.h> - -#include "libudev.h" -#include "libudev-private.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; - char *sys_path; - char *dev_path; - char *rules_path; - char *run_config_path; - char *run_path; - struct udev_list_node properties_list; - int log_priority; -}; - -void udev_log(struct udev *udev, - int priority, const char *file, int line, const char *fn, - const char *format, ...) -{ - va_list args; - - va_start(args, format); - udev->log_fn(udev, priority, file, line, fn, format, args); - va_end(args); -} - -static void log_stderr(struct udev *udev, - int priority, const char *file, int line, const char *fn, - const char *format, va_list args) -{ - fprintf(stderr, "libudev: %s: ", fn); - vfprintf(stderr, format, args); -} - -/** - * udev_get_userdata: - * @udev: udev library context - * - * Retrieve stored data pointer from library context. This might be useful - * to access from callbacks like a custom logging function. - * - * Returns: stored userdata - **/ -UDEV_EXPORT 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. - **/ -UDEV_EXPORT void udev_set_userdata(struct udev *udev, void *userdata) -{ - if (udev == NULL) - return; - udev->userdata = userdata; -} - -static char *set_value(char **s, const char *v) -{ - free(*s); - *s = strdup(v); - util_remove_trailing_chars(*s, '/'); - return *s; -} - -/** - * 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 - **/ -UDEV_EXPORT struct udev *udev_new(void) -{ - struct udev *udev; - const char *env; - char *config_file = NULL; - FILE *f; - - udev = calloc(1, sizeof(struct udev)); - if (udev == NULL) - return NULL; - udev->refcount = 1; - udev->log_fn = log_stderr; - udev->log_priority = LOG_ERR; - udev_list_init(&udev->properties_list); - - /* custom config file */ - env = getenv("UDEV_CONFIG_FILE"); - if (env != NULL) { - udev_add_property(udev, "UDEV_CONFIG_FILE", udev->dev_path); - if (set_value(&config_file, env) == NULL) - goto err; - } - - /* default config file */ - if (config_file == NULL) - config_file = strdup(UDEV_CONF_FILE); - if (config_file == NULL) - goto err; - - f = fopen(config_file, "re"); - if (f != NULL) { - char line[UTIL_LINE_SIZE]; - int 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) { - err(udev, "missing <key>=<value> in '%s'[%i], skip line\n", config_file, 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]) { - err(udev, "inconsistent quoting in '%s'[%i], skip line\n", config_file, line_nr); - continue; - } - val[len-1] = '\0'; - val++; - } - - if (strcmp(key, "udev_log") == 0) { - udev_set_log_priority(udev, util_log_priority(val)); - continue; - } - if (strcmp(key, "udev_root") == 0) { - set_value(&udev->dev_path, val); - continue; - } - if (strcmp(key, "udev_run") == 0) { - set_value(&udev->run_config_path, val); - continue; - } - if (strcmp(key, "udev_rules") == 0) { - set_value(&udev->rules_path, val); - continue; - } - } - fclose(f); - } - - /* environment overwrites config */ - env = getenv("UDEV_LOG"); - if (env != NULL) - udev_set_log_priority(udev, util_log_priority(env)); - - env = getenv("UDEV_ROOT"); - if (env != NULL) { - set_value(&udev->dev_path, env); - udev_add_property(udev, "UDEV_ROOT", udev->dev_path); - } - - env = getenv("SYSFS_PATH"); - if (env != NULL) { - set_value(&udev->sys_path, env); - udev_add_property(udev, "SYSFS_PATH", udev->sys_path); - } - - /* set defaults */ - if (udev->dev_path == NULL) - if (set_value(&udev->dev_path, "/dev") == NULL) - goto err; - - if (udev->sys_path == NULL) - if (set_value(&udev->sys_path, "/sys") == NULL) - goto err; - - if (udev->run_config_path == NULL) - if (set_value(&udev->run_config_path, "/run/udev") == NULL) - goto err; - - dbg(udev, "context %p created\n", udev); - dbg(udev, "log_priority=%d\n", udev->log_priority); - dbg(udev, "config_file='%s'\n", config_file); - dbg(udev, "dev_path='%s'\n", udev->dev_path); - dbg(udev, "sys_path='%s'\n", udev->sys_path); - dbg(udev, "run_path='%s'\n", udev->run_config_path); - if (udev->rules_path != NULL) - dbg(udev, "rules_path='%s'\n", udev->rules_path); - free(config_file); - return udev; -err: - free(config_file); - err(udev, "context creation failed\n"); - udev_unref(udev); - return NULL; -} - -/** - * udev_ref: - * @udev: udev library context - * - * Take a reference of the udev library context. - * - * Returns: the passed udev library context - **/ -UDEV_EXPORT 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. - * - **/ -UDEV_EXPORT void udev_unref(struct udev *udev) -{ - if (udev == NULL) - return; - udev->refcount--; - if (udev->refcount > 0) - return; - udev_list_cleanup_entries(udev, &udev->properties_list); - free(udev->dev_path); - free(udev->sys_path); - free(udev->rules_path); - free(udev->run_path); - free(udev->run_config_path); - dbg(udev, "context %p released\n", udev); - free(udev); -} - -/** - * udev_set_log_fn: - * @udev: udev library context - * @log_fn: function to be called for logging messages - * - * The built-in logging writes to stderr. It can be - * overridden by a custom function, to plug log messages - * into the users' logging functionality. - * - **/ -UDEV_EXPORT 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)) -{ - udev->log_fn = log_fn; - info(udev, "custom logging function %p registered\n", udev); -} - -/** - * udev_get_log_priority: - * @udev: udev library context - * - * The initial logging priority is read from the udev config file - * at startup. - * - * Returns: the current logging priority - **/ -UDEV_EXPORT int udev_get_log_priority(struct udev *udev) -{ - return udev->log_priority; -} - -/** - * udev_set_log_priority: - * @udev: udev library context - * @priority: the new logging priority - * - * Set the current logging priority. The value controls which messages - * are logged. - **/ -UDEV_EXPORT void udev_set_log_priority(struct udev *udev, int priority) -{ - char num[32]; - - udev->log_priority = priority; - snprintf(num, sizeof(num), "%u", udev->log_priority); - udev_add_property(udev, "UDEV_LOG", num); -} - -const char *udev_get_rules_path(struct udev *udev) -{ - return udev->rules_path; -} - -/** - * udev_get_sys_path: - * @udev: udev library context - * - * Retrieve the sysfs mount point. The default is "/sys". For - * testing purposes, it can be overridden with the environment - * variable SYSFS_PATH. - * - * Returns: the sys mount point - **/ -UDEV_EXPORT const char *udev_get_sys_path(struct udev *udev) -{ - if (udev == NULL) - return NULL; - return udev->sys_path; -} - -/** - * udev_get_dev_path: - * @udev: udev library context - * - * Retrieve the device directory path. The default value is "/dev", - * the actual value may be overridden in the udev configuration - * file. - * - * Returns: the device directory path - **/ -UDEV_EXPORT const char *udev_get_dev_path(struct udev *udev) -{ - if (udev == NULL) - return NULL; - return udev->dev_path; -} - -const char *udev_get_run_config_path(struct udev *udev) -{ - return udev->run_config_path; -} - -/** - * udev_get_run_path: - * @udev: udev library context - * - * Retrieve the udev runtime directory path. The default is "/run/udev". - * - * Returns: the runtime directory path - **/ -UDEV_EXPORT const char *udev_get_run_path(struct udev *udev) -{ - if (udev->run_path != NULL) - return udev->run_path; - - /* check if configured path exists */ - if (access(udev->run_config_path, F_OK) < 0) { - char filename[UTIL_PATH_SIZE]; - - /* fall back to /dev/.udev if that exists */ - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev", NULL); - if (access(filename, F_OK) >= 0) - if (set_value(&udev->run_path, filename) != NULL) - return udev->run_path; - } - - /* use default path */ - set_value(&udev->run_path, udev->run_config_path); - if (udev->run_path == NULL) - return udev->run_config_path; - return udev->run_path; -} - -const char *udev_set_run_path(struct udev *udev, const char *path) -{ - return set_value(&udev->run_path, path); -} - -struct udev_list_entry *udev_add_property(struct udev *udev, const char *key, const char *value) -{ - if (value == NULL) { - struct udev_list_entry *list_entry; - - list_entry = udev_get_properties_list_entry(udev); - list_entry = udev_list_entry_get_by_name(list_entry, key); - if (list_entry != NULL) - udev_list_entry_delete(list_entry); - return NULL; - } - return udev_list_entry_add(udev, &udev->properties_list, key, value, UDEV_LIST_UNIQUE); -} - -struct udev_list_entry *udev_get_properties_list_entry(struct udev *udev) -{ - return udev_list_get_entry(&udev->properties_list); -} diff --git a/src/libudev-legacy/libudev.h b/src/libudev-legacy/libudev.h deleted file mode 100644 index 021ef9e8c0..0000000000 --- a/src/libudev-legacy/libudev.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * libudev - interface to udev device information - * - * Copyright (C) 2008-2010 Kay Sievers <kay.sievers@vrfy.org> - * - * This library 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. - */ - -#ifndef _LIBUDEV_H_ -#define _LIBUDEV_H_ - -#include <stdarg.h> -#include <sys/types.h> -#include <sys/stat.h> - -#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); -void 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)); -int udev_get_log_priority(struct udev *udev); -void udev_set_log_priority(struct udev *udev, int priority); -const char *udev_get_sys_path(struct udev *udev); -const char *udev_get_dev_path(struct udev *udev); -const char *udev_get_run_path(struct udev *udev); -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); -void 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_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); - -/* - * udev_monitor - * - * access to kernel uevents and udev events - */ -struct udev_monitor; -struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor); -void 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); -/* custom socket (use netlink and filters instead) */ -struct udev_monitor *udev_monitor_new_from_socket(struct udev *udev, const char *socket_path); -/* 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); -void 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_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); -void 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); -unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue); -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); -int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue, - unsigned long long int start, unsigned long long int end); -struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue); -struct udev_list_entry *udev_queue_get_failed_list_entry(struct udev_queue *udev_queue); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif |