summaryrefslogtreecommitdiff
path: root/src/libudev-legacy
diff options
context:
space:
mode:
authorAnthony G. Basile <blueness@gentoo.org>2013-06-04 05:41:20 -0400
committerAnthony G. Basile <blueness@gentoo.org>2013-06-04 05:41:20 -0400
commit1cc8667cd93d764db6689820825eb78746060384 (patch)
treed0202f12c48912134b2cf4aaffbc8b0a81d12a1a /src/libudev-legacy
parent813ad77ebb13d38539f0a64f6ad8cfa5ff47fcba (diff)
Remove libudev-legacy
Signed-off-by: Anthony G. Basile <blueness@gentoo.org>
Diffstat (limited to 'src/libudev-legacy')
-rw-r--r--src/libudev-legacy/COPYING504
-rw-r--r--src/libudev-legacy/Makefile.am40
-rw-r--r--src/libudev-legacy/libudev-device.c1775
-rw-r--r--src/libudev-legacy/libudev-enumerate.c831
-rw-r--r--src/libudev-legacy/libudev-list.c278
-rw-r--r--src/libudev-legacy/libudev-monitor.c876
-rw-r--r--src/libudev-legacy/libudev-private.h253
-rw-r--r--src/libudev-legacy/libudev-queue.c515
-rw-r--r--src/libudev-legacy/libudev-util.c568
-rw-r--r--src/libudev-legacy/libudev.c467
-rw-r--r--src/libudev-legacy/libudev.h180
11 files changed, 0 insertions, 6287 deletions
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