diff options
author | Kay Sievers <kay.sievers@vrfy.org> | 2012-04-03 21:24:46 +0200 |
---|---|---|
committer | Kay Sievers <kay.sievers@vrfy.org> | 2012-04-04 05:05:07 +0200 |
commit | 3e2147858f21943d5f4a781c60f33ac22c6096ed (patch) | |
tree | caf12dcef379e98278f7d67a816e0f2069c8fd87 /src/udev/src | |
parent | 19c5f19d69bb5f520fa7213239490c55de06d99d (diff) |
move imported udev into place
Diffstat (limited to 'src/udev/src')
181 files changed, 0 insertions, 31796 deletions
diff --git a/src/udev/src/.gitignore b/src/udev/src/.gitignore deleted file mode 100644 index beb8604bc..000000000 --- a/src/udev/src/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -*.[78] -*.html -udev.pc -libudev.pc -udev*.service diff --git a/src/udev/src/COPYING b/src/udev/src/COPYING deleted file mode 100644 index d2e31278b..000000000 --- a/src/udev/src/COPYING +++ /dev/null @@ -1,502 +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/udev/src/accelerometer/61-accelerometer.rules b/src/udev/src/accelerometer/61-accelerometer.rules deleted file mode 100644 index a6a2bfd08..000000000 --- a/src/udev/src/accelerometer/61-accelerometer.rules +++ /dev/null @@ -1,3 +0,0 @@ -# do not edit this file, it will be overwritten on update - -SUBSYSTEM=="input", ACTION!="remove", ENV{ID_INPUT_ACCELEROMETER}=="1", IMPORT{program}="accelerometer %p" diff --git a/src/udev/src/accelerometer/accelerometer.c b/src/udev/src/accelerometer/accelerometer.c deleted file mode 100644 index bc9715b26..000000000 --- a/src/udev/src/accelerometer/accelerometer.c +++ /dev/null @@ -1,357 +0,0 @@ -/* - * accelerometer - exports device orientation through property - * - * When an "change" event is received on an accelerometer, - * open its device node, and from the value, as well as the previous - * value of the property, calculate the device's new orientation, - * and export it as ID_INPUT_ACCELEROMETER_ORIENTATION. - * - * Possible values are: - * undefined - * * normal - * * bottom-up - * * left-up - * * right-up - * - * The property will be persistent across sessions, and the new - * orientations can be deducted from the previous one (it allows - * for a threshold for switching between opposite ends of the - * orientation). - * - * Copyright (C) 2011 Red Hat, Inc. - * Author: - * Bastien Nocera <hadess@hadess.net> - * - * orientation_calc() from the sensorfw package - * Copyright (C) 2009-2010 Nokia Corporation - * Authors: - * Üstün Ergenoglu <ext-ustun.ergenoglu@nokia.com> - * Timo Rongas <ext-timo.2.rongas@nokia.com> - * Lihan Guo <lihan.guo@digia.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with keymap; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include <stdio.h> -#include <string.h> -#include <math.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <stdlib.h> -#include <unistd.h> -#include <getopt.h> -#include <limits.h> -#include <linux/limits.h> -#include <linux/input.h> - -#include "libudev.h" -#include "libudev-private.h" - -/* we must use this kernel-compatible implementation */ -#define BITS_PER_LONG (sizeof(unsigned long) * 8) -#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) -#define OFF(x) ((x)%BITS_PER_LONG) -#define BIT(x) (1UL<<OFF(x)) -#define LONG(x) ((x)/BITS_PER_LONG) -#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1) - -static int debug = 0; - -static void log_fn(struct udev *udev, int priority, - const char *file, int line, const char *fn, - const char *format, va_list args) -{ - if (debug) { - fprintf(stderr, "%s: ", fn); - vfprintf(stderr, format, args); - } else { - vsyslog(priority, format, args); - } -} - -typedef enum { - ORIENTATION_UNDEFINED, - ORIENTATION_NORMAL, - ORIENTATION_BOTTOM_UP, - ORIENTATION_LEFT_UP, - ORIENTATION_RIGHT_UP -} OrientationUp; - -static const char *orientations[] = { - "undefined", - "normal", - "bottom-up", - "left-up", - "right-up", - NULL -}; - -#define ORIENTATION_UP_UP ORIENTATION_NORMAL - -#define DEFAULT_THRESHOLD 250 -#define RADIANS_TO_DEGREES 180.0/M_PI -#define SAME_AXIS_LIMIT 5 - -#define THRESHOLD_LANDSCAPE 25 -#define THRESHOLD_PORTRAIT 20 - -static const char * -orientation_to_string (OrientationUp o) -{ - return orientations[o]; -} - -static OrientationUp -string_to_orientation (const char *orientation) -{ - int i; - - if (orientation == NULL) - return ORIENTATION_UNDEFINED; - for (i = 0; orientations[i] != NULL; i++) { - if (strcmp (orientation, orientations[i]) == 0) - return i; - } - return ORIENTATION_UNDEFINED; -} - -static OrientationUp -orientation_calc (OrientationUp prev, - int x, int y, int z) -{ - int rotation; - OrientationUp ret = prev; - - /* Portrait check */ - rotation = round(atan((double) x / sqrt(y * y + z * z)) * RADIANS_TO_DEGREES); - - if (abs(rotation) > THRESHOLD_PORTRAIT) { - ret = (rotation < 0) ? ORIENTATION_LEFT_UP : ORIENTATION_RIGHT_UP; - - /* Some threshold to switching between portrait modes */ - if (prev == ORIENTATION_LEFT_UP || prev == ORIENTATION_RIGHT_UP) { - if (abs(rotation) < SAME_AXIS_LIMIT) { - ret = prev; - } - } - - } else { - /* Landscape check */ - rotation = round(atan((double) y / sqrt(x * x + z * z)) * RADIANS_TO_DEGREES); - - if (abs(rotation) > THRESHOLD_LANDSCAPE) { - ret = (rotation < 0) ? ORIENTATION_BOTTOM_UP : ORIENTATION_NORMAL; - - /* Some threshold to switching between landscape modes */ - if (prev == ORIENTATION_BOTTOM_UP || prev == ORIENTATION_NORMAL) { - if (abs(rotation) < SAME_AXIS_LIMIT) { - ret = prev; - } - } - } - } - - return ret; -} - -static OrientationUp -get_prev_orientation(struct udev_device *dev) -{ - const char *value; - - value = udev_device_get_property_value(dev, "ID_INPUT_ACCELEROMETER_ORIENTATION"); - if (value == NULL) - return ORIENTATION_UNDEFINED; - return string_to_orientation(value); -} - -#define SET_AXIS(axis, code_) if (ev[i].code == code_) { if (got_##axis == 0) { axis = ev[i].value; got_##axis = 1; } } - -/* accelerometers */ -static void test_orientation(struct udev *udev, - struct udev_device *dev, - const char *devpath) -{ - OrientationUp old, new; - int fd, r; - struct input_event ev[64]; - int got_syn = 0; - int got_x, got_y, got_z; - int x = 0, y = 0, z = 0; - char text[64]; - - old = get_prev_orientation(dev); - - if ((fd = open(devpath, O_RDONLY)) < 0) - return; - - got_x = got_y = got_z = 0; - - while (1) { - int i; - - r = read(fd, ev, sizeof(struct input_event) * 64); - - if (r < (int) sizeof(struct input_event)) - return; - - for (i = 0; i < r / (int) sizeof(struct input_event); i++) { - if (got_syn == 1) { - if (ev[i].type == EV_ABS) { - SET_AXIS(x, ABS_X); - SET_AXIS(y, ABS_Y); - SET_AXIS(z, ABS_Z); - } - } - if (ev[i].type == EV_SYN && ev[i].code == SYN_REPORT) { - got_syn = 1; - } - if (got_x && got_y && got_z) - goto read_dev; - } - } - -read_dev: - close(fd); - - if (!got_x || !got_y || !got_z) - return; - - new = orientation_calc(old, x, y, z); - snprintf(text, sizeof(text), "ID_INPUT_ACCELEROMETER_ORIENTATION=%s", orientation_to_string(new)); - puts(text); -} - -static void help(void) -{ - printf("Usage: accelerometer [options] <device path>\n" - " --debug debug to stderr\n" - " --help print this help text\n\n"); -} - -int main (int argc, char** argv) -{ - struct udev *udev; - struct udev_device *dev; - - static const struct option options[] = { - { "debug", no_argument, NULL, 'd' }, - { "help", no_argument, NULL, 'h' }, - {} - }; - - char devpath[PATH_MAX]; - char *devnode; - const char *id_path; - struct udev_enumerate *enumerate; - struct udev_list_entry *list_entry; - - udev = udev_new(); - if (udev == NULL) - return 1; - - udev_log_init("input_id"); - udev_set_log_fn(udev, log_fn); - - /* CLI argument parsing */ - while (1) { - int option; - - option = getopt_long(argc, argv, "dxh", options, NULL); - if (option == -1) - break; - - switch (option) { - case 'd': - debug = 1; - if (udev_get_log_priority(udev) < LOG_INFO) - udev_set_log_priority(udev, LOG_INFO); - break; - case 'h': - help(); - exit(0); - default: - exit(1); - } - } - - if (argv[optind] == NULL) { - help(); - exit(1); - } - - /* get the device */ - snprintf(devpath, sizeof(devpath), "%s/%s", udev_get_sys_path(udev), argv[optind]); - dev = udev_device_new_from_syspath(udev, devpath); - if (dev == NULL) { - fprintf(stderr, "unable to access '%s'\n", devpath); - return 1; - } - - id_path = udev_device_get_property_value(dev, "ID_PATH"); - if (id_path == NULL) { - fprintf (stderr, "unable to get property ID_PATH for '%s'", devpath); - return 0; - } - - /* Get the children devices and find the devnode - * FIXME: use udev_enumerate_add_match_children() instead - * when it's available */ - devnode = NULL; - enumerate = udev_enumerate_new(udev); - udev_enumerate_add_match_property(enumerate, "ID_PATH", id_path); - udev_enumerate_add_match_subsystem(enumerate, "input"); - udev_enumerate_scan_devices(enumerate); - udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) { - struct udev_device *device; - const char *node; - - device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate), - udev_list_entry_get_name(list_entry)); - if (device == NULL) - continue; - /* Already found it */ - if (devnode != NULL) { - udev_device_unref(device); - continue; - } - - node = udev_device_get_devnode(device); - if (node == NULL) { - udev_device_unref(device); - continue; - } - /* Use the event sub-device */ - if (strstr(node, "/event") == NULL) { - udev_device_unref(device); - continue; - } - - devnode = strdup(node); - udev_device_unref(device); - } - - if (devnode == NULL) { - fprintf(stderr, "unable to get device node for '%s'\n", devpath); - return 0; - } - - info(udev, "Opening accelerometer device %s\n", devnode); - test_orientation(udev, dev, devnode); - free(devnode); - - return 0; -} diff --git a/src/udev/src/ata_id/ata_id.c b/src/udev/src/ata_id/ata_id.c deleted file mode 100644 index 846a73b54..000000000 --- a/src/udev/src/ata_id/ata_id.c +++ /dev/null @@ -1,721 +0,0 @@ -/* - * ata_id - reads product/serial number from ATA drives - * - * Copyright (C) 2005-2008 Kay Sievers <kay.sievers@vrfy.org> - * Copyright (C) 2009 Lennart Poettering <lennart@poettering.net> - * Copyright (C) 2009-2010 David Zeuthen <zeuthen@gmail.com> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <unistd.h> -#include <fcntl.h> -#include <ctype.h> -#include <assert.h> -#include <string.h> -#include <errno.h> -#include <getopt.h> -#include <scsi/scsi.h> -#include <scsi/sg.h> -#include <scsi/scsi_ioctl.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <linux/types.h> -#include <linux/hdreg.h> -#include <linux/fs.h> -#include <linux/cdrom.h> -#include <linux/bsg.h> -#include <arpa/inet.h> - -#include "libudev.h" -#include "libudev-private.h" - -#define COMMAND_TIMEOUT_MSEC (30 * 1000) - -static int disk_scsi_inquiry_command(int fd, - void *buf, - size_t buf_len) -{ - struct sg_io_v4 io_v4; - uint8_t cdb[6]; - uint8_t sense[32]; - int ret; - - /* - * INQUIRY, see SPC-4 section 6.4 - */ - memset(cdb, 0, sizeof(cdb)); - cdb[0] = 0x12; /* OPERATION CODE: INQUIRY */ - cdb[3] = (buf_len >> 8); /* ALLOCATION LENGTH */ - cdb[4] = (buf_len & 0xff); - - memset(sense, 0, sizeof(sense)); - - memset(&io_v4, 0, sizeof(struct sg_io_v4)); - io_v4.guard = 'Q'; - io_v4.protocol = BSG_PROTOCOL_SCSI; - io_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD; - io_v4.request_len = sizeof (cdb); - io_v4.request = (uintptr_t) cdb; - io_v4.max_response_len = sizeof (sense); - io_v4.response = (uintptr_t) sense; - io_v4.din_xfer_len = buf_len; - io_v4.din_xferp = (uintptr_t) buf; - io_v4.timeout = COMMAND_TIMEOUT_MSEC; - - ret = ioctl(fd, SG_IO, &io_v4); - if (ret != 0) { - /* could be that the driver doesn't do version 4, try version 3 */ - if (errno == EINVAL) { - struct sg_io_hdr io_hdr; - - memset(&io_hdr, 0, sizeof(struct sg_io_hdr)); - io_hdr.interface_id = 'S'; - io_hdr.cmdp = (unsigned char*) cdb; - io_hdr.cmd_len = sizeof (cdb); - io_hdr.dxferp = buf; - io_hdr.dxfer_len = buf_len; - io_hdr.sbp = sense; - io_hdr.mx_sb_len = sizeof (sense); - io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.timeout = COMMAND_TIMEOUT_MSEC; - - ret = ioctl(fd, SG_IO, &io_hdr); - if (ret != 0) - goto out; - - /* even if the ioctl succeeds, we need to check the return value */ - if (!(io_hdr.status == 0 && - io_hdr.host_status == 0 && - io_hdr.driver_status == 0)) { - errno = EIO; - ret = -1; - goto out; - } - } else { - goto out; - } - } - - /* even if the ioctl succeeds, we need to check the return value */ - if (!(io_v4.device_status == 0 && - io_v4.transport_status == 0 && - io_v4.driver_status == 0)) { - errno = EIO; - ret = -1; - goto out; - } - - out: - return ret; -} - -static int disk_identify_command(int fd, - void *buf, - size_t buf_len) -{ - struct sg_io_v4 io_v4; - uint8_t cdb[12]; - uint8_t sense[32]; - uint8_t *desc = sense+8; - int ret; - - /* - * ATA Pass-Through 12 byte command, as described in - * - * T10 04-262r8 ATA Command Pass-Through - * - * from http://www.t10.org/ftp/t10/document.04/04-262r8.pdf - */ - memset(cdb, 0, sizeof(cdb)); - cdb[0] = 0xa1; /* OPERATION CODE: 12 byte pass through */ - cdb[1] = 4 << 1; /* PROTOCOL: PIO Data-in */ - cdb[2] = 0x2e; /* OFF_LINE=0, CK_COND=1, T_DIR=1, BYT_BLOK=1, T_LENGTH=2 */ - cdb[3] = 0; /* FEATURES */ - cdb[4] = 1; /* SECTORS */ - cdb[5] = 0; /* LBA LOW */ - cdb[6] = 0; /* LBA MID */ - cdb[7] = 0; /* LBA HIGH */ - cdb[8] = 0 & 0x4F; /* SELECT */ - cdb[9] = 0xEC; /* Command: ATA IDENTIFY DEVICE */; - memset(sense, 0, sizeof(sense)); - - memset(&io_v4, 0, sizeof(struct sg_io_v4)); - io_v4.guard = 'Q'; - io_v4.protocol = BSG_PROTOCOL_SCSI; - io_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD; - io_v4.request_len = sizeof (cdb); - io_v4.request = (uintptr_t) cdb; - io_v4.max_response_len = sizeof (sense); - io_v4.response = (uintptr_t) sense; - io_v4.din_xfer_len = buf_len; - io_v4.din_xferp = (uintptr_t) buf; - io_v4.timeout = COMMAND_TIMEOUT_MSEC; - - ret = ioctl(fd, SG_IO, &io_v4); - if (ret != 0) { - /* could be that the driver doesn't do version 4, try version 3 */ - if (errno == EINVAL) { - struct sg_io_hdr io_hdr; - - memset(&io_hdr, 0, sizeof(struct sg_io_hdr)); - io_hdr.interface_id = 'S'; - io_hdr.cmdp = (unsigned char*) cdb; - io_hdr.cmd_len = sizeof (cdb); - io_hdr.dxferp = buf; - io_hdr.dxfer_len = buf_len; - io_hdr.sbp = sense; - io_hdr.mx_sb_len = sizeof (sense); - io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.timeout = COMMAND_TIMEOUT_MSEC; - - ret = ioctl(fd, SG_IO, &io_hdr); - if (ret != 0) - goto out; - } else { - goto out; - } - } - - if (!(sense[0] == 0x72 && desc[0] == 0x9 && desc[1] == 0x0c)) { - errno = EIO; - ret = -1; - goto out; - } - - out: - return ret; -} - -static int disk_identify_packet_device_command(int fd, - void *buf, - size_t buf_len) -{ - struct sg_io_v4 io_v4; - uint8_t cdb[16]; - uint8_t sense[32]; - uint8_t *desc = sense+8; - int ret; - - /* - * ATA Pass-Through 16 byte command, as described in - * - * T10 04-262r8 ATA Command Pass-Through - * - * from http://www.t10.org/ftp/t10/document.04/04-262r8.pdf - */ - memset(cdb, 0, sizeof(cdb)); - cdb[0] = 0x85; /* OPERATION CODE: 16 byte pass through */ - cdb[1] = 4 << 1; /* PROTOCOL: PIO Data-in */ - cdb[2] = 0x2e; /* OFF_LINE=0, CK_COND=1, T_DIR=1, BYT_BLOK=1, T_LENGTH=2 */ - cdb[3] = 0; /* FEATURES */ - cdb[4] = 0; /* FEATURES */ - cdb[5] = 0; /* SECTORS */ - cdb[6] = 1; /* SECTORS */ - cdb[7] = 0; /* LBA LOW */ - cdb[8] = 0; /* LBA LOW */ - cdb[9] = 0; /* LBA MID */ - cdb[10] = 0; /* LBA MID */ - cdb[11] = 0; /* LBA HIGH */ - cdb[12] = 0; /* LBA HIGH */ - cdb[13] = 0; /* DEVICE */ - cdb[14] = 0xA1; /* Command: ATA IDENTIFY PACKET DEVICE */; - cdb[15] = 0; /* CONTROL */ - memset(sense, 0, sizeof(sense)); - - memset(&io_v4, 0, sizeof(struct sg_io_v4)); - io_v4.guard = 'Q'; - io_v4.protocol = BSG_PROTOCOL_SCSI; - io_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD; - io_v4.request_len = sizeof (cdb); - io_v4.request = (uintptr_t) cdb; - io_v4.max_response_len = sizeof (sense); - io_v4.response = (uintptr_t) sense; - io_v4.din_xfer_len = buf_len; - io_v4.din_xferp = (uintptr_t) buf; - io_v4.timeout = COMMAND_TIMEOUT_MSEC; - - ret = ioctl(fd, SG_IO, &io_v4); - if (ret != 0) { - /* could be that the driver doesn't do version 4, try version 3 */ - if (errno == EINVAL) { - struct sg_io_hdr io_hdr; - - memset(&io_hdr, 0, sizeof(struct sg_io_hdr)); - io_hdr.interface_id = 'S'; - io_hdr.cmdp = (unsigned char*) cdb; - io_hdr.cmd_len = sizeof (cdb); - io_hdr.dxferp = buf; - io_hdr.dxfer_len = buf_len; - io_hdr.sbp = sense; - io_hdr.mx_sb_len = sizeof (sense); - io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.timeout = COMMAND_TIMEOUT_MSEC; - - ret = ioctl(fd, SG_IO, &io_hdr); - if (ret != 0) - goto out; - } else { - goto out; - } - } - - if (!(sense[0] == 0x72 && desc[0] == 0x9 && desc[1] == 0x0c)) { - errno = EIO; - ret = -1; - goto out; - } - - out: - return ret; -} - -/** - * disk_identify_get_string: - * @identify: A block of IDENTIFY data - * @offset_words: Offset of the string to get, in words. - * @dest: Destination buffer for the string. - * @dest_len: Length of destination buffer, in bytes. - * - * Copies the ATA string from @identify located at @offset_words into @dest. - */ -static void disk_identify_get_string(uint8_t identify[512], - unsigned int offset_words, - char *dest, - size_t dest_len) -{ - unsigned int c1; - unsigned int c2; - - assert(identify != NULL); - assert(dest != NULL); - assert((dest_len & 1) == 0); - - while (dest_len > 0) { - c1 = identify[offset_words * 2 + 1]; - c2 = identify[offset_words * 2]; - *dest = c1; - dest++; - *dest = c2; - dest++; - offset_words++; - dest_len -= 2; - } -} - -static void disk_identify_fixup_string(uint8_t identify[512], - unsigned int offset_words, - size_t len) -{ - disk_identify_get_string(identify, offset_words, - (char *) identify + offset_words * 2, len); -} - -static void disk_identify_fixup_uint16 (uint8_t identify[512], unsigned int offset_words) -{ - uint16_t *p; - - p = (uint16_t *) identify; - p[offset_words] = le16toh (p[offset_words]); -} - -/** - * disk_identify: - * @udev: The libudev context. - * @fd: File descriptor for the block device. - * @out_identify: Return location for IDENTIFY data. - * @out_is_packet_device: Return location for whether returned data is from a IDENTIFY PACKET DEVICE. - * - * Sends the IDENTIFY DEVICE or IDENTIFY PACKET DEVICE command to the - * device represented by @fd. If successful, then the result will be - * copied into @out_identify and @out_is_packet_device. - * - * This routine is based on code from libatasmart, Copyright 2008 - * Lennart Poettering, LGPL v2.1. - * - * Returns: 0 if the data was successfully obtained, otherwise - * non-zero with errno set. - */ -static int disk_identify(struct udev *udev, - int fd, - uint8_t out_identify[512], - int *out_is_packet_device) -{ - int ret; - uint8_t inquiry_buf[36]; - int peripheral_device_type; - int all_nul_bytes; - int n; - int is_packet_device; - - assert(out_identify != NULL); - - /* init results */ - ret = -1; - memset(out_identify, '\0', 512); - is_packet_device = 0; - - /* If we were to use ATA PASS_THROUGH (12) on an ATAPI device - * we could accidentally blank media. This is because MMC's BLANK - * command has the same op-code (0x61). - * - * To prevent this from happening we bail out if the device - * isn't a Direct Access Block Device, e.g. SCSI type 0x00 - * (CD/DVD devices are type 0x05). So we send a SCSI INQUIRY - * command first... libata is handling this via its SCSI - * emulation layer. - * - * This also ensures that we're actually dealing with a device - * that understands SCSI commands. - * - * (Yes, it is a bit perverse that we're tunneling the ATA - * command through SCSI and relying on the ATA driver - * emulating SCSI well-enough...) - * - * (See commit 160b069c25690bfb0c785994c7c3710289179107 for - * the original bug-fix and see http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=556635 - * for the original bug-report.) - */ - ret = disk_scsi_inquiry_command (fd, inquiry_buf, sizeof (inquiry_buf)); - if (ret != 0) - goto out; - - /* SPC-4, section 6.4.2: Standard INQUIRY data */ - peripheral_device_type = inquiry_buf[0] & 0x1f; - if (peripheral_device_type == 0x05) - { - is_packet_device = 1; - ret = disk_identify_packet_device_command(fd, out_identify, 512); - goto check_nul_bytes; - } - if (peripheral_device_type != 0x00) { - ret = -1; - errno = EIO; - goto out; - } - - /* OK, now issue the IDENTIFY DEVICE command */ - ret = disk_identify_command(fd, out_identify, 512); - if (ret != 0) - goto out; - - check_nul_bytes: - /* Check if IDENTIFY data is all NUL bytes - if so, bail */ - all_nul_bytes = 1; - for (n = 0; n < 512; n++) { - if (out_identify[n] != '\0') { - all_nul_bytes = 0; - break; - } - } - - if (all_nul_bytes) { - ret = -1; - errno = EIO; - goto out; - } - -out: - if (out_is_packet_device != NULL) - *out_is_packet_device = is_packet_device; - return ret; -} - -static void log_fn(struct udev *udev, int priority, - const char *file, int line, const char *fn, - const char *format, va_list args) -{ - vsyslog(priority, format, args); -} - -int main(int argc, char *argv[]) -{ - struct udev *udev; - struct hd_driveid id; - uint8_t identify[512]; - uint16_t *identify_words; - char model[41]; - char model_enc[256]; - char serial[21]; - char revision[9]; - const char *node = NULL; - int export = 0; - int fd; - uint16_t word; - int rc = 0; - int is_packet_device = 0; - static const struct option options[] = { - { "export", no_argument, NULL, 'x' }, - { "help", no_argument, NULL, 'h' }, - {} - }; - - udev = udev_new(); - if (udev == NULL) - goto exit; - - udev_log_init("ata_id"); - udev_set_log_fn(udev, log_fn); - - while (1) { - int option; - - option = getopt_long(argc, argv, "xh", options, NULL); - if (option == -1) - break; - - switch (option) { - case 'x': - export = 1; - break; - case 'h': - printf("Usage: ata_id [--export] [--help] <device>\n" - " --export print values as environment keys\n" - " --help print this help text\n\n"); - goto exit; - } - } - - node = argv[optind]; - if (node == NULL) { - err(udev, "no node specified\n"); - rc = 1; - goto exit; - } - - fd = open(node, O_RDONLY|O_NONBLOCK); - if (fd < 0) { - err(udev, "unable to open '%s'\n", node); - rc = 1; - goto exit; - } - - if (disk_identify(udev, fd, identify, &is_packet_device) == 0) { - /* - * fix up only the fields from the IDENTIFY data that we are going to - * use and copy it into the hd_driveid struct for convenience - */ - disk_identify_fixup_string (identify, 10, 20); /* serial */ - disk_identify_fixup_string (identify, 23, 6); /* fwrev */ - disk_identify_fixup_string (identify, 27, 40); /* model */ - disk_identify_fixup_uint16 (identify, 0); /* configuration */ - disk_identify_fixup_uint16 (identify, 75); /* queue depth */ - disk_identify_fixup_uint16 (identify, 75); /* SATA capabilities */ - disk_identify_fixup_uint16 (identify, 82); /* command set supported */ - disk_identify_fixup_uint16 (identify, 83); /* command set supported */ - disk_identify_fixup_uint16 (identify, 84); /* command set supported */ - disk_identify_fixup_uint16 (identify, 85); /* command set supported */ - disk_identify_fixup_uint16 (identify, 86); /* command set supported */ - disk_identify_fixup_uint16 (identify, 87); /* command set supported */ - disk_identify_fixup_uint16 (identify, 89); /* time required for SECURITY ERASE UNIT */ - disk_identify_fixup_uint16 (identify, 90); /* time required for enhanced SECURITY ERASE UNIT */ - disk_identify_fixup_uint16 (identify, 91); /* current APM values */ - disk_identify_fixup_uint16 (identify, 94); /* current AAM value */ - disk_identify_fixup_uint16 (identify, 128); /* device lock function */ - disk_identify_fixup_uint16 (identify, 217); /* nominal media rotation rate */ - memcpy(&id, identify, sizeof id); - } else { - /* If this fails, then try HDIO_GET_IDENTITY */ - if (ioctl(fd, HDIO_GET_IDENTITY, &id) != 0) { - info(udev, "HDIO_GET_IDENTITY failed for '%s': %m\n", node); - rc = 2; - goto close; - } - } - identify_words = (uint16_t *) identify; - - memcpy (model, id.model, 40); - model[40] = '\0'; - udev_util_encode_string(model, model_enc, sizeof(model_enc)); - util_replace_whitespace((char *) id.model, model, 40); - util_replace_chars(model, NULL); - util_replace_whitespace((char *) id.serial_no, serial, 20); - util_replace_chars(serial, NULL); - util_replace_whitespace((char *) id.fw_rev, revision, 8); - util_replace_chars(revision, NULL); - - if (export) { - /* Set this to convey the disk speaks the ATA protocol */ - printf("ID_ATA=1\n"); - - if ((id.config >> 8) & 0x80) { - /* This is an ATAPI device */ - switch ((id.config >> 8) & 0x1f) { - case 0: - printf("ID_TYPE=cd\n"); - break; - case 1: - printf("ID_TYPE=tape\n"); - break; - case 5: - printf("ID_TYPE=cd\n"); - break; - case 7: - printf("ID_TYPE=optical\n"); - break; - default: - printf("ID_TYPE=generic\n"); - break; - } - } else { - printf("ID_TYPE=disk\n"); - } - printf("ID_BUS=ata\n"); - printf("ID_MODEL=%s\n", model); - printf("ID_MODEL_ENC=%s\n", model_enc); - printf("ID_REVISION=%s\n", revision); - if (serial[0] != '\0') { - printf("ID_SERIAL=%s_%s\n", model, serial); - printf("ID_SERIAL_SHORT=%s\n", serial); - } else { - printf("ID_SERIAL=%s\n", model); - } - - if (id.command_set_1 & (1<<5)) { - printf ("ID_ATA_WRITE_CACHE=1\n"); - printf ("ID_ATA_WRITE_CACHE_ENABLED=%d\n", (id.cfs_enable_1 & (1<<5)) ? 1 : 0); - } - if (id.command_set_1 & (1<<10)) { - printf("ID_ATA_FEATURE_SET_HPA=1\n"); - printf("ID_ATA_FEATURE_SET_HPA_ENABLED=%d\n", (id.cfs_enable_1 & (1<<10)) ? 1 : 0); - - /* - * TODO: use the READ NATIVE MAX ADDRESS command to get the native max address - * so it is easy to check whether the protected area is in use. - */ - } - if (id.command_set_1 & (1<<3)) { - printf("ID_ATA_FEATURE_SET_PM=1\n"); - printf("ID_ATA_FEATURE_SET_PM_ENABLED=%d\n", (id.cfs_enable_1 & (1<<3)) ? 1 : 0); - } - if (id.command_set_1 & (1<<1)) { - printf("ID_ATA_FEATURE_SET_SECURITY=1\n"); - printf("ID_ATA_FEATURE_SET_SECURITY_ENABLED=%d\n", (id.cfs_enable_1 & (1<<1)) ? 1 : 0); - printf("ID_ATA_FEATURE_SET_SECURITY_ERASE_UNIT_MIN=%d\n", id.trseuc * 2); - if ((id.cfs_enable_1 & (1<<1))) /* enabled */ { - if (id.dlf & (1<<8)) - printf("ID_ATA_FEATURE_SET_SECURITY_LEVEL=maximum\n"); - else - printf("ID_ATA_FEATURE_SET_SECURITY_LEVEL=high\n"); - } - if (id.dlf & (1<<5)) - printf("ID_ATA_FEATURE_SET_SECURITY_ENHANCED_ERASE_UNIT_MIN=%d\n", id.trsEuc * 2); - if (id.dlf & (1<<4)) - printf("ID_ATA_FEATURE_SET_SECURITY_EXPIRE=1\n"); - if (id.dlf & (1<<3)) - printf("ID_ATA_FEATURE_SET_SECURITY_FROZEN=1\n"); - if (id.dlf & (1<<2)) - printf("ID_ATA_FEATURE_SET_SECURITY_LOCKED=1\n"); - } - if (id.command_set_1 & (1<<0)) { - printf("ID_ATA_FEATURE_SET_SMART=1\n"); - printf("ID_ATA_FEATURE_SET_SMART_ENABLED=%d\n", (id.cfs_enable_1 & (1<<0)) ? 1 : 0); - } - if (id.command_set_2 & (1<<9)) { - printf("ID_ATA_FEATURE_SET_AAM=1\n"); - printf("ID_ATA_FEATURE_SET_AAM_ENABLED=%d\n", (id.cfs_enable_2 & (1<<9)) ? 1 : 0); - printf("ID_ATA_FEATURE_SET_AAM_VENDOR_RECOMMENDED_VALUE=%d\n", id.acoustic >> 8); - printf("ID_ATA_FEATURE_SET_AAM_CURRENT_VALUE=%d\n", id.acoustic & 0xff); - } - if (id.command_set_2 & (1<<5)) { - printf("ID_ATA_FEATURE_SET_PUIS=1\n"); - printf("ID_ATA_FEATURE_SET_PUIS_ENABLED=%d\n", (id.cfs_enable_2 & (1<<5)) ? 1 : 0); - } - if (id.command_set_2 & (1<<3)) { - printf("ID_ATA_FEATURE_SET_APM=1\n"); - printf("ID_ATA_FEATURE_SET_APM_ENABLED=%d\n", (id.cfs_enable_2 & (1<<3)) ? 1 : 0); - if ((id.cfs_enable_2 & (1<<3))) - printf("ID_ATA_FEATURE_SET_APM_CURRENT_VALUE=%d\n", id.CurAPMvalues & 0xff); - } - if (id.command_set_2 & (1<<0)) - printf("ID_ATA_DOWNLOAD_MICROCODE=1\n"); - - /* - * Word 76 indicates the capabilities of a SATA device. A PATA device shall set - * word 76 to 0000h or FFFFh. If word 76 is set to 0000h or FFFFh, then - * the device does not claim compliance with the Serial ATA specification and words - * 76 through 79 are not valid and shall be ignored. - */ - word = *((uint16_t *) identify + 76); - if (word != 0x0000 && word != 0xffff) { - printf("ID_ATA_SATA=1\n"); - /* - * If bit 2 of word 76 is set to one, then the device supports the Gen2 - * signaling rate of 3.0 Gb/s (see SATA 2.6). - * - * If bit 1 of word 76 is set to one, then the device supports the Gen1 - * signaling rate of 1.5 Gb/s (see SATA 2.6). - */ - if (word & (1<<2)) - printf("ID_ATA_SATA_SIGNAL_RATE_GEN2=1\n"); - if (word & (1<<1)) - printf("ID_ATA_SATA_SIGNAL_RATE_GEN1=1\n"); - } - - /* Word 217 indicates the nominal media rotation rate of the device */ - word = *((uint16_t *) identify + 217); - if (word != 0x0000) { - if (word == 0x0001) { - printf ("ID_ATA_ROTATION_RATE_RPM=0\n"); /* non-rotating e.g. SSD */ - } else if (word >= 0x0401 && word <= 0xfffe) { - printf ("ID_ATA_ROTATION_RATE_RPM=%d\n", word); - } - } - - /* - * Words 108-111 contain a mandatory World Wide Name (WWN) in the NAA IEEE Registered identifier - * format. Word 108 bits (15:12) shall contain 5h, indicating that the naming authority is IEEE. - * All other values are reserved. - */ - word = *((uint16_t *) identify + 108); - if ((word & 0xf000) == 0x5000) { - uint64_t wwwn; - - wwwn = *((uint16_t *) identify + 108); - wwwn <<= 16; - wwwn |= *((uint16_t *) identify + 109); - wwwn <<= 16; - wwwn |= *((uint16_t *) identify + 110); - wwwn <<= 16; - wwwn |= *((uint16_t *) identify + 111); - printf("ID_WWN=0x%llx\n", (unsigned long long int) wwwn); - /* ATA devices have no vendor extension */ - printf("ID_WWN_WITH_EXTENSION=0x%llx\n", (unsigned long long int) wwwn); - } - - /* from Linux's include/linux/ata.h */ - if (identify_words[0] == 0x848a || identify_words[0] == 0x844a) { - printf("ID_ATA_CFA=1\n"); - } else { - if ((identify_words[83] & 0xc004) == 0x4004) { - printf("ID_ATA_CFA=1\n"); - } - } - } else { - if (serial[0] != '\0') - printf("%s_%s\n", model, serial); - else - printf("%s\n", model); - } -close: - close(fd); -exit: - udev_unref(udev); - udev_log_close(); - return rc; -} diff --git a/src/udev/src/cdrom_id/60-cdrom_id.rules b/src/udev/src/cdrom_id/60-cdrom_id.rules deleted file mode 100644 index 6eaf76a72..000000000 --- a/src/udev/src/cdrom_id/60-cdrom_id.rules +++ /dev/null @@ -1,20 +0,0 @@ -# do not edit this file, it will be overwritten on update - -ACTION=="remove", GOTO="cdrom_end" -SUBSYSTEM!="block", GOTO="cdrom_end" -KERNEL!="sr[0-9]*|xvd*", GOTO="cdrom_end" -ENV{DEVTYPE}!="disk", GOTO="cdrom_end" - -# unconditionally tag device as CDROM -KERNEL=="sr[0-9]*", ENV{ID_CDROM}="1" - -# media eject button pressed -ENV{DISK_EJECT_REQUEST}=="?*", RUN+="cdrom_id --eject-media $devnode", GOTO="cdrom_end" - -# import device and media properties and lock tray to -# enable the receiving of media eject button events -IMPORT{program}="cdrom_id --lock-media $devnode" - -KERNEL=="sr0", SYMLINK+="cdrom", OPTIONS+="link_priority=-100" - -LABEL="cdrom_end" diff --git a/src/udev/src/cdrom_id/cdrom_id.c b/src/udev/src/cdrom_id/cdrom_id.c deleted file mode 100644 index f90d52ec9..000000000 --- a/src/udev/src/cdrom_id/cdrom_id.c +++ /dev/null @@ -1,1099 +0,0 @@ -/* - * cdrom_id - optical drive and media information prober - * - * Copyright (C) 2008-2010 Kay Sievers <kay.sievers@vrfy.org> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE 1 -#endif - -#include <stdio.h> -#include <stddef.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <limits.h> -#include <fcntl.h> -#include <errno.h> -#include <getopt.h> -#include <time.h> -#include <scsi/sg.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <sys/ioctl.h> -#include <linux/cdrom.h> - -#include "libudev.h" -#include "libudev-private.h" - -static bool debug; - -static void log_fn(struct udev *udev, int priority, - const char *file, int line, const char *fn, - const char *format, va_list args) -{ - if (debug) { - fprintf(stderr, "%s: ", fn); - vfprintf(stderr, format, args); - } else { - vsyslog(priority, format, args); - } -} - -/* device info */ -static unsigned int cd_cd_rom; -static unsigned int cd_cd_r; -static unsigned int cd_cd_rw; -static unsigned int cd_dvd_rom; -static unsigned int cd_dvd_r; -static unsigned int cd_dvd_rw; -static unsigned int cd_dvd_ram; -static unsigned int cd_dvd_plus_r; -static unsigned int cd_dvd_plus_rw; -static unsigned int cd_dvd_plus_r_dl; -static unsigned int cd_dvd_plus_rw_dl; -static unsigned int cd_bd; -static unsigned int cd_bd_r; -static unsigned int cd_bd_re; -static unsigned int cd_hddvd; -static unsigned int cd_hddvd_r; -static unsigned int cd_hddvd_rw; -static unsigned int cd_mo; -static unsigned int cd_mrw; -static unsigned int cd_mrw_w; - -/* media info */ -static unsigned int cd_media; -static unsigned int cd_media_cd_rom; -static unsigned int cd_media_cd_r; -static unsigned int cd_media_cd_rw; -static unsigned int cd_media_dvd_rom; -static unsigned int cd_media_dvd_r; -static unsigned int cd_media_dvd_rw; -static unsigned int cd_media_dvd_rw_ro; /* restricted overwrite mode */ -static unsigned int cd_media_dvd_rw_seq; /* sequential mode */ -static unsigned int cd_media_dvd_ram; -static unsigned int cd_media_dvd_plus_r; -static unsigned int cd_media_dvd_plus_rw; -static unsigned int cd_media_dvd_plus_r_dl; -static unsigned int cd_media_dvd_plus_rw_dl; -static unsigned int cd_media_bd; -static unsigned int cd_media_bd_r; -static unsigned int cd_media_bd_re; -static unsigned int cd_media_hddvd; -static unsigned int cd_media_hddvd_r; -static unsigned int cd_media_hddvd_rw; -static unsigned int cd_media_mo; -static unsigned int cd_media_mrw; -static unsigned int cd_media_mrw_w; - -static const char *cd_media_state = NULL; -static unsigned int cd_media_session_next; -static unsigned int cd_media_session_count; -static unsigned int cd_media_track_count; -static unsigned int cd_media_track_count_data; -static unsigned int cd_media_track_count_audio; -static unsigned long long int cd_media_session_last_offset; - -#define ERRCODE(s) ((((s)[2] & 0x0F) << 16) | ((s)[12] << 8) | ((s)[13])) -#define SK(errcode) (((errcode) >> 16) & 0xF) -#define ASC(errcode) (((errcode) >> 8) & 0xFF) -#define ASCQ(errcode) ((errcode) & 0xFF) - -static bool is_mounted(const char *device) -{ - struct stat statbuf; - FILE *fp; - int maj, min; - bool mounted = false; - - if (stat(device, &statbuf) < 0) - return -ENODEV; - - fp = fopen("/proc/self/mountinfo", "r"); - if (fp == NULL) - return -ENOSYS; - while (fscanf(fp, "%*s %*s %i:%i %*[^\n]", &maj, &min) == 2) { - if (makedev(maj, min) == statbuf.st_rdev) { - mounted = true; - break; - } - } - fclose(fp); - return mounted; -} - -static void info_scsi_cmd_err(struct udev *udev, char *cmd, int err) -{ - if (err == -1) { - info(udev, "%s failed\n", cmd); - return; - } - info(udev, "%s failed with SK=%Xh/ASC=%02Xh/ACQ=%02Xh\n", cmd, SK(err), ASC(err), ASCQ(err)); -} - -struct scsi_cmd { - struct cdrom_generic_command cgc; - union { - struct request_sense s; - unsigned char u[18]; - } _sense; - struct sg_io_hdr sg_io; -}; - -static void scsi_cmd_init(struct udev *udev, struct scsi_cmd *cmd) -{ - memset(cmd, 0x00, sizeof(struct scsi_cmd)); - cmd->cgc.quiet = 1; - cmd->cgc.sense = &cmd->_sense.s; - cmd->sg_io.interface_id = 'S'; - cmd->sg_io.mx_sb_len = sizeof(cmd->_sense); - cmd->sg_io.cmdp = cmd->cgc.cmd; - cmd->sg_io.sbp = cmd->_sense.u; - cmd->sg_io.flags = SG_FLAG_LUN_INHIBIT | SG_FLAG_DIRECT_IO; -} - -static void scsi_cmd_set(struct udev *udev, struct scsi_cmd *cmd, size_t i, unsigned char arg) -{ - cmd->sg_io.cmd_len = i + 1; - cmd->cgc.cmd[i] = arg; -} - -#define CHECK_CONDITION 0x01 - -static int scsi_cmd_run(struct udev *udev, struct scsi_cmd *cmd, int fd, unsigned char *buf, size_t bufsize) -{ - int ret = 0; - - if (bufsize > 0) { - cmd->sg_io.dxferp = buf; - cmd->sg_io.dxfer_len = bufsize; - cmd->sg_io.dxfer_direction = SG_DXFER_FROM_DEV; - } else { - cmd->sg_io.dxfer_direction = SG_DXFER_NONE; - } - if (ioctl(fd, SG_IO, &cmd->sg_io)) - return -1; - - if ((cmd->sg_io.info & SG_INFO_OK_MASK) != SG_INFO_OK) { - errno = EIO; - ret = -1; - if (cmd->sg_io.masked_status & CHECK_CONDITION) { - ret = ERRCODE(cmd->_sense.u); - if (ret == 0) - ret = -1; - } - } - return ret; -} - -static int media_lock(struct udev *udev, int fd, bool lock) -{ - int err; - - /* disable the kernel's lock logic */ - err = ioctl(fd, CDROM_CLEAR_OPTIONS, CDO_LOCK); - if (err < 0) - info(udev, "CDROM_CLEAR_OPTIONS, CDO_LOCK failed\n"); - - err = ioctl(fd, CDROM_LOCKDOOR, lock ? 1 : 0); - if (err < 0) - info(udev, "CDROM_LOCKDOOR failed\n"); - - return err; -} - -static int media_eject(struct udev *udev, int fd) -{ - struct scsi_cmd sc; - int err; - - scsi_cmd_init(udev, &sc); - scsi_cmd_set(udev, &sc, 0, 0x1b); - scsi_cmd_set(udev, &sc, 4, 0x02); - scsi_cmd_set(udev, &sc, 5, 0); - err = scsi_cmd_run(udev, &sc, fd, NULL, 0); - if ((err != 0)) { - info_scsi_cmd_err(udev, "START_STOP_UNIT", err); - return -1; - } - return 0; -} - -static int cd_capability_compat(struct udev *udev, int fd) -{ - int capability; - - capability = ioctl(fd, CDROM_GET_CAPABILITY, NULL); - if (capability < 0) { - info(udev, "CDROM_GET_CAPABILITY failed\n"); - return -1; - } - - if (capability & CDC_CD_R) - cd_cd_r = 1; - if (capability & CDC_CD_RW) - cd_cd_rw = 1; - if (capability & CDC_DVD) - cd_dvd_rom = 1; - if (capability & CDC_DVD_R) - cd_dvd_r = 1; - if (capability & CDC_DVD_RAM) - cd_dvd_ram = 1; - if (capability & CDC_MRW) - cd_mrw = 1; - if (capability & CDC_MRW_W) - cd_mrw_w = 1; - return 0; -} - -static int cd_media_compat(struct udev *udev, int fd) -{ - if (ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) != CDS_DISC_OK) { - info(udev, "CDROM_DRIVE_STATUS != CDS_DISC_OK\n"); - return -1; - } - cd_media = 1; - return 0; -} - -static int cd_inquiry(struct udev *udev, int fd) -{ - struct scsi_cmd sc; - unsigned char inq[128]; - int err; - - scsi_cmd_init(udev, &sc); - scsi_cmd_set(udev, &sc, 0, 0x12); - scsi_cmd_set(udev, &sc, 4, 36); - scsi_cmd_set(udev, &sc, 5, 0); - err = scsi_cmd_run(udev, &sc, fd, inq, 36); - if ((err != 0)) { - info_scsi_cmd_err(udev, "INQUIRY", err); - return -1; - } - - if ((inq[0] & 0x1F) != 5) { - info(udev, "not an MMC unit\n"); - return -1; - } - - info(udev, "INQUIRY: [%.8s][%.16s][%.4s]\n", inq + 8, inq + 16, inq + 32); - return 0; -} - -static void feature_profile_media(struct udev *udev, int cur_profile) -{ - switch (cur_profile) { - case 0x03: - case 0x04: - case 0x05: - info(udev, "profile 0x%02x \n", cur_profile); - cd_media = 1; - cd_media_mo = 1; - break; - case 0x08: - info(udev, "profile 0x%02x media_cd_rom\n", cur_profile); - cd_media = 1; - cd_media_cd_rom = 1; - break; - case 0x09: - info(udev, "profile 0x%02x media_cd_r\n", cur_profile); - cd_media = 1; - cd_media_cd_r = 1; - break; - case 0x0a: - info(udev, "profile 0x%02x media_cd_rw\n", cur_profile); - cd_media = 1; - cd_media_cd_rw = 1; - break; - case 0x10: - info(udev, "profile 0x%02x media_dvd_ro\n", cur_profile); - cd_media = 1; - cd_media_dvd_rom = 1; - break; - case 0x11: - info(udev, "profile 0x%02x media_dvd_r\n", cur_profile); - cd_media = 1; - cd_media_dvd_r = 1; - break; - case 0x12: - info(udev, "profile 0x%02x media_dvd_ram\n", cur_profile); - cd_media = 1; - cd_media_dvd_ram = 1; - break; - case 0x13: - info(udev, "profile 0x%02x media_dvd_rw_ro\n", cur_profile); - cd_media = 1; - cd_media_dvd_rw = 1; - cd_media_dvd_rw_ro = 1; - break; - case 0x14: - info(udev, "profile 0x%02x media_dvd_rw_seq\n", cur_profile); - cd_media = 1; - cd_media_dvd_rw = 1; - cd_media_dvd_rw_seq = 1; - break; - case 0x1B: - info(udev, "profile 0x%02x media_dvd_plus_r\n", cur_profile); - cd_media = 1; - cd_media_dvd_plus_r = 1; - break; - case 0x1A: - info(udev, "profile 0x%02x media_dvd_plus_rw\n", cur_profile); - cd_media = 1; - cd_media_dvd_plus_rw = 1; - break; - case 0x2A: - info(udev, "profile 0x%02x media_dvd_plus_rw_dl\n", cur_profile); - cd_media = 1; - cd_media_dvd_plus_rw_dl = 1; - break; - case 0x2B: - info(udev, "profile 0x%02x media_dvd_plus_r_dl\n", cur_profile); - cd_media = 1; - cd_media_dvd_plus_r_dl = 1; - break; - case 0x40: - info(udev, "profile 0x%02x media_bd\n", cur_profile); - cd_media = 1; - cd_media_bd = 1; - break; - case 0x41: - case 0x42: - info(udev, "profile 0x%02x media_bd_r\n", cur_profile); - cd_media = 1; - cd_media_bd_r = 1; - break; - case 0x43: - info(udev, "profile 0x%02x media_bd_re\n", cur_profile); - cd_media = 1; - cd_media_bd_re = 1; - break; - case 0x50: - info(udev, "profile 0x%02x media_hddvd\n", cur_profile); - cd_media = 1; - cd_media_hddvd = 1; - break; - case 0x51: - info(udev, "profile 0x%02x media_hddvd_r\n", cur_profile); - cd_media = 1; - cd_media_hddvd_r = 1; - break; - case 0x52: - info(udev, "profile 0x%02x media_hddvd_rw\n", cur_profile); - cd_media = 1; - cd_media_hddvd_rw = 1; - break; - default: - info(udev, "profile 0x%02x <ignored>\n", cur_profile); - break; - } -} - -static int feature_profiles(struct udev *udev, const unsigned char *profiles, size_t size) -{ - unsigned int i; - - for (i = 0; i+4 <= size; i += 4) { - int profile; - - profile = profiles[i] << 8 | profiles[i+1]; - switch (profile) { - case 0x03: - case 0x04: - case 0x05: - info(udev, "profile 0x%02x mo\n", profile); - cd_mo = 1; - break; - case 0x08: - info(udev, "profile 0x%02x cd_rom\n", profile); - cd_cd_rom = 1; - break; - case 0x09: - info(udev, "profile 0x%02x cd_r\n", profile); - cd_cd_r = 1; - break; - case 0x0A: - info(udev, "profile 0x%02x cd_rw\n", profile); - cd_cd_rw = 1; - break; - case 0x10: - info(udev, "profile 0x%02x dvd_rom\n", profile); - cd_dvd_rom = 1; - break; - case 0x12: - info(udev, "profile 0x%02x dvd_ram\n", profile); - cd_dvd_ram = 1; - break; - case 0x13: - case 0x14: - info(udev, "profile 0x%02x dvd_rw\n", profile); - cd_dvd_rw = 1; - break; - case 0x1B: - info(udev, "profile 0x%02x dvd_plus_r\n", profile); - cd_dvd_plus_r = 1; - break; - case 0x1A: - info(udev, "profile 0x%02x dvd_plus_rw\n", profile); - cd_dvd_plus_rw = 1; - break; - case 0x2A: - info(udev, "profile 0x%02x dvd_plus_rw_dl\n", profile); - cd_dvd_plus_rw_dl = 1; - break; - case 0x2B: - info(udev, "profile 0x%02x dvd_plus_r_dl\n", profile); - cd_dvd_plus_r_dl = 1; - break; - case 0x40: - cd_bd = 1; - info(udev, "profile 0x%02x bd\n", profile); - break; - case 0x41: - case 0x42: - cd_bd_r = 1; - info(udev, "profile 0x%02x bd_r\n", profile); - break; - case 0x43: - cd_bd_re = 1; - info(udev, "profile 0x%02x bd_re\n", profile); - break; - case 0x50: - cd_hddvd = 1; - info(udev, "profile 0x%02x hddvd\n", profile); - break; - case 0x51: - cd_hddvd_r = 1; - info(udev, "profile 0x%02x hddvd_r\n", profile); - break; - case 0x52: - cd_hddvd_rw = 1; - info(udev, "profile 0x%02x hddvd_rw\n", profile); - break; - default: - info(udev, "profile 0x%02x <ignored>\n", profile); - break; - } - } - return 0; -} - -/* returns 0 if media was detected */ -static int cd_profiles_old_mmc(struct udev *udev, int fd) -{ - struct scsi_cmd sc; - int err; - - unsigned char header[32]; - - scsi_cmd_init(udev, &sc); - scsi_cmd_set(udev, &sc, 0, 0x51); - scsi_cmd_set(udev, &sc, 8, sizeof(header)); - scsi_cmd_set(udev, &sc, 9, 0); - err = scsi_cmd_run(udev, &sc, fd, header, sizeof(header)); - if ((err != 0)) { - info_scsi_cmd_err(udev, "READ DISC INFORMATION", err); - if (cd_media == 1) { - info(udev, "no current profile, but disc is present; assuming CD-ROM\n"); - cd_media_cd_rom = 1; - return 0; - } else { - info(udev, "no current profile, assuming no media\n"); - return -1; - } - }; - - cd_media = 1; - - if (header[2] & 16) { - cd_media_cd_rw = 1; - info(udev, "profile 0x0a media_cd_rw\n"); - } else if ((header[2] & 3) < 2 && cd_cd_r) { - cd_media_cd_r = 1; - info(udev, "profile 0x09 media_cd_r\n"); - } else { - cd_media_cd_rom = 1; - info(udev, "profile 0x08 media_cd_rom\n"); - } - return 0; -} - -/* returns 0 if media was detected */ -static int cd_profiles(struct udev *udev, int fd) -{ - struct scsi_cmd sc; - unsigned char features[65530]; - unsigned int cur_profile = 0; - unsigned int len; - unsigned int i; - int err; - int ret; - - ret = -1; - - /* First query the current profile */ - scsi_cmd_init(udev, &sc); - scsi_cmd_set(udev, &sc, 0, 0x46); - scsi_cmd_set(udev, &sc, 8, 8); - scsi_cmd_set(udev, &sc, 9, 0); - err = scsi_cmd_run(udev, &sc, fd, features, 8); - if ((err != 0)) { - info_scsi_cmd_err(udev, "GET CONFIGURATION", err); - /* handle pre-MMC2 drives which do not support GET CONFIGURATION */ - if (SK(err) == 0x5 && ASC(err) == 0x20) { - info(udev, "drive is pre-MMC2 and does not support 46h get configuration command\n"); - info(udev, "trying to work around the problem\n"); - ret = cd_profiles_old_mmc(udev, fd); - } - goto out; - } - - cur_profile = features[6] << 8 | features[7]; - if (cur_profile > 0) { - info(udev, "current profile 0x%02x\n", cur_profile); - feature_profile_media (udev, cur_profile); - ret = 0; /* we have media */ - } else { - info(udev, "no current profile, assuming no media\n"); - } - - len = features[0] << 24 | features[1] << 16 | features[2] << 8 | features[3]; - info(udev, "GET CONFIGURATION: size of features buffer 0x%04x\n", len); - - if (len > sizeof(features)) { - info(udev, "can not get features in a single query, truncating\n"); - len = sizeof(features); - } else if (len <= 8) { - len = sizeof(features); - } - - /* Now get the full feature buffer */ - scsi_cmd_init(udev, &sc); - scsi_cmd_set(udev, &sc, 0, 0x46); - scsi_cmd_set(udev, &sc, 7, ( len >> 8 ) & 0xff); - scsi_cmd_set(udev, &sc, 8, len & 0xff); - scsi_cmd_set(udev, &sc, 9, 0); - err = scsi_cmd_run(udev, &sc, fd, features, len); - if ((err != 0)) { - info_scsi_cmd_err(udev, "GET CONFIGURATION", err); - return -1; - } - - /* parse the length once more, in case the drive decided to have other features suddenly :) */ - len = features[0] << 24 | features[1] << 16 | features[2] << 8 | features[3]; - info(udev, "GET CONFIGURATION: size of features buffer 0x%04x\n", len); - - if (len > sizeof(features)) { - info(udev, "can not get features in a single query, truncating\n"); - len = sizeof(features); - } - - /* device features */ - for (i = 8; i+4 < len; i += (4 + features[i+3])) { - unsigned int feature; - - feature = features[i] << 8 | features[i+1]; - - switch (feature) { - case 0x00: - info(udev, "GET CONFIGURATION: feature 'profiles', with %i entries\n", features[i+3] / 4); - feature_profiles(udev, &features[i]+4, features[i+3]); - break; - default: - info(udev, "GET CONFIGURATION: feature 0x%04x <ignored>, with 0x%02x bytes\n", feature, features[i+3]); - break; - } - } -out: - return ret; -} - -static int cd_media_info(struct udev *udev, int fd) -{ - struct scsi_cmd sc; - unsigned char header[32]; - static const char *media_status[] = { - "blank", - "appendable", - "complete", - "other" - }; - int err; - - scsi_cmd_init(udev, &sc); - scsi_cmd_set(udev, &sc, 0, 0x51); - scsi_cmd_set(udev, &sc, 8, sizeof(header) & 0xff); - scsi_cmd_set(udev, &sc, 9, 0); - err = scsi_cmd_run(udev, &sc, fd, header, sizeof(header)); - if ((err != 0)) { - info_scsi_cmd_err(udev, "READ DISC INFORMATION", err); - return -1; - }; - - cd_media = 1; - info(udev, "disk type %02x\n", header[8]); - info(udev, "hardware reported media status: %s\n", media_status[header[2] & 3]); - - /* exclude plain CDROM, some fake cdroms return 0 for "blank" media here */ - if (!cd_media_cd_rom) - cd_media_state = media_status[header[2] & 3]; - - /* fresh DVD-RW in restricted overwite mode reports itself as - * "appendable"; change it to "blank" to make it consistent with what - * gets reported after blanking, and what userspace expects */ - if (cd_media_dvd_rw_ro && (header[2] & 3) == 1) - cd_media_state = media_status[0]; - - /* DVD+RW discs (and DVD-RW in restricted mode) once formatted are - * always "complete", DVD-RAM are "other" or "complete" if the disc is - * write protected; we need to check the contents if it is blank */ - if ((cd_media_dvd_rw_ro || cd_media_dvd_plus_rw || cd_media_dvd_plus_rw_dl || cd_media_dvd_ram) && (header[2] & 3) > 1) { - unsigned char buffer[32 * 2048]; - unsigned char result, len; - int block, offset; - - if (cd_media_dvd_ram) { - /* a write protected dvd-ram may report "complete" status */ - - unsigned char dvdstruct[8]; - unsigned char format[12]; - - scsi_cmd_init(udev, &sc); - scsi_cmd_set(udev, &sc, 0, 0xAD); - scsi_cmd_set(udev, &sc, 7, 0xC0); - scsi_cmd_set(udev, &sc, 9, sizeof(dvdstruct)); - scsi_cmd_set(udev, &sc, 11, 0); - err = scsi_cmd_run(udev, &sc, fd, dvdstruct, sizeof(dvdstruct)); - if ((err != 0)) { - info_scsi_cmd_err(udev, "READ DVD STRUCTURE", err); - return -1; - } - if (dvdstruct[4] & 0x02) { - cd_media_state = media_status[2]; - info(udev, "write-protected DVD-RAM media inserted\n"); - goto determined; - } - - /* let's make sure we don't try to read unformatted media */ - scsi_cmd_init(udev, &sc); - scsi_cmd_set(udev, &sc, 0, 0x23); - scsi_cmd_set(udev, &sc, 8, sizeof(format)); - scsi_cmd_set(udev, &sc, 9, 0); - err = scsi_cmd_run(udev, &sc, fd, format, sizeof(format)); - if ((err != 0)) { - info_scsi_cmd_err(udev, "READ DVD FORMAT CAPACITIES", err); - return -1; - } - - len = format[3]; - if (len & 7 || len < 16) { - info(udev, "invalid format capacities length\n"); - return -1; - } - - switch(format[8] & 3) { - case 1: - info(udev, "unformatted DVD-RAM media inserted\n"); - /* This means that last format was interrupted - * or failed, blank dvd-ram discs are factory - * formatted. Take no action here as it takes - * quite a while to reformat a dvd-ram and it's - * not automatically started */ - goto determined; - - case 2: - info(udev, "formatted DVD-RAM media inserted\n"); - break; - - case 3: - cd_media = 0; //return no media - info(udev, "format capacities returned no media\n"); - return -1; - } - } - - /* Take a closer look at formatted media (unformatted DVD+RW - * has "blank" status", DVD-RAM was examined earlier) and check - * for ISO and UDF PVDs or a fs superblock presence and do it - * in one ioctl (we need just sectors 0 and 16) */ - scsi_cmd_init(udev, &sc); - scsi_cmd_set(udev, &sc, 0, 0x28); - scsi_cmd_set(udev, &sc, 5, 0); - scsi_cmd_set(udev, &sc, 8, 32); - scsi_cmd_set(udev, &sc, 9, 0); - err = scsi_cmd_run(udev, &sc, fd, buffer, sizeof(buffer)); - if ((err != 0)) { - cd_media = 0; - info_scsi_cmd_err(udev, "READ FIRST 32 BLOCKS", err); - return -1; - } - - /* if any non-zero data is found in sector 16 (iso and udf) or - * eventually 0 (fat32 boot sector, ext2 superblock, etc), disc - * is assumed non-blank */ - result = 0; - - for (block = 32768; block >= 0 && !result; block -= 32768) { - offset = block; - while (offset < (block + 2048) && !result) { - result = buffer [offset]; - offset++; - } - } - - if (!result) { - cd_media_state = media_status[0]; - info(udev, "no data in blocks 0 or 16, assuming blank\n"); - } else { - info(udev, "data in blocks 0 or 16, assuming complete\n"); - } - } - -determined: - /* "other" is e. g. DVD-RAM, can't append sessions there; DVDs in - * restricted overwrite mode can never append, only in sequential mode */ - if ((header[2] & 3) < 2 && !cd_media_dvd_rw_ro) - cd_media_session_next = header[10] << 8 | header[5]; - cd_media_session_count = header[9] << 8 | header[4]; - cd_media_track_count = header[11] << 8 | header[6]; - - return 0; -} - -static int cd_media_toc(struct udev *udev, int fd) -{ - struct scsi_cmd sc; - unsigned char header[12]; - unsigned char toc[65536]; - unsigned int len, i, num_tracks; - unsigned char *p; - int err; - - scsi_cmd_init(udev, &sc); - scsi_cmd_set(udev, &sc, 0, 0x43); - scsi_cmd_set(udev, &sc, 6, 1); - scsi_cmd_set(udev, &sc, 8, sizeof(header) & 0xff); - scsi_cmd_set(udev, &sc, 9, 0); - err = scsi_cmd_run(udev, &sc, fd, header, sizeof(header)); - if ((err != 0)) { - info_scsi_cmd_err(udev, "READ TOC", err); - return -1; - } - - len = (header[0] << 8 | header[1]) + 2; - info(udev, "READ TOC: len: %d, start track: %d, end track: %d\n", len, header[2], header[3]); - if (len > sizeof(toc)) - return -1; - if (len < 2) - return -1; - /* 2: first track, 3: last track */ - num_tracks = header[3] - header[2] + 1; - - /* empty media has no tracks */ - if (len < 8) - return 0; - - scsi_cmd_init(udev, &sc); - scsi_cmd_set(udev, &sc, 0, 0x43); - scsi_cmd_set(udev, &sc, 6, header[2]); /* First Track/Session Number */ - scsi_cmd_set(udev, &sc, 7, (len >> 8) & 0xff); - scsi_cmd_set(udev, &sc, 8, len & 0xff); - scsi_cmd_set(udev, &sc, 9, 0); - err = scsi_cmd_run(udev, &sc, fd, toc, len); - if ((err != 0)) { - info_scsi_cmd_err(udev, "READ TOC (tracks)", err); - return -1; - } - - /* Take care to not iterate beyond the last valid track as specified in - * the TOC, but also avoid going beyond the TOC length, just in case - * the last track number is invalidly large */ - for (p = toc+4, i = 4; i < len-8 && num_tracks > 0; i += 8, p += 8, --num_tracks) { - unsigned int block; - unsigned int is_data_track; - - is_data_track = (p[1] & 0x04) != 0; - - block = p[4] << 24 | p[5] << 16 | p[6] << 8 | p[7]; - info(udev, "track=%u info=0x%x(%s) start_block=%u\n", - p[2], p[1] & 0x0f, is_data_track ? "data":"audio", block); - - if (is_data_track) - cd_media_track_count_data++; - else - cd_media_track_count_audio++; - } - - scsi_cmd_init(udev, &sc); - scsi_cmd_set(udev, &sc, 0, 0x43); - scsi_cmd_set(udev, &sc, 2, 1); /* Session Info */ - scsi_cmd_set(udev, &sc, 8, sizeof(header)); - scsi_cmd_set(udev, &sc, 9, 0); - err = scsi_cmd_run(udev, &sc, fd, header, sizeof(header)); - if ((err != 0)) { - info_scsi_cmd_err(udev, "READ TOC (multi session)", err); - return -1; - } - len = header[4+4] << 24 | header[4+5] << 16 | header[4+6] << 8 | header[4+7]; - info(udev, "last track %u starts at block %u\n", header[4+2], len); - cd_media_session_last_offset = (unsigned long long int)len * 2048; - return 0; -} - -int main(int argc, char *argv[]) -{ - struct udev *udev; - static const struct option options[] = { - { "lock-media", no_argument, NULL, 'l' }, - { "unlock-media", no_argument, NULL, 'u' }, - { "eject-media", no_argument, NULL, 'e' }, - { "debug", no_argument, NULL, 'd' }, - { "help", no_argument, NULL, 'h' }, - {} - }; - bool eject = false; - bool lock = false; - bool unlock = false; - const char *node = NULL; - int fd = -1; - int cnt; - int rc = 0; - - udev = udev_new(); - if (udev == NULL) - goto exit; - - udev_log_init("cdrom_id"); - udev_set_log_fn(udev, log_fn); - - while (1) { - int option; - - option = getopt_long(argc, argv, "deluh", options, NULL); - if (option == -1) - break; - - switch (option) { - case 'l': - lock = true; - break; - case 'u': - unlock = true; - break; - case 'e': - eject = true; - break; - case 'd': - debug = true; - if (udev_get_log_priority(udev) < LOG_INFO) - udev_set_log_priority(udev, LOG_INFO); - break; - case 'h': - printf("Usage: cdrom_id [options] <device>\n" - " --lock-media lock the media (to enable eject request events)\n" - " --unlock-media unlock the media\n" - " --eject-media eject the media\n" - " --debug debug to stderr\n" - " --help print this help text\n\n"); - goto exit; - default: - rc = 1; - goto exit; - } - } - - node = argv[optind]; - if (!node) { - err(udev, "no device\n"); - fprintf(stderr, "no device\n"); - rc = 1; - goto exit; - } - - srand((unsigned int)getpid()); - for (cnt = 20; cnt > 0; cnt--) { - struct timespec duration; - - fd = open(node, O_RDONLY|O_NONBLOCK|(is_mounted(node) ? 0 : O_EXCL)); - if (fd >= 0 || errno != EBUSY) - break; - duration.tv_sec = 0; - duration.tv_nsec = (100 * 1000 * 1000) + (rand() % 100 * 1000 * 1000); - nanosleep(&duration, NULL); - } - if (fd < 0) { - info(udev, "unable to open '%s'\n", node); - fprintf(stderr, "unable to open '%s'\n", node); - rc = 1; - goto exit; - } - info(udev, "probing: '%s'\n", node); - - /* same data as original cdrom_id */ - if (cd_capability_compat(udev, fd) < 0) { - rc = 1; - goto exit; - } - - /* check for media - don't bail if there's no media as we still need to - * to read profiles */ - cd_media_compat(udev, fd); - - /* check if drive talks MMC */ - if (cd_inquiry(udev, fd) < 0) - goto work; - - /* read drive and possibly current profile */ - if (cd_profiles(udev, fd) != 0) - goto work; - - /* at this point we are guaranteed to have media in the drive - find out more about it */ - - /* get session/track info */ - cd_media_toc(udev, fd); - - /* get writable media state */ - cd_media_info(udev, fd); - -work: - /* lock the media, so we enable eject button events */ - if (lock && cd_media) { - info(udev, "PREVENT_ALLOW_MEDIUM_REMOVAL (lock)\n"); - media_lock(udev, fd, true); - } - - if (unlock && cd_media) { - info(udev, "PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)\n"); - media_lock(udev, fd, false); - } - - if (eject) { - info(udev, "PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)\n"); - media_lock(udev, fd, false); - info(udev, "START_STOP_UNIT (eject)\n"); - media_eject(udev, fd); - } - - printf("ID_CDROM=1\n"); - if (cd_cd_rom) - printf("ID_CDROM_CD=1\n"); - if (cd_cd_r) - printf("ID_CDROM_CD_R=1\n"); - if (cd_cd_rw) - printf("ID_CDROM_CD_RW=1\n"); - if (cd_dvd_rom) - printf("ID_CDROM_DVD=1\n"); - if (cd_dvd_r) - printf("ID_CDROM_DVD_R=1\n"); - if (cd_dvd_rw) - printf("ID_CDROM_DVD_RW=1\n"); - if (cd_dvd_ram) - printf("ID_CDROM_DVD_RAM=1\n"); - if (cd_dvd_plus_r) - printf("ID_CDROM_DVD_PLUS_R=1\n"); - if (cd_dvd_plus_rw) - printf("ID_CDROM_DVD_PLUS_RW=1\n"); - if (cd_dvd_plus_r_dl) - printf("ID_CDROM_DVD_PLUS_R_DL=1\n"); - if (cd_dvd_plus_rw_dl) - printf("ID_CDROM_DVD_PLUS_RW_DL=1\n"); - if (cd_bd) - printf("ID_CDROM_BD=1\n"); - if (cd_bd_r) - printf("ID_CDROM_BD_R=1\n"); - if (cd_bd_re) - printf("ID_CDROM_BD_RE=1\n"); - if (cd_hddvd) - printf("ID_CDROM_HDDVD=1\n"); - if (cd_hddvd_r) - printf("ID_CDROM_HDDVD_R=1\n"); - if (cd_hddvd_rw) - printf("ID_CDROM_HDDVD_RW=1\n"); - if (cd_mo) - printf("ID_CDROM_MO=1\n"); - if (cd_mrw) - printf("ID_CDROM_MRW=1\n"); - if (cd_mrw_w) - printf("ID_CDROM_MRW_W=1\n"); - - if (cd_media) - printf("ID_CDROM_MEDIA=1\n"); - if (cd_media_mo) - printf("ID_CDROM_MEDIA_MO=1\n"); - if (cd_media_mrw) - printf("ID_CDROM_MEDIA_MRW=1\n"); - if (cd_media_mrw_w) - printf("ID_CDROM_MEDIA_MRW_W=1\n"); - if (cd_media_cd_rom) - printf("ID_CDROM_MEDIA_CD=1\n"); - if (cd_media_cd_r) - printf("ID_CDROM_MEDIA_CD_R=1\n"); - if (cd_media_cd_rw) - printf("ID_CDROM_MEDIA_CD_RW=1\n"); - if (cd_media_dvd_rom) - printf("ID_CDROM_MEDIA_DVD=1\n"); - if (cd_media_dvd_r) - printf("ID_CDROM_MEDIA_DVD_R=1\n"); - if (cd_media_dvd_ram) - printf("ID_CDROM_MEDIA_DVD_RAM=1\n"); - if (cd_media_dvd_rw) - printf("ID_CDROM_MEDIA_DVD_RW=1\n"); - if (cd_media_dvd_plus_r) - printf("ID_CDROM_MEDIA_DVD_PLUS_R=1\n"); - if (cd_media_dvd_plus_rw) - printf("ID_CDROM_MEDIA_DVD_PLUS_RW=1\n"); - if (cd_media_dvd_plus_rw_dl) - printf("ID_CDROM_MEDIA_DVD_PLUS_RW_DL=1\n"); - if (cd_media_dvd_plus_r_dl) - printf("ID_CDROM_MEDIA_DVD_PLUS_R_DL=1\n"); - if (cd_media_bd) - printf("ID_CDROM_MEDIA_BD=1\n"); - if (cd_media_bd_r) - printf("ID_CDROM_MEDIA_BD_R=1\n"); - if (cd_media_bd_re) - printf("ID_CDROM_MEDIA_BD_RE=1\n"); - if (cd_media_hddvd) - printf("ID_CDROM_MEDIA_HDDVD=1\n"); - if (cd_media_hddvd_r) - printf("ID_CDROM_MEDIA_HDDVD_R=1\n"); - if (cd_media_hddvd_rw) - printf("ID_CDROM_MEDIA_HDDVD_RW=1\n"); - - if (cd_media_state != NULL) - printf("ID_CDROM_MEDIA_STATE=%s\n", cd_media_state); - if (cd_media_session_next > 0) - printf("ID_CDROM_MEDIA_SESSION_NEXT=%d\n", cd_media_session_next); - if (cd_media_session_count > 0) - printf("ID_CDROM_MEDIA_SESSION_COUNT=%d\n", cd_media_session_count); - if (cd_media_session_count > 1 && cd_media_session_last_offset > 0) - printf("ID_CDROM_MEDIA_SESSION_LAST_OFFSET=%llu\n", cd_media_session_last_offset); - if (cd_media_track_count > 0) - printf("ID_CDROM_MEDIA_TRACK_COUNT=%d\n", cd_media_track_count); - if (cd_media_track_count_audio > 0) - printf("ID_CDROM_MEDIA_TRACK_COUNT_AUDIO=%d\n", cd_media_track_count_audio); - if (cd_media_track_count_data > 0) - printf("ID_CDROM_MEDIA_TRACK_COUNT_DATA=%d\n", cd_media_track_count_data); -exit: - if (fd >= 0) - close(fd); - udev_unref(udev); - udev_log_close(); - return rc; -} diff --git a/src/udev/src/collect/collect.c b/src/udev/src/collect/collect.c deleted file mode 100644 index 076fe479e..000000000 --- a/src/udev/src/collect/collect.c +++ /dev/null @@ -1,473 +0,0 @@ -/* - * Collect variables across events. - * - * usage: collect [--add|--remove] <checkpoint> <id> <idlist> - * - * Adds ID <id> to the list governed by <checkpoint>. - * <id> must be part of the ID list <idlist>. - * If all IDs given by <idlist> are listed (ie collect has been - * invoked for each ID in <idlist>) collect returns 0, the - * number of missing IDs otherwise. - * A negative number is returned on error. - * - * Copyright(C) 2007, Hannes Reinecke <hare@suse.de> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <unistd.h> -#include <signal.h> -#include <fcntl.h> -#include <errno.h> -#include <string.h> -#include <getopt.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include "libudev.h" -#include "libudev-private.h" - -#define BUFSIZE 16 -#define UDEV_ALARM_TIMEOUT 180 - -enum collect_state { - STATE_NONE, - STATE_OLD, - STATE_CONFIRMED, -}; - -struct _mate { - struct udev_list_node node; - char *name; - enum collect_state state; -}; - -static struct udev_list_node bunch; -static int debug; - -/* This can increase dynamically */ -static size_t bufsize = BUFSIZE; - -static struct _mate *node_to_mate(struct udev_list_node *node) -{ - char *mate; - - mate = (char *)node; - mate -= offsetof(struct _mate, node); - return (struct _mate *)mate; -} - -static void sig_alrm(int signo) -{ - exit(4); -} - -static void usage(void) -{ - printf("usage: collect [--add|--remove] [--debug] <checkpoint> <id> <idlist>\n" - "\n" - " Adds ID <id> to the list governed by <checkpoint>.\n" - " <id> must be part of the list <idlist>.\n" - " If all IDs given by <idlist> are listed (ie collect has been\n" - " invoked for each ID in <idlist>) collect returns 0, the\n" - " number of missing IDs otherwise.\n" - " On error a negative number is returned.\n" - "\n"); -} - -/* - * prepare - * - * Prepares the database file - */ -static int prepare(char *dir, char *filename) -{ - struct stat statbuf; - char buf[512]; - int fd; - - if (stat(dir, &statbuf) < 0) - mkdir(dir, 0700); - - sprintf(buf, "%s/%s", dir, filename); - - fd = open(buf,O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); - if (fd < 0) - fprintf(stderr, "Cannot open %s: %s\n", buf, strerror(errno)); - - if (lockf(fd,F_TLOCK,0) < 0) { - if (debug) - fprintf(stderr, "Lock taken, wait for %d seconds\n", UDEV_ALARM_TIMEOUT); - if (errno == EAGAIN || errno == EACCES) { - alarm(UDEV_ALARM_TIMEOUT); - lockf(fd, F_LOCK, 0); - if (debug) - fprintf(stderr, "Acquired lock on %s\n", buf); - } else { - if (debug) - fprintf(stderr, "Could not get lock on %s: %s\n", buf, strerror(errno)); - } - } - - return fd; -} - -/* - * Read checkpoint file - * - * Tricky reading this. We allocate a buffer twice as large - * as we're going to read. Then we read into the upper half - * of that buffer and start parsing. - * Once we do _not_ find end-of-work terminator (whitespace - * character) we move the upper half to the lower half, - * adjust the read pointer and read the next bit. - * Quite clever methinks :-) - * I should become a programmer ... - * - * Yes, one could have used fgets() for this. But then we'd - * have to use freopen etc which I found quite tedious. - */ -static int checkout(int fd) -{ - int len; - char *buf, *ptr, *word = NULL; - struct _mate *him; - - restart: - len = bufsize >> 1; - buf = calloc(1,bufsize + 1); - if (!buf) { - fprintf(stderr, "Out of memory\n"); - return -1; - } - memset(buf, ' ', bufsize); - ptr = buf + len; - while ((read(fd, buf + len, len)) > 0) { - while (ptr && *ptr) { - word = ptr; - ptr = strpbrk(word," \n\t\r"); - if (!ptr && word < (buf + len)) { - bufsize = bufsize << 1; - if (debug) - fprintf(stderr, "ID overflow, restarting with size %zi\n", bufsize); - free(buf); - lseek(fd, 0, SEEK_SET); - goto restart; - } - if (ptr) { - *ptr = '\0'; - ptr++; - if (!strlen(word)) - continue; - - if (debug) - fprintf(stderr, "Found word %s\n", word); - him = malloc(sizeof (struct _mate)); - him->name = strdup(word); - him->state = STATE_OLD; - udev_list_node_append(&him->node, &bunch); - word = NULL; - } - } - memcpy(buf, buf + len, len); - memset(buf + len, ' ', len); - - if (!ptr) - ptr = word; - if (!ptr) - break; - ptr -= len; - } - - free(buf); - return 0; -} - -/* - * invite - * - * Adds a new ID 'us' to the internal list, - * marks it as confirmed. - */ -static void invite(char *us) -{ - struct udev_list_node *him_node; - struct _mate *who = NULL; - - if (debug) - fprintf(stderr, "Adding ID '%s'\n", us); - - udev_list_node_foreach(him_node, &bunch) { - struct _mate *him = node_to_mate(him_node); - - if (!strcmp(him->name, us)) { - him->state = STATE_CONFIRMED; - who = him; - } - } - if (debug && !who) - fprintf(stderr, "ID '%s' not in database\n", us); - -} - -/* - * reject - * - * Marks the ID 'us' as invalid, - * causing it to be removed when the - * list is written out. - */ -static void reject(char *us) -{ - struct udev_list_node *him_node; - struct _mate *who = NULL; - - if (debug) - fprintf(stderr, "Removing ID '%s'\n", us); - - udev_list_node_foreach(him_node, &bunch) { - struct _mate *him = node_to_mate(him_node); - - if (!strcmp(him->name, us)) { - him->state = STATE_NONE; - who = him; - } - } - if (debug && !who) - fprintf(stderr, "ID '%s' not in database\n", us); -} - -/* - * kickout - * - * Remove all IDs in the internal list which are not part - * of the list passed via the commandline. - */ -static void kickout(void) -{ - struct udev_list_node *him_node; - struct udev_list_node *tmp; - - udev_list_node_foreach_safe(him_node, tmp, &bunch) { - struct _mate *him = node_to_mate(him_node); - - if (him->state == STATE_OLD) { - udev_list_node_remove(&him->node); - free(him->name); - free(him); - } - } -} - -/* - * missing - * - * Counts all missing IDs in the internal list. - */ -static int missing(int fd) -{ - char *buf; - int ret = 0; - struct udev_list_node *him_node; - - buf = malloc(bufsize); - if (!buf) - return -1; - - udev_list_node_foreach(him_node, &bunch) { - struct _mate *him = node_to_mate(him_node); - - if (him->state == STATE_NONE) { - ret++; - } else { - while (strlen(him->name)+1 >= bufsize) { - char *tmpbuf; - - bufsize = bufsize << 1; - tmpbuf = realloc(buf, bufsize); - if (!tmpbuf) { - free(buf); - return -1; - } - buf = tmpbuf; - } - snprintf(buf, strlen(him->name)+2, "%s ", him->name); - write(fd, buf, strlen(buf)); - } - } - - free(buf); - return ret; -} - -/* - * everybody - * - * Prints out the status of the internal list. - */ -static void everybody(void) -{ - struct udev_list_node *him_node; - const char *state = ""; - - udev_list_node_foreach(him_node, &bunch) { - struct _mate *him = node_to_mate(him_node); - - switch (him->state) { - case STATE_NONE: - state = "none"; - break; - case STATE_OLD: - state = "old"; - break; - case STATE_CONFIRMED: - state = "confirmed"; - break; - } - fprintf(stderr, "ID: %s=%s\n", him->name, state); - } -} - -int main(int argc, char **argv) -{ - struct udev *udev; - static const struct option options[] = { - { "add", no_argument, NULL, 'a' }, - { "remove", no_argument, NULL, 'r' }, - { "debug", no_argument, NULL, 'd' }, - { "help", no_argument, NULL, 'h' }, - {} - }; - int argi; - char *checkpoint, *us; - int fd; - int i; - int ret = EXIT_SUCCESS; - int prune = 0; - char tmpdir[UTIL_PATH_SIZE]; - - udev = udev_new(); - if (udev == NULL) { - ret = EXIT_FAILURE; - goto exit; - } - - while (1) { - int option; - - option = getopt_long(argc, argv, "ardh", options, NULL); - if (option == -1) - break; - - switch (option) { - case 'a': - prune = 0; - break; - case 'r': - prune = 1; - break; - case 'd': - debug = 1; - break; - case 'h': - usage(); - goto exit; - default: - ret = 1; - goto exit; - } - } - - argi = optind; - if (argi + 2 > argc) { - printf("Missing parameter(s)\n"); - ret = 1; - goto exit; - } - checkpoint = argv[argi++]; - us = argv[argi++]; - - if (signal(SIGALRM, sig_alrm) == SIG_ERR) { - fprintf(stderr, "Cannot set SIGALRM: %s\n", strerror(errno)); - ret = 2; - goto exit; - } - - udev_list_node_init(&bunch); - - if (debug) - fprintf(stderr, "Using checkpoint '%s'\n", checkpoint); - - util_strscpyl(tmpdir, sizeof(tmpdir), udev_get_run_path(udev), "/collect", NULL); - fd = prepare(tmpdir, checkpoint); - if (fd < 0) { - ret = 3; - goto out; - } - - if (checkout(fd) < 0) { - ret = 2; - goto out; - } - - for (i = argi; i < argc; i++) { - struct udev_list_node *him_node; - struct _mate *who; - - who = NULL; - udev_list_node_foreach(him_node, &bunch) { - struct _mate *him = node_to_mate(him_node); - - if (!strcmp(him->name, argv[i])) - who = him; - } - if (!who) { - struct _mate *him; - - if (debug) - fprintf(stderr, "ID %s: not in database\n", argv[i]); - him = malloc(sizeof (struct _mate)); - him->name = malloc(strlen(argv[i]) + 1); - strcpy(him->name, argv[i]); - him->state = STATE_NONE; - udev_list_node_append(&him->node, &bunch); - } else { - if (debug) - fprintf(stderr, "ID %s: found in database\n", argv[i]); - who->state = STATE_CONFIRMED; - } - } - - if (prune) - reject(us); - else - invite(us); - - if (debug) { - everybody(); - fprintf(stderr, "Prune lists\n"); - } - kickout(); - - lseek(fd, 0, SEEK_SET); - ftruncate(fd, 0); - ret = missing(fd); - - lockf(fd, F_ULOCK, 0); - close(fd); -out: - if (debug) - everybody(); - if (ret >= 0) - printf("COLLECT_%s=%d\n", checkpoint, ret); -exit: - udev_unref(udev); - return ret; -} diff --git a/src/udev/src/docs/.gitignore b/src/udev/src/docs/.gitignore deleted file mode 100644 index dca700a99..000000000 --- a/src/udev/src/docs/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -libudev-overrides.txt -html/ -tmpl/ -xml/ -*.stamp -*.bak -version.xml -libudev-decl-list.txt -libudev-decl.txt -libudev-undeclared.txt -libudev-undocumented.txt -libudev-unused.txt -libudev.args -libudev.hierarchy -libudev.interfaces -libudev.prerequisites -libudev.signals diff --git a/src/udev/src/docs/Makefile.am b/src/udev/src/docs/Makefile.am deleted file mode 100644 index 07d06eb14..000000000 --- a/src/udev/src/docs/Makefile.am +++ /dev/null @@ -1,99 +0,0 @@ -## Process this file with automake to produce Makefile.in - -# We require automake 1.10 at least. -AUTOMAKE_OPTIONS = 1.10 - -# This is a blank Makefile.am for using gtk-doc. -# Copy this to your project's API docs directory and modify the variables to -# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples -# of using the various options. - -# The name of the module, e.g. 'glib'. -DOC_MODULE=libudev - -# Uncomment for versioned docs and specify the version of the module, e.g. '2'. -#DOC_MODULE_VERSION=2 - -# The top-level SGML file. You can change this if you want to. -DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.xml - -# The directory containing the source code. Relative to $(srcdir). -# gtk-doc will search all .c & .h files beneath here for inline comments -# documenting the functions and macros. -# e.g. DOC_SOURCE_DIR=../../../gtk -DOC_SOURCE_DIR=$(top_srcdir)/src - -# Extra options to pass to gtkdoc-scangobj. Not normally needed. -SCANGOBJ_OPTIONS= - -# Extra options to supply to gtkdoc-scan. -# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" -SCAN_OPTIONS= - -# Extra options to supply to gtkdoc-mkdb. -# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml -MKDB_OPTIONS=--sgml-mode --output-format=xml --name-space udev - -# Extra options to supply to gtkdoc-mktmpl -# e.g. MKTMPL_OPTIONS=--only-section-tmpl -MKTMPL_OPTIONS= - -# Extra options to supply to gtkdoc-mkhtml -MKHTML_OPTIONS=--path=$(abs_srcdir) --path=$(abs_builddir) - -# Extra options to supply to gtkdoc-fixref. Not normally needed. -# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html -FIXXREF_OPTIONS= - -# Used for dependencies. The docs will be rebuilt if any of these change. -# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h -# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c -HFILE_GLOB=$(top_srcdir)/src/libudev*.h -CFILE_GLOB=$(top_srcdir)/src/libudev*.c - -# Extra header to include when scanning, which are not under DOC_SOURCE_DIR -# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h -EXTRA_HFILES= - -# Header files to ignore when scanning. Use base file name, no paths -# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h -IGNORE_HFILES= libudev-private.h - -# Images to copy into HTML directory. -# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png -HTML_IMAGES= - -# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). -# e.g. content_files=running.sgml building.sgml changes-2.0.sgml -content_files = version.xml - -# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded -# These files must be listed here *and* in content_files -# e.g. expand_content_files=running.sgml -expand_content_files= - -# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. -# Only needed if you are using gtkdoc-scangobj to dynamically query widget -# signals and properties. -# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) -# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) -GTKDOC_CFLAGS= -GTKDOC_LIBS= - -# This includes the standard gtk-doc make rules, copied by gtkdocize. -include $(top_srcdir)/gtk-doc.make - -# Other files to distribute -# e.g. EXTRA_DIST += version.xml.in -EXTRA_DIST += version.xml.in - -# Files not to distribute -# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types -# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt -#DISTCLEANFILES += - -# Comment this out if you want your docs-status tested during 'make check' -if ENABLE_GTK_DOC -#TESTS_ENVIRONMENT = cd $(srcsrc) -#TESTS = $(GTKDOC_CHECK) -endif diff --git a/src/udev/src/docs/libudev-docs.xml b/src/udev/src/docs/libudev-docs.xml deleted file mode 100644 index b7feb4552..000000000 --- a/src/udev/src/docs/libudev-docs.xml +++ /dev/null @@ -1,32 +0,0 @@ -<?xml version="1.0"?> -<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" - "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" -[ - <!ENTITY version SYSTEM "version.xml"> -]> -<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude"> - <bookinfo> - <title>libudev Reference Manual</title> - <releaseinfo>for libudev version &version;</releaseinfo> - <copyright> - <year>2009-2011</year> - <holder>Kay Sievers <kay.sievers@vrfy.org></holder> - </copyright> - </bookinfo> - - <chapter> - <title>libudev</title> - <xi:include href="xml/libudev.xml"/> - <xi:include href="xml/libudev-list.xml"/> - <xi:include href="xml/libudev-device.xml"/> - <xi:include href="xml/libudev-monitor.xml"/> - <xi:include href="xml/libudev-enumerate.xml"/> - <xi:include href="xml/libudev-queue.xml"/> - <xi:include href="xml/libudev-util.xml"/> - </chapter> - - <index id="api-index-full"> - <title>API Index</title> - <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include> - </index> -</book> diff --git a/src/udev/src/docs/libudev-sections.txt b/src/udev/src/docs/libudev-sections.txt deleted file mode 100644 index 15c3e934b..000000000 --- a/src/udev/src/docs/libudev-sections.txt +++ /dev/null @@ -1,127 +0,0 @@ -<SECTION> -<FILE>libudev</FILE> -<TITLE>udev</TITLE> -udev -udev_ref -udev_unref -udev_new -udev_set_log_fn -udev_get_log_priority -udev_set_log_priority -udev_get_sys_path -udev_get_dev_path -udev_get_run_path -udev_get_userdata -udev_set_userdata -</SECTION> - -<SECTION> -<FILE>libudev-list</FILE> -<TITLE>udev_list</TITLE> -udev_list_entry -udev_list_entry_get_next -udev_list_entry_get_by_name -udev_list_entry_get_name -udev_list_entry_get_value -udev_list_entry_foreach -</SECTION> - -<SECTION> -<FILE>libudev-device</FILE> -<TITLE>udev_device</TITLE> -udev_device -udev_device_ref -udev_device_unref -udev_device_get_udev -udev_device_new_from_syspath -udev_device_new_from_devnum -udev_device_new_from_subsystem_sysname -udev_device_new_from_environment -udev_device_get_parent -udev_device_get_parent_with_subsystem_devtype -udev_device_get_devpath -udev_device_get_subsystem -udev_device_get_devtype -udev_device_get_syspath -udev_device_get_sysname -udev_device_get_sysnum -udev_device_get_devnode -udev_device_get_is_initialized -udev_device_get_devlinks_list_entry -udev_device_get_properties_list_entry -udev_device_get_tags_list_entry -udev_device_get_property_value -udev_device_get_driver -udev_device_get_devnum -udev_device_get_action -udev_device_get_sysattr_value -udev_device_get_sysattr_list_entry -udev_device_get_seqnum -udev_device_get_usec_since_initialized -udev_device_has_tag -</SECTION> - -<SECTION> -<FILE>libudev-monitor</FILE> -<TITLE>udev_monitor</TITLE> -udev_monitor -udev_monitor_ref -udev_monitor_unref -udev_monitor_get_udev -udev_monitor_new_from_netlink -udev_monitor_new_from_socket -udev_monitor_enable_receiving -udev_monitor_set_receive_buffer_size -udev_monitor_get_fd -udev_monitor_receive_device -udev_monitor_filter_add_match_subsystem_devtype -udev_monitor_filter_add_match_tag -udev_monitor_filter_update -udev_monitor_filter_remove -</SECTION> - -<SECTION> -<FILE>libudev-enumerate</FILE> -<TITLE>udev_enumerate</TITLE> -udev_enumerate -udev_enumerate_ref -udev_enumerate_unref -udev_enumerate_get_udev -udev_enumerate_new -udev_enumerate_add_match_subsystem -udev_enumerate_add_nomatch_subsystem -udev_enumerate_add_match_sysattr -udev_enumerate_add_nomatch_sysattr -udev_enumerate_add_match_property -udev_enumerate_add_match_tag -udev_enumerate_add_match_parent -udev_enumerate_add_match_is_initialized -udev_enumerate_add_match_sysname -udev_enumerate_add_syspath -udev_enumerate_scan_devices -udev_enumerate_scan_subsystems -udev_enumerate_get_list_entry -</SECTION> - -<SECTION> -<FILE>libudev-queue</FILE> -<TITLE>udev_queue</TITLE> -udev_queue -udev_queue_ref -udev_queue_unref -udev_queue_get_udev -udev_queue_new -udev_queue_get_udev_is_active -udev_queue_get_queue_is_empty -udev_queue_get_seqnum_is_finished -udev_queue_get_seqnum_sequence_is_finished -udev_queue_get_queued_list_entry -udev_queue_get_kernel_seqnum -udev_queue_get_udev_seqnum -</SECTION> - -<SECTION> -<FILE>libudev-util</FILE> -<TITLE>udev_util</TITLE> -udev_util_encode_string -</SECTION> diff --git a/src/udev/src/docs/libudev.types b/src/udev/src/docs/libudev.types deleted file mode 100644 index e69de29bb..000000000 --- a/src/udev/src/docs/libudev.types +++ /dev/null diff --git a/src/udev/src/docs/version.xml.in b/src/udev/src/docs/version.xml.in deleted file mode 100644 index d78bda934..000000000 --- a/src/udev/src/docs/version.xml.in +++ /dev/null @@ -1 +0,0 @@ -@VERSION@ diff --git a/src/udev/src/floppy/60-floppy.rules b/src/udev/src/floppy/60-floppy.rules deleted file mode 100644 index 53e4a9e59..000000000 --- a/src/udev/src/floppy/60-floppy.rules +++ /dev/null @@ -1,4 +0,0 @@ -# do not edit this file, it will be overwritten on update - -SUBSYSTEM=="block", KERNEL=="fd[0-9]", ACTION=="add", ATTRS{cmos}=="?*", ENV{CMOS_TYPE}="$attr{cmos}", \ - RUN+="create_floppy_devices -c -t $env{CMOS_TYPE} -m %M -M 0660 -G floppy $root/%k" diff --git a/src/udev/src/floppy/create_floppy_devices.c b/src/udev/src/floppy/create_floppy_devices.c deleted file mode 100644 index f71ef0d80..000000000 --- a/src/udev/src/floppy/create_floppy_devices.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Create all possible floppy device based on the CMOS type. - * Based upon code from drivers/block/floppy.c - * - * Copyright(C) 2005, SUSE Linux Products GmbH - * - * Author: Hannes Reinecke <hare@suse.de> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> -#include <pwd.h> -#include <grp.h> - -#include "libudev.h" -#include "libudev-private.h" - -static char *table[] = { - "", "d360", "h1200", "u360", "u720", "h360", "h720", - "u1440", "u2880", "CompaQ", "h1440", "u1680", "h410", - "u820", "h1476", "u1722", "h420", "u830", "h1494", "u1743", - "h880", "u1040", "u1120", "h1600", "u1760", "u1920", - "u3200", "u3520", "u3840", "u1840", "u800", "u1600", - NULL -}; - -static int t360[] = { 1, 0 }; -static int t1200[] = { 2, 5, 6, 10, 12, 14, 16, 18, 20, 23, 0 }; -static int t3in[] = { 8, 9, 26, 27, 28, 7, 11, 15, 19, 24, 25, 29, 31, 3, 4, 13, 17, 21, 22, 30, 0 }; -static int *table_sup[] = { NULL, t360, t1200, t3in+5+8, t3in+5, t3in, t3in }; - -static void log_fn(struct udev *udev, int priority, - const char *file, int line, const char *fn, - const char *format, va_list args) -{ - vsyslog(priority, format, args); -} - -int main(int argc, char **argv) -{ - struct udev *udev; - char *dev; - char *devname; - char node[64]; - int type = 0, i, fdnum, c; - int major = 2, minor; - uid_t uid = 0; - gid_t gid = 0; - mode_t mode = 0660; - int create_nodes = 0; - int print_nodes = 0; - int is_err = 0; - - udev = udev_new(); - if (udev == NULL) - goto exit; - - udev_log_init("create_floppy_devices"); - udev_set_log_fn(udev, log_fn); - udev_selinux_init(udev); - - while ((c = getopt(argc, argv, "cudm:U:G:M:t:")) != -1) { - switch (c) { - case 'c': - create_nodes = 1; - break; - case 'd': - print_nodes = 1; - break; - case 'U': - uid = util_lookup_user(udev, optarg); - break; - case 'G': - gid = util_lookup_group(udev, optarg); - break; - case 'M': - mode = strtol(optarg, NULL, 0); - mode = mode & 0666; - break; - case 'm': - major = strtol(optarg, NULL, 0); - break; - case 't': - type = strtol(optarg, NULL, 0); - break; - default: - is_err++; - break; - } - } - - if (is_err || optind >= argc) { - printf("Usage: %s [OPTION] device\n" - " -c create\n" - " -d debug\n" - " -m Major number\n" - " -t floppy type number\n" - " -U device node user ownership\n" - " -G device node group owner\n" - " -M device node mode\n" - "\n", argv[0]); - return 1; - } - - dev = argv[optind]; - devname = strrchr(dev, '/'); - if (devname != NULL) - devname = &devname[1]; - else - devname = dev; - if (strncmp(devname, "fd", 2) != 0) { - fprintf(stderr,"Device '%s' is not a floppy device\n", dev); - return 1; - } - - fdnum = strtol(&devname[2], NULL, 10); - if (fdnum < 0 || fdnum > 7) { - fprintf(stderr,"Floppy device number %d out of range (0-7)\n", fdnum); - return 1; - } - if (fdnum > 3) - fdnum += 124; - - if (major < 1) { - fprintf(stderr,"Invalid major number %d\n", major); - return 1; - } - - if (type < 0 || type >= (int) ARRAY_SIZE(table_sup)) { - fprintf(stderr,"Invalid CMOS type %d\n", type); - return 1; - } - - if (type == 0) - return 0; - - i = 0; - while (table_sup[type][i]) { - sprintf(node, "%s%s", dev, table[table_sup[type][i]]); - minor = (table_sup[type][i] << 2) + fdnum; - if (print_nodes) - printf("%s b %.4o %d %d\n", node, mode, major, minor); - if (create_nodes) { - unlink(node); - udev_selinux_setfscreatecon(udev, node, S_IFBLK | mode); - mknod(node, S_IFBLK | mode, makedev(major,minor)); - udev_selinux_resetfscreatecon(udev); - chown(node, uid, gid); - chmod(node, S_IFBLK | mode); - } - i++; - } - - udev_selinux_exit(udev); - udev_unref(udev); - udev_log_close(); -exit: - return 0; -} diff --git a/src/udev/src/gudev/.gitignore b/src/udev/src/gudev/.gitignore deleted file mode 100644 index d20fa523e..000000000 --- a/src/udev/src/gudev/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -gtk-doc.make -docs/version.xml -gudev-1.0.pc -gudevenumtypes.c -gudevenumtypes.h -gudevmarshal.c -gudevmarshal.h -GUdev-1.0.gir -GUdev-1.0.typelib diff --git a/src/udev/src/gudev/COPYING b/src/udev/src/gudev/COPYING deleted file mode 100644 index da97db2bd..000000000 --- a/src/udev/src/gudev/COPYING +++ /dev/null @@ -1,502 +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/udev/src/gudev/docs/.gitignore b/src/udev/src/gudev/docs/.gitignore deleted file mode 100644 index 8eada6d40..000000000 --- a/src/udev/src/gudev/docs/.gitignore +++ /dev/null @@ -1,16 +0,0 @@ -gudev-overrides.txt -gudev-decl-list.txt -gudev-decl.txt -gudev-undeclared.txt -gudev-undocumented.txt -gudev-unused.txt -gudev.args -gudev.hierarchy -gudev.interfaces -gudev.prerequisites -gudev.signals -html.stamp -html/* -xml/* -tmpl/* -*.stamp diff --git a/src/udev/src/gudev/docs/Makefile.am b/src/udev/src/gudev/docs/Makefile.am deleted file mode 100644 index cfe696c50..000000000 --- a/src/udev/src/gudev/docs/Makefile.am +++ /dev/null @@ -1,106 +0,0 @@ -## Process this file with automake to produce Makefile.in - -# We require automake 1.10 at least. -AUTOMAKE_OPTIONS = 1.10 - -# This is a blank Makefile.am for using gtk-doc. -# Copy this to your project's API docs directory and modify the variables to -# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples -# of using the various options. - -# The name of the module, e.g. 'glib'. -DOC_MODULE=gudev - -# Uncomment for versioned docs and specify the version of the module, e.g. '2'. -#DOC_MODULE_VERSION=2 - -# The top-level SGML file. You can change this if you want to. -DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.xml - -# The directory containing the source code. Relative to $(srcdir). -# gtk-doc will search all .c & .h files beneath here for inline comments -# documenting the functions and macros. -# e.g. DOC_SOURCE_DIR=../../../gtk -DOC_SOURCE_DIR=$(top_srcdir)/src - -# Extra options to pass to gtkdoc-scangobj. Not normally needed. -SCANGOBJ_OPTIONS= - -# Extra options to supply to gtkdoc-scan. -# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" -SCAN_OPTIONS= - -# Extra options to supply to gtkdoc-mkdb. -# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml -MKDB_OPTIONS=--sgml-mode --output-format=xml --name-space=g_udev - -# Extra options to supply to gtkdoc-mktmpl -# e.g. MKTMPL_OPTIONS=--only-section-tmpl -MKTMPL_OPTIONS= - -# Extra options to supply to gtkdoc-mkhtml -MKHTML_OPTIONS=--path=$(abs_srcdir) --path=$(abs_builddir) - -# Extra options to supply to gtkdoc-fixref. Not normally needed. -# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html -FIXXREF_OPTIONS= - -# Used for dependencies. The docs will be rebuilt if any of these change. -# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h -# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c -HFILE_GLOB=$(top_srcdir)/src/gudev/*.h -CFILE_GLOB=$(top_srcdir)/src/gudev/*.c - -# Extra header to include when scanning, which are not under DOC_SOURCE_DIR -# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h -EXTRA_HFILES= - -# Header files to ignore when scanning. Use base file name, no paths -# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h -IGNORE_HFILES= - -# Images to copy into HTML directory. -# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png -HTML_IMAGES= - -# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). -# e.g. content_files=running.sgml building.sgml changes-2.0.sgml -content_files = version.xml - -# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded -# These files must be listed here *and* in content_files -# e.g. expand_content_files=running.sgml -expand_content_files= - -# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. -# Only needed if you are using gtkdoc-scangobj to dynamically query widget -# signals and properties. -# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) -# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) -GTKDOC_CFLAGS = \ - $(DBUS_GLIB_CFLAGS) \ - $(GLIB_CFLAGS) \ - -I$(top_srcdir)/src/gudev \ - -I$(top_builddir)/src/gudev - -GTKDOC_LIBS = \ - $(GLIB_LIBS) \ - $(top_builddir)/libgudev-1.0.la - -# This includes the standard gtk-doc make rules, copied by gtkdocize. -include $(top_srcdir)/gtk-doc.make - -# Other files to distribute -# e.g. EXTRA_DIST += version.xml.in -EXTRA_DIST += version.xml.in - -# Files not to distribute -# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types -# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt -#DISTCLEANFILES += - -# Comment this out if you want your docs-status tested during 'make check' -if ENABLE_GTK_DOC -#TESTS_ENVIRONMENT = cd $(srcsrc) -#TESTS = $(GTKDOC_CHECK) -endif diff --git a/src/udev/src/gudev/docs/gudev-docs.xml b/src/udev/src/gudev/docs/gudev-docs.xml deleted file mode 100644 index f876c3bc0..000000000 --- a/src/udev/src/gudev/docs/gudev-docs.xml +++ /dev/null @@ -1,93 +0,0 @@ -<?xml version="1.0"?> -<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" - "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ -<!ENTITY version SYSTEM "version.xml"> -]> -<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude"> - <bookinfo> - <title>GUDev Reference Manual</title> - <releaseinfo>For GUdev version &version;</releaseinfo> - <authorgroup> - <author> - <firstname>David</firstname> - <surname>Zeuthen</surname> - <affiliation> - <address> - <email>davidz@redhat.com</email> - </address> - </affiliation> - </author> - <author> - <firstname>Bastien</firstname> - <surname>Nocera</surname> - <affiliation> - <address> - <email>hadess@hadess.net</email> - </address> - </affiliation> - </author> - </authorgroup> - - <copyright> - <year>2011</year> - <holder>The GUDev Authors</holder> - </copyright> - - <legalnotice> - <para> - Permission is granted to copy, distribute and/or modify this - document under the terms of the <citetitle>GNU Free - Documentation License</citetitle>, Version 1.1 or any later - version published by the Free Software Foundation with no - Invariant Sections, no Front-Cover Texts, and no Back-Cover - Texts. You may obtain a copy of the <citetitle>GNU Free - Documentation License</citetitle> from the Free Software - Foundation by visiting <ulink type="http" - url="http://www.fsf.org">their Web site</ulink> or by writing - to: - - <address> - The Free Software Foundation, Inc., - <street>59 Temple Place</street> - Suite 330, - <city>Boston</city>, <state>MA</state> <postcode>02111-1307</postcode>, - <country>USA</country> - </address> - </para> - - <para> - Many of the names used by companies to distinguish their - products and services are claimed as trademarks. Where those - names appear in any freedesktop.org documentation, and those - trademarks are made aware to the members of the - freedesktop.org Project, the names have been printed in caps - or initial caps. - </para> - </legalnotice> - </bookinfo> - - <reference id="ref-API"> - <title>API Reference</title> - <partintro> - <para> - This part presents the class and function reference for the - <literal>libgudev</literal> library. - </para> - </partintro> - <xi:include href="xml/gudevclient.xml"/> - <xi:include href="xml/gudevdevice.xml"/> - <xi:include href="xml/gudevenumerator.xml"/> - </reference> - - <chapter id="gudev-hierarchy"> - <title>Object Hierarchy</title> - <xi:include href="xml/tree_index.sgml"/> - </chapter> - <index> - <title>Index</title> - </index> - <index role="165"> - <title>Index of new symbols in 165</title> - <xi:include href="xml/api-index-165.xml"><xi:fallback /></xi:include> - </index> - -</book> diff --git a/src/udev/src/gudev/docs/gudev-sections.txt b/src/udev/src/gudev/docs/gudev-sections.txt deleted file mode 100644 index 213e1a746..000000000 --- a/src/udev/src/gudev/docs/gudev-sections.txt +++ /dev/null @@ -1,113 +0,0 @@ -<SECTION> -<FILE>gudevclient</FILE> -<TITLE>GUdevClient</TITLE> -GUdevClient -GUdevClientClass -GUdevDeviceType -GUdevDeviceNumber -g_udev_client_new -g_udev_client_query_by_subsystem -g_udev_client_query_by_device_number -g_udev_client_query_by_device_file -g_udev_client_query_by_sysfs_path -g_udev_client_query_by_subsystem_and_name -<SUBSECTION Standard> -G_UDEV_CLIENT -G_UDEV_IS_CLIENT -G_UDEV_TYPE_CLIENT -g_udev_client_get_type -G_UDEV_CLIENT_CLASS -G_UDEV_IS_CLIENT_CLASS -G_UDEV_CLIENT_GET_CLASS -<SUBSECTION Private> -GUdevClientPrivate -</SECTION> - -<SECTION> -<FILE>gudevdevice</FILE> -<TITLE>GUdevDevice</TITLE> -GUdevDevice -GUdevDeviceClass -g_udev_device_get_subsystem -g_udev_device_get_devtype -g_udev_device_get_name -g_udev_device_get_number -g_udev_device_get_sysfs_path -g_udev_device_get_driver -g_udev_device_get_action -g_udev_device_get_seqnum -g_udev_device_get_device_type -g_udev_device_get_device_number -g_udev_device_get_device_file -g_udev_device_get_device_file_symlinks -g_udev_device_get_parent -g_udev_device_get_parent_with_subsystem -g_udev_device_get_tags -g_udev_device_get_is_initialized -g_udev_device_get_usec_since_initialized -g_udev_device_get_property_keys -g_udev_device_has_property -g_udev_device_get_property -g_udev_device_get_property_as_int -g_udev_device_get_property_as_uint64 -g_udev_device_get_property_as_double -g_udev_device_get_property_as_boolean -g_udev_device_get_property_as_strv -g_udev_device_get_sysfs_attr -g_udev_device_get_sysfs_attr_as_int -g_udev_device_get_sysfs_attr_as_uint64 -g_udev_device_get_sysfs_attr_as_double -g_udev_device_get_sysfs_attr_as_boolean -g_udev_device_get_sysfs_attr_as_strv -<SUBSECTION Standard> -G_UDEV_DEVICE -G_UDEV_IS_DEVICE -G_UDEV_TYPE_DEVICE -g_udev_device_get_type -G_UDEV_DEVICE_CLASS -G_UDEV_IS_DEVICE_CLASS -G_UDEV_DEVICE_GET_CLASS -<SUBSECTION Private> -GUdevDevicePrivate -</SECTION> - -<SECTION> -<FILE>gudevenumerator</FILE> -<TITLE>GUdevEnumerator</TITLE> -GUdevEnumerator -GUdevEnumeratorClass -g_udev_enumerator_new -g_udev_enumerator_add_match_subsystem -g_udev_enumerator_add_nomatch_subsystem -g_udev_enumerator_add_match_sysfs_attr -g_udev_enumerator_add_nomatch_sysfs_attr -g_udev_enumerator_add_match_property -g_udev_enumerator_add_match_name -g_udev_enumerator_add_match_tag -g_udev_enumerator_add_match_is_initialized -g_udev_enumerator_add_sysfs_path -g_udev_enumerator_execute -<SUBSECTION Standard> -G_UDEV_ENUMERATOR -G_UDEV_IS_ENUMERATOR -G_UDEV_TYPE_ENUMERATOR -g_udev_enumerator_get_type -G_UDEV_ENUMERATOR_CLASS -G_UDEV_IS_ENUMERATOR_CLASS -G_UDEV_ENUMERATOR_GET_CLASS -<SUBSECTION Private> -GUdevEnumeratorPrivate -</SECTION> - -<SECTION> -<FILE>gudevmarshal</FILE> -<SUBSECTION Private> -g_udev_marshal_VOID__STRING_OBJECT -</SECTION> - -<SECTION> -<FILE>gudevenumtypes</FILE> -<SUBSECTION Private> -G_TYPE_UDEV_DEVICE_TYPE -g_udev_device_type_get_type -</SECTION> diff --git a/src/udev/src/gudev/docs/gudev.types b/src/udev/src/gudev/docs/gudev.types deleted file mode 100644 index a89857a04..000000000 --- a/src/udev/src/gudev/docs/gudev.types +++ /dev/null @@ -1,4 +0,0 @@ -g_udev_device_type_get_type -g_udev_device_get_type -g_udev_client_get_type -g_udev_enumerator_get_type diff --git a/src/udev/src/gudev/docs/version.xml.in b/src/udev/src/gudev/docs/version.xml.in deleted file mode 100644 index d78bda934..000000000 --- a/src/udev/src/gudev/docs/version.xml.in +++ /dev/null @@ -1 +0,0 @@ -@VERSION@ diff --git a/src/udev/src/gudev/gjs-example.js b/src/udev/src/gudev/gjs-example.js deleted file mode 100755 index 5586fd6a6..000000000 --- a/src/udev/src/gudev/gjs-example.js +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env gjs-console - -// This currently depends on the following patches to gjs -// -// http://bugzilla.gnome.org/show_bug.cgi?id=584558 -// http://bugzilla.gnome.org/show_bug.cgi?id=584560 -// http://bugzilla.gnome.org/show_bug.cgi?id=584568 - -const GUdev = imports.gi.GUdev; -const Mainloop = imports.mainloop; - -function print_device (device) { - print (" subsystem: " + device.get_subsystem ()); - print (" devtype: " + device.get_devtype ()); - print (" name: " + device.get_name ()); - print (" number: " + device.get_number ()); - print (" sysfs_path: " + device.get_sysfs_path ()); - print (" driver: " + device.get_driver ()); - print (" action: " + device.get_action ()); - print (" seqnum: " + device.get_seqnum ()); - print (" device type: " + device.get_device_type ()); - print (" device number: " + device.get_device_number ()); - print (" device file: " + device.get_device_file ()); - print (" device file symlinks: " + device.get_device_file_symlinks ()); - print (" foo: " + device.get_sysfs_attr_as_strv ("stat")); - var keys = device.get_property_keys (); - for (var n = 0; n < keys.length; n++) { - print (" " + keys[n] + "=" + device.get_property (keys[n])); - } -} - -function on_uevent (client, action, device) { - print ("action " + action + " on device " + device.get_sysfs_path()); - print_device (device); - print (""); -} - -var client = new GUdev.Client ({subsystems: ["block", "usb/usb_interface"]}); -client.connect ("uevent", on_uevent); - -var block_devices = client.query_by_subsystem ("block"); -for (var n = 0; n < block_devices.length; n++) { - print ("block device: " + block_devices[n].get_device_file ()); -} - -var d; - -d = client.query_by_device_number (GUdev.DeviceType.BLOCK, 0x0810); -if (d == null) { - print ("query_by_device_number 0x810 -> null"); -} else { - print ("query_by_device_number 0x810 -> " + d.get_device_file ()); - var dd = d.get_parent_with_subsystem ("usb", null); - print_device (dd); - print ("--------------------------------------------------------------------------"); - while (d != null) { - print_device (d); - print (""); - d = d.get_parent (); - } -} - -d = client.query_by_sysfs_path ("/sys/block/sda/sda1"); -print ("query_by_sysfs_path (\"/sys/block/sda1\") -> " + d.get_device_file ()); - -d = client.query_by_subsystem_and_name ("block", "sda2"); -print ("query_by_subsystem_and_name (\"block\", \"sda2\") -> " + d.get_device_file ()); - -d = client.query_by_device_file ("/dev/sda"); -print ("query_by_device_file (\"/dev/sda\") -> " + d.get_device_file ()); - -d = client.query_by_device_file ("/dev/block/8:0"); -print ("query_by_device_file (\"/dev/block/8:0\") -> " + d.get_device_file ()); - -Mainloop.run('udev-example'); diff --git a/src/udev/src/gudev/gudev-1.0.pc.in b/src/udev/src/gudev/gudev-1.0.pc.in deleted file mode 100644 index 058262d76..000000000 --- a/src/udev/src/gudev/gudev-1.0.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: gudev-1.0 -Description: GObject bindings for libudev -Version: @VERSION@ -Requires: glib-2.0, gobject-2.0 -Libs: -L${libdir} -lgudev-1.0 -Cflags: -I${includedir}/gudev-1.0 diff --git a/src/udev/src/gudev/gudev.h b/src/udev/src/gudev/gudev.h deleted file mode 100644 index a31346081..000000000 --- a/src/udev/src/gudev/gudev.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2008 David Zeuthen <davidz@redhat.com> - * - * 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 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __G_UDEV_H__ -#define __G_UDEV_H__ - -#define _GUDEV_INSIDE_GUDEV_H 1 -#include <gudev/gudevenums.h> -#include <gudev/gudevenumtypes.h> -#include <gudev/gudevtypes.h> -#include <gudev/gudevclient.h> -#include <gudev/gudevdevice.h> -#include <gudev/gudevenumerator.h> -#undef _GUDEV_INSIDE_GUDEV_H - -#endif /* __G_UDEV_H__ */ diff --git a/src/udev/src/gudev/gudevclient.c b/src/udev/src/gudev/gudevclient.c deleted file mode 100644 index 2b94102ac..000000000 --- a/src/udev/src/gudev/gudevclient.c +++ /dev/null @@ -1,527 +0,0 @@ -/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2008-2010 David Zeuthen <davidz@redhat.com> - * - * 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 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdlib.h> -#include <string.h> - -#include "gudevclient.h" -#include "gudevdevice.h" -#include "gudevmarshal.h" -#include "gudevprivate.h" - -/** - * SECTION:gudevclient - * @short_description: Query devices and listen to uevents - * - * #GUdevClient is used to query information about devices on a Linux - * system from the Linux kernel and the udev device - * manager. - * - * Device information is retrieved from the kernel (through the - * <literal>sysfs</literal> filesystem) and the udev daemon (through a - * <literal>tmpfs</literal> filesystem) and presented through - * #GUdevDevice objects. This means that no blocking IO ever happens - * (in both cases, we are essentially just reading data from kernel - * memory) and as such there are no asynchronous versions of the - * provided methods. - * - * To get #GUdevDevice objects, use - * g_udev_client_query_by_subsystem(), - * g_udev_client_query_by_device_number(), - * g_udev_client_query_by_device_file(), - * g_udev_client_query_by_sysfs_path(), - * g_udev_client_query_by_subsystem_and_name() - * or the #GUdevEnumerator type. - * - * To listen to uevents, connect to the #GUdevClient::uevent signal. - */ - -struct _GUdevClientPrivate -{ - GSource *watch_source; - struct udev *udev; - struct udev_monitor *monitor; - - gchar **subsystems; -}; - -enum -{ - PROP_0, - PROP_SUBSYSTEMS, -}; - -enum -{ - UEVENT_SIGNAL, - LAST_SIGNAL, -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -G_DEFINE_TYPE (GUdevClient, g_udev_client, G_TYPE_OBJECT) - -/* ---------------------------------------------------------------------------------------------------- */ - -static gboolean -monitor_event (GIOChannel *source, - GIOCondition condition, - gpointer data) -{ - GUdevClient *client = (GUdevClient *) data; - GUdevDevice *device; - struct udev_device *udevice; - - if (client->priv->monitor == NULL) - goto out; - udevice = udev_monitor_receive_device (client->priv->monitor); - if (udevice == NULL) - goto out; - - device = _g_udev_device_new (udevice); - udev_device_unref (udevice); - g_signal_emit (client, - signals[UEVENT_SIGNAL], - 0, - g_udev_device_get_action (device), - device); - g_object_unref (device); - - out: - return TRUE; -} - -static void -g_udev_client_finalize (GObject *object) -{ - GUdevClient *client = G_UDEV_CLIENT (object); - - if (client->priv->watch_source != NULL) - { - g_source_destroy (client->priv->watch_source); - client->priv->watch_source = NULL; - } - - if (client->priv->monitor != NULL) - { - udev_monitor_unref (client->priv->monitor); - client->priv->monitor = NULL; - } - - if (client->priv->udev != NULL) - { - udev_unref (client->priv->udev); - client->priv->udev = NULL; - } - - g_strfreev (client->priv->subsystems); - - if (G_OBJECT_CLASS (g_udev_client_parent_class)->finalize != NULL) - G_OBJECT_CLASS (g_udev_client_parent_class)->finalize (object); -} - -static void -g_udev_client_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GUdevClient *client = G_UDEV_CLIENT (object); - - switch (prop_id) - { - case PROP_SUBSYSTEMS: - if (client->priv->subsystems != NULL) - g_strfreev (client->priv->subsystems); - client->priv->subsystems = g_strdupv (g_value_get_boxed (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -g_udev_client_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GUdevClient *client = G_UDEV_CLIENT (object); - - switch (prop_id) - { - case PROP_SUBSYSTEMS: - g_value_set_boxed (value, client->priv->subsystems); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -g_udev_client_constructed (GObject *object) -{ - GUdevClient *client = G_UDEV_CLIENT (object); - GIOChannel *channel; - guint n; - - client->priv->udev = udev_new (); - - /* connect to event source */ - client->priv->monitor = udev_monitor_new_from_netlink (client->priv->udev, "udev"); - - //g_debug ("ss = %p", client->priv->subsystems); - - if (client->priv->subsystems != NULL) - { - /* install subsystem filters to only wake up for certain events */ - for (n = 0; client->priv->subsystems[n] != NULL; n++) - { - gchar *subsystem; - gchar *devtype; - gchar *s; - - subsystem = g_strdup (client->priv->subsystems[n]); - devtype = NULL; - - //g_debug ("s = '%s'", subsystem); - - s = strstr (subsystem, "/"); - if (s != NULL) - { - devtype = s + 1; - *s = '\0'; - } - - if (client->priv->monitor != NULL) - udev_monitor_filter_add_match_subsystem_devtype (client->priv->monitor, subsystem, devtype); - - g_free (subsystem); - } - - /* listen to events, and buffer them */ - if (client->priv->monitor != NULL) - { - udev_monitor_enable_receiving (client->priv->monitor); - channel = g_io_channel_unix_new (udev_monitor_get_fd (client->priv->monitor)); - client->priv->watch_source = g_io_create_watch (channel, G_IO_IN); - g_io_channel_unref (channel); - g_source_set_callback (client->priv->watch_source, (GSourceFunc) monitor_event, client, NULL); - g_source_attach (client->priv->watch_source, g_main_context_get_thread_default ()); - g_source_unref (client->priv->watch_source); - } - else - { - client->priv->watch_source = NULL; - } - } - - if (G_OBJECT_CLASS (g_udev_client_parent_class)->constructed != NULL) - G_OBJECT_CLASS (g_udev_client_parent_class)->constructed (object); -} - - -static void -g_udev_client_class_init (GUdevClientClass *klass) -{ - GObjectClass *gobject_class = (GObjectClass *) klass; - - gobject_class->constructed = g_udev_client_constructed; - gobject_class->set_property = g_udev_client_set_property; - gobject_class->get_property = g_udev_client_get_property; - gobject_class->finalize = g_udev_client_finalize; - - /** - * GUdevClient:subsystems: - * - * The subsystems to listen for uevents on. - * - * To listen for only a specific DEVTYPE for a given SUBSYSTEM, use - * "subsystem/devtype". For example, to only listen for uevents - * where SUBSYSTEM is usb and DEVTYPE is usb_interface, use - * "usb/usb_interface". - * - * If this property is %NULL, then no events will be reported. If - * it's the empty array, events from all subsystems will be - * reported. - */ - g_object_class_install_property (gobject_class, - PROP_SUBSYSTEMS, - g_param_spec_boxed ("subsystems", - "The subsystems to listen for changes on", - "The subsystems to listen for changes on", - G_TYPE_STRV, - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_READWRITE)); - - /** - * GUdevClient::uevent: - * @client: The #GUdevClient receiving the event. - * @action: The action for the uevent e.g. "add", "remove", "change", "move", etc. - * @device: Details about the #GUdevDevice the event is for. - * - * Emitted when @client receives an uevent. - * - * This signal is emitted in the - * <link linkend="g-main-context-push-thread-default">thread-default main loop</link> - * of the thread that @client was created in. - */ - signals[UEVENT_SIGNAL] = g_signal_new ("uevent", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GUdevClientClass, uevent), - NULL, - NULL, - g_udev_marshal_VOID__STRING_OBJECT, - G_TYPE_NONE, - 2, - G_TYPE_STRING, - G_UDEV_TYPE_DEVICE); - - g_type_class_add_private (klass, sizeof (GUdevClientPrivate)); -} - -static void -g_udev_client_init (GUdevClient *client) -{ - client->priv = G_TYPE_INSTANCE_GET_PRIVATE (client, - G_UDEV_TYPE_CLIENT, - GUdevClientPrivate); -} - -/** - * g_udev_client_new: - * @subsystems: (array zero-terminated=1) (element-type utf8) (transfer none) (allow-none): A %NULL terminated string array of subsystems to listen for uevents on, %NULL to not listen on uevents at all, or an empty array to listen to uevents on all subsystems. See the documentation for the #GUdevClient:subsystems property for details on this parameter. - * - * Constructs a #GUdevClient object that can be used to query - * information about devices. Connect to the #GUdevClient::uevent - * signal to listen for uevents. Note that signals are emitted in the - * <link linkend="g-main-context-push-thread-default">thread-default main loop</link> - * of the thread that you call this constructor from. - * - * Returns: A new #GUdevClient object. Free with g_object_unref(). - */ -GUdevClient * -g_udev_client_new (const gchar * const *subsystems) -{ - return G_UDEV_CLIENT (g_object_new (G_UDEV_TYPE_CLIENT, "subsystems", subsystems, NULL)); -} - -/** - * g_udev_client_query_by_subsystem: - * @client: A #GUdevClient. - * @subsystem: (allow-none): The subsystem to get devices for or %NULL to get all devices. - * - * Gets all devices belonging to @subsystem. - * - * Returns: (element-type GUdevDevice) (transfer full): A list of #GUdevDevice objects. The caller should free the result by using g_object_unref() on each element in the list and then g_list_free() on the list. - */ -GList * -g_udev_client_query_by_subsystem (GUdevClient *client, - const gchar *subsystem) -{ - struct udev_enumerate *enumerate; - struct udev_list_entry *l, *devices; - GList *ret; - - g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL); - - ret = NULL; - - /* prepare a device scan */ - enumerate = udev_enumerate_new (client->priv->udev); - - /* filter for subsystem */ - if (subsystem != NULL) - udev_enumerate_add_match_subsystem (enumerate, subsystem); - /* retrieve the list */ - udev_enumerate_scan_devices (enumerate); - - /* add devices to the list */ - devices = udev_enumerate_get_list_entry (enumerate); - for (l = devices; l != NULL; l = udev_list_entry_get_next (l)) - { - struct udev_device *udevice; - GUdevDevice *device; - - udevice = udev_device_new_from_syspath (udev_enumerate_get_udev (enumerate), - udev_list_entry_get_name (l)); - if (udevice == NULL) - continue; - device = _g_udev_device_new (udevice); - udev_device_unref (udevice); - ret = g_list_prepend (ret, device); - } - udev_enumerate_unref (enumerate); - - ret = g_list_reverse (ret); - - return ret; -} - -/** - * g_udev_client_query_by_device_number: - * @client: A #GUdevClient. - * @type: A value from the #GUdevDeviceType enumeration. - * @number: A device number. - * - * Looks up a device for a type and device number. - * - * Returns: (transfer full): A #GUdevDevice object or %NULL if the device was not found. Free with g_object_unref(). - */ -GUdevDevice * -g_udev_client_query_by_device_number (GUdevClient *client, - GUdevDeviceType type, - GUdevDeviceNumber number) -{ - struct udev_device *udevice; - GUdevDevice *device; - - g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL); - - device = NULL; - udevice = udev_device_new_from_devnum (client->priv->udev, type, number); - - if (udevice == NULL) - goto out; - - device = _g_udev_device_new (udevice); - udev_device_unref (udevice); - - out: - return device; -} - -/** - * g_udev_client_query_by_device_file: - * @client: A #GUdevClient. - * @device_file: A device file. - * - * Looks up a device for a device file. - * - * Returns: (transfer full): A #GUdevDevice object or %NULL if the device was not found. Free with g_object_unref(). - */ -GUdevDevice * -g_udev_client_query_by_device_file (GUdevClient *client, - const gchar *device_file) -{ - struct stat stat_buf; - GUdevDevice *device; - - g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL); - g_return_val_if_fail (device_file != NULL, NULL); - - device = NULL; - - if (stat (device_file, &stat_buf) != 0) - goto out; - - if (stat_buf.st_rdev == 0) - goto out; - - if (S_ISBLK (stat_buf.st_mode)) - device = g_udev_client_query_by_device_number (client, G_UDEV_DEVICE_TYPE_BLOCK, stat_buf.st_rdev); - else if (S_ISCHR (stat_buf.st_mode)) - device = g_udev_client_query_by_device_number (client, G_UDEV_DEVICE_TYPE_CHAR, stat_buf.st_rdev); - - out: - return device; -} - -/** - * g_udev_client_query_by_sysfs_path: - * @client: A #GUdevClient. - * @sysfs_path: A sysfs path. - * - * Looks up a device for a sysfs path. - * - * Returns: (transfer full): A #GUdevDevice object or %NULL if the device was not found. Free with g_object_unref(). - */ -GUdevDevice * -g_udev_client_query_by_sysfs_path (GUdevClient *client, - const gchar *sysfs_path) -{ - struct udev_device *udevice; - GUdevDevice *device; - - g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL); - g_return_val_if_fail (sysfs_path != NULL, NULL); - - device = NULL; - udevice = udev_device_new_from_syspath (client->priv->udev, sysfs_path); - if (udevice == NULL) - goto out; - - device = _g_udev_device_new (udevice); - udev_device_unref (udevice); - - out: - return device; -} - -/** - * g_udev_client_query_by_subsystem_and_name: - * @client: A #GUdevClient. - * @subsystem: A subsystem name. - * @name: The name of the device. - * - * Looks up a device for a subsystem and name. - * - * Returns: (transfer full): A #GUdevDevice object or %NULL if the device was not found. Free with g_object_unref(). - */ -GUdevDevice * -g_udev_client_query_by_subsystem_and_name (GUdevClient *client, - const gchar *subsystem, - const gchar *name) -{ - struct udev_device *udevice; - GUdevDevice *device; - - g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL); - g_return_val_if_fail (subsystem != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); - - device = NULL; - udevice = udev_device_new_from_subsystem_sysname (client->priv->udev, subsystem, name); - if (udevice == NULL) - goto out; - - device = _g_udev_device_new (udevice); - udev_device_unref (udevice); - - out: - return device; -} - -struct udev * -_g_udev_client_get_udev (GUdevClient *client) -{ - g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL); - return client->priv->udev; -} diff --git a/src/udev/src/gudev/gudevclient.h b/src/udev/src/gudev/gudevclient.h deleted file mode 100644 index b425d03d4..000000000 --- a/src/udev/src/gudev/gudevclient.h +++ /dev/null @@ -1,100 +0,0 @@ -/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2008 David Zeuthen <davidz@redhat.com> - * - * 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 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined (_GUDEV_COMPILATION) && !defined(_GUDEV_INSIDE_GUDEV_H) -#error "Only <gudev/gudev.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __G_UDEV_CLIENT_H__ -#define __G_UDEV_CLIENT_H__ - -#include <gudev/gudevtypes.h> - -G_BEGIN_DECLS - -#define G_UDEV_TYPE_CLIENT (g_udev_client_get_type ()) -#define G_UDEV_CLIENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_UDEV_TYPE_CLIENT, GUdevClient)) -#define G_UDEV_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_UDEV_TYPE_CLIENT, GUdevClientClass)) -#define G_UDEV_IS_CLIENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_UDEV_TYPE_CLIENT)) -#define G_UDEV_IS_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_UDEV_TYPE_CLIENT)) -#define G_UDEV_CLIENT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_UDEV_TYPE_CLIENT, GUdevClientClass)) - -typedef struct _GUdevClientClass GUdevClientClass; -typedef struct _GUdevClientPrivate GUdevClientPrivate; - -/** - * GUdevClient: - * - * The #GUdevClient struct is opaque and should not be accessed directly. - */ -struct _GUdevClient -{ - GObject parent; - - /*< private >*/ - GUdevClientPrivate *priv; -}; - -/** - * GUdevClientClass: - * @parent_class: Parent class. - * @uevent: Signal class handler for the #GUdevClient::uevent signal. - * - * Class structure for #GUdevClient. - */ -struct _GUdevClientClass -{ - GObjectClass parent_class; - - /* signals */ - void (*uevent) (GUdevClient *client, - const gchar *action, - GUdevDevice *device); - - /*< private >*/ - /* Padding for future expansion */ - void (*reserved1) (void); - void (*reserved2) (void); - void (*reserved3) (void); - void (*reserved4) (void); - void (*reserved5) (void); - void (*reserved6) (void); - void (*reserved7) (void); - void (*reserved8) (void); -}; - -GType g_udev_client_get_type (void) G_GNUC_CONST; -GUdevClient *g_udev_client_new (const gchar* const *subsystems); -GList *g_udev_client_query_by_subsystem (GUdevClient *client, - const gchar *subsystem); -GUdevDevice *g_udev_client_query_by_device_number (GUdevClient *client, - GUdevDeviceType type, - GUdevDeviceNumber number); -GUdevDevice *g_udev_client_query_by_device_file (GUdevClient *client, - const gchar *device_file); -GUdevDevice *g_udev_client_query_by_sysfs_path (GUdevClient *client, - const gchar *sysfs_path); -GUdevDevice *g_udev_client_query_by_subsystem_and_name (GUdevClient *client, - const gchar *subsystem, - const gchar *name); - -G_END_DECLS - -#endif /* __G_UDEV_CLIENT_H__ */ diff --git a/src/udev/src/gudev/gudevdevice.c b/src/udev/src/gudev/gudevdevice.c deleted file mode 100644 index 62a26f99b..000000000 --- a/src/udev/src/gudev/gudevdevice.c +++ /dev/null @@ -1,963 +0,0 @@ -/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2008 David Zeuthen <davidz@redhat.com> - * - * 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 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdlib.h> -#include <string.h> - -#include "gudevdevice.h" -#include "gudevprivate.h" - -/** - * SECTION:gudevdevice - * @short_description: Get information about a device - * - * The #GUdevDevice class is used to get information about a specific - * device. Note that you cannot instantiate a #GUdevDevice object - * yourself. Instead you must use #GUdevClient to obtain #GUdevDevice - * objects. - * - * To get basic information about a device, use - * g_udev_device_get_subsystem(), g_udev_device_get_devtype(), - * g_udev_device_get_name(), g_udev_device_get_number(), - * g_udev_device_get_sysfs_path(), g_udev_device_get_driver(), - * g_udev_device_get_action(), g_udev_device_get_seqnum(), - * g_udev_device_get_device_type(), g_udev_device_get_device_number(), - * g_udev_device_get_device_file(), - * g_udev_device_get_device_file_symlinks(). - * - * To navigate the device tree, use g_udev_device_get_parent() and - * g_udev_device_get_parent_with_subsystem(). - * - * To access udev properties for the device, use - * g_udev_device_get_property_keys(), - * g_udev_device_has_property(), - * g_udev_device_get_property(), - * g_udev_device_get_property_as_int(), - * g_udev_device_get_property_as_uint64(), - * g_udev_device_get_property_as_double(), - * g_udev_device_get_property_as_boolean() and - * g_udev_device_get_property_as_strv(). - * - * To access sysfs attributes for the device, use - * g_udev_device_get_sysfs_attr(), - * g_udev_device_get_sysfs_attr_as_int(), - * g_udev_device_get_sysfs_attr_as_uint64(), - * g_udev_device_get_sysfs_attr_as_double(), - * g_udev_device_get_sysfs_attr_as_boolean() and - * g_udev_device_get_sysfs_attr_as_strv(). - * - * Note that all getters on #GUdevDevice are non-reffing – returned - * values are owned by the object, should not be freed and are only - * valid as long as the object is alive. - * - * By design, #GUdevDevice will not react to changes for a device – it - * only contains a snapshot of information when the #GUdevDevice - * object was created. To work with changes, you typically connect to - * the #GUdevClient::uevent signal on a #GUdevClient and get a new - * #GUdevDevice whenever an event happens. - */ - -struct _GUdevDevicePrivate -{ - struct udev_device *udevice; - - /* computed ondemand and cached */ - gchar **device_file_symlinks; - gchar **property_keys; - gchar **tags; - GHashTable *prop_strvs; - GHashTable *sysfs_attr_strvs; -}; - -G_DEFINE_TYPE (GUdevDevice, g_udev_device, G_TYPE_OBJECT) - -static void -g_udev_device_finalize (GObject *object) -{ - GUdevDevice *device = G_UDEV_DEVICE (object); - - g_strfreev (device->priv->device_file_symlinks); - g_strfreev (device->priv->property_keys); - g_strfreev (device->priv->tags); - - if (device->priv->udevice != NULL) - udev_device_unref (device->priv->udevice); - - if (device->priv->prop_strvs != NULL) - g_hash_table_unref (device->priv->prop_strvs); - - if (device->priv->sysfs_attr_strvs != NULL) - g_hash_table_unref (device->priv->sysfs_attr_strvs); - - if (G_OBJECT_CLASS (g_udev_device_parent_class)->finalize != NULL) - (* G_OBJECT_CLASS (g_udev_device_parent_class)->finalize) (object); -} - -static void -g_udev_device_class_init (GUdevDeviceClass *klass) -{ - GObjectClass *gobject_class = (GObjectClass *) klass; - - gobject_class->finalize = g_udev_device_finalize; - - g_type_class_add_private (klass, sizeof (GUdevDevicePrivate)); -} - -static void -g_udev_device_init (GUdevDevice *device) -{ - device->priv = G_TYPE_INSTANCE_GET_PRIVATE (device, - G_UDEV_TYPE_DEVICE, - GUdevDevicePrivate); -} - - -GUdevDevice * -_g_udev_device_new (struct udev_device *udevice) -{ - GUdevDevice *device; - - device = G_UDEV_DEVICE (g_object_new (G_UDEV_TYPE_DEVICE, NULL)); - device->priv->udevice = udev_device_ref (udevice); - - return device; -} - -/** - * g_udev_device_get_subsystem: - * @device: A #GUdevDevice. - * - * Gets the subsystem for @device. - * - * Returns: The subsystem for @device. - */ -const gchar * -g_udev_device_get_subsystem (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - return udev_device_get_subsystem (device->priv->udevice); -} - -/** - * g_udev_device_get_devtype: - * @device: A #GUdevDevice. - * - * Gets the device type for @device. - * - * Returns: The devtype for @device. - */ -const gchar * -g_udev_device_get_devtype (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - return udev_device_get_devtype (device->priv->udevice); -} - -/** - * g_udev_device_get_name: - * @device: A #GUdevDevice. - * - * Gets the name of @device, e.g. "sda3". - * - * Returns: The name of @device. - */ -const gchar * -g_udev_device_get_name (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - return udev_device_get_sysname (device->priv->udevice); -} - -/** - * g_udev_device_get_number: - * @device: A #GUdevDevice. - * - * Gets the number of @device, e.g. "3" if g_udev_device_get_name() returns "sda3". - * - * Returns: The number of @device. - */ -const gchar * -g_udev_device_get_number (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - return udev_device_get_sysnum (device->priv->udevice); -} - -/** - * g_udev_device_get_sysfs_path: - * @device: A #GUdevDevice. - * - * Gets the sysfs path for @device. - * - * Returns: The sysfs path for @device. - */ -const gchar * -g_udev_device_get_sysfs_path (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - return udev_device_get_syspath (device->priv->udevice); -} - -/** - * g_udev_device_get_driver: - * @device: A #GUdevDevice. - * - * Gets the name of the driver used for @device. - * - * Returns: The name of the driver for @device or %NULL if unknown. - */ -const gchar * -g_udev_device_get_driver (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - return udev_device_get_driver (device->priv->udevice); -} - -/** - * g_udev_device_get_action: - * @device: A #GUdevDevice. - * - * Gets the most recent action (e.g. "add", "remove", "change", etc.) for @device. - * - * Returns: An action string. - */ -const gchar * -g_udev_device_get_action (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - return udev_device_get_action (device->priv->udevice); -} - -/** - * g_udev_device_get_seqnum: - * @device: A #GUdevDevice. - * - * Gets the most recent sequence number for @device. - * - * Returns: A sequence number. - */ -guint64 -g_udev_device_get_seqnum (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0); - return udev_device_get_seqnum (device->priv->udevice); -} - -/** - * g_udev_device_get_device_type: - * @device: A #GUdevDevice. - * - * Gets the type of the device file, if any, for @device. - * - * Returns: The device number for @device or #G_UDEV_DEVICE_TYPE_NONE if the device does not have a device file. - */ -GUdevDeviceType -g_udev_device_get_device_type (GUdevDevice *device) -{ - struct stat stat_buf; - const gchar *device_file; - GUdevDeviceType type; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), G_UDEV_DEVICE_TYPE_NONE); - - type = G_UDEV_DEVICE_TYPE_NONE; - - /* TODO: would be better to have support for this in libudev... */ - - device_file = g_udev_device_get_device_file (device); - if (device_file == NULL) - goto out; - - if (stat (device_file, &stat_buf) != 0) - goto out; - - if (S_ISBLK (stat_buf.st_mode)) - type = G_UDEV_DEVICE_TYPE_BLOCK; - else if (S_ISCHR (stat_buf.st_mode)) - type = G_UDEV_DEVICE_TYPE_CHAR; - - out: - return type; -} - -/** - * g_udev_device_get_device_number: - * @device: A #GUdevDevice. - * - * Gets the device number, if any, for @device. - * - * Returns: The device number for @device or 0 if unknown. - */ -GUdevDeviceNumber -g_udev_device_get_device_number (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0); - return udev_device_get_devnum (device->priv->udevice); -} - -/** - * g_udev_device_get_device_file: - * @device: A #GUdevDevice. - * - * Gets the device file for @device. - * - * Returns: The device file for @device or %NULL if no device file - * exists. - */ -const gchar * -g_udev_device_get_device_file (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - return udev_device_get_devnode (device->priv->udevice); -} - -/** - * g_udev_device_get_device_file_symlinks: - * @device: A #GUdevDevice. - * - * Gets a list of symlinks (in <literal>/dev</literal>) that points to - * the device file for @device. - * - * Returns: (transfer none) (array zero-terminated=1) (element-type utf8): A %NULL terminated string array of symlinks. This array is owned by @device and should not be freed by the caller. - */ -const gchar * const * -g_udev_device_get_device_file_symlinks (GUdevDevice *device) -{ - struct udev_list_entry *l; - GPtrArray *p; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - - if (device->priv->device_file_symlinks != NULL) - goto out; - - p = g_ptr_array_new (); - for (l = udev_device_get_devlinks_list_entry (device->priv->udevice); l != NULL; l = udev_list_entry_get_next (l)) - { - g_ptr_array_add (p, g_strdup (udev_list_entry_get_name (l))); - } - g_ptr_array_add (p, NULL); - device->priv->device_file_symlinks = (gchar **) g_ptr_array_free (p, FALSE); - - out: - return (const gchar * const *) device->priv->device_file_symlinks; -} - -/* ---------------------------------------------------------------------------------------------------- */ - -/** - * g_udev_device_get_parent: - * @device: A #GUdevDevice. - * - * Gets the immediate parent of @device, if any. - * - * Returns: (transfer full): A #GUdevDevice or %NULL if @device has no parent. Free with g_object_unref(). - */ -GUdevDevice * -g_udev_device_get_parent (GUdevDevice *device) -{ - GUdevDevice *ret; - struct udev_device *udevice; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - - ret = NULL; - - udevice = udev_device_get_parent (device->priv->udevice); - if (udevice == NULL) - goto out; - - ret = _g_udev_device_new (udevice); - - out: - return ret; -} - -/** - * g_udev_device_get_parent_with_subsystem: - * @device: A #GUdevDevice. - * @subsystem: The subsystem of the parent to get. - * @devtype: (allow-none): The devtype of the parent to get or %NULL. - * - * Walks up the chain of parents of @device and returns the first - * device encountered where @subsystem and @devtype matches, if any. - * - * Returns: (transfer full): A #GUdevDevice or %NULL if @device has no parent with @subsystem and @devtype. Free with g_object_unref(). - */ -GUdevDevice * -g_udev_device_get_parent_with_subsystem (GUdevDevice *device, - const gchar *subsystem, - const gchar *devtype) -{ - GUdevDevice *ret; - struct udev_device *udevice; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - g_return_val_if_fail (subsystem != NULL, NULL); - - ret = NULL; - - udevice = udev_device_get_parent_with_subsystem_devtype (device->priv->udevice, - subsystem, - devtype); - if (udevice == NULL) - goto out; - - ret = _g_udev_device_new (udevice); - - out: - return ret; -} - -/* ---------------------------------------------------------------------------------------------------- */ - -/** - * g_udev_device_get_property_keys: - * @device: A #GUdevDevice. - * - * Gets all keys for properties on @device. - * - * Returns: (transfer none) (array zero-terminated=1) (element-type utf8): A %NULL terminated string array of property keys. This array is owned by @device and should not be freed by the caller. - */ -const gchar* const * -g_udev_device_get_property_keys (GUdevDevice *device) -{ - struct udev_list_entry *l; - GPtrArray *p; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - - if (device->priv->property_keys != NULL) - goto out; - - p = g_ptr_array_new (); - for (l = udev_device_get_properties_list_entry (device->priv->udevice); l != NULL; l = udev_list_entry_get_next (l)) - { - g_ptr_array_add (p, g_strdup (udev_list_entry_get_name (l))); - } - g_ptr_array_add (p, NULL); - device->priv->property_keys = (gchar **) g_ptr_array_free (p, FALSE); - - out: - return (const gchar * const *) device->priv->property_keys; -} - - -/** - * g_udev_device_has_property: - * @device: A #GUdevDevice. - * @key: Name of property. - * - * Check if a the property with the given key exists. - * - * Returns: %TRUE only if the value for @key exist. - */ -gboolean -g_udev_device_has_property (GUdevDevice *device, - const gchar *key) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), FALSE); - g_return_val_if_fail (key != NULL, FALSE); - return udev_device_get_property_value (device->priv->udevice, key) != NULL; -} - -/** - * g_udev_device_get_property: - * @device: A #GUdevDevice. - * @key: Name of property. - * - * Look up the value for @key on @device. - * - * Returns: The value for @key or %NULL if @key doesn't exist on @device. Do not free this string, it is owned by @device. - */ -const gchar * -g_udev_device_get_property (GUdevDevice *device, - const gchar *key) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - g_return_val_if_fail (key != NULL, NULL); - return udev_device_get_property_value (device->priv->udevice, key); -} - -/** - * g_udev_device_get_property_as_int: - * @device: A #GUdevDevice. - * @key: Name of property. - * - * Look up the value for @key on @device and convert it to an integer - * using strtol(). - * - * Returns: The value for @key or 0 if @key doesn't exist or - * isn't an integer. - */ -gint -g_udev_device_get_property_as_int (GUdevDevice *device, - const gchar *key) -{ - gint result; - const gchar *s; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0); - g_return_val_if_fail (key != NULL, 0); - - result = 0; - s = g_udev_device_get_property (device, key); - if (s == NULL) - goto out; - - result = strtol (s, NULL, 0); -out: - return result; -} - -/** - * g_udev_device_get_property_as_uint64: - * @device: A #GUdevDevice. - * @key: Name of property. - * - * Look up the value for @key on @device and convert it to an unsigned - * 64-bit integer using g_ascii_strtoull(). - * - * Returns: The value for @key or 0 if @key doesn't exist or isn't a - * #guint64. - */ -guint64 -g_udev_device_get_property_as_uint64 (GUdevDevice *device, - const gchar *key) -{ - guint64 result; - const gchar *s; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0); - g_return_val_if_fail (key != NULL, 0); - - result = 0; - s = g_udev_device_get_property (device, key); - if (s == NULL) - goto out; - - result = g_ascii_strtoull (s, NULL, 0); -out: - return result; -} - -/** - * g_udev_device_get_property_as_double: - * @device: A #GUdevDevice. - * @key: Name of property. - * - * Look up the value for @key on @device and convert it to a double - * precision floating point number using strtod(). - * - * Returns: The value for @key or 0.0 if @key doesn't exist or isn't a - * #gdouble. - */ -gdouble -g_udev_device_get_property_as_double (GUdevDevice *device, - const gchar *key) -{ - gdouble result; - const gchar *s; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0.0); - g_return_val_if_fail (key != NULL, 0.0); - - result = 0.0; - s = g_udev_device_get_property (device, key); - if (s == NULL) - goto out; - - result = strtod (s, NULL); -out: - return result; -} - -/** - * g_udev_device_get_property_as_boolean: - * @device: A #GUdevDevice. - * @key: Name of property. - * - * Look up the value for @key on @device and convert it to an - * boolean. This is done by doing a case-insensitive string comparison - * on the string value against "1" and "true". - * - * Returns: The value for @key or %FALSE if @key doesn't exist or - * isn't a #gboolean. - */ -gboolean -g_udev_device_get_property_as_boolean (GUdevDevice *device, - const gchar *key) -{ - gboolean result; - const gchar *s; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), FALSE); - g_return_val_if_fail (key != NULL, FALSE); - - result = FALSE; - s = g_udev_device_get_property (device, key); - if (s == NULL) - goto out; - - if (strcmp (s, "1") == 0 || g_ascii_strcasecmp (s, "true") == 0) - result = TRUE; - out: - return result; -} - -static gchar ** -split_at_whitespace (const gchar *s) -{ - gchar **result; - guint n; - guint m; - - result = g_strsplit_set (s, " \v\t\r\n", 0); - - /* remove empty strings, thanks GLib */ - for (n = 0; result[n] != NULL; n++) - { - if (strlen (result[n]) == 0) - { - g_free (result[n]); - for (m = n; result[m] != NULL; m++) - result[m] = result[m + 1]; - n--; - } - } - - return result; -} - -/** - * g_udev_device_get_property_as_strv: - * @device: A #GUdevDevice. - * @key: Name of property. - * - * Look up the value for @key on @device and return the result of - * splitting it into non-empty tokens split at white space (only space - * (' '), form-feed ('\f'), newline ('\n'), carriage return ('\r'), - * horizontal tab ('\t'), and vertical tab ('\v') are considered; the - * locale is not taken into account). - * - * Returns: (transfer none) (array zero-terminated=1) (element-type utf8): The value of @key on @device split into tokens or %NULL if @key doesn't exist. This array is owned by @device and should not be freed by the caller. - */ -const gchar* const * -g_udev_device_get_property_as_strv (GUdevDevice *device, - const gchar *key) -{ - gchar **result; - const gchar *s; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - g_return_val_if_fail (key != NULL, NULL); - - if (device->priv->prop_strvs != NULL) - { - result = g_hash_table_lookup (device->priv->prop_strvs, key); - if (result != NULL) - goto out; - } - - result = NULL; - s = g_udev_device_get_property (device, key); - if (s == NULL) - goto out; - - result = split_at_whitespace (s); - if (result == NULL) - goto out; - - if (device->priv->prop_strvs == NULL) - device->priv->prop_strvs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_strfreev); - g_hash_table_insert (device->priv->prop_strvs, g_strdup (key), result); - -out: - return (const gchar* const *) result; -} - -/* ---------------------------------------------------------------------------------------------------- */ - -/** - * g_udev_device_get_sysfs_attr: - * @device: A #GUdevDevice. - * @name: Name of the sysfs attribute. - * - * Look up the sysfs attribute with @name on @device. - * - * Returns: The value of the sysfs attribute or %NULL if there is no - * such attribute. Do not free this string, it is owned by @device. - */ -const gchar * -g_udev_device_get_sysfs_attr (GUdevDevice *device, - const gchar *name) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - g_return_val_if_fail (name != NULL, NULL); - return udev_device_get_sysattr_value (device->priv->udevice, name); -} - -/** - * g_udev_device_get_sysfs_attr_as_int: - * @device: A #GUdevDevice. - * @name: Name of the sysfs attribute. - * - * Look up the sysfs attribute with @name on @device and convert it to an integer - * using strtol(). - * - * Returns: The value of the sysfs attribute or 0 if there is no such - * attribute. - */ -gint -g_udev_device_get_sysfs_attr_as_int (GUdevDevice *device, - const gchar *name) -{ - gint result; - const gchar *s; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0); - g_return_val_if_fail (name != NULL, 0); - - result = 0; - s = g_udev_device_get_sysfs_attr (device, name); - if (s == NULL) - goto out; - - result = strtol (s, NULL, 0); -out: - return result; -} - -/** - * g_udev_device_get_sysfs_attr_as_uint64: - * @device: A #GUdevDevice. - * @name: Name of the sysfs attribute. - * - * Look up the sysfs attribute with @name on @device and convert it to an unsigned - * 64-bit integer using g_ascii_strtoull(). - * - * Returns: The value of the sysfs attribute or 0 if there is no such - * attribute. - */ -guint64 -g_udev_device_get_sysfs_attr_as_uint64 (GUdevDevice *device, - const gchar *name) -{ - guint64 result; - const gchar *s; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0); - g_return_val_if_fail (name != NULL, 0); - - result = 0; - s = g_udev_device_get_sysfs_attr (device, name); - if (s == NULL) - goto out; - - result = g_ascii_strtoull (s, NULL, 0); -out: - return result; -} - -/** - * g_udev_device_get_sysfs_attr_as_double: - * @device: A #GUdevDevice. - * @name: Name of the sysfs attribute. - * - * Look up the sysfs attribute with @name on @device and convert it to a double - * precision floating point number using strtod(). - * - * Returns: The value of the sysfs attribute or 0.0 if there is no such - * attribute. - */ -gdouble -g_udev_device_get_sysfs_attr_as_double (GUdevDevice *device, - const gchar *name) -{ - gdouble result; - const gchar *s; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0.0); - g_return_val_if_fail (name != NULL, 0.0); - - result = 0.0; - s = g_udev_device_get_sysfs_attr (device, name); - if (s == NULL) - goto out; - - result = strtod (s, NULL); -out: - return result; -} - -/** - * g_udev_device_get_sysfs_attr_as_boolean: - * @device: A #GUdevDevice. - * @name: Name of the sysfs attribute. - * - * Look up the sysfs attribute with @name on @device and convert it to an - * boolean. This is done by doing a case-insensitive string comparison - * on the string value against "1" and "true". - * - * Returns: The value of the sysfs attribute or %FALSE if there is no such - * attribute. - */ -gboolean -g_udev_device_get_sysfs_attr_as_boolean (GUdevDevice *device, - const gchar *name) -{ - gboolean result; - const gchar *s; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), FALSE); - g_return_val_if_fail (name != NULL, FALSE); - - result = FALSE; - s = g_udev_device_get_sysfs_attr (device, name); - if (s == NULL) - goto out; - - if (strcmp (s, "1") == 0 || g_ascii_strcasecmp (s, "true") == 0) - result = TRUE; - out: - return result; -} - -/** - * g_udev_device_get_sysfs_attr_as_strv: - * @device: A #GUdevDevice. - * @name: Name of the sysfs attribute. - * - * Look up the sysfs attribute with @name on @device and return the result of - * splitting it into non-empty tokens split at white space (only space (' '), - * form-feed ('\f'), newline ('\n'), carriage return ('\r'), horizontal - * tab ('\t'), and vertical tab ('\v') are considered; the locale is - * not taken into account). - * - * Returns: (transfer none) (array zero-terminated=1) (element-type utf8): The value of the sysfs attribute split into tokens or %NULL if there is no such attribute. This array is owned by @device and should not be freed by the caller. - */ -const gchar * const * -g_udev_device_get_sysfs_attr_as_strv (GUdevDevice *device, - const gchar *name) -{ - gchar **result; - const gchar *s; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - g_return_val_if_fail (name != NULL, NULL); - - if (device->priv->sysfs_attr_strvs != NULL) - { - result = g_hash_table_lookup (device->priv->sysfs_attr_strvs, name); - if (result != NULL) - goto out; - } - - result = NULL; - s = g_udev_device_get_sysfs_attr (device, name); - if (s == NULL) - goto out; - - result = split_at_whitespace (s); - if (result == NULL) - goto out; - - if (device->priv->sysfs_attr_strvs == NULL) - device->priv->sysfs_attr_strvs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_strfreev); - g_hash_table_insert (device->priv->sysfs_attr_strvs, g_strdup (name), result); - -out: - return (const gchar* const *) result; -} - -/** - * g_udev_device_get_tags: - * @device: A #GUdevDevice. - * - * Gets all tags for @device. - * - * Returns: (transfer none) (array zero-terminated=1) (element-type utf8): A %NULL terminated string array of tags. This array is owned by @device and should not be freed by the caller. - * - * Since: 165 - */ -const gchar* const * -g_udev_device_get_tags (GUdevDevice *device) -{ - struct udev_list_entry *l; - GPtrArray *p; - - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); - - if (device->priv->tags != NULL) - goto out; - - p = g_ptr_array_new (); - for (l = udev_device_get_tags_list_entry (device->priv->udevice); l != NULL; l = udev_list_entry_get_next (l)) - { - g_ptr_array_add (p, g_strdup (udev_list_entry_get_name (l))); - } - g_ptr_array_add (p, NULL); - device->priv->tags = (gchar **) g_ptr_array_free (p, FALSE); - - out: - return (const gchar * const *) device->priv->tags; -} - -/** - * g_udev_device_get_is_initialized: - * @device: A #GUdevDevice. - * - * Gets whether @device has been initalized. - * - * Returns: Whether @device has been initialized. - * - * Since: 165 - */ -gboolean -g_udev_device_get_is_initialized (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), FALSE); - return udev_device_get_is_initialized (device->priv->udevice); -} - -/** - * g_udev_device_get_usec_since_initialized: - * @device: A #GUdevDevice. - * - * Gets number of micro-seconds since @device was initialized. - * - * This only works for devices with properties in the udev - * database. All other devices return 0. - * - * Returns: Number of micro-seconds since @device was initialized or 0 if unknown. - * - * Since: 165 - */ -guint64 -g_udev_device_get_usec_since_initialized (GUdevDevice *device) -{ - g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0); - return udev_device_get_usec_since_initialized (device->priv->udevice); -} diff --git a/src/udev/src/gudev/gudevdevice.h b/src/udev/src/gudev/gudevdevice.h deleted file mode 100644 index d4873bad0..000000000 --- a/src/udev/src/gudev/gudevdevice.h +++ /dev/null @@ -1,128 +0,0 @@ -/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2008 David Zeuthen <davidz@redhat.com> - * - * 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 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined (_GUDEV_COMPILATION) && !defined(_GUDEV_INSIDE_GUDEV_H) -#error "Only <gudev/gudev.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __G_UDEV_DEVICE_H__ -#define __G_UDEV_DEVICE_H__ - -#include <gudev/gudevtypes.h> - -G_BEGIN_DECLS - -#define G_UDEV_TYPE_DEVICE (g_udev_device_get_type ()) -#define G_UDEV_DEVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_UDEV_TYPE_DEVICE, GUdevDevice)) -#define G_UDEV_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_UDEV_TYPE_DEVICE, GUdevDeviceClass)) -#define G_UDEV_IS_DEVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_UDEV_TYPE_DEVICE)) -#define G_UDEV_IS_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_UDEV_TYPE_DEVICE)) -#define G_UDEV_DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_UDEV_TYPE_DEVICE, GUdevDeviceClass)) - -typedef struct _GUdevDeviceClass GUdevDeviceClass; -typedef struct _GUdevDevicePrivate GUdevDevicePrivate; - -/** - * GUdevDevice: - * - * The #GUdevDevice struct is opaque and should not be accessed directly. - */ -struct _GUdevDevice -{ - GObject parent; - - /*< private >*/ - GUdevDevicePrivate *priv; -}; - -/** - * GUdevDeviceClass: - * @parent_class: Parent class. - * - * Class structure for #GUdevDevice. - */ -struct _GUdevDeviceClass -{ - GObjectClass parent_class; - - /*< private >*/ - /* Padding for future expansion */ - void (*reserved1) (void); - void (*reserved2) (void); - void (*reserved3) (void); - void (*reserved4) (void); - void (*reserved5) (void); - void (*reserved6) (void); - void (*reserved7) (void); - void (*reserved8) (void); -}; - -GType g_udev_device_get_type (void) G_GNUC_CONST; -gboolean g_udev_device_get_is_initialized (GUdevDevice *device); -guint64 g_udev_device_get_usec_since_initialized (GUdevDevice *device); -const gchar *g_udev_device_get_subsystem (GUdevDevice *device); -const gchar *g_udev_device_get_devtype (GUdevDevice *device); -const gchar *g_udev_device_get_name (GUdevDevice *device); -const gchar *g_udev_device_get_number (GUdevDevice *device); -const gchar *g_udev_device_get_sysfs_path (GUdevDevice *device); -const gchar *g_udev_device_get_driver (GUdevDevice *device); -const gchar *g_udev_device_get_action (GUdevDevice *device); -guint64 g_udev_device_get_seqnum (GUdevDevice *device); -GUdevDeviceType g_udev_device_get_device_type (GUdevDevice *device); -GUdevDeviceNumber g_udev_device_get_device_number (GUdevDevice *device); -const gchar *g_udev_device_get_device_file (GUdevDevice *device); -const gchar* const *g_udev_device_get_device_file_symlinks (GUdevDevice *device); -GUdevDevice *g_udev_device_get_parent (GUdevDevice *device); -GUdevDevice *g_udev_device_get_parent_with_subsystem (GUdevDevice *device, - const gchar *subsystem, - const gchar *devtype); -const gchar* const *g_udev_device_get_property_keys (GUdevDevice *device); -gboolean g_udev_device_has_property (GUdevDevice *device, - const gchar *key); -const gchar *g_udev_device_get_property (GUdevDevice *device, - const gchar *key); -gint g_udev_device_get_property_as_int (GUdevDevice *device, - const gchar *key); -guint64 g_udev_device_get_property_as_uint64 (GUdevDevice *device, - const gchar *key); -gdouble g_udev_device_get_property_as_double (GUdevDevice *device, - const gchar *key); -gboolean g_udev_device_get_property_as_boolean (GUdevDevice *device, - const gchar *key); -const gchar* const *g_udev_device_get_property_as_strv (GUdevDevice *device, - const gchar *key); - -const gchar *g_udev_device_get_sysfs_attr (GUdevDevice *device, - const gchar *name); -gint g_udev_device_get_sysfs_attr_as_int (GUdevDevice *device, - const gchar *name); -guint64 g_udev_device_get_sysfs_attr_as_uint64 (GUdevDevice *device, - const gchar *name); -gdouble g_udev_device_get_sysfs_attr_as_double (GUdevDevice *device, - const gchar *name); -gboolean g_udev_device_get_sysfs_attr_as_boolean (GUdevDevice *device, - const gchar *name); -const gchar* const *g_udev_device_get_sysfs_attr_as_strv (GUdevDevice *device, - const gchar *name); -const gchar* const *g_udev_device_get_tags (GUdevDevice *device); - -G_END_DECLS - -#endif /* __G_UDEV_DEVICE_H__ */ diff --git a/src/udev/src/gudev/gudevenumerator.c b/src/udev/src/gudev/gudevenumerator.c deleted file mode 100644 index db0907462..000000000 --- a/src/udev/src/gudev/gudevenumerator.c +++ /dev/null @@ -1,431 +0,0 @@ -/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2008-2010 David Zeuthen <davidz@redhat.com> - * - * 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 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdlib.h> -#include <string.h> - -#include "gudevclient.h" -#include "gudevenumerator.h" -#include "gudevdevice.h" -#include "gudevmarshal.h" -#include "gudevprivate.h" - -/** - * SECTION:gudevenumerator - * @short_description: Lookup and sort devices - * - * #GUdevEnumerator is used to lookup and sort devices. - * - * Since: 165 - */ - -struct _GUdevEnumeratorPrivate -{ - GUdevClient *client; - struct udev_enumerate *e; -}; - -enum -{ - PROP_0, - PROP_CLIENT, -}; - -G_DEFINE_TYPE (GUdevEnumerator, g_udev_enumerator, G_TYPE_OBJECT) - -/* ---------------------------------------------------------------------------------------------------- */ - -static void -g_udev_enumerator_finalize (GObject *object) -{ - GUdevEnumerator *enumerator = G_UDEV_ENUMERATOR (object); - - if (enumerator->priv->client != NULL) - { - g_object_unref (enumerator->priv->client); - enumerator->priv->client = NULL; - } - - if (enumerator->priv->e != NULL) - { - udev_enumerate_unref (enumerator->priv->e); - enumerator->priv->e = NULL; - } - - if (G_OBJECT_CLASS (g_udev_enumerator_parent_class)->finalize != NULL) - G_OBJECT_CLASS (g_udev_enumerator_parent_class)->finalize (object); -} - -static void -g_udev_enumerator_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GUdevEnumerator *enumerator = G_UDEV_ENUMERATOR (object); - - switch (prop_id) - { - case PROP_CLIENT: - if (enumerator->priv->client != NULL) - g_object_unref (enumerator->priv->client); - enumerator->priv->client = g_value_dup_object (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -g_udev_enumerator_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GUdevEnumerator *enumerator = G_UDEV_ENUMERATOR (object); - - switch (prop_id) - { - case PROP_CLIENT: - g_value_set_object (value, enumerator->priv->client); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -g_udev_enumerator_constructed (GObject *object) -{ - GUdevEnumerator *enumerator = G_UDEV_ENUMERATOR (object); - - g_assert (G_UDEV_IS_CLIENT (enumerator->priv->client)); - - enumerator->priv->e = udev_enumerate_new (_g_udev_client_get_udev (enumerator->priv->client)); - - if (G_OBJECT_CLASS (g_udev_enumerator_parent_class)->constructed != NULL) - G_OBJECT_CLASS (g_udev_enumerator_parent_class)->constructed (object); -} - -static void -g_udev_enumerator_class_init (GUdevEnumeratorClass *klass) -{ - GObjectClass *gobject_class = (GObjectClass *) klass; - - gobject_class->finalize = g_udev_enumerator_finalize; - gobject_class->set_property = g_udev_enumerator_set_property; - gobject_class->get_property = g_udev_enumerator_get_property; - gobject_class->constructed = g_udev_enumerator_constructed; - - /** - * GUdevEnumerator:client: - * - * The #GUdevClient to enumerate devices from. - * - * Since: 165 - */ - g_object_class_install_property (gobject_class, - PROP_CLIENT, - g_param_spec_object ("client", - "The client to enumerate devices from", - "The client to enumerate devices from", - G_UDEV_TYPE_CLIENT, - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_READWRITE)); - - g_type_class_add_private (klass, sizeof (GUdevEnumeratorPrivate)); -} - -static void -g_udev_enumerator_init (GUdevEnumerator *enumerator) -{ - enumerator->priv = G_TYPE_INSTANCE_GET_PRIVATE (enumerator, - G_UDEV_TYPE_ENUMERATOR, - GUdevEnumeratorPrivate); -} - -/** - * g_udev_enumerator_new: - * @client: A #GUdevClient to enumerate devices from. - * - * Constructs a #GUdevEnumerator object that can be used to enumerate - * and sort devices. Use the add_match_*() and add_nomatch_*() methods - * and execute the query to get a list of devices with - * g_udev_enumerator_execute(). - * - * Returns: A new #GUdevEnumerator object. Free with g_object_unref(). - * - * Since: 165 - */ -GUdevEnumerator * -g_udev_enumerator_new (GUdevClient *client) -{ - g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL); - return G_UDEV_ENUMERATOR (g_object_new (G_UDEV_TYPE_ENUMERATOR, "client", client, NULL)); -} - - -/** - * g_udev_enumerator_add_match_subsystem: - * @enumerator: A #GUdevEnumerator. - * @subsystem: Wildcard for subsystem name e.g. 'scsi' or 'a*'. - * - * All returned devices will match the given @subsystem. - * - * Returns: (transfer none): The passed in @enumerator. - * - * Since: 165 - */ -GUdevEnumerator * -g_udev_enumerator_add_match_subsystem (GUdevEnumerator *enumerator, - const gchar *subsystem) -{ - g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); - g_return_val_if_fail (subsystem != NULL, NULL); - udev_enumerate_add_match_subsystem (enumerator->priv->e, subsystem); - return enumerator; -} - -/** - * g_udev_enumerator_add_nomatch_subsystem: - * @enumerator: A #GUdevEnumerator. - * @subsystem: Wildcard for subsystem name e.g. 'scsi' or 'a*'. - * - * All returned devices will not match the given @subsystem. - * - * Returns: (transfer none): The passed in @enumerator. - * - * Since: 165 - */ -GUdevEnumerator * -g_udev_enumerator_add_nomatch_subsystem (GUdevEnumerator *enumerator, - const gchar *subsystem) -{ - g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); - g_return_val_if_fail (subsystem != NULL, NULL); - udev_enumerate_add_nomatch_subsystem (enumerator->priv->e, subsystem); - return enumerator; -} - -/** - * g_udev_enumerator_add_match_sysfs_attr: - * @enumerator: A #GUdevEnumerator. - * @name: Wildcard filter for sysfs attribute key. - * @value: Wildcard filter for sysfs attribute value. - * - * All returned devices will have a sysfs attribute matching the given @name and @value. - * - * Returns: (transfer none): The passed in @enumerator. - * - * Since: 165 - */ -GUdevEnumerator * -g_udev_enumerator_add_match_sysfs_attr (GUdevEnumerator *enumerator, - const gchar *name, - const gchar *value) -{ - g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); - g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (value != NULL, NULL); - udev_enumerate_add_match_sysattr (enumerator->priv->e, name, value); - return enumerator; -} - -/** - * g_udev_enumerator_add_nomatch_sysfs_attr: - * @enumerator: A #GUdevEnumerator. - * @name: Wildcard filter for sysfs attribute key. - * @value: Wildcard filter for sysfs attribute value. - * - * All returned devices will not have a sysfs attribute matching the given @name and @value. - * - * Returns: (transfer none): The passed in @enumerator. - * - * Since: 165 - */ -GUdevEnumerator * -g_udev_enumerator_add_nomatch_sysfs_attr (GUdevEnumerator *enumerator, - const gchar *name, - const gchar *value) -{ - g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); - g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (value != NULL, NULL); - udev_enumerate_add_nomatch_sysattr (enumerator->priv->e, name, value); - return enumerator; -} - -/** - * g_udev_enumerator_add_match_property: - * @enumerator: A #GUdevEnumerator. - * @name: Wildcard filter for property name. - * @value: Wildcard filter for property value. - * - * All returned devices will have a property matching the given @name and @value. - * - * Returns: (transfer none): The passed in @enumerator. - * - * Since: 165 - */ -GUdevEnumerator * -g_udev_enumerator_add_match_property (GUdevEnumerator *enumerator, - const gchar *name, - const gchar *value) -{ - g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); - g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (value != NULL, NULL); - udev_enumerate_add_match_property (enumerator->priv->e, name, value); - return enumerator; -} - -/** - * g_udev_enumerator_add_match_name: - * @enumerator: A #GUdevEnumerator. - * @name: Wildcard filter for kernel name e.g. "sda*". - * - * All returned devices will match the given @name. - * - * Returns: (transfer none): The passed in @enumerator. - * - * Since: 165 - */ -GUdevEnumerator * -g_udev_enumerator_add_match_name (GUdevEnumerator *enumerator, - const gchar *name) -{ - g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); - g_return_val_if_fail (name != NULL, NULL); - udev_enumerate_add_match_sysname (enumerator->priv->e, name); - return enumerator; -} - -/** - * g_udev_enumerator_add_sysfs_path: - * @enumerator: A #GUdevEnumerator. - * @sysfs_path: A sysfs path, e.g. "/sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda" - * - * Add a device to the list of devices, to retrieve it back sorted in dependency order. - * - * Returns: (transfer none): The passed in @enumerator. - * - * Since: 165 - */ -GUdevEnumerator * -g_udev_enumerator_add_sysfs_path (GUdevEnumerator *enumerator, - const gchar *sysfs_path) -{ - g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); - g_return_val_if_fail (sysfs_path != NULL, NULL); - udev_enumerate_add_syspath (enumerator->priv->e, sysfs_path); - return enumerator; -} - -/** - * g_udev_enumerator_add_match_tag: - * @enumerator: A #GUdevEnumerator. - * @tag: A udev tag e.g. "udev-acl". - * - * All returned devices will match the given @tag. - * - * Returns: (transfer none): The passed in @enumerator. - * - * Since: 165 - */ -GUdevEnumerator * -g_udev_enumerator_add_match_tag (GUdevEnumerator *enumerator, - const gchar *tag) -{ - g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); - g_return_val_if_fail (tag != NULL, NULL); - udev_enumerate_add_match_tag (enumerator->priv->e, tag); - return enumerator; -} - -/** - * g_udev_enumerator_add_match_is_initialized: - * @enumerator: A #GUdevEnumerator. - * - * All returned devices will be initialized. - * - * Returns: (transfer none): The passed in @enumerator. - * - * Since: 165 - */ -GUdevEnumerator * -g_udev_enumerator_add_match_is_initialized (GUdevEnumerator *enumerator) -{ - g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); - udev_enumerate_add_match_is_initialized (enumerator->priv->e); - return enumerator; -} - -/** - * g_udev_enumerator_execute: - * @enumerator: A #GUdevEnumerator. - * - * Executes the query in @enumerator. - * - * Returns: (element-type GUdevDevice) (transfer full): A list of #GUdevDevice objects. The caller should free the result by using g_object_unref() on each element in the list and then g_list_free() on the list. - * - * Since: 165 - */ -GList * -g_udev_enumerator_execute (GUdevEnumerator *enumerator) -{ - GList *ret; - struct udev_list_entry *l, *devices; - - g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); - - ret = NULL; - - /* retrieve the list */ - udev_enumerate_scan_devices (enumerator->priv->e); - - devices = udev_enumerate_get_list_entry (enumerator->priv->e); - for (l = devices; l != NULL; l = udev_list_entry_get_next (l)) - { - struct udev_device *udevice; - GUdevDevice *device; - - udevice = udev_device_new_from_syspath (udev_enumerate_get_udev (enumerator->priv->e), - udev_list_entry_get_name (l)); - if (udevice == NULL) - continue; - - device = _g_udev_device_new (udevice); - udev_device_unref (udevice); - ret = g_list_prepend (ret, device); - } - - ret = g_list_reverse (ret); - - return ret; -} diff --git a/src/udev/src/gudev/gudevenumerator.h b/src/udev/src/gudev/gudevenumerator.h deleted file mode 100644 index 3fddccf57..000000000 --- a/src/udev/src/gudev/gudevenumerator.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2008-2010 David Zeuthen <davidz@redhat.com> - * - * 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 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined (_GUDEV_COMPILATION) && !defined(_GUDEV_INSIDE_GUDEV_H) -#error "Only <gudev/gudev.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __G_UDEV_ENUMERATOR_H__ -#define __G_UDEV_ENUMERATOR_H__ - -#include <gudev/gudevtypes.h> - -G_BEGIN_DECLS - -#define G_UDEV_TYPE_ENUMERATOR (g_udev_enumerator_get_type ()) -#define G_UDEV_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_UDEV_TYPE_ENUMERATOR, GUdevEnumerator)) -#define G_UDEV_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_UDEV_TYPE_ENUMERATOR, GUdevEnumeratorClass)) -#define G_UDEV_IS_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_UDEV_TYPE_ENUMERATOR)) -#define G_UDEV_IS_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_UDEV_TYPE_ENUMERATOR)) -#define G_UDEV_ENUMERATOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_UDEV_TYPE_ENUMERATOR, GUdevEnumeratorClass)) - -typedef struct _GUdevEnumeratorClass GUdevEnumeratorClass; -typedef struct _GUdevEnumeratorPrivate GUdevEnumeratorPrivate; - -/** - * GUdevEnumerator: - * - * The #GUdevEnumerator struct is opaque and should not be accessed directly. - * - * Since: 165 - */ -struct _GUdevEnumerator -{ - GObject parent; - - /*< private >*/ - GUdevEnumeratorPrivate *priv; -}; - -/** - * GUdevEnumeratorClass: - * @parent_class: Parent class. - * - * Class structure for #GUdevEnumerator. - * - * Since: 165 - */ -struct _GUdevEnumeratorClass -{ - GObjectClass parent_class; - - /*< private >*/ - /* Padding for future expansion */ - void (*reserved1) (void); - void (*reserved2) (void); - void (*reserved3) (void); - void (*reserved4) (void); - void (*reserved5) (void); - void (*reserved6) (void); - void (*reserved7) (void); - void (*reserved8) (void); -}; - -GType g_udev_enumerator_get_type (void) G_GNUC_CONST; -GUdevEnumerator *g_udev_enumerator_new (GUdevClient *client); -GUdevEnumerator *g_udev_enumerator_add_match_subsystem (GUdevEnumerator *enumerator, - const gchar *subsystem); -GUdevEnumerator *g_udev_enumerator_add_nomatch_subsystem (GUdevEnumerator *enumerator, - const gchar *subsystem); -GUdevEnumerator *g_udev_enumerator_add_match_sysfs_attr (GUdevEnumerator *enumerator, - const gchar *name, - const gchar *value); -GUdevEnumerator *g_udev_enumerator_add_nomatch_sysfs_attr (GUdevEnumerator *enumerator, - const gchar *name, - const gchar *value); -GUdevEnumerator *g_udev_enumerator_add_match_property (GUdevEnumerator *enumerator, - const gchar *name, - const gchar *value); -GUdevEnumerator *g_udev_enumerator_add_match_name (GUdevEnumerator *enumerator, - const gchar *name); -GUdevEnumerator *g_udev_enumerator_add_match_tag (GUdevEnumerator *enumerator, - const gchar *tag); -GUdevEnumerator *g_udev_enumerator_add_match_is_initialized (GUdevEnumerator *enumerator); -GUdevEnumerator *g_udev_enumerator_add_sysfs_path (GUdevEnumerator *enumerator, - const gchar *sysfs_path); -GList *g_udev_enumerator_execute (GUdevEnumerator *enumerator); - -G_END_DECLS - -#endif /* __G_UDEV_ENUMERATOR_H__ */ diff --git a/src/udev/src/gudev/gudevenums.h b/src/udev/src/gudev/gudevenums.h deleted file mode 100644 index c3a0aa874..000000000 --- a/src/udev/src/gudev/gudevenums.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2008 David Zeuthen <davidz@redhat.com> - * - * 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 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined (_GUDEV_COMPILATION) && !defined(_GUDEV_INSIDE_GUDEV_H) -#error "Only <gudev/gudev.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __G_UDEV_ENUMS_H__ -#define __G_UDEV_ENUMS_H__ - -#include <glib-object.h> - -G_BEGIN_DECLS - -/** - * GUdevDeviceType: - * @G_UDEV_DEVICE_TYPE_NONE: Device does not have a device file. - * @G_UDEV_DEVICE_TYPE_BLOCK: Device is a block device. - * @G_UDEV_DEVICE_TYPE_CHAR: Device is a character device. - * - * Enumeration used to specify a the type of a device. - */ -typedef enum -{ - G_UDEV_DEVICE_TYPE_NONE = 0, - G_UDEV_DEVICE_TYPE_BLOCK = 'b', - G_UDEV_DEVICE_TYPE_CHAR = 'c', -} GUdevDeviceType; - -G_END_DECLS - -#endif /* __G_UDEV_ENUMS_H__ */ diff --git a/src/udev/src/gudev/gudevenumtypes.c.template b/src/udev/src/gudev/gudevenumtypes.c.template deleted file mode 100644 index fc30b39e2..000000000 --- a/src/udev/src/gudev/gudevenumtypes.c.template +++ /dev/null @@ -1,39 +0,0 @@ -/*** BEGIN file-header ***/ -#include <gudev.h> - -/*** END file-header ***/ - -/*** BEGIN file-production ***/ -/* enumerations from "@filename@" */ -/*** END file-production ***/ - -/*** BEGIN value-header ***/ -GType -@enum_name@_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const G@Type@Value values[] = { -/*** END value-header ***/ - -/*** BEGIN value-production ***/ - { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, -/*** END value-production ***/ - -/*** BEGIN value-tail ***/ - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} - -/*** END value-tail ***/ - -/*** BEGIN file-tail ***/ -/*** END file-tail ***/ diff --git a/src/udev/src/gudev/gudevenumtypes.h.template b/src/udev/src/gudev/gudevenumtypes.h.template deleted file mode 100644 index d0ab3393e..000000000 --- a/src/udev/src/gudev/gudevenumtypes.h.template +++ /dev/null @@ -1,24 +0,0 @@ -/*** BEGIN file-header ***/ -#ifndef __GUDEV_ENUM_TYPES_H__ -#define __GUDEV_ENUM_TYPES_H__ - -#include <glib-object.h> - -G_BEGIN_DECLS -/*** END file-header ***/ - -/*** BEGIN file-production ***/ - -/* enumerations from "@filename@" */ -/*** END file-production ***/ - -/*** BEGIN value-header ***/ -GType @enum_name@_get_type (void) G_GNUC_CONST; -#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) -/*** END value-header ***/ - -/*** BEGIN file-tail ***/ -G_END_DECLS - -#endif /* __GUDEV_ENUM_TYPES_H__ */ -/*** END file-tail ***/ diff --git a/src/udev/src/gudev/gudevmarshal.list b/src/udev/src/gudev/gudevmarshal.list deleted file mode 100644 index 7e665999e..000000000 --- a/src/udev/src/gudev/gudevmarshal.list +++ /dev/null @@ -1 +0,0 @@ -VOID:STRING,OBJECT diff --git a/src/udev/src/gudev/gudevprivate.h b/src/udev/src/gudev/gudevprivate.h deleted file mode 100644 index 8866f52b8..000000000 --- a/src/udev/src/gudev/gudevprivate.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2008 David Zeuthen <davidz@redhat.com> - * - * 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 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined (_GUDEV_COMPILATION) && !defined(_GUDEV_INSIDE_GUDEV_H) -#error "Only <gudev/gudev.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __G_UDEV_PRIVATE_H__ -#define __G_UDEV_PRIVATE_H__ - -#include <gudev/gudevtypes.h> - -#include <libudev.h> - -G_BEGIN_DECLS - -GUdevDevice * -_g_udev_device_new (struct udev_device *udevice); - -struct udev *_g_udev_client_get_udev (GUdevClient *client); - -G_END_DECLS - -#endif /* __G_UDEV_PRIVATE_H__ */ diff --git a/src/udev/src/gudev/gudevtypes.h b/src/udev/src/gudev/gudevtypes.h deleted file mode 100644 index 888482783..000000000 --- a/src/udev/src/gudev/gudevtypes.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2008 David Zeuthen <davidz@redhat.com> - * - * 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 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined (_GUDEV_COMPILATION) && !defined(_GUDEV_INSIDE_GUDEV_H) -#error "Only <gudev/gudev.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __G_UDEV_TYPES_H__ -#define __G_UDEV_TYPES_H__ - -#include <gudev/gudevenums.h> -#include <sys/types.h> - -G_BEGIN_DECLS - -typedef struct _GUdevClient GUdevClient; -typedef struct _GUdevDevice GUdevDevice; -typedef struct _GUdevEnumerator GUdevEnumerator; - -/** - * GUdevDeviceNumber: - * - * Corresponds to the standard #dev_t type as defined by POSIX (Until - * bug 584517 is resolved this work-around is needed). - */ -#ifdef _GUDEV_WORK_AROUND_DEV_T_BUG -typedef guint64 GUdevDeviceNumber; /* __UQUAD_TYPE */ -#else -typedef dev_t GUdevDeviceNumber; -#endif - -G_END_DECLS - -#endif /* __G_UDEV_TYPES_H__ */ diff --git a/src/udev/src/gudev/seed-example-enum.js b/src/udev/src/gudev/seed-example-enum.js deleted file mode 100755 index 66206ad80..000000000 --- a/src/udev/src/gudev/seed-example-enum.js +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env seed - -const GLib = imports.gi.GLib; -const GUdev = imports.gi.GUdev; - -function print_device(device) { - print(" initialized: " + device.get_is_initialized()); - print(" usec since initialized: " + device.get_usec_since_initialized()); - print(" subsystem: " + device.get_subsystem()); - print(" devtype: " + device.get_devtype()); - print(" name: " + device.get_name()); - print(" number: " + device.get_number()); - print(" sysfs_path: " + device.get_sysfs_path()); - print(" driver: " + device.get_driver()); - print(" action: " + device.get_action()); - print(" seqnum: " + device.get_seqnum()); - print(" device type: " + device.get_device_type()); - print(" device number: " + device.get_device_number()); - print(" device file: " + device.get_device_file()); - print(" device file symlinks: " + device.get_device_file_symlinks()); - print(" tags: " + device.get_tags()); - var keys = device.get_property_keys(); - for (var n = 0; n < keys.length; n++) { - print(" " + keys[n] + "=" + device.get_property(keys[n])); - } -} - -var client = new GUdev.Client({subsystems: []}); -var enumerator = new GUdev.Enumerator({client: client}); -enumerator.add_match_subsystem('b*') - -var devices = enumerator.execute(); - -for (var n=0; n < devices.length; n++) { - var device = devices[n]; - print_device(device); - print(""); -} diff --git a/src/udev/src/gudev/seed-example.js b/src/udev/src/gudev/seed-example.js deleted file mode 100755 index e2ac324d2..000000000 --- a/src/udev/src/gudev/seed-example.js +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env seed - -// seed example - -const GLib = imports.gi.GLib; -const GUdev = imports.gi.GUdev; - -function print_device (device) { - print (" subsystem: " + device.get_subsystem ()); - print (" devtype: " + device.get_devtype ()); - print (" name: " + device.get_name ()); - print (" number: " + device.get_number ()); - print (" sysfs_path: " + device.get_sysfs_path ()); - print (" driver: " + device.get_driver ()); - print (" action: " + device.get_action ()); - print (" seqnum: " + device.get_seqnum ()); - print (" device type: " + device.get_device_type ()); - print (" device number: " + device.get_device_number ()); - print (" device file: " + device.get_device_file ()); - print (" device file symlinks: " + device.get_device_file_symlinks ()); - print (" foo: " + device.get_sysfs_attr_as_strv ("stat")); - var keys = device.get_property_keys (); - for (var n = 0; n < keys.length; n++) { - print (" " + keys[n] + "=" + device.get_property (keys[n])); - } -} - -function on_uevent (client, action, device) { - print ("action " + action + " on device " + device.get_sysfs_path()); - print_device (device); - print (""); -} - -var client = new GUdev.Client ({subsystems: ["block", "usb/usb_interface"]}); -client.signal.connect ("uevent", on_uevent); - -var block_devices = client.query_by_subsystem ("block"); -for (var n = 0; n < block_devices.length; n++) { - print ("block device: " + block_devices[n].get_device_file ()); -} - -var d; - -d = client.query_by_device_number (GUdev.DeviceType.BLOCK, 0x0810); -if (d == null) { - print ("query_by_device_number 0x810 -> null"); -} else { - print ("query_by_device_number 0x810 -> " + d.get_device_file ()); - dd = d.get_parent_with_subsystem ("usb", null); - print_device (dd); - print ("--------------------------------------------------------------------------"); - while (d != null) { - print_device (d); - print (""); - d = d.get_parent (); - } -} - -d = client.query_by_sysfs_path ("/sys/block/sda/sda1"); -print ("query_by_sysfs_path (\"/sys/block/sda1\") -> " + d.get_device_file ()); - -d = client.query_by_subsystem_and_name ("block", "sda2"); -print ("query_by_subsystem_and_name (\"block\", \"sda2\") -> " + d.get_device_file ()); - -d = client.query_by_device_file ("/dev/sda"); -print ("query_by_device_file (\"/dev/sda\") -> " + d.get_device_file ()); - -d = client.query_by_device_file ("/dev/block/8:0"); -print ("query_by_device_file (\"/dev/block/8:0\") -> " + d.get_device_file ()); - -var mainloop = GLib.main_loop_new (); -GLib.main_loop_run (mainloop); diff --git a/src/udev/src/keymap/.gitignore b/src/udev/src/keymap/.gitignore deleted file mode 100644 index 4567584f4..000000000 --- a/src/udev/src/keymap/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -keyboard-force-release.sh -keys-from-name.gperf -keys-from-name.h -keys-to-name.h -keys.txt diff --git a/src/udev/src/keymap/95-keyboard-force-release.rules b/src/udev/src/keymap/95-keyboard-force-release.rules deleted file mode 100644 index 03d56e8aa..000000000 --- a/src/udev/src/keymap/95-keyboard-force-release.rules +++ /dev/null @@ -1,54 +0,0 @@ -# Set model specific atkbd force_release quirk -# -# Several laptops have hotkeys which don't generate release events, -# which can cause problems with software key repeat. -# The atkbd driver has a quirk handler for generating synthetic -# release events, which can be configured via sysfs since 2.6.32. -# Simply add a file with a list of scancodes for your laptop model -# in /usr/lib/udev/keymaps, and add a rule here. -# If the hotkeys also need a keymap assignment you can copy the -# scancodes from the keymap file, otherwise you can run -# /usr/lib/udev/keymap -i /dev/input/eventX -# on a Linux vt to find out. - -ACTION=="remove", GOTO="force_release_end" -SUBSYSTEM!="serio", GOTO="force_release_end" -KERNEL!="serio*", GOTO="force_release_end" -DRIVER!="atkbd", GOTO="force_release_end" - -ENV{DMI_VENDOR}="$attr{[dmi/id]sys_vendor}" - -ENV{DMI_VENDOR}=="[sS][aA][mM][sS][uU][nN][gG]*", RUN+="keyboard-force-release.sh $devpath samsung-other" -ENV{DMI_VENDOR}=="[sS][aA][mM][sS][uU][nN][gG]*", ATTR{[dmi/id]product_name}=="*90X3A*", RUN+="keyboard-force-release.sh $devpath samsung-90x3a" - -ENV{DMI_VENDOR}=="Dell Inc.", ATTR{[dmi/id]product_name}=="Studio 1557|Studio 1558", RUN+="keyboard-force-release.sh $devpath common-volume-keys" -ENV{DMI_VENDOR}=="Dell Inc.", ATTR{[dmi/id]product_name}=="Latitude E*|Precision M*", RUN+="keyboard-force-release.sh $devpath dell-touchpad" - -ENV{DMI_VENDOR}=="FUJITSU SIEMENS", ATTR{[dmi/id]product_name}=="AMILO Si 1848+u|AMILO Xi 2428", RUN+="keyboard-force-release.sh $devpath common-volume-keys" - -ENV{DMI_VENDOR}=="FOXCONN", ATTR{[dmi/id]product_name}=="QBOOK", RUN+="keyboard-force-release.sh $devpath common-volume-keys" - -ENV{DMI_VENDOR}=="MTC", ATTR{[dmi/id]product_version}=="A0", RUN+="keyboard-force-release.sh $devpath common-volume-keys" - -ENV{DMI_VENDOR}=="PEGATRON CORP.", ATTR{[dmi/id]product_name}=="Spring Peak", RUN+="keyboard-force-release.sh $devpath common-volume-keys" - -ENV{DMI_VENDOR}=="TOSHIBA", ATTR{[dmi/id]product_name}=="Satellite [uU]300*|Satellite Pro [uU]300*|Satellite [uU]305*|SATELLITE [uU]500*", RUN+="keyboard-force-release.sh $devpath common-volume-keys" - -ENV{DMI_VENDOR}=="Viooo Corporation", ATTR{[dmi/id]product_name}=="PT17", RUN+="keyboard-force-release.sh $devpath common-volume-keys" - -# These are all the HP laptops that setup a touchpad toggle key -ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*[pP][aA][vV][iI][lL][iI][oO][nN]*", RUN+="keyboard-force-release.sh $devpath hp-other" -ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*[tT][xX]2*", RUN+="keyboard-force-release.sh $devpath hp-other" -ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*2510p*|*2530p*|HP G60 Notebook PC", RUN+="keyboard-force-release.sh $devpath hp-other" - -ENV{DMI_VENDOR}=="Zepto", ATTR{[dmi/id]product_name}=="Znote 6615WD", RUN+="keyboard-force-release.sh $devpath common-volume-keys" - -ENV{DMI_VENDOR}=="Zepto", ATTR{[dmi/id]product_name}=="Znote", ATTR{[dmi/id]product_version}=="6625WD", RUN+="keyboard-force-release.sh $devpath common-volume-keys" - -ENV{DMI_VENDOR}=="HANNspree", ATTR{[dmi/id]product_name}=="SN10E100", RUN+="keyboard-force-release.sh $devpath common-volume-keys" - -ENV{DMI_VENDOR}=="GIGABYTE", ATTR{[dmi/id]product_name}=="i1520M", RUN+="keyboard-force-release.sh $devpath common-volume-keys" - -ENV{DMI_VENDOR}=="BenQ", ATTR{[dmi/id]product_name}=="*nScreen*", RUN+="keyboard-force-release.sh $devpath common-volume-keys" - -LABEL="force_release_end" diff --git a/src/udev/src/keymap/95-keymap.rules b/src/udev/src/keymap/95-keymap.rules deleted file mode 100644 index bbf311a17..000000000 --- a/src/udev/src/keymap/95-keymap.rules +++ /dev/null @@ -1,170 +0,0 @@ -# Set model specific hotkey keycodes. -# -# Key map overrides can be specified by either giving scancode/keyname pairs -# directly as keymap arguments (if there are just one or two to change), or as -# a file name (in /usr/lib/udev/keymaps), which has to contain scancode/keyname -# pairs. - -ACTION=="remove", GOTO="keyboard_end" -KERNEL!="event*", GOTO="keyboard_end" -ENV{ID_INPUT_KEY}=="", GOTO="keyboard_end" -SUBSYSTEMS=="bluetooth", GOTO="keyboard_end" - -SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id" -SUBSYSTEMS=="usb", GOTO="keyboard_usbcheck" -GOTO="keyboard_modulecheck" - -# -# The following are external USB keyboards -# - -LABEL="keyboard_usbcheck" - -ENV{ID_VENDOR}=="Genius", ENV{ID_MODEL_ID}=="0708", ENV{ID_USB_INTERFACE_NUM}=="01", RUN+="keymap $name genius-slimstar-320" -ENV{ID_VENDOR}=="Logitech*", ATTRS{name}=="Logitech USB Multimedia Keyboard", RUN+="keymap $name logitech-wave" -ENV{ID_VENDOR}=="Logitech*", ATTRS{name}=="Logitech USB Receiver", RUN+="keymap $name logitech-wave-cordless" -# Logitech Cordless Wave Pro looks slightly weird; some hotkeys are coming through the mouse interface -ENV{ID_VENDOR_ID}=="046d", ENV{ID_MODEL_ID}=="c52[9b]", ATTRS{name}=="Logitech USB Receiver", RUN+="keymap $name logitech-wave-pro-cordless" - -ENV{ID_VENDOR}=="Lite-On_Technology_Corp*", ATTRS{name}=="Lite-On Technology Corp. ThinkPad USB Keyboard with TrackPoint", RUN+="keymap $name lenovo-thinkpad-usb-keyboard-trackpoint" -ENV{ID_VENDOR_ID}=="04b3", ENV{ID_MODEL_ID}=="301[89]", RUN+="keymap $name ibm-thinkpad-usb-keyboard-trackpoint" - -ENV{ID_VENDOR}=="Microsoft", ENV{ID_MODEL_ID}=="00db", RUN+="keymap $name 0xc022d zoomin 0xc022e zoomout" - -GOTO="keyboard_end" - -# -# The following are exposed as separate input devices with low key codes, thus -# we need to check their input device product name -# - -LABEL="keyboard_modulecheck" - -ENV{DMI_VENDOR}="$attr{[dmi/id]sys_vendor}" -ENV{DMI_VENDOR}=="", GOTO="keyboard_end" - -ENV{DMI_VENDOR}=="LENOVO*", KERNELS=="input*", ATTRS{name}=="ThinkPad Extra Buttons", RUN+="keymap $name module-lenovo" -ENV{DMI_VENDOR}=="LENOVO*", KERNELS=="input*", ATTRS{name}=="Lenovo ThinkPad SL Series extra buttons", RUN+="keymap $name 0x0E bluetooth" - -ENV{DMI_VENDOR}=="ASUS*", KERNELS=="input*", ATTRS{name}=="Asus Extra Buttons", ATTR{[dmi/id]product_name}=="W3J", RUN+="keymap $name module-asus-w3j" -ENV{DMI_VENDOR}=="ASUS*", KERNELS=="input*", ATTRS{name}=="Eee PC WMI hotkeys|Asus Laptop Support|Asus*WMI*", RUN+="keymap $name 0x6B f21" -ENV{DMI_VENDOR}=="ASUS*", KERNELS=="input*", ATTRS{name}=="Eee PC Hotkey Driver", RUN+="keymap $name 0x37 f21" - -ENV{DMI_VENDOR}=="IBM*", KERNELS=="input*", ATTRS{name}=="ThinkPad Extra Buttons", RUN+="keymap $name module-ibm" -ENV{DMI_VENDOR}=="Sony*", KERNELS=="input*", ATTRS{name}=="Sony Vaio Keys", RUN+="keymap $name module-sony" -ENV{DMI_VENDOR}=="Acer*", KERNELS=="input*", ATTRS{name}=="Acer WMI hotkeys", RUN+="keymap $name 0x82 f21" -ENV{DMI_VENDOR}=="MICRO-STAR*|Micro-Star*", KERNELS=="input*", ATTRS{name}=="MSI Laptop hotkeys", RUN+="keymap $name 0x213 f22 0x214 f23" - -# Older Vaios have some different keys -ENV{DMI_VENDOR}=="Sony*", ATTR{[dmi/id]product_name}=="*PCG-C1*|*PCG-K25*|*PCG-F1*|*PCG-F2*|*PCG-F3*|*PCG-F4*|*PCG-F5*|*PCG-F6*|*PCG-FX*|*PCG-FRV*|*PCG-GR*|*PCG-TR*|*PCG-NV*|*PCG-Z*|*VGN-S360*", ATTRS{name}=="Sony Vaio Keys", RUN+="keymap $name module-sony-old" - -# Some Sony VGN models have yet another one -ENV{DMI_VENDOR}=="Sony*", ATTR{[dmi/id]product_name}=="VGN-AR71*|VGN-FW*|VGN-Z21*", ATTRS{name}=="Sony Vaio Keys", RUN+="keymap $name module-sony-vgn" - - -# -# The following rules belong to standard i8042 AT keyboard with high key codes. -# - -DRIVERS=="atkbd", GOTO="keyboard_vendorcheck" -GOTO="keyboard_end" - -LABEL="keyboard_vendorcheck" - -ENV{DMI_VENDOR}=="Dell*", RUN+="keymap $name dell" -ENV{DMI_VENDOR}=="Dell*", ATTR{[dmi/id]product_name}=="Inspiron 910|Inspiron 1010|Inspiron 1011|Inspiron 1012|Inspiron 1110|Inspiron 1210", RUN+="keymap $name 0x84 wlan" -ENV{DMI_VENDOR}=="Dell*", ATTR{[dmi/id]product_name}=="Latitude XT2", RUN+="keymap $name dell-latitude-xt2" - -ENV{DMI_VENDOR}=="Compaq*", ATTR{[dmi/id]product_name}=="*E500*|*Evo N*", RUN+="keymap $name compaq-e_evo" - -ENV{DMI_VENDOR}=="LENOVO*", ATTR{[dmi/id]product_version}=="*3000*", RUN+="keymap $name lenovo-3000" -ENV{DMI_VENDOR}=="LENOVO*", ATTR{[dmi/id]product_version}=="ThinkPad X6*", ATTR{[dmi/id]product_version}=="* Tablet", RUN+="keymap $name lenovo-thinkpad_x6_tablet" -ENV{DMI_VENDOR}=="LENOVO*", ATTR{[dmi/id]product_version}=="ThinkPad X2[02]* Tablet*", ATTR{[dmi/id]product_version}=="* Tablet", RUN+="keymap $name lenovo-thinkpad_x200_tablet" -ENV{DMI_VENDOR}=="LENOVO*", ATTR{[dmi/id]product_version}=="*IdeaPad*", RUN+="keymap $name lenovo-ideapad" -ENV{DMI_VENDOR}=="LENOVO*", ATTR{[dmi/id]product_name}=="S10-*", RUN+="keymap $name lenovo-ideapad" -ENV{DMI_VENDOR}=="LENOVO", ATTR{[dmi/id]product_version}=="*IdeaPad Y550*", RUN+="keymap $name 0x95 media 0xA3 play" - -ENV{DMI_VENDOR}=="Hewlett-Packard*", RUN+="keymap $name hewlett-packard" -ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*[tT][aA][bB][lL][eE][tT]*", RUN+="keymap $name hewlett-packard-tablet" -ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*[pP][aA][vV][iI][lL][iI][oO][nN]*", RUN+="keymap $name hewlett-packard-pavilion" -ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*Compaq*|*EliteBook*|*2230s*", RUN+="keymap $name hewlett-packard-compaq_elitebook" -ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*2510p*|*2530p*|HP G60 Notebook PC", RUN+="keymap $name hewlett-packard-2510p_2530p" -ENV{DMI_VENDOR}=="Hewlett-Packard*", ATTR{[dmi/id]product_name}=="*[tT][xX]2*", RUN+="keymap $name hewlett-packard-tx2" -ENV{DMI_VENDOR}=="Hewlett-Packard", ATTR{[dmi/id]product_name}=="Presario 2100*", RUN+="keymap $name hewlett-packard-presario-2100" -ENV{DMI_VENDOR}=="Hewlett-Packard", ATTR{[dmi/id]product_name}=="HP G62 Notebook PC", RUN+="keymap $name 0xB2 www" -ENV{DMI_VENDOR}=="Hewlett-Packard", ATTR{[dmi/id]product_name}=="HP ProBook*", RUN+="keymap $name 0xF8 rfkill" -# HP Pavillion dv6315ea has empty DMI_VENDOR -ATTR{[dmi/id]board_vendor}=="Quanta", ATTR{[dmi/id]board_name}=="30B7", ATTR{[dmi/id]board_version}=="65.2B", RUN+="keymap $name 0x88 media" # "quick play - -# Gateway clone of Acer Aspire One AOA110/AOA150 -ENV{DMI_VENDOR}=="Gateway*", ATTR{[dmi/id]product_name}=="*AOA1*", RUN+="keymap $name acer" - -ENV{DMI_VENDOR}=="Acer*", RUN+="keymap $name acer" -ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="Extensa*", ATTR{[dmi/id]product_name}=="*5210*|*5220*|*5610*|*5620*|*5720*", RUN+="keymap $name 0xEE screenlock" -ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="TravelMate*C3[01]0*", RUN+="keymap $name acer-travelmate_c300" -ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="TravelMate*6292*|TravelMate*8471*|TravelMate*4720*|TravelMate*7720*|Aspire 1810T*|AO751h|AO531h", RUN+="keymap $name 0xD9 bluetooth" -ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="TravelMate*4720*", RUN+="keymap $name 0xB2 www 0xEE screenlock" -ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="TravelMate 6593|Aspire 1640", RUN+="keymap $name 0xB2 www 0xEE screenlock" -ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="Aspire 6920", RUN+="keymap $name acer-aspire_6920" -ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="Aspire 5920G", RUN+="keymap $name acer-aspire_5920g" -ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="Aspire 5720*", RUN+="keymap $name acer-aspire_5720" -ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_name}=="Aspire 8930", RUN+="keymap $name acer-aspire_8930" -ENV{DMI_VENDOR}=="Acer*", ATTR{[dmi/id]product_serial}=="ZG8*", RUN+="keymap $name acer-aspire_5720" - -ENV{DMI_VENDOR}=="*BenQ*", ATTR{[dmi/id]product_name}=="*Joybook R22*", RUN+="keymap $name 0x6E wlan" - -ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="*AMILO Pro V3205*", RUN+="keymap $name fujitsu-amilo_pro_v3205" -ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="*AMILO Pa 2548*", RUN+="keymap $name fujitsu-amilo_pa_2548" -ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="*ESPRIMO Mobile V5*", RUN+="keymap $name fujitsu-esprimo_mobile_v5" -ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="*ESPRIMO Mobile V6*", RUN+="keymap $name fujitsu-esprimo_mobile_v6" -ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="*AMILO Pro Edition V3505*", RUN+="keymap $name fujitsu-amilo_pro_edition_v3505" -ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="*Amilo Si 1520*", RUN+="keymap $name fujitsu-amilo_si_1520" -ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="AMILO*M*", RUN+="keymap $name 0x97 prog2 0x9F prog1" -ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="Amilo Li 1718", RUN+="keymap $name 0xD6 wlan" -ENV{DMI_VENDOR}=="FUJITSU*", ATTR{[dmi/id]product_name}=="AMILO Li 2732", RUN+="keymap $name fujitsu-amilo_li_2732" - -ENV{DMI_VENDOR}=="LG*", ATTR{[dmi/id]product_name}=="*X110*", RUN+="keymap $name lg-x110" - -ENV{DMI_VENDOR}=="MEDION*", ATTR{[dmi/id]product_name}=="*FID2060*", RUN+="keymap $name medion-fid2060" -ENV{DMI_VENDOR}=="MEDIONNB", ATTR{[dmi/id]product_name}=="A555*", RUN+="keymap $name medionnb-a555" - -ENV{DMI_VENDOR}=="MICRO-STAR*|Micro-Star*", RUN+="keymap $name micro-star" - -# some MSI models generate ACPI/input events on the LNXVIDEO input devices, -# plus some extra synthesized ones on atkbd as an echo of actually changing the -# brightness; so ignore those atkbd ones, to avoid loops -ENV{DMI_VENDOR}=="MICRO-STAR*", ATTR{[dmi/id]product_name}=="*U-100*|*U100*|*N033", RUN+="keymap $name 0xF7 reserved 0xF8 reserved" - -ENV{DMI_VENDOR}=="INVENTEC", ATTR{[dmi/id]product_name}=="SYMPHONY 6.0/7.0", RUN+="keymap $name inventec-symphony_6.0_7.0" - -ENV{DMI_VENDOR}=="MAXDATA", ATTR{[dmi/id]product_name}=="Pro 7000*", RUN+="keymap $name maxdata-pro_7000" - -ENV{DMI_VENDOR}=="[sS][aA][mM][sS][uU][nN][gG]*", RUN+="keymap $name samsung-other" -ENV{DMI_VENDOR}=="[sS][aA][mM][sS][uU][nN][gG]*", ATTR{[dmi/id]product_name}=="*SX20S*", RUN+="keymap $name samsung-sx20s" -ENV{DMI_VENDOR}=="[sS][aA][mM][sS][uU][nN][gG]*", ATTR{[dmi/id]product_name}=="SQ1US", RUN+="keymap $name samsung-sq1us" -ENV{DMI_VENDOR}=="[sS][aA][mM][sS][uU][nN][gG]*", ATTR{[dmi/id]product_name}=="*700Z*", RUN+="keymap $name 0xBA ejectcd 0x96 keyboardbrightnessup 0x97 keyboardbrightnessdown" -ENV{DMI_VENDOR}=="[sS][aA][mM][sS][uU][nN][gG]*", ATTR{[dmi/id]product_name}=="*90X3A*", RUN+="keymap $name samsung-90x3a" - -ENV{DMI_VENDOR}=="TOSHIBA", ATTR{[dmi/id]product_name}=="SATELLITE A100", RUN+="keymap $name toshiba-satellite_a100" -ENV{DMI_VENDOR}=="TOSHIBA", ATTR{[dmi/id]product_name}=="Satellite A110", RUN+="keymap $name toshiba-satellite_a110" -ENV{DMI_VENDOR}=="TOSHIBA", ATTR{[dmi/id]product_name}=="Satellite M30X", RUN+="keymap $name toshiba-satellite_m30x" - -ENV{DMI_VENDOR}=="OQO Inc.*", ATTR{[dmi/id]product_name}=="OQO Model 2*", RUN+="keymap $name oqo-model2" - -ENV{DMI_VENDOR}=="ONKYO CORPORATION", ATTR{[dmi/id]product_name}=="ONKYOPC", RUN+="keymap $name onkyo" - -ENV{DMI_VENDOR}=="ASUS", RUN+="keymap $name asus" - -ENV{DMI_VENDOR}=="VIA", ATTR{[dmi/id]product_name}=="K8N800", ATTR{[dmi/id]product_version}=="VT8204B", RUN+="keymap $name 0x81 prog1" - -ENV{DMI_VENDOR}=="Zepto", ATTR{[dmi/id]product_name}=="Znote", ATTR{[dmi/id]product_version}=="62*|63*", RUN+="keymap $name zepto-znote" - -ENV{DMI_VENDOR}=="Everex", ATTR{[dmi/id]product_name}=="XT5000*", RUN+="keymap $name everex-xt5000" - -ENV{DMI_VENDOR}=="COMPAL", ATTR{[dmi/id]product_name}=="HEL80I", RUN+="keymap $name 0x84 wlan" - -ENV{DMI_VENDOR}=="OLPC", ATTR{[dmi/id]product_name}=="XO", RUN+="keymap $name olpc-xo" - -ENV{DMI_VENDOR}=="Alienware*", ATTR{[dmi/id]product_name}=="M14xR1", RUN+="keymap $name 0x8A ejectcd" - -LABEL="keyboard_end" diff --git a/src/udev/src/keymap/README.keymap.txt b/src/udev/src/keymap/README.keymap.txt deleted file mode 100644 index 52d50ed2d..000000000 --- a/src/udev/src/keymap/README.keymap.txt +++ /dev/null @@ -1,101 +0,0 @@ -= The udev keymap tool = - -== Introduction == - -This udev extension configures computer model specific key mappings. This is -particularly necessary for the non-standard extra keys found on many laptops, -such as "brightness up", "next song", "www browser", or "suspend". Often these -are accessed with the Fn key. - -Every key produces a "scan code", which is highly vendor/model specific for the -nonstandard keys. This tool maintains mappings for these scan codes to standard -"key codes", which denote the "meaning" of the key. The key codes are defined -in /usr/include/linux/input.h. - -If some of your keys on your keyboard are not working at all, or produce the -wrong effect, then a very likely cause of this is that the scan code -> key -code mapping is incorrect on your computer. - -== Structure == - -udev-keymap consists of the following parts: - - keymaps/*:: mappings of scan codes to key code names - - 95-keymap.rules:: udev rules for mapping system vendor/product names and - input module names to one of the keymaps above - - keymap:: manipulate an evdev input device: - * write a key map file into a device (used by udev rules) - * dump current scan → key code mapping - * interactively display scan and key codes of pressed keys - - findkeyboards:: display evdev input devices which belong to actual keyboards, - i. e. those suitable for the keymap program - - fdi2rules.py:: convert hal keymap FDIs into udev rules and key map files - (Please note that this is far from perfect, since the mapping between fdi and - udev rules is not straightforward, and impossible in some cases.) - -== Fixing broken keys == - -In order to make a broken key work on your system and send it back to upstream -for inclusion you need to do the following steps: - - 1. Find the keyboard device. - - Run /usr/lib/udev/findkeyboards. This should always give you an "AT - keyboard" and possibly a "module". Some laptops (notably Thinkpads, Sonys, and - Acers) have multimedia/function keys on a separate input device instead of the - primary keyboard. The keyboard device should have a name like "input/event3". - In the following commands, the name will be written as "input/eventX" (replace - X with the appropriate number). - - 2. Find broken scan codes: - - sudo /usr/lib/udev/keymap -i input/eventX - - Press all multimedia/function keys and check if the key name that gets printed - out is plausible. If it is unknown or wrong, write down the scan code (looks - like "0x1E") and the intended functionality of this key. Look in - /usr/include/linux/input.h for an available KEY_XXXXX constant which most - closely approximates this functionality and write it down as the new key code. - - For example, you might press a key labeled "web browser" which currently - produces "unknown". Note down this: - - 0x1E www # Fn+F2 web browser - - Repeat that for all other keys. Write the resulting list into a file. Look at - /usr/lib/udev/keymaps/ for existing key map files and make sure that you use the - same structure. - - If the key only ever works once and then your keyboard (or the entire desktop) - gets stuck for a long time, then it is likely that the BIOS fails to send a - corresponding "key release" event after the key press event. Please note down - this case as well, as it can be worked around in - /usr/lib/udev/keymaps/95-keyboard-force-release.rules . - - 3. Find out your system vendor and product: - - cat /sys/class/dmi/id/sys_vendor - cat /sys/class/dmi/id/product_name - - 4. Generate a device dump with "udevadm info --export-db > /tmp/udev-db.txt". - - 6. Send the system vendor/product names, the key mapping from step 2, - and /tmp/udev-db.txt from step 4 to the linux-hotplug@vger.kernel.org mailing - list, so that they can be included in the next release. - -For local testing, copy your map file to /usr/lib/udev/keymaps/ with an appropriate -name, and add an appropriate udev rule to /usr/lib/udev/rules.d/95-keymap.rules: - - * If you selected an "AT keyboard", add the rule to the section after - 'LABEL="keyboard_vendorcheck"'. - - * If you selected a "module", add the rule to the top section where the - "ThinkPad Extra Buttons" are. - -== Author == - -keymap is written and maintained by Martin Pitt <martin.pitt@ubuntu.com>. diff --git a/src/udev/src/keymap/check-keymaps.sh b/src/udev/src/keymap/check-keymaps.sh deleted file mode 100755 index 405168c66..000000000 --- a/src/udev/src/keymap/check-keymaps.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -# check that all key names in keymaps/* are known in <linux/input.h> -# and that all key maps listed in the rules are valid and present in -# Makefile.am -SRCDIR=${1:-.} -KEYLIST=${2:-src/keymap/keys.txt} -KEYMAPS_DIR=$SRCDIR/src/keymap/keymaps -RULES=$SRCDIR/src/keymap/95-keymap.rules - -[ -e "$KEYLIST" ] || { - echo "need $KEYLIST please build first" >&2 - exit 1 -} - -missing=$(join -v 2 <(awk '{print tolower(substr($1,5))}' $KEYLIST | sort -u) \ - <(grep -hv '^#' ${KEYMAPS_DIR}/*| awk '{print $2}' | sort -u)) -[ -z "$missing" ] || { - echo "ERROR: unknown key names in src/keymap/keymaps/*:" >&2 - echo "$missing" >&2 - exit 1 -} - -# check that all maps referred to in $RULES exist -maps=$(sed -rn '/keymap \$name/ { s/^.*\$name ([^"[:space:]]+).*$/\1/; p }' $RULES) -for m in $maps; do - # ignore inline mappings - [ "$m" = "${m#0x}" ] || continue - - [ -e ${KEYMAPS_DIR}/$m ] || { - echo "ERROR: unknown map name in $RULES: $m" >&2 - exit 1 - } - grep -q "src/keymap/keymaps/$m\>" $SRCDIR/Makefile.am || { - echo "ERROR: map file $m is not added to Makefile.am" >&2 - exit 1 - } -done diff --git a/src/udev/src/keymap/findkeyboards b/src/udev/src/keymap/findkeyboards deleted file mode 100755 index 9ce27429b..000000000 --- a/src/udev/src/keymap/findkeyboards +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/sh -e -# Find "real" keyboard devices and print their device path. -# Author: Martin Pitt <martin.pitt@ubuntu.com> -# -# Copyright (C) 2009, Canonical Ltd. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program 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 -# General Public License for more details. - -# returns OK if $1 contains $2 -strstr() { - [ "${1#*$2*}" != "$1" ] -} - -# returns OK if $1 contains $2 at the beginning -str_starts() { - [ "${1#$2*}" != "$1" ] -} - -str_line_starts() { - while read a; do str_starts "$a" "$1" && return 0;done - return 1; -} - -# print a list of input devices which are keyboard-like -keyboard_devices() { - # standard AT keyboard - for dev in `udevadm trigger --dry-run --verbose --property-match=ID_INPUT_KEYBOARD=1`; do - walk=`udevadm info --attribute-walk --path=$dev` - env=`udevadm info --query=env --path=$dev` - # filter out non-event devices, such as the parent input devices which have no devnode - if ! echo "$env" | str_line_starts 'DEVNAME='; then - continue - fi - if strstr "$walk" 'DRIVERS=="atkbd"'; then - echo -n 'AT keyboard: ' - elif echo "$env" | str_line_starts 'ID_USB_DRIVER=usbhid'; then - echo -n 'USB keyboard: ' - else - echo -n 'Unknown type: ' - fi - udevadm info --query=name --path=$dev - done - - # modules - module=$(udevadm trigger --verbose --dry-run --subsystem-match=input --attr-match=name='*Extra Buttons') - module="$module - $(udevadm trigger --verbose --dry-run --subsystem-match=input --attr-match=name='*extra buttons')" - module="$module - $(udevadm trigger --verbose --dry-run --subsystem-match=input --attr-match=name='Sony Vaio Keys')" - for m in $module; do - for evdev in $m/event*/dev; do - if [ -e "$evdev" ]; then - echo -n 'module: ' - udevadm info --query=name --path=${evdev%%/dev} - fi - done - done -} - -keyboard_devices diff --git a/src/udev/src/keymap/force-release-maps/common-volume-keys b/src/udev/src/keymap/force-release-maps/common-volume-keys deleted file mode 100644 index 3a7654d73..000000000 --- a/src/udev/src/keymap/force-release-maps/common-volume-keys +++ /dev/null @@ -1,3 +0,0 @@ -0xa0 #mute -0xae #volume down -0xb0 #volume up diff --git a/src/udev/src/keymap/force-release-maps/dell-touchpad b/src/udev/src/keymap/force-release-maps/dell-touchpad deleted file mode 100644 index 18e9bdee6..000000000 --- a/src/udev/src/keymap/force-release-maps/dell-touchpad +++ /dev/null @@ -1 +0,0 @@ -0x9E diff --git a/src/udev/src/keymap/force-release-maps/hp-other b/src/udev/src/keymap/force-release-maps/hp-other deleted file mode 100644 index 662137009..000000000 --- a/src/udev/src/keymap/force-release-maps/hp-other +++ /dev/null @@ -1,3 +0,0 @@ -# list of scancodes (hex or decimal), optional comment -0xd8 # Touchpad off -0xd9 # Touchpad on diff --git a/src/udev/src/keymap/force-release-maps/samsung-90x3a b/src/udev/src/keymap/force-release-maps/samsung-90x3a deleted file mode 100644 index 65707effb..000000000 --- a/src/udev/src/keymap/force-release-maps/samsung-90x3a +++ /dev/null @@ -1,6 +0,0 @@ -# list of scancodes (hex or decimal), optional comment -0xCE # Fn+F8 keyboard backlit up -0x8D # Fn+F7 keyboard backlit down -0x97 # Fn+F12 wifi on/off -0x96 # Fn+F1 performance mode (?) -0xD5 # Fn+F6 battery life extender diff --git a/src/udev/src/keymap/force-release-maps/samsung-other b/src/udev/src/keymap/force-release-maps/samsung-other deleted file mode 100644 index c51123a0b..000000000 --- a/src/udev/src/keymap/force-release-maps/samsung-other +++ /dev/null @@ -1,10 +0,0 @@ -# list of scancodes (hex or decimal), optional comment -0x82 # Fn+F4 CRT/LCD -0x83 # Fn+F2 battery -0x84 # Fn+F5 backlight on/off -0x86 # Fn+F9 WLAN -0x88 # Fn-Up brightness up -0x89 # Fn-Down brightness down -0xB3 # Fn+F8 switch power mode (battery/dynamic/performance) -0xF7 # Fn+F10 Touchpad on -0xF9 # Fn+F10 Touchpad off diff --git a/src/udev/src/keymap/keyboard-force-release.sh.in b/src/udev/src/keymap/keyboard-force-release.sh.in deleted file mode 100755 index dd040cebc..000000000 --- a/src/udev/src/keymap/keyboard-force-release.sh.in +++ /dev/null @@ -1,22 +0,0 @@ -#!@rootprefix@/bin/sh -e -# read list of scancodes, convert hex to decimal and -# append to the atkbd force_release sysfs attribute -# $1 sysfs devpath for serioX -# $2 file with scancode list (hex or dec) - -case "$2" in - /*) scf="$2" ;; - *) scf="@pkglibexecdir@/keymaps/force-release/$2" ;; -esac - -read attr <"/sys/$1/force_release" -while read scancode dummy; do - case "$scancode" in - \#*) ;; - *) - scancode=$(($scancode)) - attr="$attr${attr:+,}$scancode" - ;; - esac -done <"$scf" -echo "$attr" >"/sys/$1/force_release" diff --git a/src/udev/src/keymap/keymap.c b/src/udev/src/keymap/keymap.c deleted file mode 100644 index 92ec67b3a..000000000 --- a/src/udev/src/keymap/keymap.c +++ /dev/null @@ -1,447 +0,0 @@ -/* - * keymap - dump keymap of an evdev device or set a new keymap from a file - * - * Based on keyfuzz by Lennart Poettering <mzqrovna@0pointer.net> - * Adapted for udev-extras by Martin Pitt <martin.pitt@ubuntu.com> - * - * Copyright (C) 2006, Lennart Poettering - * Copyright (C) 2009, Canonical Ltd. - * - * keymap is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * keymap 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with keymap; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdint.h> -#include <ctype.h> -#include <unistd.h> -#include <errno.h> -#include <limits.h> -#include <fcntl.h> -#include <getopt.h> -#include <sys/ioctl.h> -#include <linux/limits.h> -#include <linux/input.h> - -const struct key* lookup_key (const char *str, unsigned int len); - -#include "keys-from-name.h" -#include "keys-to-name.h" - -#define MAX_SCANCODES 1024 - -static int evdev_open(const char *dev) -{ - int fd; - char fn[PATH_MAX]; - - if (strncmp(dev, "/dev", 4) != 0) { - snprintf(fn, sizeof(fn), "/dev/%s", dev); - dev = fn; - } - - if ((fd = open(dev, O_RDWR)) < 0) { - fprintf(stderr, "error open('%s'): %m\n", dev); - return -1; - } - return fd; -} - -static int evdev_get_keycode(int fd, int scancode, int e) -{ - int codes[2]; - - codes[0] = scancode; - if (ioctl(fd, EVIOCGKEYCODE, codes) < 0) { - if (e && errno == EINVAL) { - return -2; - } else { - fprintf(stderr, "EVIOCGKEYCODE: %m\n"); - return -1; - } - } - return codes[1]; -} - -static int evdev_set_keycode(int fd, int scancode, int keycode) -{ - int codes[2]; - - codes[0] = scancode; - codes[1] = keycode; - - if (ioctl(fd, EVIOCSKEYCODE, codes) < 0) { - fprintf(stderr, "EVIOCSKEYCODE: %m\n"); - return -1; - } - return 0; -} - -static int evdev_driver_version(int fd, char *v, size_t l) -{ - int version; - - if (ioctl(fd, EVIOCGVERSION, &version)) { - fprintf(stderr, "EVIOCGVERSION: %m\n"); - return -1; - } - - snprintf(v, l, "%i.%i.%i.", version >> 16, (version >> 8) & 0xff, version & 0xff); - return 0; -} - -static int evdev_device_name(int fd, char *n, size_t l) -{ - if (ioctl(fd, EVIOCGNAME(l), n) < 0) { - fprintf(stderr, "EVIOCGNAME: %m\n"); - return -1; - } - return 0; -} - -/* Return a lower-case string with KEY_ prefix removed */ -static const char* format_keyname(const char* key) { - static char result[101]; - const char* s; - int len; - - for (s = key+4, len = 0; *s && len < 100; ++len, ++s) - result[len] = tolower(*s); - result[len] = '\0'; - return result; -} - -static int dump_table(int fd) { - char version[256], name[256]; - int scancode, r = -1; - - if (evdev_driver_version(fd, version, sizeof(version)) < 0) - goto fail; - - if (evdev_device_name(fd, name, sizeof(name)) < 0) - goto fail; - - printf("### evdev %s, driver '%s'\n", version, name); - - r = 0; - for (scancode = 0; scancode < MAX_SCANCODES; scancode++) { - int keycode; - - if ((keycode = evdev_get_keycode(fd, scancode, 1)) < 0) { - if (keycode == -2) - continue; - r = -1; - break; - } - - if (keycode < KEY_MAX && key_names[keycode]) - printf("0x%03x %s\n", scancode, format_keyname(key_names[keycode])); - else - printf("0x%03x 0x%03x\n", scancode, keycode); - } -fail: - return r; -} - -static void set_key(int fd, const char* scancode_str, const char* keyname) -{ - unsigned scancode; - char *endptr; - char t[105] = "KEY_UNKNOWN"; - const struct key *k; - - scancode = (unsigned) strtol(scancode_str, &endptr, 0); - if (*endptr != '\0') { - fprintf(stderr, "ERROR: Invalid scancode\n"); - exit(1); - } - - snprintf(t, sizeof(t), "KEY_%s", keyname); - - if (!(k = lookup_key(t, strlen(t)))) { - fprintf(stderr, "ERROR: Unknown key name '%s'\n", keyname); - exit(1); - } - - if (evdev_set_keycode(fd, scancode, k->id) < 0) - fprintf(stderr, "setting scancode 0x%2X to key code %i failed\n", - scancode, k->id); - else - printf("setting scancode 0x%2X to key code %i\n", - scancode, k->id); -} - -static int merge_table(int fd, FILE *f) { - int r = 0; - int line = 0; - - while (!feof(f)) { - char s[256], *p; - int scancode, new_keycode, old_keycode; - - if (!fgets(s, sizeof(s), f)) - break; - - line++; - p = s+strspn(s, "\t "); - if (*p == '#' || *p == '\n') - continue; - - if (sscanf(p, "%i %i", &scancode, &new_keycode) != 2) { - char t[105] = "KEY_UNKNOWN"; - const struct key *k; - - if (sscanf(p, "%i %100s", &scancode, t+4) != 2) { - fprintf(stderr, "WARNING: Parse failure at line %i, ignoring.\n", line); - r = -1; - continue; - } - - if (!(k = lookup_key(t, strlen(t)))) { - fprintf(stderr, "WARNING: Unknown key '%s' at line %i, ignoring.\n", t, line); - r = -1; - continue; - } - - new_keycode = k->id; - } - - - if ((old_keycode = evdev_get_keycode(fd, scancode, 0)) < 0) { - r = -1; - goto fail; - } - - if (evdev_set_keycode(fd, scancode, new_keycode) < 0) { - r = -1; - goto fail; - } - - if (new_keycode != old_keycode) - fprintf(stderr, "Remapped scancode 0x%02x to 0x%02x (prior: 0x%02x)\n", - scancode, new_keycode, old_keycode); - } -fail: - fclose(f); - return r; -} - - -/* read one event; return 1 if valid */ -static int read_event(int fd, struct input_event* ev) -{ - int ret; - ret = read(fd, ev, sizeof(struct input_event)); - - if (ret < 0) { - perror("read"); - return 0; - } - if (ret != sizeof(struct input_event)) { - fprintf(stderr, "did not get enough data for event struct, aborting\n"); - return 0; - } - - return 1; -} - -static void print_key(uint32_t scancode, uint16_t keycode, int has_scan, int has_key) -{ - const char *keyname; - - /* ignore key release events */ - if (has_key == 1) - return; - - if (has_key == 0 && has_scan != 0) { - fprintf(stderr, "got scan code event 0x%02X without a key code event\n", - scancode); - return; - } - - if (has_scan != 0) - printf("scan code: 0x%02X ", scancode); - else - printf("(no scan code received) "); - - keyname = key_names[keycode]; - if (keyname != NULL) - printf("key code: %s\n", format_keyname(keyname)); - else - printf("key code: %03X\n", keycode); -} - -static void interactive(int fd) -{ - struct input_event ev; - uint32_t last_scan = 0; - uint16_t last_key = 0; - int has_scan; /* boolean */ - int has_key; /* 0: none, 1: release, 2: press */ - - /* grab input device */ - ioctl(fd, EVIOCGRAB, 1); - puts("Press ESC to finish, or Control-C if this device is not your primary keyboard"); - - has_scan = has_key = 0; - while (read_event(fd, &ev)) { - /* Drivers usually send the scan code first, then the key code, - * then a SYN. Some drivers (like thinkpad_acpi) send the key - * code first, and some drivers might not send SYN events, so - * keep a robust state machine which can deal with any of those - */ - - if (ev.type == EV_MSC && ev.code == MSC_SCAN) { - if (has_scan) { - fputs("driver did not send SYN event in between key events; previous event:\n", - stderr); - print_key(last_scan, last_key, has_scan, has_key); - has_key = 0; - } - - last_scan = ev.value; - has_scan = 1; - /*printf("--- got scan %u; has scan %i key %i\n", last_scan, has_scan, has_key); */ - } - else if (ev.type == EV_KEY) { - if (has_key) { - fputs("driver did not send SYN event in between key events; previous event:\n", - stderr); - print_key(last_scan, last_key, has_scan, has_key); - has_scan = 0; - } - - last_key = ev.code; - has_key = 1 + ev.value; - /*printf("--- got key %hu; has scan %i key %i\n", last_key, has_scan, has_key);*/ - - /* Stop on ESC */ - if (ev.code == KEY_ESC && ev.value == 0) - break; - } - else if (ev.type == EV_SYN) { - /*printf("--- got SYN; has scan %i key %i\n", has_scan, has_key);*/ - print_key(last_scan, last_key, has_scan, has_key); - - has_scan = has_key = 0; - } - - } - - /* release input device */ - ioctl(fd, EVIOCGRAB, 0); -} - -static void help(int error) -{ - const char* h = "Usage: keymap <event device> [<map file>]\n" - " keymap <event device> scancode keyname [...]\n" - " keymap -i <event device>\n"; - if (error) { - fputs(h, stderr); - exit(2); - } else { - fputs(h, stdout); - exit(0); - } -} - -int main(int argc, char **argv) -{ - static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "interactive", no_argument, NULL, 'i' }, - {} - }; - int fd = -1; - int opt_interactive = 0; - int i; - - while (1) { - int option; - - option = getopt_long(argc, argv, "hi", options, NULL); - if (option == -1) - break; - - switch (option) { - case 'h': - help(0); - - case 'i': - opt_interactive = 1; - break; - default: - return 1; - } - } - - if (argc < optind+1) - help (1); - - if ((fd = evdev_open(argv[optind])) < 0) - return 3; - - /* one argument (device): dump or interactive */ - if (argc == optind+1) { - if (opt_interactive) - interactive(fd); - else - dump_table(fd); - return 0; - } - - /* two arguments (device, mapfile): set map file */ - if (argc == optind+2) { - const char *filearg = argv[optind+1]; - if (strchr(filearg, '/')) { - /* Keymap file argument is a path */ - FILE *f = fopen(filearg, "r"); - if (f) - merge_table(fd, f); - else - perror(filearg); - } else { - /* Keymap file argument is a filename */ - /* Open override file if present, otherwise default file */ - char keymap_path[PATH_MAX]; - snprintf(keymap_path, sizeof(keymap_path), "%s%s", SYSCONFDIR "/udev/keymaps/", filearg); - FILE *f = fopen(keymap_path, "r"); - if (f) { - merge_table(fd, f); - } else { - snprintf(keymap_path, sizeof(keymap_path), "%s%s", PKGLIBEXECDIR "/keymaps/", filearg); - f = fopen(keymap_path, "r"); - if (f) - merge_table(fd, f); - else - perror(keymap_path); - } - } - return 0; - } - - /* more arguments (device, scancode/keyname pairs): set keys directly */ - if ((argc - optind - 1) % 2 == 0) { - for (i = optind+1; i < argc; i += 2) - set_key(fd, argv[i], argv[i+1]); - return 0; - } - - /* invalid number of arguments */ - help(1); - return 1; /* not reached */ -} diff --git a/src/udev/src/keymap/keymaps/acer b/src/udev/src/keymap/keymaps/acer deleted file mode 100644 index 4e7c297de..000000000 --- a/src/udev/src/keymap/keymaps/acer +++ /dev/null @@ -1,22 +0,0 @@ -0xA5 help # Fn+F1 -0xA6 setup # Fn+F2 Acer eSettings -0xA7 battery # Fn+F3 Power Management -0xA9 switchvideomode # Fn+F5 -0xB3 euro -0xB4 dollar -0xCE brightnessup # Fn+Right -0xD4 bluetooth # (toggle) off-to-on -0xD5 wlan # (toggle) on-to-off -0xD6 wlan # (toggle) off-to-on -0xD7 bluetooth # (toggle) on-to-off -0xD8 bluetooth # (toggle) off-to-on -0xD9 brightnessup # Fn+Right -0xEE brightnessup # Fn+Right -0xEF brightnessdown # Fn+Left -0xF1 f22 # Fn+F7 Touchpad toggle (off-to-on) -0xF2 f23 # Fn+F7 Touchpad toggle (on-to-off) -0xF3 prog2 # "P2" programmable button -0xF4 prog1 # "P1" programmable button -0xF5 presentation -0xF8 fn -0xF9 f23 # Launch NTI shadow diff --git a/src/udev/src/keymap/keymaps/acer-aspire_5720 b/src/udev/src/keymap/keymaps/acer-aspire_5720 deleted file mode 100644 index 1496d63a5..000000000 --- a/src/udev/src/keymap/keymaps/acer-aspire_5720 +++ /dev/null @@ -1,4 +0,0 @@ -0x84 bluetooth # sent when bluetooth module missing, and key pressed -0x92 media # acer arcade -0xD4 bluetooth # bluetooth on -0xD9 bluetooth # bluetooth off diff --git a/src/udev/src/keymap/keymaps/acer-aspire_5920g b/src/udev/src/keymap/keymaps/acer-aspire_5920g deleted file mode 100644 index 633c4e854..000000000 --- a/src/udev/src/keymap/keymaps/acer-aspire_5920g +++ /dev/null @@ -1,5 +0,0 @@ -0x8A media -0x92 media -0xA6 setup -0xB2 www -0xD9 bluetooth # (toggle) on-to-off diff --git a/src/udev/src/keymap/keymaps/acer-aspire_6920 b/src/udev/src/keymap/keymaps/acer-aspire_6920 deleted file mode 100644 index 699c954b4..000000000 --- a/src/udev/src/keymap/keymaps/acer-aspire_6920 +++ /dev/null @@ -1,5 +0,0 @@ -0xD9 bluetooth # (toggle) on-to-off -0x92 media -0x9E back -0x83 rewind -0x89 fastforward diff --git a/src/udev/src/keymap/keymaps/acer-aspire_8930 b/src/udev/src/keymap/keymaps/acer-aspire_8930 deleted file mode 100644 index fb27bfb4f..000000000 --- a/src/udev/src/keymap/keymaps/acer-aspire_8930 +++ /dev/null @@ -1,5 +0,0 @@ -0xCA prog3 # key 'HOLD' on cine dash media console -0x83 rewind -0x89 fastforward -0x92 media # key 'ARCADE' on cine dash media console -0x9E back diff --git a/src/udev/src/keymap/keymaps/acer-travelmate_c300 b/src/udev/src/keymap/keymaps/acer-travelmate_c300 deleted file mode 100644 index bfef4cf86..000000000 --- a/src/udev/src/keymap/keymaps/acer-travelmate_c300 +++ /dev/null @@ -1,5 +0,0 @@ -0x67 f24 # FIXME: rotate screen -0x68 up -0x69 down -0x6B fn -0x6C screenlock # FIXME: lock tablet device/buttons diff --git a/src/udev/src/keymap/keymaps/asus b/src/udev/src/keymap/keymaps/asus deleted file mode 100644 index 2a5995f98..000000000 --- a/src/udev/src/keymap/keymaps/asus +++ /dev/null @@ -1,3 +0,0 @@ -0xED volumeup -0xEE volumedown -0xEF mute diff --git a/src/udev/src/keymap/keymaps/compaq-e_evo b/src/udev/src/keymap/keymaps/compaq-e_evo deleted file mode 100644 index 5fbc573aa..000000000 --- a/src/udev/src/keymap/keymaps/compaq-e_evo +++ /dev/null @@ -1,4 +0,0 @@ -0xA3 www # I key -0x9A search -0x9E email -0x9F homepage diff --git a/src/udev/src/keymap/keymaps/dell b/src/udev/src/keymap/keymaps/dell deleted file mode 100644 index 4f907b3ee..000000000 --- a/src/udev/src/keymap/keymaps/dell +++ /dev/null @@ -1,29 +0,0 @@ -0x81 playpause # Play/Pause -0x82 stopcd # Stop -0x83 previoussong # Previous song -0x84 nextsong # Next song -0x85 brightnessdown # Fn+Down arrow Brightness Down -0x86 brightnessup # Fn+Up arrow Brightness Up -0x87 battery # Fn+F3 battery icon -0x88 unknown # Fn+F2 Turn On/Off Wireless - handled in hardware -0x89 ejectclosecd # Fn+F10 Eject CD -0x8A suspend # Fn+F1 hibernate -0x8B switchvideomode # Fn+F8 CRT/LCD (high keycode: "displaytoggle") -0x8C f23 # Fn+Right arrow Auto Brightness -0x8F switchvideomode # Fn+F7 aspect ratio -0x90 previoussong # Front panel previous song -0x91 prog1 # Wifi Catcher (DELL Specific) -0x92 media # MediaDirect button (house icon) -0x93 f23 # FIXME Fn+Left arrow Auto Brightness -0x95 camera # Shutter button Takes a picture if optional camera available -0x97 email # Tablet email button -0x98 f21 # FIXME: Tablet screen rotatation -0x99 nextsong # Front panel next song -0x9A setup # Tablet tools button -0x9B switchvideomode # Display Toggle button -0x9E f21 #touchpad toggle -0xA2 playpause # Front panel play/pause -0xA4 stopcd # Front panel stop -0xED media # MediaDirect button -0xD8 screenlock # FIXME: Tablet lock button -0xD9 f21 # touchpad toggle diff --git a/src/udev/src/keymap/keymaps/dell-latitude-xt2 b/src/udev/src/keymap/keymaps/dell-latitude-xt2 deleted file mode 100644 index 39872f559..000000000 --- a/src/udev/src/keymap/keymaps/dell-latitude-xt2 +++ /dev/null @@ -1,4 +0,0 @@ -0x9B up # tablet rocker up -0x9E enter # tablet rocker press -0x9F back # tablet back -0xA3 down # tablet rocker down diff --git a/src/udev/src/keymap/keymaps/everex-xt5000 b/src/udev/src/keymap/keymaps/everex-xt5000 deleted file mode 100644 index 4823a832f..000000000 --- a/src/udev/src/keymap/keymaps/everex-xt5000 +++ /dev/null @@ -1,7 +0,0 @@ -0x5C media -0x65 f21 # Fn+F5 Touchpad toggle -0x67 prog3 # Fan Speed Control button -0x6F brightnessup -0x7F brightnessdown -0xB2 www -0xEC mail diff --git a/src/udev/src/keymap/keymaps/fujitsu-amilo_li_2732 b/src/udev/src/keymap/keymaps/fujitsu-amilo_li_2732 deleted file mode 100644 index 9b8b36a17..000000000 --- a/src/udev/src/keymap/keymaps/fujitsu-amilo_li_2732 +++ /dev/null @@ -1,3 +0,0 @@ -0xD9 brightnessdown # Fn+F8 brightness down -0xEF brightnessup # Fn+F9 brightness up -0xA9 switchvideomode # Fn+F10 Cycle between available video outputs diff --git a/src/udev/src/keymap/keymaps/fujitsu-amilo_pa_2548 b/src/udev/src/keymap/keymaps/fujitsu-amilo_pa_2548 deleted file mode 100644 index f7b0c5244..000000000 --- a/src/udev/src/keymap/keymaps/fujitsu-amilo_pa_2548 +++ /dev/null @@ -1,3 +0,0 @@ -0xE0 volumedown -0xE1 volumeup -0xE5 prog1 diff --git a/src/udev/src/keymap/keymaps/fujitsu-amilo_pro_edition_v3505 b/src/udev/src/keymap/keymaps/fujitsu-amilo_pro_edition_v3505 deleted file mode 100644 index d2e38cbb2..000000000 --- a/src/udev/src/keymap/keymaps/fujitsu-amilo_pro_edition_v3505 +++ /dev/null @@ -1,4 +0,0 @@ -0xA5 help # Fn-F1 -0xA9 switchvideomode # Fn-F3 -0xD9 brightnessdown # Fn-F8 -0xE0 brightnessup # Fn-F9 diff --git a/src/udev/src/keymap/keymaps/fujitsu-amilo_pro_v3205 b/src/udev/src/keymap/keymaps/fujitsu-amilo_pro_v3205 deleted file mode 100644 index 43e3199d5..000000000 --- a/src/udev/src/keymap/keymaps/fujitsu-amilo_pro_v3205 +++ /dev/null @@ -1,2 +0,0 @@ -0xF4 f21 # FIXME: silent-mode decrease CPU/GPU clock -0xF7 switchvideomode # Fn+F3 diff --git a/src/udev/src/keymap/keymaps/fujitsu-amilo_si_1520 b/src/udev/src/keymap/keymaps/fujitsu-amilo_si_1520 deleted file mode 100644 index 1419bd9b5..000000000 --- a/src/udev/src/keymap/keymaps/fujitsu-amilo_si_1520 +++ /dev/null @@ -1,6 +0,0 @@ -0xE1 wlan -0xF3 wlan -0xEE brightnessdown -0xE0 brightnessup -0xE2 bluetooth -0xF7 video diff --git a/src/udev/src/keymap/keymaps/fujitsu-esprimo_mobile_v5 b/src/udev/src/keymap/keymaps/fujitsu-esprimo_mobile_v5 deleted file mode 100644 index d3d056b36..000000000 --- a/src/udev/src/keymap/keymaps/fujitsu-esprimo_mobile_v5 +++ /dev/null @@ -1,4 +0,0 @@ -0xA9 switchvideomode -0xD9 brightnessdown -0xDF sleep -0xEF brightnessup diff --git a/src/udev/src/keymap/keymaps/fujitsu-esprimo_mobile_v6 b/src/udev/src/keymap/keymaps/fujitsu-esprimo_mobile_v6 deleted file mode 100644 index 52c70c50c..000000000 --- a/src/udev/src/keymap/keymaps/fujitsu-esprimo_mobile_v6 +++ /dev/null @@ -1,2 +0,0 @@ -0xCE brightnessup -0xEF brightnessdown diff --git a/src/udev/src/keymap/keymaps/genius-slimstar-320 b/src/udev/src/keymap/keymaps/genius-slimstar-320 deleted file mode 100644 index d0a3656dd..000000000 --- a/src/udev/src/keymap/keymaps/genius-slimstar-320 +++ /dev/null @@ -1,35 +0,0 @@ -# Genius SlimStar 320 -# -# Only buttons which are not properly mapped yet are configured below - -# "Scroll wheel", a circular up/down/left/right button. Aimed for scolling, -# but since there are no scrollleft/scrollright, let's map to back/forward. -0x900f0 scrollup -0x900f1 scrolldown -0x900f3 back -0x900f2 forward - -# Multimedia buttons, left side (from left to right) -# [W] -0x900f5 wordprocessor -# [Ex] -0x900f6 spreadsheet -# [P] -0x900f4 presentation -# Other five (calculator, playpause, stop, mute and eject) are OK - -# Right side, from left to right -# [e] -0xc0223 www -# "man" -0x900f7 chat -# "Y" -0x900fb prog1 -# [X] -0x900f8 close -# "picture" -0x900f9 graphicseditor -# "two windows" -0x900fd scale -# "lock" -0x900fc screenlock diff --git a/src/udev/src/keymap/keymaps/hewlett-packard b/src/udev/src/keymap/keymaps/hewlett-packard deleted file mode 100644 index 4461fa2ce..000000000 --- a/src/udev/src/keymap/keymaps/hewlett-packard +++ /dev/null @@ -1,12 +0,0 @@ -0x81 fn_esc -0x89 battery # FnF8 -0x8A screenlock # FnF6 -0x8B camera -0x8C media # music -0x8E dvd -0xB1 help -0xB3 f23 # FIXME: Auto brightness -0xD7 wlan -0x92 brightnessdown # FnF7 (FnF9 on 6730b) -0x97 brightnessup # FnF8 (FnF10 on 6730b) -0xEE switchvideomode # FnF4 diff --git a/src/udev/src/keymap/keymaps/hewlett-packard-2510p_2530p b/src/udev/src/keymap/keymaps/hewlett-packard-2510p_2530p deleted file mode 100644 index 41ad2e9b5..000000000 --- a/src/udev/src/keymap/keymaps/hewlett-packard-2510p_2530p +++ /dev/null @@ -1,2 +0,0 @@ -0xD8 f23 # touchpad off -0xD9 f22 # touchpad on diff --git a/src/udev/src/keymap/keymaps/hewlett-packard-compaq_elitebook b/src/udev/src/keymap/keymaps/hewlett-packard-compaq_elitebook deleted file mode 100644 index 42007c548..000000000 --- a/src/udev/src/keymap/keymaps/hewlett-packard-compaq_elitebook +++ /dev/null @@ -1,2 +0,0 @@ -0x88 presentation -0xD9 help # I key (high keycode: "info") diff --git a/src/udev/src/keymap/keymaps/hewlett-packard-pavilion b/src/udev/src/keymap/keymaps/hewlett-packard-pavilion deleted file mode 100644 index 3d3cefc8e..000000000 --- a/src/udev/src/keymap/keymaps/hewlett-packard-pavilion +++ /dev/null @@ -1,3 +0,0 @@ -0x88 media # FIXME: quick play -0xD8 f23 # touchpad off -0xD9 f22 # touchpad on diff --git a/src/udev/src/keymap/keymaps/hewlett-packard-presario-2100 b/src/udev/src/keymap/keymaps/hewlett-packard-presario-2100 deleted file mode 100644 index 1df39dcbd..000000000 --- a/src/udev/src/keymap/keymaps/hewlett-packard-presario-2100 +++ /dev/null @@ -1,3 +0,0 @@ -0xF0 help -0xF1 screenlock -0xF3 search diff --git a/src/udev/src/keymap/keymaps/hewlett-packard-tablet b/src/udev/src/keymap/keymaps/hewlett-packard-tablet deleted file mode 100644 index d19005ab9..000000000 --- a/src/udev/src/keymap/keymaps/hewlett-packard-tablet +++ /dev/null @@ -1,6 +0,0 @@ -0x82 prog2 # Funny Key -0x83 prog1 # Q -0x84 tab -0x85 esc -0x86 pageup -0x87 pagedown diff --git a/src/udev/src/keymap/keymaps/hewlett-packard-tx2 b/src/udev/src/keymap/keymaps/hewlett-packard-tx2 deleted file mode 100644 index 36a690fcf..000000000 --- a/src/udev/src/keymap/keymaps/hewlett-packard-tx2 +++ /dev/null @@ -1,3 +0,0 @@ -0xC2 media -0xD8 f23 # Toggle touchpad button on tx2 (OFF) -0xD9 f22 # Toggle touchpad button on tx2 (ON) diff --git a/src/udev/src/keymap/keymaps/ibm-thinkpad-usb-keyboard-trackpoint b/src/udev/src/keymap/keymaps/ibm-thinkpad-usb-keyboard-trackpoint deleted file mode 100644 index 027e50bf8..000000000 --- a/src/udev/src/keymap/keymaps/ibm-thinkpad-usb-keyboard-trackpoint +++ /dev/null @@ -1,7 +0,0 @@ -0x900f0 screenlock -0x900f1 wlan -0x900f2 switchvideomode -0x900f3 suspend -0x900f4 brightnessup -0x900f5 brightnessdown -0x900f8 zoom diff --git a/src/udev/src/keymap/keymaps/inventec-symphony_6.0_7.0 b/src/udev/src/keymap/keymaps/inventec-symphony_6.0_7.0 deleted file mode 100644 index 4a8b4ba5a..000000000 --- a/src/udev/src/keymap/keymaps/inventec-symphony_6.0_7.0 +++ /dev/null @@ -1,2 +0,0 @@ -0xF3 prog2 -0xF4 prog1 diff --git a/src/udev/src/keymap/keymaps/lenovo-3000 b/src/udev/src/keymap/keymaps/lenovo-3000 deleted file mode 100644 index 5bd165654..000000000 --- a/src/udev/src/keymap/keymaps/lenovo-3000 +++ /dev/null @@ -1,5 +0,0 @@ -0x8B switchvideomode # Fn+F7 video -0x96 wlan # Fn+F5 wireless -0x97 sleep # Fn+F4 suspend -0x98 suspend # Fn+F12 hibernate -0xB4 prog1 # Lenovo Care diff --git a/src/udev/src/keymap/keymaps/lenovo-ideapad b/src/udev/src/keymap/keymaps/lenovo-ideapad deleted file mode 100644 index fc339839f..000000000 --- a/src/udev/src/keymap/keymaps/lenovo-ideapad +++ /dev/null @@ -1,8 +0,0 @@ -# Key codes observed on S10-3, assumed valid on other IdeaPad models -0x81 rfkill # does nothing in BIOS -0x83 display_off # BIOS toggles screen state -0xB9 brightnessup # does nothing in BIOS -0xBA brightnessdown # does nothing in BIOS -0xF1 camera # BIOS toggles camera power -0xf2 f21 # touchpad toggle (key alternately emits f2 and f3) -0xf3 f21 diff --git a/src/udev/src/keymap/keymaps/lenovo-thinkpad-usb-keyboard-trackpoint b/src/udev/src/keymap/keymaps/lenovo-thinkpad-usb-keyboard-trackpoint deleted file mode 100644 index 47e8846a6..000000000 --- a/src/udev/src/keymap/keymaps/lenovo-thinkpad-usb-keyboard-trackpoint +++ /dev/null @@ -1,13 +0,0 @@ -0x90012 screenlock # Fn+F2 -0x90013 battery # Fn+F3 -0x90014 wlan # Fn+F5 -0x90016 switchvideomode # Fn+F7 -0x90017 f21 # Fn+F8 touchpadtoggle -0x90019 suspend # Fn+F12 -0x9001A brightnessup # Fn+Home -0x9001B brightnessdown # Fn+End -0x9001D zoom # Fn+Space -0x90011 prog1 # Thinkvantage button - -0x90015 camera # Fn+F6 headset/camera VoIP key ?? -0x90010 micmute # Microphone mute button diff --git a/src/udev/src/keymap/keymaps/lenovo-thinkpad_x200_tablet b/src/udev/src/keymap/keymaps/lenovo-thinkpad_x200_tablet deleted file mode 100644 index 31ea3b2c7..000000000 --- a/src/udev/src/keymap/keymaps/lenovo-thinkpad_x200_tablet +++ /dev/null @@ -1,6 +0,0 @@ -0x5D menu -0x63 fn -0x66 screenlock -0x67 cyclewindows # bezel circular arrow -0x68 setup # bezel setup / menu -0x6c direction # rotate screen diff --git a/src/udev/src/keymap/keymaps/lenovo-thinkpad_x6_tablet b/src/udev/src/keymap/keymaps/lenovo-thinkpad_x6_tablet deleted file mode 100644 index 6fd16b566..000000000 --- a/src/udev/src/keymap/keymaps/lenovo-thinkpad_x6_tablet +++ /dev/null @@ -1,8 +0,0 @@ -0x6C f21 # rotate -0x68 screenlock # screenlock -0x6B esc # escape -0x6D right # right on d-pad -0x6E left # left on d-pad -0x71 up # up on d-pad -0x6F down # down on d-pad -0x69 enter # enter on d-pad diff --git a/src/udev/src/keymap/keymaps/lg-x110 b/src/udev/src/keymap/keymaps/lg-x110 deleted file mode 100644 index ba08cba3f..000000000 --- a/src/udev/src/keymap/keymaps/lg-x110 +++ /dev/null @@ -1,12 +0,0 @@ -0xA0 mute # Fn-F9 -0xAE volumedown # Fn-Left -0xAF search # Fn-F3 -0xB0 volumeup # Fn-Right -0xB1 battery # Fn-F10 Info -0xB3 suspend # Fn-F12 -0xDF sleep # Fn-F4 -# 0xE2 bluetooth # satellite dish2 -0xE4 f21 # Fn-F5 Touchpad disable -0xF6 wlan # Fn-F6 -0xF7 reserved # brightnessdown # Fn-Down -0xF8 reserved # brightnessup # Fn-Up diff --git a/src/udev/src/keymap/keymaps/logitech-wave b/src/udev/src/keymap/keymaps/logitech-wave deleted file mode 100644 index caa5d5d31..000000000 --- a/src/udev/src/keymap/keymaps/logitech-wave +++ /dev/null @@ -1,16 +0,0 @@ -0x9001C scale #expo -0x9001F zoomout #zoom out -0x90020 zoomin #zoom in -0x9003D prog1 #gadget -0x90005 camera #camera -0x90018 media #media center -0x90041 wordprocessor #fn+f1 (word) -0x90042 spreadsheet #fn+f2 (excel) -0x90043 calendar #fn+f3 (calendar) -0x90044 prog2 #fn+f4 (program a) -0x90045 prog3 #fn+f5 (program b) -0x90046 prog4 #fn+f6 (program c) -0x90048 messenger #fn+f8 (msn messenger) -0x9002D find #fn+f10 (search www) -0x9004B search #fn+f11 (search pc) -0x9004C ejectclosecd #fn+f12 (eject) diff --git a/src/udev/src/keymap/keymaps/logitech-wave-cordless b/src/udev/src/keymap/keymaps/logitech-wave-cordless deleted file mode 100644 index a10dad5e4..000000000 --- a/src/udev/src/keymap/keymaps/logitech-wave-cordless +++ /dev/null @@ -1,15 +0,0 @@ -0xD4 zoomin -0xCC zoomout -0xC0183 media -0xC1005 camera -0xC101F zoomout -0xC1020 zoomin -0xC1041 wordprocessor -0xC1042 spreadsheet -0xC1043 calendar -0xC1044 prog2 #fn+f4 (program a) -0xC1045 prog3 #fn+f5 (program b) -0xC1046 prog4 #fn+f6 (program c) -0xC1048 messenger -0xC104A find #fn+f10 (search www) -0xC104C ejectclosecd diff --git a/src/udev/src/keymap/keymaps/logitech-wave-pro-cordless b/src/udev/src/keymap/keymaps/logitech-wave-pro-cordless deleted file mode 100644 index e7aa02206..000000000 --- a/src/udev/src/keymap/keymaps/logitech-wave-pro-cordless +++ /dev/null @@ -1,12 +0,0 @@ -0xC01B6 camera -0xC0183 media -0xC0184 wordprocessor -0xC0186 spreadsheet -0xC018E calendar -0xC0223 homepage -0xC01BC messenger -0xC018A mail -0xC0221 search -0xC00B8 ejectcd -0xC022D zoomin -0xC022E zoomout diff --git a/src/udev/src/keymap/keymaps/maxdata-pro_7000 b/src/udev/src/keymap/keymaps/maxdata-pro_7000 deleted file mode 100644 index c0e4f77af..000000000 --- a/src/udev/src/keymap/keymaps/maxdata-pro_7000 +++ /dev/null @@ -1,9 +0,0 @@ -0x97 prog2 -0x9F prog1 -0xA0 mute # Fn-F5 -0x82 www -0xEC email -0xAE volumedown # Fn-Down -0xB0 volumeup # Fn-Up -0xDF suspend # Fn+F2 -0xF5 help diff --git a/src/udev/src/keymap/keymaps/medion-fid2060 b/src/udev/src/keymap/keymaps/medion-fid2060 deleted file mode 100644 index 5a76c7679..000000000 --- a/src/udev/src/keymap/keymaps/medion-fid2060 +++ /dev/null @@ -1,2 +0,0 @@ -0x6B channeldown # Thottle Down -0x6D channelup # Thottle Up diff --git a/src/udev/src/keymap/keymaps/medionnb-a555 b/src/udev/src/keymap/keymaps/medionnb-a555 deleted file mode 100644 index c3b5dfa60..000000000 --- a/src/udev/src/keymap/keymaps/medionnb-a555 +++ /dev/null @@ -1,4 +0,0 @@ -0x63 www # N button -0x66 prog1 # link 1 button -0x67 email # envelope button -0x69 prog2 # link 2 button diff --git a/src/udev/src/keymap/keymaps/micro-star b/src/udev/src/keymap/keymaps/micro-star deleted file mode 100644 index 4a438698e..000000000 --- a/src/udev/src/keymap/keymaps/micro-star +++ /dev/null @@ -1,13 +0,0 @@ -0xA0 mute # Fn-F9 -0xAE volumedown # Fn-F7 -0xB0 volumeup # Fn-F8 -0xB2 www # e button -0xDF sleep # Fn-F12 -0xE2 bluetooth # satellite dish2 -0xE4 f21 # Fn-F3 Touchpad disable -0xEC email # envelope button -0xEE camera # Fn-F6 camera disable -0xF6 wlan # satellite dish1 -0xF7 brightnessdown # Fn-F4 -0xF8 brightnessup # Fn-F5 -0xF9 search diff --git a/src/udev/src/keymap/keymaps/module-asus-w3j b/src/udev/src/keymap/keymaps/module-asus-w3j deleted file mode 100644 index 773e0b3e8..000000000 --- a/src/udev/src/keymap/keymaps/module-asus-w3j +++ /dev/null @@ -1,11 +0,0 @@ -0x41 nextsong -0x45 playpause -0x43 stopcd -0x40 previoussong -0x4C ejectclosecd -0x32 mute -0x31 volumedown -0x30 volumeup -0x5D wlan -0x7E bluetooth -0x8A media # high keycode: "tv" diff --git a/src/udev/src/keymap/keymaps/module-ibm b/src/udev/src/keymap/keymaps/module-ibm deleted file mode 100644 index a92dfa250..000000000 --- a/src/udev/src/keymap/keymaps/module-ibm +++ /dev/null @@ -1,16 +0,0 @@ -0x01 battery # Fn+F2 -0x02 screenlock # Fn+F3 -0x03 sleep # Fn+F4 -0x04 wlan # Fn+F5 -0x06 switchvideomode # Fn+F7 -0x07 zoom # Fn+F8 screen expand -0x08 f24 # Fn+F9 undock -0x0B suspend # Fn+F12 -0x0F brightnessup # Fn+Home -0x10 brightnessdown # Fn+End -0x11 kbdillumtoggle # Fn+PgUp - ThinkLight -0x13 zoom # Fn+Space -0x14 volumeup -0x15 volumedown -0x16 mute -0x17 prog1 # ThinkPad/ThinkVantage button (high keycode: "vendor") diff --git a/src/udev/src/keymap/keymaps/module-lenovo b/src/udev/src/keymap/keymaps/module-lenovo deleted file mode 100644 index 8e3888309..000000000 --- a/src/udev/src/keymap/keymaps/module-lenovo +++ /dev/null @@ -1,17 +0,0 @@ -0x1 screenlock # Fn+F2 -0x2 battery # Fn+F3 -0x3 sleep # Fn+F4 -0x4 wlan # Fn+F5 -0x6 switchvideomode # Fn+F7 -0x7 f21 # Fn+F8 touchpadtoggle -0x8 f24 # Fn+F9 undock -0xB suspend # Fn+F12 -0xF brightnessup # Fn+Home -0x10 brightnessdown # Fn+End -0x11 kbdillumtoggle # Fn+PgUp - ThinkLight -0x13 zoom # Fn+Space -0x14 volumeup -0x15 volumedown -0x16 mute -0x17 prog1 # ThinkPad/ThinkVantage button (high keycode: "vendor") -0x1A micmute # Microphone mute diff --git a/src/udev/src/keymap/keymaps/module-sony b/src/udev/src/keymap/keymaps/module-sony deleted file mode 100644 index 7c000131d..000000000 --- a/src/udev/src/keymap/keymaps/module-sony +++ /dev/null @@ -1,8 +0,0 @@ -0x06 mute # Fn+F2 -0x07 volumedown # Fn+F3 -0x08 volumeup # Fn+F4 -0x09 brightnessdown # Fn+F5 -0x0A brightnessup # Fn+F6 -0x0B switchvideomode # Fn+F7 -0x0E zoom # Fn+F10 -0x10 suspend # Fn+F12 diff --git a/src/udev/src/keymap/keymaps/module-sony-old b/src/udev/src/keymap/keymaps/module-sony-old deleted file mode 100644 index 596a34258..000000000 --- a/src/udev/src/keymap/keymaps/module-sony-old +++ /dev/null @@ -1,2 +0,0 @@ -0x06 battery -0x07 mute diff --git a/src/udev/src/keymap/keymaps/module-sony-vgn b/src/udev/src/keymap/keymaps/module-sony-vgn deleted file mode 100644 index c8ba00151..000000000 --- a/src/udev/src/keymap/keymaps/module-sony-vgn +++ /dev/null @@ -1,8 +0,0 @@ -0x00 brightnessdown # Fn+F5 -0x10 brightnessup # Fn+F6 -0x11 switchvideomode # Fn+F7 -0x12 zoomout -0x14 zoomin -0x15 suspend # Fn+F12 -0x17 prog1 -0x20 media diff --git a/src/udev/src/keymap/keymaps/olpc-xo b/src/udev/src/keymap/keymaps/olpc-xo deleted file mode 100644 index 34434a121..000000000 --- a/src/udev/src/keymap/keymaps/olpc-xo +++ /dev/null @@ -1,74 +0,0 @@ -0x59 fn -0x81 fn_esc -0xF9 camera -0xF8 sound # Fn-CAMERA = Mic - - -# Function key mappings, as per -# http://dev.laptop.org/ticket/10213#comment:20 -# -# Unmodified F1-F8 produce F1-F8, so no remap necessary. -# Unmodified F9-F12 control brightness and volume. -0x43 brightnessdown -0x44 brightnessup -0x57 volumedown -0x58 volumeup - -# fn-modified fkeys all produce the unmodified version of the key. -0xBB f1 -0xBC f2 -0xBD f3 -0xBE f4 -0xBF f5 -0xC0 f6 -0xC1 f7 -0xC2 f8 -0xC3 f9 -0xC4 f10 -0xD7 f11 -0xD8 f12 - - -# Using F13-F21 for the .5 F keys right now. -0xF7 f13 -0xF6 f14 -0xF5 f15 -0xF4 f16 -0xF3 f17 -0xF2 f18 -0xF1 f19 -0xF0 f20 -0xEF f21 - -0xEE chat -0xE4 chat # Just mapping Fn-Chat to Chat for now -0xDD menu # Frame -0xDA prog1 # Fn-Frame - -# The FN of some keys is other keys -0xD3 delete -0xD2 insert -0xC9 pageup -0xD1 pagedown -0xC7 home -0xCF end - -# Language key - don't ask what they are doing as KEY_HP -0x73 hp -0x7E hp - -0xDB leftmeta # left grab -0xDC rightmeta # right grab -0x85 rightmeta # Right grab releases on a different scancode -0xD6 kbdillumtoggle # Fn-space -0x69 switchvideomode # Brightness key - -# Game keys -0x65 kp8 # up -0x66 kp2 # down -0x67 kp4 # left -0x68 kp6 # right -0xE5 kp9 # pgup -0xE6 kp3 # pgdn -0xE7 kp7 # home -0xE8 kp1 # end diff --git a/src/udev/src/keymap/keymaps/onkyo b/src/udev/src/keymap/keymaps/onkyo deleted file mode 100644 index ee864ade4..000000000 --- a/src/udev/src/keymap/keymaps/onkyo +++ /dev/null @@ -1,14 +0,0 @@ -0xA0 mute # Fn+D -0xAE volumedown # Fn+F -0xB0 volumeup # Fn+G -0xDF sleep # Fn+W -0xE0 bluetooth # Fn+H -0xE2 cyclewindows # Fn+Esc -0xEE battery # Fn+Q -0xF0 media # Fn+R -0xF5 switchvideomode # Fn+E -0xF6 camera # Fn+T -0xF7 f21 # Fn+Y (touchpad toggle) -0xF8 brightnessup # Fn+S -0xF9 brightnessdown # Fn+A -0xFB wlan # Fn+J diff --git a/src/udev/src/keymap/keymaps/oqo-model2 b/src/udev/src/keymap/keymaps/oqo-model2 deleted file mode 100644 index b7f4851ab..000000000 --- a/src/udev/src/keymap/keymaps/oqo-model2 +++ /dev/null @@ -1,5 +0,0 @@ -0x8E wlan -0xF0 switchvideomode -0xF1 mute -0xF2 volumedown -0xF3 volumeup diff --git a/src/udev/src/keymap/keymaps/samsung-90x3a b/src/udev/src/keymap/keymaps/samsung-90x3a deleted file mode 100644 index 8b65eb6d0..000000000 --- a/src/udev/src/keymap/keymaps/samsung-90x3a +++ /dev/null @@ -1,5 +0,0 @@ -0x96 kbdillumup        # Fn+F8 keyboard backlit up -0x97 kbdillumdown      # Fn+F7 keyboard backlit down -0xD5 wlan              # Fn+F12 wifi on/off -0xCE prog1             # Fn+F1 performance mode -0x8D prog2             # Fn+F6 battery life extender diff --git a/src/udev/src/keymap/keymaps/samsung-other b/src/udev/src/keymap/keymaps/samsung-other deleted file mode 100644 index 3ac0c2f10..000000000 --- a/src/udev/src/keymap/keymaps/samsung-other +++ /dev/null @@ -1,14 +0,0 @@ -0x74 prog1 # User key -0x75 www -0x78 mail -0x82 switchvideomode # Fn+F4 CRT/LCD (high keycode: "displaytoggle") -0x83 battery # Fn+F2 -0x84 prog1 # Fn+F5 backlight on/off -0x86 wlan # Fn+F9 -0x88 brightnessup # Fn-Up -0x89 brightnessdown # Fn-Down -0xB1 prog2 # Fn+F7 run Samsung Magic Doctor (keypressed event is generated twice) -0xB3 prog3 # Fn+F8 switch power mode (battery/dynamic/performance) -0xB4 wlan # Fn+F9 (X60P) -0xF7 f22 # Fn+F10 Touchpad on -0xF9 f23 # Fn+F10 Touchpad off diff --git a/src/udev/src/keymap/keymaps/samsung-sq1us b/src/udev/src/keymap/keymaps/samsung-sq1us deleted file mode 100644 index ea2141ef8..000000000 --- a/src/udev/src/keymap/keymaps/samsung-sq1us +++ /dev/null @@ -1,7 +0,0 @@ -0xD4 menu -0xD8 f1 -0xD9 f10 -0xD6 f3 -0xD7 f9 -0xE4 f5 -0xEE f11 diff --git a/src/udev/src/keymap/keymaps/samsung-sx20s b/src/udev/src/keymap/keymaps/samsung-sx20s deleted file mode 100644 index 9d954ee41..000000000 --- a/src/udev/src/keymap/keymaps/samsung-sx20s +++ /dev/null @@ -1,4 +0,0 @@ -0x74 mute -0x75 mute -0x77 f22 # Touchpad on -0x79 f23 # Touchpad off diff --git a/src/udev/src/keymap/keymaps/toshiba-satellite_a100 b/src/udev/src/keymap/keymaps/toshiba-satellite_a100 deleted file mode 100644 index 22007be71..000000000 --- a/src/udev/src/keymap/keymaps/toshiba-satellite_a100 +++ /dev/null @@ -1,2 +0,0 @@ -0xA4 stopcd -0xB2 www diff --git a/src/udev/src/keymap/keymaps/toshiba-satellite_a110 b/src/udev/src/keymap/keymaps/toshiba-satellite_a110 deleted file mode 100644 index 142940935..000000000 --- a/src/udev/src/keymap/keymaps/toshiba-satellite_a110 +++ /dev/null @@ -1,10 +0,0 @@ -0x92 stop -0x93 www -0x94 media -0x9E f22 # Touchpad on -0x9F f23 # Touchpad off -0xB9 nextsong -0xD9 brightnessup -0xEE screenlock -0xF4 previoussong -0xF7 playpause diff --git a/src/udev/src/keymap/keymaps/toshiba-satellite_m30x b/src/udev/src/keymap/keymaps/toshiba-satellite_m30x deleted file mode 100644 index ae8e34941..000000000 --- a/src/udev/src/keymap/keymaps/toshiba-satellite_m30x +++ /dev/null @@ -1,6 +0,0 @@ -0xef brightnessdown -0xd9 brightnessup -0xee screenlock -0x93 media -0x9e f22 #touchpad_enable -0x9f f23 #touchpad_disable diff --git a/src/udev/src/keymap/keymaps/zepto-znote b/src/udev/src/keymap/keymaps/zepto-znote deleted file mode 100644 index cf72fda47..000000000 --- a/src/udev/src/keymap/keymaps/zepto-znote +++ /dev/null @@ -1,11 +0,0 @@ -0x93 switchvideomode # Fn+F3 Toggle Video Output -0x95 brightnessdown # Fn+F4 Brightness Down -0x91 brightnessup # Fn+F5 Brightness Up -0xA5 f23 # Fn+F6 Disable Touchpad -0xA6 f22 # Fn+F6 Enable Touchpad -0xA7 bluetooth # Fn+F10 Enable Bluetooth -0XA9 bluetooth # Fn+F10 Disable Bluetooth -0xF1 wlan # RF Switch Off -0xF2 wlan # RF Switch On -0xF4 prog1 # P1 Button -0xF3 prog2 # P2 Button diff --git a/src/udev/src/libudev-device-private.c b/src/udev/src/libudev-device-private.c deleted file mode 100644 index 13fdb8eb5..000000000 --- a/src/udev/src/libudev-device-private.c +++ /dev/null @@ -1,185 +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 <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <stddef.h> -#include <stdbool.h> -#include <unistd.h> -#include <fcntl.h> -#include <string.h> -#include <sys/stat.h> - -#include "libudev.h" -#include "libudev-private.h" - -static void udev_device_tag(struct udev_device *dev, const char *tag, bool add) -{ - const char *id; - struct udev *udev = udev_device_get_udev(dev); - char filename[UTIL_PATH_SIZE]; - - id = udev_device_get_id_filename(dev); - if (id == NULL) - return; - util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/tags/", tag, "/", id, NULL); - - if (add) { - int fd; - - util_create_path(udev, filename); - fd = open(filename, O_WRONLY|O_CREAT|O_CLOEXEC|O_TRUNC|O_NOFOLLOW, 0444); - if (fd >= 0) - close(fd); - } else { - unlink(filename); - } -} - -int udev_device_tag_index(struct udev_device *dev, struct udev_device *dev_old, bool add) -{ - struct udev_list_entry *list_entry; - bool found; - - if (add && dev_old != NULL) { - /* delete possible left-over tags */ - udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(dev_old)) { - const char *tag_old = udev_list_entry_get_name(list_entry); - struct udev_list_entry *list_entry_current; - - found = false; - udev_list_entry_foreach(list_entry_current, udev_device_get_tags_list_entry(dev)) { - const char *tag = udev_list_entry_get_name(list_entry_current); - - if (strcmp(tag, tag_old) == 0) { - found = true; - break; - } - } - if (!found) - udev_device_tag(dev_old, tag_old, false); - } - } - - udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(dev)) - udev_device_tag(dev, udev_list_entry_get_name(list_entry), add); - - return 0; -} - -static bool device_has_info(struct udev_device *udev_device) -{ - struct udev_list_entry *list_entry; - - if (udev_device_get_devlinks_list_entry(udev_device) != NULL) - return true; - if (udev_device_get_devlink_priority(udev_device) != 0) - return true; - udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(udev_device)) - if (udev_list_entry_get_num(list_entry)) - return true; - if (udev_device_get_tags_list_entry(udev_device) != NULL) - return true; - if (udev_device_get_watch_handle(udev_device) >= 0) - return true; - return false; -} - -int udev_device_update_db(struct udev_device *udev_device) -{ - bool has_info; - const char *id; - struct udev *udev = udev_device_get_udev(udev_device); - char filename[UTIL_PATH_SIZE]; - char filename_tmp[UTIL_PATH_SIZE]; - FILE *f; - - id = udev_device_get_id_filename(udev_device); - if (id == NULL) - return -1; - - has_info = device_has_info(udev_device); - util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/data/", id, NULL); - - /* do not store anything for otherwise empty devices */ - if (!has_info && - major(udev_device_get_devnum(udev_device)) == 0 && - udev_device_get_ifindex(udev_device) == 0) { - unlink(filename); - return 0; - } - - /* write a database file */ - util_strscpyl(filename_tmp, sizeof(filename_tmp), filename, ".tmp", NULL); - util_create_path(udev, filename_tmp); - f = fopen(filename_tmp, "we"); - if (f == NULL) { - err(udev, "unable to create temporary db file '%s': %m\n", filename_tmp); - return -1; - } - - /* - * set 'sticky' bit to indicate that we should not clean the - * database when we transition from initramfs to the real root - */ - if (udev_device_get_db_persist(udev_device)) - fchmod(fileno(f), 01644); - - if (has_info) { - struct udev_list_entry *list_entry; - - if (major(udev_device_get_devnum(udev_device)) > 0) { - size_t devlen = strlen(udev_get_dev_path(udev))+1; - - udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(udev_device)) - fprintf(f, "S:%s\n", &udev_list_entry_get_name(list_entry)[devlen]); - if (udev_device_get_devlink_priority(udev_device) != 0) - fprintf(f, "L:%i\n", udev_device_get_devlink_priority(udev_device)); - if (udev_device_get_watch_handle(udev_device) >= 0) - fprintf(f, "W:%i\n", udev_device_get_watch_handle(udev_device)); - } - - if (udev_device_get_usec_initialized(udev_device) > 0) - fprintf(f, "I:%llu\n", udev_device_get_usec_initialized(udev_device)); - - udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(udev_device)) { - if (!udev_list_entry_get_num(list_entry)) - continue; - fprintf(f, "E:%s=%s\n", - udev_list_entry_get_name(list_entry), - udev_list_entry_get_value(list_entry)); - } - - udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(udev_device)) - fprintf(f, "G:%s\n", udev_list_entry_get_name(list_entry)); - } - - fclose(f); - rename(filename_tmp, filename); - info(udev, "created %s file '%s' for '%s'\n", has_info ? "db" : "empty", - filename, udev_device_get_devpath(udev_device)); - return 0; -} - -int udev_device_delete_db(struct udev_device *udev_device) -{ - const char *id; - struct udev *udev = udev_device_get_udev(udev_device); - char filename[UTIL_PATH_SIZE]; - - id = udev_device_get_id_filename(udev_device); - if (id == NULL) - return -1; - util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/data/", id, NULL); - unlink(filename); - return 0; -} diff --git a/src/udev/src/libudev-device.c b/src/udev/src/libudev-device.c deleted file mode 100644 index 10f28b8cd..000000000 --- a/src/udev/src/libudev-device.c +++ /dev/null @@ -1,1744 +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 *id_filename; - char **envp; - char *monitor_buf; - size_t monitor_buf_len; - struct udev_list devlinks_list; - struct udev_list properties_list; - struct udev_list sysattr_value_list; - struct udev_list sysattr_list; - struct udev_list tags_list; - unsigned long long int seqnum; - unsigned long long int usec_initialized; - 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_seqnum: - * @udev_device: udev device - * - * This is only valid if the device was received through a monitor. Devices read from - * sys do not have a sequence number. - * - * Returns: the kernel event sequence number, or 0 if there is no sequence number available. - **/ -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; -} - -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_core_link_value(udev_device->udev, "driver", 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_core_link_value(udev_device->udev, "subsystem", 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->properties_list, key, value); -} - -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) { - udev_device_set_devnode(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, "USEC_INITIALIZED=", 19) == 0) { - udev_device_set_usec_initialized(udev_device, strtoull(&property[19], NULL, 10)); - } 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, "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 '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]); - continue; - } - if (strncmp(line, "IFINDEX=", 8) == 0) { - udev_device_set_ifindex(udev_device, strtoull(&line[8], NULL, 10)); - continue; - } - if (strncmp(line, "DEVNAME=", 8) == 0) { - udev_device_set_devnode(udev_device, &line[8]); - continue; - } - - 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, "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, &udev_device->devlinks_list, true); - udev_list_init(udev, &udev_device->properties_list, true); - udev_list_init(udev, &udev_device->sysattr_value_list, true); - udev_list_init(udev, &udev_device->sysattr_list, false); - udev_list_init(udev, &udev_device->tags_list, true); - 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(&udev_device->devlinks_list); - udev_list_cleanup(&udev_device->properties_list); - udev_list_cleanup(&udev_device->sysattr_value_list); - udev_list_cleanup(&udev_device->sysattr_list); - udev_list_cleanup(&udev_device->tags_list); - free(udev_device->action); - free(udev_device->driver); - free(udev_device->devpath_old); - 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->devnode != NULL) - return udev_device->devnode; - if (!udev_device->info_loaded) - udev_device_read_uevent_file(udev_device); - 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(&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) -{ - char num[32]; - - udev_device->usec_initialized = usec_initialized; - snprintf(num, sizeof(num), "%llu", usec_initialized); - udev_device_add_property(udev_device, "USEC_INITIALIZED", num); -} - -/** - * 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 */ - list_entry = udev_list_get_entry(&udev_device->sysattr_value_list); - list_entry = udev_list_entry_get_by_name(list_entry, sysattr); - if (list_entry != NULL) { - 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->sysattr_value_list, sysattr, NULL); - goto out; - } - - if (S_ISLNK(statbuf.st_mode)) { - struct udev_device *dev; - - /* - * Some core links return only the last element of the target path, - * these are just values, the paths should not be exposed. - */ - if (strcmp(sysattr, "driver") == 0 || - strcmp(sysattr, "subsystem") == 0 || - strcmp(sysattr, "module") == 0) { - if (util_get_sys_core_link_value(udev_device->udev, sysattr, - udev_device->syspath, value, sizeof(value)) < 0) - return NULL; - dbg(udev_device->udev, "cache '%s' with link value '%s'\n", sysattr, value); - list_entry = udev_list_entry_add(&udev_device->sysattr_value_list, sysattr, value); - val = udev_list_entry_get_value(list_entry); - goto out; - } - - /* resolve link to a device and return its syspath */ - util_strscpyl(path, sizeof(path), udev_device->syspath, "/", sysattr, NULL); - dev = udev_device_new_from_syspath(udev_device->udev, path); - if (dev != NULL) { - list_entry = udev_list_entry_add(&udev_device->sysattr_value_list, sysattr, - udev_device_get_syspath(dev)); - val = udev_list_entry_get_value(list_entry); - udev_device_unref(dev); - } - - 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->sysattr_value_list, sysattr, value); - 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->sysattr_list, dent->d_name, NULL); - 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); - if (devnode[0] != '/') { - if (asprintf(&udev_device->devnode, "%s/%s", udev_get_dev_path(udev_device->udev), devnode) < 0) - udev_device->devnode = NULL; - } else { - 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->devlinks_list, devlink, NULL); - 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->tags_list, tag, NULL) != NULL) - return 0; - return -ENOMEM; -} - -void udev_device_cleanup_tags_list(struct udev_device *udev_device) -{ - udev_device->tags_uptodate = false; - udev_list_cleanup(&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; - if (!udev_device->info_loaded) - udev_device_read_db(udev_device, NULL); - return udev_list_get_entry(&udev_device->tags_list); -} - -UDEV_EXPORT int udev_device_has_tag(struct udev_device *udev_device, const char *tag) -{ - struct udev_list_entry *list_entry; - - if (udev_device == NULL) - return false; - if (!udev_device->info_loaded) - udev_device_read_db(udev_device, NULL); - list_entry = udev_device_get_tags_list_entry(udev_device); - if (udev_list_entry_get_by_name(list_entry, tag) != NULL) - return true; - return false; -} - -#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/udev/src/libudev-enumerate.c b/src/udev/src/libudev-enumerate.c deleted file mode 100644 index 034d96feb..000000000 --- a/src/udev/src/libudev-enumerate.c +++ /dev/null @@ -1,947 +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 sysattr_match_list; - struct udev_list sysattr_nomatch_list; - struct udev_list subsystem_match_list; - struct udev_list subsystem_nomatch_list; - struct udev_list sysname_match_list; - struct udev_list properties_match_list; - struct udev_list tags_match_list; - struct udev_device *parent_match; - struct udev_list devices_list; - struct syspath *devices; - unsigned int devices_cur; - unsigned int devices_max; - bool devices_uptodate:1; - bool match_is_initialized; -}; - -/** - * udev_enumerate_new: - * @udev: udev library context - * - * 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, &udev_enumerate->sysattr_match_list, false); - udev_list_init(udev, &udev_enumerate->sysattr_nomatch_list, false); - udev_list_init(udev, &udev_enumerate->subsystem_match_list, true); - udev_list_init(udev, &udev_enumerate->subsystem_nomatch_list, true); - udev_list_init(udev, &udev_enumerate->sysname_match_list, true); - udev_list_init(udev, &udev_enumerate->properties_match_list, false); - udev_list_init(udev, &udev_enumerate->tags_match_list, true); - udev_list_init(udev, &udev_enumerate->devices_list, false); - return udev_enumerate; -} - -/** - * udev_enumerate_ref: - * @udev_enumerate: context - * - * Take a reference of a enumeration context. - * - * Returns: the passed enumeration context - **/ -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(&udev_enumerate->sysattr_match_list); - udev_list_cleanup(&udev_enumerate->sysattr_nomatch_list); - udev_list_cleanup(&udev_enumerate->subsystem_match_list); - udev_list_cleanup(&udev_enumerate->subsystem_nomatch_list); - udev_list_cleanup(&udev_enumerate->sysname_match_list); - udev_list_cleanup(&udev_enumerate->properties_match_list); - udev_list_cleanup(&udev_enumerate->tags_match_list); - udev_device_unref(udev_enumerate->parent_match); - udev_list_cleanup(&udev_enumerate->devices_list); - for (i = 0; i < udev_enumerate->devices_cur; i++) - free(udev_enumerate->devices[i].syspath); - free(udev_enumerate->devices); - free(udev_enumerate); -} - -/** - * 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(&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->devices_list, move_later->syspath, NULL); - move_later = NULL; - } - - udev_list_entry_add(&udev_enumerate->devices_list, entry->syspath, NULL); - } - - if (move_later) - udev_list_entry_add(&udev_enumerate->devices_list, move_later->syspath, NULL); - - /* add and cleanup delayed devices from end of list */ - for (i = max; i < udev_enumerate->devices_cur; i++) { - struct syspath *entry = &udev_enumerate->devices[i]; - - udev_list_entry_add(&udev_enumerate->devices_list, entry->syspath, NULL); - free(entry->syspath); - } - udev_enumerate->devices_cur = max; - - udev_enumerate->devices_uptodate = true; - } - return udev_list_get_entry(&udev_enumerate->devices_list); -} - -/** - * udev_enumerate_add_match_subsystem: - * @udev_enumerate: context - * @subsystem: filter for a subsystem of the device to include in the list - * - * 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->subsystem_match_list, subsystem, NULL) == NULL) - return -ENOMEM; - return 0; -} - -/** - * udev_enumerate_add_nomatch_subsystem: - * @udev_enumerate: context - * @subsystem: filter for a subsystem of the device to exclude from the list - * - * 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->subsystem_nomatch_list, subsystem, NULL) == NULL) - return -ENOMEM; - return 0; -} - -/** - * udev_enumerate_add_match_sysattr: - * @udev_enumerate: context - * @sysattr: filter for a sys attribute at the device to include in the list - * @value: optional value of the sys attribute - * - * 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->sysattr_match_list, sysattr, value) == NULL) - return -ENOMEM; - return 0; -} - -/** - * udev_enumerate_add_nomatch_sysattr: - * @udev_enumerate: context - * @sysattr: filter for a sys attribute at the device to exclude from the list - * @value: optional value of the sys attribute - * - * 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->sysattr_nomatch_list, sysattr, value) == NULL) - return -ENOMEM; - return 0; -} - -static int match_sysattr_value(struct udev_device *dev, const char *sysattr, const char *match_val) -{ - const char *val = NULL; - bool match = false; - - val = udev_device_get_sysattr_value(dev, sysattr); - if (val == NULL) - goto exit; - if (match_val == NULL) { - match = true; - goto exit; - } - if (fnmatch(match_val, val, 0) == 0) { - match = true; - goto exit; - } -exit: - return match; -} - -/** - * udev_enumerate_add_match_property: - * @udev_enumerate: context - * @property: filter for a property of the device to include in the list - * @value: value of the property - * - * 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->properties_match_list, property, value) == NULL) - return -ENOMEM; - return 0; -} - -/** - * udev_enumerate_add_match_tag: - * @udev_enumerate: context - * @tag: filter for a tag of the device to include in the list - * - * 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->tags_match_list, tag, NULL) == NULL) - return -ENOMEM; - return 0; -} - -/** - * udev_enumerate_add_match_parent: - * @udev_enumerate: context - * @parent: parent device where to start searching - * - * Return the devices on the subtree of one given device. The parent - * itself is included in the list. - * - * A reference for the device is held until the udev_enumerate context - * is cleaned up. - * - * Returns: 0 on success, otherwise a negative error value. - */ -UDEV_EXPORT int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent) -{ - if (udev_enumerate == NULL) - return -EINVAL; - if (parent == NULL) - return 0; - if (udev_enumerate->parent_match != NULL) - udev_device_unref(udev_enumerate->parent_match); - udev_enumerate->parent_match = udev_device_ref(parent); - return 0; -} - -/** - * udev_enumerate_add_match_is_initialized: - * @udev_enumerate: context - * - * Match only devices which udev has set up already. This makes - * sure, that the device node permissions and context are properly set - * and that network devices are fully renamed. - * - * Usually, devices which are found in the kernel but not already - * handled by udev, have still pending events. Services should subscribe - * to monitor events and wait for these devices to become ready, instead - * of using uninitialized devices. - * - * For now, this will not affect devices which do not have a device node - * and are not network interfaces. - * - * Returns: 0 on success, otherwise a negative error value. - */ -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->sysname_match_list, sysname, NULL) == NULL) - return -ENOMEM; - return 0; -} - -static bool match_sysattr(struct udev_enumerate *udev_enumerate, struct udev_device *dev) -{ - struct udev_list_entry *list_entry; - - /* skip list */ - udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->sysattr_nomatch_list)) { - if (match_sysattr_value(dev, udev_list_entry_get_name(list_entry), - udev_list_entry_get_value(list_entry))) - return false; - } - /* include list */ - if (udev_list_get_entry(&udev_enumerate->sysattr_match_list) != NULL) { - udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->sysattr_match_list)) { - /* anything that does not match, will make it FALSE */ - if (!match_sysattr_value(dev, udev_list_entry_get_name(list_entry), - udev_list_entry_get_value(list_entry))) - return false; - } - return true; - } - return true; -} - -static bool match_property(struct udev_enumerate *udev_enumerate, struct udev_device *dev) -{ - struct udev_list_entry *list_entry; - bool match = false; - - /* no match always matches */ - if (udev_list_get_entry(&udev_enumerate->properties_match_list) == NULL) - return true; - - /* loop over matches */ - udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->properties_match_list)) { - const char *match_key = udev_list_entry_get_name(list_entry); - const char *match_value = udev_list_entry_get_value(list_entry); - struct udev_list_entry *property_entry; - - /* loop over device properties */ - udev_list_entry_foreach(property_entry, udev_device_get_properties_list_entry(dev)) { - const char *dev_key = udev_list_entry_get_name(property_entry); - const char *dev_value = udev_list_entry_get_value(property_entry); - - if (fnmatch(match_key, dev_key, 0) != 0) - continue; - if (match_value == NULL && dev_value == NULL) { - match = true; - goto out; - } - if (match_value == NULL || dev_value == NULL) - continue; - if (fnmatch(match_value, dev_value, 0) == 0) { - match = true; - goto out; - } - } - } -out: - return match; -} - -static bool match_tag(struct udev_enumerate *udev_enumerate, struct udev_device *dev) -{ - struct udev_list_entry *list_entry; - - /* no match always matches */ - if (udev_list_get_entry(&udev_enumerate->tags_match_list) == NULL) - return true; - - /* loop over matches */ - udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->tags_match_list)) - if (!udev_device_has_tag(dev, udev_list_entry_get_name(list_entry))) - return false; - - return true; -} - -static bool match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *dev) -{ - const char *parent; - - if (udev_enumerate->parent_match == NULL) - return true; - - parent = udev_device_get_devpath(udev_enumerate->parent_match); - return strncmp(parent, udev_device_get_devpath(dev), strlen(parent)) == 0; -} - -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_parent(udev_enumerate, dev)) - goto nomatch; - if (!match_tag(udev_enumerate, dev)) - goto nomatch; - if (!match_property(udev_enumerate, dev)) - goto nomatch; - if (!match_sysattr(udev_enumerate, dev)) - goto nomatch; - - syspath_add(udev_enumerate, udev_device_get_syspath(dev)); -nomatch: - udev_device_unref(dev); - } - closedir(dir); - return 0; -} - -static bool match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) -{ - struct udev_list_entry *list_entry; - - 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; -} - -static int scan_devices_tags(struct udev_enumerate *udev_enumerate) -{ - struct udev *udev = udev_enumerate_get_udev(udev_enumerate); - struct udev_list_entry *list_entry; - - /* scan only tagged devices, use tags reverse-index, instead of searching all devices in /sys */ - udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->tags_match_list)) { - DIR *dir; - struct dirent *dent; - char path[UTIL_PATH_SIZE]; - - 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_parent(udev_enumerate, dev)) - goto nomatch; - if (!match_property(udev_enumerate, dev)) - goto nomatch; - if (!match_sysattr(udev_enumerate, dev)) - goto nomatch; - - syspath_add(udev_enumerate, udev_device_get_syspath(dev)); -nomatch: - udev_device_unref(dev); - } - closedir(dir); - } - return 0; -} - -static int parent_add_child(struct udev_enumerate *enumerate, const char *path) -{ - struct udev_device *dev; - - dev = udev_device_new_from_syspath(enumerate->udev, path); - if (dev == NULL) - return -ENODEV; - - if (!match_subsystem(enumerate, udev_device_get_subsystem(dev))) - return 0; - if (!match_sysname(enumerate, udev_device_get_sysname(dev))) - return 0; - if (!match_property(enumerate, dev)) - return 0; - if (!match_sysattr(enumerate, dev)) - return 0; - - syspath_add(enumerate, udev_device_get_syspath(dev)); - udev_device_unref(dev); - return 1; -} - -static int parent_crawl_children(struct udev_enumerate *enumerate, const char *path, int maxdepth) -{ - DIR *d; - struct dirent *dent; - - d = opendir(path); - if (d == NULL) - return -errno; - - for (dent = readdir(d); dent != NULL; dent = readdir(d)) { - char *child; - - if (dent->d_name[0] == '.') - continue; - if (dent->d_type != DT_DIR) - continue; - if (asprintf(&child, "%s/%s", path, dent->d_name) < 0) - continue; - parent_add_child(enumerate, child); - if (maxdepth > 0) - parent_crawl_children(enumerate, child, maxdepth-1); - free(child); - } - - closedir(d); - return 0; -} - -static int scan_devices_children(struct udev_enumerate *enumerate) -{ - const char *path; - - path = udev_device_get_syspath(enumerate->parent_match); - parent_add_child(enumerate, path); - return parent_crawl_children(enumerate, path, 256); -} - -static int scan_devices_all(struct udev_enumerate *udev_enumerate) -{ - struct udev *udev = udev_enumerate_get_udev(udev_enumerate); - char base[UTIL_PATH_SIZE]; - struct stat statbuf; - - 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_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) -{ - if (udev_enumerate == NULL) - return -EINVAL; - - /* efficiently lookup tags only, we maintain a reverse-index */ - if (udev_list_get_entry(&udev_enumerate->tags_match_list) != NULL) - return scan_devices_tags(udev_enumerate); - - /* walk the subtree of one parent device only */ - if (udev_enumerate->parent_match != NULL) - return scan_devices_children(udev_enumerate); - - /* scan devices of all subsystems */ - return scan_devices_all(udev_enumerate); -} - -/** - * udev_enumerate_scan_subsystems: - * @udev_enumerate: udev enumeration context - * - * 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; - - /* all kernel modules */ - if (match_subsystem(udev_enumerate, "module")) { - dbg(udev, "searching 'modules/*' dir\n"); - scan_dir_and_add_devices(udev_enumerate, "module", NULL, NULL); - } - - util_strscpyl(base, sizeof(base), udev_get_sys_path(udev), "/subsystem", NULL); - if (stat(base, &statbuf) == 0) - subsysdir = "subsystem"; - else - subsysdir = "bus"; - - /* all subsystems (only buses support coldplug) */ - if (match_subsystem(udev_enumerate, "subsystem")) { - dbg(udev, "searching '%s/*' dir\n", subsysdir); - scan_dir_and_add_devices(udev_enumerate, subsysdir, NULL, NULL); - } - - /* all subsystem drivers */ - 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/udev/src/libudev-list.c b/src/udev/src/libudev-list.c deleted file mode 100644 index 4bdef35ae..000000000 --- a/src/udev/src/libudev-list.c +++ /dev/null @@ -1,344 +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_list *list; - char *name; - char *value; - int num; -}; - -/* the list's head points to itself if empty */ -void udev_list_node_init(struct udev_list_node *list) -{ - list->next = list; - list->prev = list; -} - -int udev_list_node_is_empty(struct udev_list_node *list) -{ - return list->next == list; -} - -static void udev_list_node_insert_between(struct udev_list_node *new, - struct udev_list_node *prev, - struct udev_list_node *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -void udev_list_node_append(struct udev_list_node *new, struct udev_list_node *list) -{ - udev_list_node_insert_between(new, list->prev, list); -} - -void udev_list_node_remove(struct udev_list_node *entry) -{ - struct udev_list_node *prev = entry->prev; - struct udev_list_node *next = entry->next; - - next->prev = prev; - prev->next = next; - - entry->prev = NULL; - entry->next = NULL; -} - -/* return list entry which embeds this node */ -static 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; -} - -void udev_list_init(struct udev *udev, struct udev_list *list, bool unique) -{ - memset(list, 0x00, sizeof(struct udev_list)); - list->udev = udev; - list->unique = unique; - udev_list_node_init(&list->node); -} - -/* insert entry into a list as the last element */ -void udev_list_entry_append(struct udev_list_entry *new, struct udev_list *list) -{ - /* inserting before the list head make the node the last node in the list */ - udev_list_node_insert_between(&new->node, list->node.prev, &list->node); - new->list = list; -} - -/* insert entry into a list, before a given existing entry */ -void udev_list_entry_insert_before(struct udev_list_entry *new, struct udev_list_entry *entry) -{ - udev_list_node_insert_between(&new->node, entry->node.prev, &entry->node); - new->list = entry->list; -} - -/* binary search in sorted array */ -static int list_search(struct udev_list *list, const char *name) -{ - unsigned int first, last; - - first = 0; - last = list->entries_cur; - while (first < last) { - unsigned int i; - int cmp; - - i = (first + last)/2; - cmp = strcmp(name, list->entries[i]->name); - if (cmp < 0) - last = i; - else if (cmp > 0) - first = i+1; - else - return i; - } - - /* not found, return negative insertion-index+1 */ - return -(first+1); -} - -struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char *name, const char *value) -{ - struct udev_list_entry *entry; - int i = 0; - - if (list->unique) { - /* lookup existing name or insertion-index */ - i = list_search(list, name); - if (i >= 0) { - entry = list->entries[i]; - - dbg(list->udev, "'%s' is already in the list\n", name); - free(entry->value); - if (value == NULL) { - entry->value = NULL; - dbg(list->udev, "'%s' value unset\n", name); - return entry; - } - entry->value = strdup(value); - if (entry->value == NULL) - return NULL; - dbg(list->udev, "'%s' value replaced with '%s'\n", name, value); - return entry; - } - } - - /* add new name */ - entry = calloc(1, sizeof(struct udev_list_entry)); - if (entry == NULL) - return NULL; - entry->name = strdup(name); - if (entry->name == NULL) { - free(entry); - return NULL; - } - if (value != NULL) { - entry->value = strdup(value); - if (entry->value == NULL) { - free(entry->name); - free(entry); - return NULL; - } - } - - if (list->unique) { - /* allocate or enlarge sorted array if needed */ - if (list->entries_cur >= list->entries_max) { - unsigned int add; - - add = list->entries_max; - if (add < 1) - add = 64; - list->entries = realloc(list->entries, (list->entries_max + add) * sizeof(struct udev_list_entry *)); - if (list->entries == NULL) { - free(entry->name); - free(entry->value); - return NULL; - } - list->entries_max += add; - } - - /* the negative i returned the insertion index */ - i = (-i)-1; - - /* insert into sorted list */ - if ((unsigned int)i < list->entries_cur) - udev_list_entry_insert_before(entry, list->entries[i]); - else - udev_list_entry_append(entry, list); - - /* insert into sorted array */ - memmove(&list->entries[i+1], &list->entries[i], - (list->entries_cur - i) * sizeof(struct udev_list_entry *)); - list->entries[i] = entry; - list->entries_cur++; - } else { - udev_list_entry_append(entry, list); - } - - dbg(list->udev, "'%s=%s' added\n", entry->name, entry->value); - return entry; -} - -void udev_list_entry_delete(struct udev_list_entry *entry) -{ - if (entry->list->entries != NULL) { - int i; - struct udev_list *list = entry->list; - - /* remove entry from sorted array */ - i = list_search(list, entry->name); - if (i >= 0) { - memmove(&list->entries[i], &list->entries[i+1], - ((list->entries_cur-1) - i) * sizeof(struct udev_list_entry *)); - list->entries_cur--; - } - } - - udev_list_node_remove(&entry->node); - free(entry->name); - free(entry->value); - free(entry); -} - -void udev_list_cleanup(struct udev_list *list) -{ - struct udev_list_entry *entry_loop; - struct udev_list_entry *entry_tmp; - - free(list->entries); - list->entries = NULL; - list->entries_cur = 0; - list->entries_max = 0; - udev_list_entry_foreach_safe(entry_loop, entry_tmp, udev_list_get_entry(list)) - udev_list_entry_delete(entry_loop); -} - -struct udev_list_entry *udev_list_get_entry(struct udev_list *list) -{ - if (udev_list_node_is_empty(&list->node)) - return NULL; - return list_node_to_entry(list->node.next); -} - -/** - * udev_list_entry_get_next: - * @list_entry: current entry - * - * 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->node) - 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) -{ - int i; - - if (list_entry == NULL) - return NULL; - - if (!list_entry->list->unique) - return NULL; - - i = list_search(list_entry->list, name); - if (i < 0) - return NULL; - return list_entry->list->entries[i]; -} - -/** - * udev_list_entry_get_name: - * @list_entry: current entry - * - * 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/udev/src/libudev-monitor.c b/src/udev/src/libudev-monitor.c deleted file mode 100644 index 77dc55572..000000000 --- a/src/udev/src/libudev-monitor.c +++ /dev/null @@ -1,874 +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 an 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 filter_subsystem_list; - struct udev_list filter_tag_list; - bool bound; -}; - -enum udev_monitor_netlink_group { - UDEV_MONITOR_NONE, - UDEV_MONITOR_KERNEL, - UDEV_MONITOR_UDEV, -}; - -#define UDEV_MONITOR_MAGIC 0xfeedcafe -struct udev_monitor_netlink_header { - /* "libudev" prefix to distinguish libudev and kernel messages */ - char prefix[8]; - /* - * magic to protect against daemon <-> library message format mismatch - * used in the kernel from socket filter rules; needs to be stored in network order - */ - unsigned int magic; - /* total length of header structure known to the sender */ - unsigned int header_size; - /* properties string buffer */ - unsigned int properties_off; - unsigned int properties_len; - /* - * hashes of primary device properties strings, to let libudev subscribers - * use in-kernel socket filters; values need to be stored in network order - */ - unsigned int filter_subsystem_hash; - unsigned int filter_devtype_hash; - unsigned int filter_tag_bloom_hi; - unsigned int filter_tag_bloom_lo; -}; - -static struct udev_monitor *udev_monitor_new(struct udev *udev) -{ - struct udev_monitor *udev_monitor; - - udev_monitor = calloc(1, sizeof(struct udev_monitor)); - if (udev_monitor == NULL) - return NULL; - udev_monitor->refcount = 1; - udev_monitor->udev = udev; - udev_list_init(udev, &udev_monitor->filter_subsystem_list, false); - udev_list_init(udev, &udev_monitor->filter_tag_list, true); - return udev_monitor; -} - -/** - * udev_monitor_new_from_socket: - * @udev: udev library context - * @socket_path: unix socket path - * - * This function should not be used in any new application. The - * kernel's netlink socket multiplexes messages to all interested - * clients. Creating custom sockets from udev to applications - * should be avoided. - * - * Create a 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 socket filter. This is only 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(&udev_monitor->filter_subsystem_list); - udev_list_cleanup(&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 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; - 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, "unrecognized message signature (%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 filter is efficiently executed inside the kernel, and libudev subscribers - * will usually not be woken up for devices which do not match. - * - * The filter must be installed before the monitor is switched to listening mode. - * - * Returns: 0 on success, otherwise a negative error value. - */ -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->filter_subsystem_list, subsystem, devtype) == NULL) - return -ENOMEM; - return 0; -} - -/** - * udev_monitor_filter_add_match_tag: - * @udev_monitor: the monitor - * @tag: the name of a tag - * - * This filter is efficiently executed inside the kernel, and libudev subscribers - * will usually not be woken up for devices which do not match. - * - * The filter must be installed before the monitor is switched to listening mode. - * - * Returns: 0 on success, otherwise a negative error value. - */ -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->filter_tag_list, tag, NULL) == NULL) - return -ENOMEM; - return 0; -} - -/** - * udev_monitor_filter_remove: - * @udev_monitor: monitor - * - * Remove all filters from monitor. - * - * Returns: 0 on success, otherwise a negative error value. - */ -UDEV_EXPORT int udev_monitor_filter_remove(struct udev_monitor *udev_monitor) -{ - static struct sock_fprog filter = { 0, NULL }; - - udev_list_cleanup(&udev_monitor->filter_subsystem_list); - return setsockopt(udev_monitor->sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)); -} diff --git a/src/udev/src/libudev-private.h b/src/udev/src/libudev-private.h deleted file mode 100644 index 5f5c64a63..000000000 --- a/src/udev/src/libudev-private.h +++ /dev/null @@ -1,213 +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))); -int udev_get_rules_path(struct udev *udev, char **path[], unsigned long long *ts_usec[]); -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_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); -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-list.c */ -struct udev_list_node { - struct udev_list_node *next, *prev; -}; -struct udev_list { - struct udev *udev; - struct udev_list_node node; - struct udev_list_entry **entries; - unsigned int entries_cur; - unsigned int entries_max; - bool unique; -}; -#define UDEV_LIST(list) struct udev_list_node list = { &(list), &(list) } -void udev_list_node_init(struct udev_list_node *list); -int udev_list_node_is_empty(struct udev_list_node *list); -void udev_list_node_append(struct udev_list_node *new, struct udev_list_node *list); -void udev_list_node_remove(struct udev_list_node *entry); -#define udev_list_node_foreach(node, list) \ - for (node = (list)->next; \ - node != list; \ - node = (node)->next) -#define udev_list_node_foreach_safe(node, tmp, list) \ - for (node = (list)->next, tmp = (node)->next; \ - node != list; \ - node = tmp, tmp = (tmp)->next) -void udev_list_init(struct udev *udev, struct udev_list *list, bool unique); -void udev_list_cleanup(struct udev_list *list); -struct udev_list_entry *udev_list_get_entry(struct udev_list *list); -struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char *name, const char *value); -void udev_list_entry_delete(struct udev_list_entry *entry); -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 *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); - -/* libudev-util.c */ -#define UTIL_PATH_SIZE 1024 -#define UTIL_NAME_SIZE 512 -#define UTIL_LINE_SIZE 16384 -#define UDEV_ALLOWED_CHARS_INPUT "/ $%?," -ssize_t util_get_sys_core_link_value(struct udev *udev, const char *slink, const char *syspath, char *value, size_t size); -int util_resolve_sys_link(struct udev *udev, char *syspath, size_t size); -int util_log_priority(const char *priority); -size_t util_path_encode(const char *src, char *dest, size_t size); -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 util_replace_whitespace(const char *str, char *to, size_t len); -int util_replace_chars(char *str, const char *white); -unsigned int util_string_hash32(const char *key); -uint64_t util_string_bloom64(const char *str); - -/* libudev-util-private.c */ -int util_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); -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 ts_usec(const struct timespec *ts); -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/udev/src/libudev-queue-private.c b/src/udev/src/libudev-queue-private.c deleted file mode 100644 index 71771950a..000000000 --- a/src/udev/src/libudev-queue-private.c +++ /dev/null @@ -1,412 +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. - */ - -/* - * DISCLAIMER - The file format mentioned here is private to udev/libudev, - * and may be changed without notice. - * - * The udev event queue is exported as a binary log file. - * Each log record consists of a sequence number followed by the device path. - * - * When a new event is queued, its details are appended to the log. - * When the event finishes, a second record is appended to the log - * with the same sequence number but a devpath len of 0. - * - * Example: - * { 0x0000000000000001 } - * { 0x0000000000000001, 0x0019, "/devices/virtual/mem/null" }, - * { 0x0000000000000002, 0x001b, "/devices/virtual/mem/random" }, - * { 0x0000000000000001, 0x0000 }, - * { 0x0000000000000003, 0x0019, "/devices/virtual/mem/zero" }, - * - * Events 2 and 3 are still queued, but event 1 has finished. - * - * The queue does not grow indefinitely. It is periodically re-created - * to remove finished events. Atomic rename() makes this transparent to readers. - * - * The queue file starts with a single sequence number which specifies the - * minimum sequence number in the log that follows. Any events prior to this - * sequence number have already finished. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <dirent.h> -#include <limits.h> -#include <errno.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include "libudev.h" -#include "libudev-private.h" - -static int rebuild_queue_file(struct udev_queue_export *udev_queue_export); - -struct udev_queue_export { - struct udev *udev; - int queued_count; /* number of unfinished events exported in queue file */ - FILE *queue_file; - unsigned long long int seqnum_max; /* earliest sequence number in queue file */ - unsigned long long int seqnum_min; /* latest sequence number in queue file */ - int waste_bytes; /* queue file bytes wasted on finished events */ -}; - -struct udev_queue_export *udev_queue_export_new(struct udev *udev) -{ - struct udev_queue_export *udev_queue_export; - unsigned long long int initial_seqnum; - - if (udev == NULL) - return NULL; - - udev_queue_export = calloc(1, sizeof(struct udev_queue_export)); - if (udev_queue_export == NULL) - return NULL; - udev_queue_export->udev = udev; - - initial_seqnum = udev_get_kernel_seqnum(udev); - udev_queue_export->seqnum_min = initial_seqnum; - udev_queue_export->seqnum_max = initial_seqnum; - - udev_queue_export_cleanup(udev_queue_export); - if (rebuild_queue_file(udev_queue_export) != 0) { - free(udev_queue_export); - return NULL; - } - - return udev_queue_export; -} - -struct udev_queue_export *udev_queue_export_unref(struct udev_queue_export *udev_queue_export) -{ - if (udev_queue_export == NULL) - return NULL; - if (udev_queue_export->queue_file != NULL) - fclose(udev_queue_export->queue_file); - free(udev_queue_export); - return NULL; -} - -void udev_queue_export_cleanup(struct udev_queue_export *udev_queue_export) -{ - char filename[UTIL_PATH_SIZE]; - - if (udev_queue_export == NULL) - return; - util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev_queue_export->udev), "/queue.tmp", NULL); - unlink(filename); - util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev_queue_export->udev), "/queue.bin", NULL); - unlink(filename); -} - -static int skip_to(FILE *file, long offset) -{ - long old_offset; - - /* fseek may drop buffered data, avoid it for small seeks */ - old_offset = ftell(file); - if (offset > old_offset && offset - old_offset <= BUFSIZ) { - size_t skip_bytes = offset - old_offset; - char buf[skip_bytes]; - - if (fread(buf, skip_bytes, 1, file) != skip_bytes) - return -1; - } - - return fseek(file, offset, SEEK_SET); -} - -struct queue_devpaths { - unsigned int devpaths_first; /* index of first queued event */ - unsigned int devpaths_size; - long devpaths[]; /* seqnum -> offset of devpath in queue file (or 0) */ -}; - -/* - * Returns a table mapping seqnum to devpath file offset for currently queued events. - * devpaths[i] represents the event with seqnum = i + udev_queue_export->seqnum_min. - */ -static struct queue_devpaths *build_index(struct udev_queue_export *udev_queue_export) -{ - struct queue_devpaths *devpaths; - unsigned long long int range; - long devpath_offset; - ssize_t devpath_len; - unsigned long long int seqnum; - unsigned long long int n; - unsigned int i; - - /* seek to the first event in the file */ - rewind(udev_queue_export->queue_file); - udev_queue_read_seqnum(udev_queue_export->queue_file, &seqnum); - - /* allocate the table */ - range = udev_queue_export->seqnum_min - udev_queue_export->seqnum_max; - if (range - 1 > INT_MAX) { - err(udev_queue_export->udev, "queue file overflow\n"); - return NULL; - } - devpaths = calloc(1, sizeof(struct queue_devpaths) + (range + 1) * sizeof(long)); - if (devpaths == NULL) - return NULL; - devpaths->devpaths_size = range + 1; - - /* read all records and populate the table */ - for (;;) { - if (udev_queue_read_seqnum(udev_queue_export->queue_file, &seqnum) < 0) - break; - n = seqnum - udev_queue_export->seqnum_max; - if (n >= devpaths->devpaths_size) - goto read_error; - - devpath_offset = ftell(udev_queue_export->queue_file); - devpath_len = udev_queue_skip_devpath(udev_queue_export->queue_file); - if (devpath_len < 0) - goto read_error; - - if (devpath_len > 0) - devpaths->devpaths[n] = devpath_offset; - else - devpaths->devpaths[n] = 0; - } - - /* find first queued event */ - for (i = 0; i < devpaths->devpaths_size; i++) { - if (devpaths->devpaths[i] != 0) - break; - } - devpaths->devpaths_first = i; - - return devpaths; - -read_error: - err(udev_queue_export->udev, "queue file corrupted\n"); - free(devpaths); - return NULL; -} - -static int rebuild_queue_file(struct udev_queue_export *udev_queue_export) -{ - unsigned long long int seqnum; - struct queue_devpaths *devpaths = NULL; - char filename[UTIL_PATH_SIZE]; - char filename_tmp[UTIL_PATH_SIZE]; - FILE *new_queue_file = NULL; - unsigned int i; - - /* read old queue file */ - if (udev_queue_export->queue_file != NULL) { - dbg(udev_queue_export->udev, "compacting queue file, freeing %d bytes\n", - udev_queue_export->waste_bytes); - - devpaths = build_index(udev_queue_export); - if (devpaths != NULL) - udev_queue_export->seqnum_max += devpaths->devpaths_first; - } - if (devpaths == NULL) { - dbg(udev_queue_export->udev, "creating empty queue file\n"); - udev_queue_export->queued_count = 0; - udev_queue_export->seqnum_max = udev_queue_export->seqnum_min; - } - - /* create new queue file */ - util_strscpyl(filename_tmp, sizeof(filename_tmp), udev_get_run_path(udev_queue_export->udev), "/queue.tmp", NULL); - new_queue_file = fopen(filename_tmp, "w+"); - if (new_queue_file == NULL) - goto error; - seqnum = udev_queue_export->seqnum_max; - fwrite(&seqnum, 1, sizeof(unsigned long long int), new_queue_file); - - /* copy unfinished events only to the new file */ - if (devpaths != NULL) { - for (i = devpaths->devpaths_first; i < devpaths->devpaths_size; i++) { - char devpath[UTIL_PATH_SIZE]; - int err; - unsigned short devpath_len; - - if (devpaths->devpaths[i] != 0) - { - skip_to(udev_queue_export->queue_file, devpaths->devpaths[i]); - err = udev_queue_read_devpath(udev_queue_export->queue_file, devpath, sizeof(devpath)); - devpath_len = err; - - fwrite(&seqnum, sizeof(unsigned long long int), 1, new_queue_file); - fwrite(&devpath_len, sizeof(unsigned short), 1, new_queue_file); - fwrite(devpath, 1, devpath_len, new_queue_file); - } - seqnum++; - } - free(devpaths); - devpaths = NULL; - } - fflush(new_queue_file); - if (ferror(new_queue_file)) - goto error; - - /* rename the new file on top of the old one */ - util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev_queue_export->udev), "/queue.bin", NULL); - if (rename(filename_tmp, filename) != 0) - goto error; - - if (udev_queue_export->queue_file != NULL) - fclose(udev_queue_export->queue_file); - udev_queue_export->queue_file = new_queue_file; - udev_queue_export->waste_bytes = 0; - - return 0; - -error: - err(udev_queue_export->udev, "failed to create queue file: %m\n"); - udev_queue_export_cleanup(udev_queue_export); - - if (udev_queue_export->queue_file != NULL) { - fclose(udev_queue_export->queue_file); - udev_queue_export->queue_file = NULL; - } - if (new_queue_file != NULL) - fclose(new_queue_file); - - if (devpaths != NULL) - free(devpaths); - udev_queue_export->queued_count = 0; - udev_queue_export->waste_bytes = 0; - udev_queue_export->seqnum_max = udev_queue_export->seqnum_min; - - return -1; -} - -static int write_queue_record(struct udev_queue_export *udev_queue_export, - unsigned long long int seqnum, const char *devpath, size_t devpath_len) -{ - unsigned short len; - - if (udev_queue_export->queue_file == NULL) { - dbg(udev_queue_export->udev, "can't record event: queue file not available\n"); - return -1; - } - - if (fwrite(&seqnum, sizeof(unsigned long long int), 1, udev_queue_export->queue_file) != 1) - goto write_error; - - len = (devpath_len < USHRT_MAX) ? devpath_len : USHRT_MAX; - if (fwrite(&len, sizeof(unsigned short), 1, udev_queue_export->queue_file) != 1) - goto write_error; - if (len > 0) { - if (fwrite(devpath, 1, len, udev_queue_export->queue_file) != len) - goto write_error; - } - - /* *must* flush output; caller may fork */ - if (fflush(udev_queue_export->queue_file) != 0) - goto write_error; - - return 0; - -write_error: - /* if we failed half way through writing a record to a file, - we should not try to write any further records to it. */ - err(udev_queue_export->udev, "error writing to queue file: %m\n"); - fclose(udev_queue_export->queue_file); - udev_queue_export->queue_file = NULL; - - return -1; -} - -enum device_state { - DEVICE_QUEUED, - DEVICE_FINISHED, -}; - -static inline size_t queue_record_size(size_t devpath_len) -{ - return sizeof(unsigned long long int) + sizeof(unsigned short int) + devpath_len; -} - -static int update_queue(struct udev_queue_export *udev_queue_export, - struct udev_device *udev_device, enum device_state state) -{ - unsigned long long int seqnum = udev_device_get_seqnum(udev_device); - const char *devpath = NULL; - size_t devpath_len = 0; - int bytes; - int err; - - /* FINISHED records have a zero length devpath */ - if (state == DEVICE_QUEUED) { - devpath = udev_device_get_devpath(udev_device); - devpath_len = strlen(devpath); - } - - /* recover from an earlier failed rebuild */ - if (udev_queue_export->queue_file == NULL) { - if (rebuild_queue_file(udev_queue_export) != 0) - return -1; - } - - /* if we're removing the last event from the queue, that's the best time to rebuild it */ - if (state != DEVICE_QUEUED && udev_queue_export->queued_count == 1) { - /* we don't need to read the old queue file */ - fclose(udev_queue_export->queue_file); - udev_queue_export->queue_file = NULL; - rebuild_queue_file(udev_queue_export); - return 0; - } - - /* try to rebuild the queue files before they grow larger than one page. */ - bytes = ftell(udev_queue_export->queue_file) + queue_record_size(devpath_len); - if ((udev_queue_export->waste_bytes > bytes / 2) && bytes > 4096) - rebuild_queue_file(udev_queue_export); - - /* don't record a finished event, if we already dropped the event in a failed rebuild */ - if (seqnum < udev_queue_export->seqnum_max) - return 0; - - /* now write to the queue */ - if (state == DEVICE_QUEUED) { - udev_queue_export->queued_count++; - udev_queue_export->seqnum_min = seqnum; - } else { - udev_queue_export->waste_bytes += queue_record_size(devpath_len) + queue_record_size(0); - udev_queue_export->queued_count--; - } - err = write_queue_record(udev_queue_export, seqnum, devpath, devpath_len); - - /* try to handle ENOSPC */ - if (err != 0 && udev_queue_export->queued_count == 0) { - udev_queue_export_cleanup(udev_queue_export); - err = rebuild_queue_file(udev_queue_export); - } - - return err; -} - -static int update(struct udev_queue_export *udev_queue_export, - struct udev_device *udev_device, enum device_state state) -{ - if (update_queue(udev_queue_export, udev_device, state) != 0) - return -1; - - return 0; -} - -int udev_queue_export_device_queued(struct udev_queue_export *udev_queue_export, struct udev_device *udev_device) -{ - return update(udev_queue_export, udev_device, DEVICE_QUEUED); -} - -int udev_queue_export_device_finished(struct udev_queue_export *udev_queue_export, struct udev_device *udev_device) -{ - return update(udev_queue_export, udev_device, DEVICE_FINISHED); -} diff --git a/src/udev/src/libudev-queue.c b/src/udev/src/libudev-queue.c deleted file mode 100644 index 0e82cb6ae..000000000 --- a/src/udev/src/libudev-queue.c +++ /dev/null @@ -1,474 +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 queue_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, &udev_queue->queue_list, false); - 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(&udev_queue->queue_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(&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->queue_list, syspath, seqnum_str); - } 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); -} - -struct udev_list_entry *udev_queue_get_failed_list_entry(struct udev_queue *udev_queue); -UDEV_EXPORT struct udev_list_entry *udev_queue_get_failed_list_entry(struct udev_queue *udev_queue) -{ - errno = ENOSYS; - return NULL; -} diff --git a/src/udev/src/libudev-selinux-private.c b/src/udev/src/libudev-selinux-private.c deleted file mode 100644 index 0f2a617b1..000000000 --- a/src/udev/src/libudev-selinux-private.c +++ /dev/null @@ -1,109 +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 <stdarg.h> -#include <unistd.h> -#include <selinux/selinux.h> - -#include "libudev.h" -#include "libudev-private.h" - -static int selinux_enabled; -security_context_t selinux_prev_scontext; - -void udev_selinux_init(struct udev *udev) -{ - /* record the present security context */ - selinux_enabled = (is_selinux_enabled() > 0); - info(udev, "selinux=%i\n", selinux_enabled); - if (!selinux_enabled) - return; - matchpathcon_init_prefix(NULL, udev_get_dev_path(udev)); - if (getfscreatecon(&selinux_prev_scontext) < 0) { - err(udev, "getfscreatecon failed\n"); - selinux_prev_scontext = NULL; - } -} - -void udev_selinux_exit(struct udev *udev) -{ - if (!selinux_enabled) - return; - freecon(selinux_prev_scontext); - selinux_prev_scontext = NULL; -} - -void udev_selinux_lsetfilecon(struct udev *udev, const char *file, unsigned int mode) -{ - security_context_t scontext = NULL; - - if (!selinux_enabled) - return; - if (matchpathcon(file, mode, &scontext) < 0) { - err(udev, "matchpathcon(%s) failed\n", file); - return; - } - if (lsetfilecon(file, scontext) < 0) - err(udev, "setfilecon %s failed: %m\n", file); - freecon(scontext); -} - -void udev_selinux_setfscreatecon(struct udev *udev, const char *file, unsigned int mode) -{ - security_context_t scontext = NULL; - - if (!selinux_enabled) - return; - - if (matchpathcon(file, mode, &scontext) < 0) { - err(udev, "matchpathcon(%s) failed\n", file); - return; - } - if (setfscreatecon(scontext) < 0) - err(udev, "setfscreatecon %s failed: %m\n", file); - freecon(scontext); -} - -void udev_selinux_resetfscreatecon(struct udev *udev) -{ - if (!selinux_enabled) - return; - if (setfscreatecon(selinux_prev_scontext) < 0) - err(udev, "setfscreatecon failed: %m\n"); -} - -void udev_selinux_setfscreateconat(struct udev *udev, int dfd, const char *file, unsigned int mode) -{ - char filename[UTIL_PATH_SIZE]; - - if (!selinux_enabled) - return; - - /* resolve relative filename */ - if (file[0] != '/') { - char procfd[UTIL_PATH_SIZE]; - char target[UTIL_PATH_SIZE]; - ssize_t len; - - snprintf(procfd, sizeof(procfd), "/proc/%u/fd/%u", getpid(), dfd); - len = readlink(procfd, target, sizeof(target)); - if (len <= 0 || len == sizeof(target)) - return; - target[len] = '\0'; - - util_strscpyl(filename, sizeof(filename), target, "/", file, NULL); - file = filename; - } - udev_selinux_setfscreatecon(udev, file, mode); -} diff --git a/src/udev/src/libudev-util-private.c b/src/udev/src/libudev-util-private.c deleted file mode 100644 index 08f0ba222..000000000 --- a/src/udev/src/libudev-util-private.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * libudev - interface to udev device information - * - * Copyright (C) 2003-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 <stdlib.h> -#include <stdio.h> -#include <stddef.h> -#include <unistd.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#include <ctype.h> -#include <pwd.h> -#include <grp.h> -#include <sys/param.h> - -#include "libudev.h" -#include "libudev-private.h" - -static int create_path(struct udev *udev, const char *path, bool selinux) -{ - char p[UTIL_PATH_SIZE]; - char *pos; - struct stat stats; - int err; - - util_strscpy(p, sizeof(p), path); - pos = strrchr(p, '/'); - if (pos == NULL) - return 0; - while (pos != p && pos[-1] == '/') - pos--; - if (pos == p) - return 0; - pos[0] = '\0'; - - dbg(udev, "stat '%s'\n", p); - if (stat(p, &stats) == 0) { - if ((stats.st_mode & S_IFMT) == S_IFDIR) - return 0; - else - return -ENOTDIR; - } - - err = util_create_path(udev, p); - if (err != 0) - return err; - - dbg(udev, "mkdir '%s'\n", p); - if (selinux) - udev_selinux_setfscreatecon(udev, p, S_IFDIR|0755); - err = mkdir(p, 0755); - if (err != 0) { - err = -errno; - if (err == -EEXIST && stat(p, &stats) == 0) { - if ((stats.st_mode & S_IFMT) == S_IFDIR) - err = 0; - else - err = -ENOTDIR; - } - } - if (selinux) - udev_selinux_resetfscreatecon(udev); - return err; -} - -int util_create_path(struct udev *udev, const char *path) -{ - return create_path(udev, path, false); -} - -int util_create_path_selinux(struct udev *udev, const char *path) -{ - return create_path(udev, path, true); -} - -int util_delete_path(struct udev *udev, const char *path) -{ - char p[UTIL_PATH_SIZE]; - char *pos; - int err = 0; - - if (path[0] == '/') - while(path[1] == '/') - path++; - util_strscpy(p, sizeof(p), path); - pos = strrchr(p, '/'); - if (pos == p || pos == NULL) - return 0; - - for (;;) { - *pos = '\0'; - pos = strrchr(p, '/'); - - /* don't remove the last one */ - if ((pos == p) || (pos == NULL)) - break; - - err = rmdir(p); - if (err < 0) { - if (errno == ENOENT) - err = 0; - break; - } - } - return err; -} - -uid_t util_lookup_user(struct udev *udev, const char *user) -{ - char *endptr; - size_t buflen = sysconf(_SC_GETPW_R_SIZE_MAX); - char buf[buflen]; - struct passwd pwbuf; - struct passwd *pw; - uid_t uid; - - if (strcmp(user, "root") == 0) - return 0; - uid = strtoul(user, &endptr, 10); - if (endptr[0] == '\0') - return uid; - - errno = getpwnam_r(user, &pwbuf, buf, buflen, &pw); - if (pw != NULL) - return pw->pw_uid; - if (errno == 0 || errno == ENOENT || errno == ESRCH) - err(udev, "specified user '%s' unknown\n", user); - else - err(udev, "error resolving user '%s': %m\n", user); - return 0; -} - -gid_t util_lookup_group(struct udev *udev, const char *group) -{ - char *endptr; - size_t buflen = sysconf(_SC_GETGR_R_SIZE_MAX); - char *buf; - struct group grbuf; - struct group *gr; - gid_t gid = 0; - - if (strcmp(group, "root") == 0) - return 0; - gid = strtoul(group, &endptr, 10); - if (endptr[0] == '\0') - return gid; - buf = NULL; - gid = 0; - for (;;) { - char *newbuf; - - newbuf = realloc(buf, buflen); - if (!newbuf) - break; - buf = newbuf; - errno = getgrnam_r(group, &grbuf, buf, buflen, &gr); - if (gr != NULL) { - gid = gr->gr_gid; - } else if (errno == ERANGE) { - buflen *= 2; - continue; - } else if (errno == 0 || errno == ENOENT || errno == ESRCH) { - err(udev, "specified group '%s' unknown\n", group); - } else { - err(udev, "error resolving group '%s': %m\n", group); - } - break; - } - free(buf); - return gid; -} - -/* handle "[<SUBSYSTEM>/<KERNEL>]<attribute>" format */ -int util_resolve_subsys_kernel(struct udev *udev, const char *string, - char *result, size_t maxsize, int read_value) -{ - char temp[UTIL_PATH_SIZE]; - char *subsys; - char *sysname; - struct udev_device *dev; - char *attr; - - if (string[0] != '[') - return -1; - - util_strscpy(temp, sizeof(temp), string); - - subsys = &temp[1]; - - sysname = strchr(subsys, '/'); - if (sysname == NULL) - return -1; - sysname[0] = '\0'; - sysname = &sysname[1]; - - attr = strchr(sysname, ']'); - if (attr == NULL) - return -1; - attr[0] = '\0'; - attr = &attr[1]; - if (attr[0] == '/') - attr = &attr[1]; - if (attr[0] == '\0') - attr = NULL; - - if (read_value && attr == NULL) - return -1; - - dev = udev_device_new_from_subsystem_sysname(udev, subsys, sysname); - if (dev == NULL) - return -1; - - if (read_value) { - const char *val; - - val = udev_device_get_sysattr_value(dev, attr); - if (val != NULL) - util_strscpy(result, maxsize, val); - else - result[0] = '\0'; - info(udev, "value '[%s/%s]%s' is '%s'\n", subsys, sysname, attr, result); - } else { - size_t l; - char *s; - - s = result; - l = util_strpcpyl(&s, maxsize, udev_device_get_syspath(dev), NULL); - if (attr != NULL) - util_strpcpyl(&s, l, "/", attr, NULL); - info(udev, "path '[%s/%s]%s' is '%s'\n", subsys, sysname, attr, result); - } - udev_device_unref(dev); - return 0; -} diff --git a/src/udev/src/libudev-util.c b/src/udev/src/libudev-util.c deleted file mode 100644 index 7e345f0fb..000000000 --- a/src/udev/src/libudev-util.c +++ /dev/null @@ -1,570 +0,0 @@ -/* - * libudev - interface to udev device information - * - * Copyright (C) 2008-2011 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" - -/** - * SECTION:libudev-util - * @short_description: utils - */ - -ssize_t util_get_sys_core_link_value(struct udev *udev, const char *slink, const char *syspath, char *value, size_t size) -{ - char path[UTIL_PATH_SIZE]; - char target[UTIL_PATH_SIZE]; - ssize_t len; - const char *pos; - - 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); -} - -int util_resolve_sys_link(struct udev *udev, char *syspath, size_t size) -{ - char link_target[UTIL_PATH_SIZE]; - - ssize_t len; - int i; - int back; - char *base = NULL; - - len = readlink(syspath, link_target, sizeof(link_target)); - if (len <= 0 || len == (ssize_t)sizeof(link_target)) - return -1; - link_target[len] = '\0'; - 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 -EINVAL; - base[0] = '\0'; - } - if (base == NULL) - return -EINVAL; - 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 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 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; -} - -/** - * udev_util_encode_string: - * @str: input string to be encoded - * @str_enc: output string to store the encoded input string - * @len: maximum size of the output string, which may be - * four times as long as the input string - * - * Encode all potentially unsafe characters of a string to the - * corresponding 2 char hex value prefixed by '\x'. - * - * Returns: 0 if the entire string was copied, non-zero otherwise. - **/ -UDEV_EXPORT 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 ts_usec(const struct timespec *ts) -{ - return (unsigned long long) ts->tv_sec * USEC_PER_SEC + - (unsigned long long) ts->tv_nsec / NSEC_PER_USEC; -} - -unsigned long long now_usec(void) -{ - struct timespec ts; - - if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) - return 0; - return ts_usec(&ts); -} diff --git a/src/udev/src/libudev.c b/src/udev/src/libudev.c deleted file mode 100644 index d954daef6..000000000 --- a/src/udev/src/libudev.c +++ /dev/null @@ -1,457 +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 <time.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[4]; - unsigned long long rules_path_ts[4]; - int rules_path_count; - char *run_path; - struct udev_list 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, &udev->properties_list, true); - - /* custom config file */ - env = getenv("UDEV_CONFIG_FILE"); - if (env != NULL) { - if (set_value(&config_file, env) == NULL) - goto err; - udev_add_property(udev, "UDEV_CONFIG_FILE", config_file); - } - - /* default config file */ - if (config_file == NULL) - config_file = strdup(SYSCONFDIR "/udev/udev.conf"); - 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_path, val); - continue; - } - if (strcmp(key, "udev_sys") == 0) { - set_value(&udev->sys_path, val); - continue; - } - if (strcmp(key, "udev_rules") == 0) { - set_value(&udev->rules_path[0], val); - udev->rules_path_count = 1; - continue; - } - } - fclose(f); - } - - /* environment overrides config */ - env = getenv("UDEV_LOG"); - if (env != NULL) - udev_set_log_priority(udev, util_log_priority(env)); - - /* 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_path == NULL) - if (set_value(&udev->run_path, "/run/udev") == NULL) - goto err; - - if (udev->rules_path[0] == NULL) { - /* /usr/lib/udev -- system rules */ - udev->rules_path[0] = strdup(PKGLIBEXECDIR "/rules.d"); - if (!udev->rules_path[0]) - goto err; - - /* /run/udev -- runtime rules */ - if (asprintf(&udev->rules_path[2], "%s/rules.d", udev->run_path) < 0) - goto err; - - /* /etc/udev -- local administration rules */ - udev->rules_path[1] = strdup(SYSCONFDIR "/udev/rules.d"); - if (!udev->rules_path[1]) - goto err; - - udev->rules_path_count = 3; - } - - 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_path); - dbg(udev, "rules_path='%s':'%s':'%s'\n", udev->rules_path[0], udev->rules_path[1], udev->rules_path[2]); - 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(&udev->properties_list); - free(udev->dev_path); - free(udev->sys_path); - free(udev->rules_path[0]); - free(udev->rules_path[1]); - free(udev->rules_path[2]); - free(udev->run_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", log_fn); -} - -/** - * 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); -} - -int udev_get_rules_path(struct udev *udev, char **path[], unsigned long long *stamp_usec[]) -{ - *path = udev->rules_path; - if (stamp_usec) - *stamp_usec = udev->rules_path_ts; - return udev->rules_path_count; -} - -/** - * 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 udev_sys= - * in the udev configuration file. - * - * 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; -} - -/** - * 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 == NULL) - return NULL; - return udev->run_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->properties_list, key, value); -} - -struct udev_list_entry *udev_get_properties_list_entry(struct udev *udev) -{ - return udev_list_get_entry(&udev->properties_list); -} diff --git a/src/udev/src/libudev.h b/src/udev/src/libudev.h deleted file mode 100644 index 10e098d4f..000000000 --- a/src/udev/src/libudev.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * libudev - interface to udev device information - * - * Copyright (C) 2008-2011 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); -int udev_device_has_tag(struct udev_device *udev_device, const char *tag); - -/* - * udev_monitor - * - * access to kernel uevents and udev events - */ -struct udev_monitor; -struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor); -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_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent); -int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate); -int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath); -/* run enumeration with active filters */ -int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate); -int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate); -/* return device list */ -struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate); - -/* - * udev_queue - * - * access to the currently running udev events - */ -struct udev_queue; -struct udev_queue *udev_queue_ref(struct udev_queue *udev_queue); -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); - -/* - * udev_util - * - * udev specific utilities - */ -int udev_util_encode_string(const char *str, char *str_enc, size_t len); - - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/src/udev/src/libudev.pc.in b/src/udev/src/libudev.pc.in deleted file mode 100644 index c9a47fc9b..000000000 --- a/src/udev/src/libudev.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: libudev -Description: Library to access udev device information -Version: @VERSION@ -Libs: -L${libdir} -ludev -lrt -Libs.private: -Cflags: -I${includedir} diff --git a/src/udev/src/mtd_probe/75-probe_mtd.rules b/src/udev/src/mtd_probe/75-probe_mtd.rules deleted file mode 100644 index c0e083978..000000000 --- a/src/udev/src/mtd_probe/75-probe_mtd.rules +++ /dev/null @@ -1,8 +0,0 @@ -# do not edit this file, it will be overwritten on update - -ACTION!="add", GOTO="mtd_probe_end" - -KERNEL=="mtd*ro", IMPORT{program}="mtd_probe $devnode" -KERNEL=="mtd*ro", ENV{MTD_FTL}=="smartmedia", IMPORT{builtin}="kmod load sm_ftl" - -LABEL="mtd_probe_end" diff --git a/src/udev/src/mtd_probe/mtd_probe.c b/src/udev/src/mtd_probe/mtd_probe.c deleted file mode 100644 index 1aa08d385..000000000 --- a/src/udev/src/mtd_probe/mtd_probe.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2010 - Maxim Levitsky - * - * mtd_probe is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mtd_probe 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with mtd_probe; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301 USA - */ -#include "mtd_probe.h" -#include <stdio.h> -#include <sys/ioctl.h> -#include <mtd/mtd-user.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdlib.h> - -int main(int argc, char** argv) -{ - if (argc != 2) { - printf("usage: mtd_probe /dev/mtd[n]\n"); - return 1; - } - - int mtd_fd = open(argv[1], O_RDONLY); - if (mtd_fd == -1) { - perror("open"); - exit(-1); - } - - mtd_info_t mtd_info; - int error = ioctl(mtd_fd, MEMGETINFO, &mtd_info); - if (error == -1) { - perror("ioctl"); - exit(-1); - } - - probe_smart_media(mtd_fd, &mtd_info); - return -1; -} diff --git a/src/udev/src/mtd_probe/mtd_probe.h b/src/udev/src/mtd_probe/mtd_probe.h deleted file mode 100644 index 2a37ede57..000000000 --- a/src/udev/src/mtd_probe/mtd_probe.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2010 - Maxim Levitsky - * - * mtd_probe is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mtd_probe 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with mtd_probe; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301 USA - */ - -#include <mtd/mtd-user.h> - -/* Full oob structure as written on the flash */ -struct sm_oob { - uint32_t reserved; - uint8_t data_status; - uint8_t block_status; - uint8_t lba_copy1[2]; - uint8_t ecc2[3]; - uint8_t lba_copy2[2]; - uint8_t ecc1[3]; -} __attribute__((packed)); - - -/* one sector is always 512 bytes, but it can consist of two nand pages */ -#define SM_SECTOR_SIZE 512 - -/* oob area is also 16 bytes, but might be from two pages */ -#define SM_OOB_SIZE 16 - -/* This is maximum zone size, and all devices that have more that one zone - have this size */ -#define SM_MAX_ZONE_SIZE 1024 - -/* support for small page nand */ -#define SM_SMALL_PAGE 256 -#define SM_SMALL_OOB_SIZE 8 - - -void probe_smart_media(int mtd_fd, mtd_info_t *info); diff --git a/src/udev/src/mtd_probe/probe_smartmedia.c b/src/udev/src/mtd_probe/probe_smartmedia.c deleted file mode 100644 index b3cdefc63..000000000 --- a/src/udev/src/mtd_probe/probe_smartmedia.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2010 - Maxim Levitsky - * - * mtd_probe is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mtd_probe 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with mtd_probe; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301 USA - */ - -#include <stdio.h> -#include <stdlib.h> -#include <mtd/mtd-user.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdint.h> -#include <stdlib.h> -#include "mtd_probe.h" - -static const uint8_t cis_signature[] = { - 0x01, 0x03, 0xD9, 0x01, 0xFF, 0x18, 0x02, 0xDF, 0x01, 0x20 -}; - - -void probe_smart_media(int mtd_fd, mtd_info_t* info) -{ - char* cis_buffer = malloc(SM_SECTOR_SIZE); - - if (!cis_buffer) - return; - - if (info->type != MTD_NANDFLASH) - goto exit; - - int sector_size = info->writesize; - int block_size = info->erasesize; - int size_in_megs = info->size / (1024 * 1024); - int spare_count; - - - if (sector_size != SM_SECTOR_SIZE && sector_size != SM_SMALL_PAGE) - goto exit; - - switch(size_in_megs) { - case 1: - case 2: - spare_count = 6; - break; - case 4: - spare_count = 12; - break; - default: - spare_count = 24; - break; - } - - - int offset; - int cis_found = 0; - - for (offset = 0 ; offset < block_size * spare_count ; - offset += sector_size) { - - lseek(mtd_fd, SEEK_SET, offset); - if (read(mtd_fd, cis_buffer, SM_SECTOR_SIZE) == SM_SECTOR_SIZE){ - cis_found = 1; - break; - } - } - - if (!cis_found) - goto exit; - - if (memcmp(cis_buffer, cis_signature, sizeof(cis_signature)) != 0 && - (memcmp(cis_buffer + SM_SMALL_PAGE, cis_signature, - sizeof(cis_signature)) != 0)) - goto exit; - - printf("MTD_FTL=smartmedia\n"); - free(cis_buffer); - exit(0); -exit: - free(cis_buffer); - return; -} diff --git a/src/udev/src/rule_generator/75-cd-aliases-generator.rules b/src/udev/src/rule_generator/75-cd-aliases-generator.rules deleted file mode 100644 index e6da0101d..000000000 --- a/src/udev/src/rule_generator/75-cd-aliases-generator.rules +++ /dev/null @@ -1,9 +0,0 @@ -# these rules generate rules for the /dev/{cdrom,dvd,...} symlinks - -# the "path" of usb/ieee1394 devices changes frequently, use "id" -ACTION=="add", SUBSYSTEM=="block", SUBSYSTEMS=="usb|ieee1394", ENV{ID_CDROM}=="?*", ENV{GENERATED}!="?*", \ - PROGRAM="write_cd_rules by-id", SYMLINK+="%c", GOTO="persistent_cd_end" - -ACTION=="add", SUBSYSTEM=="block", ENV{ID_CDROM}=="?*", ENV{GENERATED}!="?*", PROGRAM="write_cd_rules", SYMLINK+="%c" - -LABEL="persistent_cd_end" diff --git a/src/udev/src/rule_generator/75-persistent-net-generator.rules b/src/udev/src/rule_generator/75-persistent-net-generator.rules deleted file mode 100644 index 4f8057347..000000000 --- a/src/udev/src/rule_generator/75-persistent-net-generator.rules +++ /dev/null @@ -1,102 +0,0 @@ -# do not edit this file, it will be overwritten on update - -# these rules generate rules for persistent network device naming -# -# variables used to communicate: -# MATCHADDR MAC address used for the match -# MATCHID bus_id used for the match -# MATCHDRV driver name used for the match -# MATCHIFTYPE interface type match -# COMMENT comment to add to the generated rule -# INTERFACE_NAME requested name supplied by external tool -# INTERFACE_NEW new interface name returned by rule writer - -ACTION!="add", GOTO="persistent_net_generator_end" -SUBSYSTEM!="net", GOTO="persistent_net_generator_end" - -# ignore the interface if a name has already been set -NAME=="?*", GOTO="persistent_net_generator_end" - -# device name whitelist -KERNEL!="eth*|ath*|wlan*[0-9]|msh*|ra*|sta*|ctc*|lcs*|hsi*", GOTO="persistent_net_generator_end" - -# ignore Xen virtual interfaces -SUBSYSTEMS=="xen", GOTO="persistent_net_generator_end" - -# read MAC address -ENV{MATCHADDR}="$attr{address}" - -# match interface type -ENV{MATCHIFTYPE}="$attr{type}" - -# ignore KVM virtual interfaces -ENV{MATCHADDR}=="52:54:00:*", GOTO="persistent_net_generator_end" -# ignore VMWare virtual interfaces -ENV{MATCHADDR}=="00:0c:29:*|00:50:56:*", GOTO="persistent_net_generator_end" -# ignore Hyper-V virtual interfaces -ENV{MATCHADDR}=="00:15:5d:*", GOTO="persistent_net_generator_end" - -# These vendors are known to violate the local MAC address assignment scheme -# Interlan, DEC (UNIBUS or QBUS), Apollo, Cisco, Racal-Datacom -ENV{MATCHADDR}=="02:07:01:*", GOTO="globally_administered_whitelist" -# 3Com -ENV{MATCHADDR}=="02:60:60:*", GOTO="globally_administered_whitelist" -# 3Com IBM PC; Imagen; Valid; Cisco; Apple -ENV{MATCHADDR}=="02:60:8c:*", GOTO="globally_administered_whitelist" -# Intel -ENV{MATCHADDR}=="02:a0:c9:*", GOTO="globally_administered_whitelist" -# Olivetti -ENV{MATCHADDR}=="02:aa:3c:*", GOTO="globally_administered_whitelist" -# CMC Masscomp; Silicon Graphics; Prime EXL -ENV{MATCHADDR}=="02:cf:1f:*", GOTO="globally_administered_whitelist" -# Prominet Corporation Gigabit Ethernet Switch -ENV{MATCHADDR}=="02:e0:3b:*", GOTO="globally_administered_whitelist" -# BTI (Bus-Tech, Inc.) IBM Mainframes -ENV{MATCHADDR}=="02:e6:d3:*", GOTO="globally_administered_whitelist" -# Realtek -ENV{MATCHADDR}=="52:54:00:*", GOTO="globally_administered_whitelist" -# Novell 2000 -ENV{MATCHADDR}=="52:54:4c:*", GOTO="globally_administered_whitelist" -# Realtec -ENV{MATCHADDR}=="52:54:ab:*", GOTO="globally_administered_whitelist" -# Kingston Technologies -ENV{MATCHADDR}=="e2:0c:0f:*", GOTO="globally_administered_whitelist" -# Xensource -ENV{MATCHADDR}=="00:16:3e:*", GOTO="globally_administered_whitelist" - -# match interface dev_id -ATTR{dev_id}=="?*", ENV{MATCHDEVID}="$attr{dev_id}" - -# do not use "locally administered" MAC address -ENV{MATCHADDR}=="?[2367abef]:*", ENV{MATCHADDR}="" - -# do not use empty address -ENV{MATCHADDR}=="00:00:00:00:00:00", ENV{MATCHADDR}="" - -LABEL="globally_administered_whitelist" - -# build comment line for generated rule: -SUBSYSTEMS=="pci", ENV{COMMENT}="PCI device $attr{vendor}:$attr{device} ($driver)" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="?*", ENV{COMMENT}="USB device 0x$attr{idVendor}:0x$attr{idProduct} ($driver)" -SUBSYSTEMS=="pcmcia", ENV{COMMENT}="PCMCIA device $attr{card_id}:$attr{manf_id} ($driver)" -SUBSYSTEMS=="ieee1394", ENV{COMMENT}="Firewire device $attr{host_id})" - -# ibmveth likes to use "locally administered" MAC addresses -DRIVERS=="ibmveth", ENV{MATCHADDR}="$attr{address}", ENV{COMMENT}="ibmveth ($id)" - -# S/390 uses id matches only, do not use MAC address match -SUBSYSTEMS=="ccwgroup", ENV{COMMENT}="S/390 $driver device at $id", ENV{MATCHID}="$id", ENV{MATCHDRV}="$driver", ENV{MATCHADDR}="" - -# see if we got enough data to create a rule -ENV{MATCHADDR}=="", ENV{MATCHID}=="", ENV{INTERFACE_NAME}=="", GOTO="persistent_net_generator_end" - -# default comment -ENV{COMMENT}=="", ENV{COMMENT}="net device ($attr{driver})" - -# write rule -DRIVERS=="?*", IMPORT{program}="write_net_rules" - -# rename interface if needed -ENV{INTERFACE_NEW}=="?*", NAME="$env{INTERFACE_NEW}" - -LABEL="persistent_net_generator_end" diff --git a/src/udev/src/rule_generator/rule_generator.functions b/src/udev/src/rule_generator/rule_generator.functions deleted file mode 100644 index 2eec1b6ab..000000000 --- a/src/udev/src/rule_generator/rule_generator.functions +++ /dev/null @@ -1,113 +0,0 @@ -# functions used by the udev rule generator - -# Copyright (C) 2006 Marco d'Itri <md@Linux.IT> - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. - -# This program 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 General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -PATH='/usr/bin:/bin:/usr/sbin:/sbin' - -# Read a single line from file $1 in the $DEVPATH directory. -# The function must not return an error even if the file does not exist. -sysread() { - local file="$1" - [ -e "/sys$DEVPATH/$file" ] || return 0 - local value - read value < "/sys$DEVPATH/$file" || return 0 - echo "$value" -} - -sysreadlink() { - local file="$1" - [ -e "/sys$DEVPATH/$file" ] || return 0 - readlink -f /sys$DEVPATH/$file 2> /dev/null || true -} - -# Return true if a directory is writeable. -writeable() { - if ln -s test-link $1/.is-writeable 2> /dev/null; then - rm -f $1/.is-writeable - return 0 - else - return 1 - fi -} - -# Create a lock file for the current rules file. -lock_rules_file() { - RUNDIR=$(udevadm info --run) - [ -e "$RUNDIR" ] || return 0 - - RULES_LOCK="$RUNDIR/.lock-${RULES_FILE##*/}" - - retry=30 - while ! mkdir $RULES_LOCK 2> /dev/null; do - if [ $retry -eq 0 ]; then - echo "Cannot lock $RULES_FILE!" >&2 - exit 2 - fi - sleep 1 - retry=$(($retry - 1)) - done -} - -unlock_rules_file() { - [ "$RULES_LOCK" ] || return 0 - rmdir $RULES_LOCK || true -} - -# Choose the real rules file if it is writeable or a temporary file if not. -# Both files should be checked later when looking for existing rules. -choose_rules_file() { - RUNDIR=$(udevadm info --run) - local tmp_rules_file="$RUNDIR/tmp-rules--${RULES_FILE##*/}" - [ -e "$RULES_FILE" -o -e "$tmp_rules_file" ] || PRINT_HEADER=1 - - if writeable ${RULES_FILE%/*}; then - RO_RULES_FILE='/dev/null' - else - RO_RULES_FILE=$RULES_FILE - RULES_FILE=$tmp_rules_file - fi -} - -# Return the name of the first free device. -raw_find_next_available() { - local links="$1" - - local basename=${links%%[ 0-9]*} - local max=-1 - for name in $links; do - local num=${name#$basename} - [ "$num" ] || num=0 - [ $num -gt $max ] && max=$num - done - - local max=$(($max + 1)) - # "name0" actually is just "name" - [ $max -eq 0 ] && return - echo "$max" -} - -# Find all rules matching a key (with action) and a pattern. -find_all_rules() { - local key="$1" - local linkre="$2" - local match="$3" - - local search='.*[[:space:],]'"$key"'"('"$linkre"')".*' - echo $(sed -n -r -e 's/^#.*//' -e "${match}s/${search}/\1/p" \ - $RO_RULES_FILE \ - $([ -e $RULES_FILE ] && echo $RULES_FILE) \ - 2>/dev/null) -} diff --git a/src/udev/src/rule_generator/write_cd_rules b/src/udev/src/rule_generator/write_cd_rules deleted file mode 100644 index 645b9cd52..000000000 --- a/src/udev/src/rule_generator/write_cd_rules +++ /dev/null @@ -1,126 +0,0 @@ -#!/bin/sh -e - -# This script is run if an optical drive lacks a rule for persistent naming. -# -# It adds symlinks for optical drives based on the device class determined -# by cdrom_id and used ID_PATH to identify the device. - -# (C) 2006 Marco d'Itri <md@Linux.IT> -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. - -# This program 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 General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -# debug, if UDEV_LOG=<debug> -if [ -n "$UDEV_LOG" ]; then - if [ "$UDEV_LOG" -ge 7 ]; then - set -x - fi -fi - -RULES_FILE="/etc/udev/rules.d/70-persistent-cd.rules" - -. /lib/udev/rule_generator.functions - -find_next_available() { - raw_find_next_available "$(find_all_rules 'SYMLINK\+=' "$1")" -} - -write_rule() { - local match="$1" - local link="$2" - local comment="$3" - - { - if [ "$PRINT_HEADER" ]; then - PRINT_HEADER= - echo "# This file was automatically generated by the $0" - echo "# program, run by the cd-aliases-generator.rules rules file." - echo "#" - echo "# You can modify it, as long as you keep each rule on a single" - echo "# line, and set the \$GENERATED variable." - echo "" - fi - - [ "$comment" ] && echo "# $comment" - echo "$match, SYMLINK+=\"$link\", ENV{GENERATED}=\"1\"" - } >> $RULES_FILE - SYMLINKS="$SYMLINKS $link" -} - -if [ -z "$DEVPATH" ]; then - echo "Missing \$DEVPATH." >&2 - exit 1 -fi -if [ -z "$ID_CDROM" ]; then - echo "$DEVPATH is not a CD reader." >&2 - exit 1 -fi - -if [ "$1" ]; then - METHOD="$1" -else - METHOD='by-path' -fi - -case "$METHOD" in - by-path) - if [ -z "$ID_PATH" ]; then - echo "$DEVPATH not supported by path_id. by-id may work." >&2 - exit 1 - fi - RULE="ENV{ID_PATH}==\"$ID_PATH\"" - ;; - - by-id) - if [ "$ID_SERIAL" ]; then - RULE="ENV{ID_SERIAL}==\"$ID_SERIAL\"" - elif [ "$ID_MODEL" -a "$ID_REVISION" ]; then - RULE="ENV{ID_MODEL}==\"$ID_MODEL\", ENV{ID_REVISION}==\"$ID_REVISION\"" - else - echo "$DEVPATH not supported by ata_id. by-path may work." >&2 - exit 1 - fi - ;; - - *) - echo "Invalid argument (must be either by-path or by-id)." >&2 - exit 1 - ;; -esac - -# Prevent concurrent processes from modifying the file at the same time. -lock_rules_file - -# Check if the rules file is writeable. -choose_rules_file - -link_num=$(find_next_available 'cdrom[0-9]*') - -match="SUBSYSTEM==\"block\", ENV{ID_CDROM}==\"?*\", $RULE" - -comment="$ID_MODEL ($ID_PATH)" - - write_rule "$match" "cdrom$link_num" "$comment" -[ "$ID_CDROM_CD_R" -o "$ID_CDROM_CD_RW" ] && \ - write_rule "$match" "cdrw$link_num" -[ "$ID_CDROM_DVD" ] && \ - write_rule "$match" "dvd$link_num" -[ "$ID_CDROM_DVD_R" -o "$ID_CDROM_DVD_RW" -o "$ID_CDROM_DVD_RAM" ] && \ - write_rule "$match" "dvdrw$link_num" -echo >> $RULES_FILE - -unlock_rules_file - -echo $SYMLINKS - -exit 0 diff --git a/src/udev/src/rule_generator/write_net_rules b/src/udev/src/rule_generator/write_net_rules deleted file mode 100644 index bcea4b09d..000000000 --- a/src/udev/src/rule_generator/write_net_rules +++ /dev/null @@ -1,141 +0,0 @@ -#!/bin/sh -e - -# This script is run to create persistent network device naming rules -# based on properties of the device. -# If the interface needs to be renamed, INTERFACE_NEW=<name> will be printed -# on stdout to allow udev to IMPORT it. - -# variables used to communicate: -# MATCHADDR MAC address used for the match -# MATCHID bus_id used for the match -# MATCHDEVID dev_id used for the match -# MATCHDRV driver name used for the match -# MATCHIFTYPE interface type match -# COMMENT comment to add to the generated rule -# INTERFACE_NAME requested name supplied by external tool -# INTERFACE_NEW new interface name returned by rule writer - -# Copyright (C) 2006 Marco d'Itri <md@Linux.IT> -# Copyright (C) 2007 Kay Sievers <kay.sievers@vrfy.org> -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# This program 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -# debug, if UDEV_LOG=<debug> -if [ -n "$UDEV_LOG" ]; then - if [ "$UDEV_LOG" -ge 7 ]; then - set -x - fi -fi - -RULES_FILE='/etc/udev/rules.d/70-persistent-net.rules' - -. /lib/udev/rule_generator.functions - -interface_name_taken() { - local value="$(find_all_rules 'NAME=' $INTERFACE)" - if [ "$value" ]; then - return 0 - else - return 1 - fi -} - -find_next_available() { - raw_find_next_available "$(find_all_rules 'NAME=' "$1")" -} - -write_rule() { - local match="$1" - local name="$2" - local comment="$3" - - { - if [ "$PRINT_HEADER" ]; then - PRINT_HEADER= - echo "# This file was automatically generated by the $0" - echo "# program, run by the persistent-net-generator.rules rules file." - echo "#" - echo "# You can modify it, as long as you keep each rule on a single" - echo "# line, and change only the value of the NAME= key." - fi - - echo "" - [ "$comment" ] && echo "# $comment" - echo "SUBSYSTEM==\"net\", ACTION==\"add\"$match, NAME=\"$name\"" - } >> $RULES_FILE -} - -if [ -z "$INTERFACE" ]; then - echo "missing \$INTERFACE" >&2 - exit 1 -fi - -# Prevent concurrent processes from modifying the file at the same time. -lock_rules_file - -# Check if the rules file is writeable. -choose_rules_file - -# the DRIVERS key is needed to not match bridges and VLAN sub-interfaces -if [ "$MATCHADDR" ]; then - match="$match, DRIVERS==\"?*\", ATTR{address}==\"$MATCHADDR\"" -fi - -if [ "$MATCHDRV" ]; then - match="$match, DRIVERS==\"$MATCHDRV\"" -fi - -if [ "$MATCHDEVID" ]; then - match="$match, ATTR{dev_id}==\"$MATCHDEVID\"" -fi - -if [ "$MATCHID" ]; then - match="$match, KERNELS==\"$MATCHID\"" -fi - -if [ "$MATCHIFTYPE" ]; then - match="$match, ATTR{type}==\"$MATCHIFTYPE\"" -fi - -if [ -z "$match" ]; then - echo "missing valid match" >&2 - unlock_rules_file - exit 1 -fi - -basename=${INTERFACE%%[0-9]*} -match="$match, KERNEL==\"$basename*\"" - -if [ "$INTERFACE_NAME" ]; then - # external tools may request a custom name - COMMENT="$COMMENT (custom name provided by external tool)" - if [ "$INTERFACE_NAME" != "$INTERFACE" ]; then - INTERFACE=$INTERFACE_NAME; - echo "INTERFACE_NEW=$INTERFACE" - fi -else - # if a rule using the current name already exists, find a new name - if interface_name_taken; then - INTERFACE="$basename$(find_next_available "$basename[0-9]*")" - # prevent INTERFACE from being "eth" instead of "eth0" - [ "$INTERFACE" = "${INTERFACE%%[ \[\]0-9]*}" ] && INTERFACE=${INTERFACE}0 - echo "INTERFACE_NEW=$INTERFACE" - fi -fi - -write_rule "$match" "$INTERFACE" "$COMMENT" - -unlock_rules_file - -exit 0 diff --git a/src/udev/src/scsi_id/.gitignore b/src/udev/src/scsi_id/.gitignore deleted file mode 100644 index 6aebddd80..000000000 --- a/src/udev/src/scsi_id/.gitignore +++ /dev/null @@ -1 +0,0 @@ -scsi_id_version.h diff --git a/src/udev/src/scsi_id/README b/src/udev/src/scsi_id/README deleted file mode 100644 index 9cfe73991..000000000 --- a/src/udev/src/scsi_id/README +++ /dev/null @@ -1,4 +0,0 @@ -scsi_id - generate a SCSI unique identifier for a given SCSI device - -Please send questions, comments or patches to <patmans@us.ibm.com> or -<linux-hotplug-devel@lists.sourceforge.net>. diff --git a/src/udev/src/scsi_id/scsi.h b/src/udev/src/scsi_id/scsi.h deleted file mode 100644 index c423cac57..000000000 --- a/src/udev/src/scsi_id/scsi.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * scsi.h - * - * General scsi and linux scsi specific defines and structs. - * - * Copyright (C) IBM Corp. 2003 - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 of the License. - */ - -#include <scsi/scsi.h> - -struct scsi_ioctl_command { - unsigned int inlen; /* excluding scsi command length */ - unsigned int outlen; - unsigned char data[1]; - /* on input, scsi command starts here then opt. data */ -}; - -/* - * Default 5 second timeout - */ -#define DEF_TIMEOUT 5000 - -#define SENSE_BUFF_LEN 32 - -/* - * The request buffer size passed to the SCSI INQUIRY commands, use 254, - * as this is a nice value for some devices, especially some of the usb - * mass storage devices. - */ -#define SCSI_INQ_BUFF_LEN 254 - -/* - * SCSI INQUIRY vendor and model (really product) lengths. - */ -#define VENDOR_LENGTH 8 -#define MODEL_LENGTH 16 - -#define INQUIRY_CMD 0x12 -#define INQUIRY_CMDLEN 6 - -/* - * INQUIRY VPD page 0x83 identifier descriptor related values. Reference the - * SCSI Primary Commands specification for details. - */ - -/* - * id type values of id descriptors. These are assumed to fit in 4 bits. - */ -#define SCSI_ID_VENDOR_SPECIFIC 0 -#define SCSI_ID_T10_VENDOR 1 -#define SCSI_ID_EUI_64 2 -#define SCSI_ID_NAA 3 -#define SCSI_ID_RELPORT 4 -#define SCSI_ID_TGTGROUP 5 -#define SCSI_ID_LUNGROUP 6 -#define SCSI_ID_MD5 7 -#define SCSI_ID_NAME 8 - -/* - * Supported NAA values. These fit in 4 bits, so the "don't care" value - * cannot conflict with real values. - */ -#define SCSI_ID_NAA_DONT_CARE 0xff -#define SCSI_ID_NAA_IEEE_REG 5 -#define SCSI_ID_NAA_IEEE_REG_EXTENDED 6 - -/* - * Supported Code Set values. - */ -#define SCSI_ID_BINARY 1 -#define SCSI_ID_ASCII 2 - -struct scsi_id_search_values { - u_char id_type; - u_char naa_type; - u_char code_set; -}; - -/* - * Following are the "true" SCSI status codes. Linux has traditionally - * used a 1 bit right and masked version of these. So now CHECK_CONDITION - * and friends (in <scsi/scsi.h>) are deprecated. - */ -#define SCSI_CHECK_CONDITION 0x2 -#define SCSI_CONDITION_MET 0x4 -#define SCSI_BUSY 0x8 -#define SCSI_IMMEDIATE 0x10 -#define SCSI_IMMEDIATE_CONDITION_MET 0x14 -#define SCSI_RESERVATION_CONFLICT 0x18 -#define SCSI_COMMAND_TERMINATED 0x22 -#define SCSI_TASK_SET_FULL 0x28 -#define SCSI_ACA_ACTIVE 0x30 -#define SCSI_TASK_ABORTED 0x40 diff --git a/src/udev/src/scsi_id/scsi_id.8 b/src/udev/src/scsi_id/scsi_id.8 deleted file mode 100644 index 0d4dba914..000000000 --- a/src/udev/src/scsi_id/scsi_id.8 +++ /dev/null @@ -1,119 +0,0 @@ -.TH SCSI_ID 8 "December 2003" "" "Linux Administrator's Manual" -.SH NAME -scsi_id \- retrieve and generate a unique SCSI identifier -.SH SYNOPSIS -.BI scsi_id -[\fIoptions\fP] -.SH "DESCRIPTION" -.B scsi_id -queries a SCSI device via the SCSI INQUIRY vital product data (VPD) page 0x80 or -0x83 and uses the resulting data to generate a value that is unique across -all SCSI devices that properly support page 0x80 or page 0x83. - -If a result is generated it is sent to standard output, and the program -exits with a zero value. If no identifier is output, the program exits -with a non\-zero value. - -\fBscsi_id\fP is primarily for use by other utilities such as \fBudev\fP -that require a unique SCSI identifier. - -By default all devices are assumed black listed, the \fB\-\-whitelisted\fP option must -be specified on the command line or in the config file for any useful -behaviour. - -SCSI commands are sent directly to the device via the SG_IO ioctl -interface. - -In order to generate unique values for either page 0x80 or page 0x83, the -serial numbers or world wide names are prefixed as follows. - -Identifiers based on page 0x80 are prefixed by the character 'S', the SCSI -vendor, the SCSI product (model) and then the the serial number returned -by page 0x80. For example: - -.sp -.nf -# /usr/lib/udev/scsi_id \-\-page=0x80 \-\-whitelisted \-\-device=/dev/sda -SIBM 3542 1T05078453 -.fi -.P - -Identifiers based on page 0x83 are prefixed by the identifier type -followed by the page 0x83 identifier. For example, a device with a NAA -(Name Address Authority) type of 3 (also in this case the page 0x83 -identifier starts with the NAA value of 6): - -.sp -.nf -# /usr/lib/udev/scsi_id \-\-page=0x83 \-\-whitelisted \-\-device=/dev/sda -3600a0b80000b174b000000d63efc5c8c -.fi -.P - -.SH OPTIONS -.TP -.BI \-\-blacklisted -The default behaviour \- treat the device as black listed, and do nothing -unless a white listed device is found in the scsi_id config\-file. -.TP -.BI \-\-device=\| device\^ -Send SG_IO commands to \fBdevice\fP, such as \fB/dev/sdc\fP. -.TP -.BI \-\-config=\| config\-file -Read configuration and black/white list entries from -.B config\-file -rather than the default -.B /etc/scsi_id.config -file. -.TP -.BI \-\-whitelisted -Treat the device as white listed. The \fB\-\-whitelisted\fP option must be specified -on the command line or in the scsi_id configuration file for -.B scsi_id -to generate any output. -.TP -.BI \-\-page=\| 0x80 | 0x83 | pre-spc3-83 -Use SCSI INQUIRY VPD page code 0x80, 0x83, or pre-spc3-83. -.sp -The default -behaviour is to query the available VPD pages, and use page 0x83 if found, -else page 0x80 if found, else nothing. -.sp -Page pre-spc3-83 should only be utilized for those scsi devices which -are not compliant with the SPC-2 or SPC-3 format for page 83. While this -option is used for older model 4, 5, and 6 EMC Symmetrix devices, its -use with SPC-2 or SPC-3 compliant devices will fallback to the page 83 -format supported by these devices. -.TP -.BI \-\-replace-whitespace -Reformat the output : replace all whitespaces by underscores. -.TP -.BI \-\-export -Export all data in KEY=<value> format used to import in other programs. -.TP -.BI \-\-verbose -Generate verbose debugging output. -.TP -.BI \-\-version -Display version number and exit. -.RE - -.SH "FILES" -.nf -.ft B -.ft -.TP -\fI/etc/scsi_id.config\fP -Configuration of black/white list entries and per device options: -# one config per line, short match strings match longer strings -# vendor=string[,model=string],options=<per-device scsi_id command line options> -vendor="ATA",options=-p 0x80 -.RE -.fi -.LP -.SH "SEE ALSO" -.BR udev (7) -.SH AUTHORS -Developed by Patrick Mansfield <patmans@us.ibm.com> based on SCSI ID -source included in earlier linux 2.5 kernels, sg_utils source, and SCSI -specifications. diff --git a/src/udev/src/scsi_id/scsi_id.c b/src/udev/src/scsi_id/scsi_id.c deleted file mode 100644 index 9bb0d7f53..000000000 --- a/src/udev/src/scsi_id/scsi_id.c +++ /dev/null @@ -1,657 +0,0 @@ -/* - * Copyright (C) IBM Corp. 2003 - * Copyright (C) SUSE Linux Products GmbH, 2006 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <signal.h> -#include <fcntl.h> -#include <errno.h> -#include <string.h> -#include <syslog.h> -#include <stdarg.h> -#include <ctype.h> -#include <getopt.h> -#include <sys/stat.h> - -#include "libudev.h" -#include "libudev-private.h" -#include "scsi_id.h" - -static const struct option options[] = { - { "device", required_argument, NULL, 'd' }, - { "config", required_argument, NULL, 'f' }, - { "page", required_argument, NULL, 'p' }, - { "blacklisted", no_argument, NULL, 'b' }, - { "whitelisted", no_argument, NULL, 'g' }, - { "replace-whitespace", no_argument, NULL, 'u' }, - { "sg-version", required_argument, NULL, 's' }, - { "verbose", no_argument, NULL, 'v' }, - { "version", no_argument, NULL, 'V' }, - { "export", no_argument, NULL, 'x' }, - { "help", no_argument, NULL, 'h' }, - {} -}; - -static const char short_options[] = "d:f:ghip:uvVx"; -static const char dev_short_options[] = "bgp:"; - -static int all_good; -static int dev_specified; -static char config_file[MAX_PATH_LEN] = SYSCONFDIR "/scsi_id.config"; -static enum page_code default_page_code; -static int sg_version = 4; -static int use_stderr; -static int debug; -static int reformat_serial; -static int export; -static char vendor_str[64]; -static char model_str[64]; -static char vendor_enc_str[256]; -static char model_enc_str[256]; -static char revision_str[16]; -static char type_str[16]; - -static void log_fn(struct udev *udev, int priority, - const char *file, int line, const char *fn, - const char *format, va_list args) -{ - vsyslog(priority, format, args); -} - -static void set_type(const char *from, char *to, size_t len) -{ - int type_num; - char *eptr; - char *type = "generic"; - - type_num = strtoul(from, &eptr, 0); - if (eptr != from) { - switch (type_num) { - case 0: - type = "disk"; - break; - case 1: - type = "tape"; - break; - case 4: - type = "optical"; - break; - case 5: - type = "cd"; - break; - case 7: - type = "optical"; - break; - case 0xe: - type = "disk"; - break; - case 0xf: - type = "optical"; - break; - default: - break; - } - } - util_strscpy(to, len, type); -} - -/* - * get_value: - * - * buf points to an '=' followed by a quoted string ("foo") or a string ending - * with a space or ','. - * - * Return a pointer to the NUL terminated string, returns NULL if no - * matches. - */ -static char *get_value(char **buffer) -{ - static char *quote_string = "\"\n"; - static char *comma_string = ",\n"; - char *val; - char *end; - - if (**buffer == '"') { - /* - * skip leading quote, terminate when quote seen - */ - (*buffer)++; - end = quote_string; - } else { - end = comma_string; - } - val = strsep(buffer, end); - if (val && end == quote_string) - /* - * skip trailing quote - */ - (*buffer)++; - - while (isspace(**buffer)) - (*buffer)++; - - return val; -} - -static int argc_count(char *opts) -{ - int i = 0; - while (*opts != '\0') - if (*opts++ == ' ') - i++; - return i; -} - -/* - * get_file_options: - * - * If vendor == NULL, find a line in the config file with only "OPTIONS="; - * if vendor and model are set find the first OPTIONS line in the config - * file that matches. Set argc and argv to match the OPTIONS string. - * - * vendor and model can end in '\n'. - */ -static int get_file_options(struct udev *udev, - const char *vendor, const char *model, - int *argc, char ***newargv) -{ - char *buffer; - FILE *fd; - char *buf; - char *str1; - char *vendor_in, *model_in, *options_in; /* read in from file */ - int lineno; - int c; - int retval = 0; - - dbg(udev, "vendor='%s'; model='%s'\n", vendor, model); - fd = fopen(config_file, "r"); - if (fd == NULL) { - dbg(udev, "can't open %s\n", config_file); - if (errno == ENOENT) { - return 1; - } else { - err(udev, "can't open %s: %s\n", config_file, strerror(errno)); - return -1; - } - } - - /* - * Allocate a buffer rather than put it on the stack so we can - * keep it around to parse any options (any allocated newargv - * points into this buffer for its strings). - */ - buffer = malloc(MAX_BUFFER_LEN); - if (!buffer) { - fclose(fd); - err(udev, "can't allocate memory\n"); - return -1; - } - - *newargv = NULL; - lineno = 0; - while (1) { - vendor_in = model_in = options_in = NULL; - - buf = fgets(buffer, MAX_BUFFER_LEN, fd); - if (buf == NULL) - break; - lineno++; - if (buf[strlen(buffer) - 1] != '\n') { - err(udev, "Config file line %d too long\n", lineno); - break; - } - - while (isspace(*buf)) - buf++; - - /* blank or all whitespace line */ - if (*buf == '\0') - continue; - - /* comment line */ - if (*buf == '#') - continue; - - dbg(udev, "lineno %d: '%s'\n", lineno, buf); - str1 = strsep(&buf, "="); - if (str1 && strcasecmp(str1, "VENDOR") == 0) { - str1 = get_value(&buf); - if (!str1) { - retval = -1; - break; - } - vendor_in = str1; - - str1 = strsep(&buf, "="); - if (str1 && strcasecmp(str1, "MODEL") == 0) { - str1 = get_value(&buf); - if (!str1) { - retval = -1; - break; - } - model_in = str1; - str1 = strsep(&buf, "="); - } - } - - if (str1 && strcasecmp(str1, "OPTIONS") == 0) { - str1 = get_value(&buf); - if (!str1) { - retval = -1; - break; - } - options_in = str1; - } - dbg(udev, "config file line %d:\n" - " vendor '%s'; model '%s'; options '%s'\n", - lineno, vendor_in, model_in, options_in); - /* - * Only allow: [vendor=foo[,model=bar]]options=stuff - */ - if (!options_in || (!vendor_in && model_in)) { - err(udev, "Error parsing config file line %d '%s'\n", lineno, buffer); - retval = -1; - break; - } - if (vendor == NULL) { - if (vendor_in == NULL) { - dbg(udev, "matched global option\n"); - break; - } - } else if ((vendor_in && strncmp(vendor, vendor_in, - strlen(vendor_in)) == 0) && - (!model_in || (strncmp(model, model_in, - strlen(model_in)) == 0))) { - /* - * Matched vendor and optionally model. - * - * Note: a short vendor_in or model_in can - * give a partial match (that is FOO - * matches FOOBAR). - */ - dbg(udev, "matched vendor/model\n"); - break; - } else { - dbg(udev, "no match\n"); - } - } - - if (retval == 0) { - if (vendor_in != NULL || model_in != NULL || - options_in != NULL) { - /* - * Something matched. Allocate newargv, and store - * values found in options_in. - */ - strcpy(buffer, options_in); - c = argc_count(buffer) + 2; - *newargv = calloc(c, sizeof(**newargv)); - if (!*newargv) { - err(udev, "can't allocate memory\n"); - retval = -1; - } else { - *argc = c; - c = 0; - /* - * argv[0] at 0 is skipped by getopt, but - * store the buffer address there for - * later freeing - */ - (*newargv)[c] = buffer; - for (c = 1; c < *argc; c++) - (*newargv)[c] = strsep(&buffer, " \t"); - } - } else { - /* No matches */ - retval = 1; - } - } - if (retval != 0) - free(buffer); - fclose(fd); - return retval; -} - -static int set_options(struct udev *udev, - int argc, char **argv, const char *short_opts, - char *maj_min_dev) -{ - int option; - - /* - * optind is a global extern used by getopt. Since we can call - * set_options twice (once for command line, and once for config - * file) we have to reset this back to 1. - */ - optind = 1; - while (1) { - option = getopt_long(argc, argv, short_opts, options, NULL); - if (option == -1) - break; - - if (optarg) - dbg(udev, "option '%c' arg '%s'\n", option, optarg); - else - dbg(udev, "option '%c'\n", option); - - switch (option) { - case 'b': - all_good = 0; - break; - - case 'd': - dev_specified = 1; - util_strscpy(maj_min_dev, MAX_PATH_LEN, optarg); - break; - - case 'e': - use_stderr = 1; - break; - - case 'f': - util_strscpy(config_file, MAX_PATH_LEN, optarg); - break; - - case 'g': - all_good = 1; - break; - - case 'h': - printf("Usage: scsi_id OPTIONS <device>\n" - " --device= device node for SG_IO commands\n" - " --config= location of config file\n" - " --page=0x80|0x83|pre-spc3-83 SCSI page (0x80, 0x83, pre-spc3-83)\n" - " --sg-version=3|4 use SGv3 or SGv4\n" - " --blacklisted threat device as blacklisted\n" - " --whitelisted threat device as whitelisted\n" - " --replace-whitespace replace all whitespaces by underscores\n" - " --verbose verbose logging\n" - " --version print version\n" - " --export print values as environment keys\n" - " --help print this help text\n\n"); - exit(0); - - case 'p': - if (strcmp(optarg, "0x80") == 0) { - default_page_code = PAGE_80; - } else if (strcmp(optarg, "0x83") == 0) { - default_page_code = PAGE_83; - } else if (strcmp(optarg, "pre-spc3-83") == 0) { - default_page_code = PAGE_83_PRE_SPC3; - } else { - err(udev, "Unknown page code '%s'\n", optarg); - return -1; - } - break; - - case 's': - sg_version = atoi(optarg); - if (sg_version < 3 || sg_version > 4) { - err(udev, "Unknown SG version '%s'\n", optarg); - return -1; - } - break; - - case 'u': - reformat_serial = 1; - break; - - case 'x': - export = 1; - break; - - case 'v': - debug++; - break; - - case 'V': - printf("%s\n", VERSION); - exit(0); - break; - - default: - exit(1); - } - } - if (optind < argc && !dev_specified) { - dev_specified = 1; - util_strscpy(maj_min_dev, MAX_PATH_LEN, argv[optind]); - } - return 0; -} - -static int per_dev_options(struct udev *udev, - struct scsi_id_device *dev_scsi, int *good_bad, int *page_code) -{ - int retval; - int newargc; - char **newargv = NULL; - int option; - - *good_bad = all_good; - *page_code = default_page_code; - - retval = get_file_options(udev, vendor_str, model_str, &newargc, &newargv); - - optind = 1; /* reset this global extern */ - while (retval == 0) { - option = getopt_long(newargc, newargv, dev_short_options, options, NULL); - if (option == -1) - break; - - if (optarg) - dbg(udev, "option '%c' arg '%s'\n", option, optarg); - else - dbg(udev, "option '%c'\n", option); - - switch (option) { - case 'b': - *good_bad = 0; - break; - - case 'g': - *good_bad = 1; - break; - - case 'p': - if (strcmp(optarg, "0x80") == 0) { - *page_code = PAGE_80; - } else if (strcmp(optarg, "0x83") == 0) { - *page_code = PAGE_83; - } else if (strcmp(optarg, "pre-spc3-83") == 0) { - *page_code = PAGE_83_PRE_SPC3; - } else { - err(udev, "Unknown page code '%s'\n", optarg); - retval = -1; - } - break; - - default: - err(udev, "Unknown or bad option '%c' (0x%x)\n", option, option); - retval = -1; - break; - } - } - - if (newargv) { - free(newargv[0]); - free(newargv); - } - return retval; -} - -static int set_inq_values(struct udev *udev, struct scsi_id_device *dev_scsi, const char *path) -{ - int retval; - - dev_scsi->use_sg = sg_version; - - retval = scsi_std_inquiry(udev, dev_scsi, path); - if (retval) - return retval; - - udev_util_encode_string(dev_scsi->vendor, vendor_enc_str, sizeof(vendor_enc_str)); - udev_util_encode_string(dev_scsi->model, model_enc_str, sizeof(model_enc_str)); - - util_replace_whitespace(dev_scsi->vendor, vendor_str, sizeof(vendor_str)); - util_replace_chars(vendor_str, NULL); - util_replace_whitespace(dev_scsi->model, model_str, sizeof(model_str)); - util_replace_chars(model_str, NULL); - set_type(dev_scsi->type, type_str, sizeof(type_str)); - util_replace_whitespace(dev_scsi->revision, revision_str, sizeof(revision_str)); - util_replace_chars(revision_str, NULL); - return 0; -} - -/* - * scsi_id: try to get an id, if one is found, printf it to stdout. - * returns a value passed to exit() - 0 if printed an id, else 1. - */ -static int scsi_id(struct udev *udev, char *maj_min_dev) -{ - struct scsi_id_device dev_scsi; - int good_dev; - int page_code; - int retval = 0; - - memset(&dev_scsi, 0x00, sizeof(struct scsi_id_device)); - - if (set_inq_values(udev, &dev_scsi, maj_min_dev) < 0) { - retval = 1; - goto out; - } - - /* get per device (vendor + model) options from the config file */ - per_dev_options(udev, &dev_scsi, &good_dev, &page_code); - dbg(udev, "per dev options: good %d; page code 0x%x\n", good_dev, page_code); - if (!good_dev) { - retval = 1; - goto out; - } - - /* read serial number from mode pages (no values for optical drives) */ - scsi_get_serial(udev, &dev_scsi, maj_min_dev, page_code, MAX_SERIAL_LEN); - - if (export) { - char serial_str[MAX_SERIAL_LEN]; - - printf("ID_SCSI=1\n"); - printf("ID_VENDOR=%s\n", vendor_str); - printf("ID_VENDOR_ENC=%s\n", vendor_enc_str); - printf("ID_MODEL=%s\n", model_str); - printf("ID_MODEL_ENC=%s\n", model_enc_str); - printf("ID_REVISION=%s\n", revision_str); - printf("ID_TYPE=%s\n", type_str); - if (dev_scsi.serial[0] != '\0') { - util_replace_whitespace(dev_scsi.serial, serial_str, sizeof(serial_str)); - util_replace_chars(serial_str, NULL); - printf("ID_SERIAL=%s\n", serial_str); - util_replace_whitespace(dev_scsi.serial_short, serial_str, sizeof(serial_str)); - util_replace_chars(serial_str, NULL); - printf("ID_SERIAL_SHORT=%s\n", serial_str); - } - if (dev_scsi.wwn[0] != '\0') { - printf("ID_WWN=0x%s\n", dev_scsi.wwn); - if (dev_scsi.wwn_vendor_extension[0] != '\0') { - printf("ID_WWN_VENDOR_EXTENSION=0x%s\n", dev_scsi.wwn_vendor_extension); - printf("ID_WWN_WITH_EXTENSION=0x%s%s\n", dev_scsi.wwn, dev_scsi.wwn_vendor_extension); - } else { - printf("ID_WWN_WITH_EXTENSION=0x%s\n", dev_scsi.wwn); - } - } - if (dev_scsi.tgpt_group[0] != '\0') { - printf("ID_TARGET_PORT=%s\n", dev_scsi.tgpt_group); - } - if (dev_scsi.unit_serial_number[0] != '\0') { - printf("ID_SCSI_SERIAL=%s\n", dev_scsi.unit_serial_number); - } - goto out; - } - - if (dev_scsi.serial[0] == '\0') { - retval = 1; - goto out; - } - - if (reformat_serial) { - char serial_str[MAX_SERIAL_LEN]; - - util_replace_whitespace(dev_scsi.serial, serial_str, sizeof(serial_str)); - util_replace_chars(serial_str, NULL); - printf("%s\n", serial_str); - goto out; - } - - printf("%s\n", dev_scsi.serial); -out: - return retval; -} - -int main(int argc, char **argv) -{ - struct udev *udev; - int retval = 0; - char maj_min_dev[MAX_PATH_LEN]; - int newargc; - char **newargv; - - udev = udev_new(); - if (udev == NULL) - goto exit; - - udev_log_init("scsi_id"); - udev_set_log_fn(udev, log_fn); - - /* - * Get config file options. - */ - newargv = NULL; - retval = get_file_options(udev, NULL, NULL, &newargc, &newargv); - if (retval < 0) { - retval = 1; - goto exit; - } - if (newargv && (retval == 0)) { - if (set_options(udev, newargc, newargv, short_options, maj_min_dev) < 0) { - retval = 2; - goto exit; - } - free(newargv); - } - - /* - * Get command line options (overriding any config file settings). - */ - if (set_options(udev, argc, argv, short_options, maj_min_dev) < 0) - exit(1); - - if (!dev_specified) { - err(udev, "no device specified\n"); - retval = 1; - goto exit; - } - - retval = scsi_id(udev, maj_min_dev); - -exit: - udev_unref(udev); - udev_log_close(); - return retval; -} diff --git a/src/udev/src/scsi_id/scsi_id.h b/src/udev/src/scsi_id/scsi_id.h deleted file mode 100644 index 828a98305..000000000 --- a/src/udev/src/scsi_id/scsi_id.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) IBM Corp. 2003 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#define MAX_PATH_LEN 512 - -/* - * MAX_ATTR_LEN: maximum length of the result of reading a sysfs - * attribute. - */ -#define MAX_ATTR_LEN 256 - -/* - * MAX_SERIAL_LEN: the maximum length of the serial number, including - * added prefixes such as vendor and product (model) strings. - */ -#define MAX_SERIAL_LEN 256 - -/* - * MAX_BUFFER_LEN: maximum buffer size and line length used while reading - * the config file. - */ -#define MAX_BUFFER_LEN 256 - -struct scsi_id_device { - char vendor[9]; - char model[17]; - char revision[5]; - char type[33]; - char kernel[64]; - char serial[MAX_SERIAL_LEN]; - char serial_short[MAX_SERIAL_LEN]; - int use_sg; - - /* Always from page 0x80 e.g. 'B3G1P8500RWT' - may not be unique */ - char unit_serial_number[MAX_SERIAL_LEN]; - - /* NULs if not set - otherwise hex encoding using lower-case e.g. '50014ee0016eb572' */ - char wwn[17]; - - /* NULs if not set - otherwise hex encoding using lower-case e.g. '0xe00000d80000' */ - char wwn_vendor_extension[17]; - - /* NULs if not set - otherwise decimal number */ - char tgpt_group[8]; -}; - -extern int scsi_std_inquiry(struct udev *udev, struct scsi_id_device *dev_scsi, const char *devname); -extern int scsi_get_serial (struct udev *udev, struct scsi_id_device *dev_scsi, const char *devname, - int page_code, int len); - -/* - * Page code values. - */ -enum page_code { - PAGE_83_PRE_SPC3 = -0x83, - PAGE_UNSPECIFIED = 0x00, - PAGE_80 = 0x80, - PAGE_83 = 0x83, -}; diff --git a/src/udev/src/scsi_id/scsi_serial.c b/src/udev/src/scsi_id/scsi_serial.c deleted file mode 100644 index f1d63f40c..000000000 --- a/src/udev/src/scsi_id/scsi_serial.c +++ /dev/null @@ -1,990 +0,0 @@ -/* - * Copyright (C) IBM Corp. 2003 - * - * Author: Patrick Mansfield<patmans@us.ibm.com> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <sys/types.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <stdio.h> -#include <errno.h> -#include <string.h> -#include <fcntl.h> -#include <stdlib.h> -#include <unistd.h> -#include <syslog.h> -#include <time.h> -#include <inttypes.h> -#include <scsi/scsi.h> -#include <scsi/sg.h> -#include <linux/types.h> -#include <linux/bsg.h> - -#include "libudev.h" -#include "libudev-private.h" -#include "scsi.h" -#include "scsi_id.h" - -/* - * A priority based list of id, naa, and binary/ascii for the identifier - * descriptor in VPD page 0x83. - * - * Brute force search for a match starting with the first value in the - * following id_search_list. This is not a performance issue, since there - * is normally one or some small number of descriptors. - */ -static const struct scsi_id_search_values id_search_list[] = { - { SCSI_ID_TGTGROUP, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY }, - { SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG_EXTENDED, SCSI_ID_BINARY }, - { SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG_EXTENDED, SCSI_ID_ASCII }, - { SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG, SCSI_ID_BINARY }, - { SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG, SCSI_ID_ASCII }, - /* - * Devices already exist using NAA values that are now marked - * reserved. These should not conflict with other values, or it is - * a bug in the device. As long as we find the IEEE extended one - * first, we really don't care what other ones are used. Using - * don't care here means that a device that returns multiple - * non-IEEE descriptors in a random order will get different - * names. - */ - { SCSI_ID_NAA, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY }, - { SCSI_ID_NAA, SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII }, - { SCSI_ID_EUI_64, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY }, - { SCSI_ID_EUI_64, SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII }, - { SCSI_ID_T10_VENDOR, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY }, - { SCSI_ID_T10_VENDOR, SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII }, - { SCSI_ID_VENDOR_SPECIFIC, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY }, - { SCSI_ID_VENDOR_SPECIFIC, SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII }, -}; - -static const char hex_str[]="0123456789abcdef"; - -/* - * Values returned in the result/status, only the ones used by the code - * are used here. - */ - -#define DID_NO_CONNECT 0x01 /* Unable to connect before timeout */ -#define DID_BUS_BUSY 0x02 /* Bus remain busy until timeout */ -#define DID_TIME_OUT 0x03 /* Timed out for some other reason */ -#define DRIVER_TIMEOUT 0x06 -#define DRIVER_SENSE 0x08 /* Sense_buffer has been set */ - -/* The following "category" function returns one of the following */ -#define SG_ERR_CAT_CLEAN 0 /* No errors or other information */ -#define SG_ERR_CAT_MEDIA_CHANGED 1 /* interpreted from sense buffer */ -#define SG_ERR_CAT_RESET 2 /* interpreted from sense buffer */ -#define SG_ERR_CAT_TIMEOUT 3 -#define SG_ERR_CAT_RECOVERED 4 /* Successful command after recovered err */ -#define SG_ERR_CAT_NOTSUPPORTED 5 /* Illegal / unsupported command */ -#define SG_ERR_CAT_SENSE 98 /* Something else in the sense buffer */ -#define SG_ERR_CAT_OTHER 99 /* Some other error/warning */ - -static int do_scsi_page80_inquiry(struct udev *udev, - struct scsi_id_device *dev_scsi, int fd, - char *serial, char *serial_short, int max_len); - -static int sg_err_category_new(struct udev *udev, - int scsi_status, int msg_status, int - host_status, int driver_status, const - unsigned char *sense_buffer, int sb_len) -{ - scsi_status &= 0x7e; - - /* - * XXX change to return only two values - failed or OK. - */ - - if (!scsi_status && !host_status && !driver_status) - return SG_ERR_CAT_CLEAN; - - if ((scsi_status == SCSI_CHECK_CONDITION) || - (scsi_status == SCSI_COMMAND_TERMINATED) || - ((driver_status & 0xf) == DRIVER_SENSE)) { - if (sense_buffer && (sb_len > 2)) { - int sense_key; - unsigned char asc; - - if (sense_buffer[0] & 0x2) { - sense_key = sense_buffer[1] & 0xf; - asc = sense_buffer[2]; - } else { - sense_key = sense_buffer[2] & 0xf; - asc = (sb_len > 12) ? sense_buffer[12] : 0; - } - - if (sense_key == RECOVERED_ERROR) - return SG_ERR_CAT_RECOVERED; - else if (sense_key == UNIT_ATTENTION) { - if (0x28 == asc) - return SG_ERR_CAT_MEDIA_CHANGED; - if (0x29 == asc) - return SG_ERR_CAT_RESET; - } else if (sense_key == ILLEGAL_REQUEST) { - return SG_ERR_CAT_NOTSUPPORTED; - } - } - return SG_ERR_CAT_SENSE; - } - if (host_status) { - if ((host_status == DID_NO_CONNECT) || - (host_status == DID_BUS_BUSY) || - (host_status == DID_TIME_OUT)) - return SG_ERR_CAT_TIMEOUT; - } - if (driver_status) { - if (driver_status == DRIVER_TIMEOUT) - return SG_ERR_CAT_TIMEOUT; - } - return SG_ERR_CAT_OTHER; -} - -static int sg_err_category3(struct udev *udev, struct sg_io_hdr *hp) -{ - return sg_err_category_new(udev, - hp->status, hp->msg_status, - hp->host_status, hp->driver_status, - hp->sbp, hp->sb_len_wr); -} - -static int sg_err_category4(struct udev *udev, struct sg_io_v4 *hp) -{ - return sg_err_category_new(udev, hp->device_status, 0, - hp->transport_status, hp->driver_status, - (unsigned char *)(uintptr_t)hp->response, - hp->response_len); -} - -static int scsi_dump_sense(struct udev *udev, - struct scsi_id_device *dev_scsi, - unsigned char *sense_buffer, int sb_len) -{ - int s; - int code; - int sense_class; - int sense_key; - int asc, ascq; -#ifdef DUMP_SENSE - char out_buffer[256]; - int i, j; -#endif - - /* - * Figure out and print the sense key, asc and ascq. - * - * If you want to suppress these for a particular drive model, add - * a black list entry in the scsi_id config file. - * - * XXX We probably need to: lookup the sense/asc/ascq in a retry - * table, and if found return 1 (after dumping the sense, asc, and - * ascq). So, if/when we get something like a power on/reset, - * we'll retry the command. - */ - - dbg(udev, "got check condition\n"); - - if (sb_len < 1) { - info(udev, "%s: sense buffer empty\n", dev_scsi->kernel); - return -1; - } - - sense_class = (sense_buffer[0] >> 4) & 0x07; - code = sense_buffer[0] & 0xf; - - if (sense_class == 7) { - /* - * extended sense data. - */ - s = sense_buffer[7] + 8; - if (sb_len < s) { - info(udev, "%s: sense buffer too small %d bytes, %d bytes too short\n", - dev_scsi->kernel, sb_len, s - sb_len); - return -1; - } - if ((code == 0x0) || (code == 0x1)) { - sense_key = sense_buffer[2] & 0xf; - if (s < 14) { - /* - * Possible? - */ - info(udev, "%s: sense result too" " small %d bytes\n", - dev_scsi->kernel, s); - return -1; - } - asc = sense_buffer[12]; - ascq = sense_buffer[13]; - } else if ((code == 0x2) || (code == 0x3)) { - sense_key = sense_buffer[1] & 0xf; - asc = sense_buffer[2]; - ascq = sense_buffer[3]; - } else { - info(udev, "%s: invalid sense code 0x%x\n", - dev_scsi->kernel, code); - return -1; - } - info(udev, "%s: sense key 0x%x ASC 0x%x ASCQ 0x%x\n", - dev_scsi->kernel, sense_key, asc, ascq); - } else { - if (sb_len < 4) { - info(udev, "%s: sense buffer too small %d bytes, %d bytes too short\n", - dev_scsi->kernel, sb_len, 4 - sb_len); - return -1; - } - - if (sense_buffer[0] < 15) - info(udev, "%s: old sense key: 0x%x\n", dev_scsi->kernel, sense_buffer[0] & 0x0f); - else - info(udev, "%s: sense = %2x %2x\n", - dev_scsi->kernel, sense_buffer[0], sense_buffer[2]); - info(udev, "%s: non-extended sense class %d code 0x%0x\n", - dev_scsi->kernel, sense_class, code); - - } - -#ifdef DUMP_SENSE - for (i = 0, j = 0; (i < s) && (j < 254); i++) { - dbg(udev, "i %d, j %d\n", i, j); - out_buffer[j++] = hex_str[(sense_buffer[i] & 0xf0) >> 4]; - out_buffer[j++] = hex_str[sense_buffer[i] & 0x0f]; - out_buffer[j++] = ' '; - } - out_buffer[j] = '\0'; - info(udev, "%s: sense dump:\n", dev_scsi->kernel); - info(udev, "%s: %s\n", dev_scsi->kernel, out_buffer); - -#endif - return -1; -} - -static int scsi_dump(struct udev *udev, - struct scsi_id_device *dev_scsi, struct sg_io_hdr *io) -{ - if (!io->status && !io->host_status && !io->msg_status && - !io->driver_status) { - /* - * Impossible, should not be called. - */ - info(udev, "%s: called with no error\n", __FUNCTION__); - return -1; - } - - info(udev, "%s: sg_io failed status 0x%x 0x%x 0x%x 0x%x\n", - dev_scsi->kernel, io->driver_status, io->host_status, io->msg_status, io->status); - if (io->status == SCSI_CHECK_CONDITION) - return scsi_dump_sense(udev, dev_scsi, io->sbp, io->sb_len_wr); - else - return -1; -} - -static int scsi_dump_v4(struct udev *udev, - struct scsi_id_device *dev_scsi, struct sg_io_v4 *io) -{ - if (!io->device_status && !io->transport_status && - !io->driver_status) { - /* - * Impossible, should not be called. - */ - info(udev, "%s: called with no error\n", __FUNCTION__); - return -1; - } - - info(udev, "%s: sg_io failed status 0x%x 0x%x 0x%x\n", - dev_scsi->kernel, io->driver_status, io->transport_status, - io->device_status); - if (io->device_status == SCSI_CHECK_CONDITION) - return scsi_dump_sense(udev, dev_scsi, (unsigned char *)(uintptr_t)io->response, - io->response_len); - else - return -1; -} - -static int scsi_inquiry(struct udev *udev, - struct scsi_id_device *dev_scsi, int fd, - unsigned char evpd, unsigned char page, - unsigned char *buf, unsigned int buflen) -{ - unsigned char inq_cmd[INQUIRY_CMDLEN] = - { INQUIRY_CMD, evpd, page, 0, buflen, 0 }; - unsigned char sense[SENSE_BUFF_LEN]; - void *io_buf; - struct sg_io_v4 io_v4; - struct sg_io_hdr io_hdr; - int retry = 3; /* rather random */ - int retval; - - if (buflen > SCSI_INQ_BUFF_LEN) { - info(udev, "buflen %d too long\n", buflen); - return -1; - } - -resend: - dbg(udev, "%s evpd %d, page 0x%x\n", dev_scsi->kernel, evpd, page); - - if (dev_scsi->use_sg == 4) { - memset(&io_v4, 0, sizeof(struct sg_io_v4)); - io_v4.guard = 'Q'; - io_v4.protocol = BSG_PROTOCOL_SCSI; - io_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD; - io_v4.request_len = sizeof(inq_cmd); - io_v4.request = (uintptr_t)inq_cmd; - io_v4.max_response_len = sizeof(sense); - io_v4.response = (uintptr_t)sense; - io_v4.din_xfer_len = buflen; - io_v4.din_xferp = (uintptr_t)buf; - io_buf = (void *)&io_v4; - } else { - memset(&io_hdr, 0, sizeof(struct sg_io_hdr)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(inq_cmd); - io_hdr.mx_sb_len = sizeof(sense); - io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.dxfer_len = buflen; - io_hdr.dxferp = buf; - io_hdr.cmdp = inq_cmd; - io_hdr.sbp = sense; - io_hdr.timeout = DEF_TIMEOUT; - io_buf = (void *)&io_hdr; - } - - retval = ioctl(fd, SG_IO, io_buf); - if (retval < 0) { - if ((errno == EINVAL || errno == ENOSYS) && dev_scsi->use_sg == 4) { - dev_scsi->use_sg = 3; - goto resend; - } - info(udev, "%s: ioctl failed: %s\n", dev_scsi->kernel, strerror(errno)); - goto error; - } - - if (dev_scsi->use_sg == 4) - retval = sg_err_category4(udev, io_buf); - else - retval = sg_err_category3(udev, io_buf); - - switch (retval) { - case SG_ERR_CAT_NOTSUPPORTED: - buf[1] = 0; - /* Fallthrough */ - case SG_ERR_CAT_CLEAN: - case SG_ERR_CAT_RECOVERED: - retval = 0; - break; - - default: - if (dev_scsi->use_sg == 4) - retval = scsi_dump_v4(udev, dev_scsi, io_buf); - else - retval = scsi_dump(udev, dev_scsi, io_buf); - } - - if (!retval) { - retval = buflen; - } else if (retval > 0) { - if (--retry > 0) { - dbg(udev, "%s: Retrying ...\n", dev_scsi->kernel); - goto resend; - } - retval = -1; - } - -error: - if (retval < 0) - info(udev, "%s: Unable to get INQUIRY vpd %d page 0x%x.\n", - dev_scsi->kernel, evpd, page); - - return retval; -} - -/* Get list of supported EVPD pages */ -static int do_scsi_page0_inquiry(struct udev *udev, - struct scsi_id_device *dev_scsi, int fd, - unsigned char *buffer, unsigned int len) -{ - int retval; - - memset(buffer, 0, len); - retval = scsi_inquiry(udev, dev_scsi, fd, 1, 0x0, buffer, len); - if (retval < 0) - return 1; - - if (buffer[1] != 0) { - info(udev, "%s: page 0 not available.\n", dev_scsi->kernel); - return 1; - } - if (buffer[3] > len) { - info(udev, "%s: page 0 buffer too long %d\n", dev_scsi->kernel, buffer[3]); - return 1; - } - - /* - * Following check is based on code once included in the 2.5.x - * kernel. - * - * Some ill behaved devices return the standard inquiry here - * rather than the evpd data, snoop the data to verify. - */ - if (buffer[3] > MODEL_LENGTH) { - /* - * If the vendor id appears in the page assume the page is - * invalid. - */ - if (!strncmp((char *)&buffer[VENDOR_LENGTH], dev_scsi->vendor, VENDOR_LENGTH)) { - info(udev, "%s: invalid page0 data\n", dev_scsi->kernel); - return 1; - } - } - return 0; -} - -/* - * The caller checks that serial is long enough to include the vendor + - * model. - */ -static int prepend_vendor_model(struct udev *udev, - struct scsi_id_device *dev_scsi, char *serial) -{ - int ind; - - strncpy(serial, dev_scsi->vendor, VENDOR_LENGTH); - strncat(serial, dev_scsi->model, MODEL_LENGTH); - ind = strlen(serial); - - /* - * This is not a complete check, since we are using strncat/cpy - * above, ind will never be too large. - */ - if (ind != (VENDOR_LENGTH + MODEL_LENGTH)) { - info(udev, "%s: expected length %d, got length %d\n", - dev_scsi->kernel, (VENDOR_LENGTH + MODEL_LENGTH), ind); - return -1; - } - return ind; -} - -/** - * check_fill_0x83_id - check the page 0x83 id, if OK allocate and fill - * serial number. - **/ -static int check_fill_0x83_id(struct udev *udev, - struct scsi_id_device *dev_scsi, - unsigned char *page_83, - const struct scsi_id_search_values - *id_search, char *serial, char *serial_short, - int max_len, char *wwn, - char *wwn_vendor_extension, char *tgpt_group) -{ - int i, j, s, len; - - /* - * ASSOCIATION must be with the device (value 0) - * or with the target port for SCSI_ID_TGTPORT - */ - if ((page_83[1] & 0x30) == 0x10) { - if (id_search->id_type != SCSI_ID_TGTGROUP) - return 1; - } else if ((page_83[1] & 0x30) != 0) { - return 1; - } - - if ((page_83[1] & 0x0f) != id_search->id_type) - return 1; - - /* - * Possibly check NAA sub-type. - */ - if ((id_search->naa_type != SCSI_ID_NAA_DONT_CARE) && - (id_search->naa_type != (page_83[4] & 0xf0) >> 4)) - return 1; - - /* - * Check for matching code set - ASCII or BINARY. - */ - if ((page_83[0] & 0x0f) != id_search->code_set) - return 1; - - /* - * page_83[3]: identifier length - */ - len = page_83[3]; - if ((page_83[0] & 0x0f) != SCSI_ID_ASCII) - /* - * If not ASCII, use two bytes for each binary value. - */ - len *= 2; - - /* - * Add one byte for the NUL termination, and one for the id_type. - */ - len += 2; - if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC) - len += VENDOR_LENGTH + MODEL_LENGTH; - - if (max_len < len) { - info(udev, "%s: length %d too short - need %d\n", - dev_scsi->kernel, max_len, len); - return 1; - } - - if (id_search->id_type == SCSI_ID_TGTGROUP && tgpt_group != NULL) { - unsigned int group; - - group = ((unsigned int)page_83[6] << 8) | page_83[7]; - sprintf(tgpt_group,"%x", group); - return 1; - } - - serial[0] = hex_str[id_search->id_type]; - - /* - * For SCSI_ID_VENDOR_SPECIFIC prepend the vendor and model before - * the id since it is not unique across all vendors and models, - * this differs from SCSI_ID_T10_VENDOR, where the vendor is - * included in the identifier. - */ - if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC) - if (prepend_vendor_model(udev, dev_scsi, &serial[1]) < 0) { - dbg(udev, "prepend failed\n"); - return 1; - } - - i = 4; /* offset to the start of the identifier */ - s = j = strlen(serial); - if ((page_83[0] & 0x0f) == SCSI_ID_ASCII) { - /* - * ASCII descriptor. - */ - while (i < (4 + page_83[3])) - serial[j++] = page_83[i++]; - } else { - /* - * Binary descriptor, convert to ASCII, using two bytes of - * ASCII for each byte in the page_83. - */ - while (i < (4 + page_83[3])) { - serial[j++] = hex_str[(page_83[i] & 0xf0) >> 4]; - serial[j++] = hex_str[page_83[i] & 0x0f]; - i++; - } - } - - strcpy(serial_short, &serial[s]); - - if (id_search->id_type == SCSI_ID_NAA && wwn != NULL) { - strncpy(wwn, &serial[s], 16); - if (wwn_vendor_extension != NULL) { - strncpy(wwn_vendor_extension, &serial[s + 16], 16); - } - } - - return 0; -} - -/* Extract the raw binary from VPD 0x83 pre-SPC devices */ -static int check_fill_0x83_prespc3(struct udev *udev, - struct scsi_id_device *dev_scsi, - unsigned char *page_83, - const struct scsi_id_search_values - *id_search, char *serial, char *serial_short, int max_len) -{ - int i, j; - - dbg(udev, "using pre-spc3-83 for %s\n", dev_scsi->kernel); - serial[0] = hex_str[id_search->id_type]; - /* serial has been memset to zero before */ - j = strlen(serial); /* j = 1; */ - - for (i = 0; (i < page_83[3]) && (j < max_len-3); ++i) { - serial[j++] = hex_str[(page_83[4+i] & 0xf0) >> 4]; - serial[j++] = hex_str[ page_83[4+i] & 0x0f]; - } - serial[max_len-1] = 0; - strncpy(serial_short, serial, max_len-1); - return 0; -} - - -/* Get device identification VPD page */ -static int do_scsi_page83_inquiry(struct udev *udev, - struct scsi_id_device *dev_scsi, int fd, - char *serial, char *serial_short, int len, - char *unit_serial_number, char *wwn, - char *wwn_vendor_extension, char *tgpt_group) -{ - int retval; - unsigned int id_ind, j; - unsigned char page_83[SCSI_INQ_BUFF_LEN]; - - /* also pick up the page 80 serial number */ - do_scsi_page80_inquiry(udev, dev_scsi, fd, NULL, unit_serial_number, MAX_SERIAL_LEN); - - memset(page_83, 0, SCSI_INQ_BUFF_LEN); - retval = scsi_inquiry(udev, dev_scsi, fd, 1, PAGE_83, page_83, - SCSI_INQ_BUFF_LEN); - if (retval < 0) - return 1; - - if (page_83[1] != PAGE_83) { - info(udev, "%s: Invalid page 0x83\n", dev_scsi->kernel); - return 1; - } - - /* - * XXX Some devices (IBM 3542) return all spaces for an identifier if - * the LUN is not actually configured. This leads to identifiers of - * the form: "1 ". - */ - - /* - * Model 4, 5, and (some) model 6 EMC Symmetrix devices return - * a page 83 reply according to SCSI-2 format instead of SPC-2/3. - * - * The SCSI-2 page 83 format returns an IEEE WWN in binary - * encoded hexi-decimal in the 16 bytes following the initial - * 4-byte page 83 reply header. - * - * Both the SPC-2 and SPC-3 formats return an IEEE WWN as part - * of an Identification descriptor. The 3rd byte of the first - * Identification descriptor is a reserved (BSZ) byte field. - * - * Reference the 7th byte of the page 83 reply to determine - * whether the reply is compliant with SCSI-2 or SPC-2/3 - * specifications. A zero value in the 7th byte indicates - * an SPC-2/3 conformant reply, (i.e., the reserved field of the - * first Identification descriptor). This byte will be non-zero - * for a SCSI-2 conformant page 83 reply from these EMC - * Symmetrix models since the 7th byte of the reply corresponds - * to the 4th and 5th nibbles of the 6-byte OUI for EMC, that is, - * 0x006048. - */ - - if (page_83[6] != 0) - return check_fill_0x83_prespc3(udev, - dev_scsi, page_83, id_search_list, - serial, serial_short, len); - - /* - * Search for a match in the prioritized id_search_list - since WWN ids - * come first we can pick up the WWN in check_fill_0x83_id(). - */ - for (id_ind = 0; - id_ind < sizeof(id_search_list)/sizeof(id_search_list[0]); - id_ind++) { - /* - * Examine each descriptor returned. There is normally only - * one or a small number of descriptors. - */ - for (j = 4; j <= (unsigned int)page_83[3] + 3; j += page_83[j + 3] + 4) { - retval = check_fill_0x83_id(udev, - dev_scsi, &page_83[j], - &id_search_list[id_ind], - serial, serial_short, len, - wwn, wwn_vendor_extension, - tgpt_group); - dbg(udev, "%s id desc %d/%d/%d\n", dev_scsi->kernel, - id_search_list[id_ind].id_type, - id_search_list[id_ind].naa_type, - id_search_list[id_ind].code_set); - if (!retval) { - dbg(udev, " used\n"); - return retval; - } else if (retval < 0) { - dbg(udev, " failed\n"); - return retval; - } else { - dbg(udev, " not used\n"); - } - } - } - return 1; -} - -/* - * Get device identification VPD page for older SCSI-2 device which is not - * compliant with either SPC-2 or SPC-3 format. - * - * Return the hard coded error code value 2 if the page 83 reply is not - * conformant to the SCSI-2 format. - */ -static int do_scsi_page83_prespc3_inquiry(struct udev *udev, - struct scsi_id_device *dev_scsi, int fd, - char *serial, char *serial_short, int len) -{ - int retval; - int i, j; - unsigned char page_83[SCSI_INQ_BUFF_LEN]; - - memset(page_83, 0, SCSI_INQ_BUFF_LEN); - retval = scsi_inquiry(udev, dev_scsi, fd, 1, PAGE_83, page_83, SCSI_INQ_BUFF_LEN); - if (retval < 0) - return 1; - - if (page_83[1] != PAGE_83) { - info(udev, "%s: Invalid page 0x83\n", dev_scsi->kernel); - return 1; - } - /* - * Model 4, 5, and (some) model 6 EMC Symmetrix devices return - * a page 83 reply according to SCSI-2 format instead of SPC-2/3. - * - * The SCSI-2 page 83 format returns an IEEE WWN in binary - * encoded hexi-decimal in the 16 bytes following the initial - * 4-byte page 83 reply header. - * - * Both the SPC-2 and SPC-3 formats return an IEEE WWN as part - * of an Identification descriptor. The 3rd byte of the first - * Identification descriptor is a reserved (BSZ) byte field. - * - * Reference the 7th byte of the page 83 reply to determine - * whether the reply is compliant with SCSI-2 or SPC-2/3 - * specifications. A zero value in the 7th byte indicates - * an SPC-2/3 conformant reply, (i.e., the reserved field of the - * first Identification descriptor). This byte will be non-zero - * for a SCSI-2 conformant page 83 reply from these EMC - * Symmetrix models since the 7th byte of the reply corresponds - * to the 4th and 5th nibbles of the 6-byte OUI for EMC, that is, - * 0x006048. - */ - if (page_83[6] == 0) - return 2; - - serial[0] = hex_str[id_search_list[0].id_type]; - /* - * The first four bytes contain data, not a descriptor. - */ - i = 4; - j = strlen(serial); - /* - * Binary descriptor, convert to ASCII, - * using two bytes of ASCII for each byte - * in the page_83. - */ - while (i < (page_83[3]+4)) { - serial[j++] = hex_str[(page_83[i] & 0xf0) >> 4]; - serial[j++] = hex_str[page_83[i] & 0x0f]; - i++; - } - dbg(udev, "using pre-spc3-83 for %s\n", dev_scsi->kernel); - return 0; -} - -/* Get unit serial number VPD page */ -static int do_scsi_page80_inquiry(struct udev *udev, - struct scsi_id_device *dev_scsi, int fd, - char *serial, char *serial_short, int max_len) -{ - int retval; - int ser_ind; - int i; - int len; - unsigned char buf[SCSI_INQ_BUFF_LEN]; - - memset(buf, 0, SCSI_INQ_BUFF_LEN); - retval = scsi_inquiry(udev, dev_scsi, fd, 1, PAGE_80, buf, SCSI_INQ_BUFF_LEN); - if (retval < 0) - return retval; - - if (buf[1] != PAGE_80) { - info(udev, "%s: Invalid page 0x80\n", dev_scsi->kernel); - return 1; - } - - len = 1 + VENDOR_LENGTH + MODEL_LENGTH + buf[3]; - if (max_len < len) { - info(udev, "%s: length %d too short - need %d\n", - dev_scsi->kernel, max_len, len); - return 1; - } - /* - * Prepend 'S' to avoid unlikely collision with page 0x83 vendor - * specific type where we prepend '0' + vendor + model. - */ - len = buf[3]; - if (serial != NULL) { - serial[0] = 'S'; - ser_ind = prepend_vendor_model(udev, dev_scsi, &serial[1]); - if (ser_ind < 0) - return 1; - for (i = 4; i < len + 4; i++, ser_ind++) - serial[ser_ind] = buf[i]; - } - if (serial_short != NULL) { - memcpy(serial_short, &buf[4], len); - serial_short[len] = '\0'; - } - return 0; -} - -int scsi_std_inquiry(struct udev *udev, - struct scsi_id_device *dev_scsi, const char *devname) -{ - int fd; - unsigned char buf[SCSI_INQ_BUFF_LEN]; - struct stat statbuf; - int err = 0; - - dbg(udev, "opening %s\n", devname); - fd = open(devname, O_RDONLY | O_NONBLOCK); - if (fd < 0) { - info(udev, "scsi_id: cannot open %s: %s\n", - devname, strerror(errno)); - return 1; - } - - if (fstat(fd, &statbuf) < 0) { - info(udev, "scsi_id: cannot stat %s: %s\n", - devname, strerror(errno)); - err = 2; - goto out; - } - sprintf(dev_scsi->kernel,"%d:%d", major(statbuf.st_rdev), - minor(statbuf.st_rdev)); - - memset(buf, 0, SCSI_INQ_BUFF_LEN); - err = scsi_inquiry(udev, dev_scsi, fd, 0, 0, buf, SCSI_INQ_BUFF_LEN); - if (err < 0) - goto out; - - err = 0; - memcpy(dev_scsi->vendor, buf + 8, 8); - dev_scsi->vendor[8] = '\0'; - memcpy(dev_scsi->model, buf + 16, 16); - dev_scsi->model[16] = '\0'; - memcpy(dev_scsi->revision, buf + 32, 4); - dev_scsi->revision[4] = '\0'; - sprintf(dev_scsi->type,"%x", buf[0] & 0x1f); - -out: - close(fd); - return err; -} - -int scsi_get_serial(struct udev *udev, - struct scsi_id_device *dev_scsi, const char *devname, - int page_code, int len) -{ - unsigned char page0[SCSI_INQ_BUFF_LEN]; - int fd = -1; - int cnt; - int ind; - int retval; - - memset(dev_scsi->serial, 0, len); - dbg(udev, "opening %s\n", devname); - srand((unsigned int)getpid()); - for (cnt = 20; cnt > 0; cnt--) { - struct timespec duration; - - fd = open(devname, O_RDONLY | O_NONBLOCK); - if (fd >= 0 || errno != EBUSY) - break; - duration.tv_sec = 0; - duration.tv_nsec = (200 * 1000 * 1000) + (rand() % 100 * 1000 * 1000); - nanosleep(&duration, NULL); - } - if (fd < 0) - return 1; - - if (page_code == PAGE_80) { - if (do_scsi_page80_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len)) { - retval = 1; - goto completed; - } else { - retval = 0; - goto completed; - } - } else if (page_code == PAGE_83) { - if (do_scsi_page83_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) { - retval = 1; - goto completed; - } else { - retval = 0; - goto completed; - } - } else if (page_code == PAGE_83_PRE_SPC3) { - retval = do_scsi_page83_prespc3_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len); - if (retval) { - /* - * Fallback to servicing a SPC-2/3 compliant page 83 - * inquiry if the page 83 reply format does not - * conform to pre-SPC3 expectations. - */ - if (retval == 2) { - if (do_scsi_page83_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) { - retval = 1; - goto completed; - } else { - retval = 0; - goto completed; - } - } - else { - retval = 1; - goto completed; - } - } else { - retval = 0; - goto completed; - } - } else if (page_code != 0x00) { - info(udev, "%s: unsupported page code 0x%d\n", dev_scsi->kernel, page_code); - return 1; - } - - /* - * Get page 0, the page of the pages. By default, try from best to - * worst of supported pages: 0x83 then 0x80. - */ - if (do_scsi_page0_inquiry(udev, dev_scsi, fd, page0, SCSI_INQ_BUFF_LEN)) { - /* - * Don't try anything else. Black list if a specific page - * should be used for this vendor+model, or maybe have an - * optional fall-back to page 0x80 or page 0x83. - */ - retval = 1; - goto completed; - } - - dbg(udev, "%s: Checking page0\n", dev_scsi->kernel); - - for (ind = 4; ind <= page0[3] + 3; ind++) - if (page0[ind] == PAGE_83) - if (!do_scsi_page83_inquiry(udev, dev_scsi, fd, - dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) { - /* - * Success - */ - retval = 0; - goto completed; - } - - for (ind = 4; ind <= page0[3] + 3; ind++) - if (page0[ind] == PAGE_80) - if (!do_scsi_page80_inquiry(udev, dev_scsi, fd, - dev_scsi->serial, dev_scsi->serial_short, len)) { - /* - * Success - */ - retval = 0; - goto completed; - } - retval = 1; - -completed: - close(fd); - return retval; -} diff --git a/src/udev/src/sd-daemon.c b/src/udev/src/sd-daemon.c deleted file mode 100644 index 763e079b4..000000000 --- a/src/udev/src/sd-daemon.c +++ /dev/null @@ -1,530 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - Copyright 2010 Lennart Poettering - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -***/ - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <sys/un.h> -#ifdef __BIONIC__ -#include <linux/fcntl.h> -#else -#include <sys/fcntl.h> -#endif -#include <netinet/in.h> -#include <stdlib.h> -#include <errno.h> -#include <unistd.h> -#include <string.h> -#include <stdarg.h> -#include <stdio.h> -#include <stddef.h> -#include <limits.h> - -#if defined(__linux__) -#include <mqueue.h> -#endif - -#include "sd-daemon.h" - -#if (__GNUC__ >= 4) -#ifdef SD_EXPORT_SYMBOLS -/* Export symbols */ -#define _sd_export_ __attribute__ ((visibility("default"))) -#else -/* Don't export the symbols */ -#define _sd_export_ __attribute__ ((visibility("hidden"))) -#endif -#else -#define _sd_export_ -#endif - -_sd_export_ int sd_listen_fds(int unset_environment) { - -#if defined(DISABLE_SYSTEMD) || !defined(__linux__) - return 0; -#else - int r, fd; - const char *e; - char *p = NULL; - unsigned long l; - - if (!(e = getenv("LISTEN_PID"))) { - r = 0; - goto finish; - } - - errno = 0; - l = strtoul(e, &p, 10); - - if (errno != 0) { - r = -errno; - goto finish; - } - - if (!p || *p || l <= 0) { - r = -EINVAL; - goto finish; - } - - /* Is this for us? */ - if (getpid() != (pid_t) l) { - r = 0; - goto finish; - } - - if (!(e = getenv("LISTEN_FDS"))) { - r = 0; - goto finish; - } - - errno = 0; - l = strtoul(e, &p, 10); - - if (errno != 0) { - r = -errno; - goto finish; - } - - if (!p || *p) { - r = -EINVAL; - goto finish; - } - - for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) { - int flags; - - if ((flags = fcntl(fd, F_GETFD)) < 0) { - r = -errno; - goto finish; - } - - if (flags & FD_CLOEXEC) - continue; - - if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) { - r = -errno; - goto finish; - } - } - - r = (int) l; - -finish: - if (unset_environment) { - unsetenv("LISTEN_PID"); - unsetenv("LISTEN_FDS"); - } - - return r; -#endif -} - -_sd_export_ int sd_is_fifo(int fd, const char *path) { - struct stat st_fd; - - if (fd < 0) - return -EINVAL; - - memset(&st_fd, 0, sizeof(st_fd)); - if (fstat(fd, &st_fd) < 0) - return -errno; - - if (!S_ISFIFO(st_fd.st_mode)) - return 0; - - if (path) { - struct stat st_path; - - memset(&st_path, 0, sizeof(st_path)); - if (stat(path, &st_path) < 0) { - - if (errno == ENOENT || errno == ENOTDIR) - return 0; - - return -errno; - } - - return - st_path.st_dev == st_fd.st_dev && - st_path.st_ino == st_fd.st_ino; - } - - return 1; -} - -_sd_export_ int sd_is_special(int fd, const char *path) { - struct stat st_fd; - - if (fd < 0) - return -EINVAL; - - if (fstat(fd, &st_fd) < 0) - return -errno; - - if (!S_ISREG(st_fd.st_mode) && !S_ISCHR(st_fd.st_mode)) - return 0; - - if (path) { - struct stat st_path; - - if (stat(path, &st_path) < 0) { - - if (errno == ENOENT || errno == ENOTDIR) - return 0; - - return -errno; - } - - if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode)) - return - st_path.st_dev == st_fd.st_dev && - st_path.st_ino == st_fd.st_ino; - else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode)) - return st_path.st_rdev == st_fd.st_rdev; - else - return 0; - } - - return 1; -} - -static int sd_is_socket_internal(int fd, int type, int listening) { - struct stat st_fd; - - if (fd < 0 || type < 0) - return -EINVAL; - - if (fstat(fd, &st_fd) < 0) - return -errno; - - if (!S_ISSOCK(st_fd.st_mode)) - return 0; - - if (type != 0) { - int other_type = 0; - socklen_t l = sizeof(other_type); - - if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0) - return -errno; - - if (l != sizeof(other_type)) - return -EINVAL; - - if (other_type != type) - return 0; - } - - if (listening >= 0) { - int accepting = 0; - socklen_t l = sizeof(accepting); - - if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0) - return -errno; - - if (l != sizeof(accepting)) - return -EINVAL; - - if (!accepting != !listening) - return 0; - } - - return 1; -} - -union sockaddr_union { - struct sockaddr sa; - struct sockaddr_in in4; - struct sockaddr_in6 in6; - struct sockaddr_un un; - struct sockaddr_storage storage; -}; - -_sd_export_ int sd_is_socket(int fd, int family, int type, int listening) { - int r; - - if (family < 0) - return -EINVAL; - - if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) - return r; - - if (family > 0) { - union sockaddr_union sockaddr; - socklen_t l; - - memset(&sockaddr, 0, sizeof(sockaddr)); - l = sizeof(sockaddr); - - if (getsockname(fd, &sockaddr.sa, &l) < 0) - return -errno; - - if (l < sizeof(sa_family_t)) - return -EINVAL; - - return sockaddr.sa.sa_family == family; - } - - return 1; -} - -_sd_export_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) { - union sockaddr_union sockaddr; - socklen_t l; - int r; - - if (family != 0 && family != AF_INET && family != AF_INET6) - return -EINVAL; - - if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) - return r; - - memset(&sockaddr, 0, sizeof(sockaddr)); - l = sizeof(sockaddr); - - if (getsockname(fd, &sockaddr.sa, &l) < 0) - return -errno; - - if (l < sizeof(sa_family_t)) - return -EINVAL; - - if (sockaddr.sa.sa_family != AF_INET && - sockaddr.sa.sa_family != AF_INET6) - return 0; - - if (family > 0) - if (sockaddr.sa.sa_family != family) - return 0; - - if (port > 0) { - if (sockaddr.sa.sa_family == AF_INET) { - if (l < sizeof(struct sockaddr_in)) - return -EINVAL; - - return htons(port) == sockaddr.in4.sin_port; - } else { - if (l < sizeof(struct sockaddr_in6)) - return -EINVAL; - - return htons(port) == sockaddr.in6.sin6_port; - } - } - - return 1; -} - -_sd_export_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) { - union sockaddr_union sockaddr; - socklen_t l; - int r; - - if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) - return r; - - memset(&sockaddr, 0, sizeof(sockaddr)); - l = sizeof(sockaddr); - - if (getsockname(fd, &sockaddr.sa, &l) < 0) - return -errno; - - if (l < sizeof(sa_family_t)) - return -EINVAL; - - if (sockaddr.sa.sa_family != AF_UNIX) - return 0; - - if (path) { - if (length <= 0) - length = strlen(path); - - if (length <= 0) - /* Unnamed socket */ - return l == offsetof(struct sockaddr_un, sun_path); - - if (path[0]) - /* Normal path socket */ - return - (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) && - memcmp(path, sockaddr.un.sun_path, length+1) == 0; - else - /* Abstract namespace socket */ - return - (l == offsetof(struct sockaddr_un, sun_path) + length) && - memcmp(path, sockaddr.un.sun_path, length) == 0; - } - - return 1; -} - -_sd_export_ int sd_is_mq(int fd, const char *path) { -#if !defined(__linux__) - return 0; -#else - struct mq_attr attr; - - if (fd < 0) - return -EINVAL; - - if (mq_getattr(fd, &attr) < 0) - return -errno; - - if (path) { - char fpath[PATH_MAX]; - struct stat a, b; - - if (path[0] != '/') - return -EINVAL; - - if (fstat(fd, &a) < 0) - return -errno; - - strncpy(stpcpy(fpath, "/dev/mqueue"), path, sizeof(fpath) - 12); - fpath[sizeof(fpath)-1] = 0; - - if (stat(fpath, &b) < 0) - return -errno; - - if (a.st_dev != b.st_dev || - a.st_ino != b.st_ino) - return 0; - } - - return 1; -#endif -} - -_sd_export_ int sd_notify(int unset_environment, const char *state) { -#if defined(DISABLE_SYSTEMD) || !defined(__linux__) || !defined(SOCK_CLOEXEC) - return 0; -#else - int fd = -1, r; - struct msghdr msghdr; - struct iovec iovec; - union sockaddr_union sockaddr; - const char *e; - - if (!state) { - r = -EINVAL; - goto finish; - } - - if (!(e = getenv("NOTIFY_SOCKET"))) - return 0; - - /* Must be an abstract socket, or an absolute path */ - if ((e[0] != '@' && e[0] != '/') || e[1] == 0) { - r = -EINVAL; - goto finish; - } - - if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) { - r = -errno; - goto finish; - } - - memset(&sockaddr, 0, sizeof(sockaddr)); - sockaddr.sa.sa_family = AF_UNIX; - strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path)); - - if (sockaddr.un.sun_path[0] == '@') - sockaddr.un.sun_path[0] = 0; - - memset(&iovec, 0, sizeof(iovec)); - iovec.iov_base = (char*) state; - iovec.iov_len = strlen(state); - - memset(&msghdr, 0, sizeof(msghdr)); - msghdr.msg_name = &sockaddr; - msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e); - - if (msghdr.msg_namelen > sizeof(struct sockaddr_un)) - msghdr.msg_namelen = sizeof(struct sockaddr_un); - - msghdr.msg_iov = &iovec; - msghdr.msg_iovlen = 1; - - if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) { - r = -errno; - goto finish; - } - - r = 1; - -finish: - if (unset_environment) - unsetenv("NOTIFY_SOCKET"); - - if (fd >= 0) - close(fd); - - return r; -#endif -} - -_sd_export_ int sd_notifyf(int unset_environment, const char *format, ...) { -#if defined(DISABLE_SYSTEMD) || !defined(__linux__) - return 0; -#else - va_list ap; - char *p = NULL; - int r; - - va_start(ap, format); - r = vasprintf(&p, format, ap); - va_end(ap); - - if (r < 0 || !p) - return -ENOMEM; - - r = sd_notify(unset_environment, p); - free(p); - - return r; -#endif -} - -_sd_export_ int sd_booted(void) { -#if defined(DISABLE_SYSTEMD) || !defined(__linux__) - return 0; -#else - - struct stat a, b; - - /* We simply test whether the systemd cgroup hierarchy is - * mounted */ - - if (lstat("/sys/fs/cgroup", &a) < 0) - return 0; - - if (lstat("/sys/fs/cgroup/systemd", &b) < 0) - return 0; - - return a.st_dev != b.st_dev; -#endif -} diff --git a/src/udev/src/sd-daemon.h b/src/udev/src/sd-daemon.h deleted file mode 100644 index fe51159ee..000000000 --- a/src/udev/src/sd-daemon.h +++ /dev/null @@ -1,282 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -#ifndef foosddaemonhfoo -#define foosddaemonhfoo - -/*** - Copyright 2010 Lennart Poettering - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -***/ - -#include <sys/types.h> -#include <inttypes.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* - Reference implementation of a few systemd related interfaces for - writing daemons. These interfaces are trivial to implement. To - simplify porting we provide this reference implementation. - Applications are welcome to reimplement the algorithms described - here if they do not want to include these two source files. - - The following functionality is provided: - - - Support for logging with log levels on stderr - - File descriptor passing for socket-based activation - - Daemon startup and status notification - - Detection of systemd boots - - You may compile this with -DDISABLE_SYSTEMD to disable systemd - support. This makes all those calls NOPs that are directly related to - systemd (i.e. only sd_is_xxx() will stay useful). - - Since this is drop-in code we don't want any of our symbols to be - exported in any case. Hence we declare hidden visibility for all of - them. - - You may find an up-to-date version of these source files online: - - http://cgit.freedesktop.org/systemd/systemd/plain/src/systemd/sd-daemon.h - http://cgit.freedesktop.org/systemd/systemd/plain/src/sd-daemon.c - - This should compile on non-Linux systems, too, but with the - exception of the sd_is_xxx() calls all functions will become NOPs. - - See sd-daemon(7) for more information. -*/ - -#ifndef _sd_printf_attr_ -#if __GNUC__ >= 4 -#define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b))) -#else -#define _sd_printf_attr_(a,b) -#endif -#endif - -/* - Log levels for usage on stderr: - - fprintf(stderr, SD_NOTICE "Hello World!\n"); - - This is similar to printk() usage in the kernel. -*/ -#define SD_EMERG "<0>" /* system is unusable */ -#define SD_ALERT "<1>" /* action must be taken immediately */ -#define SD_CRIT "<2>" /* critical conditions */ -#define SD_ERR "<3>" /* error conditions */ -#define SD_WARNING "<4>" /* warning conditions */ -#define SD_NOTICE "<5>" /* normal but significant condition */ -#define SD_INFO "<6>" /* informational */ -#define SD_DEBUG "<7>" /* debug-level messages */ - -/* The first passed file descriptor is fd 3 */ -#define SD_LISTEN_FDS_START 3 - -/* - Returns how many file descriptors have been passed, or a negative - errno code on failure. Optionally, removes the $LISTEN_FDS and - $LISTEN_PID file descriptors from the environment (recommended, but - problematic in threaded environments). If r is the return value of - this function you'll find the file descriptors passed as fds - SD_LISTEN_FDS_START to SD_LISTEN_FDS_START+r-1. Returns a negative - errno style error code on failure. This function call ensures that - the FD_CLOEXEC flag is set for the passed file descriptors, to make - sure they are not passed on to child processes. If FD_CLOEXEC shall - not be set, the caller needs to unset it after this call for all file - descriptors that are used. - - See sd_listen_fds(3) for more information. -*/ -int sd_listen_fds(int unset_environment); - -/* - Helper call for identifying a passed file descriptor. Returns 1 if - the file descriptor is a FIFO in the file system stored under the - specified path, 0 otherwise. If path is NULL a path name check will - not be done and the call only verifies if the file descriptor - refers to a FIFO. Returns a negative errno style error code on - failure. - - See sd_is_fifo(3) for more information. -*/ -int sd_is_fifo(int fd, const char *path); - -/* - Helper call for identifying a passed file descriptor. Returns 1 if - the file descriptor is a special character device on the file - system stored under the specified path, 0 otherwise. - If path is NULL a path name check will not be done and the call - only verifies if the file descriptor refers to a special character. - Returns a negative errno style error code on failure. - - See sd_is_special(3) for more information. -*/ -int sd_is_special(int fd, const char *path); - -/* - Helper call for identifying a passed file descriptor. Returns 1 if - the file descriptor is a socket of the specified family (AF_INET, - ...) and type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If - family is 0 a socket family check will not be done. If type is 0 a - socket type check will not be done and the call only verifies if - the file descriptor refers to a socket. If listening is > 0 it is - verified that the socket is in listening mode. (i.e. listen() has - been called) If listening is == 0 it is verified that the socket is - not in listening mode. If listening is < 0 no listening mode check - is done. Returns a negative errno style error code on failure. - - See sd_is_socket(3) for more information. -*/ -int sd_is_socket(int fd, int family, int type, int listening); - -/* - Helper call for identifying a passed file descriptor. Returns 1 if - the file descriptor is an Internet socket, of the specified family - (either AF_INET or AF_INET6) and the specified type (SOCK_DGRAM, - SOCK_STREAM, ...), 0 otherwise. If version is 0 a protocol version - check is not done. If type is 0 a socket type check will not be - done. If port is 0 a socket port check will not be done. The - listening flag is used the same way as in sd_is_socket(). Returns a - negative errno style error code on failure. - - See sd_is_socket_inet(3) for more information. -*/ -int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port); - -/* - Helper call for identifying a passed file descriptor. Returns 1 if - the file descriptor is an AF_UNIX socket of the specified type - (SOCK_DGRAM, SOCK_STREAM, ...) and path, 0 otherwise. If type is 0 - a socket type check will not be done. If path is NULL a socket path - check will not be done. For normal AF_UNIX sockets set length to - 0. For abstract namespace sockets set length to the length of the - socket name (including the initial 0 byte), and pass the full - socket path in path (including the initial 0 byte). The listening - flag is used the same way as in sd_is_socket(). Returns a negative - errno style error code on failure. - - See sd_is_socket_unix(3) for more information. -*/ -int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length); - -/* - Helper call for identifying a passed file descriptor. Returns 1 if - the file descriptor is a POSIX Message Queue of the specified name, - 0 otherwise. If path is NULL a message queue name check is not - done. Returns a negative errno style error code on failure. -*/ -int sd_is_mq(int fd, const char *path); - -/* - Informs systemd about changed daemon state. This takes a number of - newline separated environment-style variable assignments in a - string. The following variables are known: - - READY=1 Tells systemd that daemon startup is finished (only - relevant for services of Type=notify). The passed - argument is a boolean "1" or "0". Since there is - little value in signaling non-readiness the only - value daemons should send is "READY=1". - - STATUS=... Passes a single-line status string back to systemd - that describes the daemon state. This is free-from - and can be used for various purposes: general state - feedback, fsck-like programs could pass completion - percentages and failing programs could pass a human - readable error message. Example: "STATUS=Completed - 66% of file system check..." - - ERRNO=... If a daemon fails, the errno-style error code, - formatted as string. Example: "ERRNO=2" for ENOENT. - - BUSERROR=... If a daemon fails, the D-Bus error-style error - code. Example: "BUSERROR=org.freedesktop.DBus.Error.TimedOut" - - MAINPID=... The main pid of a daemon, in case systemd did not - fork off the process itself. Example: "MAINPID=4711" - - WATCHDOG=1 Tells systemd to update the watchdog timestamp. - Services using this feature should do this in - regular intervals. A watchdog framework can use the - timestamps to detect failed services. - - Daemons can choose to send additional variables. However, it is - recommended to prefix variable names not listed above with X_. - - Returns a negative errno-style error code on failure. Returns > 0 - if systemd could be notified, 0 if it couldn't possibly because - systemd is not running. - - Example: When a daemon finished starting up, it could issue this - call to notify systemd about it: - - sd_notify(0, "READY=1"); - - See sd_notifyf() for more complete examples. - - See sd_notify(3) for more information. -*/ -int sd_notify(int unset_environment, const char *state); - -/* - Similar to sd_notify() but takes a format string. - - Example 1: A daemon could send the following after initialization: - - sd_notifyf(0, "READY=1\n" - "STATUS=Processing requests...\n" - "MAINPID=%lu", - (unsigned long) getpid()); - - Example 2: A daemon could send the following shortly before - exiting, on failure: - - sd_notifyf(0, "STATUS=Failed to start up: %s\n" - "ERRNO=%i", - strerror(errno), - errno); - - See sd_notifyf(3) for more information. -*/ -int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_attr_(2,3); - -/* - Returns > 0 if the system was booted with systemd. Returns < 0 on - error. Returns 0 if the system was not booted with systemd. Note - that all of the functions above handle non-systemd boots just - fine. You should NOT protect them with a call to this function. Also - note that this function checks whether the system, not the user - session is controlled by systemd. However the functions above work - for both user and system services. - - See sd_booted(3) for more information. -*/ -int sd_booted(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/udev/src/test-libudev.c b/src/udev/src/test-libudev.c deleted file mode 100644 index 6161fb3e3..000000000 --- a/src/udev/src/test-libudev.c +++ /dev/null @@ -1,501 +0,0 @@ -/* - * test-libudev - * - * 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 <stdarg.h> -#include <stdlib.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <getopt.h> -#include <syslog.h> -#include <fcntl.h> -#include <sys/epoll.h> - -#include "libudev.h" - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) - -static void log_fn(struct udev *udev, - int priority, const char *file, int line, const char *fn, - const char *format, va_list args) -{ - printf("test-libudev: %s %s:%d ", fn, file, line); - vprintf(format, args); -} - -static void print_device(struct udev_device *device) -{ - const char *str; - dev_t devnum; - int count; - struct udev_list_entry *list_entry; - - printf("*** device: %p ***\n", device); - str = udev_device_get_action(device); - if (str != NULL) - printf("action: '%s'\n", str); - - str = udev_device_get_syspath(device); - printf("syspath: '%s'\n", str); - - str = udev_device_get_sysname(device); - printf("sysname: '%s'\n", str); - - str = udev_device_get_sysnum(device); - if (str != NULL) - printf("sysnum: '%s'\n", str); - - str = udev_device_get_devpath(device); - printf("devpath: '%s'\n", str); - - str = udev_device_get_subsystem(device); - if (str != NULL) - printf("subsystem: '%s'\n", str); - - str = udev_device_get_devtype(device); - if (str != NULL) - printf("devtype: '%s'\n", str); - - str = udev_device_get_driver(device); - if (str != NULL) - printf("driver: '%s'\n", str); - - str = udev_device_get_devnode(device); - if (str != NULL) - printf("devname: '%s'\n", str); - - devnum = udev_device_get_devnum(device); - if (major(devnum) > 0) - printf("devnum: %u:%u\n", major(devnum), minor(devnum)); - - count = 0; - udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(device)) { - printf("link: '%s'\n", udev_list_entry_get_name(list_entry)); - count++; - } - if (count > 0) - printf("found %i links\n", count); - - count = 0; - udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(device)) { - printf("property: '%s=%s'\n", - udev_list_entry_get_name(list_entry), - udev_list_entry_get_value(list_entry)); - count++; - } - if (count > 0) - printf("found %i properties\n", count); - - str = udev_device_get_property_value(device, "MAJOR"); - if (str != NULL) - printf("MAJOR: '%s'\n", str); - - str = udev_device_get_sysattr_value(device, "dev"); - if (str != NULL) - printf("attr{dev}: '%s'\n", str); - - printf("\n"); -} - -static int test_device(struct udev *udev, const char *syspath) -{ - struct udev_device *device; - - printf("looking at device: %s\n", syspath); - device = udev_device_new_from_syspath(udev, syspath); - if (device == NULL) { - printf("no device found\n"); - return -1; - } - print_device(device); - udev_device_unref(device); - return 0; -} - -static int test_device_parents(struct udev *udev, const char *syspath) -{ - struct udev_device *device; - struct udev_device *device_parent; - - printf("looking at device: %s\n", syspath); - device = udev_device_new_from_syspath(udev, syspath); - if (device == NULL) - return -1; - - printf("looking at parents\n"); - device_parent = device; - do { - print_device(device_parent); - device_parent = udev_device_get_parent(device_parent); - } while (device_parent != NULL); - - printf("looking at parents again\n"); - device_parent = device; - do { - print_device(device_parent); - device_parent = udev_device_get_parent(device_parent); - } while (device_parent != NULL); - udev_device_unref(device); - - return 0; -} - -static int test_device_devnum(struct udev *udev) -{ - dev_t devnum = makedev(1, 3); - struct udev_device *device; - - printf("looking up device: %u:%u\n", major(devnum), minor(devnum)); - device = udev_device_new_from_devnum(udev, 'c', devnum); - if (device == NULL) - return -1; - print_device(device); - udev_device_unref(device); - return 0; -} - -static int test_device_subsys_name(struct udev *udev) -{ - struct udev_device *device; - - printf("looking up device: 'block':'sda'\n"); - device = udev_device_new_from_subsystem_sysname(udev, "block", "sda"); - if (device == NULL) - return -1; - print_device(device); - udev_device_unref(device); - - printf("looking up device: 'subsystem':'pci'\n"); - device = udev_device_new_from_subsystem_sysname(udev, "subsystem", "pci"); - if (device == NULL) - return -1; - print_device(device); - udev_device_unref(device); - - printf("looking up device: 'drivers':'scsi:sd'\n"); - device = udev_device_new_from_subsystem_sysname(udev, "drivers", "scsi:sd"); - if (device == NULL) - return -1; - print_device(device); - udev_device_unref(device); - - printf("looking up device: 'module':'printk'\n"); - device = udev_device_new_from_subsystem_sysname(udev, "module", "printk"); - if (device == NULL) - return -1; - print_device(device); - udev_device_unref(device); - return 0; -} - -static int test_enumerate_print_list(struct udev_enumerate *enumerate) -{ - struct udev_list_entry *list_entry; - int count = 0; - - udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) { - struct udev_device *device; - - device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate), - udev_list_entry_get_name(list_entry)); - if (device != NULL) { - printf("device: '%s' (%s)\n", - udev_device_get_syspath(device), - udev_device_get_subsystem(device)); - udev_device_unref(device); - count++; - } - } - printf("found %i devices\n\n", count); - return count; -} - -static int test_monitor(struct udev *udev) -{ - struct udev_monitor *udev_monitor = NULL; - int fd_ep; - int fd_udev = -1; - struct epoll_event ep_udev, ep_stdin; - - fd_ep = epoll_create1(EPOLL_CLOEXEC); - if (fd_ep < 0) { - printf("error creating epoll fd: %m\n"); - goto out; - } - - udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); - if (udev_monitor == NULL) { - printf("no socket\n"); - goto out; - } - fd_udev = udev_monitor_get_fd(udev_monitor); - - if (udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "block", NULL) < 0 || - udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "tty", NULL) < 0 || - udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_device") < 0) { - printf("filter failed\n"); - goto out; - } - - if (udev_monitor_enable_receiving(udev_monitor) < 0) { - printf("bind failed\n"); - goto out; - } - - memset(&ep_udev, 0, sizeof(struct epoll_event)); - ep_udev.events = EPOLLIN; - ep_udev.data.fd = fd_udev; - if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) < 0) { - printf("fail to add fd to epoll: %m\n"); - goto out; - } - - memset(&ep_stdin, 0, sizeof(struct epoll_event)); - ep_stdin.events = EPOLLIN; - ep_stdin.data.fd = STDIN_FILENO; - if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, STDIN_FILENO, &ep_stdin) < 0) { - printf("fail to add fd to epoll: %m\n"); - goto out; - } - - for (;;) { - int fdcount; - struct epoll_event ev[4]; - struct udev_device *device; - int i; - - printf("waiting for events from udev, press ENTER to exit\n"); - fdcount = epoll_wait(fd_ep, ev, ARRAY_SIZE(ev), -1); - printf("epoll fd count: %i\n", fdcount); - - for (i = 0; i < fdcount; i++) { - if (ev[i].data.fd == fd_udev && ev[i].events & EPOLLIN) { - device = udev_monitor_receive_device(udev_monitor); - if (device == NULL) { - printf("no device from socket\n"); - continue; - } - print_device(device); - udev_device_unref(device); - } else if (ev[i].data.fd == STDIN_FILENO && ev[i].events & EPOLLIN) { - printf("exiting loop\n"); - goto out; - } - } - } -out: - if (fd_ep >= 0) - close(fd_ep); - udev_monitor_unref(udev_monitor); - return 0; -} - -static int test_queue(struct udev *udev) -{ - struct udev_queue *udev_queue; - unsigned long long int seqnum; - struct udev_list_entry *list_entry; - - udev_queue = udev_queue_new(udev); - if (udev_queue == NULL) - return -1; - seqnum = udev_queue_get_kernel_seqnum(udev_queue); - printf("seqnum kernel: %llu\n", seqnum); - seqnum = udev_queue_get_udev_seqnum(udev_queue); - printf("seqnum udev : %llu\n", seqnum); - - if (udev_queue_get_queue_is_empty(udev_queue)) - printf("queue is empty\n"); - printf("get queue list\n"); - udev_list_entry_foreach(list_entry, udev_queue_get_queued_list_entry(udev_queue)) - printf("queued: '%s' [%s]\n", udev_list_entry_get_name(list_entry), udev_list_entry_get_value(list_entry)); - printf("\n"); - printf("get queue list again\n"); - udev_list_entry_foreach(list_entry, udev_queue_get_queued_list_entry(udev_queue)) - printf("queued: '%s' [%s]\n", udev_list_entry_get_name(list_entry), udev_list_entry_get_value(list_entry)); - printf("\n"); - - list_entry = udev_queue_get_queued_list_entry(udev_queue); - if (list_entry != NULL) { - printf("event [%llu] is queued\n", seqnum); - seqnum = strtoull(udev_list_entry_get_value(list_entry), NULL, 10); - if (udev_queue_get_seqnum_is_finished(udev_queue, seqnum)) - printf("event [%llu] is not finished\n", seqnum); - else - printf("event [%llu] is finished\n", seqnum); - } - printf("\n"); - udev_queue_unref(udev_queue); - return 0; -} - -static int test_enumerate(struct udev *udev, const char *subsystem) -{ - struct udev_enumerate *udev_enumerate; - - printf("enumerate '%s'\n", subsystem == NULL ? "<all>" : subsystem); - udev_enumerate = udev_enumerate_new(udev); - if (udev_enumerate == NULL) - return -1; - udev_enumerate_add_match_subsystem(udev_enumerate, subsystem); - udev_enumerate_scan_devices(udev_enumerate); - test_enumerate_print_list(udev_enumerate); - udev_enumerate_unref(udev_enumerate); - - printf("enumerate 'net' + duplicated scan + null + zero\n"); - udev_enumerate = udev_enumerate_new(udev); - if (udev_enumerate == NULL) - return -1; - udev_enumerate_add_match_subsystem(udev_enumerate, "net"); - udev_enumerate_scan_devices(udev_enumerate); - udev_enumerate_scan_devices(udev_enumerate); - udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero"); - udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null"); - udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero"); - udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null"); - udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero"); - udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null"); - udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null"); - udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero"); - udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero"); - udev_enumerate_scan_devices(udev_enumerate); - test_enumerate_print_list(udev_enumerate); - udev_enumerate_unref(udev_enumerate); - - printf("enumerate 'block'\n"); - udev_enumerate = udev_enumerate_new(udev); - if (udev_enumerate == NULL) - return -1; - udev_enumerate_add_match_subsystem(udev_enumerate,"block"); - udev_enumerate_add_match_is_initialized(udev_enumerate); - udev_enumerate_scan_devices(udev_enumerate); - test_enumerate_print_list(udev_enumerate); - udev_enumerate_unref(udev_enumerate); - - printf("enumerate 'not block'\n"); - udev_enumerate = udev_enumerate_new(udev); - if (udev_enumerate == NULL) - return -1; - udev_enumerate_add_nomatch_subsystem(udev_enumerate, "block"); - udev_enumerate_scan_devices(udev_enumerate); - test_enumerate_print_list(udev_enumerate); - udev_enumerate_unref(udev_enumerate); - - printf("enumerate 'pci, mem, vc'\n"); - udev_enumerate = udev_enumerate_new(udev); - if (udev_enumerate == NULL) - return -1; - udev_enumerate_add_match_subsystem(udev_enumerate, "pci"); - udev_enumerate_add_match_subsystem(udev_enumerate, "mem"); - udev_enumerate_add_match_subsystem(udev_enumerate, "vc"); - udev_enumerate_scan_devices(udev_enumerate); - test_enumerate_print_list(udev_enumerate); - udev_enumerate_unref(udev_enumerate); - - printf("enumerate 'subsystem'\n"); - udev_enumerate = udev_enumerate_new(udev); - if (udev_enumerate == NULL) - return -1; - udev_enumerate_scan_subsystems(udev_enumerate); - test_enumerate_print_list(udev_enumerate); - udev_enumerate_unref(udev_enumerate); - - printf("enumerate 'property IF_FS_*=filesystem'\n"); - udev_enumerate = udev_enumerate_new(udev); - if (udev_enumerate == NULL) - return -1; - udev_enumerate_add_match_property(udev_enumerate, "ID_FS*", "filesystem"); - udev_enumerate_scan_devices(udev_enumerate); - test_enumerate_print_list(udev_enumerate); - udev_enumerate_unref(udev_enumerate); - return 0; -} - -int main(int argc, char *argv[]) -{ - struct udev *udev = NULL; - static const struct option options[] = { - { "syspath", required_argument, NULL, 'p' }, - { "subsystem", required_argument, NULL, 's' }, - { "debug", no_argument, NULL, 'd' }, - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'V' }, - {} - }; - const char *syspath = "/devices/virtual/mem/null"; - const char *subsystem = NULL; - char path[1024]; - const char *str; - - udev = udev_new(); - printf("context: %p\n", udev); - if (udev == NULL) { - printf("no context\n"); - return 1; - } - udev_set_log_fn(udev, log_fn); - printf("set log: %p\n", log_fn); - - for (;;) { - int option; - - option = getopt_long(argc, argv, "+p:s:dhV", options, NULL); - if (option == -1) - break; - - switch (option) { - case 'p': - syspath = optarg; - break; - case 's': - subsystem = optarg; - break; - case 'd': - if (udev_get_log_priority(udev) < LOG_INFO) - udev_set_log_priority(udev, LOG_INFO); - break; - case 'h': - printf("--debug --syspath= --subsystem= --help\n"); - goto out; - case 'V': - printf("%s\n", VERSION); - goto out; - default: - goto out; - } - } - - str = udev_get_sys_path(udev); - printf("sys_path: '%s'\n", str); - str = udev_get_dev_path(udev); - printf("dev_path: '%s'\n", str); - - /* add sys path if needed */ - if (strncmp(syspath, udev_get_sys_path(udev), strlen(udev_get_sys_path(udev))) != 0) { - snprintf(path, sizeof(path), "%s%s", udev_get_sys_path(udev), syspath); - syspath = path; - } - - test_device(udev, syspath); - test_device_devnum(udev); - test_device_subsys_name(udev); - test_device_parents(udev, syspath); - - test_enumerate(udev, subsystem); - - test_queue(udev); - - test_monitor(udev); -out: - udev_unref(udev); - return 0; -} diff --git a/src/udev/src/test-udev.c b/src/udev/src/test-udev.c deleted file mode 100644 index c9712e974..000000000 --- a/src/udev/src/test-udev.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2003-2004 Greg Kroah-Hartman <greg@kroah.com> - * Copyright (C) 2004-2008 Kay Sievers <kay.sievers@vrfy.org> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <ctype.h> -#include <errno.h> -#include <unistd.h> -#include <syslog.h> -#include <grp.h> -#include <sys/signalfd.h> - -#include "udev.h" - -void udev_main_log(struct udev *udev, int priority, - const char *file, int line, const char *fn, - const char *format, va_list args) {} - -int main(int argc, char *argv[]) -{ - struct udev *udev; - struct udev_event *event = NULL; - struct udev_device *dev = NULL; - struct udev_rules *rules = NULL; - char syspath[UTIL_PATH_SIZE]; - const char *devpath; - const char *action; - sigset_t mask, sigmask_orig; - int err = -EINVAL; - - udev = udev_new(); - if (udev == NULL) - exit(1); - info(udev, "version %s\n", VERSION); - udev_selinux_init(udev); - - sigprocmask(SIG_SETMASK, NULL, &sigmask_orig); - - action = argv[1]; - if (action == NULL) { - err(udev, "action missing\n"); - goto out; - } - - devpath = argv[2]; - if (devpath == NULL) { - err(udev, "devpath missing\n"); - goto out; - } - - rules = udev_rules_new(udev, 1); - - util_strscpyl(syspath, sizeof(syspath), udev_get_sys_path(udev), devpath, NULL); - dev = udev_device_new_from_syspath(udev, syspath); - if (dev == NULL) { - info(udev, "unknown device '%s'\n", devpath); - goto out; - } - - udev_device_set_action(dev, action); - event = udev_event_new(dev); - - sigfillset(&mask); - sigprocmask(SIG_SETMASK, &mask, &sigmask_orig); - event->fd_signal = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); - if (event->fd_signal < 0) { - fprintf(stderr, "error creating signalfd\n"); - goto out; - } - - /* do what devtmpfs usually provides us */ - if (udev_device_get_devnode(dev) != NULL) { - mode_t mode; - - if (strcmp(udev_device_get_subsystem(dev), "block") == 0) - mode |= S_IFBLK; - else - mode |= S_IFCHR; - - if (strcmp(action, "remove") != 0) { - util_create_path(udev, udev_device_get_devnode(dev)); - mknod(udev_device_get_devnode(dev), mode, udev_device_get_devnum(dev)); - } else { - unlink(udev_device_get_devnode(dev)); - util_delete_path(udev, udev_device_get_devnode(dev)); - } - } - - err = udev_event_execute_rules(event, rules, &sigmask_orig); - if (err == 0) - udev_event_execute_run(event, NULL); -out: - if (event != NULL && event->fd_signal >= 0) - close(event->fd_signal); - udev_event_unref(event); - udev_device_unref(dev); - udev_rules_unref(rules); - udev_selinux_exit(udev); - udev_unref(udev); - if (err != 0) - return 1; - return 0; -} diff --git a/src/udev/src/udev-builtin-blkid.c b/src/udev/src/udev-builtin-blkid.c deleted file mode 100644 index e57f03e5a..000000000 --- a/src/udev/src/udev-builtin-blkid.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * probe disks for filesystems and partitions - * - * Copyright (C) 2011 Kay Sievers <kay.sievers@vrfy.org> - * Copyright (C) 2011 Karel Zak <kzak@redhat.com> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include <fcntl.h> -#include <getopt.h> -#include <sys/stat.h> -#include <blkid/blkid.h> - -#include "udev.h" - -static void print_property(struct udev_device *dev, bool test, const char *name, const char *value) -{ - char s[265]; - - s[0] = '\0'; - - if (!strcmp(name, "TYPE")) { - udev_builtin_add_property(dev, test, "ID_FS_TYPE", value); - - } else if (!strcmp(name, "USAGE")) { - udev_builtin_add_property(dev, test, "ID_FS_USAGE", value); - - } else if (!strcmp(name, "VERSION")) { - udev_builtin_add_property(dev, test, "ID_FS_VERSION", value); - - } else if (!strcmp(name, "UUID")) { - blkid_safe_string(value, s, sizeof(s)); - udev_builtin_add_property(dev, test, "ID_FS_UUID", s); - blkid_encode_string(value, s, sizeof(s)); - udev_builtin_add_property(dev, test, "ID_FS_UUID_ENC", s); - - } else if (!strcmp(name, "UUID_SUB")) { - blkid_safe_string(value, s, sizeof(s)); - udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB", s); - blkid_encode_string(value, s, sizeof(s)); - udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB_ENC", s); - - } else if (!strcmp(name, "LABEL")) { - blkid_safe_string(value, s, sizeof(s)); - udev_builtin_add_property(dev, test, "ID_FS_LABEL", s); - blkid_encode_string(value, s, sizeof(s)); - udev_builtin_add_property(dev, test, "ID_FS_LABEL_ENC", s); - - } else if (!strcmp(name, "PTTYPE")) { - udev_builtin_add_property(dev, test, "ID_PART_TABLE_TYPE", value); - - } else if (!strcmp(name, "PART_ENTRY_NAME")) { - blkid_encode_string(value, s, sizeof(s)); - udev_builtin_add_property(dev, test, "ID_PART_ENTRY_NAME", s); - - } else if (!strcmp(name, "PART_ENTRY_TYPE")) { - blkid_encode_string(value, s, sizeof(s)); - udev_builtin_add_property(dev, test, "ID_PART_ENTRY_TYPE", s); - - } else if (!strncmp(name, "PART_ENTRY_", 11)) { - util_strscpyl(s, sizeof(s), "ID_", name, NULL); - udev_builtin_add_property(dev, test, s, value); - } -} - -static int probe_superblocks(blkid_probe pr) -{ - struct stat st; - int rc; - - if (fstat(blkid_probe_get_fd(pr), &st)) - return -1; - - blkid_probe_enable_partitions(pr, 1); - - if (!S_ISCHR(st.st_mode) && blkid_probe_get_size(pr) <= 1024 * 1440 && - blkid_probe_is_wholedisk(pr)) { - /* - * check if the small disk is partitioned, if yes then - * don't probe for filesystems. - */ - blkid_probe_enable_superblocks(pr, 0); - - rc = blkid_do_fullprobe(pr); - if (rc < 0) - return rc; /* -1 = error, 1 = nothing, 0 = succes */ - - if (blkid_probe_lookup_value(pr, "PTTYPE", NULL, NULL) == 0) - return 0; /* partition table detected */ - } - - blkid_probe_set_partitions_flags(pr, BLKID_PARTS_ENTRY_DETAILS); - blkid_probe_enable_superblocks(pr, 1); - - return blkid_do_safeprobe(pr); -} - -static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool test) -{ - struct udev *udev = udev_device_get_udev(dev); - int64_t offset = 0; - bool noraid = false; - int fd = -1; - blkid_probe pr; - const char *data; - const char *name; - int nvals; - int i; - size_t len; - int err = 0; - - static const struct option options[] = { - { "offset", optional_argument, NULL, 'o' }, - { "noraid", no_argument, NULL, 'R' }, - {} - }; - - for (;;) { - int option; - - option = getopt_long(argc, argv, "oR", options, NULL); - if (option == -1) - break; - - switch (option) { - case 'o': - offset = strtoull(optarg, NULL, 0); - break; - case 'R': - noraid = true; - break; - } - } - - pr = blkid_new_probe(); - if (!pr) { - err = -ENOMEM; - return EXIT_FAILURE; - } - - blkid_probe_set_superblocks_flags(pr, - BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | - BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE | - BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION); - - if (noraid) - blkid_probe_filter_superblocks_usage(pr, BLKID_FLTR_NOTIN, BLKID_USAGE_RAID); - - fd = open(udev_device_get_devnode(dev), O_RDONLY|O_CLOEXEC); - if (fd < 0) { - fprintf(stderr, "error: %s: %m\n", udev_device_get_devnode(dev)); - goto out; - } - - err = blkid_probe_set_device(pr, fd, offset, 0); - if (err < 0) - goto out; - - info(udev, "probe %s %sraid offset=%llu\n", - udev_device_get_devnode(dev), - noraid ? "no" : "", (unsigned long long) offset); - - err = probe_superblocks(pr); - if (err < 0) - goto out; - - nvals = blkid_probe_numof_values(pr); - for (i = 0; i < nvals; i++) { - if (blkid_probe_get_value(pr, i, &name, &data, &len)) - continue; - len = strnlen((char *) data, len); - print_property(dev, test, name, (char *) data); - } - - blkid_free_probe(pr); -out: - if (fd > 0) - close(fd); - if (err < 0) - return EXIT_FAILURE; - return EXIT_SUCCESS; -} - -const struct udev_builtin udev_builtin_blkid = { - .name = "blkid", - .cmd = builtin_blkid, - .help = "filesystem and partition probing", - .run_once = true, -}; diff --git a/src/udev/src/udev-builtin-firmware.c b/src/udev/src/udev-builtin-firmware.c deleted file mode 100644 index d212c64b4..000000000 --- a/src/udev/src/udev-builtin-firmware.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * firmware - Kernel firmware loader - * - * Copyright (C) 2009 Piter Punk <piterpunk@slackware.com> - * Copyright (C) 2009-2011 Kay Sievers <kay.sievers@vrfy.org> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program 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 - * General Public License for more details:* - */ - -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <getopt.h> -#include <errno.h> -#include <stdbool.h> -#include <sys/utsname.h> -#include <sys/stat.h> - -#include "udev.h" - -static bool set_loading(struct udev *udev, char *loadpath, const char *state) -{ - FILE *ldfile; - - ldfile = fopen(loadpath, "we"); - if (ldfile == NULL) { - err(udev, "error: can not open '%s'\n", loadpath); - return false; - }; - fprintf(ldfile, "%s\n", state); - fclose(ldfile); - return true; -} - -static bool copy_firmware(struct udev *udev, const char *source, const char *target, size_t size) -{ - char *buf; - FILE *fsource = NULL, *ftarget = NULL; - bool ret = false; - - buf = malloc(size); - if (buf == NULL) { - err(udev,"No memory available to load firmware file"); - return false; - } - - info(udev, "writing '%s' (%zi) to '%s'\n", source, size, target); - - fsource = fopen(source, "re"); - if (fsource == NULL) - goto exit; - ftarget = fopen(target, "we"); - if (ftarget == NULL) - goto exit; - if (fread(buf, size, 1, fsource) != 1) - goto exit; - if (fwrite(buf, size, 1, ftarget) == 1) - ret = true; -exit: - if (ftarget != NULL) - fclose(ftarget); - if (fsource != NULL) - fclose(fsource); - free(buf); - return ret; -} - -static int builtin_firmware(struct udev_device *dev, int argc, char *argv[], bool test) -{ - struct udev *udev = udev_device_get_udev(dev); - static const char *searchpath[] = { FIRMWARE_PATH }; - char fwencpath[UTIL_PATH_SIZE]; - char misspath[UTIL_PATH_SIZE]; - char loadpath[UTIL_PATH_SIZE]; - char datapath[UTIL_PATH_SIZE]; - char fwpath[UTIL_PATH_SIZE]; - const char *firmware; - FILE *fwfile; - struct utsname kernel; - struct stat statbuf; - unsigned int i; - int rc = EXIT_SUCCESS; - - firmware = udev_device_get_property_value(dev, "FIRMWARE"); - if (firmware == NULL) { - err(udev, "firmware parameter missing\n\n"); - rc = EXIT_FAILURE; - goto exit; - } - - /* lookup firmware file */ - uname(&kernel); - for (i = 0; i < ARRAY_SIZE(searchpath); i++) { - util_strscpyl(fwpath, sizeof(fwpath), searchpath[i], kernel.release, "/", firmware, NULL); - dbg(udev, "trying %s\n", fwpath); - fwfile = fopen(fwpath, "re"); - if (fwfile != NULL) - break; - - util_strscpyl(fwpath, sizeof(fwpath), searchpath[i], firmware, NULL); - dbg(udev, "trying %s\n", fwpath); - fwfile = fopen(fwpath, "re"); - if (fwfile != NULL) - break; - } - - util_path_encode(firmware, fwencpath, sizeof(fwencpath)); - util_strscpyl(misspath, sizeof(misspath), udev_get_run_path(udev), "/firmware-missing/", fwencpath, NULL); - util_strscpyl(loadpath, sizeof(loadpath), udev_device_get_syspath(dev), "/loading", NULL); - - if (fwfile == NULL) { - int err; - - /* This link indicates the missing firmware file and the associated device */ - info(udev, "did not find firmware file '%s'\n", firmware); - do { - err = util_create_path(udev, misspath); - if (err != 0 && err != -ENOENT) - break; - err = symlink(udev_device_get_devpath(dev), misspath); - if (err != 0) - err = -errno; - } while (err == -ENOENT); - rc = EXIT_FAILURE; - set_loading(udev, loadpath, "-1"); - goto exit; - } - - if (stat(fwpath, &statbuf) < 0 || statbuf.st_size == 0) { - rc = EXIT_FAILURE; - goto exit; - } - if (unlink(misspath) == 0) - util_delete_path(udev, misspath); - - if (!set_loading(udev, loadpath, "1")) - goto exit; - - util_strscpyl(datapath, sizeof(datapath), udev_device_get_syspath(dev), "/data", NULL); - if (!copy_firmware(udev, fwpath, datapath, statbuf.st_size)) { - err(udev, "error sending firmware '%s' to device\n", firmware); - set_loading(udev, loadpath, "-1"); - rc = EXIT_FAILURE; - goto exit; - }; - - set_loading(udev, loadpath, "0"); -exit: - if (fwfile) - fclose(fwfile); - return rc; -} - -const struct udev_builtin udev_builtin_firmware = { - .name = "firmware", - .cmd = builtin_firmware, - .help = "kernel firmware loader", - .run_once = true, -}; diff --git a/src/udev/src/udev-builtin-hwdb.c b/src/udev/src/udev-builtin-hwdb.c deleted file mode 100644 index aa996f375..000000000 --- a/src/udev/src/udev-builtin-hwdb.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * usb-db, pci-db - lookup vendor/product database - * - * Copyright (C) 2009 Lennart Poettering <lennart@poettering.net> - * Copyright (C) 2011 Kay Sievers <kay.sievers@vrfy.org> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <errno.h> -#include <string.h> -#include <inttypes.h> -#include <ctype.h> -#include <stdlib.h> - -#include "udev.h" - -static int get_id_attr( - struct udev_device *parent, - const char *name, - uint16_t *value) { - - const char *t; - unsigned u; - - if (!(t = udev_device_get_sysattr_value(parent, name))) { - fprintf(stderr, "%s lacks %s.\n", udev_device_get_syspath(parent), name); - return -1; - } - - if (!strncmp(t, "0x", 2)) - t += 2; - - if (sscanf(t, "%04x", &u) != 1 || u > 0xFFFFU) { - fprintf(stderr, "Failed to parse %s on %s.\n", name, udev_device_get_syspath(parent)); - return -1; - } - - *value = (uint16_t) u; - return 0; -} - -static int get_vid_pid( - struct udev_device *parent, - const char *vendor_attr, - const char *product_attr, - uint16_t *vid, - uint16_t *pid) { - - if (get_id_attr(parent, vendor_attr, vid) < 0) - return -1; - else if (*vid <= 0) { - fprintf(stderr, "Invalid vendor id.\n"); - return -1; - } - - if (get_id_attr(parent, product_attr, pid) < 0) - return -1; - - return 0; -} - -static void rstrip(char *n) { - size_t i; - - for (i = strlen(n); i > 0 && isspace(n[i-1]); i--) - n[i-1] = 0; -} - -#define HEXCHARS "0123456789abcdefABCDEF" -#define WHITESPACE " \t\n\r" -static int lookup_vid_pid(const char *database, - uint16_t vid, uint16_t pid, - char **vendor, char **product) -{ - - FILE *f; - int ret = -1; - int found_vendor = 0; - char *line = NULL; - - *vendor = *product = NULL; - - if (!(f = fopen(database, "rme"))) { - fprintf(stderr, "Failed to open database file '%s': %s\n", database, strerror(errno)); - return -1; - } - - for (;;) { - size_t n; - - if (getline(&line, &n, f) < 0) - break; - - rstrip(line); - - if (line[0] == '#' || line[0] == 0) - continue; - - if (strspn(line, HEXCHARS) == 4) { - unsigned u; - - if (found_vendor) - break; - - if (sscanf(line, "%04x", &u) == 1 && u == vid) { - char *t; - - t = line+4; - t += strspn(t, WHITESPACE); - - if (!(*vendor = strdup(t))) { - fprintf(stderr, "Out of memory.\n"); - goto finish; - } - - found_vendor = 1; - } - - continue; - } - - if (found_vendor && line[0] == '\t' && strspn(line+1, HEXCHARS) == 4) { - unsigned u; - - if (sscanf(line+1, "%04x", &u) == 1 && u == pid) { - char *t; - - t = line+5; - t += strspn(t, WHITESPACE); - - if (!(*product = strdup(t))) { - fprintf(stderr, "Out of memory.\n"); - goto finish; - } - - break; - } - } - } - - ret = 0; - -finish: - free(line); - fclose(f); - - if (ret < 0) { - free(*product); - free(*vendor); - - *product = *vendor = NULL; - } - - return ret; -} - -static struct udev_device *find_device(struct udev_device *dev, const char *subsys, const char *devtype) -{ - const char *str; - - str = udev_device_get_subsystem(dev); - if (str == NULL) - goto try_parent; - if (strcmp(str, subsys) != 0) - goto try_parent; - - if (devtype != NULL) { - str = udev_device_get_devtype(dev); - if (str == NULL) - goto try_parent; - if (strcmp(str, devtype) != 0) - goto try_parent; - } - return dev; -try_parent: - return udev_device_get_parent_with_subsystem_devtype(dev, subsys, devtype); -} - - -static int builtin_db(struct udev_device *dev, bool test, - const char *database, - const char *vendor_attr, const char *product_attr, - const char *subsys, const char *devtype) -{ - struct udev_device *parent; - uint16_t vid = 0, pid = 0; - char *vendor = NULL, *product = NULL; - - parent = find_device(dev, subsys, devtype); - if (!parent) { - fprintf(stderr, "Failed to find device.\n"); - goto finish; - } - - if (get_vid_pid(parent, vendor_attr, product_attr, &vid, &pid) < 0) - goto finish; - - if (lookup_vid_pid(database, vid, pid, &vendor, &product) < 0) - goto finish; - - if (vendor) - udev_builtin_add_property(dev, test, "ID_VENDOR_FROM_DATABASE", vendor); - if (product) - udev_builtin_add_property(dev, test, "ID_MODEL_FROM_DATABASE", product); - -finish: - free(vendor); - free(product); - return 0; -} - -static int builtin_usb_db(struct udev_device *dev, int argc, char *argv[], bool test) -{ - return builtin_db(dev, test, USB_DATABASE, "idVendor", "idProduct", "usb", "usb_device"); -} - -static int builtin_pci_db(struct udev_device *dev, int argc, char *argv[], bool test) -{ - return builtin_db(dev, test, PCI_DATABASE, "vendor", "device", "pci", NULL); -} - -const struct udev_builtin udev_builtin_usb_db = { - .name = "usb-db", - .cmd = builtin_usb_db, - .help = "USB vendor/product database", - .run_once = true, -}; - -const struct udev_builtin udev_builtin_pci_db = { - .name = "pci-db", - .cmd = builtin_pci_db, - .help = "PCI vendor/product database", - .run_once = true, -}; diff --git a/src/udev/src/udev-builtin-input_id.c b/src/udev/src/udev-builtin-input_id.c deleted file mode 100644 index a062ef7c7..000000000 --- a/src/udev/src/udev-builtin-input_id.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * compose persistent device path - * - * Copyright (C) 2009 Martin Pitt <martin.pitt@ubuntu.com> - * Portions Copyright (C) 2004 David Zeuthen, <david@fubar.dk> - * Copyright (C) 2011 Kay Sievers <kay.sievers@vrfy.org> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include <linux/limits.h> -#include <linux/input.h> - -#include "udev.h" - -/* we must use this kernel-compatible implementation */ -#define BITS_PER_LONG (sizeof(unsigned long) * 8) -#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) -#define OFF(x) ((x)%BITS_PER_LONG) -#define BIT(x) (1UL<<OFF(x)) -#define LONG(x) ((x)/BITS_PER_LONG) -#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1) - -/* - * Read a capability attribute and return bitmask. - * @param dev udev_device - * @param attr sysfs attribute name (e. g. "capabilities/key") - * @param bitmask: Output array which has a sizeof of bitmask_size - */ -static void get_cap_mask(struct udev_device *dev, - struct udev_device *pdev, const char* attr, - unsigned long *bitmask, size_t bitmask_size, - bool test) -{ - struct udev *udev = udev_device_get_udev(dev); - char text[4096]; - unsigned i; - char* word; - unsigned long val; - - snprintf(text, sizeof(text), "%s", udev_device_get_sysattr_value(pdev, attr)); - info(udev, "%s raw kernel attribute: %s\n", attr, text); - - memset (bitmask, 0, bitmask_size); - i = 0; - while ((word = strrchr(text, ' ')) != NULL) { - val = strtoul (word+1, NULL, 16); - if (i < bitmask_size/sizeof(unsigned long)) - bitmask[i] = val; - else - info(udev, "ignoring %s block %lX which is larger than maximum size\n", attr, val); - *word = '\0'; - ++i; - } - val = strtoul (text, NULL, 16); - if (i < bitmask_size / sizeof(unsigned long)) - bitmask[i] = val; - else - info(udev, "ignoring %s block %lX which is larger than maximum size\n", attr, val); - - if (test) { - /* printf pattern with the right unsigned long number of hex chars */ - snprintf(text, sizeof(text), " bit %%4u: %%0%zilX\n", 2 * sizeof(unsigned long)); - info(udev, "%s decoded bit map:\n", attr); - val = bitmask_size / sizeof (unsigned long); - /* skip over leading zeros */ - while (bitmask[val-1] == 0 && val > 0) - --val; - for (i = 0; i < val; ++i) - info(udev, text, i * BITS_PER_LONG, bitmask[i]); - } -} - -/* pointer devices */ -static void test_pointers (struct udev_device *dev, - const unsigned long* bitmask_ev, - const unsigned long* bitmask_abs, - const unsigned long* bitmask_key, - const unsigned long* bitmask_rel, - bool test) -{ - int is_mouse = 0; - int is_touchpad = 0; - - if (!test_bit (EV_KEY, bitmask_ev)) { - if (test_bit (EV_ABS, bitmask_ev) && - test_bit (ABS_X, bitmask_abs) && - test_bit (ABS_Y, bitmask_abs) && - test_bit (ABS_Z, bitmask_abs)) - udev_builtin_add_property(dev, test, "ID_INPUT_ACCELEROMETER", "1"); - return; - } - - if (test_bit (EV_ABS, bitmask_ev) && - test_bit (ABS_X, bitmask_abs) && test_bit (ABS_Y, bitmask_abs)) { - if (test_bit (BTN_STYLUS, bitmask_key) || test_bit (BTN_TOOL_PEN, bitmask_key)) - udev_builtin_add_property(dev, test, "ID_INPUT_TABLET", "1"); - else if (test_bit (BTN_TOOL_FINGER, bitmask_key) && !test_bit (BTN_TOOL_PEN, bitmask_key)) - is_touchpad = 1; - else if (test_bit (BTN_TRIGGER, bitmask_key) || - test_bit (BTN_A, bitmask_key) || - test_bit (BTN_1, bitmask_key)) - udev_builtin_add_property(dev, test, "ID_INPUT_JOYSTICK", "1"); - else if (test_bit (BTN_MOUSE, bitmask_key)) - /* This path is taken by VMware's USB mouse, which has - * absolute axes, but no touch/pressure button. */ - is_mouse = 1; - else if (test_bit (BTN_TOUCH, bitmask_key)) - udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHSCREEN", "1"); - } - - if (test_bit (EV_REL, bitmask_ev) && - test_bit (REL_X, bitmask_rel) && test_bit (REL_Y, bitmask_rel) && - test_bit (BTN_MOUSE, bitmask_key)) - is_mouse = 1; - - if (is_mouse) - udev_builtin_add_property(dev, test, "ID_INPUT_MOUSE", "1"); - if (is_touchpad) - udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHPAD", "1"); -} - -/* key like devices */ -static void test_key (struct udev_device *dev, - const unsigned long* bitmask_ev, - const unsigned long* bitmask_key, - bool test) -{ - struct udev *udev = udev_device_get_udev(dev); - unsigned i; - unsigned long found; - unsigned long mask; - - /* do we have any KEY_* capability? */ - if (!test_bit (EV_KEY, bitmask_ev)) { - info(udev, "test_key: no EV_KEY capability\n"); - return; - } - - /* only consider KEY_* here, not BTN_* */ - found = 0; - for (i = 0; i < BTN_MISC/BITS_PER_LONG; ++i) { - found |= bitmask_key[i]; - info(udev, "test_key: checking bit block %lu for any keys; found=%i\n", i*BITS_PER_LONG, found > 0); - } - /* If there are no keys in the lower block, check the higher block */ - if (!found) { - for (i = KEY_OK; i < BTN_TRIGGER_HAPPY; ++i) { - if (test_bit (i, bitmask_key)) { - info(udev, "test_key: Found key %x in high block\n", i); - found = 1; - break; - } - } - } - - if (found > 0) - udev_builtin_add_property(dev, test, "ID_INPUT_KEY", "1"); - - /* the first 32 bits are ESC, numbers, and Q to D; if we have all of - * those, consider it a full keyboard; do not test KEY_RESERVED, though */ - mask = 0xFFFFFFFE; - if ((bitmask_key[0] & mask) == mask) - udev_builtin_add_property(dev, test, "ID_INPUT_KEYBOARD", "1"); -} - -static int builtin_input_id(struct udev_device *dev, int argc, char *argv[], bool test) -{ - struct udev_device *pdev; - unsigned long bitmask_ev[NBITS(EV_MAX)]; - unsigned long bitmask_abs[NBITS(ABS_MAX)]; - unsigned long bitmask_key[NBITS(KEY_MAX)]; - unsigned long bitmask_rel[NBITS(REL_MAX)]; - - /* walk up the parental chain until we find the real input device; the - * argument is very likely a subdevice of this, like eventN */ - pdev = dev; - while (pdev != NULL && udev_device_get_sysattr_value(pdev, "capabilities/ev") == NULL) - pdev = udev_device_get_parent_with_subsystem_devtype(pdev, "input", NULL); - - /* not an "input" class device */ - if (pdev == NULL) - return EXIT_SUCCESS; - - /* Use this as a flag that input devices were detected, so that this - * program doesn't need to be called more than once per device */ - udev_builtin_add_property(dev, test, "ID_INPUT", "1"); - get_cap_mask(dev, pdev, "capabilities/ev", bitmask_ev, sizeof(bitmask_ev), test); - get_cap_mask(dev, pdev, "capabilities/abs", bitmask_abs, sizeof(bitmask_abs), test); - get_cap_mask(dev, pdev, "capabilities/rel", bitmask_rel, sizeof(bitmask_rel), test); - get_cap_mask(dev, pdev, "capabilities/key", bitmask_key, sizeof(bitmask_key), test); - test_pointers(dev, bitmask_ev, bitmask_abs, bitmask_key, bitmask_rel, test); - test_key(dev, bitmask_ev, bitmask_key, test); - return EXIT_SUCCESS; -} - -const struct udev_builtin udev_builtin_input_id = { - .name = "input_id", - .cmd = builtin_input_id, - .help = "input device properties", -}; diff --git a/src/udev/src/udev-builtin-kmod.c b/src/udev/src/udev-builtin-kmod.c deleted file mode 100644 index 57e813f86..000000000 --- a/src/udev/src/udev-builtin-kmod.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * load kernel modules - * - * Copyright (C) 2011 Kay Sievers <kay.sievers@vrfy.org> - * Copyright (C) 2011 ProFUSION embedded systems - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <libkmod.h> - -#include "udev.h" - -static struct kmod_ctx *ctx; - -static int load_module(struct udev *udev, const char *alias) -{ - struct kmod_list *list = NULL; - struct kmod_list *l; - int err; - - err = kmod_module_new_from_lookup(ctx, alias, &list); - if (err < 0) - return err; - - if (list == NULL) - info(udev, "no module matches '%s'\n", alias); - - kmod_list_foreach(l, list) { - struct kmod_module *mod = kmod_module_get_module(l); - - err = kmod_module_probe_insert_module(mod, KMOD_PROBE_APPLY_BLACKLIST, NULL, NULL, NULL, NULL); - if (err == KMOD_PROBE_APPLY_BLACKLIST) - info(udev, "module '%s' is blacklisted\n", kmod_module_get_name(mod)); - else if (err == 0) - info(udev, "inserted '%s'\n", kmod_module_get_name(mod)); - else - info(udev, "failed to insert '%s'\n", kmod_module_get_name(mod)); - - kmod_module_unref(mod); - } - - kmod_module_unref_list(list); - return err; -} - -static void udev_kmod_log(void *data, int priority, const char *file, int line, - const char *fn, const char *format, va_list args) -{ - udev_main_log(data, priority, file, line, fn, format, args); -} - -/* needs to re-instantiate the context after a reload */ -static int builtin_kmod(struct udev_device *dev, int argc, char *argv[], bool test) -{ - struct udev *udev = udev_device_get_udev(dev); - int i; - - if (!ctx) { - ctx = kmod_new(NULL, NULL); - if (!ctx) - return -ENOMEM; - - info(udev, "load module index\n"); - kmod_set_log_fn(ctx, udev_kmod_log, udev); - kmod_load_resources(ctx); - } - - if (argc < 3 || strcmp(argv[1], "load")) { - err(udev, "expect: %s load <module>\n", argv[0]); - return EXIT_FAILURE; - } - - for (i = 2; argv[i]; i++) { - info(udev, "execute '%s' '%s'\n", argv[1], argv[i]); - load_module(udev, argv[i]); - } - - return EXIT_SUCCESS; -} - -/* called at udev startup */ -static int builtin_kmod_init(struct udev *udev) -{ - if (ctx) - return 0; - - ctx = kmod_new(NULL, NULL); - if (!ctx) - return -ENOMEM; - - info(udev, "load module index\n"); - kmod_set_log_fn(ctx, udev_kmod_log, udev); - kmod_load_resources(ctx); - return 0; -} - -/* called on udev shutdown and reload request */ -static void builtin_kmod_exit(struct udev *udev) -{ - info(udev, "unload module index\n"); - ctx = kmod_unref(ctx); -} - -/* called every couple of seconds during event activity; 'true' if config has changed */ -static bool builtin_kmod_validate(struct udev *udev) -{ - info(udev, "validate module index\n"); - if (kmod_validate_resources(ctx) != KMOD_RESOURCES_OK) - return true; - return false; -} - -const struct udev_builtin udev_builtin_kmod = { - .name = "kmod", - .cmd = builtin_kmod, - .init = builtin_kmod_init, - .exit = builtin_kmod_exit, - .validate = builtin_kmod_validate, - .help = "kernel module loader", - .run_once = false, -}; diff --git a/src/udev/src/udev-builtin-path_id.c b/src/udev/src/udev-builtin-path_id.c deleted file mode 100644 index a8559d2dd..000000000 --- a/src/udev/src/udev-builtin-path_id.c +++ /dev/null @@ -1,498 +0,0 @@ -/* - * compose persistent device path - * - * Copyright (C) 2009-2011 Kay Sievers <kay.sievers@vrfy.org> - * - * Logic based on Hannes Reinecke's shell script. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <unistd.h> -#include <string.h> -#include <ctype.h> -#include <fcntl.h> -#include <errno.h> -#include <dirent.h> -#include <getopt.h> - -#include "udev.h" - -static int path_prepend(char **path, const char *fmt, ...) -{ - va_list va; - char *pre; - int err = 0; - - va_start(va, fmt); - err = vasprintf(&pre, fmt, va); - va_end(va); - if (err < 0) - goto out; - - if (*path != NULL) { - char *new; - - err = asprintf(&new, "%s-%s", pre, *path); - free(pre); - if (err < 0) - goto out; - free(*path); - *path = new; - } else { - *path = pre; - } -out: - return err; -} - -/* -** Linux only supports 32 bit luns. -** See drivers/scsi/scsi_scan.c::scsilun_to_int() for more details. -*/ -static int format_lun_number(struct udev_device *dev, char **path) -{ - unsigned long lun = strtoul(udev_device_get_sysnum(dev), NULL, 10); - - /* address method 0, peripheral device addressing with bus id of zero */ - if (lun < 256) - return path_prepend(path, "lun-%d", lun); - /* handle all other lun addressing methods by using a variant of the original lun format */ - return path_prepend(path, "lun-0x%04x%04x00000000", (lun & 0xffff), (lun >> 16) & 0xffff); -} - -static struct udev_device *skip_subsystem(struct udev_device *dev, const char *subsys) -{ - struct udev_device *parent = dev; - - while (parent != NULL) { - const char *subsystem; - - subsystem = udev_device_get_subsystem(parent); - if (subsystem == NULL || strcmp(subsystem, subsys) != 0) - break; - dev = parent; - parent = udev_device_get_parent(parent); - } - return dev; -} - -static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent, char **path) -{ - struct udev *udev = udev_device_get_udev(parent); - struct udev_device *targetdev; - struct udev_device *fcdev = NULL; - const char *port; - char *lun = NULL;; - - targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target"); - if (targetdev == NULL) - return NULL; - - fcdev = udev_device_new_from_subsystem_sysname(udev, "fc_transport", udev_device_get_sysname(targetdev)); - if (fcdev == NULL) - return NULL; - port = udev_device_get_sysattr_value(fcdev, "port_name"); - if (port == NULL) { - parent = NULL; - goto out; - } - - format_lun_number(parent, &lun); - path_prepend(path, "fc-%s-%s", port, lun); - if (lun) - free(lun); -out: - udev_device_unref(fcdev); - return parent; -} - -static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **path) -{ - struct udev *udev = udev_device_get_udev(parent); - struct udev_device *targetdev; - struct udev_device *target_parent; - struct udev_device *sasdev; - const char *sas_address; - char *lun = NULL; - - targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target"); - if (targetdev == NULL) - return NULL; - - target_parent = udev_device_get_parent(targetdev); - if (target_parent == NULL) - return NULL; - - sasdev = udev_device_new_from_subsystem_sysname(udev, "sas_device", - udev_device_get_sysname(target_parent)); - if (sasdev == NULL) - return NULL; - - sas_address = udev_device_get_sysattr_value(sasdev, "sas_address"); - if (sas_address == NULL) { - parent = NULL; - goto out; - } - - format_lun_number(parent, &lun); - path_prepend(path, "sas-%s-%s", sas_address, lun); - if (lun) - free(lun); -out: - udev_device_unref(sasdev); - return parent; -} - -static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char **path) -{ - struct udev *udev = udev_device_get_udev(parent); - struct udev_device *transportdev; - struct udev_device *sessiondev = NULL; - const char *target; - char *connname; - struct udev_device *conndev = NULL; - const char *addr; - const char *port; - char *lun = NULL; - - /* find iscsi session */ - transportdev = parent; - for (;;) { - transportdev = udev_device_get_parent(transportdev); - if (transportdev == NULL) - return NULL; - if (strncmp(udev_device_get_sysname(transportdev), "session", 7) == 0) - break; - } - - /* find iscsi session device */ - sessiondev = udev_device_new_from_subsystem_sysname(udev, "iscsi_session", udev_device_get_sysname(transportdev)); - if (sessiondev == NULL) - return NULL; - target = udev_device_get_sysattr_value(sessiondev, "targetname"); - if (target == NULL) { - parent = NULL; - goto out; - } - - if (asprintf(&connname, "connection%s:0", udev_device_get_sysnum(transportdev)) < 0) { - parent = NULL; - goto out; - } - conndev = udev_device_new_from_subsystem_sysname(udev, "iscsi_connection", connname); - free(connname); - if (conndev == NULL) { - parent = NULL; - goto out; - } - addr = udev_device_get_sysattr_value(conndev, "persistent_address"); - port = udev_device_get_sysattr_value(conndev, "persistent_port"); - if (addr == NULL || port == NULL) { - parent = NULL; - goto out; - } - - format_lun_number(parent, &lun); - path_prepend(path, "ip-%s:%s-iscsi-%s-%s", addr, port, target, lun); - if (lun) - free(lun); -out: - udev_device_unref(sessiondev); - udev_device_unref(conndev); - return parent; -} - -static struct udev_device *handle_scsi_default(struct udev_device *parent, char **path) -{ - struct udev_device *hostdev; - int host, bus, target, lun; - const char *name; - char *base; - char *pos; - DIR *dir; - struct dirent *dent; - int basenum; - - hostdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host"); - if (hostdev == NULL) - return NULL; - - name = udev_device_get_sysname(parent); - if (sscanf(name, "%d:%d:%d:%d", &host, &bus, &target, &lun) != 4) - return NULL; - - /* rebase host offset to get the local relative number */ - basenum = -1; - base = strdup(udev_device_get_syspath(hostdev)); - if (base == NULL) - return NULL; - pos = strrchr(base, '/'); - if (pos == NULL) { - parent = NULL; - goto out; - } - pos[0] = '\0'; - dir = opendir(base); - if (dir == NULL) { - parent = NULL; - goto out; - } - for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { - char *rest; - int i; - - if (dent->d_name[0] == '.') - continue; - if (dent->d_type != DT_DIR && dent->d_type != DT_LNK) - continue; - if (strncmp(dent->d_name, "host", 4) != 0) - continue; - i = strtoul(&dent->d_name[4], &rest, 10); - if (rest[0] != '\0') - continue; - /* - * find the smallest number; the host really needs to export its - * own instance number per parent device; relying on the global host - * enumeration and plainly rebasing the numbers sounds unreliable - */ - if (basenum == -1 || i < basenum) - basenum = i; - } - closedir(dir); - if (basenum == -1) { - parent = NULL; - goto out; - } - host -= basenum; - - path_prepend(path, "scsi-%u:%u:%u:%u", host, bus, target, lun); -out: - free(base); - return hostdev; -} - -static struct udev_device *handle_scsi(struct udev_device *parent, char **path) -{ - const char *devtype; - const char *name; - const char *id; - - devtype = udev_device_get_devtype(parent); - if (devtype == NULL || strcmp(devtype, "scsi_device") != 0) - return parent; - - /* firewire */ - id = udev_device_get_sysattr_value(parent, "ieee1394_id"); - if (id != NULL) { - parent = skip_subsystem(parent, "scsi"); - path_prepend(path, "ieee1394-0x%s", id); - goto out; - } - - /* lousy scsi sysfs does not have a "subsystem" for the transport */ - name = udev_device_get_syspath(parent); - - if (strstr(name, "/rport-") != NULL) { - parent = handle_scsi_fibre_channel(parent, path); - goto out; - } - - if (strstr(name, "/end_device-") != NULL) { - parent = handle_scsi_sas(parent, path); - goto out; - } - - if (strstr(name, "/session") != NULL) { - parent = handle_scsi_iscsi(parent, path); - goto out; - } - - /* - * We do not support the ATA transport class, it creates duplicated link - * names as the fake SCSI host adapters are all separated, they are all - * re-based as host == 0. ATA should just stop faking two duplicated - * hierarchies for a single topology and leave the SCSI stuff alone; - * until that happens, there are no by-path/ links for ATA devices behind - * an ATA transport class. - */ - if (strstr(name, "/ata") != NULL) { - parent = NULL; - goto out; - } - - parent = handle_scsi_default(parent, path); -out: - return parent; -} - -static void handle_scsi_tape(struct udev_device *dev, char **path) -{ - const char *name; - - /* must be the last device in the syspath */ - if (*path != NULL) - return; - - name = udev_device_get_sysname(dev); - if (strncmp(name, "nst", 3) == 0 && strchr("lma", name[3]) != NULL) - path_prepend(path, "nst%c", name[3]); - else if (strncmp(name, "st", 2) == 0 && strchr("lma", name[2]) != NULL) - path_prepend(path, "st%c", name[2]); -} - -static struct udev_device *handle_usb(struct udev_device *parent, char **path) -{ - const char *devtype; - const char *str; - const char *port; - - devtype = udev_device_get_devtype(parent); - if (devtype == NULL) - return parent; - if (strcmp(devtype, "usb_interface") != 0 && strcmp(devtype, "usb_device") != 0) - return parent; - - str = udev_device_get_sysname(parent); - port = strchr(str, '-'); - if (port == NULL) - return parent; - port++; - - parent = skip_subsystem(parent, "usb"); - path_prepend(path, "usb-0:%s", port); - return parent; -} - -static struct udev_device *handle_ccw(struct udev_device *parent, struct udev_device *dev, char **path) -{ - struct udev_device *scsi_dev; - - scsi_dev = udev_device_get_parent_with_subsystem_devtype(dev, "scsi", "scsi_device"); - if (scsi_dev != NULL) { - const char *wwpn; - const char *lun; - const char *hba_id; - - hba_id = udev_device_get_sysattr_value(scsi_dev, "hba_id"); - wwpn = udev_device_get_sysattr_value(scsi_dev, "wwpn"); - lun = udev_device_get_sysattr_value(scsi_dev, "fcp_lun"); - if (hba_id != NULL && lun != NULL && wwpn != NULL) { - path_prepend(path, "ccw-%s-zfcp-%s:%s", hba_id, wwpn, lun); - goto out; - } - } - - path_prepend(path, "ccw-%s", udev_device_get_sysname(parent)); -out: - parent = skip_subsystem(parent, "ccw"); - return parent; -} - -static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool test) -{ - struct udev_device *parent; - char *path = NULL; - - /* S390 ccw bus */ - parent = udev_device_get_parent_with_subsystem_devtype(dev, "ccw", NULL); - if (parent != NULL) { - handle_ccw(parent, dev, &path); - goto out; - } - - /* walk up the chain of devices and compose path */ - parent = dev; - while (parent != NULL) { - const char *subsys; - - subsys = udev_device_get_subsystem(parent); - if (subsys == NULL) { - ; - } else if (strcmp(subsys, "scsi_tape") == 0) { - handle_scsi_tape(parent, &path); - } else if (strcmp(subsys, "scsi") == 0) { - parent = handle_scsi(parent, &path); - } else if (strcmp(subsys, "usb") == 0) { - parent = handle_usb(parent, &path); - } else if (strcmp(subsys, "serio") == 0) { - path_prepend(&path, "serio-%s", udev_device_get_sysnum(parent)); - parent = skip_subsystem(parent, "serio"); - } else if (strcmp(subsys, "pci") == 0) { - path_prepend(&path, "pci-%s", udev_device_get_sysname(parent)); - parent = skip_subsystem(parent, "pci"); - } else if (strcmp(subsys, "platform") == 0) { - path_prepend(&path, "platform-%s", udev_device_get_sysname(parent)); - parent = skip_subsystem(parent, "platform"); - } else if (strcmp(subsys, "acpi") == 0) { - path_prepend(&path, "acpi-%s", udev_device_get_sysname(parent)); - parent = skip_subsystem(parent, "acpi"); - } else if (strcmp(subsys, "xen") == 0) { - path_prepend(&path, "xen-%s", udev_device_get_sysname(parent)); - parent = skip_subsystem(parent, "xen"); - } else if (strcmp(subsys, "virtio") == 0) { - path_prepend(&path, "virtio-pci-%s", udev_device_get_sysname(parent)); - parent = skip_subsystem(parent, "virtio"); - } - - parent = udev_device_get_parent(parent); - } -out: - if (path != NULL) { - char tag[UTIL_NAME_SIZE]; - size_t i; - const char *p; - - /* compose valid udev tag name */ - for (p = path, i = 0; *p; p++) { - if ((*p >= '0' && *p <= '9') || - (*p >= 'A' && *p <= 'Z') || - (*p >= 'a' && *p <= 'z') || - *p == '-') { - tag[i++] = *p; - continue; - } - - /* skip all leading '_' */ - if (i == 0) - continue; - - /* avoid second '_' */ - if (tag[i-1] == '_') - continue; - - tag[i++] = '_'; - } - /* strip trailing '_' */ - while (i > 0 && tag[i-1] == '_') - i--; - tag[i] = '\0'; - - udev_builtin_add_property(dev, test, "ID_PATH", path); - udev_builtin_add_property(dev, test, "ID_PATH_TAG", tag); - free(path); - return EXIT_SUCCESS; - } - return EXIT_FAILURE; -} - -const struct udev_builtin udev_builtin_path_id = { - .name = "path_id", - .cmd = builtin_path_id, - .help = "compose persistent device path", - .run_once = true, -}; diff --git a/src/udev/src/udev-builtin-usb_id.c b/src/udev/src/udev-builtin-usb_id.c deleted file mode 100644 index 85828e32d..000000000 --- a/src/udev/src/udev-builtin-usb_id.c +++ /dev/null @@ -1,482 +0,0 @@ -/* - * USB device properties and persistent device path - * - * Copyright (c) 2005 SUSE Linux Products GmbH, Germany - * Author: Hannes Reinecke <hare@suse.de> - * - * Copyright (C) 2005-2011 Kay Sievers <kay.sievers@vrfy.org> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <unistd.h> -#include <string.h> -#include <ctype.h> -#include <fcntl.h> -#include <errno.h> - -#include "udev.h" - -static void set_usb_iftype(char *to, int if_class_num, size_t len) -{ - char *type = "generic"; - - switch (if_class_num) { - case 1: - type = "audio"; - break; - case 2: /* CDC-Control */ - break; - case 3: - type = "hid"; - break; - case 5: /* Physical */ - break; - case 6: - type = "media"; - break; - case 7: - type = "printer"; - break; - case 8: - type = "storage"; - break; - case 9: - type = "hub"; - break; - case 0x0a: /* CDC-Data */ - break; - case 0x0b: /* Chip/Smart Card */ - break; - case 0x0d: /* Content Security */ - break; - case 0x0e: - type = "video"; - break; - case 0xdc: /* Diagnostic Device */ - break; - case 0xe0: /* Wireless Controller */ - break; - case 0xfe: /* Application-specific */ - break; - case 0xff: /* Vendor-specific */ - break; - default: - break; - } - strncpy(to, type, len); - to[len-1] = '\0'; -} - -static int set_usb_mass_storage_ifsubtype(char *to, const char *from, size_t len) -{ - int type_num = 0; - char *eptr; - char *type = "generic"; - - type_num = strtoul(from, &eptr, 0); - if (eptr != from) { - switch (type_num) { - case 2: - type = "atapi"; - break; - case 3: - type = "tape"; - break; - case 4: /* UFI */ - case 5: /* SFF-8070i */ - type = "floppy"; - break; - case 1: /* RBC devices */ - type = "rbc"; - break; - case 6: /* Transparent SPC-2 devices */ - type = "scsi"; - break; - default: - break; - } - } - util_strscpy(to, len, type); - return type_num; -} - -static void set_scsi_type(char *to, const char *from, size_t len) -{ - int type_num; - char *eptr; - char *type = "generic"; - - type_num = strtoul(from, &eptr, 0); - if (eptr != from) { - switch (type_num) { - case 0: - case 0xe: - type = "disk"; - break; - case 1: - type = "tape"; - break; - case 4: - case 7: - case 0xf: - type = "optical"; - break; - case 5: - type = "cd"; - break; - default: - break; - } - } - util_strscpy(to, len, type); -} - -#define USB_DT_DEVICE 0x01 -#define USB_DT_INTERFACE 0x04 - -static int dev_if_packed_info(struct udev_device *dev, char *ifs_str, size_t len) -{ - char *filename = NULL; - int fd; - ssize_t size; - unsigned char buf[18 + 65535]; - unsigned int pos, strpos; - struct usb_interface_descriptor { - u_int8_t bLength; - u_int8_t bDescriptorType; - u_int8_t bInterfaceNumber; - u_int8_t bAlternateSetting; - u_int8_t bNumEndpoints; - u_int8_t bInterfaceClass; - u_int8_t bInterfaceSubClass; - u_int8_t bInterfaceProtocol; - u_int8_t iInterface; - } __attribute__((packed)); - int err = 0; - - if (asprintf(&filename, "%s/descriptors", udev_device_get_syspath(dev)) < 0) { - err = -1; - goto out; - } - fd = open(filename, O_RDONLY|O_CLOEXEC); - if (fd < 0) { - fprintf(stderr, "error opening USB device 'descriptors' file\n"); - err = -1; - goto out; - } - size = read(fd, buf, sizeof(buf)); - close(fd); - if (size < 18 || size == sizeof(buf)) { - err = -1; - goto out; - } - - pos = 0; - strpos = 0; - ifs_str[0] = '\0'; - while (pos < sizeof(buf) && strpos+7 < len-2) { - struct usb_interface_descriptor *desc; - char if_str[8]; - - desc = (struct usb_interface_descriptor *) &buf[pos]; - if (desc->bLength < 3) - break; - pos += desc->bLength; - - if (desc->bDescriptorType != USB_DT_INTERFACE) - continue; - - if (snprintf(if_str, 8, ":%02x%02x%02x", - desc->bInterfaceClass, - desc->bInterfaceSubClass, - desc->bInterfaceProtocol) != 7) - continue; - - if (strstr(ifs_str, if_str) != NULL) - continue; - - memcpy(&ifs_str[strpos], if_str, 8), - strpos += 7; - } - if (strpos > 0) { - ifs_str[strpos++] = ':'; - ifs_str[strpos++] = '\0'; - } -out: - free(filename); - return err; -} - -/* - * A unique USB identification is generated like this: - * - * 1.) Get the USB device type from InterfaceClass and InterfaceSubClass - * 2.) If the device type is 'Mass-Storage/SPC-2' or 'Mass-Storage/RBC' - * use the SCSI vendor and model as USB-Vendor and USB-model. - * 3.) Otherwise use the USB manufacturer and product as - * USB-Vendor and USB-model. Any non-printable characters - * in those strings will be skipped; a slash '/' will be converted - * into a full stop '.'. - * 4.) If that fails, too, we will use idVendor and idProduct - * as USB-Vendor and USB-model. - * 5.) The USB identification is the USB-vendor and USB-model - * string concatenated with an underscore '_'. - * 6.) If the device supplies a serial number, this number - * is concatenated with the identification with an underscore '_'. - */ -static int builtin_usb_id(struct udev_device *dev, int argc, char *argv[], bool test) -{ - char vendor_str[64]; - char vendor_str_enc[256]; - const char *vendor_id; - char model_str[64]; - char model_str_enc[256]; - const char *product_id; - char serial_str[UTIL_NAME_SIZE]; - char packed_if_str[UTIL_NAME_SIZE]; - char revision_str[64]; - char type_str[64]; - char instance_str[64]; - const char *ifnum = NULL; - const char *driver = NULL; - char serial[256]; - - struct udev *udev = udev_device_get_udev(dev); - struct udev_device *dev_interface = NULL; - struct udev_device *dev_usb = NULL; - const char *if_class, *if_subclass; - int if_class_num; - int protocol = 0; - size_t l; - char *s; - - vendor_str[0] = '\0'; - model_str[0] = '\0'; - serial_str[0] = '\0'; - packed_if_str[0] = '\0'; - revision_str[0] = '\0'; - type_str[0] = '\0'; - instance_str[0] = '\0'; - - dbg(udev, "syspath %s\n", udev_device_get_syspath(dev)); - - /* shortcut, if we are called directly for a "usb_device" type */ - if (udev_device_get_devtype(dev) != NULL && strcmp(udev_device_get_devtype(dev), "usb_device") == 0) { - dev_if_packed_info(dev, packed_if_str, sizeof(packed_if_str)); - dev_usb = dev; - goto fallback; - } - - /* usb interface directory */ - dev_interface = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_interface"); - if (dev_interface == NULL) { - info(udev, "unable to access usb_interface device of '%s'\n", - udev_device_get_syspath(dev)); - return EXIT_FAILURE; - } - - ifnum = udev_device_get_sysattr_value(dev_interface, "bInterfaceNumber"); - driver = udev_device_get_sysattr_value(dev_interface, "driver"); - - if_class = udev_device_get_sysattr_value(dev_interface, "bInterfaceClass"); - if (!if_class) { - info(udev, "%s: cannot get bInterfaceClass attribute\n", - udev_device_get_sysname(dev)); - return EXIT_FAILURE; - } - - if_class_num = strtoul(if_class, NULL, 16); - if (if_class_num == 8) { - /* mass storage */ - if_subclass = udev_device_get_sysattr_value(dev_interface, "bInterfaceSubClass"); - if (if_subclass != NULL) - protocol = set_usb_mass_storage_ifsubtype(type_str, if_subclass, sizeof(type_str)-1); - } else { - set_usb_iftype(type_str, if_class_num, sizeof(type_str)-1); - } - - info(udev, "%s: if_class %d protocol %d\n", - udev_device_get_syspath(dev_interface), if_class_num, protocol); - - /* usb device directory */ - dev_usb = udev_device_get_parent_with_subsystem_devtype(dev_interface, "usb", "usb_device"); - if (!dev_usb) { - info(udev, "unable to find parent 'usb' device of '%s'\n", - udev_device_get_syspath(dev)); - return EXIT_FAILURE; - } - - /* all interfaces of the device in a single string */ - dev_if_packed_info(dev_usb, packed_if_str, sizeof(packed_if_str)); - - /* mass storage : SCSI or ATAPI */ - if ((protocol == 6 || protocol == 2)) { - struct udev_device *dev_scsi; - const char *scsi_model, *scsi_vendor, *scsi_type, *scsi_rev; - int host, bus, target, lun; - - /* get scsi device */ - dev_scsi = udev_device_get_parent_with_subsystem_devtype(dev, "scsi", "scsi_device"); - if (dev_scsi == NULL) { - info(udev, "unable to find parent 'scsi' device of '%s'\n", - udev_device_get_syspath(dev)); - goto fallback; - } - if (sscanf(udev_device_get_sysname(dev_scsi), "%d:%d:%d:%d", &host, &bus, &target, &lun) != 4) { - info(udev, "invalid scsi device '%s'\n", udev_device_get_sysname(dev_scsi)); - goto fallback; - } - - /* Generic SPC-2 device */ - scsi_vendor = udev_device_get_sysattr_value(dev_scsi, "vendor"); - if (!scsi_vendor) { - info(udev, "%s: cannot get SCSI vendor attribute\n", - udev_device_get_sysname(dev_scsi)); - goto fallback; - } - udev_util_encode_string(scsi_vendor, vendor_str_enc, sizeof(vendor_str_enc)); - util_replace_whitespace(scsi_vendor, vendor_str, sizeof(vendor_str)-1); - util_replace_chars(vendor_str, NULL); - - scsi_model = udev_device_get_sysattr_value(dev_scsi, "model"); - if (!scsi_model) { - info(udev, "%s: cannot get SCSI model attribute\n", - udev_device_get_sysname(dev_scsi)); - goto fallback; - } - udev_util_encode_string(scsi_model, model_str_enc, sizeof(model_str_enc)); - util_replace_whitespace(scsi_model, model_str, sizeof(model_str)-1); - util_replace_chars(model_str, NULL); - - scsi_type = udev_device_get_sysattr_value(dev_scsi, "type"); - if (!scsi_type) { - info(udev, "%s: cannot get SCSI type attribute\n", - udev_device_get_sysname(dev_scsi)); - goto fallback; - } - set_scsi_type(type_str, scsi_type, sizeof(type_str)-1); - - scsi_rev = udev_device_get_sysattr_value(dev_scsi, "rev"); - if (!scsi_rev) { - info(udev, "%s: cannot get SCSI revision attribute\n", - udev_device_get_sysname(dev_scsi)); - goto fallback; - } - util_replace_whitespace(scsi_rev, revision_str, sizeof(revision_str)-1); - util_replace_chars(revision_str, NULL); - - /* - * some broken devices have the same identifiers - * for all luns, export the target:lun number - */ - sprintf(instance_str, "%d:%d", target, lun); - } - -fallback: - vendor_id = udev_device_get_sysattr_value(dev_usb, "idVendor"); - product_id = udev_device_get_sysattr_value(dev_usb, "idProduct"); - - /* fallback to USB vendor & device */ - if (vendor_str[0] == '\0') { - const char *usb_vendor = NULL; - - usb_vendor = udev_device_get_sysattr_value(dev_usb, "manufacturer"); - if (!usb_vendor) - usb_vendor = vendor_id; - if (!usb_vendor) { - info(udev, "No USB vendor information available\n"); - return EXIT_FAILURE; - } - udev_util_encode_string(usb_vendor, vendor_str_enc, sizeof(vendor_str_enc)); - util_replace_whitespace(usb_vendor, vendor_str, sizeof(vendor_str)-1); - util_replace_chars(vendor_str, NULL); - } - - if (model_str[0] == '\0') { - const char *usb_model = NULL; - - usb_model = udev_device_get_sysattr_value(dev_usb, "product"); - if (!usb_model) - usb_model = product_id; - if (!usb_model) { - dbg(udev, "No USB model information available\n"); - return EXIT_FAILURE; - } - udev_util_encode_string(usb_model, model_str_enc, sizeof(model_str_enc)); - util_replace_whitespace(usb_model, model_str, sizeof(model_str)-1); - util_replace_chars(model_str, NULL); - } - - if (revision_str[0] == '\0') { - const char *usb_rev; - - usb_rev = udev_device_get_sysattr_value(dev_usb, "bcdDevice"); - if (usb_rev) { - util_replace_whitespace(usb_rev, revision_str, sizeof(revision_str)-1); - util_replace_chars(revision_str, NULL); - } - } - - if (serial_str[0] == '\0') { - const char *usb_serial; - - usb_serial = udev_device_get_sysattr_value(dev_usb, "serial"); - if (usb_serial) { - util_replace_whitespace(usb_serial, serial_str, sizeof(serial_str)-1); - util_replace_chars(serial_str, NULL); - } - } - - s = serial; - l = util_strpcpyl(&s, sizeof(serial), vendor_str, "_", model_str, NULL); - if (serial_str[0] != '\0') - l = util_strpcpyl(&s, l, "_", serial_str, NULL); - - if (instance_str[0] != '\0') - util_strpcpyl(&s, l, "-", instance_str, NULL); - - udev_builtin_add_property(dev, test, "ID_VENDOR", vendor_str); - udev_builtin_add_property(dev, test, "ID_VENDOR_ENC", vendor_str_enc); - udev_builtin_add_property(dev, test, "ID_VENDOR_ID", vendor_id); - udev_builtin_add_property(dev, test, "ID_MODEL", model_str); - udev_builtin_add_property(dev, test, "ID_MODEL_ENC", model_str_enc); - udev_builtin_add_property(dev, test, "ID_MODEL_ID", product_id); - udev_builtin_add_property(dev, test, "ID_REVISION", revision_str); - udev_builtin_add_property(dev, test, "ID_SERIAL", serial); - if (serial_str[0] != '\0') - udev_builtin_add_property(dev, test, "ID_SERIAL_SHORT", serial_str); - if (type_str[0] != '\0') - udev_builtin_add_property(dev, test, "ID_TYPE", type_str); - if (instance_str[0] != '\0') - udev_builtin_add_property(dev, test, "ID_INSTANCE", instance_str); - udev_builtin_add_property(dev, test, "ID_BUS", "usb"); - if (packed_if_str[0] != '\0') - udev_builtin_add_property(dev, test, "ID_USB_INTERFACES", packed_if_str); - if (ifnum != NULL) - udev_builtin_add_property(dev, test, "ID_USB_INTERFACE_NUM", ifnum); - if (driver != NULL) - udev_builtin_add_property(dev, test, "ID_USB_DRIVER", driver); - return EXIT_SUCCESS; -} - -const struct udev_builtin udev_builtin_usb_id = { - .name = "usb_id", - .cmd = builtin_usb_id, - .help = "usb device properties", - .run_once = true, -}; diff --git a/src/udev/src/udev-builtin.c b/src/udev/src/udev-builtin.c deleted file mode 100644 index 5bc5fa68f..000000000 --- a/src/udev/src/udev-builtin.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2007-2009 Kay Sievers <kay.sievers@vrfy.org> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <errno.h> -#include <getopt.h> - -#include "udev.h" - -static const struct udev_builtin *builtins[] = { - [UDEV_BUILTIN_BLKID] = &udev_builtin_blkid, - [UDEV_BUILTIN_FIRMWARE] = &udev_builtin_firmware, - [UDEV_BUILTIN_INPUT_ID] = &udev_builtin_input_id, - [UDEV_BUILTIN_KMOD] = &udev_builtin_kmod, - [UDEV_BUILTIN_PATH_ID] = &udev_builtin_path_id, - [UDEV_BUILTIN_PCI_DB] = &udev_builtin_pci_db, - [UDEV_BUILTIN_USB_DB] = &udev_builtin_usb_db, - [UDEV_BUILTIN_USB_ID] = &udev_builtin_usb_id, -}; - -int udev_builtin_init(struct udev *udev) -{ - unsigned int i; - int err; - - for (i = 0; i < ARRAY_SIZE(builtins); i++) { - if (builtins[i]->init) { - err = builtins[i]->init(udev); - if (err < 0) - break; - } - } - return err; -} - -void udev_builtin_exit(struct udev *udev) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(builtins); i++) - if (builtins[i]->exit) - builtins[i]->exit(udev); -} - -bool udev_builtin_validate(struct udev *udev) -{ - unsigned int i; - bool change = false; - - for (i = 0; i < ARRAY_SIZE(builtins); i++) - if (builtins[i]->validate) - if (builtins[i]->validate(udev)) - change = true; - return change; -} - -void udev_builtin_list(struct udev *udev) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(builtins); i++) - fprintf(stderr, " %-12s %s\n", builtins[i]->name, builtins[i]->help); -} - -const char *udev_builtin_name(enum udev_builtin_cmd cmd) -{ - return builtins[cmd]->name; -} - -bool udev_builtin_run_once(enum udev_builtin_cmd cmd) -{ - return builtins[cmd]->run_once; -} - -enum udev_builtin_cmd udev_builtin_lookup(const char *command) -{ - char name[UTIL_PATH_SIZE]; - enum udev_builtin_cmd i; - char *pos; - - util_strscpy(name, sizeof(name), command); - pos = strchr(name, ' '); - if (pos) - pos[0] = '\0'; - for (i = 0; i < ARRAY_SIZE(builtins); i++) - if (strcmp(builtins[i]->name, name) == 0) - return i; - return UDEV_BUILTIN_MAX; -} - -int udev_builtin_run(struct udev_device *dev, enum udev_builtin_cmd cmd, const char *command, bool test) -{ - char arg[UTIL_PATH_SIZE]; - int argc; - char *argv[128]; - - optind = 0; - util_strscpy(arg, sizeof(arg), command); - udev_build_argv(udev_device_get_udev(dev), arg, &argc, argv); - return builtins[cmd]->cmd(dev, argc, argv, test); -} - -int udev_builtin_add_property(struct udev_device *dev, bool test, const char *key, const char *val) -{ - struct udev_list_entry *entry; - - entry = udev_device_add_property(dev, key, val); - /* store in db, skip private keys */ - if (key[0] != '.') - udev_list_entry_set_num(entry, true); - - info(udev_device_get_udev(dev), "%s=%s\n", key, val); - if (test) - printf("%s=%s\n", key, val); - return 0; -} diff --git a/src/udev/src/udev-control.socket b/src/udev/src/udev-control.socket deleted file mode 100644 index f80f77442..000000000 --- a/src/udev/src/udev-control.socket +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=udev Control Socket -DefaultDependencies=no -ConditionCapability=CAP_MKNOD - -[Socket] -Service=udev.service -ListenSequentialPacket=/run/udev/control -SocketMode=0600 -PassCredentials=yes diff --git a/src/udev/src/udev-ctrl.c b/src/udev/src/udev-ctrl.c deleted file mode 100644 index 5556f1a77..000000000 --- a/src/udev/src/udev-ctrl.c +++ /dev/null @@ -1,494 +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 <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/poll.h> -#include <sys/socket.h> -#include <sys/un.h> - -#include "udev.h" - -/* wire protocol magic must match */ -#define UDEV_CTRL_MAGIC 0xdead1dea - -enum udev_ctrl_msg_type { - UDEV_CTRL_UNKNOWN, - UDEV_CTRL_SET_LOG_LEVEL, - UDEV_CTRL_STOP_EXEC_QUEUE, - UDEV_CTRL_START_EXEC_QUEUE, - UDEV_CTRL_RELOAD, - UDEV_CTRL_SET_ENV, - UDEV_CTRL_SET_CHILDREN_MAX, - UDEV_CTRL_PING, - UDEV_CTRL_EXIT, -}; - -struct udev_ctrl_msg_wire { - char version[16]; - unsigned int magic; - enum udev_ctrl_msg_type type; - union { - int intval; - char buf[256]; - }; -}; - -struct udev_ctrl_msg { - int refcount; - struct udev_ctrl_connection *conn; - struct udev_ctrl_msg_wire ctrl_msg_wire; -}; - -struct udev_ctrl { - int refcount; - struct udev *udev; - int sock; - struct sockaddr_un saddr; - socklen_t addrlen; - bool bound; - bool cleanup_socket; - bool connected; -}; - -struct udev_ctrl_connection { - int refcount; - struct udev_ctrl *uctrl; - int sock; -}; - -struct udev_ctrl *udev_ctrl_new_from_fd(struct udev *udev, int fd) -{ - struct udev_ctrl *uctrl; - - uctrl = calloc(1, sizeof(struct udev_ctrl)); - if (uctrl == NULL) - return NULL; - uctrl->refcount = 1; - uctrl->udev = udev; - - if (fd < 0) { - uctrl->sock = socket(AF_LOCAL, SOCK_SEQPACKET|SOCK_NONBLOCK|SOCK_CLOEXEC, 0); - if (uctrl->sock < 0) { - err(udev, "error getting socket: %m\n"); - udev_ctrl_unref(uctrl); - return NULL; - } - } else { - uctrl->bound = true; - uctrl->sock = fd; - } - - uctrl->saddr.sun_family = AF_LOCAL; - util_strscpyl(uctrl->saddr.sun_path, sizeof(uctrl->saddr.sun_path), - udev_get_run_path(udev), "/control", NULL); - uctrl->addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(uctrl->saddr.sun_path); - return uctrl; -} - -struct udev_ctrl *udev_ctrl_new(struct udev *udev) -{ - return udev_ctrl_new_from_fd(udev, -1); -} - -int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl) -{ - int err; - - if (!uctrl->bound) { - err = bind(uctrl->sock, (struct sockaddr *)&uctrl->saddr, uctrl->addrlen); - if (err < 0 && errno == EADDRINUSE) { - unlink(uctrl->saddr.sun_path); - err = bind(uctrl->sock, (struct sockaddr *)&uctrl->saddr, uctrl->addrlen); - } - - if (err < 0) { - err = -errno; - err(uctrl->udev, "bind failed: %m\n"); - return err; - } - - err = listen(uctrl->sock, 0); - if (err < 0) { - err = -errno; - err(uctrl->udev, "listen failed: %m\n"); - return err; - } - - uctrl->bound = true; - uctrl->cleanup_socket = true; - } - return 0; -} - -struct udev *udev_ctrl_get_udev(struct udev_ctrl *uctrl) -{ - return uctrl->udev; -} - -struct udev_ctrl *udev_ctrl_ref(struct udev_ctrl *uctrl) -{ - if (uctrl == NULL) - return NULL; - uctrl->refcount++; - return uctrl; -} - -struct udev_ctrl *udev_ctrl_unref(struct udev_ctrl *uctrl) -{ - if (uctrl == NULL) - return NULL; - uctrl->refcount--; - if (uctrl->refcount > 0) - return uctrl; - if (uctrl->sock >= 0) - close(uctrl->sock); - free(uctrl); - return NULL; -} - -int udev_ctrl_cleanup(struct udev_ctrl *uctrl) -{ - if (uctrl == NULL) - return 0; - if (uctrl->cleanup_socket) - unlink(uctrl->saddr.sun_path); - return 0; -} - -int udev_ctrl_get_fd(struct udev_ctrl *uctrl) -{ - if (uctrl == NULL) - return -EINVAL; - return uctrl->sock; -} - -struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl) -{ - struct udev_ctrl_connection *conn; - struct ucred ucred; - socklen_t slen; - const int on = 1; - - conn = calloc(1, sizeof(struct udev_ctrl_connection)); - if (conn == NULL) - return NULL; - conn->refcount = 1; - conn->uctrl = uctrl; - - conn->sock = accept4(uctrl->sock, NULL, NULL, SOCK_CLOEXEC|SOCK_NONBLOCK); - if (conn->sock < 0) { - if (errno != EINTR) - err(uctrl->udev, "unable to receive ctrl connection: %m\n"); - goto err; - } - - /* check peer credential of connection */ - slen = sizeof(ucred); - if (getsockopt(conn->sock, SOL_SOCKET, SO_PEERCRED, &ucred, &slen) < 0) { - err(uctrl->udev, "unable to receive credentials of ctrl connection: %m\n"); - goto err; - } - if (ucred.uid > 0) { - err(uctrl->udev, "sender uid=%i, message ignored\n", ucred.uid); - goto err; - } - - /* enable receiving of the sender credentials in the messages */ - setsockopt(conn->sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); - udev_ctrl_ref(uctrl); - return conn; -err: - if (conn->sock >= 0) - close(conn->sock); - free(conn); - return NULL; -} - -struct udev_ctrl_connection *udev_ctrl_connection_ref(struct udev_ctrl_connection *conn) -{ - if (conn == NULL) - return NULL; - conn->refcount++; - return conn; -} - -struct udev_ctrl_connection *udev_ctrl_connection_unref(struct udev_ctrl_connection *conn) -{ - if (conn == NULL) - return NULL; - conn->refcount--; - if (conn->refcount > 0) - return conn; - if (conn->sock >= 0) - close(conn->sock); - udev_ctrl_unref(conn->uctrl); - free(conn); - return NULL; -} - -static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int intval, const char *buf, int timeout) -{ - struct udev_ctrl_msg_wire ctrl_msg_wire; - int err = 0; - - memset(&ctrl_msg_wire, 0x00, sizeof(struct udev_ctrl_msg_wire)); - strcpy(ctrl_msg_wire.version, "udev-" VERSION); - ctrl_msg_wire.magic = UDEV_CTRL_MAGIC; - ctrl_msg_wire.type = type; - - if (buf != NULL) - util_strscpy(ctrl_msg_wire.buf, sizeof(ctrl_msg_wire.buf), buf); - else - ctrl_msg_wire.intval = intval; - - if (!uctrl->connected) { - if (connect(uctrl->sock, (struct sockaddr *)&uctrl->saddr, uctrl->addrlen) < 0) { - err = -errno; - goto out; - } - uctrl->connected = true; - } - if (send(uctrl->sock, &ctrl_msg_wire, sizeof(ctrl_msg_wire), 0) < 0) { - err = -errno; - goto out; - } - - /* wait for peer message handling or disconnect */ - for (;;) { - struct pollfd pfd[1]; - int r; - - pfd[0].fd = uctrl->sock; - pfd[0].events = POLLIN; - r = poll(pfd, 1, timeout * 1000); - if (r < 0) { - if (errno == EINTR) - continue; - err = -errno; - break; - } - - if (r > 0 && pfd[0].revents & POLLERR) { - err = -EIO; - break; - } - - if (r == 0) - err = -ETIMEDOUT; - break; - } -out: - return err; -} - -int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, int timeout) -{ - return ctrl_send(uctrl, UDEV_CTRL_SET_LOG_LEVEL, priority, NULL, timeout); -} - -int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, int timeout) -{ - return ctrl_send(uctrl, UDEV_CTRL_STOP_EXEC_QUEUE, 0, NULL, timeout); -} - -int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, int timeout) -{ - return ctrl_send(uctrl, UDEV_CTRL_START_EXEC_QUEUE, 0, NULL, timeout); -} - -int udev_ctrl_send_reload(struct udev_ctrl *uctrl, int timeout) -{ - return ctrl_send(uctrl, UDEV_CTRL_RELOAD, 0, NULL, timeout); -} - -int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, int timeout) -{ - return ctrl_send(uctrl, UDEV_CTRL_SET_ENV, 0, key, timeout); -} - -int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, int timeout) -{ - return ctrl_send(uctrl, UDEV_CTRL_SET_CHILDREN_MAX, count, NULL, timeout); -} - -int udev_ctrl_send_ping(struct udev_ctrl *uctrl, int timeout) -{ - return ctrl_send(uctrl, UDEV_CTRL_PING, 0, NULL, timeout); -} - -int udev_ctrl_send_exit(struct udev_ctrl *uctrl, int timeout) -{ - return ctrl_send(uctrl, UDEV_CTRL_EXIT, 0, NULL, timeout); -} - -struct udev_ctrl_msg *udev_ctrl_receive_msg(struct udev_ctrl_connection *conn) -{ - struct udev *udev = conn->uctrl->udev; - struct udev_ctrl_msg *uctrl_msg; - ssize_t size; - struct msghdr smsg; - struct cmsghdr *cmsg; - struct iovec iov; - struct ucred *cred; - char cred_msg[CMSG_SPACE(sizeof(struct ucred))]; - - uctrl_msg = calloc(1, sizeof(struct udev_ctrl_msg)); - if (uctrl_msg == NULL) - return NULL; - uctrl_msg->refcount = 1; - uctrl_msg->conn = conn; - udev_ctrl_connection_ref(conn); - - /* wait for the incoming message */ - for(;;) { - struct pollfd pfd[1]; - int r; - - pfd[0].fd = conn->sock; - pfd[0].events = POLLIN; - - r = poll(pfd, 1, 10000); - if (r < 0) { - if (errno == EINTR) - continue; - goto err; - } else if (r == 0) { - err(udev, "timeout waiting for ctrl message\n"); - goto err; - } else { - if (!(pfd[0].revents & POLLIN)) { - err(udev, "ctrl connection error: %m\n"); - goto err; - } - } - - break; - } - - iov.iov_base = &uctrl_msg->ctrl_msg_wire; - iov.iov_len = sizeof(struct udev_ctrl_msg_wire); - 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); - size = recvmsg(conn->sock, &smsg, 0); - if (size < 0) { - err(udev, "unable to receive ctrl message: %m\n"); - goto err; - } - cmsg = CMSG_FIRSTHDR(&smsg); - cred = (struct ucred *) CMSG_DATA(cmsg); - - if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) { - err(udev, "no sender credentials received, message ignored\n"); - goto err; - } - - if (cred->uid != 0) { - err(udev, "sender uid=%i, message ignored\n", cred->uid); - goto err; - } - - if (uctrl_msg->ctrl_msg_wire.magic != UDEV_CTRL_MAGIC) { - err(udev, "message magic 0x%08x doesn't match, ignore it\n", uctrl_msg->ctrl_msg_wire.magic); - goto err; - } - - dbg(udev, "created ctrl_msg %p (%i)\n", uctrl_msg, uctrl_msg->ctrl_msg_wire.type); - return uctrl_msg; -err: - udev_ctrl_msg_unref(uctrl_msg); - return NULL; -} - -struct udev_ctrl_msg *udev_ctrl_msg_ref(struct udev_ctrl_msg *ctrl_msg) -{ - if (ctrl_msg == NULL) - return NULL; - ctrl_msg->refcount++; - return ctrl_msg; -} - -struct udev_ctrl_msg *udev_ctrl_msg_unref(struct udev_ctrl_msg *ctrl_msg) -{ - if (ctrl_msg == NULL) - return NULL; - ctrl_msg->refcount--; - if (ctrl_msg->refcount > 0) - return ctrl_msg; - dbg(ctrl_msg->conn->uctrl->udev, "release ctrl_msg %p\n", ctrl_msg); - udev_ctrl_connection_unref(ctrl_msg->conn); - free(ctrl_msg); - return NULL; -} - -int udev_ctrl_get_set_log_level(struct udev_ctrl_msg *ctrl_msg) -{ - if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SET_LOG_LEVEL) - return ctrl_msg->ctrl_msg_wire.intval; - return -1; -} - -int udev_ctrl_get_stop_exec_queue(struct udev_ctrl_msg *ctrl_msg) -{ - if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_STOP_EXEC_QUEUE) - return 1; - return -1; -} - -int udev_ctrl_get_start_exec_queue(struct udev_ctrl_msg *ctrl_msg) -{ - if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_START_EXEC_QUEUE) - return 1; - return -1; -} - -int udev_ctrl_get_reload(struct udev_ctrl_msg *ctrl_msg) -{ - if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_RELOAD) - return 1; - return -1; -} - -const char *udev_ctrl_get_set_env(struct udev_ctrl_msg *ctrl_msg) -{ - if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SET_ENV) - return ctrl_msg->ctrl_msg_wire.buf; - return NULL; -} - -int udev_ctrl_get_set_children_max(struct udev_ctrl_msg *ctrl_msg) -{ - if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SET_CHILDREN_MAX) - return ctrl_msg->ctrl_msg_wire.intval; - return -1; -} - -int udev_ctrl_get_ping(struct udev_ctrl_msg *ctrl_msg) -{ - if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_PING) - return 1; - return -1; -} - -int udev_ctrl_get_exit(struct udev_ctrl_msg *ctrl_msg) -{ - if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_EXIT) - return 1; - return -1; -} diff --git a/src/udev/src/udev-event.c b/src/udev/src/udev-event.c deleted file mode 100644 index 45dd77ba2..000000000 --- a/src/udev/src/udev-event.c +++ /dev/null @@ -1,1011 +0,0 @@ -/* - * Copyright (C) 2003-2010 Kay Sievers <kay.sievers@vrfy.org> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <stddef.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <ctype.h> -#include <string.h> -#include <time.h> -#include <net/if.h> -#include <sys/ioctl.h> -#include <sys/prctl.h> -#include <sys/poll.h> -#include <sys/epoll.h> -#include <sys/wait.h> -#include <sys/socket.h> -#include <sys/signalfd.h> -#include <linux/sockios.h> - -#include "udev.h" - -struct udev_event *udev_event_new(struct udev_device *dev) -{ - struct udev *udev = udev_device_get_udev(dev); - struct udev_event *event; - - event = calloc(1, sizeof(struct udev_event)); - if (event == NULL) - return NULL; - event->dev = dev; - event->udev = udev; - udev_list_init(udev, &event->run_list, false); - event->fd_signal = -1; - event->birth_usec = now_usec(); - event->timeout_usec = 30 * 1000 * 1000; - dbg(event->udev, "allocated event %p\n", event); - return event; -} - -void udev_event_unref(struct udev_event *event) -{ - if (event == NULL) - return; - udev_list_cleanup(&event->run_list); - free(event->program_result); - free(event->name); - dbg(event->udev, "free event %p\n", event); - free(event); -} - -size_t udev_event_apply_format(struct udev_event *event, const char *src, char *dest, size_t size) -{ - struct udev_device *dev = event->dev; - enum subst_type { - SUBST_UNKNOWN, - SUBST_DEVNODE, - SUBST_ATTR, - SUBST_ENV, - SUBST_KERNEL, - SUBST_KERNEL_NUMBER, - SUBST_DRIVER, - SUBST_DEVPATH, - SUBST_ID, - SUBST_MAJOR, - SUBST_MINOR, - SUBST_RESULT, - SUBST_PARENT, - SUBST_NAME, - SUBST_LINKS, - SUBST_ROOT, - SUBST_SYS, - }; - static const struct subst_map { - char *name; - char fmt; - enum subst_type type; - } map[] = { - { .name = "devnode", .fmt = 'N', .type = SUBST_DEVNODE }, - { .name = "tempnode", .fmt = 'N', .type = SUBST_DEVNODE }, - { .name = "attr", .fmt = 's', .type = SUBST_ATTR }, - { .name = "sysfs", .fmt = 's', .type = SUBST_ATTR }, - { .name = "env", .fmt = 'E', .type = SUBST_ENV }, - { .name = "kernel", .fmt = 'k', .type = SUBST_KERNEL }, - { .name = "number", .fmt = 'n', .type = SUBST_KERNEL_NUMBER }, - { .name = "driver", .fmt = 'd', .type = SUBST_DRIVER }, - { .name = "devpath", .fmt = 'p', .type = SUBST_DEVPATH }, - { .name = "id", .fmt = 'b', .type = SUBST_ID }, - { .name = "major", .fmt = 'M', .type = SUBST_MAJOR }, - { .name = "minor", .fmt = 'm', .type = SUBST_MINOR }, - { .name = "result", .fmt = 'c', .type = SUBST_RESULT }, - { .name = "parent", .fmt = 'P', .type = SUBST_PARENT }, - { .name = "name", .fmt = 'D', .type = SUBST_NAME }, - { .name = "links", .fmt = 'L', .type = SUBST_LINKS }, - { .name = "root", .fmt = 'r', .type = SUBST_ROOT }, - { .name = "sys", .fmt = 'S', .type = SUBST_SYS }, - }; - const char *from; - char *s; - size_t l; - - from = src; - s = dest; - l = size; - - for (;;) { - enum subst_type type = SUBST_UNKNOWN; - char attrbuf[UTIL_PATH_SIZE]; - char *attr = NULL; - - while (from[0] != '\0') { - if (from[0] == '$') { - /* substitute named variable */ - unsigned int i; - - if (from[1] == '$') { - from++; - goto copy; - } - - for (i = 0; i < ARRAY_SIZE(map); i++) { - if (strncmp(&from[1], map[i].name, strlen(map[i].name)) == 0) { - type = map[i].type; - from += strlen(map[i].name)+1; - dbg(event->udev, "will substitute format name '%s'\n", map[i].name); - goto subst; - } - } - } else if (from[0] == '%') { - /* substitute format char */ - unsigned int i; - - if (from[1] == '%') { - from++; - goto copy; - } - - for (i = 0; i < ARRAY_SIZE(map); i++) { - if (from[1] == map[i].fmt) { - type = map[i].type; - from += 2; - dbg(event->udev, "will substitute format char '%c'\n", map[i].fmt); - goto subst; - } - } - } -copy: - /* copy char */ - if (l == 0) - goto out; - s[0] = from[0]; - from++; - s++; - l--; - } - - goto out; -subst: - /* extract possible $format{attr} */ - if (from[0] == '{') { - unsigned int i; - - from++; - for (i = 0; from[i] != '}'; i++) { - if (from[i] == '\0') { - err(event->udev, "missing closing brace for format '%s'\n", src); - goto out; - } - } - if (i >= sizeof(attrbuf)) - goto out; - memcpy(attrbuf, from, i); - attrbuf[i] = '\0'; - from += i+1; - attr = attrbuf; - } else { - attr = NULL; - } - - switch (type) { - case SUBST_DEVPATH: - l = util_strpcpy(&s, l, udev_device_get_devpath(dev)); - dbg(event->udev, "substitute devpath '%s'\n", udev_device_get_devpath(dev)); - break; - case SUBST_KERNEL: - l = util_strpcpy(&s, l, udev_device_get_sysname(dev)); - dbg(event->udev, "substitute kernel name '%s'\n", udev_device_get_sysname(dev)); - break; - case SUBST_KERNEL_NUMBER: - if (udev_device_get_sysnum(dev) == NULL) - break; - l = util_strpcpy(&s, l, udev_device_get_sysnum(dev)); - dbg(event->udev, "substitute kernel number '%s'\n", udev_device_get_sysnum(dev)); - break; - case SUBST_ID: - if (event->dev_parent == NULL) - break; - l = util_strpcpy(&s, l, udev_device_get_sysname(event->dev_parent)); - dbg(event->udev, "substitute id '%s'\n", udev_device_get_sysname(event->dev_parent)); - break; - case SUBST_DRIVER: { - const char *driver; - - if (event->dev_parent == NULL) - break; - - driver = udev_device_get_driver(event->dev_parent); - if (driver == NULL) - break; - l = util_strpcpy(&s, l, driver); - dbg(event->udev, "substitute driver '%s'\n", driver); - break; - } - case SUBST_MAJOR: { - char num[UTIL_PATH_SIZE]; - - sprintf(num, "%d", major(udev_device_get_devnum(dev))); - l = util_strpcpy(&s, l, num); - dbg(event->udev, "substitute major number '%s'\n", num); - break; - } - case SUBST_MINOR: { - char num[UTIL_PATH_SIZE]; - - sprintf(num, "%d", minor(udev_device_get_devnum(dev))); - l = util_strpcpy(&s, l, num); - dbg(event->udev, "substitute minor number '%s'\n", num); - break; - } - case SUBST_RESULT: { - char *rest; - int i; - - if (event->program_result == NULL) - break; - /* get part part of the result string */ - i = 0; - if (attr != NULL) - i = strtoul(attr, &rest, 10); - if (i > 0) { - char result[UTIL_PATH_SIZE]; - char tmp[UTIL_PATH_SIZE]; - char *cpos; - - dbg(event->udev, "request part #%d of result string\n", i); - util_strscpy(result, sizeof(result), event->program_result); - cpos = result; - while (--i) { - while (cpos[0] != '\0' && !isspace(cpos[0])) - cpos++; - while (isspace(cpos[0])) - cpos++; - } - if (i > 0) { - err(event->udev, "requested part of result string not found\n"); - break; - } - util_strscpy(tmp, sizeof(tmp), cpos); - /* %{2+}c copies the whole string from the second part on */ - if (rest[0] != '+') { - cpos = strchr(tmp, ' '); - if (cpos) - cpos[0] = '\0'; - } - l = util_strpcpy(&s, l, tmp); - dbg(event->udev, "substitute part of result string '%s'\n", tmp); - } else { - l = util_strpcpy(&s, l, event->program_result); - dbg(event->udev, "substitute result string '%s'\n", event->program_result); - } - break; - } - case SUBST_ATTR: { - const char *value = NULL; - char vbuf[UTIL_NAME_SIZE]; - size_t len; - int count; - - if (attr == NULL) { - err(event->udev, "missing file parameter for attr\n"); - break; - } - - /* try to read the value specified by "[dmi/id]product_name" */ - if (util_resolve_subsys_kernel(event->udev, attr, vbuf, sizeof(vbuf), 1) == 0) - value = vbuf; - - /* try to read the attribute the device */ - if (value == NULL) - value = udev_device_get_sysattr_value(event->dev, attr); - - /* try to read the attribute of the parent device, other matches have selected */ - if (value == NULL && event->dev_parent != NULL && event->dev_parent != event->dev) - value = udev_device_get_sysattr_value(event->dev_parent, attr); - - if (value == NULL) - break; - - /* strip trailing whitespace, and replace unwanted characters */ - if (value != vbuf) - util_strscpy(vbuf, sizeof(vbuf), value); - len = strlen(vbuf); - while (len > 0 && isspace(vbuf[--len])) - vbuf[len] = '\0'; - count = util_replace_chars(vbuf, UDEV_ALLOWED_CHARS_INPUT); - if (count > 0) - info(event->udev, "%i character(s) replaced\n" , count); - l = util_strpcpy(&s, l, vbuf); - dbg(event->udev, "substitute sysfs value '%s'\n", vbuf); - break; - } - case SUBST_PARENT: { - struct udev_device *dev_parent; - const char *devnode; - - dev_parent = udev_device_get_parent(event->dev); - if (dev_parent == NULL) - break; - devnode = udev_device_get_devnode(dev_parent); - if (devnode != NULL) { - size_t devlen = strlen(udev_get_dev_path(event->udev))+1; - - l = util_strpcpy(&s, l, &devnode[devlen]); - dbg(event->udev, "found parent '%s', got node name '%s'\n", - udev_device_get_syspath(dev_parent), &devnode[devlen]); - } - break; - } - case SUBST_DEVNODE: - if (udev_device_get_devnode(dev) != NULL) - l = util_strpcpy(&s, l, udev_device_get_devnode(dev)); - break; - case SUBST_NAME: { - if (event->name != NULL) { - l = util_strpcpy(&s, l, event->name); - dbg(event->udev, "substitute custom node name '%s'\n", event->name); - } else if (udev_device_get_devnode(dev) != NULL) { - size_t devlen = strlen(udev_get_dev_path(event->udev))+1; - - l = util_strpcpy(&s, l, &udev_device_get_devnode(dev)[devlen]); - dbg(event->udev, "substitute node name'%s'\n", &udev_device_get_devnode(dev)[devlen]); - } else { - l = util_strpcpy(&s, l, udev_device_get_sysname(dev)); - dbg(event->udev, "substitute device name'%s'\n", udev_device_get_sysname(dev)); - } - break; - } - case SUBST_LINKS: { - size_t devlen = strlen(udev_get_dev_path(event->udev))+1; - struct udev_list_entry *list_entry; - - list_entry = udev_device_get_devlinks_list_entry(dev); - if (list_entry == NULL) - break; - l = util_strpcpy(&s, l, &udev_list_entry_get_name(list_entry)[devlen]); - 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)[devlen], NULL); - break; - } - case SUBST_ROOT: - l = util_strpcpy(&s, l, udev_get_dev_path(event->udev)); - dbg(event->udev, "substitute udev_root '%s'\n", udev_get_dev_path(event->udev)); - break; - case SUBST_SYS: - l = util_strpcpy(&s, l, udev_get_sys_path(event->udev)); - dbg(event->udev, "substitute sys_path '%s'\n", udev_get_sys_path(event->udev)); - break; - case SUBST_ENV: - if (attr == NULL) { - dbg(event->udev, "missing attribute\n"); - break; - } else { - const char *value; - - value = udev_device_get_property_value(event->dev, attr); - if (value == NULL) - break; - dbg(event->udev, "substitute env '%s=%s'\n", attr, value); - l = util_strpcpy(&s, l, value); - break; - } - default: - err(event->udev, "unknown substitution type=%i\n", type); - break; - } - } - -out: - s[0] = '\0'; - dbg(event->udev, "'%s' -> '%s' (%zu)\n", src, dest, l); - return l; -} - -static int spawn_exec(struct udev_event *event, - const char *cmd, char *const argv[], char **envp, const sigset_t *sigmask, - int fd_stdout, int fd_stderr) -{ - struct udev *udev = event->udev; - int err; - int fd; - - /* discard child output or connect to pipe */ - fd = open("/dev/null", O_RDWR); - if (fd >= 0) { - dup2(fd, STDIN_FILENO); - if (fd_stdout < 0) - dup2(fd, STDOUT_FILENO); - if (fd_stderr < 0) - dup2(fd, STDERR_FILENO); - close(fd); - } else { - err(udev, "open /dev/null failed: %m\n"); - } - - /* connect pipes to std{out,err} */ - if (fd_stdout >= 0) { - dup2(fd_stdout, STDOUT_FILENO); - close(fd_stdout); - } - if (fd_stderr >= 0) { - dup2(fd_stderr, STDERR_FILENO); - close(fd_stderr); - } - - /* terminate child in case parent goes away */ - prctl(PR_SET_PDEATHSIG, SIGTERM); - - /* restore original udev sigmask before exec */ - if (sigmask) - sigprocmask(SIG_SETMASK, sigmask, NULL); - - execve(argv[0], argv, envp); - - /* exec failed */ - err = -errno; - err(udev, "failed to execute '%s' '%s': %m\n", argv[0], cmd); - return err; -} - -static void spawn_read(struct udev_event *event, - const char *cmd, - int fd_stdout, int fd_stderr, - char *result, size_t ressize) -{ - struct udev *udev = event->udev; - size_t respos = 0; - int fd_ep = -1; - struct epoll_event ep_outpipe, ep_errpipe; - - /* read from child if requested */ - if (fd_stdout < 0 && fd_stderr < 0) - return; - - fd_ep = epoll_create1(EPOLL_CLOEXEC); - if (fd_ep < 0) { - err(udev, "error creating epoll fd: %m\n"); - goto out; - } - - if (fd_stdout >= 0) { - memset(&ep_outpipe, 0, sizeof(struct epoll_event)); - ep_outpipe.events = EPOLLIN; - ep_outpipe.data.ptr = &fd_stdout; - if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_stdout, &ep_outpipe) < 0) { - err(udev, "fail to add fd to epoll: %m\n"); - goto out; - } - } - - if (fd_stderr >= 0) { - memset(&ep_errpipe, 0, sizeof(struct epoll_event)); - ep_errpipe.events = EPOLLIN; - ep_errpipe.data.ptr = &fd_stderr; - if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_stderr, &ep_errpipe) < 0) { - err(udev, "fail to add fd to epoll: %m\n"); - goto out; - } - } - - /* read child output */ - while (fd_stdout >= 0 || fd_stderr >= 0) { - int timeout; - int fdcount; - struct epoll_event ev[4]; - int i; - - if (event->timeout_usec > 0) { - unsigned long long age_usec; - - age_usec = now_usec() - event->birth_usec; - if (age_usec >= event->timeout_usec) { - err(udev, "timeout '%s'\n", cmd); - goto out; - } - timeout = ((event->timeout_usec - age_usec) / 1000) + 1000; - } else { - timeout = -1; - } - - fdcount = epoll_wait(fd_ep, ev, ARRAY_SIZE(ev), timeout); - if (fdcount < 0) { - if (errno == EINTR) - continue; - err(udev, "failed to poll: %m\n"); - goto out; - } - if (fdcount == 0) { - err(udev, "timeout '%s'\n", cmd); - goto out; - } - - for (i = 0; i < fdcount; i++) { - int *fd = (int *)ev[i].data.ptr; - - if (ev[i].events & EPOLLIN) { - ssize_t count; - char buf[4096]; - - count = read(*fd, buf, sizeof(buf)-1); - if (count <= 0) - continue; - buf[count] = '\0'; - - /* store stdout result */ - if (result != NULL && *fd == fd_stdout) { - if (respos + count < ressize) { - memcpy(&result[respos], buf, count); - respos += count; - } else { - err(udev, "'%s' ressize %zd too short\n", cmd, ressize); - } - } - - /* log debug output only if we watch stderr */ - if (fd_stderr >= 0) { - char *pos; - char *line; - - pos = buf; - while ((line = strsep(&pos, "\n"))) { - if (pos != NULL || line[0] != '\0') - info(udev, "'%s'(%s) '%s'\n", cmd, *fd == fd_stdout ? "out" : "err" , line); - } - } - } else if (ev[i].events & EPOLLHUP) { - if (epoll_ctl(fd_ep, EPOLL_CTL_DEL, *fd, NULL) < 0) { - err(udev, "failed to remove fd from epoll: %m\n"); - goto out; - } - *fd = -1; - } - } - } - - /* return the child's stdout string */ - if (result != NULL) { - result[respos] = '\0'; - dbg(udev, "result='%s'\n", result); - } -out: - if (fd_ep >= 0) - close(fd_ep); -} - -static int spawn_wait(struct udev_event *event, const char *cmd, pid_t pid) -{ - struct udev *udev = event->udev; - struct pollfd pfd[1]; - int err = 0; - - pfd[0].events = POLLIN; - pfd[0].fd = event->fd_signal; - - while (pid > 0) { - int timeout; - int fdcount; - - if (event->timeout_usec > 0) { - unsigned long long age_usec; - - age_usec = now_usec() - event->birth_usec; - if (age_usec >= event->timeout_usec) - timeout = 1000; - else - timeout = ((event->timeout_usec - age_usec) / 1000) + 1000; - } else { - timeout = -1; - } - - fdcount = poll(pfd, 1, timeout); - if (fdcount < 0) { - if (errno == EINTR) - continue; - err = -errno; - err(udev, "failed to poll: %m\n"); - goto out; - } - if (fdcount == 0) { - err(udev, "timeout: killing '%s' [%u]\n", cmd, pid); - kill(pid, SIGKILL); - } - - if (pfd[0].revents & POLLIN) { - struct signalfd_siginfo fdsi; - int status; - ssize_t size; - - size = read(event->fd_signal, &fdsi, sizeof(struct signalfd_siginfo)); - if (size != sizeof(struct signalfd_siginfo)) - continue; - - switch (fdsi.ssi_signo) { - case SIGTERM: - event->sigterm = true; - break; - case SIGCHLD: - if (waitpid(pid, &status, WNOHANG) < 0) - break; - if (WIFEXITED(status)) { - info(udev, "'%s' [%u] exit with return code %i\n", cmd, pid, WEXITSTATUS(status)); - if (WEXITSTATUS(status) != 0) - err = -1; - } else if (WIFSIGNALED(status)) { - err(udev, "'%s' [%u] terminated by signal %i (%s)\n", cmd, pid, WTERMSIG(status), strsignal(WTERMSIG(status))); - err = -1; - } else if (WIFSTOPPED(status)) { - err(udev, "'%s' [%u] stopped\n", cmd, pid); - err = -1; - } else if (WIFCONTINUED(status)) { - err(udev, "'%s' [%u] continued\n", cmd, pid); - err = -1; - } else { - err(udev, "'%s' [%u] exit with status 0x%04x\n", cmd, pid, status); - err = -1; - } - pid = 0; - break; - } - } - } -out: - return err; -} - -int udev_build_argv(struct udev *udev, char *cmd, int *argc, char *argv[]) -{ - int i = 0; - char *pos; - - if (strchr(cmd, ' ') == NULL) { - argv[i++] = cmd; - goto out; - } - - pos = cmd; - while (pos != NULL && pos[0] != '\0') { - if (pos[0] == '\'') { - /* do not separate quotes */ - pos++; - argv[i] = strsep(&pos, "\'"); - if (pos != NULL) - while (pos[0] == ' ') - pos++; - } else { - argv[i] = strsep(&pos, " "); - if (pos != NULL) - while (pos[0] == ' ') - pos++; - } - dbg(udev, "argv[%i] '%s'\n", i, argv[i]); - i++; - } -out: - argv[i] = NULL; - if (argc) - *argc = i; - return 0; -} - -int udev_event_spawn(struct udev_event *event, - const char *cmd, char **envp, const sigset_t *sigmask, - char *result, size_t ressize) -{ - struct udev *udev = event->udev; - int outpipe[2] = {-1, -1}; - int errpipe[2] = {-1, -1}; - pid_t pid; - char arg[UTIL_PATH_SIZE]; - char *argv[128]; - char program[UTIL_PATH_SIZE]; - int err = 0; - - util_strscpy(arg, sizeof(arg), cmd); - udev_build_argv(event->udev, arg, NULL, argv); - - /* pipes from child to parent */ - if (result != NULL || udev_get_log_priority(udev) >= LOG_INFO) { - if (pipe2(outpipe, O_NONBLOCK) != 0) { - err = -errno; - err(udev, "pipe failed: %m\n"); - goto out; - } - } - if (udev_get_log_priority(udev) >= LOG_INFO) { - if (pipe2(errpipe, O_NONBLOCK) != 0) { - err = -errno; - err(udev, "pipe failed: %m\n"); - goto out; - } - } - - /* allow programs in /usr/lib/udev/ to be called without the path */ - if (argv[0][0] != '/') { - util_strscpyl(program, sizeof(program), PKGLIBEXECDIR "/", argv[0], NULL); - argv[0] = program; - } - - pid = fork(); - switch(pid) { - case 0: - /* child closes parent's ends of pipes */ - if (outpipe[READ_END] >= 0) { - close(outpipe[READ_END]); - outpipe[READ_END] = -1; - } - if (errpipe[READ_END] >= 0) { - close(errpipe[READ_END]); - errpipe[READ_END] = -1; - } - - info(udev, "starting '%s'\n", cmd); - - err = spawn_exec(event, cmd, argv, envp, sigmask, - outpipe[WRITE_END], errpipe[WRITE_END]); - - _exit(2 ); - case -1: - err(udev, "fork of '%s' failed: %m\n", cmd); - err = -1; - goto out; - default: - /* parent closed child's ends of pipes */ - if (outpipe[WRITE_END] >= 0) { - close(outpipe[WRITE_END]); - outpipe[WRITE_END] = -1; - } - if (errpipe[WRITE_END] >= 0) { - close(errpipe[WRITE_END]); - errpipe[WRITE_END] = -1; - } - - spawn_read(event, cmd, - outpipe[READ_END], errpipe[READ_END], - result, ressize); - - err = spawn_wait(event, cmd, pid); - } - -out: - if (outpipe[READ_END] >= 0) - close(outpipe[READ_END]); - if (outpipe[WRITE_END] >= 0) - close(outpipe[WRITE_END]); - if (errpipe[READ_END] >= 0) - close(errpipe[READ_END]); - if (errpipe[WRITE_END] >= 0) - close(errpipe[WRITE_END]); - return err; -} - -static void rename_netif_kernel_log(struct ifreq ifr) -{ - int klog; - FILE *f; - - klog = open("/dev/kmsg", O_WRONLY); - if (klog < 0) - return; - - f = fdopen(klog, "w"); - if (f == NULL) { - close(klog); - return; - } - - fprintf(f, "<30>udevd[%u]: renamed network interface %s to %s\n", - getpid(), ifr.ifr_name, ifr.ifr_newname); - fclose(f); -} - -static int rename_netif(struct udev_event *event) -{ - struct udev_device *dev = event->dev; - int sk; - struct ifreq ifr; - int loop; - int err; - - info(event->udev, "changing net interface name from '%s' to '%s'\n", - udev_device_get_sysname(dev), event->name); - - sk = socket(PF_INET, SOCK_DGRAM, 0); - if (sk < 0) { - err = -errno; - err(event->udev, "error opening socket: %m\n"); - return err; - } - - memset(&ifr, 0x00, sizeof(struct ifreq)); - util_strscpy(ifr.ifr_name, IFNAMSIZ, udev_device_get_sysname(dev)); - util_strscpy(ifr.ifr_newname, IFNAMSIZ, event->name); - err = ioctl(sk, SIOCSIFNAME, &ifr); - if (err == 0) { - rename_netif_kernel_log(ifr); - goto out; - } - - /* keep trying if the destination interface name already exists */ - err = -errno; - if (err != -EEXIST) - goto out; - - /* free our own name, another process may wait for us */ - snprintf(ifr.ifr_newname, IFNAMSIZ, "rename%u", udev_device_get_ifindex(dev)); - err = ioctl(sk, SIOCSIFNAME, &ifr); - if (err < 0) { - err = -errno; - goto out; - } - - /* log temporary name */ - rename_netif_kernel_log(ifr); - - /* wait a maximum of 90 seconds for our target to become available */ - util_strscpy(ifr.ifr_name, IFNAMSIZ, ifr.ifr_newname); - util_strscpy(ifr.ifr_newname, IFNAMSIZ, event->name); - loop = 90 * 20; - while (loop--) { - const struct timespec duration = { 0, 1000 * 1000 * 1000 / 20 }; - - dbg(event->udev, "wait for netif '%s' to become free, loop=%i\n", - event->name, (90 * 20) - loop); - nanosleep(&duration, NULL); - - err = ioctl(sk, SIOCSIFNAME, &ifr); - if (err == 0) { - rename_netif_kernel_log(ifr); - break; - } - err = -errno; - if (err != -EEXIST) - break; - } - -out: - if (err < 0) - err(event->udev, "error changing net interface name %s to %s: %m\n", ifr.ifr_name, ifr.ifr_newname); - close(sk); - return err; -} - -int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules, const sigset_t *sigmask) -{ - struct udev_device *dev = event->dev; - int err = 0; - - if (udev_device_get_subsystem(dev) == NULL) - return -1; - - if (strcmp(udev_device_get_action(dev), "remove") == 0) { - udev_device_read_db(dev, NULL); - udev_device_delete_db(dev); - udev_device_tag_index(dev, NULL, false); - - if (major(udev_device_get_devnum(dev)) != 0) - udev_watch_end(event->udev, dev); - - udev_rules_apply_to_event(rules, event, sigmask); - - if (major(udev_device_get_devnum(dev)) != 0) - udev_node_remove(dev); - } else { - event->dev_db = udev_device_new_from_syspath(event->udev, udev_device_get_syspath(dev)); - if (event->dev_db != NULL) { - udev_device_read_db(event->dev_db, NULL); - udev_device_set_info_loaded(event->dev_db); - - /* disable watch during event processing */ - if (major(udev_device_get_devnum(dev)) != 0) - udev_watch_end(event->udev, event->dev_db); - } - - udev_rules_apply_to_event(rules, event, sigmask); - - /* rename a new network interface, if needed */ - if (udev_device_get_ifindex(dev) > 0 && strcmp(udev_device_get_action(dev), "add") == 0 && - event->name != NULL && strcmp(event->name, udev_device_get_sysname(dev)) != 0) { - char syspath[UTIL_PATH_SIZE]; - char *pos; - - err = rename_netif(event); - if (err == 0) { - info(event->udev, "renamed netif to '%s'\n", event->name); - - /* remember old name */ - udev_device_add_property(dev, "INTERFACE_OLD", udev_device_get_sysname(dev)); - - /* now change the devpath, because the kernel device name has changed */ - util_strscpy(syspath, sizeof(syspath), udev_device_get_syspath(dev)); - pos = strrchr(syspath, '/'); - if (pos != NULL) { - pos++; - util_strscpy(pos, sizeof(syspath) - (pos - syspath), event->name); - udev_device_set_syspath(event->dev, syspath); - udev_device_add_property(dev, "INTERFACE", udev_device_get_sysname(dev)); - info(event->udev, "changed devpath to '%s'\n", udev_device_get_devpath(dev)); - } - } - } - - if (major(udev_device_get_devnum(dev)) > 0) { - /* remove/update possible left-over symlinks from old database entry */ - if (event->dev_db != NULL) - udev_node_update_old_links(dev, event->dev_db); - - if (!event->mode_set) { - if (udev_device_get_devnode_mode(dev) > 0) { - /* kernel supplied value */ - event->mode = udev_device_get_devnode_mode(dev); - } else if (event->gid > 0) { - /* default 0660 if a group is assigned */ - event->mode = 0660; - } else { - /* default 0600 */ - event->mode = 0600; - } - } - - udev_node_add(dev, event->mode, event->uid, event->gid); - } - - /* preserve old, or get new initialization timestamp */ - if (event->dev_db != NULL && udev_device_get_usec_initialized(event->dev_db) > 0) - udev_device_set_usec_initialized(event->dev, udev_device_get_usec_initialized(event->dev_db)); - else if (udev_device_get_usec_initialized(event->dev) == 0) - udev_device_set_usec_initialized(event->dev, now_usec()); - - /* (re)write database file */ - udev_device_update_db(dev); - udev_device_tag_index(dev, event->dev_db, true); - udev_device_set_is_initialized(dev); - - udev_device_unref(event->dev_db); - event->dev_db = NULL; - } -out: - return err; -} - -int udev_event_execute_run(struct udev_event *event, const sigset_t *sigmask) -{ - struct udev_list_entry *list_entry; - int err = 0; - - dbg(event->udev, "executing run list\n"); - udev_list_entry_foreach(list_entry, udev_list_get_entry(&event->run_list)) { - const char *cmd = udev_list_entry_get_name(list_entry); - - if (strncmp(cmd, "socket:", strlen("socket:")) == 0) { - struct udev_monitor *monitor; - - monitor = udev_monitor_new_from_socket(event->udev, &cmd[strlen("socket:")]); - if (monitor == NULL) - continue; - udev_monitor_send_device(monitor, NULL, event->dev); - udev_monitor_unref(monitor); - } else { - char program[UTIL_PATH_SIZE]; - char **envp; - - if (event->exec_delay > 0) { - info(event->udev, "delay execution of '%s'\n", program); - sleep(event->exec_delay); - } - - udev_event_apply_format(event, cmd, program, sizeof(program)); - envp = udev_device_get_properties_envp(event->dev); - if (udev_event_spawn(event, program, envp, sigmask, NULL, 0) < 0) { - if (udev_list_entry_get_num(list_entry)) - err = -1; - } - } - } - return err; -} diff --git a/src/udev/src/udev-kernel.socket b/src/udev/src/udev-kernel.socket deleted file mode 100644 index 23fa9d5e1..000000000 --- a/src/udev/src/udev-kernel.socket +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=udev Kernel Socket -DefaultDependencies=no -ConditionCapability=CAP_MKNOD - -[Socket] -Service=udev.service -ReceiveBuffer=134217728 -ListenNetlink=kobject-uevent 1 -PassCredentials=yes diff --git a/src/udev/src/udev-node.c b/src/udev/src/udev-node.c deleted file mode 100644 index 7a01a479e..000000000 --- a/src/udev/src/udev-node.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright (C) 2003-2010 Kay Sievers <kay.sievers@vrfy.org> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <stddef.h> -#include <stdbool.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> -#include <grp.h> -#include <dirent.h> -#include <sys/time.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include "udev.h" - -#define TMP_FILE_EXT ".udev-tmp" - -static int node_symlink(struct udev *udev, const char *node, const char *slink) -{ - struct stat stats; - char target[UTIL_PATH_SIZE]; - char *s; - size_t l; - char slink_tmp[UTIL_PATH_SIZE + sizeof(TMP_FILE_EXT)]; - int i = 0; - int tail = 0; - int err = 0; - - /* use relative link */ - target[0] = '\0'; - while (node[i] && (node[i] == slink[i])) { - if (node[i] == '/') - tail = i+1; - i++; - } - s = target; - l = sizeof(target); - while (slink[i] != '\0') { - if (slink[i] == '/') - l = util_strpcpy(&s, l, "../"); - i++; - } - l = util_strscpy(s, l, &node[tail]); - if (l == 0) { - err = -EINVAL; - goto exit; - } - - /* preserve link with correct target, do not replace node of other device */ - if (lstat(slink, &stats) == 0) { - if (S_ISBLK(stats.st_mode) || S_ISCHR(stats.st_mode)) { - struct stat stats2; - - info(udev, "found existing node instead of symlink '%s'\n", slink); - if (lstat(node, &stats2) == 0) { - if ((stats.st_mode & S_IFMT) == (stats2.st_mode & S_IFMT) && - stats.st_rdev == stats2.st_rdev && stats.st_ino != stats2.st_ino) { - info(udev, "replace device node '%s' with symlink to our node '%s'\n", - slink, node); - } else { - err(udev, "device node '%s' already exists, " - "link to '%s' will not overwrite it\n", - slink, node); - goto exit; - } - } - } else if (S_ISLNK(stats.st_mode)) { - char buf[UTIL_PATH_SIZE]; - int len; - - dbg(udev, "found existing symlink '%s'\n", slink); - len = readlink(slink, buf, sizeof(buf)); - if (len > 0 && len < (int)sizeof(buf)) { - buf[len] = '\0'; - if (strcmp(target, buf) == 0) { - info(udev, "preserve already existing symlink '%s' to '%s'\n", - slink, target); - udev_selinux_lsetfilecon(udev, slink, S_IFLNK); - utimensat(AT_FDCWD, slink, NULL, AT_SYMLINK_NOFOLLOW); - goto exit; - } - } - } - } else { - info(udev, "creating symlink '%s' to '%s'\n", slink, target); - do { - err = util_create_path_selinux(udev, slink); - if (err != 0 && err != -ENOENT) - break; - udev_selinux_setfscreatecon(udev, slink, S_IFLNK); - err = symlink(target, slink); - if (err != 0) - err = -errno; - udev_selinux_resetfscreatecon(udev); - } while (err == -ENOENT); - if (err == 0) - goto exit; - } - - info(udev, "atomically replace '%s'\n", slink); - util_strscpyl(slink_tmp, sizeof(slink_tmp), slink, TMP_FILE_EXT, NULL); - unlink(slink_tmp); - do { - err = util_create_path_selinux(udev, slink_tmp); - if (err != 0 && err != -ENOENT) - break; - udev_selinux_setfscreatecon(udev, slink_tmp, S_IFLNK); - err = symlink(target, slink_tmp); - if (err != 0) - err = -errno; - udev_selinux_resetfscreatecon(udev); - } while (err == -ENOENT); - if (err != 0) { - err(udev, "symlink '%s' '%s' failed: %m\n", target, slink_tmp); - goto exit; - } - err = rename(slink_tmp, slink); - if (err != 0) { - err(udev, "rename '%s' '%s' failed: %m\n", slink_tmp, slink); - unlink(slink_tmp); - } -exit: - return err; -} - -/* find device node of device with highest priority */ -static const char *link_find_prioritized(struct udev_device *dev, bool add, const char *stackdir, char *buf, size_t bufsize) -{ - struct udev *udev = udev_device_get_udev(dev); - DIR *dir; - int priority = 0; - const char *target = NULL; - - if (add) { - priority = udev_device_get_devlink_priority(dev); - util_strscpy(buf, bufsize, udev_device_get_devnode(dev)); - target = buf; - } - - dir = opendir(stackdir); - if (dir == NULL) - return target; - for (;;) { - struct udev_device *dev_db; - struct dirent *dent; - - dent = readdir(dir); - if (dent == NULL || dent->d_name[0] == '\0') - break; - if (dent->d_name[0] == '.') - continue; - - info(udev, "found '%s' claiming '%s'\n", dent->d_name, stackdir); - - /* did we find ourself? */ - if (strcmp(dent->d_name, udev_device_get_id_filename(dev)) == 0) - continue; - - dev_db = udev_device_new_from_id_filename(udev, dent->d_name); - if (dev_db != NULL) { - const char *devnode; - - devnode = udev_device_get_devnode(dev_db); - if (devnode != NULL) { - dbg(udev, "compare priority of '%s'(%i) > '%s'(%i)\n", target, priority, - udev_device_get_devnode(dev_db), udev_device_get_devlink_priority(dev_db)); - if (target == NULL || udev_device_get_devlink_priority(dev_db) > priority) { - info(udev, "'%s' claims priority %i for '%s'\n", - udev_device_get_syspath(dev_db), udev_device_get_devlink_priority(dev_db), stackdir); - priority = udev_device_get_devlink_priority(dev_db); - util_strscpy(buf, bufsize, devnode); - target = buf; - } - } - udev_device_unref(dev_db); - } - } - closedir(dir); - return target; -} - -/* manage "stack of names" with possibly specified device priorities */ -static void link_update(struct udev_device *dev, const char *slink, bool add) -{ - struct udev *udev = udev_device_get_udev(dev); - char name_enc[UTIL_PATH_SIZE]; - char filename[UTIL_PATH_SIZE * 2]; - char dirname[UTIL_PATH_SIZE]; - const char *target; - char buf[UTIL_PATH_SIZE]; - - dbg(udev, "update symlink '%s' of '%s'\n", slink, udev_device_get_syspath(dev)); - - util_path_encode(&slink[strlen(udev_get_dev_path(udev))+1], name_enc, sizeof(name_enc)); - util_strscpyl(dirname, sizeof(dirname), udev_get_run_path(udev), "/links/", name_enc, NULL); - util_strscpyl(filename, sizeof(filename), dirname, "/", udev_device_get_id_filename(dev), NULL); - - if (!add) { - dbg(udev, "removing index: '%s'\n", filename); - if (unlink(filename) == 0) - rmdir(dirname); - } - - target = link_find_prioritized(dev, add, dirname, buf, sizeof(buf)); - if (target == NULL) { - info(udev, "no reference left, remove '%s'\n", slink); - if (unlink(slink) == 0) - util_delete_path(udev, slink); - } else { - info(udev, "creating link '%s' to '%s'\n", slink, target); - node_symlink(udev, target, slink); - } - - if (add) { - int err; - - dbg(udev, "creating index: '%s'\n", filename); - do { - int fd; - - err = util_create_path(udev, filename); - if (err != 0 && err != -ENOENT) - break; - fd = open(filename, O_WRONLY|O_CREAT|O_CLOEXEC|O_TRUNC|O_NOFOLLOW, 0444); - if (fd >= 0) - close(fd); - else - err = -errno; - } while (err == -ENOENT); - } -} - -void udev_node_update_old_links(struct udev_device *dev, struct udev_device *dev_old) -{ - struct udev *udev = udev_device_get_udev(dev); - struct udev_list_entry *list_entry; - - /* update possible left-over symlinks */ - udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev_old)) { - const char *name = udev_list_entry_get_name(list_entry); - struct udev_list_entry *list_entry_current; - int found; - - /* check if old link name still belongs to this device */ - found = 0; - udev_list_entry_foreach(list_entry_current, udev_device_get_devlinks_list_entry(dev)) { - const char *name_current = udev_list_entry_get_name(list_entry_current); - - if (strcmp(name, name_current) == 0) { - found = 1; - break; - } - } - if (found) - continue; - - info(udev, "update old name, '%s' no longer belonging to '%s'\n", - name, udev_device_get_devpath(dev)); - link_update(dev, name, 0); - } -} - -static int node_fixup(struct udev_device *dev, mode_t mode, uid_t uid, gid_t gid) -{ - struct udev *udev = udev_device_get_udev(dev); - const char *devnode = udev_device_get_devnode(dev); - dev_t devnum = udev_device_get_devnum(dev); - struct stat stats; - int err = 0; - - if (strcmp(udev_device_get_subsystem(dev), "block") == 0) - mode |= S_IFBLK; - else - mode |= S_IFCHR; - - if (lstat(devnode, &stats) != 0) { - err = -errno; - info(udev, "can not stat() node '%s' (%m)\n", devnode); - goto out; - } - - if (((stats.st_mode & S_IFMT) != (mode & S_IFMT)) || (stats.st_rdev != devnum)) { - err = -EEXIST; - info(udev, "found node '%s' with non-matching devnum %s, skip handling\n", - udev_device_get_devnode(dev), udev_device_get_id_filename(dev)); - goto out; - } - - if ((stats.st_mode & 0777) != (mode & 0777) || stats.st_uid != uid || stats.st_gid != gid) { - info(udev, "set permissions %s, %#o, uid=%u, gid=%u\n", devnode, mode, uid, gid); - chmod(devnode, mode); - chown(devnode, uid, gid); - } else { - info(udev, "preserve permissions %s, %#o, uid=%u, gid=%u\n", devnode, mode, uid, gid); - } - - /* - * Set initial selinux file context only on add events. - * We set the proper context on bootup (triger) or for newly - * added devices, but we don't change it later, in case - * something else has set a custom context in the meantime. - */ - if (strcmp(udev_device_get_action(dev), "add") == 0) - udev_selinux_lsetfilecon(udev, devnode, mode); - - /* always update timestamp when we re-use the node, like on media change events */ - utimensat(AT_FDCWD, devnode, NULL, 0); -out: - return err; -} - -void udev_node_add(struct udev_device *dev, mode_t mode, uid_t uid, gid_t gid) -{ - struct udev *udev = udev_device_get_udev(dev); - char filename[UTIL_PATH_SIZE]; - struct udev_list_entry *list_entry; - int err = 0; - - info(udev, "handling device node '%s', devnum=%s, mode=%#o, uid=%d, gid=%d\n", - udev_device_get_devnode(dev), udev_device_get_id_filename(dev), mode, uid, gid); - - if (node_fixup(dev, mode, uid, gid) < 0) - return; - - /* always add /dev/{block,char}/$major:$minor */ - snprintf(filename, sizeof(filename), "%s/%s/%u:%u", - udev_get_dev_path(udev), - strcmp(udev_device_get_subsystem(dev), "block") == 0 ? "block" : "char", - major(udev_device_get_devnum(dev)), minor(udev_device_get_devnum(dev))); - node_symlink(udev, udev_device_get_devnode(dev), filename); - - /* create/update symlinks, add symlinks to name index */ - udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) { - if (udev_list_entry_get_num(list_entry)) - /* simple unmanaged link name */ - node_symlink(udev, udev_device_get_devnode(dev), udev_list_entry_get_name(list_entry)); - else - link_update(dev, udev_list_entry_get_name(list_entry), 1); - } -} - -void udev_node_remove(struct udev_device *dev) -{ - struct udev *udev = udev_device_get_udev(dev); - struct udev_list_entry *list_entry; - const char *devnode; - struct stat stats; - struct udev_device *dev_check; - char filename[UTIL_PATH_SIZE]; - - /* remove/update symlinks, remove symlinks from name index */ - udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) - link_update(dev, udev_list_entry_get_name(list_entry), 0); - - /* remove /dev/{block,char}/$major:$minor */ - snprintf(filename, sizeof(filename), "%s/%s/%u:%u", - udev_get_dev_path(udev), - strcmp(udev_device_get_subsystem(dev), "block") == 0 ? "block" : "char", - major(udev_device_get_devnum(dev)), minor(udev_device_get_devnum(dev))); - unlink(filename); -} diff --git a/src/udev/src/udev-rules.c b/src/udev/src/udev-rules.c deleted file mode 100644 index 8a85eae71..000000000 --- a/src/udev/src/udev-rules.c +++ /dev/null @@ -1,2767 +0,0 @@ -/* - * Copyright (C) 2003-2010 Kay Sievers <kay.sievers@vrfy.org> - * Copyright (C) 2008 Alan Jenkins <alan-jenkins@tuffmail.co.uk> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stddef.h> -#include <limits.h> -#include <stdlib.h> -#include <stdbool.h> -#include <string.h> -#include <stdio.h> -#include <fcntl.h> -#include <ctype.h> -#include <unistd.h> -#include <errno.h> -#include <dirent.h> -#include <fnmatch.h> -#include <time.h> - -#include "udev.h" - -#define PREALLOC_TOKEN 2048 -#define PREALLOC_STRBUF 32 * 1024 -#define PREALLOC_TRIE 256 - -struct uid_gid { - unsigned int name_off; - union { - uid_t uid; - gid_t gid; - }; -}; - -struct trie_node { - /* this node's first child */ - unsigned int child_idx; - /* the next child of our parent node's child list */ - unsigned int next_child_idx; - /* this node's last child (shortcut for append) */ - unsigned int last_child_idx; - unsigned int value_off; - unsigned short value_len; - unsigned char key; -}; - -struct udev_rules { - struct udev *udev; - int resolve_names; - - /* every key in the rules file becomes a token */ - struct token *tokens; - unsigned int token_cur; - unsigned int token_max; - - /* all key strings are copied to a single string buffer */ - char *buf; - size_t buf_cur; - size_t buf_max; - unsigned int buf_count; - - /* during rule parsing, strings are indexed to find duplicates */ - struct trie_node *trie_nodes; - unsigned int trie_nodes_cur; - unsigned int trie_nodes_max; - - /* during rule parsing, uid/gid lookup results are cached */ - struct uid_gid *uids; - unsigned int uids_cur; - unsigned int uids_max; - struct uid_gid *gids; - unsigned int gids_cur; - unsigned int gids_max; -}; - -/* KEY=="", KEY!="", KEY+="", KEY="", KEY:="" */ -enum operation_type { - OP_UNSET, - - OP_MATCH, - OP_NOMATCH, - OP_MATCH_MAX, - - OP_ADD, - OP_ASSIGN, - OP_ASSIGN_FINAL, -}; - -enum string_glob_type { - GL_UNSET, - GL_PLAIN, /* no special chars */ - GL_GLOB, /* shell globs ?,*,[] */ - GL_SPLIT, /* multi-value A|B */ - GL_SPLIT_GLOB, /* multi-value with glob A*|B* */ - GL_SOMETHING, /* commonly used "?*" */ -}; - -enum string_subst_type { - SB_UNSET, - SB_NONE, - SB_FORMAT, - SB_SUBSYS, -}; - -/* tokens of a rule are sorted/handled in this order */ -enum token_type { - TK_UNSET, - TK_RULE, - - TK_M_ACTION, /* val */ - TK_M_DEVPATH, /* val */ - TK_M_KERNEL, /* val */ - TK_M_DEVLINK, /* val */ - TK_M_NAME, /* val */ - TK_M_ENV, /* val, attr */ - TK_M_TAG, /* val */ - TK_M_SUBSYSTEM, /* val */ - TK_M_DRIVER, /* val */ - TK_M_WAITFOR, /* val */ - TK_M_ATTR, /* val, attr */ - - TK_M_PARENTS_MIN, - TK_M_KERNELS, /* val */ - TK_M_SUBSYSTEMS, /* val */ - TK_M_DRIVERS, /* val */ - TK_M_ATTRS, /* val, attr */ - TK_M_TAGS, /* val */ - TK_M_PARENTS_MAX, - - TK_M_TEST, /* val, mode_t */ - TK_M_EVENT_TIMEOUT, /* int */ - TK_M_PROGRAM, /* val */ - TK_M_IMPORT_FILE, /* val */ - TK_M_IMPORT_PROG, /* val */ - TK_M_IMPORT_BUILTIN, /* val */ - TK_M_IMPORT_DB, /* val */ - TK_M_IMPORT_CMDLINE, /* val */ - TK_M_IMPORT_PARENT, /* val */ - TK_M_RESULT, /* val */ - TK_M_MAX, - - TK_A_STRING_ESCAPE_NONE, - TK_A_STRING_ESCAPE_REPLACE, - TK_A_DB_PERSIST, - TK_A_INOTIFY_WATCH, /* int */ - TK_A_DEVLINK_PRIO, /* int */ - TK_A_OWNER, /* val */ - TK_A_GROUP, /* val */ - TK_A_MODE, /* val */ - TK_A_OWNER_ID, /* uid_t */ - TK_A_GROUP_ID, /* gid_t */ - TK_A_MODE_ID, /* mode_t */ - TK_A_STATIC_NODE, /* val */ - TK_A_ENV, /* val, attr */ - TK_A_TAG, /* val */ - TK_A_NAME, /* val */ - TK_A_DEVLINK, /* val */ - TK_A_ATTR, /* val, attr */ - TK_A_RUN, /* val, bool */ - TK_A_GOTO, /* size_t */ - - TK_END, -}; - -/* we try to pack stuff in a way that we take only 12 bytes per token */ -struct token { - union { - unsigned char type; /* same in rule and key */ - struct { - enum token_type type:8; - bool can_set_name:1; - bool has_static_node:1; - unsigned int unused:6; - unsigned short token_count; - unsigned int label_off; - unsigned short filename_off; - unsigned short filename_line; - } rule; - struct { - enum token_type type:8; - enum operation_type op:8; - enum string_glob_type glob:8; - enum string_subst_type subst:4; - enum string_subst_type attrsubst:4; - unsigned int value_off; - union { - unsigned int attr_off; - int devlink_unique; - unsigned int rule_goto; - mode_t mode; - uid_t uid; - gid_t gid; - int devlink_prio; - int event_timeout; - int watch; - enum udev_builtin_cmd builtin_cmd; - }; - } key; - }; -}; - -#define MAX_TK 64 -struct rule_tmp { - struct udev_rules *rules; - struct token rule; - struct token token[MAX_TK]; - unsigned int token_cur; -}; - -#ifdef ENABLE_DEBUG -static const char *operation_str(enum operation_type type) -{ - static const char *operation_strs[] = { - [OP_UNSET] = "UNSET", - [OP_MATCH] = "match", - [OP_NOMATCH] = "nomatch", - [OP_MATCH_MAX] = "MATCH_MAX", - - [OP_ADD] = "add", - [OP_ASSIGN] = "assign", - [OP_ASSIGN_FINAL] = "assign-final", -} ; - - return operation_strs[type]; -} - -static const char *string_glob_str(enum string_glob_type type) -{ - static const char *string_glob_strs[] = { - [GL_UNSET] = "UNSET", - [GL_PLAIN] = "plain", - [GL_GLOB] = "glob", - [GL_SPLIT] = "split", - [GL_SPLIT_GLOB] = "split-glob", - [GL_SOMETHING] = "split-glob", - }; - - return string_glob_strs[type]; -} - -static const char *token_str(enum token_type type) -{ - static const char *token_strs[] = { - [TK_UNSET] = "UNSET", - [TK_RULE] = "RULE", - - [TK_M_ACTION] = "M ACTION", - [TK_M_DEVPATH] = "M DEVPATH", - [TK_M_KERNEL] = "M KERNEL", - [TK_M_DEVLINK] = "M DEVLINK", - [TK_M_NAME] = "M NAME", - [TK_M_ENV] = "M ENV", - [TK_M_TAG] = "M TAG", - [TK_M_SUBSYSTEM] = "M SUBSYSTEM", - [TK_M_DRIVER] = "M DRIVER", - [TK_M_WAITFOR] = "M WAITFOR", - [TK_M_ATTR] = "M ATTR", - - [TK_M_PARENTS_MIN] = "M PARENTS_MIN", - [TK_M_KERNELS] = "M KERNELS", - [TK_M_SUBSYSTEMS] = "M SUBSYSTEMS", - [TK_M_DRIVERS] = "M DRIVERS", - [TK_M_ATTRS] = "M ATTRS", - [TK_M_TAGS] = "M TAGS", - [TK_M_PARENTS_MAX] = "M PARENTS_MAX", - - [TK_M_TEST] = "M TEST", - [TK_M_EVENT_TIMEOUT] = "M EVENT_TIMEOUT", - [TK_M_PROGRAM] = "M PROGRAM", - [TK_M_IMPORT_FILE] = "M IMPORT_FILE", - [TK_M_IMPORT_PROG] = "M IMPORT_PROG", - [TK_M_IMPORT_BUILTIN] = "M IMPORT_BUILTIN", - [TK_M_IMPORT_DB] = "M IMPORT_DB", - [TK_M_IMPORT_CMDLINE] = "M IMPORT_CMDLINE", - [TK_M_IMPORT_PARENT] = "M IMPORT_PARENT", - [TK_M_RESULT] = "M RESULT", - [TK_M_MAX] = "M MAX", - - [TK_A_STRING_ESCAPE_NONE] = "A STRING_ESCAPE_NONE", - [TK_A_STRING_ESCAPE_REPLACE] = "A STRING_ESCAPE_REPLACE", - [TK_A_DB_PERSIST] = "A DB_PERSIST", - [TK_A_INOTIFY_WATCH] = "A INOTIFY_WATCH", - [TK_A_DEVLINK_PRIO] = "A DEVLINK_PRIO", - [TK_A_OWNER] = "A OWNER", - [TK_A_GROUP] = "A GROUP", - [TK_A_MODE] = "A MODE", - [TK_A_OWNER_ID] = "A OWNER_ID", - [TK_A_GROUP_ID] = "A GROUP_ID", - [TK_A_STATIC_NODE] = "A STATIC_NODE", - [TK_A_MODE_ID] = "A MODE_ID", - [TK_A_ENV] = "A ENV", - [TK_A_TAG] = "A ENV", - [TK_A_NAME] = "A NAME", - [TK_A_DEVLINK] = "A DEVLINK", - [TK_A_ATTR] = "A ATTR", - [TK_A_RUN] = "A RUN", - [TK_A_GOTO] = "A GOTO", - - [TK_END] = "END", - }; - - return token_strs[type]; -} - -static void dump_token(struct udev_rules *rules, struct token *token) -{ - enum token_type type = token->type; - enum operation_type op = token->key.op; - enum string_glob_type glob = token->key.glob; - const char *value = &rules->buf[token->key.value_off]; - const char *attr = &rules->buf[token->key.attr_off]; - - switch (type) { - case TK_RULE: - { - const char *tks_ptr = (char *)rules->tokens; - const char *tk_ptr = (char *)token; - unsigned int idx = (tk_ptr - tks_ptr) / sizeof(struct token); - - dbg(rules->udev, "* RULE %s:%u, token: %u, count: %u, label: '%s'\n", - &rules->buf[token->rule.filename_off], token->rule.filename_line, - idx, token->rule.token_count, - &rules->buf[token->rule.label_off]); - break; - } - case TK_M_ACTION: - case TK_M_DEVPATH: - case TK_M_KERNEL: - case TK_M_SUBSYSTEM: - case TK_M_DRIVER: - case TK_M_WAITFOR: - case TK_M_DEVLINK: - case TK_M_NAME: - case TK_M_KERNELS: - case TK_M_SUBSYSTEMS: - case TK_M_DRIVERS: - case TK_M_TAGS: - case TK_M_PROGRAM: - case TK_M_IMPORT_FILE: - case TK_M_IMPORT_PROG: - case TK_M_IMPORT_DB: - case TK_M_IMPORT_CMDLINE: - case TK_M_IMPORT_PARENT: - case TK_M_RESULT: - case TK_A_NAME: - case TK_A_DEVLINK: - case TK_A_OWNER: - case TK_A_GROUP: - case TK_A_MODE: - case TK_A_RUN: - dbg(rules->udev, "%s %s '%s'(%s)\n", - token_str(type), operation_str(op), value, string_glob_str(glob)); - break; - case TK_M_IMPORT_BUILTIN: - dbg(rules->udev, "%s %i '%s'\n", token_str(type), token->key.builtin_cmd, value); - break; - case TK_M_ATTR: - case TK_M_ATTRS: - case TK_M_ENV: - case TK_A_ATTR: - case TK_A_ENV: - dbg(rules->udev, "%s %s '%s' '%s'(%s)\n", - token_str(type), operation_str(op), attr, value, string_glob_str(glob)); - break; - case TK_M_TAG: - case TK_A_TAG: - dbg(rules->udev, "%s %s '%s'\n", token_str(type), operation_str(op), value); - break; - case TK_A_STRING_ESCAPE_NONE: - case TK_A_STRING_ESCAPE_REPLACE: - case TK_A_DB_PERSIST: - dbg(rules->udev, "%s\n", token_str(type)); - break; - case TK_M_TEST: - dbg(rules->udev, "%s %s '%s'(%s) %#o\n", - token_str(type), operation_str(op), value, string_glob_str(glob), token->key.mode); - break; - case TK_A_INOTIFY_WATCH: - dbg(rules->udev, "%s %u\n", token_str(type), token->key.watch); - break; - case TK_A_DEVLINK_PRIO: - dbg(rules->udev, "%s %u\n", token_str(type), token->key.devlink_prio); - break; - case TK_A_OWNER_ID: - dbg(rules->udev, "%s %s %u\n", token_str(type), operation_str(op), token->key.uid); - break; - case TK_A_GROUP_ID: - dbg(rules->udev, "%s %s %u\n", token_str(type), operation_str(op), token->key.gid); - break; - case TK_A_MODE_ID: - dbg(rules->udev, "%s %s %#o\n", token_str(type), operation_str(op), token->key.mode); - break; - case TK_A_STATIC_NODE: - dbg(rules->udev, "%s '%s'\n", token_str(type), value); - break; - case TK_M_EVENT_TIMEOUT: - dbg(rules->udev, "%s %u\n", token_str(type), token->key.event_timeout); - break; - case TK_A_GOTO: - dbg(rules->udev, "%s '%s' %u\n", token_str(type), value, token->key.rule_goto); - break; - case TK_END: - dbg(rules->udev, "* %s\n", token_str(type)); - break; - case TK_M_PARENTS_MIN: - case TK_M_PARENTS_MAX: - case TK_M_MAX: - case TK_UNSET: - dbg(rules->udev, "unknown type %u\n", type); - break; - } -} - -static void dump_rules(struct udev_rules *rules) -{ - unsigned int i; - - dbg(rules->udev, "dumping %u (%zu bytes) tokens, %u (%zu bytes) strings\n", - rules->token_cur, - rules->token_cur * sizeof(struct token), - rules->buf_count, - rules->buf_cur); - for(i = 0; i < rules->token_cur; i++) - dump_token(rules, &rules->tokens[i]); -} -#else -static inline const char *operation_str(enum operation_type type) { return NULL; } -static inline const char *token_str(enum token_type type) { return NULL; } -static inline void dump_token(struct udev_rules *rules, struct token *token) {} -static inline void dump_rules(struct udev_rules *rules) {} -#endif /* ENABLE_DEBUG */ - -static int add_new_string(struct udev_rules *rules, const char *str, size_t bytes) -{ - int off; - - /* grow buffer if needed */ - if (rules->buf_cur + bytes+1 >= rules->buf_max) { - char *buf; - unsigned int add; - - /* double the buffer size */ - add = rules->buf_max; - if (add < bytes * 8) - add = bytes * 8; - - buf = realloc(rules->buf, rules->buf_max + add); - if (buf == NULL) - return -1; - dbg(rules->udev, "extend buffer from %zu to %zu\n", rules->buf_max, rules->buf_max + add); - rules->buf = buf; - rules->buf_max += add; - } - off = rules->buf_cur; - memcpy(&rules->buf[rules->buf_cur], str, bytes); - rules->buf_cur += bytes; - rules->buf_count++; - return off; -} - -static int add_string(struct udev_rules *rules, const char *str) -{ - unsigned int node_idx; - struct trie_node *new_node; - unsigned int new_node_idx; - unsigned char key; - unsigned short len; - unsigned int depth; - unsigned int off; - struct trie_node *parent; - - /* walk trie, start from last character of str to find matching tails */ - len = strlen(str); - key = str[len-1]; - node_idx = 0; - for (depth = 0; depth <= len; depth++) { - struct trie_node *node; - unsigned int child_idx; - - node = &rules->trie_nodes[node_idx]; - off = node->value_off + node->value_len - len; - - /* match against current node */ - if (depth == len || (node->value_len >= len && memcmp(&rules->buf[off], str, len) == 0)) - return off; - - /* lookup child node */ - key = str[len - 1 - depth]; - child_idx = node->child_idx; - while (child_idx > 0) { - struct trie_node *child; - - child = &rules->trie_nodes[child_idx]; - if (child->key == key) - break; - child_idx = child->next_child_idx; - } - if (child_idx == 0) - break; - node_idx = child_idx; - } - - /* string not found, add it */ - off = add_new_string(rules, str, len + 1); - - /* grow trie nodes if needed */ - if (rules->trie_nodes_cur >= rules->trie_nodes_max) { - struct trie_node *nodes; - unsigned int add; - - /* double the buffer size */ - add = rules->trie_nodes_max; - if (add < 8) - add = 8; - - nodes = realloc(rules->trie_nodes, (rules->trie_nodes_max + add) * sizeof(struct trie_node)); - if (nodes == NULL) - return -1; - dbg(rules->udev, "extend trie nodes from %u to %u\n", - rules->trie_nodes_max, rules->trie_nodes_max + add); - rules->trie_nodes = nodes; - rules->trie_nodes_max += add; - } - - /* get a new node */ - new_node_idx = rules->trie_nodes_cur; - rules->trie_nodes_cur++; - new_node = &rules->trie_nodes[new_node_idx]; - memset(new_node, 0x00, sizeof(struct trie_node)); - new_node->value_off = off; - new_node->value_len = len; - new_node->key = key; - - /* join the parent's child list */ - parent = &rules->trie_nodes[node_idx]; - if (parent->child_idx == 0) { - parent->child_idx = new_node_idx; - } else { - struct trie_node *last_child; - - last_child = &rules->trie_nodes[parent->last_child_idx]; - last_child->next_child_idx = new_node_idx; - } - parent->last_child_idx = new_node_idx; - return off; -} - -static int add_token(struct udev_rules *rules, struct token *token) -{ - /* grow buffer if needed */ - if (rules->token_cur+1 >= rules->token_max) { - struct token *tokens; - unsigned int add; - - /* double the buffer size */ - add = rules->token_max; - if (add < 8) - add = 8; - - tokens = realloc(rules->tokens, (rules->token_max + add ) * sizeof(struct token)); - if (tokens == NULL) - return -1; - dbg(rules->udev, "extend tokens from %u to %u\n", rules->token_max, rules->token_max + add); - rules->tokens = tokens; - rules->token_max += add; - } - memcpy(&rules->tokens[rules->token_cur], token, sizeof(struct token)); - rules->token_cur++; - return 0; -} - -static uid_t add_uid(struct udev_rules *rules, const char *owner) -{ - unsigned int i; - uid_t uid; - unsigned int off; - - /* lookup, if we know it already */ - for (i = 0; i < rules->uids_cur; i++) { - off = rules->uids[i].name_off; - if (strcmp(&rules->buf[off], owner) == 0) { - uid = rules->uids[i].uid; - dbg(rules->udev, "return existing %u for '%s'\n", uid, owner); - return uid; - } - } - uid = util_lookup_user(rules->udev, owner); - - /* grow buffer if needed */ - if (rules->uids_cur+1 >= rules->uids_max) { - struct uid_gid *uids; - unsigned int add; - - /* double the buffer size */ - add = rules->uids_max; - if (add < 1) - add = 8; - - uids = realloc(rules->uids, (rules->uids_max + add ) * sizeof(struct uid_gid)); - if (uids == NULL) - return uid; - dbg(rules->udev, "extend uids from %u to %u\n", rules->uids_max, rules->uids_max + add); - rules->uids = uids; - rules->uids_max += add; - } - rules->uids[rules->uids_cur].uid = uid; - off = add_string(rules, owner); - if (off <= 0) - return uid; - rules->uids[rules->uids_cur].name_off = off; - rules->uids_cur++; - return uid; -} - -static gid_t add_gid(struct udev_rules *rules, const char *group) -{ - unsigned int i; - gid_t gid; - unsigned int off; - - /* lookup, if we know it already */ - for (i = 0; i < rules->gids_cur; i++) { - off = rules->gids[i].name_off; - if (strcmp(&rules->buf[off], group) == 0) { - gid = rules->gids[i].gid; - dbg(rules->udev, "return existing %u for '%s'\n", gid, group); - return gid; - } - } - gid = util_lookup_group(rules->udev, group); - - /* grow buffer if needed */ - if (rules->gids_cur+1 >= rules->gids_max) { - struct uid_gid *gids; - unsigned int add; - - /* double the buffer size */ - add = rules->gids_max; - if (add < 1) - add = 8; - - gids = realloc(rules->gids, (rules->gids_max + add ) * sizeof(struct uid_gid)); - if (gids == NULL) - return gid; - dbg(rules->udev, "extend gids from %u to %u\n", rules->gids_max, rules->gids_max + add); - rules->gids = gids; - rules->gids_max += add; - } - rules->gids[rules->gids_cur].gid = gid; - off = add_string(rules, group); - if (off <= 0) - return gid; - rules->gids[rules->gids_cur].name_off = off; - rules->gids_cur++; - return gid; -} - -static int import_property_from_string(struct udev_device *dev, char *line) -{ - struct udev *udev = udev_device_get_udev(dev); - char *key; - char *val; - size_t len; - - /* find key */ - key = line; - while (isspace(key[0])) - key++; - - /* comment or empty line */ - if (key[0] == '#' || key[0] == '\0') - return -1; - - /* split key/value */ - val = strchr(key, '='); - if (val == NULL) - return -1; - val[0] = '\0'; - val++; - - /* find value */ - while (isspace(val[0])) - val++; - - /* terminate key */ - len = strlen(key); - if (len == 0) - return -1; - while (isspace(key[len-1])) - len--; - key[len] = '\0'; - - /* terminate value */ - len = strlen(val); - if (len == 0) - return -1; - while (isspace(val[len-1])) - len--; - val[len] = '\0'; - - if (len == 0) - return -1; - - /* unquote */ - if (val[0] == '"' || val[0] == '\'') { - if (val[len-1] != val[0]) { - info(udev, "inconsistent quoting: '%s', skip\n", line); - return -1; - } - val[len-1] = '\0'; - val++; - } - - dbg(udev, "adding '%s'='%s'\n", key, val); - - /* handle device, renamed by external tool, returning new path */ - if (strcmp(key, "DEVPATH") == 0) { - char syspath[UTIL_PATH_SIZE]; - - info(udev, "updating devpath from '%s' to '%s'\n", - udev_device_get_devpath(dev), val); - util_strscpyl(syspath, sizeof(syspath), udev_get_sys_path(udev), val, NULL); - udev_device_set_syspath(dev, syspath); - } else { - struct udev_list_entry *entry; - - entry = udev_device_add_property(dev, key, val); - /* store in db, skip private keys */ - if (key[0] != '.') - udev_list_entry_set_num(entry, true); - } - return 0; -} - -static int import_file_into_properties(struct udev_device *dev, const char *filename) -{ - FILE *f; - char line[UTIL_LINE_SIZE]; - - f = fopen(filename, "r"); - if (f == NULL) - return -1; - while (fgets(line, sizeof(line), f) != NULL) - import_property_from_string(dev, line); - fclose(f); - return 0; -} - -static int import_program_into_properties(struct udev_event *event, const char *program, const sigset_t *sigmask) -{ - struct udev_device *dev = event->dev; - char **envp; - char result[UTIL_LINE_SIZE]; - char *line; - int err; - - envp = udev_device_get_properties_envp(dev); - err = udev_event_spawn(event, program, envp, sigmask, result, sizeof(result)); - if (err < 0) - return err; - - line = result; - while (line != NULL) { - char *pos; - - pos = strchr(line, '\n'); - if (pos != NULL) { - pos[0] = '\0'; - pos = &pos[1]; - } - import_property_from_string(dev, line); - line = pos; - } - return 0; -} - -static int import_parent_into_properties(struct udev_device *dev, const char *filter) -{ - struct udev *udev = udev_device_get_udev(dev); - struct udev_device *dev_parent; - struct udev_list_entry *list_entry; - - dev_parent = udev_device_get_parent(dev); - if (dev_parent == NULL) - return -1; - - dbg(udev, "found parent '%s', get the node name\n", udev_device_get_syspath(dev_parent)); - udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(dev_parent)) { - const char *key = udev_list_entry_get_name(list_entry); - const char *val = udev_list_entry_get_value(list_entry); - - if (fnmatch(filter, key, 0) == 0) { - struct udev_list_entry *entry; - - dbg(udev, "import key '%s=%s'\n", key, val); - entry = udev_device_add_property(dev, key, val); - /* store in db, skip private keys */ - if (key[0] != '.') - udev_list_entry_set_num(entry, true); - } - } - return 0; -} - -#define WAIT_LOOP_PER_SECOND 50 -static int wait_for_file(struct udev_device *dev, const char *file, int timeout) -{ - struct udev *udev = udev_device_get_udev(dev); - char filepath[UTIL_PATH_SIZE]; - char devicepath[UTIL_PATH_SIZE]; - struct stat stats; - int loop = timeout * WAIT_LOOP_PER_SECOND; - - /* a relative path is a device attribute */ - devicepath[0] = '\0'; - if (file[0] != '/') { - util_strscpyl(devicepath, sizeof(devicepath), - udev_get_sys_path(udev), udev_device_get_devpath(dev), NULL); - util_strscpyl(filepath, sizeof(filepath), devicepath, "/", file, NULL); - file = filepath; - } - - dbg(udev, "will wait %i sec for '%s'\n", timeout, file); - while (--loop) { - const struct timespec duration = { 0, 1000 * 1000 * 1000 / WAIT_LOOP_PER_SECOND }; - - /* lookup file */ - if (stat(file, &stats) == 0) { - info(udev, "file '%s' appeared after %i loops\n", file, (timeout * WAIT_LOOP_PER_SECOND) - loop-1); - return 0; - } - /* make sure, the device did not disappear in the meantime */ - if (devicepath[0] != '\0' && stat(devicepath, &stats) != 0) { - info(udev, "device disappeared while waiting for '%s'\n", file); - return -2; - } - info(udev, "wait for '%s' for %i mseconds\n", file, 1000 / WAIT_LOOP_PER_SECOND); - nanosleep(&duration, NULL); - } - info(udev, "waiting for '%s' failed\n", file); - return -1; -} - -static int attr_subst_subdir(char *attr, size_t len) -{ - bool found = false; - - if (strstr(attr, "/*/")) { - char *pos; - char dirname[UTIL_PATH_SIZE]; - const char *tail; - DIR *dir; - - util_strscpy(dirname, sizeof(dirname), attr); - pos = strstr(dirname, "/*/"); - if (pos == NULL) - return -1; - pos[0] = '\0'; - tail = &pos[2]; - dir = opendir(dirname); - if (dir != NULL) { - struct dirent *dent; - - for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { - struct stat stats; - - if (dent->d_name[0] == '.') - continue; - util_strscpyl(attr, len, dirname, "/", dent->d_name, tail, NULL); - if (stat(attr, &stats) == 0) { - found = true; - break; - } - } - closedir(dir); - } - } - - return found; -} - -static int get_key(struct udev *udev, char **line, char **key, enum operation_type *op, char **value) -{ - char *linepos; - char *temp; - - linepos = *line; - if (linepos == NULL || linepos[0] == '\0') - return -1; - - /* skip whitespace */ - while (isspace(linepos[0]) || linepos[0] == ',') - linepos++; - - /* get the key */ - if (linepos[0] == '\0') - return -1; - *key = linepos; - - for (;;) { - linepos++; - if (linepos[0] == '\0') - return -1; - if (isspace(linepos[0])) - break; - if (linepos[0] == '=') - break; - if ((linepos[0] == '+') || (linepos[0] == '!') || (linepos[0] == ':')) - if (linepos[1] == '=') - break; - } - - /* remember end of key */ - temp = linepos; - - /* skip whitespace after key */ - while (isspace(linepos[0])) - linepos++; - if (linepos[0] == '\0') - return -1; - - /* get operation type */ - if (linepos[0] == '=' && linepos[1] == '=') { - *op = OP_MATCH; - linepos += 2; - } else if (linepos[0] == '!' && linepos[1] == '=') { - *op = OP_NOMATCH; - linepos += 2; - } else if (linepos[0] == '+' && linepos[1] == '=') { - *op = OP_ADD; - linepos += 2; - } else if (linepos[0] == '=') { - *op = OP_ASSIGN; - linepos++; - } else if (linepos[0] == ':' && linepos[1] == '=') { - *op = OP_ASSIGN_FINAL; - linepos += 2; - } else - return -1; - - /* terminate key */ - temp[0] = '\0'; - - /* skip whitespace after operator */ - while (isspace(linepos[0])) - linepos++; - if (linepos[0] == '\0') - return -1; - - /* get the value */ - if (linepos[0] == '"') - linepos++; - else - return -1; - *value = linepos; - - /* terminate */ - temp = strchr(linepos, '"'); - if (!temp) - return -1; - temp[0] = '\0'; - temp++; - dbg(udev, "%s '%s'-'%s'\n", operation_str(*op), *key, *value); - - /* move line to next key */ - *line = temp; - return 0; -} - -/* extract possible KEY{attr} */ -static char *get_key_attribute(struct udev *udev, char *str) -{ - char *pos; - char *attr; - - attr = strchr(str, '{'); - if (attr != NULL) { - attr++; - pos = strchr(attr, '}'); - if (pos == NULL) { - err(udev, "missing closing brace for format\n"); - return NULL; - } - pos[0] = '\0'; - dbg(udev, "attribute='%s'\n", attr); - return attr; - } - return NULL; -} - -static int rule_add_key(struct rule_tmp *rule_tmp, enum token_type type, - enum operation_type op, - const char *value, const void *data) -{ - struct token *token = &rule_tmp->token[rule_tmp->token_cur]; - const char *attr = NULL; - - memset(token, 0x00, sizeof(struct token)); - - switch (type) { - case TK_M_ACTION: - case TK_M_DEVPATH: - case TK_M_KERNEL: - case TK_M_SUBSYSTEM: - case TK_M_DRIVER: - case TK_M_WAITFOR: - case TK_M_DEVLINK: - case TK_M_NAME: - case TK_M_KERNELS: - case TK_M_SUBSYSTEMS: - case TK_M_DRIVERS: - case TK_M_TAGS: - case TK_M_PROGRAM: - case TK_M_IMPORT_FILE: - case TK_M_IMPORT_PROG: - case TK_M_IMPORT_DB: - case TK_M_IMPORT_CMDLINE: - case TK_M_IMPORT_PARENT: - case TK_M_RESULT: - case TK_A_OWNER: - case TK_A_GROUP: - case TK_A_MODE: - case TK_A_NAME: - case TK_A_GOTO: - case TK_M_TAG: - case TK_A_TAG: - token->key.value_off = add_string(rule_tmp->rules, value); - break; - case TK_M_IMPORT_BUILTIN: - token->key.value_off = add_string(rule_tmp->rules, value); - token->key.builtin_cmd = *(enum udev_builtin_cmd *)data; - break; - case TK_M_ENV: - case TK_M_ATTR: - case TK_M_ATTRS: - case TK_A_ATTR: - case TK_A_ENV: - attr = data; - token->key.value_off = add_string(rule_tmp->rules, value); - token->key.attr_off = add_string(rule_tmp->rules, attr); - break; - case TK_A_DEVLINK: - token->key.value_off = add_string(rule_tmp->rules, value); - token->key.devlink_unique = *(int *)data; - break; - case TK_M_TEST: - token->key.value_off = add_string(rule_tmp->rules, value); - if (data != NULL) - token->key.mode = *(mode_t *)data; - break; - case TK_A_STRING_ESCAPE_NONE: - case TK_A_STRING_ESCAPE_REPLACE: - case TK_A_DB_PERSIST: - break; - case TK_A_RUN: - token->key.value_off = add_string(rule_tmp->rules, value); - break; - case TK_A_INOTIFY_WATCH: - case TK_A_DEVLINK_PRIO: - token->key.devlink_prio = *(int *)data; - break; - case TK_A_OWNER_ID: - token->key.uid = *(uid_t *)data; - break; - case TK_A_GROUP_ID: - token->key.gid = *(gid_t *)data; - break; - case TK_A_MODE_ID: - token->key.mode = *(mode_t *)data; - break; - case TK_A_STATIC_NODE: - token->key.value_off = add_string(rule_tmp->rules, value); - break; - case TK_M_EVENT_TIMEOUT: - token->key.event_timeout = *(int *)data; - break; - case TK_RULE: - case TK_M_PARENTS_MIN: - case TK_M_PARENTS_MAX: - case TK_M_MAX: - case TK_END: - case TK_UNSET: - err(rule_tmp->rules->udev, "wrong type %u\n", type); - return -1; - } - - if (value != NULL && type < TK_M_MAX) { - /* check if we need to split or call fnmatch() while matching rules */ - enum string_glob_type glob; - int has_split; - int has_glob; - - has_split = (strchr(value, '|') != NULL); - has_glob = (strchr(value, '*') != NULL || strchr(value, '?') != NULL || strchr(value, '[') != NULL); - if (has_split && has_glob) { - glob = GL_SPLIT_GLOB; - } else if (has_split) { - glob = GL_SPLIT; - } else if (has_glob) { - if (strcmp(value, "?*") == 0) - glob = GL_SOMETHING; - else - glob = GL_GLOB; - } else { - glob = GL_PLAIN; - } - token->key.glob = glob; - } - - if (value != NULL && type > TK_M_MAX) { - /* check if assigned value has substitution chars */ - if (value[0] == '[') - token->key.subst = SB_SUBSYS; - else if (strchr(value, '%') != NULL || strchr(value, '$') != NULL) - token->key.subst = SB_FORMAT; - else - token->key.subst = SB_NONE; - } - - if (attr != NULL) { - /* check if property/attribut name has substitution chars */ - if (attr[0] == '[') - token->key.attrsubst = SB_SUBSYS; - else if (strchr(attr, '%') != NULL || strchr(attr, '$') != NULL) - token->key.attrsubst = SB_FORMAT; - else - token->key.attrsubst = SB_NONE; - } - - token->key.type = type; - token->key.op = op; - rule_tmp->token_cur++; - if (rule_tmp->token_cur >= ARRAY_SIZE(rule_tmp->token)) { - err(rule_tmp->rules->udev, "temporary rule array too small\n"); - return -1; - } - return 0; -} - -static int sort_token(struct udev_rules *rules, struct rule_tmp *rule_tmp) -{ - unsigned int i; - unsigned int start = 0; - unsigned int end = rule_tmp->token_cur; - - for (i = 0; i < rule_tmp->token_cur; i++) { - enum token_type next_val = TK_UNSET; - unsigned int next_idx = 0; - unsigned int j; - - /* find smallest value */ - for (j = start; j < end; j++) { - if (rule_tmp->token[j].type == TK_UNSET) - continue; - if (next_val == TK_UNSET || rule_tmp->token[j].type < next_val) { - next_val = rule_tmp->token[j].type; - next_idx = j; - } - } - - /* add token and mark done */ - if (add_token(rules, &rule_tmp->token[next_idx]) != 0) - return -1; - rule_tmp->token[next_idx].type = TK_UNSET; - - /* shrink range */ - if (next_idx == start) - start++; - if (next_idx+1 == end) - end--; - } - return 0; -} - -static int add_rule(struct udev_rules *rules, char *line, - const char *filename, unsigned int filename_off, unsigned int lineno) -{ - char *linepos; - char *attr; - struct rule_tmp rule_tmp; - - memset(&rule_tmp, 0x00, sizeof(struct rule_tmp)); - rule_tmp.rules = rules; - rule_tmp.rule.type = TK_RULE; - rule_tmp.rule.rule.filename_off = filename_off; - rule_tmp.rule.rule.filename_line = lineno; - - linepos = line; - for (;;) { - char *key; - char *value; - enum operation_type op; - - if (get_key(rules->udev, &linepos, &key, &op, &value) != 0) - break; - - if (strcmp(key, "ACTION") == 0) { - if (op > OP_MATCH_MAX) { - err(rules->udev, "invalid ACTION operation\n"); - goto invalid; - } - rule_add_key(&rule_tmp, TK_M_ACTION, op, value, NULL); - continue; - } - - if (strcmp(key, "DEVPATH") == 0) { - if (op > OP_MATCH_MAX) { - err(rules->udev, "invalid DEVPATH operation\n"); - goto invalid; - } - rule_add_key(&rule_tmp, TK_M_DEVPATH, op, value, NULL); - continue; - } - - if (strcmp(key, "KERNEL") == 0) { - if (op > OP_MATCH_MAX) { - err(rules->udev, "invalid KERNEL operation\n"); - goto invalid; - } - rule_add_key(&rule_tmp, TK_M_KERNEL, op, value, NULL); - continue; - } - - if (strcmp(key, "SUBSYSTEM") == 0) { - if (op > OP_MATCH_MAX) { - err(rules->udev, "invalid SUBSYSTEM operation\n"); - goto invalid; - } - /* bus, class, subsystem events should all be the same */ - if (strcmp(value, "subsystem") == 0 || - strcmp(value, "bus") == 0 || - strcmp(value, "class") == 0) { - if (strcmp(value, "bus") == 0 || strcmp(value, "class") == 0) - err(rules->udev, "'%s' must be specified as 'subsystem' \n" - "please fix it in %s:%u", value, filename, lineno); - rule_add_key(&rule_tmp, TK_M_SUBSYSTEM, op, "subsystem|class|bus", NULL); - } else - rule_add_key(&rule_tmp, TK_M_SUBSYSTEM, op, value, NULL); - continue; - } - - if (strcmp(key, "DRIVER") == 0) { - if (op > OP_MATCH_MAX) { - err(rules->udev, "invalid DRIVER operation\n"); - goto invalid; - } - rule_add_key(&rule_tmp, TK_M_DRIVER, op, value, NULL); - continue; - } - - if (strncmp(key, "ATTR{", sizeof("ATTR{")-1) == 0) { - attr = get_key_attribute(rules->udev, key + sizeof("ATTR")-1); - if (attr == NULL) { - err(rules->udev, "error parsing ATTR attribute\n"); - goto invalid; - } - if (op < OP_MATCH_MAX) { - rule_add_key(&rule_tmp, TK_M_ATTR, op, value, attr); - } else { - rule_add_key(&rule_tmp, TK_A_ATTR, op, value, attr); - } - continue; - } - - if (strcmp(key, "KERNELS") == 0) { - if (op > OP_MATCH_MAX) { - err(rules->udev, "invalid KERNELS operation\n"); - goto invalid; - } - rule_add_key(&rule_tmp, TK_M_KERNELS, op, value, NULL); - continue; - } - - if (strcmp(key, "SUBSYSTEMS") == 0) { - if (op > OP_MATCH_MAX) { - err(rules->udev, "invalid SUBSYSTEMS operation\n"); - goto invalid; - } - rule_add_key(&rule_tmp, TK_M_SUBSYSTEMS, op, value, NULL); - continue; - } - - if (strcmp(key, "DRIVERS") == 0) { - if (op > OP_MATCH_MAX) { - err(rules->udev, "invalid DRIVERS operation\n"); - goto invalid; - } - rule_add_key(&rule_tmp, TK_M_DRIVERS, op, value, NULL); - continue; - } - - if (strncmp(key, "ATTRS{", sizeof("ATTRS{")-1) == 0) { - if (op > OP_MATCH_MAX) { - err(rules->udev, "invalid ATTRS operation\n"); - goto invalid; - } - attr = get_key_attribute(rules->udev, key + sizeof("ATTRS")-1); - if (attr == NULL) { - err(rules->udev, "error parsing ATTRS attribute\n"); - goto invalid; - } - if (strncmp(attr, "device/", 7) == 0) - err(rules->udev, "the 'device' link may not be available in a future kernel, " - "please fix it in %s:%u", filename, lineno); - else if (strstr(attr, "../") != NULL) - err(rules->udev, "do not reference parent sysfs directories directly, " - "it may break with a future kernel, please fix it in %s:%u", filename, lineno); - rule_add_key(&rule_tmp, TK_M_ATTRS, op, value, attr); - continue; - } - - if (strcmp(key, "TAGS") == 0) { - if (op > OP_MATCH_MAX) { - err(rules->udev, "invalid TAGS operation\n"); - goto invalid; - } - rule_add_key(&rule_tmp, TK_M_TAGS, op, value, NULL); - continue; - } - - if (strncmp(key, "ENV{", sizeof("ENV{")-1) == 0) { - attr = get_key_attribute(rules->udev, key + sizeof("ENV")-1); - if (attr == NULL) { - err(rules->udev, "error parsing ENV attribute\n"); - goto invalid; - } - if (op < OP_MATCH_MAX) { - if (rule_add_key(&rule_tmp, TK_M_ENV, op, value, attr) != 0) - goto invalid; - } else { - static const char *blacklist[] = { - "ACTION", - "SUBSYSTEM", - "DEVTYPE", - "MAJOR", - "MINOR", - "DRIVER", - "IFINDEX", - "DEVNAME", - "DEVLINKS", - "DEVPATH", - "TAGS", - }; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(blacklist); i++) - if (strcmp(attr, blacklist[i]) == 0) { - err(rules->udev, "invalid ENV attribute, '%s' can not be set %s:%u\n", attr, filename, lineno); - continue; - } - if (rule_add_key(&rule_tmp, TK_A_ENV, op, value, attr) != 0) - goto invalid; - } - continue; - } - - if (strcmp(key, "TAG") == 0) { - if (op < OP_MATCH_MAX) - rule_add_key(&rule_tmp, TK_M_TAG, op, value, NULL); - else - rule_add_key(&rule_tmp, TK_A_TAG, op, value, NULL); - continue; - } - - if (strcmp(key, "PROGRAM") == 0) { - rule_add_key(&rule_tmp, TK_M_PROGRAM, op, value, NULL); - continue; - } - - if (strcmp(key, "RESULT") == 0) { - if (op > OP_MATCH_MAX) { - err(rules->udev, "invalid RESULT operation\n"); - goto invalid; - } - rule_add_key(&rule_tmp, TK_M_RESULT, op, value, NULL); - continue; - } - - if (strncmp(key, "IMPORT", sizeof("IMPORT")-1) == 0) { - attr = get_key_attribute(rules->udev, key + sizeof("IMPORT")-1); - if (attr == NULL) { - err(rules->udev, "IMPORT{} type missing, ignoring IMPORT %s:%u\n", filename, lineno); - continue; - } - if (strstr(attr, "program")) { - /* find known built-in command */ - if (value[0] != '/') { - enum udev_builtin_cmd cmd; - - cmd = udev_builtin_lookup(value); - if (cmd < UDEV_BUILTIN_MAX) { - info(rules->udev, "IMPORT found builtin '%s', replacing %s:%u\n", - value, filename, lineno); - rule_add_key(&rule_tmp, TK_M_IMPORT_BUILTIN, op, value, &cmd); - continue; - } - } - dbg(rules->udev, "IMPORT will be executed\n"); - rule_add_key(&rule_tmp, TK_M_IMPORT_PROG, op, value, NULL); - } else if (strstr(attr, "builtin")) { - enum udev_builtin_cmd cmd = udev_builtin_lookup(value); - - dbg(rules->udev, "IMPORT execute builtin\n"); - if (cmd < UDEV_BUILTIN_MAX) - rule_add_key(&rule_tmp, TK_M_IMPORT_BUILTIN, op, value, &cmd); - else - err(rules->udev, "IMPORT{builtin}: '%s' unknown %s:%u\n", value, filename, lineno); - } else if (strstr(attr, "file")) { - dbg(rules->udev, "IMPORT will be included as file\n"); - rule_add_key(&rule_tmp, TK_M_IMPORT_FILE, op, value, NULL); - } else if (strstr(attr, "db")) { - dbg(rules->udev, "IMPORT will include db values\n"); - rule_add_key(&rule_tmp, TK_M_IMPORT_DB, op, value, NULL); - } else if (strstr(attr, "cmdline")) { - dbg(rules->udev, "IMPORT will include db values\n"); - rule_add_key(&rule_tmp, TK_M_IMPORT_CMDLINE, op, value, NULL); - } else if (strstr(attr, "parent")) { - dbg(rules->udev, "IMPORT will include the parent values\n"); - rule_add_key(&rule_tmp, TK_M_IMPORT_PARENT, op, value, NULL); - } - continue; - } - - if (strncmp(key, "TEST", sizeof("TEST")-1) == 0) { - mode_t mode = 0; - - if (op > OP_MATCH_MAX) { - err(rules->udev, "invalid TEST operation\n"); - goto invalid; - } - attr = get_key_attribute(rules->udev, key + sizeof("TEST")-1); - if (attr != NULL) { - mode = strtol(attr, NULL, 8); - rule_add_key(&rule_tmp, TK_M_TEST, op, value, &mode); - } else { - rule_add_key(&rule_tmp, TK_M_TEST, op, value, NULL); - } - continue; - } - - if (strcmp(key, "RUN") == 0) { - if (strncmp(value, "socket:", 7) == 0) - err(rules->udev, "RUN+=\"socket:...\" support will be removed from a future udev release. " - "Please remove it from: %s:%u and use libudev to subscribe to events.\n", filename, lineno); - rule_add_key(&rule_tmp, TK_A_RUN, op, value, NULL); - continue; - } - - if (strcmp(key, "WAIT_FOR") == 0 || strcmp(key, "WAIT_FOR_SYSFS") == 0) { - rule_add_key(&rule_tmp, TK_M_WAITFOR, 0, value, NULL); - continue; - } - - if (strcmp(key, "LABEL") == 0) { - rule_tmp.rule.rule.label_off = add_string(rules, value); - continue; - } - - if (strcmp(key, "GOTO") == 0) { - rule_add_key(&rule_tmp, TK_A_GOTO, 0, value, NULL); - continue; - } - - if (strncmp(key, "NAME", sizeof("NAME")-1) == 0) { - if (op < OP_MATCH_MAX) { - rule_add_key(&rule_tmp, TK_M_NAME, op, value, NULL); - } else { - if (strcmp(value, "%k") == 0) { - err(rules->udev, "NAME=\"%%k\" is ignored, because it breaks kernel supplied names, " - "please remove it from %s:%u\n", filename, lineno); - continue; - } - if (value[0] == '\0') { - info(rules->udev, "NAME=\"\" is ignored, because udev will not delete any device nodes, " - "please remove it from %s:%u\n", filename, lineno); - continue; - } - rule_add_key(&rule_tmp, TK_A_NAME, op, value, NULL); - } - rule_tmp.rule.rule.can_set_name = true; - continue; - } - - if (strncmp(key, "SYMLINK", sizeof("SYMLINK")-1) == 0) { - if (op < OP_MATCH_MAX) { - rule_add_key(&rule_tmp, TK_M_DEVLINK, op, value, NULL); - } else { - int flag = 0; - - attr = get_key_attribute(rules->udev, key + sizeof("SYMLINK")-1); - if (attr != NULL && strstr(attr, "unique") != NULL) - flag = 1; - rule_add_key(&rule_tmp, TK_A_DEVLINK, op, value, &flag); - } - rule_tmp.rule.rule.can_set_name = true; - continue; - } - - if (strcmp(key, "OWNER") == 0) { - uid_t uid; - char *endptr; - - uid = strtoul(value, &endptr, 10); - if (endptr[0] == '\0') { - rule_add_key(&rule_tmp, TK_A_OWNER_ID, op, NULL, &uid); - } else if ((rules->resolve_names > 0) && strchr("$%", value[0]) == NULL) { - uid = add_uid(rules, value); - rule_add_key(&rule_tmp, TK_A_OWNER_ID, op, NULL, &uid); - } else if (rules->resolve_names >= 0) { - rule_add_key(&rule_tmp, TK_A_OWNER, op, value, NULL); - } - rule_tmp.rule.rule.can_set_name = true; - continue; - } - - if (strcmp(key, "GROUP") == 0) { - gid_t gid; - char *endptr; - - gid = strtoul(value, &endptr, 10); - if (endptr[0] == '\0') { - rule_add_key(&rule_tmp, TK_A_GROUP_ID, op, NULL, &gid); - } else if ((rules->resolve_names > 0) && strchr("$%", value[0]) == NULL) { - gid = add_gid(rules, value); - rule_add_key(&rule_tmp, TK_A_GROUP_ID, op, NULL, &gid); - } else if (rules->resolve_names >= 0) { - rule_add_key(&rule_tmp, TK_A_GROUP, op, value, NULL); - } - rule_tmp.rule.rule.can_set_name = true; - continue; - } - - if (strcmp(key, "MODE") == 0) { - mode_t mode; - char *endptr; - - mode = strtol(value, &endptr, 8); - if (endptr[0] == '\0') - rule_add_key(&rule_tmp, TK_A_MODE_ID, op, NULL, &mode); - else - rule_add_key(&rule_tmp, TK_A_MODE, op, value, NULL); - rule_tmp.rule.rule.can_set_name = true; - continue; - } - - if (strcmp(key, "OPTIONS") == 0) { - const char *pos; - - pos = strstr(value, "link_priority="); - if (pos != NULL) { - int prio = atoi(&pos[strlen("link_priority=")]); - - rule_add_key(&rule_tmp, TK_A_DEVLINK_PRIO, op, NULL, &prio); - dbg(rules->udev, "link priority=%i\n", prio); - } - - pos = strstr(value, "event_timeout="); - if (pos != NULL) { - int tout = atoi(&pos[strlen("event_timeout=")]); - - rule_add_key(&rule_tmp, TK_M_EVENT_TIMEOUT, op, NULL, &tout); - dbg(rules->udev, "event timeout=%i\n", tout); - } - - pos = strstr(value, "string_escape="); - if (pos != NULL) { - pos = &pos[strlen("string_escape=")]; - if (strncmp(pos, "none", strlen("none")) == 0) - rule_add_key(&rule_tmp, TK_A_STRING_ESCAPE_NONE, op, NULL, NULL); - else if (strncmp(pos, "replace", strlen("replace")) == 0) - rule_add_key(&rule_tmp, TK_A_STRING_ESCAPE_REPLACE, op, NULL, NULL); - } - - pos = strstr(value, "db_persist"); - if (pos != NULL) - rule_add_key(&rule_tmp, TK_A_DB_PERSIST, op, NULL, NULL); - - pos = strstr(value, "nowatch"); - if (pos != NULL) { - const int off = 0; - - rule_add_key(&rule_tmp, TK_A_INOTIFY_WATCH, op, NULL, &off); - dbg(rules->udev, "inotify watch of device disabled\n"); - } else { - pos = strstr(value, "watch"); - if (pos != NULL) { - const int on = 1; - - rule_add_key(&rule_tmp, TK_A_INOTIFY_WATCH, op, NULL, &on); - dbg(rules->udev, "inotify watch of device requested\n"); - } - } - - pos = strstr(value, "static_node="); - if (pos != NULL) { - rule_add_key(&rule_tmp, TK_A_STATIC_NODE, op, &pos[strlen("static_node=")], NULL); - rule_tmp.rule.rule.has_static_node = true; - } - - continue; - } - - err(rules->udev, "unknown key '%s' in %s:%u\n", key, filename, lineno); - goto invalid; - } - - /* add rule token */ - rule_tmp.rule.rule.token_count = 1 + rule_tmp.token_cur; - if (add_token(rules, &rule_tmp.rule) != 0) - goto invalid; - - /* add tokens to list, sorted by type */ - if (sort_token(rules, &rule_tmp) != 0) - goto invalid; - - return 0; -invalid: - err(rules->udev, "invalid rule '%s:%u'\n", filename, lineno); - return -1; -} - -static int parse_file(struct udev_rules *rules, const char *filename, unsigned short filename_off) -{ - FILE *f; - unsigned int first_token; - char line[UTIL_LINE_SIZE]; - int line_nr = 0; - unsigned int i; - - info(rules->udev, "reading '%s' as rules file\n", filename); - - f = fopen(filename, "r"); - if (f == NULL) - return -1; - - first_token = rules->token_cur; - - while (fgets(line, sizeof(line), f) != NULL) { - char *key; - size_t len; - - /* skip whitespace */ - line_nr++; - key = line; - while (isspace(key[0])) - key++; - - /* comment */ - if (key[0] == '#') - continue; - - len = strlen(line); - if (len < 3) - continue; - - /* continue reading if backslash+newline is found */ - while (line[len-2] == '\\') { - if (fgets(&line[len-2], (sizeof(line)-len)+2, f) == NULL) - break; - if (strlen(&line[len-2]) < 2) - break; - line_nr++; - len = strlen(line); - } - - if (len+1 >= sizeof(line)) { - err(rules->udev, "line too long '%s':%u, ignored\n", filename, line_nr); - continue; - } - add_rule(rules, key, filename, filename_off, line_nr); - } - fclose(f); - - /* link GOTOs to LABEL rules in this file to be able to fast-forward */ - for (i = first_token+1; i < rules->token_cur; i++) { - if (rules->tokens[i].type == TK_A_GOTO) { - char *label = &rules->buf[rules->tokens[i].key.value_off]; - unsigned int j; - - for (j = i+1; j < rules->token_cur; j++) { - if (rules->tokens[j].type != TK_RULE) - continue; - if (rules->tokens[j].rule.label_off == 0) - continue; - if (strcmp(label, &rules->buf[rules->tokens[j].rule.label_off]) != 0) - continue; - rules->tokens[i].key.rule_goto = j; - break; - } - if (rules->tokens[i].key.rule_goto == 0) - err(rules->udev, "GOTO '%s' has no matching label in: '%s'\n", label, filename); - } - } - return 0; -} - -static int add_matching_files(struct udev *udev, struct udev_list *file_list, const char *dirname, const char *suffix) -{ - DIR *dir; - struct dirent *dent; - char filename[UTIL_PATH_SIZE]; - - dbg(udev, "open directory '%s'\n", dirname); - dir = opendir(dirname); - if (dir == NULL) { - info(udev, "unable to open '%s': %m\n", dirname); - return -1; - } - - for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { - if (dent->d_name[0] == '.') - continue; - - /* look for file matching with specified suffix */ - if (suffix != NULL) { - const char *ext; - - ext = strrchr(dent->d_name, '.'); - if (ext == NULL) - continue; - if (strcmp(ext, suffix) != 0) - continue; - } - util_strscpyl(filename, sizeof(filename), dirname, "/", dent->d_name, NULL); - dbg(udev, "put file '%s' into list\n", filename); - /* - * the basename is the key, the filename the value - * identical basenames from different directories override each other - * entries are sorted after basename - */ - udev_list_entry_add(file_list, dent->d_name, filename); - } - - closedir(dir); - return 0; -} - -struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names) -{ - struct udev_rules *rules; - struct udev_list file_list; - struct udev_list_entry *file_loop; - struct token end_token; - char **s; - - rules = calloc(1, sizeof(struct udev_rules)); - if (rules == NULL) - return NULL; - rules->udev = udev; - rules->resolve_names = resolve_names; - udev_list_init(udev, &file_list, true); - - /* init token array and string buffer */ - rules->tokens = malloc(PREALLOC_TOKEN * sizeof(struct token)); - if (rules->tokens == NULL) { - free(rules); - return NULL; - } - rules->token_max = PREALLOC_TOKEN; - - rules->buf = malloc(PREALLOC_STRBUF); - if (rules->buf == NULL) { - free(rules->tokens); - free(rules); - return NULL; - } - rules->buf_max = PREALLOC_STRBUF; - /* offset 0 is always '\0' */ - rules->buf[0] = '\0'; - rules->buf_cur = 1; - dbg(udev, "prealloc %zu bytes tokens (%u * %zu bytes), %zu bytes buffer\n", - rules->token_max * sizeof(struct token), rules->token_max, sizeof(struct token), rules->buf_max); - - rules->trie_nodes = malloc(PREALLOC_TRIE * sizeof(struct trie_node)); - if (rules->trie_nodes == NULL) { - free(rules->buf); - free(rules->tokens); - free(rules); - return NULL; - } - rules->trie_nodes_max = PREALLOC_TRIE; - /* offset 0 is the trie root, with an empty string */ - memset(rules->trie_nodes, 0x00, sizeof(struct trie_node)); - rules->trie_nodes_cur = 1; - - for (udev_get_rules_path(udev, &s, NULL); *s != NULL; s++) - add_matching_files(udev, &file_list, *s, ".rules"); - - /* add all filenames to the string buffer */ - udev_list_entry_foreach(file_loop, udev_list_get_entry(&file_list)) { - const char *filename = udev_list_entry_get_value(file_loop); - unsigned int filename_off; - - filename_off = add_string(rules, filename); - /* the offset in the rule is limited to unsigned short */ - if (filename_off < USHRT_MAX) - udev_list_entry_set_num(file_loop, filename_off); - } - - /* parse all rules files */ - udev_list_entry_foreach(file_loop, udev_list_get_entry(&file_list)) { - const char *filename = udev_list_entry_get_value(file_loop); - unsigned int filename_off = udev_list_entry_get_num(file_loop); - struct stat st; - - if (stat(filename, &st) != 0) { - err(udev, "can not find '%s': %m\n", filename); - continue; - } - if (S_ISREG(st.st_mode) && st.st_size <= 0) { - info(udev, "ignore empty '%s'\n", filename); - continue; - } - if (S_ISCHR(st.st_mode)) { - info(udev, "ignore masked '%s'\n", filename); - continue; - } - parse_file(rules, filename, filename_off); - } - udev_list_cleanup(&file_list); - - memset(&end_token, 0x00, sizeof(struct token)); - end_token.type = TK_END; - add_token(rules, &end_token); - - /* shrink allocated token and string buffer */ - if (rules->token_cur < rules->token_max) { - struct token *tokens; - - tokens = realloc(rules->tokens, rules->token_cur * sizeof(struct token)); - if (tokens != NULL || rules->token_cur == 0) { - rules->tokens = tokens; - rules->token_max = rules->token_cur; - } - } - if (rules->buf_cur < rules->buf_max) { - char *buf; - - buf = realloc(rules->buf, rules->buf_cur); - if (buf != NULL || rules->buf_cur == 0) { - rules->buf = buf; - rules->buf_max = rules->buf_cur; - } - } - info(udev, "rules use %zu bytes tokens (%u * %zu bytes), %zu bytes buffer\n", - rules->token_max * sizeof(struct token), rules->token_max, sizeof(struct token), rules->buf_max); - info(udev, "temporary index used %zu bytes (%u * %zu bytes)\n", - rules->trie_nodes_cur * sizeof(struct trie_node), - rules->trie_nodes_cur, sizeof(struct trie_node)); - - /* cleanup trie */ - free(rules->trie_nodes); - rules->trie_nodes = NULL; - rules->trie_nodes_cur = 0; - rules->trie_nodes_max = 0; - - /* cleanup uid/gid cache */ - free(rules->uids); - rules->uids = NULL; - rules->uids_cur = 0; - rules->uids_max = 0; - free(rules->gids); - rules->gids = NULL; - rules->gids_cur = 0; - rules->gids_max = 0; - - dump_rules(rules); - return rules; -} - -struct udev_rules *udev_rules_unref(struct udev_rules *rules) -{ - if (rules == NULL) - return NULL; - free(rules->tokens); - free(rules->buf); - free(rules->trie_nodes); - free(rules->uids); - free(rules->gids); - free(rules); - return NULL; -} - -static int match_key(struct udev_rules *rules, struct token *token, const char *val) -{ - char *key_value = &rules->buf[token->key.value_off]; - char *pos; - bool match = false; - - if (val == NULL) - val = ""; - - switch (token->key.glob) { - case GL_PLAIN: - match = (strcmp(key_value, val) == 0); - break; - case GL_GLOB: - match = (fnmatch(key_value, val, 0) == 0); - break; - case GL_SPLIT: - { - const char *split; - size_t len; - - split = &rules->buf[token->key.value_off]; - len = strlen(val); - for (;;) { - const char *next; - - next = strchr(split, '|'); - if (next != NULL) { - size_t matchlen = (size_t)(next - split); - - match = (matchlen == len && strncmp(split, val, matchlen) == 0); - if (match) - break; - } else { - match = (strcmp(split, val) == 0); - break; - } - split = &next[1]; - } - break; - } - case GL_SPLIT_GLOB: - { - char value[UTIL_PATH_SIZE]; - - util_strscpy(value, sizeof(value), &rules->buf[token->key.value_off]); - key_value = value; - while (key_value != NULL) { - pos = strchr(key_value, '|'); - if (pos != NULL) { - pos[0] = '\0'; - pos = &pos[1]; - } - dbg(rules->udev, "match %s '%s' <-> '%s'\n", token_str(token->type), key_value, val); - match = (fnmatch(key_value, val, 0) == 0); - if (match) - break; - key_value = pos; - } - break; - } - case GL_SOMETHING: - match = (val[0] != '\0'); - break; - case GL_UNSET: - return -1; - } - - if (match && (token->key.op == OP_MATCH)) { - dbg(rules->udev, "%s is true (matching value)\n", token_str(token->type)); - return 0; - } - if (!match && (token->key.op == OP_NOMATCH)) { - dbg(rules->udev, "%s is true (non-matching value)\n", token_str(token->type)); - return 0; - } - dbg(rules->udev, "%s is not true\n", token_str(token->type)); - return -1; -} - -static int match_attr(struct udev_rules *rules, struct udev_device *dev, struct udev_event *event, struct token *cur) -{ - const char *name; - char nbuf[UTIL_NAME_SIZE]; - const char *value; - char vbuf[UTIL_NAME_SIZE]; - size_t len; - - name = &rules->buf[cur->key.attr_off]; - switch (cur->key.attrsubst) { - case SB_FORMAT: - udev_event_apply_format(event, name, nbuf, sizeof(nbuf)); - name = nbuf; - /* fall through */ - case SB_NONE: - value = udev_device_get_sysattr_value(dev, name); - if (value == NULL) - return -1; - break; - case SB_SUBSYS: - if (util_resolve_subsys_kernel(event->udev, name, vbuf, sizeof(vbuf), 1) != 0) - return -1; - value = vbuf; - break; - default: - return -1; - } - - /* remove trailing whitespace, if not asked to match for it */ - len = strlen(value); - if (len > 0 && isspace(value[len-1])) { - const char *key_value; - size_t klen; - - key_value = &rules->buf[cur->key.value_off]; - klen = strlen(key_value); - if (klen > 0 && !isspace(key_value[klen-1])) { - if (value != vbuf) { - util_strscpy(vbuf, sizeof(vbuf), value); - value = vbuf; - } - while (len > 0 && isspace(vbuf[--len])) - vbuf[len] = '\0'; - dbg(rules->udev, "removed trailing whitespace from '%s'\n", value); - } - } - - return match_key(rules, cur, value); -} - -enum escape_type { - ESCAPE_UNSET, - ESCAPE_NONE, - ESCAPE_REPLACE, -}; - -int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event, const sigset_t *sigmask) -{ - struct token *cur; - struct token *rule; - enum escape_type esc = ESCAPE_UNSET; - bool can_set_name; - - if (rules->tokens == NULL) - return -1; - - can_set_name = ((strcmp(udev_device_get_action(event->dev), "remove") != 0) && - (major(udev_device_get_devnum(event->dev)) > 0 || - udev_device_get_ifindex(event->dev) > 0)); - - /* loop through token list, match, run actions or forward to next rule */ - cur = &rules->tokens[0]; - rule = cur; - for (;;) { - dump_token(rules, cur); - switch (cur->type) { - case TK_RULE: - /* current rule */ - rule = cur; - /* possibly skip rules which want to set NAME, SYMLINK, OWNER, GROUP, MODE */ - if (!can_set_name && rule->rule.can_set_name) - goto nomatch; - esc = ESCAPE_UNSET; - break; - case TK_M_ACTION: - if (match_key(rules, cur, udev_device_get_action(event->dev)) != 0) - goto nomatch; - break; - case TK_M_DEVPATH: - if (match_key(rules, cur, udev_device_get_devpath(event->dev)) != 0) - goto nomatch; - break; - case TK_M_KERNEL: - if (match_key(rules, cur, udev_device_get_sysname(event->dev)) != 0) - goto nomatch; - break; - case TK_M_DEVLINK: { - size_t devlen = strlen(udev_get_dev_path(event->udev))+1; - struct udev_list_entry *list_entry; - bool match = false; - - udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(event->dev)) { - const char *devlink; - - devlink = &udev_list_entry_get_name(list_entry)[devlen]; - if (match_key(rules, cur, devlink) == 0) { - match = true; - break; - } - } - if (!match) - goto nomatch; - break; - } - case TK_M_NAME: - if (match_key(rules, cur, event->name) != 0) - goto nomatch; - break; - case TK_M_ENV: { - const char *key_name = &rules->buf[cur->key.attr_off]; - const char *value; - - value = udev_device_get_property_value(event->dev, key_name); - if (value == NULL) { - dbg(event->udev, "ENV{%s} is not set, treat as empty\n", key_name); - value = ""; - } - if (match_key(rules, cur, value)) - goto nomatch; - break; - } - case TK_M_TAG: { - struct udev_list_entry *list_entry; - bool match = false; - - udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(event->dev)) { - if (strcmp(&rules->buf[cur->key.value_off], udev_list_entry_get_name(list_entry)) == 0) { - match = true; - break; - } - } - if (!match && (cur->key.op != OP_NOMATCH)) - goto nomatch; - break; - } - case TK_M_SUBSYSTEM: - if (match_key(rules, cur, udev_device_get_subsystem(event->dev)) != 0) - goto nomatch; - break; - case TK_M_DRIVER: - if (match_key(rules, cur, udev_device_get_driver(event->dev)) != 0) - goto nomatch; - break; - case TK_M_WAITFOR: { - char filename[UTIL_PATH_SIZE]; - int found; - - udev_event_apply_format(event, &rules->buf[cur->key.value_off], filename, sizeof(filename)); - found = (wait_for_file(event->dev, filename, 10) == 0); - if (!found && (cur->key.op != OP_NOMATCH)) - goto nomatch; - break; - } - case TK_M_ATTR: - if (match_attr(rules, event->dev, event, cur) != 0) - goto nomatch; - break; - case TK_M_KERNELS: - case TK_M_SUBSYSTEMS: - case TK_M_DRIVERS: - case TK_M_ATTRS: - case TK_M_TAGS: { - struct token *next; - - /* get whole sequence of parent matches */ - next = cur; - while (next->type > TK_M_PARENTS_MIN && next->type < TK_M_PARENTS_MAX) - next++; - - /* loop over parents */ - event->dev_parent = event->dev; - for (;;) { - struct token *key; - - dbg(event->udev, "parent: '%s'\n", udev_device_get_syspath(event->dev_parent)); - /* loop over sequence of parent match keys */ - for (key = cur; key < next; key++ ) { - dump_token(rules, key); - switch(key->type) { - case TK_M_KERNELS: - if (match_key(rules, key, udev_device_get_sysname(event->dev_parent)) != 0) - goto try_parent; - break; - case TK_M_SUBSYSTEMS: - if (match_key(rules, key, udev_device_get_subsystem(event->dev_parent)) != 0) - goto try_parent; - break; - case TK_M_DRIVERS: - if (match_key(rules, key, udev_device_get_driver(event->dev_parent)) != 0) - goto try_parent; - break; - case TK_M_ATTRS: - if (match_attr(rules, event->dev_parent, event, key) != 0) - goto try_parent; - break; - case TK_M_TAGS: { - bool match = udev_device_has_tag(event->dev_parent, &rules->buf[cur->key.value_off]); - - if (match && key->key.op == OP_NOMATCH) - goto try_parent; - if (!match && key->key.op == OP_MATCH) - goto try_parent; - break; - } - default: - goto nomatch; - } - dbg(event->udev, "parent key matched\n"); - } - dbg(event->udev, "all parent keys matched\n"); - break; - - try_parent: - event->dev_parent = udev_device_get_parent(event->dev_parent); - if (event->dev_parent == NULL) - goto nomatch; - } - /* move behind our sequence of parent match keys */ - cur = next; - continue; - } - case TK_M_TEST: { - char filename[UTIL_PATH_SIZE]; - struct stat statbuf; - int match; - - udev_event_apply_format(event, &rules->buf[cur->key.value_off], filename, sizeof(filename)); - if (util_resolve_subsys_kernel(event->udev, filename, filename, sizeof(filename), 0) != 0) { - if (filename[0] != '/') { - char tmp[UTIL_PATH_SIZE]; - - util_strscpy(tmp, sizeof(tmp), filename); - util_strscpyl(filename, sizeof(filename), - udev_device_get_syspath(event->dev), "/", tmp, NULL); - } - } - attr_subst_subdir(filename, sizeof(filename)); - - match = (stat(filename, &statbuf) == 0); - dbg(event->udev, "'%s' %s", filename, match ? "exists\n" : "does not exist\n"); - if (match && cur->key.mode > 0) { - match = ((statbuf.st_mode & cur->key.mode) > 0); - dbg(event->udev, "'%s' has mode=%#o and %s %#o\n", filename, statbuf.st_mode, - match ? "matches" : "does not match", cur->key.mode); - } - if (match && cur->key.op == OP_NOMATCH) - goto nomatch; - if (!match && cur->key.op == OP_MATCH) - goto nomatch; - break; - } - case TK_M_EVENT_TIMEOUT: - info(event->udev, "OPTIONS event_timeout=%u\n", cur->key.event_timeout); - event->timeout_usec = cur->key.event_timeout * 1000 * 1000; - break; - case TK_M_PROGRAM: { - char program[UTIL_PATH_SIZE]; - char **envp; - char result[UTIL_PATH_SIZE]; - - free(event->program_result); - event->program_result = NULL; - udev_event_apply_format(event, &rules->buf[cur->key.value_off], program, sizeof(program)); - envp = udev_device_get_properties_envp(event->dev); - info(event->udev, "PROGRAM '%s' %s:%u\n", - program, - &rules->buf[rule->rule.filename_off], - rule->rule.filename_line); - - if (udev_event_spawn(event, program, envp, sigmask, result, sizeof(result)) < 0) { - if (cur->key.op != OP_NOMATCH) - goto nomatch; - } else { - int count; - - util_remove_trailing_chars(result, '\n'); - if (esc == ESCAPE_UNSET || esc == ESCAPE_REPLACE) { - count = util_replace_chars(result, UDEV_ALLOWED_CHARS_INPUT); - if (count > 0) - info(event->udev, "%i character(s) replaced\n" , count); - } - event->program_result = strdup(result); - dbg(event->udev, "storing result '%s'\n", event->program_result); - if (cur->key.op == OP_NOMATCH) - goto nomatch; - } - break; - } - case TK_M_IMPORT_FILE: { - char import[UTIL_PATH_SIZE]; - - udev_event_apply_format(event, &rules->buf[cur->key.value_off], import, sizeof(import)); - if (import_file_into_properties(event->dev, import) != 0) - if (cur->key.op != OP_NOMATCH) - goto nomatch; - break; - } - case TK_M_IMPORT_PROG: { - char import[UTIL_PATH_SIZE]; - - udev_event_apply_format(event, &rules->buf[cur->key.value_off], import, sizeof(import)); - info(event->udev, "IMPORT '%s' %s:%u\n", - import, - &rules->buf[rule->rule.filename_off], - rule->rule.filename_line); - - if (import_program_into_properties(event, import, sigmask) != 0) - if (cur->key.op != OP_NOMATCH) - goto nomatch; - break; - } - case TK_M_IMPORT_BUILTIN: { - char command[UTIL_PATH_SIZE]; - - if (udev_builtin_run_once(cur->key.builtin_cmd)) { - /* check if we ran already */ - if (event->builtin_run & (1 << cur->key.builtin_cmd)) { - info(event->udev, "IMPORT builtin skip '%s' %s:%u\n", - udev_builtin_name(cur->key.builtin_cmd), - &rules->buf[rule->rule.filename_off], - rule->rule.filename_line); - /* return the result from earlier run */ - if (event->builtin_ret & (1 << cur->key.builtin_cmd)) - if (cur->key.op != OP_NOMATCH) - goto nomatch; - break; - } - /* mark as ran */ - event->builtin_run |= (1 << cur->key.builtin_cmd); - } - - udev_event_apply_format(event, &rules->buf[cur->key.value_off], command, sizeof(command)); - info(event->udev, "IMPORT builtin '%s' %s:%u\n", - udev_builtin_name(cur->key.builtin_cmd), - &rules->buf[rule->rule.filename_off], - rule->rule.filename_line); - - if (udev_builtin_run(event->dev, cur->key.builtin_cmd, command, false) != 0) { - /* remember failure */ - info(rules->udev, "IMPORT builtin '%s' returned non-zero\n", - udev_builtin_name(cur->key.builtin_cmd)); - event->builtin_ret |= (1 << cur->key.builtin_cmd); - if (cur->key.op != OP_NOMATCH) - goto nomatch; - } - break; - } - case TK_M_IMPORT_DB: { - const char *key = &rules->buf[cur->key.value_off]; - const char *value; - - value = udev_device_get_property_value(event->dev_db, key); - if (value != NULL) { - struct udev_list_entry *entry; - - entry = udev_device_add_property(event->dev, key, value); - udev_list_entry_set_num(entry, true); - } else { - if (cur->key.op != OP_NOMATCH) - goto nomatch; - } - break; - } - case TK_M_IMPORT_CMDLINE: { - FILE *f; - bool imported = false; - - f = fopen("/proc/cmdline", "r"); - if (f != NULL) { - char cmdline[4096]; - - if (fgets(cmdline, sizeof(cmdline), f) != NULL) { - const char *key = &rules->buf[cur->key.value_off]; - char *pos; - - pos = strstr(cmdline, key); - if (pos != NULL) { - struct udev_list_entry *entry; - - pos += strlen(key); - if (pos[0] == '\0' || isspace(pos[0])) { - /* we import simple flags as 'FLAG=1' */ - entry = udev_device_add_property(event->dev, key, "1"); - udev_list_entry_set_num(entry, true); - imported = true; - } else if (pos[0] == '=') { - const char *value; - - pos++; - value = pos; - while (pos[0] != '\0' && !isspace(pos[0])) - pos++; - pos[0] = '\0'; - entry = udev_device_add_property(event->dev, key, value); - udev_list_entry_set_num(entry, true); - imported = true; - } - } - } - fclose(f); - } - if (!imported && cur->key.op != OP_NOMATCH) - goto nomatch; - break; - } - case TK_M_IMPORT_PARENT: { - char import[UTIL_PATH_SIZE]; - - udev_event_apply_format(event, &rules->buf[cur->key.value_off], import, sizeof(import)); - if (import_parent_into_properties(event->dev, import) != 0) - if (cur->key.op != OP_NOMATCH) - goto nomatch; - break; - } - case TK_M_RESULT: - if (match_key(rules, cur, event->program_result) != 0) - goto nomatch; - break; - case TK_A_STRING_ESCAPE_NONE: - esc = ESCAPE_NONE; - break; - case TK_A_STRING_ESCAPE_REPLACE: - esc = ESCAPE_REPLACE; - break; - case TK_A_DB_PERSIST: - udev_device_set_db_persist(event->dev); - break; - case TK_A_INOTIFY_WATCH: - if (event->inotify_watch_final) - break; - if (cur->key.op == OP_ASSIGN_FINAL) - event->inotify_watch_final = true; - event->inotify_watch = cur->key.watch; - break; - case TK_A_DEVLINK_PRIO: - udev_device_set_devlink_priority(event->dev, cur->key.devlink_prio); - break; - case TK_A_OWNER: { - char owner[UTIL_NAME_SIZE]; - - if (event->owner_final) - break; - if (cur->key.op == OP_ASSIGN_FINAL) - event->owner_final = true; - udev_event_apply_format(event, &rules->buf[cur->key.value_off], owner, sizeof(owner)); - event->uid = util_lookup_user(event->udev, owner); - info(event->udev, "OWNER %u %s:%u\n", - event->uid, - &rules->buf[rule->rule.filename_off], - rule->rule.filename_line); - break; - } - case TK_A_GROUP: { - char group[UTIL_NAME_SIZE]; - - if (event->group_final) - break; - if (cur->key.op == OP_ASSIGN_FINAL) - event->group_final = true; - udev_event_apply_format(event, &rules->buf[cur->key.value_off], group, sizeof(group)); - event->gid = util_lookup_group(event->udev, group); - info(event->udev, "GROUP %u %s:%u\n", - event->gid, - &rules->buf[rule->rule.filename_off], - rule->rule.filename_line); - break; - } - case TK_A_MODE: { - char mode_str[UTIL_NAME_SIZE]; - mode_t mode; - char *endptr; - - if (event->mode_final) - break; - udev_event_apply_format(event, &rules->buf[cur->key.value_off], mode_str, sizeof(mode_str)); - mode = strtol(mode_str, &endptr, 8); - if (endptr[0] != '\0') { - err(event->udev, "ignoring invalid mode '%s'\n", mode_str); - break; - } - if (cur->key.op == OP_ASSIGN_FINAL) - event->mode_final = true; - event->mode_set = true; - event->mode = mode; - info(event->udev, "MODE %#o %s:%u\n", - event->mode, - &rules->buf[rule->rule.filename_off], - rule->rule.filename_line); - break; - } - case TK_A_OWNER_ID: - if (event->owner_final) - break; - if (cur->key.op == OP_ASSIGN_FINAL) - event->owner_final = true; - event->uid = cur->key.uid; - info(event->udev, "OWNER %u %s:%u\n", - event->uid, - &rules->buf[rule->rule.filename_off], - rule->rule.filename_line); - break; - case TK_A_GROUP_ID: - if (event->group_final) - break; - if (cur->key.op == OP_ASSIGN_FINAL) - event->group_final = true; - event->gid = cur->key.gid; - info(event->udev, "GROUP %u %s:%u\n", - event->gid, - &rules->buf[rule->rule.filename_off], - rule->rule.filename_line); - break; - case TK_A_MODE_ID: - if (event->mode_final) - break; - if (cur->key.op == OP_ASSIGN_FINAL) - event->mode_final = true; - event->mode_set = true; - event->mode = cur->key.mode; - info(event->udev, "MODE %#o %s:%u\n", - event->mode, - &rules->buf[rule->rule.filename_off], - rule->rule.filename_line); - break; - case TK_A_ENV: { - const char *name = &rules->buf[cur->key.attr_off]; - char *value = &rules->buf[cur->key.value_off]; - - if (value[0] != '\0') { - char temp_value[UTIL_NAME_SIZE]; - struct udev_list_entry *entry; - - udev_event_apply_format(event, value, temp_value, sizeof(temp_value)); - entry = udev_device_add_property(event->dev, name, temp_value); - /* store in db, skip private keys */ - if (name[0] != '.') - udev_list_entry_set_num(entry, true); - } else { - udev_device_add_property(event->dev, name, NULL); - } - break; - } - case TK_A_TAG: { - char tag[UTIL_PATH_SIZE]; - const char *p; - - udev_event_apply_format(event, &rules->buf[cur->key.value_off], tag, sizeof(tag)); - if (cur->key.op == OP_ASSIGN || cur->key.op == OP_ASSIGN_FINAL) - udev_device_cleanup_tags_list(event->dev); - for (p = tag; *p != '\0'; p++) { - if ((*p >= 'a' && *p <= 'z') || - (*p >= 'A' && *p <= 'Z') || - (*p >= '0' && *p <= '9') || - *p == '-' || *p == '_') - continue; - err(event->udev, "ignoring invalid tag name '%s'\n", tag); - break; - } - udev_device_add_tag(event->dev, tag); - break; - } - case TK_A_NAME: { - const char *name = &rules->buf[cur->key.value_off]; - - char name_str[UTIL_PATH_SIZE]; - int count; - - if (event->name_final) - break; - if (cur->key.op == OP_ASSIGN_FINAL) - event->name_final = true; - udev_event_apply_format(event, name, name_str, sizeof(name_str)); - if (esc == ESCAPE_UNSET || esc == ESCAPE_REPLACE) { - count = util_replace_chars(name_str, "/"); - if (count > 0) - info(event->udev, "%i character(s) replaced\n", count); - } - if (major(udev_device_get_devnum(event->dev))) { - size_t devlen = strlen(udev_get_dev_path(event->udev))+1; - - if (strcmp(name_str, &udev_device_get_devnode(event->dev)[devlen]) != 0) { - err(event->udev, "NAME=\"%s\" ignored, kernel device nodes " - "can not be renamed; please fix it in %s:%u\n", name, - &rules->buf[rule->rule.filename_off], rule->rule.filename_line); - break; - } - } - free(event->name); - event->name = strdup(name_str); - info(event->udev, "NAME '%s' %s:%u\n", - event->name, - &rules->buf[rule->rule.filename_off], - rule->rule.filename_line); - break; - } - case TK_A_DEVLINK: { - char temp[UTIL_PATH_SIZE]; - char filename[UTIL_PATH_SIZE]; - char *pos, *next; - int count = 0; - - if (event->devlink_final) - break; - if (major(udev_device_get_devnum(event->dev)) == 0) - break; - if (cur->key.op == OP_ASSIGN_FINAL) - event->devlink_final = true; - if (cur->key.op == OP_ASSIGN || cur->key.op == OP_ASSIGN_FINAL) - udev_device_cleanup_devlinks_list(event->dev); - - /* allow multiple symlinks separated by spaces */ - udev_event_apply_format(event, &rules->buf[cur->key.value_off], temp, sizeof(temp)); - if (esc == ESCAPE_UNSET) - count = util_replace_chars(temp, "/ "); - else if (esc == ESCAPE_REPLACE) - count = util_replace_chars(temp, "/"); - if (count > 0) - info(event->udev, "%i character(s) replaced\n" , count); - dbg(event->udev, "rule applied, added symlink(s) '%s'\n", temp); - pos = temp; - while (isspace(pos[0])) - pos++; - next = strchr(pos, ' '); - while (next != NULL) { - next[0] = '\0'; - info(event->udev, "LINK '%s' %s:%u\n", pos, - &rules->buf[rule->rule.filename_off], rule->rule.filename_line); - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(event->udev), "/", pos, NULL); - udev_device_add_devlink(event->dev, filename, cur->key.devlink_unique); - while (isspace(next[1])) - next++; - pos = &next[1]; - next = strchr(pos, ' '); - } - if (pos[0] != '\0') { - info(event->udev, "LINK '%s' %s:%u\n", pos, - &rules->buf[rule->rule.filename_off], rule->rule.filename_line); - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(event->udev), "/", pos, NULL); - udev_device_add_devlink(event->dev, filename, cur->key.devlink_unique); - } - break; - } - case TK_A_ATTR: { - const char *key_name = &rules->buf[cur->key.attr_off]; - char attr[UTIL_PATH_SIZE]; - char value[UTIL_NAME_SIZE]; - FILE *f; - - if (util_resolve_subsys_kernel(event->udev, key_name, attr, sizeof(attr), 0) != 0) - util_strscpyl(attr, sizeof(attr), udev_device_get_syspath(event->dev), "/", key_name, NULL); - attr_subst_subdir(attr, sizeof(attr)); - - udev_event_apply_format(event, &rules->buf[cur->key.value_off], value, sizeof(value)); - info(event->udev, "ATTR '%s' writing '%s' %s:%u\n", attr, value, - &rules->buf[rule->rule.filename_off], - rule->rule.filename_line); - f = fopen(attr, "w"); - if (f != NULL) { - if (fprintf(f, "%s", value) <= 0) - err(event->udev, "error writing ATTR{%s}: %m\n", attr); - fclose(f); - } else { - err(event->udev, "error opening ATTR{%s} for writing: %m\n", attr); - } - break; - } - case TK_A_RUN: { - if (cur->key.op == OP_ASSIGN || cur->key.op == OP_ASSIGN_FINAL) - udev_list_cleanup(&event->run_list); - info(event->udev, "RUN '%s' %s:%u\n", - &rules->buf[cur->key.value_off], - &rules->buf[rule->rule.filename_off], - rule->rule.filename_line); - udev_list_entry_add(&event->run_list, &rules->buf[cur->key.value_off], NULL); - break; - } - case TK_A_GOTO: - if (cur->key.rule_goto == 0) - break; - cur = &rules->tokens[cur->key.rule_goto]; - continue; - case TK_END: - return 0; - - case TK_M_PARENTS_MIN: - case TK_M_PARENTS_MAX: - case TK_M_MAX: - case TK_UNSET: - err(rules->udev, "wrong type %u\n", cur->type); - goto nomatch; - } - - cur++; - continue; - nomatch: - /* fast-forward to next rule */ - cur = rule + rule->rule.token_count; - dbg(rules->udev, "forward to rule: %u\n", - (unsigned int) (cur - rules->tokens)); - } -} - -void udev_rules_apply_static_dev_perms(struct udev_rules *rules) -{ - struct token *cur; - struct token *rule; - uid_t uid = 0; - gid_t gid = 0; - mode_t mode = 0; - - if (rules->tokens == NULL) - return; - - cur = &rules->tokens[0]; - rule = cur; - for (;;) { - switch (cur->type) { - case TK_RULE: - /* current rule */ - rule = cur; - - /* skip rules without a static_node tag */ - if (!rule->rule.has_static_node) - goto next; - - uid = 0; - gid = 0; - mode = 0; - break; - case TK_A_OWNER_ID: - uid = cur->key.uid; - break; - case TK_A_GROUP_ID: - gid = cur->key.gid; - break; - case TK_A_MODE_ID: - mode = cur->key.mode; - break; - case TK_A_STATIC_NODE: { - char filename[UTIL_PATH_SIZE]; - struct stat stats; - - /* we assure, that the permissions tokens are sorted before the static token */ - if (mode == 0 && uid == 0 && gid == 0) - goto next; - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(rules->udev), "/", - &rules->buf[cur->key.value_off], NULL); - if (stat(filename, &stats) != 0) - goto next; - if (!S_ISBLK(stats.st_mode) && !S_ISCHR(stats.st_mode)) - goto next; - if (mode == 0) { - if (gid > 0) - mode = 0660; - else - mode = 0600; - } - if (mode != (stats.st_mode & 01777)) { - chmod(filename, mode); - info(rules->udev, "chmod '%s' %#o\n", filename, mode); - } - - if ((uid != 0 && uid != stats.st_uid) || (gid != 0 && gid != stats.st_gid)) { - chown(filename, uid, gid); - info(rules->udev, "chown '%s' %u %u\n", filename, uid, gid); - } - - utimensat(AT_FDCWD, filename, NULL, 0); - break; - } - case TK_END: - return; - } - - cur++; - continue; -next: - /* fast-forward to next rule */ - cur = rule + rule->rule.token_count; - continue; - } -} diff --git a/src/udev/src/udev-settle.service.in b/src/udev/src/udev-settle.service.in deleted file mode 100644 index b0a4964f7..000000000 --- a/src/udev/src/udev-settle.service.in +++ /dev/null @@ -1,25 +0,0 @@ -# This service is usually not enabled by default. If enabled, it -# acts as a barrier for basic.target -- so all later services will -# wait for udev completely finishing its coldplug run. -# -# If needed, to work around broken or non-hotplug-aware services, -# it might be enabled unconditionally, or pulled-in on-demand by -# the services that assume a fully populated /dev at startup. It -# should not be used or pulled-in ever on systems without such -# legacy services running. - -[Unit] -Description=udev Wait for Complete Device Initialization -DefaultDependencies=no -Wants=udev.service -After=udev-trigger.service -Before=basic.target - -[Service] -Type=oneshot -TimeoutSec=180 -RemainAfterExit=yes -ExecStart=@bindir@/udevadm settle - -[Install] -WantedBy=basic.target diff --git a/src/udev/src/udev-trigger.service.in b/src/udev/src/udev-trigger.service.in deleted file mode 100644 index cd81945c8..000000000 --- a/src/udev/src/udev-trigger.service.in +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=udev Coldplug all Devices -Wants=udev.service -After=udev-kernel.socket udev-control.socket -DefaultDependencies=no - -[Service] -Type=oneshot -RemainAfterExit=yes -ExecStart=@bindir@/udevadm trigger --type=subsystems --action=add ; @bindir@/udevadm trigger --type=devices --action=add diff --git a/src/udev/src/udev-watch.c b/src/udev/src/udev-watch.c deleted file mode 100644 index 228d18fed..000000000 --- a/src/udev/src/udev-watch.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (C) 2004-2010 Kay Sievers <kay.sievers@vrfy.org> - * Copyright (C) 2009 Canonical Ltd. - * Copyright (C) 2009 Scott James Remnant <scott@netsplit.com> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <sys/types.h> -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <dirent.h> -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/inotify.h> - -#include "udev.h" - -static int inotify_fd = -1; - -/* inotify descriptor, will be shared with rules directory; - * set to cloexec since we need our children to be able to add - * watches for us - */ -int udev_watch_init(struct udev *udev) -{ - inotify_fd = inotify_init1(IN_CLOEXEC); - if (inotify_fd < 0) - err(udev, "inotify_init failed: %m\n"); - return inotify_fd; -} - -/* move any old watches directory out of the way, and then restore - * the watches - */ -void udev_watch_restore(struct udev *udev) -{ - char filename[UTIL_PATH_SIZE], oldname[UTIL_PATH_SIZE]; - - if (inotify_fd < 0) - return; - - util_strscpyl(oldname, sizeof(oldname), udev_get_run_path(udev), "/watch.old", NULL); - util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/watch", NULL); - if (rename(filename, oldname) == 0) { - DIR *dir; - struct dirent *ent; - - dir = opendir(oldname); - if (dir == NULL) { - err(udev, "unable to open old watches dir '%s', old watches will not be restored: %m", oldname); - return; - } - - for (ent = readdir(dir); ent != NULL; ent = readdir(dir)) { - char device[UTIL_PATH_SIZE]; - char *s; - size_t l; - ssize_t len; - struct udev_device *dev; - - if (ent->d_name[0] == '.') - continue; - - s = device; - l = util_strpcpy(&s, sizeof(device), udev_get_sys_path(udev)); - len = readlinkat(dirfd(dir), ent->d_name, s, l); - if (len <= 0 || len == (ssize_t)l) - goto unlink; - s[len] = '\0'; - - dev = udev_device_new_from_id_filename(udev, s); - if (dev == NULL) - goto unlink; - - info(udev, "restoring old watch on '%s'\n", udev_device_get_devnode(dev)); - udev_watch_begin(udev, dev); - udev_device_unref(dev); -unlink: - unlinkat(dirfd(dir), ent->d_name, 0); - } - - closedir(dir); - rmdir(oldname); - - } else if (errno != ENOENT) { - err(udev, "unable to move watches dir '%s', old watches will not be restored: %m", filename); - } -} - -void udev_watch_begin(struct udev *udev, struct udev_device *dev) -{ - char filename[UTIL_PATH_SIZE]; - int wd; - - if (inotify_fd < 0) - return; - - info(udev, "adding watch on '%s'\n", udev_device_get_devnode(dev)); - wd = inotify_add_watch(inotify_fd, udev_device_get_devnode(dev), IN_CLOSE_WRITE); - if (wd < 0) { - err(udev, "inotify_add_watch(%d, %s, %o) failed: %m\n", - inotify_fd, udev_device_get_devnode(dev), IN_CLOSE_WRITE); - return; - } - - snprintf(filename, sizeof(filename), "%s/watch/%d", udev_get_run_path(udev), wd); - util_create_path(udev, filename); - unlink(filename); - symlink(udev_device_get_id_filename(dev), filename); - - udev_device_set_watch_handle(dev, wd); -} - -void udev_watch_end(struct udev *udev, struct udev_device *dev) -{ - int wd; - char filename[UTIL_PATH_SIZE]; - - if (inotify_fd < 0) - return; - - wd = udev_device_get_watch_handle(dev); - if (wd < 0) - return; - - info(udev, "removing watch on '%s'\n", udev_device_get_devnode(dev)); - inotify_rm_watch(inotify_fd, wd); - - snprintf(filename, sizeof(filename), "%s/watch/%d", udev_get_run_path(udev), wd); - unlink(filename); - - udev_device_set_watch_handle(dev, -1); -} - -struct udev_device *udev_watch_lookup(struct udev *udev, int wd) -{ - char filename[UTIL_PATH_SIZE]; - char majmin[UTIL_PATH_SIZE]; - char *s; - size_t l; - ssize_t len; - - if (inotify_fd < 0 || wd < 0) - return NULL; - - snprintf(filename, sizeof(filename), "%s/watch/%d", udev_get_run_path(udev), wd); - s = majmin; - l = util_strpcpy(&s, sizeof(majmin), udev_get_sys_path(udev)); - len = readlink(filename, s, l); - if (len <= 0 || (size_t)len == l) - return NULL; - s[len] = '\0'; - - return udev_device_new_from_id_filename(udev, s); -} diff --git a/src/udev/src/udev.conf b/src/udev/src/udev.conf deleted file mode 100644 index f39253eb6..000000000 --- a/src/udev/src/udev.conf +++ /dev/null @@ -1,3 +0,0 @@ -# see udev(7) for details - -#udev_log="info" diff --git a/src/udev/src/udev.h b/src/udev/src/udev.h deleted file mode 100644 index bc051c9b6..000000000 --- a/src/udev/src/udev.h +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com> - * Copyright (C) 2003-2010 Kay Sievers <kay.sievers@vrfy.org> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _UDEV_H_ -#define _UDEV_H_ - -#include <sys/types.h> -#include <sys/param.h> -#include <signal.h> - -#include "libudev.h" -#include "libudev-private.h" - -struct udev_event { - struct udev *udev; - struct udev_device *dev; - struct udev_device *dev_parent; - struct udev_device *dev_db; - char *name; - char *program_result; - mode_t mode; - uid_t uid; - gid_t gid; - struct udev_list run_list; - int exec_delay; - unsigned long long birth_usec; - unsigned long long timeout_usec; - int fd_signal; - unsigned int builtin_run; - unsigned int builtin_ret; - bool sigterm; - bool inotify_watch; - bool inotify_watch_final; - bool group_final; - bool owner_final; - bool mode_set; - bool mode_final; - bool name_final; - bool devlink_final; - bool run_final; -}; - -struct udev_watch { - struct udev_list_node node; - int handle; - char *name; -}; - -/* udev-rules.c */ -struct udev_rules; -struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names); -struct udev_rules *udev_rules_unref(struct udev_rules *rules); -int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event, const sigset_t *sigmask); -void udev_rules_apply_static_dev_perms(struct udev_rules *rules); - -/* udev-event.c */ -struct udev_event *udev_event_new(struct udev_device *dev); -void udev_event_unref(struct udev_event *event); -size_t udev_event_apply_format(struct udev_event *event, const char *src, char *dest, size_t size); -int udev_event_apply_subsys_kernel(struct udev_event *event, const char *string, - char *result, size_t maxsize, int read_value); -int udev_event_spawn(struct udev_event *event, - const char *cmd, char **envp, const sigset_t *sigmask, - char *result, size_t ressize); -int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules, const sigset_t *sigset); -int udev_event_execute_run(struct udev_event *event, const sigset_t *sigset); -int udev_build_argv(struct udev *udev, char *cmd, int *argc, char *argv[]); - -/* udev-watch.c */ -int udev_watch_init(struct udev *udev); -void udev_watch_restore(struct udev *udev); -void udev_watch_begin(struct udev *udev, struct udev_device *dev); -void udev_watch_end(struct udev *udev, struct udev_device *dev); -struct udev_device *udev_watch_lookup(struct udev *udev, int wd); - -/* udev-node.c */ -void udev_node_add(struct udev_device *dev, mode_t mode, uid_t uid, gid_t gid); -void udev_node_remove(struct udev_device *dev); -void udev_node_update_old_links(struct udev_device *dev, struct udev_device *dev_old); - -/* udev-ctrl.c */ -struct udev_ctrl; -struct udev_ctrl *udev_ctrl_new(struct udev *udev); -struct udev_ctrl *udev_ctrl_new_from_fd(struct udev *udev, 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); -int udev_ctrl_cleanup(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(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(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); - -/* built-in commands */ -enum udev_builtin_cmd { - UDEV_BUILTIN_BLKID, - UDEV_BUILTIN_FIRMWARE, - UDEV_BUILTIN_INPUT_ID, - UDEV_BUILTIN_KMOD, - UDEV_BUILTIN_PATH_ID, - UDEV_BUILTIN_PCI_DB, - UDEV_BUILTIN_USB_DB, - UDEV_BUILTIN_USB_ID, - UDEV_BUILTIN_MAX -}; -struct udev_builtin { - const char *name; - int (*cmd)(struct udev_device *dev, int argc, char *argv[], bool test); - const char *help; - int (*init)(struct udev *udev); - void (*exit)(struct udev *udev); - bool (*validate)(struct udev *udev); - bool run_once; -}; -extern const struct udev_builtin udev_builtin_blkid; -extern const struct udev_builtin udev_builtin_firmware; -extern const struct udev_builtin udev_builtin_input_id; -extern const struct udev_builtin udev_builtin_kmod; -extern const struct udev_builtin udev_builtin_path_id; -extern const struct udev_builtin udev_builtin_pci_db; -extern const struct udev_builtin udev_builtin_usb_db; -extern const struct udev_builtin udev_builtin_usb_id; -int udev_builtin_init(struct udev *udev); -void udev_builtin_exit(struct udev *udev); -enum udev_builtin_cmd udev_builtin_lookup(const char *command); -const char *udev_builtin_name(enum udev_builtin_cmd cmd); -bool udev_builtin_run_once(enum udev_builtin_cmd cmd); -int udev_builtin_run(struct udev_device *dev, enum udev_builtin_cmd cmd, const char *command, bool test); -void udev_builtin_list(struct udev *udev); -int udev_builtin_add_property(struct udev_device *dev, bool test, const char *key, const char *val); - -/* udev logging */ -void udev_main_log(struct udev *udev, int priority, - const char *file, int line, const char *fn, - const char *format, va_list args); - -/* udevadm commands */ -struct udevadm_cmd { - const char *name; - int (*cmd)(struct udev *udev, int argc, char *argv[]); - const char *help; - int debug; -}; -extern const struct udevadm_cmd udevadm_info; -extern const struct udevadm_cmd udevadm_trigger; -extern const struct udevadm_cmd udevadm_settle; -extern const struct udevadm_cmd udevadm_control; -extern const struct udevadm_cmd udevadm_monitor; -extern const struct udevadm_cmd udevadm_test; -extern const struct udevadm_cmd udevadm_test_builtin; -#endif diff --git a/src/udev/src/udev.pc.in b/src/udev/src/udev.pc.in deleted file mode 100644 index 0b04c02ef..000000000 --- a/src/udev/src/udev.pc.in +++ /dev/null @@ -1,5 +0,0 @@ -Name: udev -Description: udev -Version: @VERSION@ - -udevdir=@pkglibexecdir@ diff --git a/src/udev/src/udev.service.in b/src/udev/src/udev.service.in deleted file mode 100644 index c27eb1baf..000000000 --- a/src/udev/src/udev.service.in +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=udev Kernel Device Manager -Wants=udev-control.socket udev-kernel.socket -After=udev-control.socket udev-kernel.socket -Before=basic.target -DefaultDependencies=no -ConditionCapability=CAP_MKNOD - -[Service] -Type=notify -OOMScoreAdjust=-1000 -Sockets=udev-control.socket udev-kernel.socket -Restart=on-failure -ExecStart=@pkglibexecdir@/udevd diff --git a/src/udev/src/udev.xml b/src/udev/src/udev.xml deleted file mode 100644 index 8eb583a82..000000000 --- a/src/udev/src/udev.xml +++ /dev/null @@ -1,695 +0,0 @@ -<?xml version='1.0'?> -<?xml-stylesheet type="text/xsl" href="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"?> -<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" - "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> - -<refentry id="udev"> - <refentryinfo> - <title>udev</title> - <productname>udev</productname> - </refentryinfo> - - <refmeta> - <refentrytitle>udev</refentrytitle> - <manvolnum>7</manvolnum> - </refmeta> - - <refnamediv> - <refname>udev</refname> - <refpurpose>Linux dynamic device management</refpurpose> - </refnamediv> - - <refsect1><title>Description</title> - <para>udev supplies the system software with device events, manages permissions - of device nodes and may create additional symlinks in the <filename>/dev</filename> - directory, or renames network interfaces. The kernel usually just assigns unpredictable - device names based on the order of discovery. Meaningful symlinks or network device - names provide a way to reliably identify devices based on their properties or - current configuration.</para> - - <para>The udev daemon, <citerefentry><refentrytitle>udevd</refentrytitle> - <manvolnum>8</manvolnum></citerefentry>, receives device uevents directly from - the kernel whenever a device is added or removed from the system, or it changes its - state. When udev receives a device event, it matches its configured set of rules - against various device attributes to identify the device. Rules that match may - provide additional device information to be stored in the udev database or - to be used to create meaningful symlink names.</para> - - <para>All device information udev processes is stored in the udev database and - sent out to possible event subscribers. Access to all stored data and the event - sources is provided by the library libudev.</para> - </refsect1> - - <refsect1><title>Configuration</title> - <para>udev configuration files are placed in <filename>/etc/udev</filename> - and <filename>/usr/lib/udev</filename>. All empty lines or lines beginning with - '#' are ignored.</para> - - <refsect2><title>Configuration file</title> - <para>udev expects its main configuration file at <filename>/etc/udev/udev.conf</filename>. - It consists of a set of variables allowing the user to override default udev values. - The following variables can be set:</para> - <variablelist> - <varlistentry> - <term><option>udev_root</option></term> - <listitem> - <para>Specifies where to place the device nodes in the filesystem. - The default value is <filename>/dev</filename>.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>udev_log</option></term> - <listitem> - <para>The logging priority. Valid values are the numerical syslog priorities - or their textual representations: <option>err</option>, <option>info</option> - and <option>debug</option>.</para> - </listitem> - </varlistentry> - </variablelist> - </refsect2> - - <refsect2><title>Rules files</title> - <para>The udev rules are read from the files located in the - system rules directory <filename>/usr/lib/udev/rules.d</filename>, - the volatile runtime directory <filename>/run/udev/rules.d</filename> - and the local administration directory <filename>/etc/udev/rules.d</filename>. - All rules files are collectively sorted and processed in lexical order, - regardless of the directories in which they live. However, files with - identical file names replace each other. Files in <filename>/etc</filename> - have the highest priority, files in <filename>/run</filename> take precedence - over files with the same name in <filename>/lib</filename>. This can be - used to override a system-supplied rules file with a local file if needed; - a symlink in <filename>/etc</filename> with the same name as a rules file in - <filename>/lib</filename>, pointing to <filename>/dev/null</filename>, - disables the rules file entirely.</para> - - <para>Rule files must have the extension <filename>.rules</filename>; other - extensions are ignored.</para> - - <para>Every line in the rules file contains at least one key-value pair. - There are two kind of keys: match and assignment. - If all match keys are matching against its value, the rule gets applied and the - assignment keys get the specified value assigned.</para> - - <para>A matching rule may rename a network interface, add symlinks - pointing to the device node, or run a specified program as part of - the event handling.</para> - - <para>A rule consists of a comma-separated list of one or more key-value pairs. - Each key has a distinct operation, depending on the used operator. Valid - operators are:</para> - <variablelist> - <varlistentry> - <term><option>==</option></term> - <listitem> - <para>Compare for equality.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>!=</option></term> - <listitem> - <para>Compare for inequality.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>=</option></term> - <listitem> - <para>Assign a value to a key. Keys that represent a list are reset - and only this single value is assigned.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>+=</option></term> - <listitem> - <para>Add the value to a key that holds a list of entries.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>:=</option></term> - <listitem> - <para>Assign a value to a key finally; disallow any later changes.</para> - </listitem> - </varlistentry> - </variablelist> - - <para>The following key names can be used to match against device properties. - Some of the keys also match against properties of the parent devices in sysfs, - not only the device that has generated the event. If multiple keys that match - a parent device are specified in a single rule, all these keys must match at - one and the same parent device.</para> - <variablelist> - <varlistentry> - <term><option>ACTION</option></term> - <listitem> - <para>Match the name of the event action.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>DEVPATH</option></term> - <listitem> - <para>Match the devpath of the event device.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>KERNEL</option></term> - <listitem> - <para>Match the name of the event device.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>NAME</option></term> - <listitem> - <para>Match the name of a network interface. It can be used once the - NAME key has been set in one of the preceding rules.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>SYMLINK</option></term> - <listitem> - <para>Match the name of a symlink targeting the node. It can - be used once a SYMLINK key has been set in one of the preceding - rules. There may be multiple symlinks; only one needs to match. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>SUBSYSTEM</option></term> - <listitem> - <para>Match the subsystem of the event device.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>DRIVER</option></term> - <listitem> - <para>Match the driver name of the event device. Only set this key for devices - which are bound to a driver at the time the event is generated.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>ATTR{<replaceable>filename</replaceable>}</option></term> - <listitem> - <para>Match sysfs attribute values of the event device. Trailing - whitespace in the attribute values is ignored unless the specified match - value itself contains trailing whitespace. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>KERNELS</option></term> - <listitem> - <para>Search the devpath upwards for a matching device name.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>SUBSYSTEMS</option></term> - <listitem> - <para>Search the devpath upwards for a matching device subsystem name.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>DRIVERS</option></term> - <listitem> - <para>Search the devpath upwards for a matching device driver name.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>ATTRS{<replaceable>filename</replaceable>}</option></term> - <listitem> - <para>Search the devpath upwards for a device with matching sysfs attribute values. - If multiple <option>ATTRS</option> matches are specified, all of them - must match on the same device. Trailing whitespace in the attribute values is ignored - unless the specified match value itself contains trailing whitespace.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>TAGS</option></term> - <listitem> - <para>Search the devpath upwards for a device with matching tag.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>ENV{<replaceable>key</replaceable>}</option></term> - <listitem> - <para>Match against a device property value.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>TAG</option></term> - <listitem> - <para>Match against a device tag.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>TEST{<replaceable>octal mode mask</replaceable>}</option></term> - <listitem> - <para>Test the existence of a file. An octal mode mask can be specified - if needed.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>PROGRAM</option></term> - <listitem> - <para>Execute a program to determine whether there - is a match; the key is true if the program returns - successfully. The device properties are made available to the - executed program in the environment. The program's stdout - is available in the RESULT key.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>RESULT</option></term> - <listitem> - <para>Match the returned string of the last PROGRAM call. This key can - be used in the same or in any later rule after a PROGRAM call.</para> - </listitem> - </varlistentry> - </variablelist> - - <para>Most of the fields support shell-style pattern matching. The following - pattern characters are supported:</para> - <variablelist> - <varlistentry> - <term><option>*</option></term> - <listitem> - <para>Matches zero or more characters.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>?</option></term> - <listitem> - <para>Matches any single character.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>[]</option></term> - <listitem> - <para>Matches any single character specified within the brackets. For - example, the pattern string 'tty[SR]' would match either 'ttyS' or 'ttyR'. - Ranges are also supported via the '-' character. - For example, to match on the range of all digits, the pattern [0-9] could - be used. If the first character following the '[' is a '!', any characters - not enclosed are matched.</para> - </listitem> - </varlistentry> - </variablelist> - - <para>The following keys can get values assigned:</para> - <variablelist> - <varlistentry> - <term><option>NAME</option></term> - <listitem> - <para>The name to use for a network interface. The name of a device node - can not be changed by udev, only additional symlinks can be created.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>SYMLINK</option></term> - <listitem> - <para>The name of a symlink targeting the node. Every matching rule adds - this value to the list of symlinks to be created. Multiple symlinks may be - specified by separating the names by the space character. In case multiple - devices claim the same name, the link always points to the device with - the highest link_priority. If the current device goes away, the links are - re-evaluated and the device with the next highest link_priority becomes the owner of - the link. If no link_priority is specified, the order of the devices (and - which one of them owns the link) is undefined. Also, symlink names must - never conflict with the kernel's default device node names, as that would - result in unpredictable behavior. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>OWNER, GROUP, MODE</option></term> - <listitem> - <para>The permissions for the device node. Every specified value overrides - the compiled-in default value.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>ATTR{<replaceable>key</replaceable>}</option></term> - <listitem> - <para>The value that should be written to a sysfs attribute of the - event device.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>ENV{<replaceable>key</replaceable>}</option></term> - <listitem> - <para>Set a device property value. Property names with a leading '.' - are neither stored in the database nor exported to events or - external tools (run by, say, the PROGRAM match key).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>TAG</option></term> - <listitem> - <para>Attach a tag to a device. This is used to filter events for users - of libudev's monitor functionality, or to enumerate a group of tagged - devices. The implementation can only work efficiently if only a few - tags are attached to a device. It is only meant to be used in - contexts with specific device filter requirements, and not as a - general-purpose flag. Excessive use might result in inefficient event - handling.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>RUN</option></term> - <listitem> - <para>Add a program to the list of programs to be executed for a specific - device.</para> - <para>If no absolute path is given, the program is expected to live in - /usr/lib/udev, otherwise the absolute path must be specified. The program - name and following arguments are separated by spaces. Single quotes can - be used to specify arguments with spaces.</para> - <para>This can only be used for very short running tasks. Running an - event process for a long period of time may block all further events for - this or a dependent device. Starting daemons or other long running processes - is not appropriate for udev.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>LABEL</option></term> - <listitem> - <para>A named label to which a GOTO may jump.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>GOTO</option></term> - <listitem> - <para>Jumps to the next LABEL with a matching name.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>IMPORT{<replaceable>type</replaceable>}</option></term> - <listitem> - <para>Import a set of variables as device properties, - depending on <replaceable>type</replaceable>:</para> - <variablelist> - <varlistentry> - <term><option>program</option></term> - <listitem> - <para>Execute an external program specified as the assigned value and - import its output, which must be in environment key - format. Path specification, command/argument separation, - and quoting work like in <option>RUN</option>.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>file</option></term> - <listitem> - <para>Import a text file specified as the assigned value, the content - of which must be in environment key format.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>db</option></term> - <listitem> - <para>Import a single property specified as the assigned value from the - current device database. This works only if the database is already populated - by an earlier event.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>cmdline</option></term> - <listitem> - <para>Import a single property from the kernel command line. For simple flags - the value of the property is set to '1'.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>parent</option></term> - <listitem> - <para>Import the stored keys from the parent device by reading - the database entry of the parent device. The value assigned to - <option>IMPORT{parent}</option> is used as a filter of key names - to import (with the same shell-style pattern matching used for - comparisons).</para> - </listitem> - </varlistentry> - </variablelist> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>WAIT_FOR</option></term> - <listitem> - <para>Wait for a file to become available or until a timeout of - 10 seconds expires. The path is relative to the sysfs device; - if no path is specified, this waits for an attribute to appear.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>OPTIONS</option></term> - <listitem> - <para>Rule and device options:</para> - <variablelist> - <varlistentry> - <term><option>link_priority=<replaceable>value</replaceable></option></term> - <listitem> - <para>Specify the priority of the created symlinks. Devices with higher - priorities overwrite existing symlinks of other devices. The default is 0.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>event_timeout=</option></term> - <listitem> - <para>Number of seconds an event waits for operations to finish before - giving up and terminating itself.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>string_escape=<replaceable>none|replace</replaceable></option></term> - <listitem> - <para>Usually control and other possibly unsafe characters are replaced - in strings used for device naming. The mode of replacement can be specified - with this option.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>static_node=</option></term> - <listitem> - <para>Apply the permissions specified in this rule to the static device node with - the specified name. Static device nodes might be provided by kernel modules - or copied from <filename>/usr/lib/udev/devices</filename>. These nodes might not have - a corresponding kernel device at the time udevd is started; they can trigger - automatic kernel module loading.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>watch</option></term> - <listitem> - <para>Watch the device node with inotify; when the node is closed after being opened for - writing, a change uevent is synthesized.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>nowatch</option></term> - <listitem> - <para>Disable the watching of a device node with inotify.</para> - </listitem> - </varlistentry> - </variablelist> - </listitem> - </varlistentry> - </variablelist> - - <para>The <option>NAME</option>, <option>SYMLINK</option>, <option>PROGRAM</option>, - <option>OWNER</option>, <option>GROUP</option>, <option>MODE</option> and <option>RUN</option> - fields support simple string substitutions. The <option>RUN</option> - substitutions are performed after all rules have been processed, right before the program - is executed, allowing for the use of device properties set by earlier matching - rules. For all other fields, substitutions are performed while the individual rule is - being processed. The available substitutions are:</para> - <variablelist> - <varlistentry> - <term><option>$kernel</option>, <option>%k</option></term> - <listitem> - <para>The kernel name for this device.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>$number</option>, <option>%n</option></term> - <listitem> - <para>The kernel number for this device. For example, 'sda3' has - kernel number of '3'</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>$devpath</option>, <option>%p</option></term> - <listitem> - <para>The devpath of the device.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>$id</option>, <option>%b</option></term> - <listitem> - <para>The name of the device matched while searching the devpath upwards for - <option>SUBSYSTEMS</option>, <option>KERNELS</option>, <option>DRIVERS</option> and <option>ATTRS</option>. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>$driver</option></term> - <listitem> - <para>The driver name of the device matched while searching the devpath upwards for - <option>SUBSYSTEMS</option>, <option>KERNELS</option>, <option>DRIVERS</option> and <option>ATTRS</option>. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>$attr{<replaceable>file</replaceable>}</option>, <option>%s{<replaceable>file</replaceable>}</option></term> - <listitem> - <para>The value of a sysfs attribute found at the device where - all keys of the rule have matched. If the matching device does not have - such an attribute, and a previous KERNELS, SUBSYSTEMS, DRIVERS, or - ATTRS test selected a parent device, then the attribute from that - parent device is used.</para> - <para>If the attribute is a symlink, the last element of the symlink target is - returned as the value.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>$env{<replaceable>key</replaceable>}</option>, <option>%E{<replaceable>key</replaceable>}</option></term> - <listitem> - <para>A device property value.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>$major</option>, <option>%M</option></term> - <listitem> - <para>The kernel major number for the device.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>$minor</option>, <option>%m</option></term> - <listitem> - <para>The kernel minor number for the device.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>$result</option>, <option>%c</option></term> - <listitem> - <para>The string returned by the external program requested with PROGRAM. - A single part of the string, separated by a space character, may be selected - by specifying the part number as an attribute: <option>%c{N}</option>. - If the number is followed by the '+' character, this part plus all remaining parts - of the result string are substituted: <option>%c{N+}</option></para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>$parent</option>, <option>%P</option></term> - <listitem> - <para>The node name of the parent device.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>$name</option></term> - <listitem> - <para>The current name of the device. If not changed by a rule, it is the - name of the kernel device.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>$links</option></term> - <listitem> - <para>A space-separated list of the current symlinks. The value is - only set during a remove event or if an earlier rule assigned a value.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>$root</option>, <option>%r</option></term> - <listitem> - <para>The udev_root value.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>$sys</option>, <option>%S</option></term> - <listitem> - <para>The sysfs mount point.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>$devnode</option>, <option>%N</option></term> - <listitem> - <para>The name of the device node.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>%%</option></term> - <listitem> - <para>The '%' character itself.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>$$</option></term> - <listitem> - <para>The '$' character itself.</para> - </listitem> - </varlistentry> - </variablelist> - </refsect2> - </refsect1> - - <refsect1><title>Author</title> - <para>Written by Greg Kroah-Hartman <email>greg@kroah.com</email> and - Kay Sievers <email>kay.sievers@vrfy.org</email>. With much help from - Dan Stekloff and many others.</para> - </refsect1> - - <refsect1> - <title>See Also</title> - <para><citerefentry> - <refentrytitle>udevd</refentrytitle><manvolnum>8</manvolnum> - </citerefentry>, - <citerefentry> - <refentrytitle>udevadm</refentrytitle><manvolnum>8</manvolnum> - </citerefentry></para> - </refsect1> -</refentry> diff --git a/src/udev/src/udevadm-control.c b/src/udev/src/udevadm-control.c deleted file mode 100644 index cafa21494..000000000 --- a/src/udev/src/udevadm-control.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (C) 2005-2011 Kay Sievers <kay.sievers@vrfy.org> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - */ - -#include <time.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <unistd.h> -#include <getopt.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/wait.h> -#include <sys/un.h> - -#include "udev.h" - -static void print_help(void) -{ - printf("Usage: udevadm control COMMAND\n" - " --exit instruct the daemon to cleanup and exit\n" - " --log-priority=<level> set the udev log level for the daemon\n" - " --stop-exec-queue do not execute events, queue only\n" - " --start-exec-queue execute events, flush queue\n" - " --reload reload rules and databases\n" - " --property=<KEY>=<value> set a global property for all events\n" - " --children-max=<N> maximum number of children\n" - " --timeout=<seconds> maximum time to block for a reply\n" - " --help print this help text\n\n"); -} - -static int adm_control(struct udev *udev, int argc, char *argv[]) -{ - struct udev_ctrl *uctrl = NULL; - int timeout = 60; - int rc = 1; - - static const struct option options[] = { - { "exit", no_argument, NULL, 'e' }, - { "log-priority", required_argument, NULL, 'l' }, - { "stop-exec-queue", no_argument, NULL, 's' }, - { "start-exec-queue", no_argument, NULL, 'S' }, - { "reload", no_argument, NULL, 'R' }, - { "reload-rules", no_argument, NULL, 'R' }, - { "property", required_argument, NULL, 'p' }, - { "env", required_argument, NULL, 'p' }, - { "children-max", required_argument, NULL, 'm' }, - { "timeout", required_argument, NULL, 't' }, - { "help", no_argument, NULL, 'h' }, - {} - }; - - if (getuid() != 0) { - fprintf(stderr, "root privileges required\n"); - return 1; - } - - uctrl = udev_ctrl_new(udev); - if (uctrl == NULL) - return 2; - - for (;;) { - int option; - - option = getopt_long(argc, argv, "el:sSRp:m:h", options, NULL); - if (option == -1) - break; - - switch (option) { - case 'e': - if (udev_ctrl_send_exit(uctrl, timeout) < 0) - rc = 2; - else - rc = 0; - break; - case 'l': { - int i; - - i = util_log_priority(optarg); - if (i < 0) { - fprintf(stderr, "invalid number '%s'\n", optarg); - goto out; - } - if (udev_ctrl_send_set_log_level(uctrl, util_log_priority(optarg), timeout) < 0) - rc = 2; - else - rc = 0; - break; - } - case 's': - if (udev_ctrl_send_stop_exec_queue(uctrl, timeout) < 0) - rc = 2; - else - rc = 0; - break; - case 'S': - if (udev_ctrl_send_start_exec_queue(uctrl, timeout) < 0) - rc = 2; - else - rc = 0; - break; - case 'R': - if (udev_ctrl_send_reload(uctrl, timeout) < 0) - rc = 2; - else - rc = 0; - break; - case 'p': - if (strchr(optarg, '=') == NULL) { - fprintf(stderr, "expect <KEY>=<value> instead of '%s'\n", optarg); - goto out; - } - if (udev_ctrl_send_set_env(uctrl, optarg, timeout) < 0) - rc = 2; - else - rc = 0; - break; - case 'm': { - char *endp; - int i; - - i = strtoul(optarg, &endp, 0); - if (endp[0] != '\0' || i < 1) { - fprintf(stderr, "invalid number '%s'\n", optarg); - goto out; - } - if (udev_ctrl_send_set_children_max(uctrl, i, timeout) < 0) - rc = 2; - else - rc = 0; - break; - } - case 't': { - int seconds; - - seconds = atoi(optarg); - if (seconds >= 0) - timeout = seconds; - else - fprintf(stderr, "invalid timeout value\n"); - break; - } - case 'h': - print_help(); - rc = 0; - break; - } - } - - if (argv[optind] != NULL) - fprintf(stderr, "unknown option\n"); - else if (optind == 1) - fprintf(stderr, "missing option\n"); -out: - udev_ctrl_unref(uctrl); - return rc; -} - -const struct udevadm_cmd udevadm_control = { - .name = "control", - .cmd = adm_control, - .help = "control the udev daemon", -}; diff --git a/src/udev/src/udevadm-info.c b/src/udev/src/udevadm-info.c deleted file mode 100644 index ee9b59fea..000000000 --- a/src/udev/src/udevadm-info.c +++ /dev/null @@ -1,568 +0,0 @@ -/* - * Copyright (C) 2004-2009 Kay Sievers <kay.sievers@vrfy.org> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <stddef.h> -#include <ctype.h> -#include <stdarg.h> -#include <unistd.h> -#include <dirent.h> -#include <errno.h> -#include <getopt.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include "udev.h" - -static bool skip_attribute(const char *name) -{ - static const char const *skip[] = { - "uevent", - "dev", - "modalias", - "resource", - "driver", - "subsystem", - "module", - }; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(skip); i++) - if (strcmp(name, skip[i]) == 0) - return true; - return false; -} - -static void print_all_attributes(struct udev_device *device, const char *key) -{ - struct udev *udev = udev_device_get_udev(device); - struct udev_list_entry *sysattr; - - udev_list_entry_foreach(sysattr, udev_device_get_sysattr_list_entry(device)) { - const char *name; - const char *value; - size_t len; - - name = udev_list_entry_get_name(sysattr); - if (skip_attribute(name)) - continue; - - value = udev_device_get_sysattr_value(device, name); - if (value == NULL) - continue; - dbg(udev, "attr '%s'='%s'\n", name, value); - - /* skip any values that look like a path */ - if (value[0] == '/') - continue; - - /* skip nonprintable attributes */ - len = strlen(value); - while (len > 0 && isprint(value[len-1])) - len--; - if (len > 0) { - dbg(udev, "attribute value of '%s' non-printable, skip\n", name); - continue; - } - - printf(" %s{%s}==\"%s\"\n", key, name, value); - } - printf("\n"); -} - -static int print_device_chain(struct udev_device *device) -{ - struct udev_device *device_parent; - const char *str; - - printf("\n" - "Udevadm info starts with the device specified by the devpath and then\n" - "walks up the chain of parent devices. It prints for every device\n" - "found, all possible attributes in the udev rules key format.\n" - "A rule to match, can be composed by the attributes of the device\n" - "and the attributes from one single parent device.\n" - "\n"); - - printf(" looking at device '%s':\n", udev_device_get_devpath(device)); - printf(" KERNEL==\"%s\"\n", udev_device_get_sysname(device)); - str = udev_device_get_subsystem(device); - if (str == NULL) - str = ""; - printf(" SUBSYSTEM==\"%s\"\n", str); - str = udev_device_get_driver(device); - if (str == NULL) - str = ""; - printf(" DRIVER==\"%s\"\n", str); - print_all_attributes(device, "ATTR"); - - device_parent = device; - do { - device_parent = udev_device_get_parent(device_parent); - if (device_parent == NULL) - break; - printf(" looking at parent device '%s':\n", udev_device_get_devpath(device_parent)); - printf(" KERNELS==\"%s\"\n", udev_device_get_sysname(device_parent)); - str = udev_device_get_subsystem(device_parent); - if (str == NULL) - str = ""; - printf(" SUBSYSTEMS==\"%s\"\n", str); - str = udev_device_get_driver(device_parent); - if (str == NULL) - str = ""; - printf(" DRIVERS==\"%s\"\n", str); - print_all_attributes(device_parent, "ATTRS"); - } while (device_parent != NULL); - - return 0; -} - -static void print_record(struct udev_device *device) -{ - size_t len; - const char *str; - int i; - struct udev_list_entry *list_entry; - - printf("P: %s\n", udev_device_get_devpath(device)); - - len = strlen(udev_get_dev_path(udev_device_get_udev(device))); - str = udev_device_get_devnode(device); - if (str != NULL) - printf("N: %s\n", &str[len+1]); - - i = udev_device_get_devlink_priority(device); - if (i != 0) - printf("L: %i\n", i); - - udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(device)) { - len = strlen(udev_get_dev_path(udev_device_get_udev(device))); - printf("S: %s\n", &udev_list_entry_get_name(list_entry)[len+1]); - } - - udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(device)) - printf("E: %s=%s\n", - udev_list_entry_get_name(list_entry), - udev_list_entry_get_value(list_entry)); - printf("\n"); -} - -static int stat_device(const char *name, bool export, const char *prefix) -{ - struct stat statbuf; - - if (stat(name, &statbuf) != 0) - return -1; - - if (export) { - if (prefix == NULL) - prefix = "INFO_"; - printf("%sMAJOR=%d\n" - "%sMINOR=%d\n", - prefix, major(statbuf.st_dev), - prefix, minor(statbuf.st_dev)); - } else - printf("%d:%d\n", major(statbuf.st_dev), minor(statbuf.st_dev)); - return 0; -} - -static int export_devices(struct udev *udev) -{ - struct udev_enumerate *udev_enumerate; - struct udev_list_entry *list_entry; - - udev_enumerate = udev_enumerate_new(udev); - if (udev_enumerate == NULL) - return -1; - udev_enumerate_scan_devices(udev_enumerate); - udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(udev_enumerate)) { - struct udev_device *device; - - device = udev_device_new_from_syspath(udev, udev_list_entry_get_name(list_entry)); - if (device != NULL) { - print_record(device); - udev_device_unref(device); - } - } - udev_enumerate_unref(udev_enumerate); - return 0; -} - -static void cleanup_dir(DIR *dir, mode_t mask, int depth) -{ - struct dirent *dent; - - if (depth <= 0) - return; - - for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { - struct stat stats; - - if (dent->d_name[0] == '.') - continue; - if (fstatat(dirfd(dir), dent->d_name, &stats, AT_SYMLINK_NOFOLLOW) != 0) - continue; - if ((stats.st_mode & mask) != 0) - continue; - if (S_ISDIR(stats.st_mode)) { - DIR *dir2; - - dir2 = fdopendir(openat(dirfd(dir), dent->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC)); - if (dir2 != NULL) { - cleanup_dir(dir2, mask, depth-1); - closedir(dir2); - } - unlinkat(dirfd(dir), dent->d_name, AT_REMOVEDIR); - } else { - unlinkat(dirfd(dir), dent->d_name, 0); - } - } -} - -static void cleanup_db(struct udev *udev) -{ - char filename[UTIL_PATH_SIZE]; - DIR *dir; - - util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/queue.bin", NULL); - unlink(filename); - - util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/data", NULL); - dir = opendir(filename); - if (dir != NULL) { - cleanup_dir(dir, S_ISVTX, 1); - closedir(dir); - } - - util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/links", NULL); - dir = opendir(filename); - if (dir != NULL) { - cleanup_dir(dir, 0, 2); - closedir(dir); - } - - util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/tags", NULL); - dir = opendir(filename); - if (dir != NULL) { - cleanup_dir(dir, 0, 2); - closedir(dir); - } - - util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/watch", NULL); - dir = opendir(filename); - if (dir != NULL) { - cleanup_dir(dir, 0, 1); - closedir(dir); - } - - util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/firmware-missing", NULL); - dir = opendir(filename); - if (dir != NULL) { - cleanup_dir(dir, 0, 1); - closedir(dir); - } -} - -static int uinfo(struct udev *udev, int argc, char *argv[]) -{ - struct udev_device *device = NULL; - bool root = 0; - bool export = 0; - const char *export_prefix = NULL; - char path[UTIL_PATH_SIZE]; - char name[UTIL_PATH_SIZE]; - struct udev_list_entry *list_entry; - int rc = 0; - - static const struct option options[] = { - { "name", required_argument, NULL, 'n' }, - { "path", required_argument, NULL, 'p' }, - { "query", required_argument, NULL, 'q' }, - { "attribute-walk", no_argument, NULL, 'a' }, - { "cleanup-db", no_argument, NULL, 'c' }, - { "export-db", no_argument, NULL, 'e' }, - { "root", no_argument, NULL, 'r' }, - { "run", no_argument, NULL, 'R' }, - { "device-id-of-file", required_argument, NULL, 'd' }, - { "export", no_argument, NULL, 'x' }, - { "export-prefix", required_argument, NULL, 'P' }, - { "version", no_argument, NULL, 'V' }, - { "help", no_argument, NULL, 'h' }, - {} - }; - - enum action_type { - ACTION_NONE, - ACTION_QUERY, - ACTION_ATTRIBUTE_WALK, - ACTION_ROOT, - ACTION_DEVICE_ID_FILE, - } action = ACTION_NONE; - - enum query_type { - QUERY_NONE, - QUERY_NAME, - QUERY_PATH, - QUERY_SYMLINK, - QUERY_PROPERTY, - QUERY_ALL, - } query = QUERY_NONE; - - for (;;) { - int option; - struct stat statbuf; - - option = getopt_long(argc, argv, "aced:n:p:q:rxP:RVh", options, NULL); - if (option == -1) - break; - - dbg(udev, "option '%c'\n", option); - switch (option) { - case 'n': - if (device != NULL) { - fprintf(stderr, "device already specified\n"); - rc = 2; - goto exit; - } - /* remove /dev if given */ - if (strncmp(optarg, udev_get_dev_path(udev), strlen(udev_get_dev_path(udev))) != 0) - util_strscpyl(name, sizeof(name), udev_get_dev_path(udev), "/", optarg, NULL); - else - util_strscpy(name, sizeof(name), optarg); - util_remove_trailing_chars(name, '/'); - if (stat(name, &statbuf) < 0) { - fprintf(stderr, "device node not found\n"); - rc = 2; - goto exit; - } else { - char type; - - if (S_ISBLK(statbuf.st_mode)) { - type = 'b'; - } else if (S_ISCHR(statbuf.st_mode)) { - type = 'c'; - } else { - fprintf(stderr, "device node has wrong file type\n"); - rc = 2; - goto exit; - } - device = udev_device_new_from_devnum(udev, type, statbuf.st_rdev); - if (device == NULL) { - fprintf(stderr, "device node not found\n"); - rc = 2; - goto exit; - } - } - break; - case 'p': - if (device != NULL) { - fprintf(stderr, "device already specified\n"); - rc = 2; - goto exit; - } - /* add sys dir if needed */ - if (strncmp(optarg, udev_get_sys_path(udev), strlen(udev_get_sys_path(udev))) != 0) - util_strscpyl(path, sizeof(path), udev_get_sys_path(udev), optarg, NULL); - else - util_strscpy(path, sizeof(path), optarg); - util_remove_trailing_chars(path, '/'); - device = udev_device_new_from_syspath(udev, path); - if (device == NULL) { - fprintf(stderr, "device path not found\n"); - rc = 2; - goto exit; - } - break; - case 'q': - action = ACTION_QUERY; - if (strcmp(optarg, "property") == 0 || strcmp(optarg, "env") == 0) { - query = QUERY_PROPERTY; - } else if (strcmp(optarg, "name") == 0) { - query = QUERY_NAME; - } else if (strcmp(optarg, "symlink") == 0) { - query = QUERY_SYMLINK; - } else if (strcmp(optarg, "path") == 0) { - query = QUERY_PATH; - } else if (strcmp(optarg, "all") == 0) { - query = QUERY_ALL; - } else { - fprintf(stderr, "unknown query type\n"); - rc = 3; - goto exit; - } - break; - case 'r': - if (action == ACTION_NONE) - action = ACTION_ROOT; - root = true; - break; - case 'R': - printf("%s\n", udev_get_run_path(udev)); - goto exit; - case 'd': - action = ACTION_DEVICE_ID_FILE; - util_strscpy(name, sizeof(name), optarg); - break; - case 'a': - action = ACTION_ATTRIBUTE_WALK; - break; - case 'e': - export_devices(udev); - goto exit; - case 'c': - cleanup_db(udev); - goto exit; - case 'x': - export = true; - break; - case 'P': - export_prefix = optarg; - break; - case 'V': - printf("%s\n", VERSION); - goto exit; - case 'h': - printf("Usage: udevadm info OPTIONS\n" - " --query=<type> query device information:\n" - " name name of device node\n" - " symlink pointing to node\n" - " path sys device path\n" - " property the device properties\n" - " all all values\n" - " --path=<syspath> sys device path used for query or attribute walk\n" - " --name=<name> node or symlink name used for query or attribute walk\n" - " --root prepend dev directory to path names\n" - " --attribute-walk print all key matches while walking along the chain\n" - " of parent devices\n" - " --device-id-of-file=<file> print major:minor of device containing this file\n" - " --export export key/value pairs\n" - " --export-prefix export the key name with a prefix\n" - " --export-db export the content of the udev database\n" - " --cleanup-db cleanup the udev database\n" - " --help\n\n"); - goto exit; - default: - rc = 1; - goto exit; - } - } - - switch (action) { - case ACTION_QUERY: - if (device == NULL) { - fprintf(stderr, "query needs a valid device specified by --path= or --name=\n"); - rc = 4; - goto exit; - } - - switch(query) { - case QUERY_NAME: { - const char *node = udev_device_get_devnode(device); - - if (node == NULL) { - fprintf(stderr, "no device node found\n"); - rc = 5; - goto exit; - } - - if (root) { - printf("%s\n", udev_device_get_devnode(device)); - } else { - size_t len = strlen(udev_get_dev_path(udev)); - - printf("%s\n", &udev_device_get_devnode(device)[len+1]); - } - break; - } - case QUERY_SYMLINK: - list_entry = udev_device_get_devlinks_list_entry(device); - while (list_entry != NULL) { - if (root) { - printf("%s", udev_list_entry_get_name(list_entry)); - } else { - size_t len; - - len = strlen(udev_get_dev_path(udev_device_get_udev(device))); - printf("%s", &udev_list_entry_get_name(list_entry)[len+1]); - } - list_entry = udev_list_entry_get_next(list_entry); - if (list_entry != NULL) - printf(" "); - } - printf("\n"); - break; - case QUERY_PATH: - printf("%s\n", udev_device_get_devpath(device)); - goto exit; - case QUERY_PROPERTY: - list_entry = udev_device_get_properties_list_entry(device); - while (list_entry != NULL) { - if (export) { - const char *prefix = export_prefix; - - if (prefix == NULL) - prefix = ""; - printf("%s%s='%s'\n", prefix, - udev_list_entry_get_name(list_entry), - udev_list_entry_get_value(list_entry)); - } else { - printf("%s=%s\n", udev_list_entry_get_name(list_entry), udev_list_entry_get_value(list_entry)); - } - list_entry = udev_list_entry_get_next(list_entry); - } - break; - case QUERY_ALL: - print_record(device); - break; - default: - fprintf(stderr, "unknown query type\n"); - break; - } - break; - case ACTION_ATTRIBUTE_WALK: - if (device == NULL) { - fprintf(stderr, "query needs a valid device specified by --path= or --name=\n"); - rc = 4; - goto exit; - } - print_device_chain(device); - break; - case ACTION_DEVICE_ID_FILE: - if (stat_device(name, export, export_prefix) != 0) - rc = 1; - break; - case ACTION_ROOT: - printf("%s\n", udev_get_dev_path(udev)); - break; - default: - fprintf(stderr, "missing option\n"); - rc = 1; - break; - } - -exit: - udev_device_unref(device); - return rc; -} - -const struct udevadm_cmd udevadm_info = { - .name = "info", - .cmd = uinfo, - .help = "query sysfs or the udev database", -}; diff --git a/src/udev/src/udevadm-monitor.c b/src/udev/src/udevadm-monitor.c deleted file mode 100644 index 5997dd8e1..000000000 --- a/src/udev/src/udevadm-monitor.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright (C) 2004-2010 Kay Sievers <kay.sievers@vrfy.org> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#include <signal.h> -#include <getopt.h> -#include <time.h> -#include <sys/time.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <sys/epoll.h> -#include <linux/types.h> -#include <linux/netlink.h> - -#include "udev.h" - -static bool udev_exit; - -static void sig_handler(int signum) -{ - if (signum == SIGINT || signum == SIGTERM) - udev_exit = true; -} - -static void print_device(struct udev_device *device, const char *source, int prop) -{ - struct timespec ts; - - clock_gettime(CLOCK_MONOTONIC, &ts); - printf("%-6s[%llu.%06u] %-8s %s (%s)\n", - source, - (unsigned long long) ts.tv_sec, (unsigned int) ts.tv_nsec/1000, - udev_device_get_action(device), - udev_device_get_devpath(device), - udev_device_get_subsystem(device)); - if (prop) { - struct udev_list_entry *list_entry; - - udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(device)) - printf("%s=%s\n", - udev_list_entry_get_name(list_entry), - udev_list_entry_get_value(list_entry)); - printf("\n"); - } -} - -static int adm_monitor(struct udev *udev, int argc, char *argv[]) -{ - struct sigaction act; - sigset_t mask; - int option; - bool prop = false; - bool print_kernel = false; - bool print_udev = false; - struct udev_list subsystem_match_list; - struct udev_list tag_match_list; - struct udev_monitor *udev_monitor = NULL; - struct udev_monitor *kernel_monitor = NULL; - int fd_ep = -1; - int fd_kernel = -1, fd_udev = -1; - struct epoll_event ep_kernel, ep_udev; - int rc = 0; - - static const struct option options[] = { - { "property", no_argument, NULL, 'p' }, - { "environment", no_argument, NULL, 'e' }, - { "kernel", no_argument, NULL, 'k' }, - { "udev", no_argument, NULL, 'u' }, - { "subsystem-match", required_argument, NULL, 's' }, - { "tag-match", required_argument, NULL, 't' }, - { "help", no_argument, NULL, 'h' }, - {} - }; - - udev_list_init(udev, &subsystem_match_list, true); - udev_list_init(udev, &tag_match_list, true); - - for (;;) { - option = getopt_long(argc, argv, "pekus:t:h", options, NULL); - if (option == -1) - break; - - switch (option) { - case 'p': - case 'e': - prop = true; - break; - case 'k': - print_kernel = true; - break; - case 'u': - print_udev = true; - break; - case 's': - { - char subsys[UTIL_NAME_SIZE]; - char *devtype; - - util_strscpy(subsys, sizeof(subsys), optarg); - devtype = strchr(subsys, '/'); - if (devtype != NULL) { - devtype[0] = '\0'; - devtype++; - } - udev_list_entry_add(&subsystem_match_list, subsys, devtype); - break; - } - case 't': - udev_list_entry_add(&tag_match_list, optarg, NULL); - break; - case 'h': - printf("Usage: udevadm monitor [--property] [--kernel] [--udev] [--help]\n" - " --property print the event properties\n" - " --kernel print kernel uevents\n" - " --udev print udev events\n" - " --subsystem-match=<subsystem[/devtype]> filter events by subsystem\n" - " --tag-match=<tag> filter events by tag\n" - " --help\n\n"); - goto out; - default: - rc = 1; - goto out; - } - } - - if (!print_kernel && !print_udev) { - print_kernel = true; - print_udev = true; - } - - /* set signal handlers */ - memset(&act, 0x00, sizeof(struct sigaction)); - act.sa_handler = sig_handler; - sigemptyset(&act.sa_mask); - act.sa_flags = SA_RESTART; - sigaction(SIGINT, &act, NULL); - sigaction(SIGTERM, &act, NULL); - sigemptyset(&mask); - sigaddset(&mask, SIGINT); - sigaddset(&mask, SIGTERM); - sigprocmask(SIG_UNBLOCK, &mask, NULL); - - fd_ep = epoll_create1(EPOLL_CLOEXEC); - if (fd_ep < 0) { - err(udev, "error creating epoll fd: %m\n"); - goto out; - } - - printf("monitor will print the received events for:\n"); - if (print_udev) { - struct udev_list_entry *entry; - - udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); - if (udev_monitor == NULL) { - fprintf(stderr, "error: unable to create netlink socket\n"); - rc = 1; - goto out; - } - udev_monitor_set_receive_buffer_size(udev_monitor, 128*1024*1024); - fd_udev = udev_monitor_get_fd(udev_monitor); - - udev_list_entry_foreach(entry, udev_list_get_entry(&subsystem_match_list)) { - const char *subsys = udev_list_entry_get_name(entry); - const char *devtype = udev_list_entry_get_value(entry); - - if (udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, subsys, devtype) < 0) - fprintf(stderr, "error: unable to apply subsystem filter '%s'\n", subsys); - } - - udev_list_entry_foreach(entry, udev_list_get_entry(&tag_match_list)) { - const char *tag = udev_list_entry_get_name(entry); - - if (udev_monitor_filter_add_match_tag(udev_monitor, tag) < 0) - fprintf(stderr, "error: unable to apply tag filter '%s'\n", tag); - } - - if (udev_monitor_enable_receiving(udev_monitor) < 0) { - fprintf(stderr, "error: unable to subscribe to udev events\n"); - rc = 2; - goto out; - } - - memset(&ep_udev, 0, sizeof(struct epoll_event)); - ep_udev.events = EPOLLIN; - ep_udev.data.fd = fd_udev; - if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) < 0) { - err(udev, "fail to add fd to epoll: %m\n"); - goto out; - } - - printf("UDEV - the event which udev sends out after rule processing\n"); - } - - if (print_kernel) { - struct udev_list_entry *entry; - - kernel_monitor = udev_monitor_new_from_netlink(udev, "kernel"); - if (kernel_monitor == NULL) { - fprintf(stderr, "error: unable to create netlink socket\n"); - rc = 3; - goto out; - } - udev_monitor_set_receive_buffer_size(kernel_monitor, 128*1024*1024); - fd_kernel = udev_monitor_get_fd(kernel_monitor); - - udev_list_entry_foreach(entry, udev_list_get_entry(&subsystem_match_list)) { - const char *subsys = udev_list_entry_get_name(entry); - - if (udev_monitor_filter_add_match_subsystem_devtype(kernel_monitor, subsys, NULL) < 0) - fprintf(stderr, "error: unable to apply subsystem filter '%s'\n", subsys); - } - - if (udev_monitor_enable_receiving(kernel_monitor) < 0) { - fprintf(stderr, "error: unable to subscribe to kernel events\n"); - rc = 4; - goto out; - } - - memset(&ep_kernel, 0, sizeof(struct epoll_event)); - ep_kernel.events = EPOLLIN; - ep_kernel.data.fd = fd_kernel; - if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_kernel, &ep_kernel) < 0) { - err(udev, "fail to add fd to epoll: %m\n"); - goto out; - } - - printf("KERNEL - the kernel uevent\n"); - } - printf("\n"); - - while (!udev_exit) { - int fdcount; - struct epoll_event ev[4]; - int i; - - fdcount = epoll_wait(fd_ep, ev, ARRAY_SIZE(ev), -1); - if (fdcount < 0) { - if (errno != EINTR) - fprintf(stderr, "error receiving uevent message: %m\n"); - continue; - } - - for (i = 0; i < fdcount; i++) { - if (ev[i].data.fd == fd_kernel && ev[i].events & EPOLLIN) { - struct udev_device *device; - - device = udev_monitor_receive_device(kernel_monitor); - if (device == NULL) - continue; - print_device(device, "KERNEL", prop); - udev_device_unref(device); - } else if (ev[i].data.fd == fd_udev && ev[i].events & EPOLLIN) { - struct udev_device *device; - - device = udev_monitor_receive_device(udev_monitor); - if (device == NULL) - continue; - print_device(device, "UDEV", prop); - udev_device_unref(device); - } - } - } -out: - if (fd_ep >= 0) - close(fd_ep); - udev_monitor_unref(udev_monitor); - udev_monitor_unref(kernel_monitor); - udev_list_cleanup(&subsystem_match_list); - udev_list_cleanup(&tag_match_list); - return rc; -} - -const struct udevadm_cmd udevadm_monitor = { - .name = "monitor", - .cmd = adm_monitor, - .help = "listen to kernel and udev events", -}; diff --git a/src/udev/src/udevadm-settle.c b/src/udev/src/udevadm-settle.c deleted file mode 100644 index b168defd9..000000000 --- a/src/udev/src/udevadm-settle.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (C) 2006-2009 Kay Sievers <kay@vrfy.org> - * Copyright (C) 2009 Canonical Ltd. - * Copyright (C) 2009 Scott James Remnant <scott@netsplit.com> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <stdio.h> -#include <unistd.h> -#include <errno.h> -#include <dirent.h> -#include <fcntl.h> -#include <syslog.h> -#include <getopt.h> -#include <signal.h> -#include <time.h> -#include <sys/inotify.h> -#include <sys/poll.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include "udev.h" - -static int adm_settle(struct udev *udev, int argc, char *argv[]) -{ - static const struct option options[] = { - { "seq-start", required_argument, NULL, 's' }, - { "seq-end", required_argument, NULL, 'e' }, - { "timeout", required_argument, NULL, 't' }, - { "exit-if-exists", required_argument, NULL, 'E' }, - { "quiet", no_argument, NULL, 'q' }, - { "help", no_argument, NULL, 'h' }, - {} - }; - unsigned long long start_usec = now_usec(); - unsigned long long start = 0; - unsigned long long end = 0; - int quiet = 0; - const char *exists = NULL; - unsigned int timeout = 120; - struct pollfd pfd[1]; - struct udev_queue *udev_queue = NULL; - int rc = EXIT_FAILURE; - - dbg(udev, "version %s\n", VERSION); - - for (;;) { - int option; - int seconds; - - option = getopt_long(argc, argv, "s:e:t:E:qh", options, NULL); - if (option == -1) - break; - - switch (option) { - case 's': - start = strtoull(optarg, NULL, 0); - break; - case 'e': - end = strtoull(optarg, NULL, 0); - break; - case 't': - seconds = atoi(optarg); - if (seconds >= 0) - timeout = seconds; - else - fprintf(stderr, "invalid timeout value\n"); - dbg(udev, "timeout=%i\n", timeout); - break; - case 'q': - quiet = 1; - break; - case 'E': - exists = optarg; - break; - case 'h': - printf("Usage: udevadm settle OPTIONS\n" - " --timeout=<seconds> maximum time to wait for events\n" - " --seq-start=<seqnum> first seqnum to wait for\n" - " --seq-end=<seqnum> last seqnum to wait for\n" - " --exit-if-exists=<file> stop waiting if file exists\n" - " --quiet do not print list after timeout\n" - " --help\n\n"); - exit(EXIT_SUCCESS); - default: - exit(EXIT_FAILURE); - } - } - - udev_queue = udev_queue_new(udev); - if (udev_queue == NULL) - exit(2); - - if (start > 0) { - unsigned long long kernel_seq; - - kernel_seq = udev_queue_get_kernel_seqnum(udev_queue); - - /* unless specified, the last event is the current kernel seqnum */ - if (end == 0) - end = udev_queue_get_kernel_seqnum(udev_queue); - - if (start > end) { - err(udev, "seq-start larger than seq-end, ignoring\n"); - start = 0; - end = 0; - } - - if (start > kernel_seq || end > kernel_seq) { - err(udev, "seq-start or seq-end larger than current kernel value, ignoring\n"); - start = 0; - end = 0; - } - info(udev, "start=%llu end=%llu current=%llu\n", start, end, kernel_seq); - } else { - if (end > 0) { - err(udev, "seq-end needs seq-start parameter, ignoring\n"); - end = 0; - } - } - - /* guarantee that the udev daemon isn't pre-processing */ - if (getuid() == 0) { - struct udev_ctrl *uctrl; - - uctrl = udev_ctrl_new(udev); - if (uctrl != NULL) { - if (udev_ctrl_send_ping(uctrl, timeout) < 0) { - info(udev, "no connection to daemon\n"); - udev_ctrl_unref(uctrl); - rc = EXIT_SUCCESS; - goto out; - } - udev_ctrl_unref(uctrl); - } - } - - pfd[0].events = POLLIN; - pfd[0].fd = inotify_init1(IN_CLOEXEC); - if (pfd[0].fd < 0) { - err(udev, "inotify_init failed: %m\n"); - } else { - if (inotify_add_watch(pfd[0].fd, udev_get_run_path(udev), IN_MOVED_TO) < 0) { - err(udev, "watching '%s' failed\n", udev_get_run_path(udev)); - close(pfd[0].fd); - pfd[0].fd = -1; - } - } - - for (;;) { - struct stat statbuf; - - if (exists != NULL && stat(exists, &statbuf) == 0) { - rc = EXIT_SUCCESS; - break; - } - - if (start > 0) { - /* if asked for, wait for a specific sequence of events */ - if (udev_queue_get_seqnum_sequence_is_finished(udev_queue, start, end) == 1) { - rc = EXIT_SUCCESS; - break; - } - } else { - /* exit if queue is empty */ - if (udev_queue_get_queue_is_empty(udev_queue)) { - rc = EXIT_SUCCESS; - break; - } - } - - if (pfd[0].fd >= 0) { - int delay; - - if (exists != NULL || start > 0) - delay = 100; - else - delay = 1000; - /* wake up after delay, or immediately after the queue is rebuilt */ - if (poll(pfd, 1, delay) > 0 && pfd[0].revents & POLLIN) { - char buf[sizeof(struct inotify_event) + PATH_MAX]; - - read(pfd[0].fd, buf, sizeof(buf)); - } - } else { - sleep(1); - } - - if (timeout > 0) { - unsigned long long age_usec; - - age_usec = now_usec() - start_usec; - if (age_usec / (1000 * 1000) >= timeout) { - struct udev_list_entry *list_entry; - - if (!quiet && udev_queue_get_queued_list_entry(udev_queue) != NULL) { - info(udev, "timeout waiting for udev queue\n"); - printf("\nudevadm settle - timeout of %i seconds reached, the event queue contains:\n", timeout); - udev_list_entry_foreach(list_entry, udev_queue_get_queued_list_entry(udev_queue)) - printf(" %s (%s)\n", - udev_list_entry_get_name(list_entry), - udev_list_entry_get_value(list_entry)); - } - - break; - } - } - } -out: - if (pfd[0].fd >= 0) - close(pfd[0].fd); - udev_queue_unref(udev_queue); - return rc; -} - -const struct udevadm_cmd udevadm_settle = { - .name = "settle", - .cmd = adm_settle, - .help = "wait for the event queue to finish", -}; diff --git a/src/udev/src/udevadm-test-builtin.c b/src/udev/src/udevadm-test-builtin.c deleted file mode 100644 index 3a49f7ce9..000000000 --- a/src/udev/src/udevadm-test-builtin.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2011 Kay Sievers <kay.sievers@vrfy.org> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <stdio.h> -#include <unistd.h> -#include <errno.h> -#include <dirent.h> -#include <fcntl.h> -#include <syslog.h> -#include <getopt.h> -#include <signal.h> -#include <time.h> -#include <sys/inotify.h> -#include <sys/poll.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include "udev.h" - -static void help(struct udev *udev) -{ - fprintf(stderr, "\n"); - fprintf(stderr, "Usage: udevadm builtin [--help] <command> <syspath>\n"); - udev_builtin_list(udev); - fprintf(stderr, "\n"); -} - -static int adm_builtin(struct udev *udev, int argc, char *argv[]) -{ - static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - {} - }; - char *command = NULL; - char *syspath = NULL; - char filename[UTIL_PATH_SIZE]; - struct udev_device *dev = NULL; - enum udev_builtin_cmd cmd; - int rc = EXIT_SUCCESS; - - dbg(udev, "version %s\n", VERSION); - - for (;;) { - int option; - - option = getopt_long(argc, argv, "h", options, NULL); - if (option == -1) - break; - - switch (option) { - case 'h': - help(udev); - goto out; - } - } - - command = argv[optind++]; - if (command == NULL) { - fprintf(stderr, "command missing\n"); - help(udev); - rc = 2; - goto out; - } - - syspath = argv[optind++]; - if (syspath == NULL) { - fprintf(stderr, "syspath missing\n\n"); - rc = 3; - goto out; - } - - udev_builtin_init(udev); - - cmd = udev_builtin_lookup(command); - if (cmd >= UDEV_BUILTIN_MAX) { - fprintf(stderr, "unknown command '%s'\n", command); - help(udev); - rc = 5; - goto out; - } - - /* add /sys if needed */ - if (strncmp(syspath, udev_get_sys_path(udev), strlen(udev_get_sys_path(udev))) != 0) - util_strscpyl(filename, sizeof(filename), udev_get_sys_path(udev), syspath, NULL); - else - util_strscpy(filename, sizeof(filename), syspath); - util_remove_trailing_chars(filename, '/'); - - dev = udev_device_new_from_syspath(udev, filename); - if (dev == NULL) { - fprintf(stderr, "unable to open device '%s'\n\n", filename); - rc = 4; - goto out; - } - - if (udev_builtin_run(dev, cmd, command, true) < 0) { - fprintf(stderr, "error executing '%s'\n\n", command); - rc = 6; - } -out: - udev_device_unref(dev); - udev_builtin_exit(udev); - return rc; -} - -const struct udevadm_cmd udevadm_test_builtin = { - .name = "test-builtin", - .cmd = adm_builtin, - .help = "test a built-in command", - .debug = true, -}; diff --git a/src/udev/src/udevadm-test.c b/src/udev/src/udevadm-test.c deleted file mode 100644 index 6275cff89..000000000 --- a/src/udev/src/udevadm-test.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2003-2004 Greg Kroah-Hartman <greg@kroah.com> - * Copyright (C) 2004-2008 Kay Sievers <kay.sievers@vrfy.org> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <stddef.h> -#include <unistd.h> -#include <errno.h> -#include <ctype.h> -#include <fcntl.h> -#include <signal.h> -#include <syslog.h> -#include <getopt.h> -#include <sys/signalfd.h> - -#include "udev.h" - -static int adm_test(struct udev *udev, int argc, char *argv[]) -{ - int resolve_names = 1; - char filename[UTIL_PATH_SIZE]; - const char *action = "add"; - const char *syspath = NULL; - struct udev_event *event = NULL; - struct udev_device *dev = NULL; - struct udev_rules *rules = NULL; - struct udev_list_entry *entry; - sigset_t mask, sigmask_orig; - int err; - int rc = 0; - - static const struct option options[] = { - { "action", required_argument, NULL, 'a' }, - { "resolve-names", required_argument, NULL, 'N' }, - { "help", no_argument, NULL, 'h' }, - {} - }; - - info(udev, "version %s\n", VERSION); - - for (;;) { - int option; - - option = getopt_long(argc, argv, "a:s:N:fh", options, NULL); - if (option == -1) - break; - - dbg(udev, "option '%c'\n", option); - switch (option) { - case 'a': - action = optarg; - break; - case 'N': - if (strcmp (optarg, "early") == 0) { - resolve_names = 1; - } else if (strcmp (optarg, "late") == 0) { - resolve_names = 0; - } else if (strcmp (optarg, "never") == 0) { - resolve_names = -1; - } else { - fprintf(stderr, "resolve-names must be early, late or never\n"); - err(udev, "resolve-names must be early, late or never\n"); - exit(EXIT_FAILURE); - } - break; - case 'h': - printf("Usage: udevadm test OPTIONS <syspath>\n" - " --action=<string> set action string\n" - " --help\n\n"); - exit(EXIT_SUCCESS); - default: - exit(EXIT_FAILURE); - } - } - syspath = argv[optind]; - - if (syspath == NULL) { - fprintf(stderr, "syspath parameter missing\n"); - rc = 2; - goto out; - } - - printf("This program is for debugging only, it does not run any program,\n" - "specified by a RUN key. It may show incorrect results, because\n" - "some values may be different, or not available at a simulation run.\n" - "\n"); - - sigprocmask(SIG_SETMASK, NULL, &sigmask_orig); - - udev_builtin_init(udev); - - rules = udev_rules_new(udev, resolve_names); - if (rules == NULL) { - fprintf(stderr, "error reading rules\n"); - rc = 3; - goto out; - } - - /* add /sys if needed */ - if (strncmp(syspath, udev_get_sys_path(udev), strlen(udev_get_sys_path(udev))) != 0) - util_strscpyl(filename, sizeof(filename), udev_get_sys_path(udev), syspath, NULL); - else - util_strscpy(filename, sizeof(filename), syspath); - util_remove_trailing_chars(filename, '/'); - - dev = udev_device_new_from_syspath(udev, filename); - if (dev == NULL) { - fprintf(stderr, "unable to open device '%s'\n", filename); - rc = 4; - goto out; - } - - /* skip reading of db, but read kernel parameters */ - udev_device_set_info_loaded(dev); - udev_device_read_uevent_file(dev); - - udev_device_set_action(dev, action); - event = udev_event_new(dev); - - sigfillset(&mask); - sigprocmask(SIG_SETMASK, &mask, &sigmask_orig); - event->fd_signal = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); - if (event->fd_signal < 0) { - fprintf(stderr, "error creating signalfd\n"); - rc = 5; - goto out; - } - - err = udev_event_execute_rules(event, rules, &sigmask_orig); - - udev_list_entry_foreach(entry, udev_device_get_properties_list_entry(dev)) - printf("%s=%s\n", udev_list_entry_get_name(entry), udev_list_entry_get_value(entry)); - - if (err == 0) { - udev_list_entry_foreach(entry, udev_list_get_entry(&event->run_list)) { - char program[UTIL_PATH_SIZE]; - - udev_event_apply_format(event, udev_list_entry_get_name(entry), program, sizeof(program)); - printf("run: '%s'\n", program); - } - } -out: - if (event != NULL && event->fd_signal >= 0) - close(event->fd_signal); - udev_event_unref(event); - udev_device_unref(dev); - udev_rules_unref(rules); - udev_builtin_exit(udev); - return rc; -} - -const struct udevadm_cmd udevadm_test = { - .name = "test", - .cmd = adm_test, - .help = "test an event run", - .debug = true, -}; diff --git a/src/udev/src/udevadm-trigger.c b/src/udev/src/udevadm-trigger.c deleted file mode 100644 index 3cce23dfb..000000000 --- a/src/udev/src/udevadm-trigger.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (C) 2008-2009 Kay Sievers <kay.sievers@vrfy.org> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <stdio.h> -#include <unistd.h> -#include <getopt.h> -#include <errno.h> -#include <dirent.h> -#include <fcntl.h> -#include <syslog.h> -#include <fnmatch.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/un.h> - -#include "udev.h" - -static int verbose; -static int dry_run; - -static void exec_list(struct udev_enumerate *udev_enumerate, const char *action) -{ - struct udev *udev = udev_enumerate_get_udev(udev_enumerate); - struct udev_list_entry *entry; - - udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(udev_enumerate)) { - char filename[UTIL_PATH_SIZE]; - int fd; - - if (verbose) - printf("%s\n", udev_list_entry_get_name(entry)); - if (dry_run) - continue; - util_strscpyl(filename, sizeof(filename), udev_list_entry_get_name(entry), "/uevent", NULL); - fd = open(filename, O_WRONLY); - if (fd < 0) { - dbg(udev, "error on opening %s: %m\n", filename); - continue; - } - if (write(fd, action, strlen(action)) < 0) - info(udev, "error writing '%s' to '%s': %m\n", action, filename); - close(fd); - } -} - -static const char *keyval(const char *str, const char **val, char *buf, size_t size) -{ - char *pos; - - util_strscpy(buf, size,str); - pos = strchr(buf, '='); - if (pos != NULL) { - pos[0] = 0; - pos++; - } - *val = pos; - return buf; -} - -static int adm_trigger(struct udev *udev, int argc, char *argv[]) -{ - static const struct option options[] = { - { "verbose", no_argument, NULL, 'v' }, - { "dry-run", no_argument, NULL, 'n' }, - { "type", required_argument, NULL, 't' }, - { "action", required_argument, NULL, 'c' }, - { "subsystem-match", required_argument, NULL, 's' }, - { "subsystem-nomatch", required_argument, NULL, 'S' }, - { "attr-match", required_argument, NULL, 'a' }, - { "attr-nomatch", required_argument, NULL, 'A' }, - { "property-match", required_argument, NULL, 'p' }, - { "tag-match", required_argument, NULL, 'g' }, - { "sysname-match", required_argument, NULL, 'y' }, - { "parent-match", required_argument, NULL, 'b' }, - { "help", no_argument, NULL, 'h' }, - {} - }; - enum { - TYPE_DEVICES, - TYPE_SUBSYSTEMS, - } device_type = TYPE_DEVICES; - const char *action = "change"; - struct udev_enumerate *udev_enumerate; - int rc = 0; - - dbg(udev, "version %s\n", VERSION); - udev_enumerate = udev_enumerate_new(udev); - if (udev_enumerate == NULL) { - rc = 1; - goto exit; - } - - for (;;) { - int option; - const char *key; - const char *val; - char buf[UTIL_PATH_SIZE]; - - option = getopt_long(argc, argv, "vng:o:t:hc:p:s:S:a:A:y:b:", options, NULL); - if (option == -1) - break; - - switch (option) { - case 'v': - verbose = 1; - break; - case 'n': - dry_run = 1; - break; - case 't': - if (strcmp(optarg, "devices") == 0) { - device_type = TYPE_DEVICES; - } else if (strcmp(optarg, "subsystems") == 0) { - device_type = TYPE_SUBSYSTEMS; - } else { - err(udev, "unknown type --type=%s\n", optarg); - rc = 2; - goto exit; - } - break; - case 'c': - action = optarg; - break; - case 's': - udev_enumerate_add_match_subsystem(udev_enumerate, optarg); - break; - case 'S': - udev_enumerate_add_nomatch_subsystem(udev_enumerate, optarg); - break; - case 'a': - key = keyval(optarg, &val, buf, sizeof(buf)); - udev_enumerate_add_match_sysattr(udev_enumerate, key, val); - break; - case 'A': - key = keyval(optarg, &val, buf, sizeof(buf)); - udev_enumerate_add_nomatch_sysattr(udev_enumerate, key, val); - break; - case 'p': - key = keyval(optarg, &val, buf, sizeof(buf)); - udev_enumerate_add_match_property(udev_enumerate, key, val); - break; - case 'g': - udev_enumerate_add_match_tag(udev_enumerate, optarg); - break; - case 'y': - udev_enumerate_add_match_sysname(udev_enumerate, optarg); - break; - case 'b': { - char path[UTIL_PATH_SIZE]; - struct udev_device *dev; - - /* add sys dir if needed */ - if (strncmp(optarg, udev_get_sys_path(udev), strlen(udev_get_sys_path(udev))) != 0) - util_strscpyl(path, sizeof(path), udev_get_sys_path(udev), optarg, NULL); - else - util_strscpy(path, sizeof(path), optarg); - util_remove_trailing_chars(path, '/'); - dev = udev_device_new_from_syspath(udev, path); - if (dev == NULL) { - err(udev, "unable to open the device '%s'\n", optarg); - rc = 2; - goto exit; - } - udev_enumerate_add_match_parent(udev_enumerate, dev); - /* drop reference immediately, enumerate pins the device as long as needed */ - udev_device_unref(dev); - break; - } - case 'h': - printf("Usage: udevadm trigger OPTIONS\n" - " --verbose print the list of devices while running\n" - " --dry-run do not actually trigger the events\n" - " --type= type of events to trigger\n" - " devices sys devices (default)\n" - " subsystems sys subsystems and drivers\n" - " --action=<action> event action value, default is \"change\"\n" - " --subsystem-match=<subsystem> trigger devices from a matching subsystem\n" - " --subsystem-nomatch=<subsystem> exclude devices from a matching subsystem\n" - " --attr-match=<file[=<value>]> trigger devices with a matching attribute\n" - " --attr-nomatch=<file[=<value>]> exclude devices with a matching attribute\n" - " --property-match=<key>=<value> trigger devices with a matching property\n" - " --tag-match=<key>=<value> trigger devices with a matching property\n" - " --sysname-match=<name> trigger devices with a matching name\n" - " --parent-match=<name> trigger devices with that parent device\n" - " --help\n\n"); - goto exit; - default: - rc = 1; - goto exit; - } - } - - switch (device_type) { - case TYPE_SUBSYSTEMS: - udev_enumerate_scan_subsystems(udev_enumerate); - exec_list(udev_enumerate, action); - goto exit; - case TYPE_DEVICES: - udev_enumerate_scan_devices(udev_enumerate); - exec_list(udev_enumerate, action); - goto exit; - default: - goto exit; - } -exit: - udev_enumerate_unref(udev_enumerate); - return rc; -} - -const struct udevadm_cmd udevadm_trigger = { - .name = "trigger", - .cmd = adm_trigger, - .help = "request events from the kernel", -}; diff --git a/src/udev/src/udevadm.c b/src/udev/src/udevadm.c deleted file mode 100644 index 224ece0bb..000000000 --- a/src/udev/src/udevadm.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2007-2009 Kay Sievers <kay.sievers@vrfy.org> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <errno.h> -#include <getopt.h> - -#include "udev.h" - -static bool debug; - -void udev_main_log(struct udev *udev, int priority, - const char *file, int line, const char *fn, - const char *format, va_list args) -{ - if (debug) { - fprintf(stderr, "%s: ", fn); - vfprintf(stderr, format, args); - } else { - va_list args2; - - va_copy(args2, args); - vfprintf(stderr, format, args2); - va_end(args2); - vsyslog(priority, format, args); - } -} - -static int adm_version(struct udev *udev, int argc, char *argv[]) -{ - printf("%s\n", VERSION); - return 0; -} -static const struct udevadm_cmd udevadm_version = { - .name = "version", - .cmd = adm_version, -}; - -static int adm_help(struct udev *udev, int argc, char *argv[]); -static const struct udevadm_cmd udevadm_help = { - .name = "help", - .cmd = adm_help, -}; - -static const struct udevadm_cmd *udevadm_cmds[] = { - &udevadm_info, - &udevadm_trigger, - &udevadm_settle, - &udevadm_control, - &udevadm_monitor, - &udevadm_test, - &udevadm_test_builtin, - &udevadm_version, - &udevadm_help, -}; - -static int adm_help(struct udev *udev, int argc, char *argv[]) -{ - unsigned int i; - - fprintf(stderr, "Usage: udevadm [--help] [--version] [--debug] COMMAND [COMMAND OPTIONS]\n"); - for (i = 0; i < ARRAY_SIZE(udevadm_cmds); i++) - if (udevadm_cmds[i]->help != NULL) - printf(" %-12s %s\n", udevadm_cmds[i]->name, udevadm_cmds[i]->help); - fprintf(stderr, "\n"); - return 0; -} - -static int run_command(struct udev *udev, const struct udevadm_cmd *cmd, int argc, char *argv[]) -{ - if (cmd->debug) { - debug = true; - if (udev_get_log_priority(udev) < LOG_INFO) - udev_set_log_priority(udev, LOG_INFO); - } - info(udev, "calling: %s\n", cmd->name); - return cmd->cmd(udev, argc, argv); -} - -int main(int argc, char *argv[]) -{ - struct udev *udev; - static const struct option options[] = { - { "debug", no_argument, NULL, 'd' }, - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'V' }, - {} - }; - const char *command; - unsigned int i; - int rc = 1; - - udev = udev_new(); - if (udev == NULL) - goto out; - - udev_log_init("udevadm"); - udev_set_log_fn(udev, udev_main_log); - udev_selinux_init(udev); - - for (;;) { - int option; - - option = getopt_long(argc, argv, "+dhV", options, NULL); - if (option == -1) - break; - - switch (option) { - case 'd': - debug = true; - if (udev_get_log_priority(udev) < LOG_INFO) - udev_set_log_priority(udev, LOG_INFO); - break; - case 'h': - rc = adm_help(udev, argc, argv); - goto out; - case 'V': - rc = adm_version(udev, argc, argv); - goto out; - default: - goto out; - } - } - command = argv[optind]; - - info(udev, "runtime dir '%s'\n", udev_get_run_path(udev)); - - if (command != NULL) - for (i = 0; i < ARRAY_SIZE(udevadm_cmds); i++) { - if (strcmp(udevadm_cmds[i]->name, command) == 0) { - argc -= optind; - argv += optind; - optind = 0; - rc = run_command(udev, udevadm_cmds[i], argc, argv); - goto out; - } - } - - fprintf(stderr, "missing or unknown command\n\n"); - adm_help(udev, argc, argv); - rc = 2; -out: - udev_selinux_exit(udev); - udev_unref(udev); - udev_log_close(); - return rc; -} diff --git a/src/udev/src/udevadm.xml b/src/udev/src/udevadm.xml deleted file mode 100644 index 455ce80ca..000000000 --- a/src/udev/src/udevadm.xml +++ /dev/null @@ -1,472 +0,0 @@ -<?xml version='1.0'?> -<?xml-stylesheet type="text/xsl" href="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"?> -<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" - "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> - -<refentry id="udevadm"> - <refentryinfo> - <title>udevadm</title> - <productname>udev</productname> - </refentryinfo> - - <refmeta> - <refentrytitle>udevadm</refentrytitle> - <manvolnum>8</manvolnum> - <refmiscinfo class="version"></refmiscinfo> - </refmeta> - - <refnamediv> - <refname>udevadm</refname><refpurpose>udev management tool</refpurpose> - </refnamediv> - - <refsynopsisdiv> - <cmdsynopsis> - <command>udevadm</command> - <arg><option>--debug</option></arg> - <arg><option>--version</option></arg> - <arg><option>--help</option></arg> - </cmdsynopsis> - <cmdsynopsis> - <command>udevadm info <replaceable>options</replaceable></command> - </cmdsynopsis> - <cmdsynopsis> - <command>udevadm trigger <optional>options</optional></command> - </cmdsynopsis> - <cmdsynopsis> - <command>udevadm settle <optional>options</optional></command> - </cmdsynopsis> - <cmdsynopsis> - <command>udevadm control <replaceable>command</replaceable></command> - </cmdsynopsis> - <cmdsynopsis> - <command>udevadm monitor <optional>options</optional></command> - </cmdsynopsis> - <cmdsynopsis> - <command>udevadm test <optional>options</optional> <replaceable>devpath</replaceable></command> - </cmdsynopsis> - <cmdsynopsis> - <command>udevadm test-builtin <optional>options</optional> <replaceable>command</replaceable> <replaceable>devpath</replaceable></command> - </cmdsynopsis> - </refsynopsisdiv> - - <refsect1><title>Description</title> - <para>udevadm expects a command and command specific options. It - controls the runtime behavior of udev, requests kernel events, - manages the event queue, and provides simple debugging mechanisms.</para> - </refsect1> - - <refsect1><title>OPTIONS</title> - <variablelist> - <varlistentry> - <term><option>--debug</option></term> - <listitem> - <para>Print debug messages to stderr.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--version</option></term> - <listitem> - <para>Print version number.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--help</option></term> - <listitem> - <para>Print help text.</para> - </listitem> - </varlistentry> - </variablelist> - - <refsect2><title>udevadm info <replaceable>options</replaceable></title> - <para>Queries the udev database for device information - stored in the udev database. It can also query the properties - of a device from its sysfs representation to help creating udev - rules that match this device.</para> - <variablelist> - <varlistentry> - <term><option>--query=<replaceable>type</replaceable></option></term> - <listitem> - <para>Query the database for specified type of device data. It needs the - <option>--path</option> or <option>--name</option> to identify the specified - device. Valid queries are: - <command>name</command>, <command>symlink</command>, <command>path</command>, - <command>property</command>, <command>all</command>.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--path=<replaceable>devpath</replaceable></option></term> - <listitem> - <para>The devpath of the device to query.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--name=<replaceable>file</replaceable></option></term> - <listitem> - <para>The name of the device node or a symlink to query</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--root</option></term> - <listitem> - <para>The udev root directory: <filename>/dev</filename>. If used in conjunction - with a <command>name</command> or <command>symlink</command> query, the - query returns the absolute path including the root directory.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--run</option></term> - <listitem> - <para>The udev runtime directory: <filename>/run/udev</filename>.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--attribute-walk</option></term> - <listitem> - <para>Print all sysfs properties of the specified device that can be used - in udev rules to match the specified device. It prints all devices - along the chain, up to the root of sysfs that can be used in udev rules.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--export</option></term> - <listitem> - <para>Print output as key/value pairs. Values are enclosed in single quotes.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--export-prefix=<replaceable>name</replaceable></option></term> - <listitem> - <para>Add a prefix to the key name of exported values.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--device-id-of-file=<replaceable>file</replaceable></option></term> - <listitem> - <para>Print major/minor numbers of the underlying device, where the file - lives on.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--export-db</option></term> - <listitem> - <para>Export the content of the udev database.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--cleanup-db</option></term> - <listitem> - <para>Cleanup the udev database.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--version</option></term> - <listitem> - <para>Print version.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--help</option></term> - <listitem> - <para>Print help text.</para> - </listitem> - </varlistentry> - </variablelist> - </refsect2> - - <refsect2><title>udevadm trigger <optional>options</optional></title> - <para>Request device events from the kernel. Primarily used to replay events at system coldplug time.</para> - <variablelist> - <varlistentry> - <term><option>--verbose</option></term> - <listitem> - <para>Print the list of devices which will be triggered.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--dry-run</option></term> - <listitem> - <para>Do not actually trigger the event.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--type=<replaceable>type</replaceable></option></term> - <listitem> - <para>Trigger a specific type of devices. Valid types are: - <command>devices</command>, <command>subsystems</command>. - The default value is <command>devices</command>.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--action=<replaceable>action</replaceable></option></term> - <listitem> - <para>Type of event to be triggered. The default value is <command>change</command>.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--subsystem-match=<replaceable>subsystem</replaceable></option></term> - <listitem> - <para>Trigger events for devices which belong to a matching subsystem. This option - can be specified multiple times and supports shell style pattern matching.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--subsystem-nomatch=<replaceable>subsystem</replaceable></option></term> - <listitem> - <para>Do not trigger events for devices which belong to a matching subsystem. This option - can be specified multiple times and supports shell style pattern matching.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--attr-match=<replaceable>attribute</replaceable>=<replaceable>value</replaceable></option></term> - <listitem> - <para>Trigger events for devices with a matching sysfs attribute. If a value is specified - along with the attribute name, the content of the attribute is matched against the given - value using shell style pattern matching. If no value is specified, the existence of the - sysfs attribute is checked. This option can be specified multiple times.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--attr-nomatch=<replaceable>attribute</replaceable>=<replaceable>value</replaceable></option></term> - <listitem> - <para>Do not trigger events for devices with a matching sysfs attribute. If a value is - specified along with the attribute name, the content of the attribute is matched against - the given value using shell style pattern matching. If no value is specified, the existence - of the sysfs attribute is checked. This option can be specified multiple times.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--property-match=<replaceable>property</replaceable>=<replaceable>value</replaceable></option></term> - <listitem> - <para>Trigger events for devices with a matching property value. This option can be - specified multiple times and supports shell style pattern matching.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--tag-match=<replaceable>property</replaceable></option></term> - <listitem> - <para>Trigger events for devices with a matching tag. This option can be - specified multiple times.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--sysname-match=<replaceable>name</replaceable></option></term> - <listitem> - <para>Trigger events for devices with a matching sys device name. This option can be - specified multiple times and supports shell style pattern matching.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--parent-match=<replaceable>syspath</replaceable></option></term> - <listitem> - <para>Trigger events for all children of a given device.</para> - </listitem> - </varlistentry> - </variablelist> - </refsect2> - - <refsect2><title>udevadm settle <optional>options</optional></title> - <para>Watches the udev event queue, and exits if all current events are handled.</para> - <variablelist> - <varlistentry> - <term><option>--timeout=<replaceable>seconds</replaceable></option></term> - <listitem> - <para>Maximum number of seconds to wait for the event queue to become empty. - The default value is 120 seconds. A value of 0 will check if the queue is empty - and always return immediately.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--seq-start=<replaceable>seqnum</replaceable></option></term> - <listitem> - <para>Wait only for events after the given sequence number.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--seq-end=<replaceable>seqnum</replaceable></option></term> - <listitem> - <para>Wait only for events before the given sequence number.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--exit-if-exists=<replaceable>file</replaceable></option></term> - <listitem> - <para>Stop waiting if file exists.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--quiet</option></term> - <listitem> - <para>Do not print any output, like the remaining queue entries when reaching the timeout.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--help</option></term> - <listitem> - <para>Print help text.</para> - </listitem> - </varlistentry> - </variablelist> - </refsect2> - - <refsect2><title>udevadm control <replaceable>command</replaceable></title> - <para>Modify the internal state of the running udev daemon.</para> - <variablelist> - <varlistentry> - <term><option>--exit</option></term> - <listitem> - <para>Signal and wait for udevd to exit.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--log-priority=<replaceable>value</replaceable></option></term> - <listitem> - <para>Set the internal log level of udevd. Valid values are the numerical - syslog priorities or their textual representations: <option>err</option>, - <option>info</option> and <option>debug</option>.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--stop-exec-queue</option></term> - <listitem> - <para>Signal udevd to stop executing new events. Incoming events - will be queued.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--start-exec-queue</option></term> - <listitem> - <para>Signal udevd to enable the execution of events.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--reload</option></term> - <listitem> - <para>Signal udevd to reload the rules files and other databases like the kernel - module index. Reloading rules and databases does not apply any changes to already - existing devices; the new configuration will only be applied to new events.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--property=<replaceable>KEY</replaceable>=<replaceable>value</replaceable></option></term> - <listitem> - <para>Set a global property for all events.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--children-max=</option><replaceable>value</replaceable></term> - <listitem> - <para>Set the maximum number of events, udevd will handle at the - same time.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--timeout=</option><replaceable>seconds</replaceable></term> - <listitem> - <para>The maximum number seconds to wait for a reply from udevd.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--help</option></term> - <listitem> - <para>Print help text.</para> - </listitem> - </varlistentry> - </variablelist> - </refsect2> - - <refsect2><title>udevadm monitor <optional>options</optional></title> - <para>Listens to the kernel uevents and events sent out by a udev rule - and prints the devpath of the event to the console. It can be used to analyze the - event timing, by comparing the timestamps of the kernel uevent and the udev event. - </para> - <variablelist> - <varlistentry> - <term><option>--kernel</option></term> - <listitem> - <para>Print the kernel uevents.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--udev</option></term> - <listitem> - <para>Print the udev event after the rule processing.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--property</option></term> - <listitem> - <para>Also print the properties of the event.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--subsystem-match=<replaceable>string[/string]</replaceable></option></term> - <listitem> - <para>Filter events by subsystem[/devtype]. Only udev events with a matching subsystem value will pass.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--tag-match=<replaceable>string</replaceable></option></term> - <listitem> - <para>Filter events by property. Only udev events with a given tag attached will pass.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--help</option></term> - <listitem> - <para>Print help text.</para> - </listitem> - </varlistentry> - </variablelist> - </refsect2> - - <refsect2><title>udevadm test <optional>options</optional> <replaceable>devpath</replaceable></title> - <para>Simulate a udev event run for the given device, and print debug output.</para> - <variablelist> - <varlistentry> - <term><option>--action=<replaceable>string</replaceable></option></term> - <listitem> - <para>The action string.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--subsystem=<replaceable>string</replaceable></option></term> - <listitem> - <para>The subsystem string.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--help</option></term> - <listitem> - <para>Print help text.</para> - </listitem> - </varlistentry> - </variablelist> - </refsect2> - - <refsect2><title>udevadm test-builtin <optional>options</optional> <replaceable>command</replaceable> <replaceable>devpath</replaceable></title> - <para>Run a built-in command for the given device, and print debug output.</para> - <variablelist> - <varlistentry> - <term><option>--help</option></term> - <listitem> - <para>Print help text.</para> - </listitem> - </varlistentry> - </variablelist> - </refsect2> - </refsect1> - - <refsect1><title>Author</title> - <para>Written by Kay Sievers <email>kay.sievers@vrfy.org</email>.</para> - </refsect1> - - <refsect1> - <title>See Also</title> - <para><citerefentry> - <refentrytitle>udev</refentrytitle><manvolnum>7</manvolnum> - </citerefentry> - <citerefentry> - <refentrytitle>udevd</refentrytitle><manvolnum>8</manvolnum> - </citerefentry></para> - </refsect1> -</refentry> diff --git a/src/udev/src/udevd.c b/src/udev/src/udevd.c deleted file mode 100644 index 170221790..000000000 --- a/src/udev/src/udevd.c +++ /dev/null @@ -1,1746 +0,0 @@ -/* - * Copyright (C) 2004-2011 Kay Sievers <kay.sievers@vrfy.org> - * Copyright (C) 2004 Chris Friesen <chris_friesen@sympatico.ca> - * Copyright (C) 2009 Canonical Ltd. - * Copyright (C) 2009 Scott James Remnant <scott@netsplit.com> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stddef.h> -#include <signal.h> -#include <unistd.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdbool.h> -#include <string.h> -#include <ctype.h> -#include <fcntl.h> -#include <time.h> -#include <getopt.h> -#include <dirent.h> -#include <sys/time.h> -#include <sys/prctl.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <sys/signalfd.h> -#include <sys/epoll.h> -#include <sys/poll.h> -#include <sys/wait.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <sys/inotify.h> -#include <sys/utsname.h> - -#include "udev.h" -#include "sd-daemon.h" - -static bool debug; - -void udev_main_log(struct udev *udev, int priority, - const char *file, int line, const char *fn, - const char *format, va_list args) -{ - if (debug) { - char buf[1024]; - struct timespec ts; - - vsnprintf(buf, sizeof(buf), format, args); - clock_gettime(CLOCK_MONOTONIC, &ts); - fprintf(stderr, "[%llu.%06u] [%u] %s: %s", - (unsigned long long) ts.tv_sec, (unsigned int) ts.tv_nsec/1000, - (int) getpid(), fn, buf); - } else { - vsyslog(priority, format, args); - } -} - -static struct udev_rules *rules; -static struct udev_queue_export *udev_queue_export; -static struct udev_ctrl *udev_ctrl; -static struct udev_monitor *monitor; -static int worker_watch[2] = { -1, -1 }; -static int fd_signal = -1; -static int fd_ep = -1; -static int fd_inotify = -1; -static bool stop_exec_queue; -static bool reload; -static int children; -static int children_max; -static int exec_delay; -static sigset_t sigmask_orig; -static UDEV_LIST(event_list); -static UDEV_LIST(worker_list); -static bool udev_exit; - -enum event_state { - EVENT_UNDEF, - EVENT_QUEUED, - EVENT_RUNNING, -}; - -struct event { - struct udev_list_node node; - struct udev *udev; - struct udev_device *dev; - enum event_state state; - int exitcode; - unsigned long long int delaying_seqnum; - unsigned long long int seqnum; - const char *devpath; - size_t devpath_len; - const char *devpath_old; - dev_t devnum; - bool is_block; - int ifindex; -}; - -static struct event *node_to_event(struct udev_list_node *node) -{ - char *event; - - event = (char *)node; - event -= offsetof(struct event, node); - return (struct event *)event; -} - -static void event_queue_cleanup(struct udev *udev, enum event_state type); - -enum worker_state { - WORKER_UNDEF, - WORKER_RUNNING, - WORKER_IDLE, - WORKER_KILLED, -}; - -struct worker { - struct udev_list_node node; - struct udev *udev; - int refcount; - pid_t pid; - struct udev_monitor *monitor; - enum worker_state state; - struct event *event; - unsigned long long event_start_usec; -}; - -/* passed from worker to main process */ -struct worker_message { - pid_t pid; - int exitcode; -}; - -static struct worker *node_to_worker(struct udev_list_node *node) -{ - char *worker; - - worker = (char *)node; - worker -= offsetof(struct worker, node); - return (struct worker *)worker; -} - -static void event_queue_delete(struct event *event, bool export) -{ - udev_list_node_remove(&event->node); - - if (export) { - udev_queue_export_device_finished(udev_queue_export, event->dev); - info(event->udev, "seq %llu done with %i\n", udev_device_get_seqnum(event->dev), event->exitcode); - } - udev_device_unref(event->dev); - free(event); -} - -static struct worker *worker_ref(struct worker *worker) -{ - worker->refcount++; - return worker; -} - -static void worker_cleanup(struct worker *worker) -{ - udev_list_node_remove(&worker->node); - udev_monitor_unref(worker->monitor); - children--; - free(worker); -} - -static void worker_unref(struct worker *worker) -{ - worker->refcount--; - if (worker->refcount > 0) - return; - info(worker->udev, "worker [%u] cleaned up\n", worker->pid); - worker_cleanup(worker); -} - -static void worker_list_cleanup(struct udev *udev) -{ - struct udev_list_node *loop, *tmp; - - udev_list_node_foreach_safe(loop, tmp, &worker_list) { - struct worker *worker = node_to_worker(loop); - - worker_cleanup(worker); - } -} - -static void worker_new(struct event *event) -{ - struct udev *udev = event->udev; - struct worker *worker; - struct udev_monitor *worker_monitor; - pid_t pid; - - /* listen for new events */ - worker_monitor = udev_monitor_new_from_netlink(udev, NULL); - if (worker_monitor == NULL) - return; - /* allow the main daemon netlink address to send devices to the worker */ - udev_monitor_allow_unicast_sender(worker_monitor, monitor); - udev_monitor_enable_receiving(worker_monitor); - - worker = calloc(1, sizeof(struct worker)); - if (worker == NULL) { - udev_monitor_unref(worker_monitor); - return; - } - /* worker + event reference */ - worker->refcount = 2; - worker->udev = udev; - - pid = fork(); - switch (pid) { - case 0: { - struct udev_device *dev = NULL; - int fd_monitor; - struct epoll_event ep_signal, ep_monitor; - sigset_t mask; - int rc = EXIT_SUCCESS; - - /* take initial device from queue */ - dev = event->dev; - event->dev = NULL; - - free(worker); - worker_list_cleanup(udev); - event_queue_cleanup(udev, EVENT_UNDEF); - udev_queue_export_unref(udev_queue_export); - udev_monitor_unref(monitor); - udev_ctrl_unref(udev_ctrl); - close(fd_signal); - close(fd_ep); - close(worker_watch[READ_END]); - - sigfillset(&mask); - fd_signal = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); - if (fd_signal < 0) { - err(udev, "error creating signalfd %m\n"); - rc = 2; - goto out; - } - - fd_ep = epoll_create1(EPOLL_CLOEXEC); - if (fd_ep < 0) { - err(udev, "error creating epoll fd: %m\n"); - rc = 3; - goto out; - } - - memset(&ep_signal, 0, sizeof(struct epoll_event)); - ep_signal.events = EPOLLIN; - ep_signal.data.fd = fd_signal; - - fd_monitor = udev_monitor_get_fd(worker_monitor); - memset(&ep_monitor, 0, sizeof(struct epoll_event)); - ep_monitor.events = EPOLLIN; - ep_monitor.data.fd = fd_monitor; - - if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_signal, &ep_signal) < 0 || - epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_monitor, &ep_monitor) < 0) { - err(udev, "fail to add fds to epoll: %m\n"); - rc = 4; - goto out; - } - - /* request TERM signal if parent exits */ - prctl(PR_SET_PDEATHSIG, SIGTERM); - - for (;;) { - struct udev_event *udev_event; - struct worker_message msg; - int err; - - info(udev, "seq %llu running\n", udev_device_get_seqnum(dev)); - udev_event = udev_event_new(dev); - if (udev_event == NULL) { - rc = 5; - goto out; - } - - /* needed for SIGCHLD/SIGTERM in spawn() */ - udev_event->fd_signal = fd_signal; - - if (exec_delay > 0) - udev_event->exec_delay = exec_delay; - - /* apply rules, create node, symlinks */ - err = udev_event_execute_rules(udev_event, rules, &sigmask_orig); - - if (err == 0) - udev_event_execute_run(udev_event, &sigmask_orig); - - /* apply/restore inotify watch */ - if (err == 0 && udev_event->inotify_watch) { - udev_watch_begin(udev, dev); - udev_device_update_db(dev); - } - - /* send processed event back to libudev listeners */ - udev_monitor_send_device(worker_monitor, NULL, dev); - - /* send udevd the result of the event execution */ - memset(&msg, 0, sizeof(struct worker_message)); - if (err != 0) - msg.exitcode = err; - msg.pid = getpid(); - send(worker_watch[WRITE_END], &msg, sizeof(struct worker_message), 0); - - info(udev, "seq %llu processed with %i\n", udev_device_get_seqnum(dev), err); - - udev_device_unref(dev); - dev = NULL; - - if (udev_event->sigterm) { - udev_event_unref(udev_event); - goto out; - } - - udev_event_unref(udev_event); - - /* wait for more device messages from main udevd, or term signal */ - while (dev == NULL) { - struct epoll_event ev[4]; - int fdcount; - int i; - - fdcount = epoll_wait(fd_ep, ev, ARRAY_SIZE(ev), -1); - if (fdcount < 0) { - if (errno == EINTR) - continue; - err = -errno; - err(udev, "failed to poll: %m\n"); - goto out; - } - - for (i = 0; i < fdcount; i++) { - if (ev[i].data.fd == fd_monitor && ev[i].events & EPOLLIN) { - dev = udev_monitor_receive_device(worker_monitor); - break; - } else if (ev[i].data.fd == fd_signal && ev[i].events & EPOLLIN) { - struct signalfd_siginfo fdsi; - ssize_t size; - - size = read(fd_signal, &fdsi, sizeof(struct signalfd_siginfo)); - if (size != sizeof(struct signalfd_siginfo)) - continue; - switch (fdsi.ssi_signo) { - case SIGTERM: - goto out; - } - } - } - } - } -out: - udev_device_unref(dev); - if (fd_signal >= 0) - close(fd_signal); - if (fd_ep >= 0) - close(fd_ep); - close(fd_inotify); - close(worker_watch[WRITE_END]); - udev_rules_unref(rules); - udev_builtin_exit(udev); - udev_monitor_unref(worker_monitor); - udev_unref(udev); - udev_log_close(); - exit(rc); - } - case -1: - udev_monitor_unref(worker_monitor); - event->state = EVENT_QUEUED; - free(worker); - err(udev, "fork of child failed: %m\n"); - break; - default: - /* close monitor, but keep address around */ - udev_monitor_disconnect(worker_monitor); - worker->monitor = worker_monitor; - worker->pid = pid; - worker->state = WORKER_RUNNING; - worker->event_start_usec = now_usec(); - worker->event = event; - event->state = EVENT_RUNNING; - udev_list_node_append(&worker->node, &worker_list); - children++; - info(udev, "seq %llu forked new worker [%u]\n", udev_device_get_seqnum(event->dev), pid); - break; - } -} - -static void event_run(struct event *event) -{ - struct udev_list_node *loop; - - udev_list_node_foreach(loop, &worker_list) { - struct worker *worker = node_to_worker(loop); - ssize_t count; - - if (worker->state != WORKER_IDLE) - continue; - - count = udev_monitor_send_device(monitor, worker->monitor, event->dev); - if (count < 0) { - err(event->udev, "worker [%u] did not accept message %zi (%m), kill it\n", worker->pid, count); - kill(worker->pid, SIGKILL); - worker->state = WORKER_KILLED; - continue; - } - worker_ref(worker); - worker->event = event; - worker->state = WORKER_RUNNING; - worker->event_start_usec = now_usec(); - event->state = EVENT_RUNNING; - return; - } - - if (children >= children_max) { - if (children_max > 1) - info(event->udev, "maximum number (%i) of children reached\n", children); - return; - } - - /* start new worker and pass initial device */ - worker_new(event); -} - -static int event_queue_insert(struct udev_device *dev) -{ - struct event *event; - - event = calloc(1, sizeof(struct event)); - if (event == NULL) - return -1; - - event->udev = udev_device_get_udev(dev); - event->dev = dev; - event->seqnum = udev_device_get_seqnum(dev); - event->devpath = udev_device_get_devpath(dev); - event->devpath_len = strlen(event->devpath); - event->devpath_old = udev_device_get_devpath_old(dev); - event->devnum = udev_device_get_devnum(dev); - event->is_block = (strcmp("block", udev_device_get_subsystem(dev)) == 0); - event->ifindex = udev_device_get_ifindex(dev); - - udev_queue_export_device_queued(udev_queue_export, dev); - info(event->udev, "seq %llu queued, '%s' '%s'\n", udev_device_get_seqnum(dev), - udev_device_get_action(dev), udev_device_get_subsystem(dev)); - - event->state = EVENT_QUEUED; - udev_list_node_append(&event->node, &event_list); - return 0; -} - -static void worker_kill(struct udev *udev, int retain) -{ - struct udev_list_node *loop; - int max; - - if (children <= retain) - return; - - max = children - retain; - - udev_list_node_foreach(loop, &worker_list) { - struct worker *worker = node_to_worker(loop); - - if (max-- <= 0) - break; - - if (worker->state == WORKER_KILLED) - continue; - - worker->state = WORKER_KILLED; - kill(worker->pid, SIGTERM); - } -} - -/* lookup event for identical, parent, child device */ -static bool is_devpath_busy(struct event *event) -{ - struct udev_list_node *loop; - size_t common; - - /* check if queue contains events we depend on */ - udev_list_node_foreach(loop, &event_list) { - struct event *loop_event = node_to_event(loop); - - /* we already found a later event, earlier can not block us, no need to check again */ - if (loop_event->seqnum < event->delaying_seqnum) - continue; - - /* event we checked earlier still exists, no need to check again */ - if (loop_event->seqnum == event->delaying_seqnum) - return true; - - /* found ourself, no later event can block us */ - if (loop_event->seqnum >= event->seqnum) - break; - - /* check major/minor */ - if (major(event->devnum) != 0 && event->devnum == loop_event->devnum && event->is_block == loop_event->is_block) - return true; - - /* check network device ifindex */ - if (event->ifindex != 0 && event->ifindex == loop_event->ifindex) - return true; - - /* check our old name */ - if (event->devpath_old != NULL && strcmp(loop_event->devpath, event->devpath_old) == 0) { - event->delaying_seqnum = loop_event->seqnum; - return true; - } - - /* compare devpath */ - common = MIN(loop_event->devpath_len, event->devpath_len); - - /* one devpath is contained in the other? */ - if (memcmp(loop_event->devpath, event->devpath, common) != 0) - continue; - - /* identical device event found */ - if (loop_event->devpath_len == event->devpath_len) { - /* devices names might have changed/swapped in the meantime */ - if (major(event->devnum) != 0 && (event->devnum != loop_event->devnum || event->is_block != loop_event->is_block)) - continue; - if (event->ifindex != 0 && event->ifindex != loop_event->ifindex) - continue; - event->delaying_seqnum = loop_event->seqnum; - return true; - } - - /* parent device event found */ - if (event->devpath[common] == '/') { - event->delaying_seqnum = loop_event->seqnum; - return true; - } - - /* child device event found */ - if (loop_event->devpath[common] == '/') { - event->delaying_seqnum = loop_event->seqnum; - return true; - } - - /* no matching device */ - continue; - } - - return false; -} - -static void event_queue_start(struct udev *udev) -{ - struct udev_list_node *loop; - - udev_list_node_foreach(loop, &event_list) { - struct event *event = node_to_event(loop); - - if (event->state != EVENT_QUEUED) - continue; - - /* do not start event if parent or child event is still running */ - if (is_devpath_busy(event)) { - dbg(udev, "delay seq %llu (%s)\n", event->seqnum, event->devpath); - continue; - } - - event_run(event); - } -} - -static void event_queue_cleanup(struct udev *udev, enum event_state match_type) -{ - struct udev_list_node *loop, *tmp; - - udev_list_node_foreach_safe(loop, tmp, &event_list) { - struct event *event = node_to_event(loop); - - if (match_type != EVENT_UNDEF && match_type != event->state) - continue; - - event_queue_delete(event, false); - } -} - -static void worker_returned(int fd_worker) -{ - for (;;) { - struct worker_message msg; - ssize_t size; - struct udev_list_node *loop; - - size = recv(fd_worker, &msg, sizeof(struct worker_message), MSG_DONTWAIT); - if (size != sizeof(struct worker_message)) - break; - - /* lookup worker who sent the signal */ - udev_list_node_foreach(loop, &worker_list) { - struct worker *worker = node_to_worker(loop); - - if (worker->pid != msg.pid) - continue; - - /* worker returned */ - if (worker->event) { - worker->event->exitcode = msg.exitcode; - event_queue_delete(worker->event, true); - worker->event = NULL; - } - if (worker->state != WORKER_KILLED) - worker->state = WORKER_IDLE; - worker_unref(worker); - break; - } - } -} - -/* receive the udevd message from userspace */ -static struct udev_ctrl_connection *handle_ctrl_msg(struct udev_ctrl *uctrl) -{ - struct udev *udev = udev_ctrl_get_udev(uctrl); - struct udev_ctrl_connection *ctrl_conn; - struct udev_ctrl_msg *ctrl_msg = NULL; - const char *str; - int i; - - ctrl_conn = udev_ctrl_get_connection(uctrl); - if (ctrl_conn == NULL) - goto out; - - ctrl_msg = udev_ctrl_receive_msg(ctrl_conn); - if (ctrl_msg == NULL) - goto out; - - i = udev_ctrl_get_set_log_level(ctrl_msg); - if (i >= 0) { - info(udev, "udevd message (SET_LOG_PRIORITY) received, log_priority=%i\n", i); - udev_set_log_priority(udev, i); - worker_kill(udev, 0); - } - - if (udev_ctrl_get_stop_exec_queue(ctrl_msg) > 0) { - info(udev, "udevd message (STOP_EXEC_QUEUE) received\n"); - stop_exec_queue = true; - } - - if (udev_ctrl_get_start_exec_queue(ctrl_msg) > 0) { - info(udev, "udevd message (START_EXEC_QUEUE) received\n"); - stop_exec_queue = false; - } - - if (udev_ctrl_get_reload(ctrl_msg) > 0) { - info(udev, "udevd message (RELOAD) received\n"); - reload = true; - } - - str = udev_ctrl_get_set_env(ctrl_msg); - if (str != NULL) { - char *key; - - key = strdup(str); - if (key != NULL) { - char *val; - - val = strchr(key, '='); - if (val != NULL) { - val[0] = '\0'; - val = &val[1]; - if (val[0] == '\0') { - info(udev, "udevd message (ENV) received, unset '%s'\n", key); - udev_add_property(udev, key, NULL); - } else { - info(udev, "udevd message (ENV) received, set '%s=%s'\n", key, val); - udev_add_property(udev, key, val); - } - } else { - err(udev, "wrong key format '%s'\n", key); - } - free(key); - } - worker_kill(udev, 0); - } - - i = udev_ctrl_get_set_children_max(ctrl_msg); - if (i >= 0) { - info(udev, "udevd message (SET_MAX_CHILDREN) received, children_max=%i\n", i); - children_max = i; - } - - if (udev_ctrl_get_ping(ctrl_msg) > 0) - info(udev, "udevd message (SYNC) received\n"); - - if (udev_ctrl_get_exit(ctrl_msg) > 0) { - info(udev, "udevd message (EXIT) received\n"); - udev_exit = true; - /* keep reference to block the client until we exit */ - udev_ctrl_connection_ref(ctrl_conn); - } -out: - udev_ctrl_msg_unref(ctrl_msg); - return udev_ctrl_connection_unref(ctrl_conn); -} - -/* read inotify messages */ -static int handle_inotify(struct udev *udev) -{ - int nbytes, pos; - char *buf; - struct inotify_event *ev; - - if ((ioctl(fd_inotify, FIONREAD, &nbytes) < 0) || (nbytes <= 0)) - return 0; - - buf = malloc(nbytes); - if (buf == NULL) { - err(udev, "error getting buffer for inotify\n"); - return -1; - } - - nbytes = read(fd_inotify, buf, nbytes); - - for (pos = 0; pos < nbytes; pos += sizeof(struct inotify_event) + ev->len) { - struct udev_device *dev; - - ev = (struct inotify_event *)(buf + pos); - dev = udev_watch_lookup(udev, ev->wd); - if (dev != NULL) { - info(udev, "inotify event: %x for %s\n", ev->mask, udev_device_get_devnode(dev)); - if (ev->mask & IN_CLOSE_WRITE) { - char filename[UTIL_PATH_SIZE]; - int fd; - - info(udev, "device %s closed, synthesising 'change'\n", udev_device_get_devnode(dev)); - util_strscpyl(filename, sizeof(filename), udev_device_get_syspath(dev), "/uevent", NULL); - fd = open(filename, O_WRONLY); - if (fd >= 0) { - if (write(fd, "change", 6) < 0) - info(udev, "error writing uevent: %m\n"); - close(fd); - } - } - if (ev->mask & IN_IGNORED) - udev_watch_end(udev, dev); - - udev_device_unref(dev); - } - - } - - free(buf); - return 0; -} - -static void handle_signal(struct udev *udev, int signo) -{ - switch (signo) { - case SIGINT: - case SIGTERM: - udev_exit = true; - break; - case SIGCHLD: - for (;;) { - pid_t pid; - int status; - struct udev_list_node *loop, *tmp; - - pid = waitpid(-1, &status, WNOHANG); - if (pid <= 0) - break; - - udev_list_node_foreach_safe(loop, tmp, &worker_list) { - struct worker *worker = node_to_worker(loop); - - if (worker->pid != pid) - continue; - info(udev, "worker [%u] exit\n", pid); - - if (WIFEXITED(status)) { - if (WEXITSTATUS(status) != 0) - err(udev, "worker [%u] exit with return code %i\n", pid, WEXITSTATUS(status)); - } else if (WIFSIGNALED(status)) { - err(udev, "worker [%u] terminated by signal %i (%s)\n", - pid, WTERMSIG(status), strsignal(WTERMSIG(status))); - } else if (WIFSTOPPED(status)) { - err(udev, "worker [%u] stopped\n", pid); - } else if (WIFCONTINUED(status)) { - err(udev, "worker [%u] continued\n", pid); - } else { - err(udev, "worker [%u] exit with status 0x%04x\n", pid, status); - } - - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - if (worker->event) { - err(udev, "worker [%u] failed while handling '%s'\n", - pid, worker->event->devpath); - worker->event->exitcode = -32; - event_queue_delete(worker->event, true); - /* drop reference taken for state 'running' */ - worker_unref(worker); - } - } - worker_unref(worker); - break; - } - } - break; - case SIGHUP: - reload = true; - break; - } -} - -static void static_dev_create_from_modules(struct udev *udev) -{ - struct utsname kernel; - char modules[UTIL_PATH_SIZE]; - char buf[4096]; - FILE *f; - - uname(&kernel); - util_strscpyl(modules, sizeof(modules), "/lib/modules/", kernel.release, "/modules.devname", NULL); - f = fopen(modules, "r"); - if (f == NULL) - return; - - while (fgets(buf, sizeof(buf), f) != NULL) { - char *s; - const char *modname; - const char *devname; - const char *devno; - int maj, min; - char type; - mode_t mode; - char filename[UTIL_PATH_SIZE]; - - if (buf[0] == '#') - continue; - - modname = buf; - s = strchr(modname, ' '); - if (s == NULL) - continue; - s[0] = '\0'; - - devname = &s[1]; - s = strchr(devname, ' '); - if (s == NULL) - continue; - s[0] = '\0'; - - devno = &s[1]; - s = strchr(devno, ' '); - if (s == NULL) - s = strchr(devno, '\n'); - if (s != NULL) - s[0] = '\0'; - if (sscanf(devno, "%c%u:%u", &type, &maj, &min) != 3) - continue; - - if (type == 'c') - mode = S_IFCHR; - else if (type == 'b') - mode = S_IFBLK; - else - continue; - - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/", devname, NULL); - util_create_path_selinux(udev, filename); - udev_selinux_setfscreatecon(udev, filename, mode); - info(udev, "mknod '%s' %c%u:%u\n", filename, type, maj, min); - if (mknod(filename, mode, makedev(maj, min)) < 0 && errno == EEXIST) - utimensat(AT_FDCWD, filename, NULL, 0); - udev_selinux_resetfscreatecon(udev); - } - - fclose(f); -} - -static int copy_dev_dir(struct udev *udev, DIR *dir_from, DIR *dir_to, int maxdepth) -{ - struct dirent *dent; - - for (dent = readdir(dir_from); dent != NULL; dent = readdir(dir_from)) { - struct stat stats; - - if (dent->d_name[0] == '.') - continue; - if (fstatat(dirfd(dir_from), dent->d_name, &stats, AT_SYMLINK_NOFOLLOW) != 0) - continue; - - if (S_ISBLK(stats.st_mode) || S_ISCHR(stats.st_mode)) { - udev_selinux_setfscreateconat(udev, dirfd(dir_to), dent->d_name, stats.st_mode & 0777); - if (mknodat(dirfd(dir_to), dent->d_name, stats.st_mode, stats.st_rdev) == 0) { - fchmodat(dirfd(dir_to), dent->d_name, stats.st_mode & 0777, 0); - fchownat(dirfd(dir_to), dent->d_name, stats.st_uid, stats.st_gid, 0); - } else { - utimensat(dirfd(dir_to), dent->d_name, NULL, 0); - } - udev_selinux_resetfscreatecon(udev); - } else if (S_ISLNK(stats.st_mode)) { - char target[UTIL_PATH_SIZE]; - ssize_t len; - - len = readlinkat(dirfd(dir_from), dent->d_name, target, sizeof(target)); - if (len <= 0 || len == (ssize_t)sizeof(target)) - continue; - target[len] = '\0'; - udev_selinux_setfscreateconat(udev, dirfd(dir_to), dent->d_name, S_IFLNK); - if (symlinkat(target, dirfd(dir_to), dent->d_name) < 0 && errno == EEXIST) - utimensat(dirfd(dir_to), dent->d_name, NULL, AT_SYMLINK_NOFOLLOW); - udev_selinux_resetfscreatecon(udev); - } else if (S_ISDIR(stats.st_mode)) { - DIR *dir2_from, *dir2_to; - - if (maxdepth == 0) - continue; - - udev_selinux_setfscreateconat(udev, dirfd(dir_to), dent->d_name, S_IFDIR|0755); - mkdirat(dirfd(dir_to), dent->d_name, 0755); - udev_selinux_resetfscreatecon(udev); - - dir2_to = fdopendir(openat(dirfd(dir_to), dent->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC)); - if (dir2_to == NULL) - continue; - - dir2_from = fdopendir(openat(dirfd(dir_from), dent->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC)); - if (dir2_from == NULL) { - closedir(dir2_to); - continue; - } - - copy_dev_dir(udev, dir2_from, dir2_to, maxdepth-1); - - closedir(dir2_to); - closedir(dir2_from); - } - } - - return 0; -} - -static void static_dev_create_links(struct udev *udev, DIR *dir) -{ - struct stdlinks { - const char *link; - const char *target; - }; - static const struct stdlinks stdlinks[] = { - { "core", "/proc/kcore" }, - { "fd", "/proc/self/fd" }, - { "stdin", "/proc/self/fd/0" }, - { "stdout", "/proc/self/fd/1" }, - { "stderr", "/proc/self/fd/2" }, - }; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(stdlinks); i++) { - struct stat sb; - - if (stat(stdlinks[i].target, &sb) == 0) { - udev_selinux_setfscreateconat(udev, dirfd(dir), stdlinks[i].link, S_IFLNK); - if (symlinkat(stdlinks[i].target, dirfd(dir), stdlinks[i].link) < 0 && errno == EEXIST) - utimensat(dirfd(dir), stdlinks[i].link, NULL, AT_SYMLINK_NOFOLLOW); - udev_selinux_resetfscreatecon(udev); - } - } -} - -static void static_dev_create_from_devices(struct udev *udev, DIR *dir) -{ - DIR *dir_from; - - dir_from = opendir(PKGLIBEXECDIR "/devices"); - if (dir_from == NULL) - return; - copy_dev_dir(udev, dir_from, dir, 8); - closedir(dir_from); -} - -static void static_dev_create(struct udev *udev) -{ - DIR *dir; - - dir = opendir(udev_get_dev_path(udev)); - if (dir == NULL) - return; - - static_dev_create_links(udev, dir); - static_dev_create_from_devices(udev, dir); - - closedir(dir); -} - -static int mem_size_mb(void) -{ - FILE *f; - char buf[4096]; - long int memsize = -1; - - f = fopen("/proc/meminfo", "r"); - if (f == NULL) - return -1; - - while (fgets(buf, sizeof(buf), f) != NULL) { - long int value; - - if (sscanf(buf, "MemTotal: %ld kB", &value) == 1) { - memsize = value / 1024; - break; - } - } - - fclose(f); - return memsize; -} - -static int convert_db(struct udev *udev) -{ - char filename[UTIL_PATH_SIZE]; - FILE *f; - struct udev_enumerate *udev_enumerate; - struct udev_list_entry *list_entry; - - /* current database */ - util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/data", NULL); - if (access(filename, F_OK) >= 0) - return 0; - - /* make sure we do not get here again */ - util_create_path(udev, filename); - mkdir(filename, 0755); - - /* old database */ - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/db", NULL); - if (access(filename, F_OK) < 0) - return 0; - - f = fopen("/dev/kmsg", "w"); - if (f != NULL) { - fprintf(f, "<30>udevd[%u]: converting old udev database\n", getpid()); - fclose(f); - } - - udev_enumerate = udev_enumerate_new(udev); - if (udev_enumerate == NULL) - return -1; - udev_enumerate_scan_devices(udev_enumerate); - udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(udev_enumerate)) { - struct udev_device *device; - - device = udev_device_new_from_syspath(udev, udev_list_entry_get_name(list_entry)); - if (device == NULL) - continue; - - /* try to find the old database for devices without a current one */ - if (udev_device_read_db(device, NULL) < 0) { - bool have_db; - const char *id; - struct stat stats; - char devpath[UTIL_PATH_SIZE]; - char from[UTIL_PATH_SIZE]; - - have_db = false; - - /* find database in old location */ - id = udev_device_get_id_filename(device); - util_strscpyl(from, sizeof(from), udev_get_dev_path(udev), "/.udev/db/", id, NULL); - if (lstat(from, &stats) == 0) { - if (!have_db) { - udev_device_read_db(device, from); - have_db = true; - } - unlink(from); - } - - /* find old database with $subsys:$sysname name */ - util_strscpyl(from, sizeof(from), udev_get_dev_path(udev), - "/.udev/db/", udev_device_get_subsystem(device), ":", - udev_device_get_sysname(device), NULL); - if (lstat(from, &stats) == 0) { - if (!have_db) { - udev_device_read_db(device, from); - have_db = true; - } - unlink(from); - } - - /* find old database with the encoded devpath name */ - util_path_encode(udev_device_get_devpath(device), devpath, sizeof(devpath)); - util_strscpyl(from, sizeof(from), udev_get_dev_path(udev), "/.udev/db/", devpath, NULL); - if (lstat(from, &stats) == 0) { - if (!have_db) { - udev_device_read_db(device, from); - have_db = true; - } - unlink(from); - } - - /* write out new database */ - if (have_db) - udev_device_update_db(device); - } - udev_device_unref(device); - } - udev_enumerate_unref(udev_enumerate); - return 0; -} - -static int systemd_fds(struct udev *udev, int *rctrl, int *rnetlink) -{ - int ctrl = -1, netlink = -1; - int fd, n; - - n = sd_listen_fds(true); - if (n <= 0) - return -1; - - for (fd = SD_LISTEN_FDS_START; fd < n + SD_LISTEN_FDS_START; fd++) { - if (sd_is_socket(fd, AF_LOCAL, SOCK_SEQPACKET, -1)) { - if (ctrl >= 0) - return -1; - ctrl = fd; - continue; - } - - if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1)) { - if (netlink >= 0) - return -1; - netlink = fd; - continue; - } - - return -1; - } - - if (ctrl < 0 || netlink < 0) - return -1; - - info(udev, "ctrl=%i netlink=%i\n", ctrl, netlink); - *rctrl = ctrl; - *rnetlink = netlink; - return 0; -} - -static bool check_rules_timestamp(struct udev *udev) -{ - char **p; - unsigned long long *stamp_usec; - int i, n; - bool changed = false; - - n = udev_get_rules_path(udev, &p, &stamp_usec); - for (i = 0; i < n; i++) { - struct stat stats; - - if (stat(p[i], &stats) < 0) - continue; - - if (stamp_usec[i] == ts_usec(&stats.st_mtim)) - continue; - - /* first check */ - if (stamp_usec[i] != 0) { - info(udev, "reload - timestamp of '%s' changed\n", p[i]); - changed = true; - } - - /* update timestamp */ - stamp_usec[i] = ts_usec(&stats.st_mtim); - } - - return changed; -} - -int main(int argc, char *argv[]) -{ - struct udev *udev; - FILE *f; - sigset_t mask; - int daemonize = false; - int resolve_names = 1; - static const struct option options[] = { - { "daemon", no_argument, NULL, 'd' }, - { "debug", no_argument, NULL, 'D' }, - { "children-max", required_argument, NULL, 'c' }, - { "exec-delay", required_argument, NULL, 'e' }, - { "resolve-names", required_argument, NULL, 'N' }, - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'V' }, - {} - }; - int fd_ctrl = -1; - int fd_netlink = -1; - int fd_worker = -1; - struct epoll_event ep_ctrl, ep_inotify, ep_signal, ep_netlink, ep_worker; - struct udev_ctrl_connection *ctrl_conn = NULL; - char **s; - int rc = 1; - - udev = udev_new(); - if (udev == NULL) - goto exit; - - udev_log_init("udevd"); - udev_set_log_fn(udev, udev_main_log); - info(udev, "version %s\n", VERSION); - udev_selinux_init(udev); - - for (;;) { - int option; - - option = getopt_long(argc, argv, "c:deDtN:hV", options, NULL); - if (option == -1) - break; - - switch (option) { - case 'd': - daemonize = true; - break; - case 'c': - children_max = strtoul(optarg, NULL, 0); - break; - case 'e': - exec_delay = strtoul(optarg, NULL, 0); - break; - case 'D': - debug = true; - if (udev_get_log_priority(udev) < LOG_INFO) - udev_set_log_priority(udev, LOG_INFO); - break; - case 'N': - if (strcmp (optarg, "early") == 0) { - resolve_names = 1; - } else if (strcmp (optarg, "late") == 0) { - resolve_names = 0; - } else if (strcmp (optarg, "never") == 0) { - resolve_names = -1; - } else { - fprintf(stderr, "resolve-names must be early, late or never\n"); - err(udev, "resolve-names must be early, late or never\n"); - goto exit; - } - break; - case 'h': - printf("Usage: udevd OPTIONS\n" - " --daemon\n" - " --debug\n" - " --children-max=<maximum number of workers>\n" - " --exec-delay=<seconds to wait before executing RUN=>\n" - " --resolve-names=early|late|never\n" - " --version\n" - " --help\n" - "\n"); - goto exit; - case 'V': - printf("%s\n", VERSION); - goto exit; - default: - goto exit; - } - } - - /* - * read the kernel commandline, in case we need to get into debug mode - * udev.log-priority=<level> syslog priority - * udev.children-max=<number of workers> events are fully serialized if set to 1 - * - */ - f = fopen("/proc/cmdline", "r"); - if (f != NULL) { - char cmdline[4096]; - - if (fgets(cmdline, sizeof(cmdline), f) != NULL) { - char *pos; - - pos = strstr(cmdline, "udev.log-priority="); - if (pos != NULL) { - pos += strlen("udev.log-priority="); - udev_set_log_priority(udev, util_log_priority(pos)); - } - - pos = strstr(cmdline, "udev.children-max="); - if (pos != NULL) { - pos += strlen("udev.children-max="); - children_max = strtoul(pos, NULL, 0); - } - - pos = strstr(cmdline, "udev.exec-delay="); - if (pos != NULL) { - pos += strlen("udev.exec-delay="); - exec_delay = strtoul(pos, NULL, 0); - } - } - fclose(f); - } - - if (getuid() != 0) { - fprintf(stderr, "root privileges required\n"); - err(udev, "root privileges required\n"); - goto exit; - } - - /* set umask before creating any file/directory */ - chdir("/"); - umask(022); - - /* /run/udev */ - mkdir(udev_get_run_path(udev), 0755); - - /* create standard links, copy static nodes, create nodes from modules */ - static_dev_create(udev); - static_dev_create_from_modules(udev); - - /* before opening new files, make sure std{in,out,err} fds are in a sane state */ - if (daemonize) { - int fd; - - fd = open("/dev/null", O_RDWR); - if (fd >= 0) { - if (write(STDOUT_FILENO, 0, 0) < 0) - dup2(fd, STDOUT_FILENO); - if (write(STDERR_FILENO, 0, 0) < 0) - dup2(fd, STDERR_FILENO); - if (fd > STDERR_FILENO) - close(fd); - } else { - fprintf(stderr, "cannot open /dev/null\n"); - err(udev, "cannot open /dev/null\n"); - } - } - - if (systemd_fds(udev, &fd_ctrl, &fd_netlink) >= 0) { - /* get control and netlink socket from from systemd */ - udev_ctrl = udev_ctrl_new_from_fd(udev, fd_ctrl); - if (udev_ctrl == NULL) { - err(udev, "error taking over udev control socket"); - rc = 1; - goto exit; - } - - monitor = udev_monitor_new_from_netlink_fd(udev, "kernel", fd_netlink); - if (monitor == NULL) { - err(udev, "error taking over netlink socket\n"); - rc = 3; - goto exit; - } - } else { - /* open control and netlink socket */ - udev_ctrl = udev_ctrl_new(udev); - if (udev_ctrl == NULL) { - fprintf(stderr, "error initializing udev control socket"); - err(udev, "error initializing udev control socket"); - rc = 1; - goto exit; - } - fd_ctrl = udev_ctrl_get_fd(udev_ctrl); - - monitor = udev_monitor_new_from_netlink(udev, "kernel"); - if (monitor == NULL) { - fprintf(stderr, "error initializing netlink socket\n"); - err(udev, "error initializing netlink socket\n"); - rc = 3; - goto exit; - } - fd_netlink = udev_monitor_get_fd(monitor); - } - - if (udev_monitor_enable_receiving(monitor) < 0) { - fprintf(stderr, "error binding netlink socket\n"); - err(udev, "error binding netlink socket\n"); - rc = 3; - goto exit; - } - - if (udev_ctrl_enable_receiving(udev_ctrl) < 0) { - fprintf(stderr, "error binding udev control socket\n"); - err(udev, "error binding udev control socket\n"); - rc = 1; - goto exit; - } - - udev_monitor_set_receive_buffer_size(monitor, 128*1024*1024); - - /* create queue file before signalling 'ready', to make sure we block 'settle' */ - udev_queue_export = udev_queue_export_new(udev); - if (udev_queue_export == NULL) { - err(udev, "error creating queue file\n"); - goto exit; - } - - if (daemonize) { - pid_t pid; - int fd; - - pid = fork(); - switch (pid) { - case 0: - break; - case -1: - err(udev, "fork of daemon failed: %m\n"); - rc = 4; - goto exit; - default: - rc = EXIT_SUCCESS; - goto exit_daemonize; - } - - setsid(); - - fd = open("/proc/self/oom_score_adj", O_RDWR); - if (fd < 0) { - /* Fallback to old interface */ - fd = open("/proc/self/oom_adj", O_RDWR); - if (fd < 0) { - err(udev, "error disabling OOM: %m\n"); - } else { - /* OOM_DISABLE == -17 */ - write(fd, "-17", 3); - close(fd); - } - } else { - write(fd, "-1000", 5); - close(fd); - } - } else { - sd_notify(1, "READY=1"); - } - - f = fopen("/dev/kmsg", "w"); - if (f != NULL) { - fprintf(f, "<30>udevd[%u]: starting version " VERSION "\n", getpid()); - fclose(f); - } - - if (!debug) { - int fd; - - fd = open("/dev/null", O_RDWR); - if (fd >= 0) { - dup2(fd, STDIN_FILENO); - dup2(fd, STDOUT_FILENO); - dup2(fd, STDERR_FILENO); - close(fd); - } - } - - fd_inotify = udev_watch_init(udev); - if (fd_inotify < 0) { - fprintf(stderr, "error initializing inotify\n"); - err(udev, "error initializing inotify\n"); - rc = 4; - goto exit; - } - udev_watch_restore(udev); - - /* block and listen to all signals on signalfd */ - sigfillset(&mask); - sigprocmask(SIG_SETMASK, &mask, &sigmask_orig); - fd_signal = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); - if (fd_signal < 0) { - fprintf(stderr, "error creating signalfd\n"); - err(udev, "error creating signalfd\n"); - rc = 5; - goto exit; - } - - /* unnamed socket from workers to the main daemon */ - if (socketpair(AF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0, worker_watch) < 0) { - fprintf(stderr, "error creating socketpair\n"); - err(udev, "error creating socketpair\n"); - rc = 6; - goto exit; - } - fd_worker = worker_watch[READ_END]; - - udev_builtin_init(udev); - - rules = udev_rules_new(udev, resolve_names); - if (rules == NULL) { - err(udev, "error reading rules\n"); - goto exit; - } - - memset(&ep_ctrl, 0, sizeof(struct epoll_event)); - ep_ctrl.events = EPOLLIN; - ep_ctrl.data.fd = fd_ctrl; - - memset(&ep_inotify, 0, sizeof(struct epoll_event)); - ep_inotify.events = EPOLLIN; - ep_inotify.data.fd = fd_inotify; - - memset(&ep_signal, 0, sizeof(struct epoll_event)); - ep_signal.events = EPOLLIN; - ep_signal.data.fd = fd_signal; - - memset(&ep_netlink, 0, sizeof(struct epoll_event)); - ep_netlink.events = EPOLLIN; - ep_netlink.data.fd = fd_netlink; - - memset(&ep_worker, 0, sizeof(struct epoll_event)); - ep_worker.events = EPOLLIN; - ep_worker.data.fd = fd_worker; - - fd_ep = epoll_create1(EPOLL_CLOEXEC); - if (fd_ep < 0) { - err(udev, "error creating epoll fd: %m\n"); - goto exit; - } - if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_ctrl, &ep_ctrl) < 0 || - epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_inotify, &ep_inotify) < 0 || - epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_signal, &ep_signal) < 0 || - epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_netlink, &ep_netlink) < 0 || - epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_worker, &ep_worker) < 0) { - err(udev, "fail to add fds to epoll: %m\n"); - goto exit; - } - - /* if needed, convert old database from earlier udev version */ - convert_db(udev); - - if (children_max <= 0) { - int memsize = mem_size_mb(); - - /* set value depending on the amount of RAM */ - if (memsize > 0) - children_max = 128 + (memsize / 8); - else - children_max = 128; - } - info(udev, "set children_max to %u\n", children_max); - - udev_rules_apply_static_dev_perms(rules); - - udev_list_node_init(&event_list); - udev_list_node_init(&worker_list); - - for (;;) { - static unsigned long long last_usec; - struct epoll_event ev[8]; - int fdcount; - int timeout; - bool is_worker, is_signal, is_inotify, is_netlink, is_ctrl; - int i; - - if (udev_exit) { - /* close sources of new events and discard buffered events */ - if (fd_ctrl >= 0) { - epoll_ctl(fd_ep, EPOLL_CTL_DEL, fd_ctrl, NULL); - fd_ctrl = -1; - } - if (monitor != NULL) { - epoll_ctl(fd_ep, EPOLL_CTL_DEL, fd_netlink, NULL); - udev_monitor_unref(monitor); - monitor = NULL; - } - if (fd_inotify >= 0) { - epoll_ctl(fd_ep, EPOLL_CTL_DEL, fd_inotify, NULL); - close(fd_inotify); - fd_inotify = -1; - } - - /* discard queued events and kill workers */ - event_queue_cleanup(udev, EVENT_QUEUED); - worker_kill(udev, 0); - - /* exit after all has cleaned up */ - if (udev_list_node_is_empty(&event_list) && udev_list_node_is_empty(&worker_list)) - break; - - /* timeout at exit for workers to finish */ - timeout = 30 * 1000; - } else if (udev_list_node_is_empty(&event_list) && children <= 2) { - /* we are idle */ - timeout = -1; - } else { - /* kill idle or hanging workers */ - timeout = 3 * 1000; - } - fdcount = epoll_wait(fd_ep, ev, ARRAY_SIZE(ev), timeout); - if (fdcount < 0) - continue; - - if (fdcount == 0) { - struct udev_list_node *loop; - - /* timeout */ - if (udev_exit) { - err(udev, "timeout, giving up waiting for workers to finish\n"); - break; - } - - /* kill idle workers */ - if (udev_list_node_is_empty(&event_list)) { - info(udev, "cleanup idle workers\n"); - worker_kill(udev, 2); - } - - /* check for hanging events */ - udev_list_node_foreach(loop, &worker_list) { - struct worker *worker = node_to_worker(loop); - - if (worker->state != WORKER_RUNNING) - continue; - - if ((now_usec() - worker->event_start_usec) > 30 * 1000 * 1000) { - err(udev, "worker [%u] timeout, kill it\n", worker->pid, - worker->event ? worker->event->devpath : "<idle>"); - kill(worker->pid, SIGKILL); - worker->state = WORKER_KILLED; - /* drop reference taken for state 'running' */ - worker_unref(worker); - if (worker->event) { - err(udev, "seq %llu '%s' killed\n", - udev_device_get_seqnum(worker->event->dev), worker->event->devpath); - worker->event->exitcode = -64; - event_queue_delete(worker->event, true); - worker->event = NULL; - } - } - } - - } - - is_worker = is_signal = is_inotify = is_netlink = is_ctrl = false; - for (i = 0; i < fdcount; i++) { - if (ev[i].data.fd == fd_worker && ev[i].events & EPOLLIN) - is_worker = true; - else if (ev[i].data.fd == fd_netlink && ev[i].events & EPOLLIN) - is_netlink = true; - else if (ev[i].data.fd == fd_signal && ev[i].events & EPOLLIN) - is_signal = true; - else if (ev[i].data.fd == fd_inotify && ev[i].events & EPOLLIN) - is_inotify = true; - else if (ev[i].data.fd == fd_ctrl && ev[i].events & EPOLLIN) - is_ctrl = true; - } - - /* check for changed config, every 3 seconds at most */ - if ((now_usec() - last_usec) > 3 * 1000 * 1000) { - if (check_rules_timestamp(udev)) - reload = true; - if (udev_builtin_validate(udev)) - reload = true; - - last_usec = now_usec(); - } - - /* reload requested, HUP signal received, rules changed, builtin changed */ - if (reload) { - worker_kill(udev, 0); - rules = udev_rules_unref(rules); - udev_builtin_exit(udev); - reload = 0; - } - - /* event has finished */ - if (is_worker) - worker_returned(fd_worker); - - if (is_netlink) { - struct udev_device *dev; - - dev = udev_monitor_receive_device(monitor); - if (dev != NULL) { - udev_device_set_usec_initialized(dev, now_usec()); - if (event_queue_insert(dev) < 0) - udev_device_unref(dev); - } - } - - /* start new events */ - if (!udev_list_node_is_empty(&event_list) && !udev_exit && !stop_exec_queue) { - if (rules == NULL) - rules = udev_rules_new(udev, resolve_names); - if (rules != NULL) - event_queue_start(udev); - } - - if (is_signal) { - struct signalfd_siginfo fdsi; - ssize_t size; - - size = read(fd_signal, &fdsi, sizeof(struct signalfd_siginfo)); - if (size == sizeof(struct signalfd_siginfo)) - handle_signal(udev, fdsi.ssi_signo); - } - - /* we are shutting down, the events below are not handled anymore */ - if (udev_exit) - continue; - - /* device node watch */ - if (is_inotify) - handle_inotify(udev); - - /* - * This needs to be after the inotify handling, to make sure, - * that the ping is send back after the possibly generated - * "change" events by the inotify device node watch. - * - * A single time we may receive a client connection which we need to - * keep open to block the client. It will be closed right before we - * exit. - */ - if (is_ctrl) - ctrl_conn = handle_ctrl_msg(udev_ctrl); - } - - rc = EXIT_SUCCESS; -exit: - udev_queue_export_cleanup(udev_queue_export); - udev_ctrl_cleanup(udev_ctrl); -exit_daemonize: - if (fd_ep >= 0) - close(fd_ep); - worker_list_cleanup(udev); - event_queue_cleanup(udev, EVENT_UNDEF); - udev_rules_unref(rules); - udev_builtin_exit(udev); - if (fd_signal >= 0) - close(fd_signal); - if (worker_watch[READ_END] >= 0) - close(worker_watch[READ_END]); - if (worker_watch[WRITE_END] >= 0) - close(worker_watch[WRITE_END]); - udev_monitor_unref(monitor); - udev_queue_export_unref(udev_queue_export); - udev_ctrl_connection_unref(ctrl_conn); - udev_ctrl_unref(udev_ctrl); - udev_selinux_exit(udev); - udev_unref(udev); - udev_log_close(); - return rc; -} diff --git a/src/udev/src/udevd.xml b/src/udev/src/udevd.xml deleted file mode 100644 index c516eb979..000000000 --- a/src/udev/src/udevd.xml +++ /dev/null @@ -1,151 +0,0 @@ -<?xml version='1.0'?> -<?xml-stylesheet type="text/xsl" href="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"?> -<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" - "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> - -<refentry id="udevd"> - <refentryinfo> - <title>udevd</title> - <productname>udev</productname> - </refentryinfo> - - <refmeta> - <refentrytitle>udevd</refentrytitle> - <manvolnum>8</manvolnum> - <refmiscinfo class="version"></refmiscinfo> - </refmeta> - - <refnamediv> - <refname>udevd</refname><refpurpose>event managing daemon</refpurpose> - </refnamediv> - - <refsynopsisdiv> - <cmdsynopsis> - <command>udevd</command> - <arg><option>--daemon</option></arg> - <arg><option>--debug</option></arg> - <arg><option>--children-max=</option></arg> - <arg><option>--exec-delay=</option></arg> - <arg><option>--resolve-names=early|late|never</option></arg> - <arg><option>--version</option></arg> - <arg><option>--help</option></arg> - </cmdsynopsis> - </refsynopsisdiv> - - <refsect1><title>Description</title> - <para>udevd listens to kernel uevents. For every event, udevd executes matching - instructions specified in udev rules. See <citerefentry> - <refentrytitle>udev</refentrytitle><manvolnum>7</manvolnum> - </citerefentry>.</para> - <para>On startup the content of the directory <filename>/usr/lib/udev/devices</filename> - is copied to <filename>/dev</filename>. If kernel modules specify static device - nodes, these nodes are created even without a corresponding kernel device, to - allow on-demand loading of kernel modules. Matching permissions specified in udev - rules are applied to these static device nodes.</para> - <para>The behavior of the running daemon can be changed with - <command>udevadm control</command>.</para> - </refsect1> - - <refsect1><title>Options</title> - <variablelist> - <varlistentry> - <term><option>--daemon</option></term> - <listitem> - <para>Detach and run in the background.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--debug</option></term> - <listitem> - <para>Print debug messages to stderr.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--children-max=</option></term> - <listitem> - <para>Limit the number of parallel executed events.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--exec-delay=</option></term> - <listitem> - <para>Number of seconds to delay the execution of RUN instructions. - This might be useful when debugging system crashes during coldplug - cause by loading non-working kernel modules.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--resolve-names=</option></term> - <listitem> - <para>Specify when udevd should resolve names of users and groups. - When set to <option>early</option> (the default) names will be - resolved when the rules are parsed. When set to - <option>late</option> names will be resolved for every event. - When set to <option>never</option> names will never be resolved - and all devices will be owned by root.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--version</option></term> - <listitem> - <para>Print version number.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><option>--help</option></term> - <listitem> - <para>Print help text.</para> - </listitem> - </varlistentry> - </variablelist> - </refsect1> - - <refsect1><title>Environment</title> - <variablelist> - <varlistentry> - <term><varname>UDEV_LOG=</varname></term> - <listitem> - <para>Set the logging priority.</para> - </listitem> - </varlistentry> - </variablelist> - </refsect1> - - <refsect1><title>Kernel command line</title> - <variablelist> - <varlistentry> - <term><varname>udev.log-priority=</varname></term> - <listitem> - <para>Set the logging priority.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><varname>udev.children-max=</varname></term> - <listitem> - <para>Limit the number of parallel executed events.</para> - </listitem> - </varlistentry> - <varlistentry> - <term><varname>udev.exec-delay=</varname></term> - <listitem> - <para>Number of seconds to delay the execution of RUN instructions. - This might be useful when debugging system crashes during coldplug - cause by loading non-working kernel modules.</para> - </listitem> - </varlistentry> - </variablelist> - </refsect1> - - <refsect1><title>Author</title> - <para>Written by Kay Sievers <email>kay.sievers@vrfy.org</email>.</para> - </refsect1> - - <refsect1> - <title>See Also</title> - <para><citerefentry> - <refentrytitle>udev</refentrytitle><manvolnum>7</manvolnum> - </citerefentry>, <citerefentry> - <refentrytitle>udevadm</refentrytitle><manvolnum>8</manvolnum> - </citerefentry></para> - </refsect1> -</refentry> diff --git a/src/udev/src/v4l_id/60-persistent-v4l.rules b/src/udev/src/v4l_id/60-persistent-v4l.rules deleted file mode 100644 index 93c5ee8c2..000000000 --- a/src/udev/src/v4l_id/60-persistent-v4l.rules +++ /dev/null @@ -1,20 +0,0 @@ -# do not edit this file, it will be overwritten on update - -ACTION=="remove", GOTO="persistent_v4l_end" -SUBSYSTEM!="video4linux", GOTO="persistent_v4l_end" -ENV{MAJOR}=="", GOTO="persistent_v4l_end" - -IMPORT{program}="v4l_id $devnode" - -SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id" -KERNEL=="video*", ENV{ID_SERIAL}=="?*", SYMLINK+="v4l/by-id/$env{ID_BUS}-$env{ID_SERIAL}-video-index$attr{index}" - -# check for valid "index" number -TEST!="index", GOTO="persistent_v4l_end" -ATTR{index}!="?*", GOTO="persistent_v4l_end" - -IMPORT{builtin}="path_id" -ENV{ID_PATH}=="?*", KERNEL=="video*|vbi*", SYMLINK+="v4l/by-path/$env{ID_PATH}-video-index$attr{index}" -ENV{ID_PATH}=="?*", KERNEL=="audio*", SYMLINK+="v4l/by-path/$env{ID_PATH}-audio-index$attr{index}" - -LABEL="persistent_v4l_end" diff --git a/src/udev/src/v4l_id/v4l_id.c b/src/udev/src/v4l_id/v4l_id.c deleted file mode 100644 index a2a80b5f4..000000000 --- a/src/udev/src/v4l_id/v4l_id.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2009 Kay Sievers <kay.sievers@vrfy.org> - * Copyright (c) 2009 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program 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 - * General Public License for more details: - */ - -#include <stdio.h> -#include <errno.h> -#include <string.h> -#include <ctype.h> -#include <stdlib.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> -#include <fcntl.h> -#include <getopt.h> -#include <sys/types.h> -#include <sys/time.h> -#include <sys/ioctl.h> -#include <linux/videodev2.h> - -int main (int argc, char *argv[]) -{ - static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - {} - }; - int fd; - char *device; - struct v4l2_capability v2cap; - - while (1) { - int option; - - option = getopt_long(argc, argv, "h", options, NULL); - if (option == -1) - break; - - switch (option) { - case 'h': - printf("Usage: v4l_id [--help] <device file>\n\n"); - return 0; - default: - return 1; - } - } - device = argv[optind]; - - if (device == NULL) - return 2; - fd = open (device, O_RDONLY); - if (fd < 0) - return 3; - - if (ioctl (fd, VIDIOC_QUERYCAP, &v2cap) == 0) { - printf("ID_V4L_VERSION=2\n"); - printf("ID_V4L_PRODUCT=%s\n", v2cap.card); - printf("ID_V4L_CAPABILITIES=:"); - if ((v2cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) > 0) - printf("capture:"); - if ((v2cap.capabilities & V4L2_CAP_VIDEO_OUTPUT) > 0) - printf("video_output:"); - if ((v2cap.capabilities & V4L2_CAP_VIDEO_OVERLAY) > 0) - printf("video_overlay:"); - if ((v2cap.capabilities & V4L2_CAP_AUDIO) > 0) - printf("audio:"); - if ((v2cap.capabilities & V4L2_CAP_TUNER) > 0) - printf("tuner:"); - if ((v2cap.capabilities & V4L2_CAP_RADIO) > 0) - printf("radio:"); - printf("\n"); - } - - close (fd); - return 0; -} |