diff options
author | Karel Zak | 2009-05-14 15:38:50 +0200 |
---|---|---|
committer | Karel Zak | 2009-05-14 15:38:50 +0200 |
commit | 40672152dcbd17ce41aa3f6670f9898402990a5c (patch) | |
tree | c1dc5fd25ee81ed8d7e86034c8aa19731db6d24d /shlibs | |
parent | blkid: make libuuid optional (diff) | |
download | kernel-qcow2-util-linux-40672152dcbd17ce41aa3f6670f9898402990a5c.tar.gz kernel-qcow2-util-linux-40672152dcbd17ce41aa3f6670f9898402990a5c.tar.xz kernel-qcow2-util-linux-40672152dcbd17ce41aa3f6670f9898402990a5c.zip |
build-sys: rename /libs to /shlibs
On Wed, May 13, 2009 at 05:38:49AM -0400, Christoph Hellwig wrote:
> Also the lib vs libs toplevel directories probably aren't a too good
> choice.
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'shlibs')
75 files changed, 12118 insertions, 0 deletions
diff --git a/shlibs/Makefile.am b/shlibs/Makefile.am new file mode 100644 index 000000000..e09828e6c --- /dev/null +++ b/shlibs/Makefile.am @@ -0,0 +1,5 @@ +SUBDIRS = + +if BUILD_LIBBLKID +SUBDIRS += blkid +endif diff --git a/shlibs/blkid/.gitignore b/shlibs/blkid/.gitignore new file mode 100644 index 000000000..d6126deab --- /dev/null +++ b/shlibs/blkid/.gitignore @@ -0,0 +1,4 @@ +*.sh +bin/blkid +bin/findfs +test_* diff --git a/shlibs/blkid/COPYING.libblkid b/shlibs/blkid/COPYING.libblkid new file mode 100644 index 000000000..cf9b6b997 --- /dev/null +++ b/shlibs/blkid/COPYING.libblkid @@ -0,0 +1,510 @@ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. +^L + 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. +^L + 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. +^L + 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. +^L + 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. +^L + 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. +^L + 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. +^L + 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 +^L + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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/shlibs/blkid/Makefile.am b/shlibs/blkid/Makefile.am new file mode 100644 index 000000000..a27c85248 --- /dev/null +++ b/shlibs/blkid/Makefile.am @@ -0,0 +1,12 @@ +include $(top_srcdir)/config/include-Makefile.am + +SUBDIRS = src bin + +# pkg-config stuff +pkgconfigdir = $(usrlibexecdir)/pkgconfig +pkgconfig_DATA = blkid.pc + +dist_man_MANS = libblkid.3 + +EXTRA_DIST = README.blkid blkid.pc blkid.pc.in libblkid.3 + diff --git a/shlibs/blkid/README.blkid b/shlibs/blkid/README.blkid new file mode 100644 index 000000000..4fa9be1f7 --- /dev/null +++ b/shlibs/blkid/README.blkid @@ -0,0 +1,78 @@ +libblkid - a library to handle device identification and token extraction + +Basic usage is as follows - there are two normal usage patterns: + +For cases where a program wants information about multiple devices, or +expects to be doing multiple token searches, the program should +directly initialize cache file via (second parameter is cache +filename, NULL = default): + + blkid_cache cache = NULL; + if (blkid_get_cache(&cache, NULL) < 0) + /* error reading the cache file, not really fatal */ + +Note that if no cache file exists, an empty cache struct is still +allocated. Usage of libblkid functions will use the cache to avoid +needless device scans. + +The model of the blkid cache is that each device has a number of +attributes that can be associated with it. Currently the attributes +which are supported (and set) by blkid are: + + TYPE filesystem type + UUID filesystem uuid + LABEL filesystem label + + +How to use libblkid? Normally, you either want to find a device with +a specific NAME=value token, or you want to output token(s) from a +device. To find a device that matches a following attribute, you +simply call the blkid_get_devname() function: + + if ((devname = blkid_get_devname(cache, attribute_name, value))) { + /* do something with devname */ + string_free(devname); + } + +The cache parameter is optional; if it is NULL, then the blkid library +will load the default blkid.tab cache file, and then release the cache +before function call returns. The return value is an allocated string +which holds the resulting device name (if it is found). If the value +is NULL, then attribute_name is parsed as if it were +"<attribute_name>=<value>"; if it cannot be so parsed, then the +original attribute_name is returned in a copied allocated string. +This is a convenience to allow user programs to want to translate user +input, whether it is of the form: "/dev/hda1", "LABEL=root", +"UUID=082D-26E3", and get back a device name that it can use. + +Alternatively, of course, the programmer can pass an attribute name of +"LABEL", and value of "root", if that is more convenient. + +Another common usage is to retrieve the value of a specific attribute +for a particular device. This can be used to determine the filesystem +type, or label, or uuid for a particular device: + + if ((value = blkid_get_tag_value(cache, attribute_name, devname))) { + /* do something with value */ + string_free(value); + } + +If a program needs to call multiple blkid functions, then passing in a +cache value of NULL is not recommended, since the /etc/blkid.tab file +will be repeatedly parsed over and over again, with memory allocated +and deallocated. To initialize the blkid cache, blkid_get_cache() +function is used: + + if (blkid_get_cache(&cache, NULL) < 0) + goto errout; + +The second parameter of blkid_get_cache (if non-zero) is the alternate +filename of the blkid cache file (where the default is +/etc/blkid.tab). Normally, programs should just pass in NULL. + +If you have called blkid_get_cache(), you should call blkid_put_cache() +when you are done using the blkid library functions. This will save the +cache to the blkid.tab file, if you have write access to the file. It +will also free all associated devices and tags: + + blkid_put_cache(cache); diff --git a/shlibs/blkid/TODO b/shlibs/blkid/TODO new file mode 100644 index 000000000..1d0a67eea --- /dev/null +++ b/shlibs/blkid/TODO @@ -0,0 +1,54 @@ + + TODO + ---- + + - add command line interface for blkid_probe_filter_types(): + + # blkid -p -o udev --filter-type nofat + + - (?) we need to ignore cache and config files when the files are writable + for non-root users and the library is linked with suid programs + + - add -<BE|LE> suffix to test images for native-endian filesystems (e.g. swap) + and add support for such functionality to tests/ts/blkid/low-probe + + - do we really need to depend on libuuid? Maybe the default should be + use in-tree code rather and link against libuuid -- especially when we + need it for uuid_unparse() only. + + - consolidate "getsize" stuff (see getsize.c and lib/blkdev.c) + + - cleanup __attribute__ usage + + - add stripe size / alignment retrival support to libbkid for use + with mkfs. This would allow to deprecate libdisk from xfsprogs (1) + in favour of a common libblkid. + + [ -- Christoph Hellwig, 16 Feb 2009 ] + (1) http://git.kernel.org/?p=fs/xfs/xfsprogs-dev.git;a=tree;f=libdisk; + + [ .. or move whole libdisk to util-linux-ng and merge partx code to the + library -- kzak ] + + - use /sys/block/<devname>/dm/name rather than scan /dev/mapper/ for the name + (see devname.c: probe_one()). The sysfs entry has been introduced by kernel + patch 784aae735d9b0bba3f8b9faef4c8b30df3bf0128. + + - in lib/fsprobe.c wrapper use blkid_parse_tag_string() rather than a local + parser implementation + + - use fstatat() in blkid__scan_dir() + + - add evaluate.c: blkid_evaluate_tag_to_buffer() (and add lib/canonicalize.c: + canonicalize_path_to_buffer()) + + - add values: + + FSSIZE -- filesystem size (klibc requirement) + + SBOFFSET -- superblock offset; offset where SB was detected + (swapon requirement to check details from swap header) + + MAGIC -- magic string + MAGICLEN -- length of magic string + diff --git a/shlibs/blkid/bin/Makefile.am b/shlibs/blkid/bin/Makefile.am new file mode 100644 index 000000000..ff992ace6 --- /dev/null +++ b/shlibs/blkid/bin/Makefile.am @@ -0,0 +1,15 @@ +include $(top_srcdir)/config/include-Makefile.am + +AM_CPPFLAGS += -I$(ul_libblkid_srcdir) +AM_LDFLAGS += $(ul_libblkid_la) + +sbin_PROGRAMS = blkid findfs +dist_man_MANS = blkid.8 findfs.8 + +if HAVE_STATIC_BLKID +sbin_PROGRAMS += blkid.static +blkid_static_SOURCES = $(blkid_SOURCES) +blkid_static_LDFLAGS = "-all-static" # libtool option +blkid_static_LDADD = $(ul_libblkid_la) +blkid_static_CFLAGS = -I$(ul_libblkid_srcdir) +endif diff --git a/shlibs/blkid/bin/blkid.8 b/shlibs/blkid/bin/blkid.8 new file mode 100644 index 000000000..ff8e8e570 --- /dev/null +++ b/shlibs/blkid/bin/blkid.8 @@ -0,0 +1,211 @@ +.\" Copyright 2000 Andreas Dilger (adilger@turbolinux.com) +.\" +.\" This man page was created for blkid from e2fsprogs-1.25. +.\" +.\" This file may be copied under the terms of the GNU Public License. +.\" +.\" Based on uuidgen, Mon Sep 17 10:42:12 2000, Andreas Dilger +.TH BLKID 8 "February 2009" "Linux" "MAINTENANCE COMMANDS" +.SH NAME +blkid \- command\-line utility to locate/print block device attributes +.SH SYNOPSIS +.B blkid +.RB \-L +.IR label " | " +.RB \-U +.IR uuid + +.B blkid +.RB [ \-ghlv ] +.RB [ \-c +.IR file ] +.RB [ \-w +.IR file ] +.RB [ \-o +.IR format ] +.in +6 +.RB [ \-s +.IR tag ] +.RB [ \-t +.IR NAME=value ] +.I device +[\fIdevice\fR ...] +.in -6 + +.B blkid +.RB -p +.RB [ \-O +.IR offset ] +.RB [ \-S +.IR size ] +.RB [ \-o +.IR format ] +.RB [ \-u +.IR list ] +.I device +[\fIdevice\fR ...] + +.SH DESCRIPTION +The +.B blkid +program is the command-line interface to working with +.BR libblkid (3) +library. It can determine the type of content (e.g. filesystem, swap) +a block device holds, and also attributes (tokens, NAME=value pairs) +from the content metadata (e.g. LABEL or UUID fields). +.PP +.B blkid +has two main forms of operation: either searching for a device with a +specific NAME=value pair, or displaying NAME=value pairs for one or +more devices. +.SH OPTIONS +.TP +.BI \-c " cachefile" +Read from +.I cachefile +instead of reading from the default cache file +.IR /etc/blkid.tab . +If you want to start with a clean cache (i.e. don't report devices previously +scanned but not necessarily available at this time), specify +.IR /dev/null . +.TP +.B \-g +Perform a garbage collection pass on the blkid cache to remove +devices which no longer exist. +.TP +.B \-h +Display a usage message and exit. +.TP +.B \-l +Look up one device that matches the search parameter specified using +the +.B \-t +option. If there are multiple devices that match the specified search +parameter, then the device with the highest priority is returned, and/or +the first device found at a given priority. Device types in order of +decreasing priority are Device Mapper, EVMS, LVM, MD, and finally regular +block devices. If this option is not specified, +.B blkid +will print all of the devices that match the search parameter. +.TP +.B \-L " label " +Look up one device that uses the label (same as: -l -o device -t +LABEL=<label>). This look up method is able to reliable use /dev/disk/by-label +udev symlinks (depends on setting in /etc/blkid.conf). Avoid to use the +symlinks directly. It is not reliable to use the symlinks without verification. +The \fB-L\fR option is portable and works on systems with and without udev. +.TP +.B \-u " list " +Restrict probing functions to defined (comma separated) list of "usage" types. +Supported usage types are: filesystem, raid, crypto and other. The list can be +prefixed with "no" to specify the usage types which should be ignored. For example: +.sp + blkid -p -u filesystem,other /dev/sda1 +.sp +probes for all filesystems and others (e.g. swap) formats, and +.sp + blkid -p -u noraid /dev/sda1 +.sp +probes for all supported formats exclude RAIDs. This option is useful with +\fB-p\fR only. +.TP +.B \-U " uuid " +Look up one device that uses the uuid. For more details see the \fB-L\fR option. +.TP +.BI \-o " format" +Display +.BR blkid 's +output using the specified format. The +.I format +parameter may be: +.RS +.TP +.B full +print all tags (the default) +.TP +.B value +print the value of the tags +.TP +.B list +print the devices in a user-friendly format +.TP +.B device +print the device name only +.TP +.B udev +vol_id compatible mode; usable in udev rules +.RE +.TP +.BI \-O " bytes" +Probe at the given offset (only useful with \fB-p\fR). +.TP +.BI \-p +Switch to low-level probing mode (bypass cache)" +.TP +.BI \-s " tag" +For each (specified) device, show only the tags that match +.IR tag . +It is possible to specify multiple +.B \-s +options. If no tag is specified, then all tokens are shown for all +(specified) devices. +In order to just refresh the cache without showing any tokens, use +.B "-s none" +with no other options. +.TP +.BI \-S " bytes" +Overwrite device/file size (only useful with \fB-p\fR). +.TP +.BI \-t " NAME" = "value" +Search for block devices with tokens named +.I NAME +that have the value +.IR value , +and display any devices which are found. +Common values for +.I NAME +include +.BR TYPE , +.BR LABEL , +and +.BR UUID . +If there are no devices specified on the command line, all block devices +will be searched; otherwise only the specified devices are searched. +.TP +.B \-v +Display version number and exit. +.TP +.BI \-w " writecachefile" +Write the device cache to +.I writecachefile +instead of writing it to the default cache file +.IR /etc/blkid.tab . +If you don't want to save the cache to the default file, specify +.IR /dev/null. +If not specified it will be the same file as that given by the +.B \-c +option. +.TP +.I device +Display tokens from only the specified device. It is possible to +give multiple +.I device +options on the command line. If none is given, all devices which +appear in +.I /proc/partitions +are shown, if they are recognized. +.SH "RETURN CODE" +If the specified token was found, or if any tags were shown from (specified) +devices, 0 is returned. If the specified token was not found, or no +(specified) devices could be identified, an exit code of 2 is returned. +For usage or other errors, an exit code of 4 is returned. +.SH AUTHOR +.B blkid +was written by Andreas Dilger for libblkid and improved by Theodore Ts'o +and Karel Zak. +.SH AVAILABILITY +The blkid command is part of the util-linux-ng package and is available from +ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/. +.SH "SEE ALSO" +.BR libblkid (3) +.BR findfs (8) diff --git a/shlibs/blkid/bin/blkid.c b/shlibs/blkid/bin/blkid.c new file mode 100644 index 000000000..528e4a222 --- /dev/null +++ b/shlibs/blkid/bin/blkid.c @@ -0,0 +1,633 @@ +/* + * blkid.c - User command-line interface for libblkid + * + * Copyright (C) 2001 Andreas Dilger + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#ifdef HAVE_TERMIOS_H +#include <termios.h> +#endif +#ifdef HAVE_TERMIO_H +#include <termio.h> +#endif +#ifdef HAVE_SYS_IOCTL_H +#include <sys/ioctl.h> +#endif +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#else +extern int getopt(int argc, char * const argv[], const char *optstring); +extern char *optarg; +extern int optind; +#endif + +#define OUTPUT_VALUE_ONLY 0x0001 +#define OUTPUT_DEVICE_ONLY 0x0002 +#define OUTPUT_PRETTY_LIST 0x0004 +#define OUTPUT_UDEV_LIST 0x0008 + +#include <blkid.h> + +const char *progname = "blkid"; + +static void print_version(FILE *out) +{ + fprintf(out, "%s from %s (libblkid %s, %s)\n", + progname, PACKAGE_STRING, LIBBLKID_VERSION, LIBBLKID_DATE); +} + +static void usage(int error) +{ + FILE *out = error ? stderr : stdout; + + print_version(out); + fprintf(out, + "Usage:\n" + " %1$s -L <label> | -U <uuid>\n\n" + " %1$s [-c <file>] [-ghlLv] [-o format] [-s <tag>] \n" + " [-t <token>] [-w <file>] [dev ...]\n\n" + " %1$s -p [-O <offset>] [-S <size>] [-o format] <dev> [dev ...]\n\n" + "Options:\n" + " -c <file> cache file (default: /etc/blkid.tab, /dev/null = none)\n" + " -h print this usage message and exit\n" + " -g garbage collect the blkid cache\n" + " -o <format> output format; can be one of:\n" + " value, device, list, udev or full; (default: full)\n" + " -s <tag> show specified tag(s) (default show all tags)\n" + " -t <token> find device with a specific token (NAME=value pair)\n" + " -l lookup the the first device with arguments specified by -t\n" + " -L <label> convert LABEL to device name\n" + " -U <uuid> convert UUID to device name\n" + " -v print version and exit\n" + " -w <file> write cache to different file (/dev/null = no write)\n" + " <dev> specify device(s) to probe (default: all devices)\n\n" + "Low-level probing options:\n" + " -p switch to low-level mode (bypass cache)\n" + " -S <bytes> overwrite device size\n" + " -O <bytes> probe at the given offset\n" + " -u <list> filter by \"usage\" (e.g. -u filesystem,raid)\n" + "\n", + progname); + + exit(error); +} + +/* + * This function does "safe" printing. It will convert non-printable + * ASCII characters using '^' and M- notation. + */ +static void safe_print(const char *cp, int len) +{ + unsigned char ch; + + if (len < 0) + len = strlen(cp); + + while (len--) { + ch = *cp++; + if (ch > 128) { + fputs("M-", stdout); + ch -= 128; + } + if ((ch < 32) || (ch == 0x7f)) { + fputc('^', stdout); + ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */ + } + fputc(ch, stdout); + } +} + +static int get_terminal_width(void) +{ +#ifdef TIOCGSIZE + struct ttysize t_win; +#endif +#ifdef TIOCGWINSZ + struct winsize w_win; +#endif + const char *cp; + +#ifdef TIOCGSIZE + if (ioctl (0, TIOCGSIZE, &t_win) == 0) + return (t_win.ts_cols); +#endif +#ifdef TIOCGWINSZ + if (ioctl (0, TIOCGWINSZ, &w_win) == 0) + return (w_win.ws_col); +#endif + cp = getenv("COLUMNS"); + if (cp) + return strtol(cp, NULL, 10); + return 80; +} + +static int pretty_print_word(const char *str, int max_len, + int left_len, int overflow_nl) +{ + int len = strlen(str) + left_len; + int ret = 0; + + fputs(str, stdout); + if (overflow_nl && len > max_len) { + fputc('\n', stdout); + len = 0; + } else if (len > max_len) + ret = len - max_len; + do + fputc(' ', stdout); + while (len++ < max_len); + return ret; +} + +static void pretty_print_line(const char *device, const char *fs_type, + const char *label, const char *mtpt, + const char *uuid) +{ + static int device_len = 10, fs_type_len = 7; + static int label_len = 8, mtpt_len = 14; + static int term_width = -1; + int len, w; + + if (term_width < 0) + term_width = get_terminal_width(); + + if (term_width > 80) { + term_width -= 80; + w = term_width / 10; + if (w > 8) + w = 8; + term_width -= 2*w; + label_len += w; + fs_type_len += w; + w = term_width/2; + device_len += w; + mtpt_len +=w; + } + + len = pretty_print_word(device, device_len, 0, 1); + len = pretty_print_word(fs_type, fs_type_len, len, 0); + len = pretty_print_word(label, label_len, len, 0); + len = pretty_print_word(mtpt, mtpt_len, len, 0); + fputs(uuid, stdout); + fputc('\n', stdout); +} + +static void pretty_print_dev(blkid_dev dev) +{ + fprintf(stderr, "pretty print not implemented yet\n"); + +#ifdef NOT_IMPLEMENTED + blkid_tag_iterate iter; + const char *type, *value, *devname; + const char *uuid = "", *fs_type = "", *label = ""; + char *cp; + int len, mount_flags; + char mtpt[80]; + errcode_t retval; + + if (dev == NULL) { + pretty_print_line("device", "fs_type", "label", + "mount point", "UUID"); + for (len=get_terminal_width()-1; len > 0; len--) + fputc('-', stdout); + fputc('\n', stdout); + return; + } + + devname = blkid_dev_devname(dev); + if (access(devname, F_OK)) + return; + + /* Get the uuid, label, type */ + iter = blkid_tag_iterate_begin(dev); + while (blkid_tag_next(iter, &type, &value) == 0) { + if (!strcmp(type, "UUID")) + uuid = value; + if (!strcmp(type, "TYPE")) + fs_type = value; + if (!strcmp(type, "LABEL")) + label = value; + } + blkid_tag_iterate_end(iter); + + /* Get the mount point */ + mtpt[0] = 0; + retval = ext2fs_check_mount_point(devname, &mount_flags, + mtpt, sizeof(mtpt)); + if (retval == 0) { + if (mount_flags & EXT2_MF_MOUNTED) { + if (!mtpt[0]) + strcpy(mtpt, "(mounted, mtpt unknown)"); + } else if (mount_flags & EXT2_MF_BUSY) + strcpy(mtpt, "(in use)"); + else + strcpy(mtpt, "(not mounted)"); + } + + pretty_print_line(devname, fs_type, label, mtpt, uuid); +#endif +} + +static void print_udev_format(const char *name, const char *value, size_t sz) +{ + char enc[265], safe[256]; + + *safe = *enc = '\0'; + + if (!strcmp(name, "TYPE") || !strcmp(name, "VERSION")) { + blkid_encode_string(value, enc, sizeof(enc)); + printf("ID_FS_%s=%s\n", name, enc); + + } else if (!strcmp(name, "UUID") || + !strcmp(name, "LABEL") || + !strcmp(name, "UUID_SUB")) { + + blkid_safe_string(value, safe, sizeof(safe)); + printf("ID_FS_%s=%s\n", name, safe); + + blkid_encode_string(value, enc, sizeof(enc)); + printf("ID_FS_%s_ENC=%s\n", name, enc); + } + else + printf("ID_FS_%s=%s\n", name, value); +} + +static void print_value(int output, int num, const char *devname, + const char *value, const char *name, size_t valsz) +{ + if (output & OUTPUT_VALUE_ONLY) { + fputs(value, stdout); + fputc('\n', stdout); + + } else if (output & OUTPUT_UDEV_LIST) { + print_udev_format(name, value, valsz); + + } else { + if (num == 1 && devname) + printf("%s: ", devname); + fputs(name, stdout); + fputs("=\"", stdout); + safe_print(value, valsz); + fputs("\" ", stdout); + } +} + +static void print_tags(blkid_dev dev, char *show[], int numtag, int output) +{ + blkid_tag_iterate iter; + const char *type, *value, *devname; + int i, num = 1; + + if (!dev) + return; + + if (output & OUTPUT_PRETTY_LIST) { + pretty_print_dev(dev); + return; + } + + devname = blkid_dev_devname(dev); + + if (output & OUTPUT_DEVICE_ONLY) { + printf("%s\n", devname); + return; + } + + iter = blkid_tag_iterate_begin(dev); + while (blkid_tag_next(iter, &type, &value) == 0) { + if (numtag && show) { + for (i=0; i < numtag; i++) + if (!strcmp(type, show[i])) + break; + if (i >= numtag) + continue; + } + print_value(output, num++, devname, value, type, strlen(value)); + } + blkid_tag_iterate_end(iter); + + if (num > 1 && !(output & (OUTPUT_VALUE_ONLY | OUTPUT_UDEV_LIST))) + printf("\n"); +} + +static int lowprobe_device(blkid_probe pr, const char *devname, int output, + blkid_loff_t offset, blkid_loff_t size) +{ + const char *data; + const char *name; + int nvals = 0, n; + size_t len; + int fd; + int rc = 0; + + fd = open(devname, O_RDONLY); + if (fd < 0) + return 2; + + if (blkid_probe_set_device(pr, fd, offset, size)) + goto done; + rc = blkid_do_safeprobe(pr); + if (rc) + goto done; + + nvals = blkid_probe_numof_values(pr); + + if (output & OUTPUT_DEVICE_ONLY) { + printf("%s\n", devname); + goto done; + } + + for (n = 0; n < nvals; n++) { + if (blkid_probe_get_value(pr, n, &name, &data, &len)) + continue; + + len = strnlen((char *) data, len); + print_value(output, n + 1, devname, (char *) data, name, len); + } + + if (nvals > 1 && !(output & (OUTPUT_VALUE_ONLY | OUTPUT_UDEV_LIST))) + printf("\n"); +done: + if (rc == -2) + fprintf(stderr, "%s: ambivalent result " + "(probably more filesystems on the device)\n", + devname); + close(fd); + return !nvals ? 2 : 0; +} + +/* converts comma separated list to BLKID_USAGE_* mask */ +static int list_to_usage(const char *list, int *flag) +{ + int mask = 0; + const char *word, *p = list; + + if (p && strncmp(p, "no", 2) == 0) { + *flag = BLKID_FLTR_NOTIN; + p += 2; + } + + for (word = p; p && *p; p++) { + if (*p == ',' || *(p + 1) == '\0') { + if (!strncmp(word, "filesystem", 10)) + mask |= BLKID_USAGE_FILESYSTEM; + else if (!strncmp(word, "raid", 4)) + mask |= BLKID_USAGE_RAID; + else if (!strncmp(word, "crypto", 6)) + mask |= BLKID_USAGE_CRYPTO; + else if (!strncmp(word, "other", 5)) + mask |= BLKID_USAGE_OTHER; + else { + fprintf(stderr, "unknown usage keyword '%*s'\n", + (int) (p - word), word); + exit(4); + } + word = p + 1; + } + } + return mask; +} + +int main(int argc, char **argv) +{ + blkid_cache cache = NULL; + char *devices[128] = { NULL, }; + char *show[128] = { NULL, }; + char *search_type = NULL, *search_value = NULL; + char *read = NULL; + char *write = NULL; + int fltr_usage = 0; + int fltr_flag = BLKID_FLTR_ONLYIN; + unsigned int numdev = 0, numtag = 0; + int version = 0; + int err = 4; + unsigned int i; + int output_format = 0; + int lookup = 0, gc = 0, lowprobe = 0, eval = 0; + int c; + blkid_loff_t offset = 0, size = 0; + + while ((c = getopt (argc, argv, "c:f:ghlL:o:O:ps:S:t:u:U:w:v")) != EOF) + switch (c) { + case 'c': + if (optarg && !*optarg) + read = NULL; + else + read = optarg; + if (!write) + write = read; + break; + case 'L': + eval++; + search_value = strdup(optarg); + search_type = strdup("LABEL"); + break; + case 'u': + fltr_usage = list_to_usage(optarg, &fltr_flag); + break; + case 'U': + eval++; + search_value = strdup(optarg); + search_type = strdup("UUID"); + break; + case 'l': + lookup++; + break; + case 'g': + gc = 1; + break; + case 'o': + if (!strcmp(optarg, "value")) + output_format = OUTPUT_VALUE_ONLY; + else if (!strcmp(optarg, "device")) + output_format = OUTPUT_DEVICE_ONLY; + else if (!strcmp(optarg, "list")) + output_format = OUTPUT_PRETTY_LIST; + else if (!strcmp(optarg, "udev")) + output_format = OUTPUT_UDEV_LIST; + else if (!strcmp(optarg, "full")) + output_format = 0; + else { + fprintf(stderr, "Invalid output format %s. " + "Choose from value,\n\t" + "device, list, udev or full\n", optarg); + exit(4); + } + break; + case 'O': + offset = strtoll(optarg, NULL, 10); + break; + case 'p': + lowprobe++; + break; + case 's': + if (numtag >= sizeof(show) / sizeof(*show)) { + fprintf(stderr, "Too many tags specified\n"); + usage(err); + } + show[numtag++] = optarg; + break; + case 'S': + size = strtoll(optarg, NULL, 10); + break; + case 't': + if (search_type) { + fprintf(stderr, "Can only search for " + "one NAME=value pair\n"); + usage(err); + } + if (blkid_parse_tag_string(optarg, + &search_type, + &search_value)) { + fprintf(stderr, "-t needs NAME=value pair\n"); + usage(err); + } + break; + case 'v': + version = 1; + break; + case 'w': + if (optarg && !*optarg) + write = NULL; + else + write = optarg; + break; + case 'h': + err = 0; + default: + usage(err); + } + + while (optind < argc) + devices[numdev++] = argv[optind++]; + + if (version) { + print_version(stdout); + goto exit; + } + + /* convert LABEL/UUID lookup to evaluate request */ + if (lookup && output_format == OUTPUT_DEVICE_ONLY && search_type && + (!strcmp(search_type, "LABEL") || !strcmp(search_type, "UUID"))) { + eval++; + lookup = 0; + } + + if (!lowprobe && !eval && blkid_get_cache(&cache, read) < 0) + goto exit; + + if (gc) { + blkid_gc_cache(cache); + err = 0; + goto exit; + } + err = 2; + + if (output_format & OUTPUT_PRETTY_LIST) + pretty_print_dev(NULL); + + if (lowprobe) { + /* + * Low-level API + */ + blkid_probe pr; + + if (!numdev) { + fprintf(stderr, "The low-probe option requires a device\n"); + exit(4); + } + pr = blkid_new_probe(); + if (!pr) + goto exit; + blkid_probe_set_request(pr, + BLKID_PROBREQ_LABEL | BLKID_PROBREQ_UUID | + BLKID_PROBREQ_TYPE | BLKID_PROBREQ_SECTYPE | + BLKID_PROBREQ_USAGE | BLKID_PROBREQ_VERSION); + if (fltr_usage && + blkid_probe_filter_usage(pr, fltr_flag, fltr_usage)) + goto exit; + + for (i = 0; i < numdev; i++) + err = lowprobe_device(pr, devices[i], + output_format, offset, size); + blkid_free_probe(pr); + } else if (eval) { + /* + * Evaluate API + */ + char *res = blkid_evaluate_tag(search_type, search_value, NULL); + if (res) { + err = 0; + printf("%s\n", res); + } + } else if (lookup) { + /* + * Classic (cache based) API + */ + blkid_dev dev; + + if (!search_type) { + fprintf(stderr, "The lookup option requires a " + "search type specified using -t\n"); + exit(4); + } + /* Load any additional devices not in the cache */ + for (i = 0; i < numdev; i++) + blkid_get_dev(cache, devices[i], BLKID_DEV_NORMAL); + + if ((dev = blkid_find_dev_with_tag(cache, search_type, + search_value))) { + print_tags(dev, show, numtag, output_format); + err = 0; + } + /* If we didn't specify a single device, show all available devices */ + } else if (!numdev) { + blkid_dev_iterate iter; + blkid_dev dev; + + blkid_probe_all(cache); + + iter = blkid_dev_iterate_begin(cache); + blkid_dev_set_search(iter, search_type, search_value); + while (blkid_dev_next(iter, &dev) == 0) { + dev = blkid_verify(cache, dev); + if (!dev) + continue; + print_tags(dev, show, numtag, output_format); + err = 0; + } + blkid_dev_iterate_end(iter); + /* Add all specified devices to cache (optionally display tags) */ + } else for (i = 0; i < numdev; i++) { + blkid_dev dev = blkid_get_dev(cache, devices[i], + BLKID_DEV_NORMAL); + + if (dev) { + if (search_type && + !blkid_dev_has_tag(dev, search_type, + search_value)) + continue; + print_tags(dev, show, numtag, output_format); + err = 0; + } + } + +exit: + free(search_type); + free(search_value); + if (!lowprobe && !eval) + blkid_put_cache(cache); + return err; +} diff --git a/shlibs/blkid/bin/blkid.sh.in b/shlibs/blkid/bin/blkid.sh.in new file mode 100644 index 000000000..3e10add11 --- /dev/null +++ b/shlibs/blkid/bin/blkid.sh.in @@ -0,0 +1,10 @@ +#!/bin/bash + +# libtool? Don't ask! + +BLKIDDIR=@SRCDIR@/libs/blkid +BINARY=$BLKIDDIR/bin/blkid +LD_LIBRARY_PATH=$BLKIDDIR/src/ + +export LD_LIBRARY_PATH +exec $BINARY $@ diff --git a/shlibs/blkid/bin/findfs.8 b/shlibs/blkid/bin/findfs.8 new file mode 100644 index 000000000..e93fe5421 --- /dev/null +++ b/shlibs/blkid/bin/findfs.8 @@ -0,0 +1,35 @@ +.\" -*- nroff -*- +.\" Copyright 1993, 1994, 1995 by Theodore Ts'o. All Rights Reserved. +.\" This file may be copied under the terms of the GNU Public License. +.\" +.TH FINDFS 8 "February 2009" "Linux" "MAINTENANCE COMMANDS" +.SH NAME +findfs \- Find a filesystem by label or UUID +.SH SYNOPSIS +.B findfs +.BI LABEL= label +.sp +.B findfs +.BI UUID= uuid +.SH DESCRIPTION +.B findfs +will search the disks in the system looking for a filesystem which has +a label matching +.I label +or a UUID equal to +.IR uuid . +If the filesystem is found, the device name for the filesystem will +be printed on stdout. +.PP +.SH AUTHOR +.B findfs +was originally written by Theodore Ts'o (tytso@mit.edu) and re-written for +util-linux-ng package by Karel Zak (kzak@redhat.com). +.SH AVAILABILITY +.B findfs +The blkid command is part of the util-linux-ng package and is available from +ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/. +.SH SEE ALSO +.BR blkid (8) +.BR fsck (8) + diff --git a/shlibs/blkid/bin/findfs.c b/shlibs/blkid/bin/findfs.c new file mode 100644 index 000000000..18608b470 --- /dev/null +++ b/shlibs/blkid/bin/findfs.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2009 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the GNU Public + * License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <err.h> + +#include <blkid.h> + +#include "nls.h" + +static void __attribute__((__noreturn__)) usage(int rc) +{ + const char *p = program_invocation_short_name; + + if (!p) + p = "findfs"; + + fprintf(stderr, _("Usage: %s LABEL=<label>|UUID=<uuid>\n"), p); + exit(rc); +} + +int main(int argc, char **argv) +{ + char *dev, *tk, *vl; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + if (argc != 2) + /* we return '2' for backward compatibility + * with version from e2fsprogs */ + usage(2); + + if (!strncmp(argv[1], "LABEL=", 6)) { + tk = "LABEL"; + vl = argv[1] + 6; + } else if (!strncmp(argv[1], "UUID=", 5)) { + tk = "UUID"; + vl = argv[1] + 5; + } else if (!strcmp(argv[1], "-h") == 0 || + !strcmp(argv[1], "--help") == 0) { + usage(EXIT_SUCCESS); + } else + usage(2); + + dev = blkid_evaluate_tag(tk, vl, NULL); + if (!dev) + errx(EXIT_FAILURE, _("unable to resolve '%s'"), argv[1]); + + puts(dev); + exit(EXIT_SUCCESS); +} + diff --git a/shlibs/blkid/bin/findfs.sh.in b/shlibs/blkid/bin/findfs.sh.in new file mode 100644 index 000000000..37876c76e --- /dev/null +++ b/shlibs/blkid/bin/findfs.sh.in @@ -0,0 +1,10 @@ +#!/bin/bash + +# libtool? Don't ask! + +BLKIDDIR=@SRCDIR@/libs/blkid +BINARY=$BLKIDDIR/bin/findfs +LD_LIBRARY_PATH=$BLKIDDIR/src/ + +export LD_LIBRARY_PATH +exec $BINARY $@ diff --git a/shlibs/blkid/blkid.pc.in b/shlibs/blkid/blkid.pc.in new file mode 100644 index 000000000..5d58c3e19 --- /dev/null +++ b/shlibs/blkid/blkid.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: blkid +Description: Block device id library +Version: @LIBBLKID_VERSION@ +Requires.private: uuid +Cflags: -I${includedir}/blkid +Libs: -L${libdir} -lblkid diff --git a/shlibs/blkid/libblkid.3 b/shlibs/blkid/libblkid.3 new file mode 100644 index 000000000..89747ecf1 --- /dev/null +++ b/shlibs/blkid/libblkid.3 @@ -0,0 +1,81 @@ +.\" Copyright 2001 Andreas Dilger (adilger@turbolinux.com) +.\" +.\" This man page was created for libblkid.so.1.0 from e2fsprogs-1.24. +.\" +.\" This file may be copied under the terms of the GNU Public License. +.\" +.\" Created Wed Sep 14 12:02:12 2001, Andreas Dilger +.TH LIBBLKID 3 "February 2009" "Linux" "MAINTENANCE COMMANDS"" +.SH NAME +libblkid \- block device identification library +.SH SYNOPSIS +.B #include <blkid/blkid.h> +.sp +.B cc +.I file.c +.B \-lblkid +.SH DESCRIPTION +The +.B libblkid +library is used to identify block devices (disks) as to their content (e.g. +filesystem type) as well as extracting additional information such as +filesystem labels/volume names, unique identifiers/serial numbers, etc. +A common use is to allow use of LABEL= and UUID= tags instead of hard-coding +specific block device names into configuration files. +.P +Block device information is normally kept in a cache file +.I /etc/blkid.tab +and is verified to still be valid before being returned to the user +(if the user has read permission on the raw block device, otherwise not). +The cache file also allows unprivileged users (normally anyone other +than root, or those not in the "disk" group) to locate devices by label/id. +The standard location of the cache file can be overridden by the +environment variable BLKID_FILE. +.P +In situations where one is getting information about a single known device, +it does not impact performance whether the cache is used or not (unless you +are not able to read the block device directly). If you are dealing with +multiple devices, use of the cache is highly recommended (even if empty) as +devices will be scanned at most one time and the on-disk cache will be +updated if possible. There is rarely a reason not to use the cache. +.P +In some cases (modular kernels), block devices are not even visible until +after they are accessed the first time, so it is critical that there is +some way to locate these devices without enumerating only visible devices, +so the use of the cache file is +.B required +in this situation. +.SH AUTHOR +.B libblkid +was written by Andreas Dilger for the ext2 filesystem utilties, with input +from Ted Ts'o. The library was subsequently heavily modified by Ted Ts'o. +.SH FILES +.TP +.I /etc/blkid.tab +Caches data extracted from each recognized block device. +.SH AVAILABILITY +.B libblkid +is part of the util-linux-ng package since version 2.15 and is available from +ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/. +.SH COPYING +.B libblkid +is available under the terms of the GNU Library General Public License (LGPL), +version 2 (or at your discretion any later version). A copy of the LGPL +should be included with this library in the file COPYING. If not, write to +.RS +Free Software Foundation, Inc. +.br +51 Franklin St +.br +Fifth Floor +.br +Boston, MA 02110-1301 USA +.RE +.PP +or visit +.UR http://www.gnu.org/licenses/licenses.html#LGPL +http://www.gnu.org/licenses/licenses.html#LGPL +.UE +.SH "SEE ALSO" +.BR blkid (8) +.BR findfs (8) diff --git a/shlibs/blkid/src/Makefile.am b/shlibs/blkid/src/Makefile.am new file mode 100644 index 000000000..805d0899b --- /dev/null +++ b/shlibs/blkid/src/Makefile.am @@ -0,0 +1,45 @@ +include $(top_srcdir)/config/include-Makefile.am + +SUBDIRS = probers . + +AM_CPPFLAGS += -I$(top_srcdir)/libs/blkid/src + +common_ldadd = + +if HAVE_UUID +common_ldadd += -luuid #TODO $(UUID_LIBS) +endif + +# includes +blkidincdir = $(includedir)/blkid +blkidinc_HEADERS = blkid.h + +lib_LTLIBRARIES = libblkid.la +libblkid_la_SOURCES = cache.c dev.c devname.c devno.c getsize.c llseek.c \ + probe.c read.c resolve.c save.c tag.c version.c verify.c \ + encode.c blkid.h list.h blkidP.h probers/probers.h \ + config.c evaluate.c \ + $(blkidinc_HEADERS) \ + $(top_srcdir)/lib/blkdev.c \ + $(top_srcdir)/lib/linux_version.c \ + $(top_srcdir)/lib/canonicalize.c \ + $(top_srcdir)/lib/md5.c + +libblkid_la_LIBADD = probers/libblkid_probers.la $(common_ldadd) +libblkid_la_DEPENDENCIES = $(libblkid_la_LIBADD) blkid.sym + +# TODO: for unknown reason "make distcheck" requires +# full path to the version script +libblkid_la_LDFLAGS = -Wl,--version-script=$(top_srcdir)/libs/blkid/src/blkid.sym \ + -version-info 1:0:0 + +tests = test_cache test_config test_dev test_devname test_devno test_getsize \ + test_read test_resolve test_save test_tag test_verify test_evaluate + +EXTRA_DIST = blkid.sym tst_types.c +CLEANFILES = $(tests) + +tests: all $(tests) +test_%: %.c + $(COMPILE) -DTEST_PROGRAM $< .libs/libblkid.a -o $@ $(common_ldadd) + diff --git a/shlibs/blkid/src/blkid.h b/shlibs/blkid/src/blkid.h new file mode 100644 index 000000000..43b2b5529 --- /dev/null +++ b/shlibs/blkid/src/blkid.h @@ -0,0 +1,171 @@ +/* + * blkid.h - Interface for libblkid, a library to identify block devices + * + * Copyright (C) 2001 Andreas Dilger + * Copyright (C) 2003 Theodore Ts'o + * Copyright (C) 2008 Karel Zak <kzak@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.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _BLKID_BLKID_H +#define _BLKID_BLKID_H + +#include <stdint.h> +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct blkid_struct_dev *blkid_dev; +typedef struct blkid_struct_cache *blkid_cache; +typedef struct blkid_struct_probe *blkid_probe; + +typedef int64_t blkid_loff_t; + +typedef struct blkid_struct_tag_iterate *blkid_tag_iterate; +typedef struct blkid_struct_dev_iterate *blkid_dev_iterate; + +/* + * Flags for blkid_get_dev + * + * BLKID_DEV_CREATE Create an empty device structure if not found + * in the cache. + * BLKID_DEV_VERIFY Make sure the device structure corresponds + * with reality. + * BLKID_DEV_FIND Just look up a device entry, and return NULL + * if it is not found. + * BLKID_DEV_NORMAL Get a valid device structure, either from the + * cache or by probing the device. + */ +#define BLKID_DEV_FIND 0x0000 +#define BLKID_DEV_CREATE 0x0001 +#define BLKID_DEV_VERIFY 0x0002 +#define BLKID_DEV_NORMAL (BLKID_DEV_CREATE | BLKID_DEV_VERIFY) + +/* cache.c */ +extern void blkid_put_cache(blkid_cache cache); +extern int blkid_get_cache(blkid_cache *cache, const char *filename); +extern void blkid_gc_cache(blkid_cache cache); + +/* dev.c */ +extern const char *blkid_dev_devname(blkid_dev dev); + +extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache); +extern int blkid_dev_set_search(blkid_dev_iterate iter, + char *search_type, char *search_value); +extern int blkid_dev_next(blkid_dev_iterate iterate, blkid_dev *dev); +extern void blkid_dev_iterate_end(blkid_dev_iterate iterate); + +/* devno.c */ +extern char *blkid_devno_to_devname(dev_t devno); + +/* devname.c */ +extern int blkid_probe_all(blkid_cache cache); +extern int blkid_probe_all_new(blkid_cache cache); +extern blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, + int flags); + +/* getsize.c */ +extern blkid_loff_t blkid_get_dev_size(int fd); + +/* verify.c */ +extern blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev); + +/* read.c */ + +/* resolve.c */ +extern char *blkid_get_tag_value(blkid_cache cache, const char *tagname, + const char *devname); +extern char *blkid_get_devname(blkid_cache cache, const char *token, + const char *value); + +/* tag.c */ +extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev); +extern int blkid_tag_next(blkid_tag_iterate iterate, + const char **type, const char **value); +extern void blkid_tag_iterate_end(blkid_tag_iterate iterate); +extern int blkid_dev_has_tag(blkid_dev dev, const char *type, + const char *value); +extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache, + const char *type, + const char *value); +extern int blkid_parse_tag_string(const char *token, char **ret_type, + char **ret_val); + +/* version.c */ +extern int blkid_parse_version_string(const char *ver_string); +extern int blkid_get_library_version(const char **ver_string, + const char **date_string); + +/* encode.c */ +extern int blkid_encode_string(const char *str, char *str_enc, size_t len); +extern int blkid_safe_string(const char *str, char *str_safe, size_t len); + +/* evaluate.c */ +extern int blkid_send_uevent(const char *devname, const char *action); +extern char *blkid_evaluate_tag(const char *token, const char *value, + blkid_cache *cache); + +/* probe.c */ +extern int blkid_known_fstype(const char *fstype); +extern blkid_probe blkid_new_probe(void); +extern void blkid_free_probe(blkid_probe pr); +extern void blkid_reset_probe(blkid_probe pr); + +extern int blkid_probe_set_device(blkid_probe pr, int fd, + blkid_loff_t off, blkid_loff_t size); + +#define BLKID_PROBREQ_LABEL (1 << 1) +#define BLKID_PROBREQ_LABELRAW (1 << 2) +#define BLKID_PROBREQ_UUID (1 << 3) +#define BLKID_PROBREQ_UUIDRAW (1 << 4) +#define BLKID_PROBREQ_TYPE (1 << 5) +#define BLKID_PROBREQ_SECTYPE (1 << 6) +#define BLKID_PROBREQ_USAGE (1 << 7) +#define BLKID_PROBREQ_VERSION (1 << 8) +extern int blkid_probe_set_request(blkid_probe pr, int flags); + +#define BLKID_USAGE_FILESYSTEM (1 << 1) +#define BLKID_USAGE_RAID (1 << 2) +#define BLKID_USAGE_CRYPTO (1 << 3) +#define BLKID_USAGE_OTHER (1 << 4) +extern int blkid_probe_filter_usage(blkid_probe pr, int flag, int usage); + +#define BLKID_FLTR_NOTIN 1 +#define BLKID_FLTR_ONLYIN 2 +extern int blkid_probe_filter_types(blkid_probe pr, + int flag, char *names[]); + + +extern int blkid_probe_invert_filter(blkid_probe pr); +extern int blkid_probe_reset_filter(blkid_probe pr); + +extern int blkid_do_probe(blkid_probe pr); +extern int blkid_do_safeprobe(blkid_probe pr); + +extern int blkid_probe_numof_values(blkid_probe pr); +extern int blkid_probe_get_value(blkid_probe pr, int num, const char **name, + const char **data, size_t *len); +extern int blkid_probe_lookup_value(blkid_probe pr, const char *name, + const char **data, size_t *len); +extern int blkid_probe_has_value(blkid_probe pr, const char *name); + +#ifdef __cplusplus +} +#endif + +#endif /* _BLKID_BLKID_H */ diff --git a/shlibs/blkid/src/blkid.sym b/shlibs/blkid/src/blkid.sym new file mode 100644 index 000000000..562f44d0c --- /dev/null +++ b/shlibs/blkid/src/blkid.sym @@ -0,0 +1,68 @@ +/* + * The symbol versioning ensures that a new application requiring symbol foo() + * can't run with old libblkid.so not providing foo() - the global SONAME + * version info can't enforce this since we never change the SONAME. + * + * The original libblkid from e2fsprogs (<=1.41.4) does not to use + * symbol versioning -- all the original symbols are in BLKID_1.0 now. + */ +BLKID_1.0 { +global: + blkid_dev_devname; + blkid_dev_has_tag; + blkid_dev_iterate_begin; + blkid_dev_iterate_end; + blkid_dev_next; + blkid_devno_to_devname; + blkid_dev_set_search; + blkid_find_dev_with_tag; + blkid_gc_cache; + blkid_get_cache; + blkid_get_dev; + blkid_get_devname; + blkid_get_dev_size; + blkid_get_library_version; + blkid_get_tag_value; + blkid_known_fstype; + blkid_parse_tag_string; + blkid_parse_version_string; + blkid_probe_all; + blkid_probe_all_new; + blkid_put_cache; + blkid_tag_iterate_begin; + blkid_tag_iterate_end; + blkid_tag_next; + blkid_verify; +local: + *; +}; + + +/* + * version(s) since util-linux-ng 2.15 + */ +BLKID_2.15 { +global: + blkid_do_probe; + blkid_do_safeprobe; + blkid_encode_string; + blkid_evaluate_tag; + blkid_free_probe; + blkid_new_probe; + blkid_probe_all; + blkid_probe_all_new; + blkid_probe_filter_types; + blkid_probe_filter_usage; + blkid_probe_get_value; + blkid_probe_has_value; + blkid_probe_invert_filter; + blkid_probe_lookup_value; + blkid_probe_numof_values; + blkid_probe_reset_filter; + blkid_probe_set_device; + blkid_probe_set_request; + blkid_reset_probe; + blkid_safe_string; + blkid_send_uevent; +} BLKID_1.0; + diff --git a/shlibs/blkid/src/blkidP.h b/shlibs/blkid/src/blkidP.h new file mode 100644 index 000000000..4131c5bba --- /dev/null +++ b/shlibs/blkid/src/blkidP.h @@ -0,0 +1,343 @@ +/* + * blkidP.h - Internal interfaces for libblkid + * + * Copyright (C) 2001 Andreas Dilger + * Copyright (C) 2003 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#ifndef _BLKID_BLKIDP_H +#define _BLKID_BLKIDP_H + + +#define CONFIG_BLKID_DEBUG 1 + +#include <sys/types.h> +#include <stdio.h> + +#include "bitops.h" /* $(top_srcdir)/include/ */ +#include "blkid.h" +#include "list.h" + +#ifdef __GNUC__ +#define __BLKID_ATTR(x) __attribute__(x) +#else +#define __BLKID_ATTR(x) +#endif + +#ifndef TRUE +#define TRUE 1 +#define FALSE 1 +#endif + +#include <limits.h> +#ifndef PATH_MAX +# define PATH_MAX 4096 +#endif + +/* TODO: move to some top-level util-linux include file */ +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#endif + +/* + * This describes the attributes of a specific device. + * We can traverse all of the tags by bid_tags (linking to the tag bit_names). + * The bid_label and bid_uuid fields are shortcuts to the LABEL and UUID tag + * values, if they exist. + */ +struct blkid_struct_dev +{ + struct list_head bid_devs; /* All devices in the cache */ + struct list_head bid_tags; /* All tags for this device */ + blkid_cache bid_cache; /* Dev belongs to this cache */ + char *bid_name; /* Device inode pathname */ + char *bid_type; /* Preferred device TYPE */ + int bid_pri; /* Device priority */ + dev_t bid_devno; /* Device major/minor number */ + time_t bid_time; /* Last update time of device */ + unsigned int bid_flags; /* Device status bitflags */ + char *bid_label; /* Shortcut to device LABEL */ + char *bid_uuid; /* Shortcut to binary UUID */ +}; + +#define BLKID_BID_FL_VERIFIED 0x0001 /* Device data validated from disk */ +#define BLKID_BID_FL_INVALID 0x0004 /* Device is invalid */ + +/* + * Each tag defines a NAME=value pair for a particular device. The tags + * are linked via bit_names for a single device, so that traversing the + * names list will get you a list of all tags associated with a device. + * They are also linked via bit_values for all devices, so one can easily + * search all tags with a given NAME for a specific value. + */ +struct blkid_struct_tag +{ + struct list_head bit_tags; /* All tags for this device */ + struct list_head bit_names; /* All tags with given NAME */ + char *bit_name; /* NAME of tag (shared) */ + char *bit_val; /* value of tag */ + blkid_dev bit_dev; /* pointer to device */ +}; +typedef struct blkid_struct_tag *blkid_tag; + +/* + * Low-level probe result + */ +#define BLKID_PROBVAL_BUFSIZ 64 +#define BLKID_PROBVAL_NVALS 8 /* see blkid.h BLKID_PROBREQ_* */ + +struct blkid_prval +{ + const char *name; /* value name */ + unsigned char data[BLKID_PROBVAL_BUFSIZ]; /* value data */ + size_t len; /* length of value data */ +}; + +/* + * Low-level probing control struct + */ +struct blkid_struct_probe +{ + int fd; /* device file descriptor */ + blkid_loff_t off; /* begin of data on the device */ + blkid_loff_t size; /* end of data on the device */ + + unsigned char *sbbuf; /* superblok buffer */ + size_t sbbuf_len; /* size of data in superblock buffer */ + + unsigned char *buf; /* seek buffer */ + blkid_loff_t buf_off; /* offset of seek buffer */ + size_t buf_len; /* size of data in seek buffer */ + size_t buf_max; /* allocated size of seek buffer */ + + struct blkid_prval vals[BLKID_PROBVAL_NVALS]; + int nvals; + + int probreq; /* BLKID_PROBREQ_* flags */ + int idx; /* index of the last prober */ + + unsigned long *fltr; /* filter */ +}; + +#define BLKID_SB_BUFSIZ 0x11000 + +/* + * Filesystem / Raid magic strings + */ +struct blkid_idmag +{ + const char *magic; /* magic string */ + unsigned len; /* length of magic */ + + long kboff; /* kilobyte offset of superblock */ + unsigned sboff; /* byte offset within superblock */ +}; + +/* + * Filesystem / Raid description + */ +struct blkid_idinfo +{ + const char *name; /* FS/RAID name */ + int usage; /* BLKID_USAGE_* flag */ + int flags; /* BLKID_IDINFO_* flags */ + + /* probe function */ + int (*probefunc)(blkid_probe pr, const struct blkid_idmag *mag); + + struct blkid_idmag magics[]; /* NULL or array with magic strings */ +}; + +#define BLKID_NONE_MAGIC {{ NULL }} + +/* + * tolerant FS - can share the same device with more filesystems (e.g. typical + * on CD-ROMs). We need this flag to detect ambivalent results (e.g. valid fat + * and valid linux swap on the same device). + */ +#define BLKID_IDINFO_TOLERANT (1 << 1) + +/* + * Evaluation methods (for blkid_eval_* API) + */ +enum { + BLKID_EVAL_UDEV = 0, + BLKID_EVAL_SCAN, + + __BLKID_EVAL_LAST +}; + +/* + * Library config options + */ +struct blkid_config { + int eval[__BLKID_EVAL_LAST]; /* array with EVALUATION=<udev,cache> options */ + int nevals; /* number of elems in eval array */ + int uevent; /* SEND_UEVENT=<yes|not> option */ + char *cachefile; /* CACHE_FILE=<path> option */ +}; + +extern struct blkid_config *blkid_read_config(const char *filename); +extern void blkid_free_config(struct blkid_config *conf); + +/* + * Minimum number of seconds between device probes, even when reading + * from the cache. This is to avoid re-probing all devices which were + * just probed by another program that does not share the cache. + */ +#define BLKID_PROBE_MIN 2 + +/* + * Time in seconds an entry remains verified in the in-memory cache + * before being reverified (in case of long-running processes that + * keep a cache in memory and continue to use it for a long time). + */ +#define BLKID_PROBE_INTERVAL 200 + +/* This describes an entire blkid cache file and probed devices. + * We can traverse all of the found devices via bic_list. + * We can traverse all of the tag types by bic_tags, which hold empty tags + * for each tag type. Those tags can be used as list_heads for iterating + * through all devices with a specific tag type (e.g. LABEL). + */ +struct blkid_struct_cache +{ + struct list_head bic_devs; /* List head of all devices */ + struct list_head bic_tags; /* List head of all tag types */ + time_t bic_time; /* Last probe time */ + time_t bic_ftime; /* Mod time of the cachefile */ + unsigned int bic_flags; /* Status flags of the cache */ + char *bic_filename; /* filename of cache */ + blkid_probe probe; /* low-level probing stuff */ +}; + +#define BLKID_BIC_FL_PROBED 0x0002 /* We probed /proc/partition devices */ +#define BLKID_BIC_FL_CHANGED 0x0004 /* Cache has changed from disk */ + +extern char *blkid_strdup(const char *s); +extern char *blkid_strndup(const char *s, const int length); + +#define BLKID_CACHE_FILE "/etc/blkid.tab" +#define BLKID_CONFIG_FILE "/etc/blkid.conf" + +#define BLKID_ERR_IO 5 +#define BLKID_ERR_PROC 9 +#define BLKID_ERR_MEM 12 +#define BLKID_ERR_CACHE 14 +#define BLKID_ERR_DEV 19 +#define BLKID_ERR_PARAM 22 +#define BLKID_ERR_BIG 27 + +/* + * Priority settings for different types of devices + */ +#define BLKID_PRI_DM 40 +#define BLKID_PRI_EVMS 30 +#define BLKID_PRI_LVM 20 +#define BLKID_PRI_MD 10 + +#if defined(TEST_PROGRAM) && !defined(CONFIG_BLKID_DEBUG) +#define CONFIG_BLKID_DEBUG +#endif + +#define DEBUG_CACHE 0x0001 +#define DEBUG_DUMP 0x0002 +#define DEBUG_DEV 0x0004 +#define DEBUG_DEVNAME 0x0008 +#define DEBUG_DEVNO 0x0010 +#define DEBUG_PROBE 0x0020 +#define DEBUG_READ 0x0040 +#define DEBUG_RESOLVE 0x0080 +#define DEBUG_SAVE 0x0100 +#define DEBUG_TAG 0x0200 +#define DEBUG_LOWPROBE 0x0400 +#define DEBUG_CONFIG 0x0800 +#define DEBUG_EVALUATE 0x1000 +#define DEBUG_INIT 0x8000 +#define DEBUG_ALL 0xFFFF + +#ifdef CONFIG_BLKID_DEBUG +#include <stdio.h> +extern int blkid_debug_mask; +extern void blkid_init_debug(int mask); +extern void blkid_debug_dump_dev(blkid_dev dev); +extern void blkid_debug_dump_tag(blkid_tag tag); + +#define DBG(m,x) if ((m) & blkid_debug_mask) x; + +#else /* !CONFIG_BLKID_DEBUG */ +#define DBG(m,x) +#define blkid_init_debug(x) +#endif /* CONFIG_BLKID_DEBUG */ + +/* devno.c */ +struct dir_list { + char *name; + struct dir_list *next; +}; +extern void blkid__scan_dir(char *, dev_t, struct dir_list **, char **); + +/* lseek.c */ +extern blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence); + +/* read.c */ +extern void blkid_read_cache(blkid_cache cache); + +/* save.c */ +extern int blkid_flush_cache(blkid_cache cache); + +/* cache */ +extern char *blkid_safe_getenv(const char *arg); +extern char *blkid_get_cache_filename(struct blkid_config *conf); + +/* + * Functions to create and find a specific tag type: tag.c + */ +extern void blkid_free_tag(blkid_tag tag); +extern blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type); +extern int blkid_set_tag(blkid_dev dev, const char *name, + const char *value, const int vlength); + +/* + * Functions to create and find a specific tag type: dev.c + */ +extern blkid_dev blkid_new_dev(void); +extern void blkid_free_dev(blkid_dev dev); + +/* probe.c */ +unsigned char *blkid_probe_get_buffer(blkid_probe pr, + blkid_loff_t off, blkid_loff_t len); + +/* returns superblok according to 'struct blkid_idmag' */ +#define blkid_probe_get_sb(_pr, _mag, type) \ + ((type *) blkid_probe_get_buffer((_pr),\ + (_mag)->kboff << 10, sizeof(type))) + +extern int blkid_probe_set_value(blkid_probe pr, const char *name, + unsigned char *data, size_t len); +extern int blkid_probe_vsprintf_value(blkid_probe pr, const char *name, + const char *fmt, va_list ap); +extern int blkid_probe_set_version(blkid_probe pr, const char *version); +extern int blkid_probe_sprintf_version(blkid_probe pr, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); + +extern int blkid_probe_set_label(blkid_probe pr, unsigned char *label, size_t len); +extern int blkid_probe_set_utf8label(blkid_probe pr, unsigned char *label, + size_t len, int enc); +extern int blkid_probe_sprintf_uuid(blkid_probe pr, unsigned char *uuid, + size_t len, const char *fmt, ...) + __attribute__ ((format (printf, 4, 5))); +extern int blkid_probe_strncpy_uuid(blkid_probe pr, unsigned char *str, size_t len); + +extern int blkid_probe_set_uuid(blkid_probe pr, unsigned char *uuid); +extern int blkid_probe_set_uuid_as(blkid_probe pr, unsigned char *uuid, const char *name); + +#define BLKID_ENC_UTF16BE 0 +#define BLKID_ENC_UTF16LE 1 + +#endif /* _BLKID_BLKIDP_H */ diff --git a/shlibs/blkid/src/cache.c b/shlibs/blkid/src/cache.c new file mode 100644 index 000000000..01e4be061 --- /dev/null +++ b/shlibs/blkid/src/cache.c @@ -0,0 +1,243 @@ +/* + * cache.c - allocation/initialization/free routines for cache + * + * Copyright (C) 2001 Andreas Dilger + * Copyright (C) 2003 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <stdlib.h> +#include <string.h> +#ifdef HAVE_SYS_PRCTL_H +#include <sys/prctl.h> +#else +#define PR_GET_DUMPABLE 3 +#endif +#if (!defined(HAVE_PRCTL) && defined(linux)) +#include <sys/syscall.h> +#endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#include "blkidP.h" + +int blkid_debug_mask = 0; + + +char *blkid_safe_getenv(const char *arg) +{ + if ((getuid() != geteuid()) || (getgid() != getegid())) + return NULL; +#if HAVE_PRCTL + if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) + return NULL; +#else +#if (defined(linux) && defined(SYS_prctl)) + if (syscall(SYS_prctl, PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) + return NULL; +#endif +#endif + +#ifdef HAVE___SECURE_GETENV + return __secure_getenv(arg); +#else + return getenv(arg); +#endif +} + +#if 0 /* ifdef CONFIG_BLKID_DEBUG */ +static blkid_debug_dump_cache(int mask, blkid_cache cache) +{ + struct list_head *p; + + if (!cache) { + printf("cache: NULL\n"); + return; + } + + printf("cache: time = %lu\n", cache->bic_time); + printf("cache: flags = 0x%08X\n", cache->bic_flags); + + list_for_each(p, &cache->bic_devs) { + blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs); + blkid_debug_dump_dev(dev); + } +} +#endif + +#ifdef CONFIG_BLKID_DEBUG +void blkid_init_debug(int mask) +{ + if (blkid_debug_mask & DEBUG_INIT) + return; + + if (!mask) + { + char *dstr = getenv("BLKID_DEBUG"); + + if (dstr) + blkid_debug_mask = strtoul(dstr, 0, 0); + } else + blkid_debug_mask = mask; + + if (blkid_debug_mask) + printf("libblkid: debug mask set to 0x%04x.\n", blkid_debug_mask); + + blkid_debug_mask |= DEBUG_INIT; +} +#endif + +/* returns allocated path to cache */ +char *blkid_get_cache_filename(struct blkid_config *conf) +{ + char *filename; + + filename = blkid_safe_getenv("BLKID_FILE"); + if (filename) + filename = blkid_strdup(filename); + else if (conf) + filename = blkid_strdup(conf->cachefile); + else { + struct blkid_config *c = blkid_read_config(NULL); + if (!c) + filename = blkid_strdup(BLKID_CONFIG_FILE); + else { + filename = c->cachefile; /* already allocated */ + c->cachefile = NULL; + blkid_free_config(c); + } + } + return filename; +} + +int blkid_get_cache(blkid_cache *ret_cache, const char *filename) +{ + blkid_cache cache; + + blkid_init_debug(0); + + DBG(DEBUG_CACHE, printf("creating blkid cache (using %s)\n", + filename ? filename : "default cache")); + + if (!(cache = (blkid_cache) calloc(1, sizeof(struct blkid_struct_cache)))) + return -BLKID_ERR_MEM; + + INIT_LIST_HEAD(&cache->bic_devs); + INIT_LIST_HEAD(&cache->bic_tags); + + if (filename && !*filename) + filename = NULL; + if (filename) + cache->bic_filename = blkid_strdup(filename); + else + cache->bic_filename = blkid_get_cache_filename(NULL); + + blkid_read_cache(cache); + *ret_cache = cache; + return 0; +} + +void blkid_put_cache(blkid_cache cache) +{ + if (!cache) + return; + + (void) blkid_flush_cache(cache); + + DBG(DEBUG_CACHE, printf("freeing cache struct\n")); + + /* DBG(DEBUG_CACHE, blkid_debug_dump_cache(cache)); */ + + while (!list_empty(&cache->bic_devs)) { + blkid_dev dev = list_entry(cache->bic_devs.next, + struct blkid_struct_dev, + bid_devs); + blkid_free_dev(dev); + } + + while (!list_empty(&cache->bic_tags)) { + blkid_tag tag = list_entry(cache->bic_tags.next, + struct blkid_struct_tag, + bit_tags); + + while (!list_empty(&tag->bit_names)) { + blkid_tag bad = list_entry(tag->bit_names.next, + struct blkid_struct_tag, + bit_names); + + DBG(DEBUG_CACHE, printf("warning: unfreed tag %s=%s\n", + bad->bit_name, bad->bit_val)); + blkid_free_tag(bad); + } + blkid_free_tag(tag); + } + free(cache->bic_filename); + + free(cache); +} + +void blkid_gc_cache(blkid_cache cache) +{ + struct list_head *p, *pnext; + struct stat st; + + if (!cache) + return; + + list_for_each_safe(p, pnext, &cache->bic_devs) { + blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs); + if (!p) + break; + if (stat(dev->bid_name, &st) < 0) { + DBG(DEBUG_CACHE, + printf("freeing %s\n", dev->bid_name)); + blkid_free_dev(dev); + cache->bic_flags |= BLKID_BIC_FL_CHANGED; + } else { + DBG(DEBUG_CACHE, + printf("Device %s exists\n", dev->bid_name)); + } + } +} + +#ifdef TEST_PROGRAM +int main(int argc, char** argv) +{ + blkid_cache cache = NULL; + int ret; + + blkid_init_debug(DEBUG_ALL); + + if ((argc > 2)) { + fprintf(stderr, "Usage: %s [filename] \n", argv[0]); + exit(1); + } + + if ((ret = blkid_get_cache(&cache, argv[1])) < 0) { + fprintf(stderr, "error %d parsing cache file %s\n", ret, + argv[1] ? argv[1] : BLKID_CACHE_FILE); + exit(1); + } + if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { + fprintf(stderr, "%s: error creating cache (%d)\n", + argv[0], ret); + exit(1); + } + if ((ret = blkid_probe_all(cache) < 0)) + fprintf(stderr, "error probing devices\n"); + + blkid_put_cache(cache); + + return ret; +} +#endif diff --git a/shlibs/blkid/src/config.c b/shlibs/blkid/src/config.c new file mode 100644 index 000000000..9091736be --- /dev/null +++ b/shlibs/blkid/src/config.c @@ -0,0 +1,205 @@ +/* + * config.c - blkid.conf routines + * + * Copyright (C) 2009 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <ctype.h> +#include <sys/types.h> +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#ifdef HAVE_SYS_MKDEV_H +#include <sys/mkdev.h> +#endif +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <stdint.h> +#include <stdarg.h> + +#include "blkdev.h" +#include "blkidP.h" + + +static int parse_evaluate(struct blkid_config *conf, char *s) +{ + while(s && *s) { + char *sep; + + if (conf->nevals >= __BLKID_EVAL_LAST) + goto err; + sep = strchr(s, ','); + if (sep) + *sep = '\0'; + if (strcmp(s, "udev") == 0) + conf->eval[conf->nevals] = BLKID_EVAL_UDEV; + else if (strcmp(s, "scan") == 0) + conf->eval[conf->nevals] = BLKID_EVAL_SCAN; + else + goto err; + conf->nevals++; + if (sep) + s = sep + 1; + else + break; + } + return 0; +err: + DBG(DEBUG_CONFIG, printf( + "config file: unknown evaluation method '%s'.\n", s)); + return -1; +} + +static int parse_next(FILE *fd, struct blkid_config *conf) +{ + char buf[BUFSIZ]; + char *s; + + /* read the next non-blank non-comment line */ + do { + if (fgets (buf, sizeof(buf), fd) == NULL) + return feof(fd) ? 0 : -1; + s = index (buf, '\n'); + if (!s) { + /* Missing final newline? Otherwise extremely */ + /* long line - assume file was corrupted */ + if (feof(fd)) + s = index (buf, '\0'); + else { + DBG(DEBUG_CONFIG, fprintf(stderr, + "libblkid: config file: missing newline at line '%s'.\n", + buf)); + return -1; + } + } + *s = '\0'; + if (--s >= buf && *s == '\r') + *s = '\0'; + + s = buf; + while (*s == ' ' || *s == '\t') /* skip space */ + s++; + + } while (*s == '\0' || *s == '#'); + + if (!strncmp(s, "SEND_UEVENT=", 12)) { + s += 13; + if (*s && !strcasecmp(s, "yes")) + conf->uevent = TRUE; + else if (*s) + conf->uevent = FALSE; + } else if (!strncmp(s, "CACHE_FILE=", 11)) { + s += 11; + if (*s) + conf->cachefile = blkid_strdup(s); + } else if (!strncmp(s, "EVALUATE=", 9)) { + s += 9; + if (*s && parse_evaluate(conf, s) == -1) + return -1; + } else { + DBG(DEBUG_CONFIG, printf( + "config file: unknown option '%s'.\n", s)); + return -1; + } + return 0; +} + +/* return real config data or built-in default */ +struct blkid_config *blkid_read_config(const char *filename) +{ + struct blkid_config *conf; + FILE *f; + + if (!filename) + filename = blkid_safe_getenv("BLKID_CONF"); + if (!filename) + filename = BLKID_CONFIG_FILE; + + conf = (struct blkid_config *) calloc(1, sizeof(*conf)); + if (!conf) + return NULL; + conf->uevent = -1; + + DBG(DEBUG_CONFIG, fprintf(stderr, + "reading config file: %s.\n", filename)); + + f = fopen(filename, "r"); + if (!f) { + DBG(DEBUG_CONFIG, fprintf(stderr, + "%s: does not exist, using built-in default\n", filename)); + goto dflt; + } + while (!feof(f)) { + if (parse_next(f, conf)) { + DBG(DEBUG_CONFIG, fprintf(stderr, + "%s: parse error\n", filename)); + goto err; + } + } +dflt: + if (!conf->nevals) { + conf->eval[0] = BLKID_EVAL_UDEV; + conf->eval[1] = BLKID_EVAL_SCAN; + conf->nevals = 2; + } + if (!conf->cachefile) + conf->cachefile = blkid_strdup(BLKID_CACHE_FILE); + if (conf->uevent == -1) + conf->uevent = TRUE; + if (f) + fclose(f); + return conf; +err: + free(conf); + fclose(f); + return NULL; +} + +void blkid_free_config(struct blkid_config *conf) +{ + if (!conf) + return; + free(conf->cachefile); + free(conf); +} + +#ifdef TEST_PROGRAM +/* + * usage: tst_config [<filename>] + */ +int main(int argc, char *argv[]) +{ + int i; + struct blkid_config *conf; + char *filename = NULL; + + blkid_init_debug(DEBUG_ALL); + + if (argc == 2) + filename = argv[1]; + + conf = blkid_read_config(filename); + if (!conf) + return EXIT_FAILURE; + + printf("EVALUATE: "); + for (i = 0; i < conf->nevals; i++) + printf("%s ", conf->eval[i] == BLKID_EVAL_UDEV ? "udev" : "scan"); + printf("\n"); + + printf("SEND UEVENT: %s\n", conf->uevent ? "TRUE" : "FALSE"); + printf("CACHE_FILE: %s\n", conf->cachefile); + + blkid_free_config(conf); + return EXIT_SUCCESS; +} +#endif diff --git a/shlibs/blkid/src/dev.c b/shlibs/blkid/src/dev.c new file mode 100644 index 000000000..31b9fe86f --- /dev/null +++ b/shlibs/blkid/src/dev.c @@ -0,0 +1,255 @@ +/* + * dev.c - allocation/initialization/free routines for dev + * + * Copyright (C) 2001 Andreas Dilger + * Copyright (C) 2003 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#include <stdlib.h> +#include <string.h> + +#include "blkidP.h" + +blkid_dev blkid_new_dev(void) +{ + blkid_dev dev; + + if (!(dev = (blkid_dev) calloc(1, sizeof(struct blkid_struct_dev)))) + return NULL; + + INIT_LIST_HEAD(&dev->bid_devs); + INIT_LIST_HEAD(&dev->bid_tags); + + return dev; +} + +void blkid_free_dev(blkid_dev dev) +{ + if (!dev) + return; + + DBG(DEBUG_DEV, + printf(" freeing dev %s (%s)\n", dev->bid_name, dev->bid_type ? + dev->bid_type : "(null)")); + DBG(DEBUG_DEV, blkid_debug_dump_dev(dev)); + + list_del(&dev->bid_devs); + while (!list_empty(&dev->bid_tags)) { + blkid_tag tag = list_entry(dev->bid_tags.next, + struct blkid_struct_tag, + bit_tags); + blkid_free_tag(tag); + } + free(dev->bid_name); + free(dev); +} + +/* + * Given a blkid device, return its name + */ +extern const char *blkid_dev_devname(blkid_dev dev) +{ + return dev->bid_name; +} + +#ifdef CONFIG_BLKID_DEBUG +void blkid_debug_dump_dev(blkid_dev dev) +{ + struct list_head *p; + + if (!dev) { + printf(" dev: NULL\n"); + return; + } + + printf(" dev: name = %s\n", dev->bid_name); + printf(" dev: DEVNO=\"0x%0llx\"\n", (long long)dev->bid_devno); + printf(" dev: TIME=\"%ld\"\n", (long)dev->bid_time); + printf(" dev: PRI=\"%d\"\n", dev->bid_pri); + printf(" dev: flags = 0x%08X\n", dev->bid_flags); + + list_for_each(p, &dev->bid_tags) { + blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags); + if (tag) + printf(" tag: %s=\"%s\"\n", tag->bit_name, + tag->bit_val); + else + printf(" tag: NULL\n"); + } + printf("\n"); +} +#endif + +/* + * dev iteration routines for the public libblkid interface. + * + * These routines do not expose the list.h implementation, which are a + * contamination of the namespace, and which force us to reveal far, far + * too much of our internal implemenation. I'm not convinced I want + * to keep list.h in the long term, anyway. It's fine for kernel + * programming, but performance is not the #1 priority for this + * library, and I really don't like the tradeoff of type-safety for + * performance for this application. [tytso:20030125.2007EST] + */ + +/* + * This series of functions iterate over all devices in a blkid cache + */ +#define DEV_ITERATE_MAGIC 0x01a5284c + +struct blkid_struct_dev_iterate { + int magic; + blkid_cache cache; + char *search_type; + char *search_value; + struct list_head *p; +}; + +extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache) +{ + blkid_dev_iterate iter; + + iter = malloc(sizeof(struct blkid_struct_dev_iterate)); + if (iter) { + iter->magic = DEV_ITERATE_MAGIC; + iter->cache = cache; + iter->p = cache->bic_devs.next; + iter->search_type = 0; + iter->search_value = 0; + } + return (iter); +} + +extern int blkid_dev_set_search(blkid_dev_iterate iter, + char *search_type, char *search_value) +{ + char *new_type, *new_value; + + if (!iter || iter->magic != DEV_ITERATE_MAGIC || !search_type || + !search_value) + return -1; + new_type = malloc(strlen(search_type)+1); + new_value = malloc(strlen(search_value)+1); + if (!new_type || !new_value) { + free(new_type); + free(new_value); + return -1; + } + strcpy(new_type, search_type); + strcpy(new_value, search_value); + free(iter->search_type); + free(iter->search_value); + iter->search_type = new_type; + iter->search_value = new_value; + return 0; +} + +/* + * Return 0 on success, -1 on error + */ +extern int blkid_dev_next(blkid_dev_iterate iter, + blkid_dev *ret_dev) +{ + blkid_dev dev; + + *ret_dev = 0; + if (!iter || iter->magic != DEV_ITERATE_MAGIC) + return -1; + while (iter->p != &iter->cache->bic_devs) { + dev = list_entry(iter->p, struct blkid_struct_dev, bid_devs); + iter->p = iter->p->next; + if (iter->search_type && + !blkid_dev_has_tag(dev, iter->search_type, + iter->search_value)) + continue; + *ret_dev = dev; + return 0; + } + return -1; +} + +extern void blkid_dev_iterate_end(blkid_dev_iterate iter) +{ + if (!iter || iter->magic != DEV_ITERATE_MAGIC) + return; + iter->magic = 0; + free(iter); +} + +#ifdef TEST_PROGRAM +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#else +extern char *optarg; +extern int optind; +#endif + +void usage(char *prog) +{ + fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask]\n", prog); + fprintf(stderr, "\tList all devices and exit\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + blkid_dev_iterate iter; + blkid_cache cache = NULL; + blkid_dev dev; + int c, ret; + char *tmp; + char *file = NULL; + char *search_type = NULL; + char *search_value = NULL; + + while ((c = getopt (argc, argv, "m:f:")) != EOF) + switch (c) { + case 'f': + file = optarg; + break; + case 'm': + { + int mask = strtoul (optarg, &tmp, 0); + if (*tmp) { + fprintf(stderr, "Invalid debug mask: %s\n", + optarg); + exit(1); + } + blkid_init_debug(mask); + break; + } + case '?': + usage(argv[0]); + } + if (argc >= optind+2) { + search_type = argv[optind]; + search_value = argv[optind+1]; + optind += 2; + } + if (argc != optind) + usage(argv[0]); + + if ((ret = blkid_get_cache(&cache, file)) != 0) { + fprintf(stderr, "%s: error creating cache (%d)\n", + argv[0], ret); + exit(1); + } + + iter = blkid_dev_iterate_begin(cache); + if (search_type) + blkid_dev_set_search(iter, search_type, search_value); + while (blkid_dev_next(iter, &dev) == 0) { + printf("Device: %s\n", blkid_dev_devname(dev)); + } + blkid_dev_iterate_end(iter); + + + blkid_put_cache(cache); + return (0); +} +#endif diff --git a/shlibs/blkid/src/devname.c b/shlibs/blkid/src/devname.c new file mode 100644 index 000000000..ef686f4b4 --- /dev/null +++ b/shlibs/blkid/src/devname.c @@ -0,0 +1,558 @@ +/* + * devname.c - get a dev by its device inode name + * + * Copyright (C) Andries Brouwer + * Copyright (C) 1999, 2000, 2001, 2002, 2003 Theodore Ts'o + * Copyright (C) 2001 Andreas Dilger + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#define _GNU_SOURCE 1 + +#include <stdio.h> +#include <string.h> +#include <limits.h> +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#if HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#include <dirent.h> +#if HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#if HAVE_ERRNO_H +#include <errno.h> +#endif +#if HAVE_SYS_MKDEV_H +#include <sys/mkdev.h> +#endif +#include <time.h> + +#include "blkidP.h" + +/* + * Find a dev struct in the cache by device name, if available. + * + * If there is no entry with the specified device name, and the create + * flag is set, then create an empty device entry. + */ +blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags) +{ + blkid_dev dev = NULL, tmp; + struct list_head *p, *pnext; + + if (!cache || !devname) + return NULL; + + list_for_each(p, &cache->bic_devs) { + tmp = list_entry(p, struct blkid_struct_dev, bid_devs); + if (strcmp(tmp->bid_name, devname)) + continue; + + DBG(DEBUG_DEVNAME, + printf("found devname %s in cache\n", tmp->bid_name)); + dev = tmp; + break; + } + + if (!dev && (flags & BLKID_DEV_CREATE)) { + if (access(devname, F_OK) < 0) + return NULL; + dev = blkid_new_dev(); + if (!dev) + return NULL; + dev->bid_time = INT_MIN; + dev->bid_name = blkid_strdup(devname); + dev->bid_cache = cache; + list_add_tail(&dev->bid_devs, &cache->bic_devs); + cache->bic_flags |= BLKID_BIC_FL_CHANGED; + } + + if (flags & BLKID_DEV_VERIFY) { + dev = blkid_verify(cache, dev); + if (!dev || !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) + return dev; + /* + * If the device is verified, then search the blkid + * cache for any entries that match on the type, uuid, + * and label, and verify them; if a cache entry can + * not be verified, then it's stale and so we remove + * it. + */ + list_for_each_safe(p, pnext, &cache->bic_devs) { + blkid_dev dev2; + if (!p) + break; + dev2 = list_entry(p, struct blkid_struct_dev, bid_devs); + if (dev2->bid_flags & BLKID_BID_FL_VERIFIED) + continue; + if (!dev->bid_type || !dev2->bid_type || + strcmp(dev->bid_type, dev2->bid_type)) + continue; + if (dev->bid_label && dev2->bid_label && + strcmp(dev->bid_label, dev2->bid_label)) + continue; + if (dev->bid_uuid && dev2->bid_uuid && + strcmp(dev->bid_uuid, dev2->bid_uuid)) + continue; + if ((dev->bid_label && !dev2->bid_label) || + (!dev->bid_label && dev2->bid_label) || + (dev->bid_uuid && !dev2->bid_uuid) || + (!dev->bid_uuid && dev2->bid_uuid)) + continue; + dev2 = blkid_verify(cache, dev2); + if (dev2 && !(dev2->bid_flags & BLKID_BID_FL_VERIFIED)) + blkid_free_dev(dev2); + } + } + return dev; +} + +/* Directories where we will try to search for device names */ +static const char *dirlist[] = { "/dev", "/devfs", "/devices", NULL }; + +static int is_dm_leaf(const char *devname) +{ + struct dirent *de, *d_de; + DIR *dir, *d_dir; + char path[256]; + int ret = 1; + + if ((dir = opendir("/sys/block")) == NULL) + return 0; + while ((de = readdir(dir)) != NULL) { + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..") || + !strcmp(de->d_name, devname) || + strncmp(de->d_name, "dm-", 3) || + strlen(de->d_name) > sizeof(path)-32) + continue; + sprintf(path, "/sys/block/%s/slaves", de->d_name); + if ((d_dir = opendir(path)) == NULL) + continue; + while ((d_de = readdir(d_dir)) != NULL) { + if (!strcmp(d_de->d_name, devname)) { + ret = 0; + break; + } + } + closedir(d_dir); + if (!ret) + break; + } + closedir(dir); + return ret; +} + +/* + * Since 2.6.29 (patch 784aae735d9b0bba3f8b9faef4c8b30df3bf0128) kernel sysfs + * provides the real DM device names in /sys/block/<ptname>/dm/name + */ +static char *get_dm_name(const char *ptname) +{ + FILE *f; + size_t sz; + char path[256], name[256], *res = NULL; + + snprintf(path, sizeof(path), "/sys/block/%s/dm/name", ptname); + if ((f = fopen(path, "r")) == NULL) + return NULL; + + /* read "<name>\n" from sysfs */ + if (fgets(name, sizeof(name), f) && (sz = strlen(name)) > 1) { + name[sz - 1] = '\0'; + snprintf(path, sizeof(path), "/dev/mapper/%s", name); + res = blkid_strdup(path); + } + fclose(f); + return res; +} + +/* + * Probe a single block device to add to the device cache. + */ +static void probe_one(blkid_cache cache, const char *ptname, + dev_t devno, int pri, int only_if_new) +{ + blkid_dev dev = NULL; + struct list_head *p, *pnext; + const char **dir; + char *devname = NULL; + + /* See if we already have this device number in the cache. */ + list_for_each_safe(p, pnext, &cache->bic_devs) { + blkid_dev tmp = list_entry(p, struct blkid_struct_dev, + bid_devs); + if (tmp->bid_devno == devno) { + if (only_if_new && !access(tmp->bid_name, F_OK)) + return; + dev = blkid_verify(cache, tmp); + if (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED)) + break; + dev = 0; + } + } + if (dev && dev->bid_devno == devno) + goto set_pri; + + /* Try to translate private device-mapper dm-<N> names + * to standard /dev/mapper/<name>. + */ + if (!strncmp(ptname, "dm-", 3) && isdigit(ptname[3])) { + devname = get_dm_name(ptname); + if (!devname) + blkid__scan_dir("/dev/mapper", devno, 0, &devname); + if (devname) + goto get_dev; + } + + /* + * Take a quick look at /dev/ptname for the device number. We check + * all of the likely device directories. If we don't find it, or if + * the stat information doesn't check out, use blkid_devno_to_devname() + * to find it via an exhaustive search for the device major/minor. + */ + for (dir = dirlist; *dir; dir++) { + struct stat st; + char device[256]; + + sprintf(device, "%s/%s", *dir, ptname); + if ((dev = blkid_get_dev(cache, device, BLKID_DEV_FIND)) && + dev->bid_devno == devno) + goto set_pri; + + if (stat(device, &st) == 0 && S_ISBLK(st.st_mode) && + st.st_rdev == devno) { + devname = blkid_strdup(device); + goto get_dev; + } + } + /* Do a short-cut scan of /dev/mapper first */ + if (!devname) + blkid__scan_dir("/dev/mapper", devno, 0, &devname); + if (!devname) { + devname = blkid_devno_to_devname(devno); + if (!devname) + return; + } + +get_dev: + dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL); + free(devname); + +set_pri: + if (dev) { + if (pri) + dev->bid_pri = pri; + else if (!strncmp(dev->bid_name, "/dev/mapper/", 11)) { + dev->bid_pri = BLKID_PRI_DM; + if (is_dm_leaf(ptname)) + dev->bid_pri += 5; + } else if (!strncmp(ptname, "md", 2)) + dev->bid_pri = BLKID_PRI_MD; + } + return; +} + +#define PROC_PARTITIONS "/proc/partitions" +#define VG_DIR "/proc/lvm/VGs" + +/* + * This function initializes the UUID cache with devices from the LVM + * proc hierarchy. We currently depend on the names of the LVM + * hierarchy giving us the device structure in /dev. (XXX is this a + * safe thing to do?) + */ +#ifdef VG_DIR +static dev_t lvm_get_devno(const char *lvm_device) +{ + FILE *lvf; + char buf[1024]; + int ma, mi; + dev_t ret = 0; + + DBG(DEBUG_DEVNAME, printf("opening %s\n", lvm_device)); + if ((lvf = fopen(lvm_device, "r")) == NULL) { + DBG(DEBUG_DEVNAME, printf("%s: (%d) %s\n", lvm_device, errno, + strerror(errno))); + return 0; + } + + while (fgets(buf, sizeof(buf), lvf)) { + if (sscanf(buf, "device: %d:%d", &ma, &mi) == 2) { + ret = makedev(ma, mi); + break; + } + } + fclose(lvf); + + return ret; +} + +static void lvm_probe_all(blkid_cache cache, int only_if_new) +{ + DIR *vg_list; + struct dirent *vg_iter; + int vg_len = strlen(VG_DIR); + dev_t dev; + + if ((vg_list = opendir(VG_DIR)) == NULL) + return; + + DBG(DEBUG_DEVNAME, printf("probing LVM devices under %s\n", VG_DIR)); + + while ((vg_iter = readdir(vg_list)) != NULL) { + DIR *lv_list; + char *vdirname; + char *vg_name; + struct dirent *lv_iter; + + vg_name = vg_iter->d_name; + if (!strcmp(vg_name, ".") || !strcmp(vg_name, "..")) + continue; + vdirname = malloc(vg_len + strlen(vg_name) + 8); + if (!vdirname) + goto exit; + sprintf(vdirname, "%s/%s/LVs", VG_DIR, vg_name); + + lv_list = opendir(vdirname); + free(vdirname); + if (lv_list == NULL) + continue; + + while ((lv_iter = readdir(lv_list)) != NULL) { + char *lv_name, *lvm_device; + + lv_name = lv_iter->d_name; + if (!strcmp(lv_name, ".") || !strcmp(lv_name, "..")) + continue; + + lvm_device = malloc(vg_len + strlen(vg_name) + + strlen(lv_name) + 8); + if (!lvm_device) { + closedir(lv_list); + goto exit; + } + sprintf(lvm_device, "%s/%s/LVs/%s", VG_DIR, vg_name, + lv_name); + dev = lvm_get_devno(lvm_device); + sprintf(lvm_device, "%s/%s", vg_name, lv_name); + DBG(DEBUG_DEVNAME, printf("LVM dev %s: devno 0x%04X\n", + lvm_device, + (unsigned int) dev)); + probe_one(cache, lvm_device, dev, BLKID_PRI_LVM, + only_if_new); + free(lvm_device); + } + closedir(lv_list); + } +exit: + closedir(vg_list); +} +#endif + +#define PROC_EVMS_VOLUMES "/proc/evms/volumes" + +static int +evms_probe_all(blkid_cache cache, int only_if_new) +{ + char line[100]; + int ma, mi, sz, num = 0; + FILE *procpt; + char device[110]; + + procpt = fopen(PROC_EVMS_VOLUMES, "r"); + if (!procpt) + return 0; + while (fgets(line, sizeof(line), procpt)) { + if (sscanf (line, " %d %d %d %*s %*s %[^\n ]", + &ma, &mi, &sz, device) != 4) + continue; + + DBG(DEBUG_DEVNAME, printf("Checking partition %s (%d, %d)\n", + device, ma, mi)); + + probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS, + only_if_new); + num++; + } + fclose(procpt); + return num; +} + +/* + * Read the device data for all available block devices in the system. + */ +static int probe_all(blkid_cache cache, int only_if_new) +{ + FILE *proc; + char line[1024]; + char ptname0[128], ptname1[128], *ptname = 0; + char *ptnames[2]; + dev_t devs[2]; + int ma, mi; + unsigned long long sz; + int lens[2] = { 0, 0 }; + int which = 0, last = 0; + struct list_head *p, *pnext; + + ptnames[0] = ptname0; + ptnames[1] = ptname1; + + if (!cache) + return -BLKID_ERR_PARAM; + + if (cache->bic_flags & BLKID_BIC_FL_PROBED && + time(0) - cache->bic_time < BLKID_PROBE_INTERVAL) + return 0; + + blkid_read_cache(cache); + evms_probe_all(cache, only_if_new); +#ifdef VG_DIR + lvm_probe_all(cache, only_if_new); +#endif + + proc = fopen(PROC_PARTITIONS, "r"); + if (!proc) + return -BLKID_ERR_PROC; + + while (fgets(line, sizeof(line), proc)) { + last = which; + which ^= 1; + ptname = ptnames[which]; + + if (sscanf(line, " %d %d %llu %128[^\n ]", + &ma, &mi, &sz, ptname) != 4) + continue; + devs[which] = makedev(ma, mi); + + DBG(DEBUG_DEVNAME, printf("read partition name %s\n", ptname)); + + /* Skip whole disk devs unless they have no partitions. + * If base name of device has changed, also + * check previous dev to see if it didn't have a partn. + * heuristic: partition name ends in a digit, & partition + * names contain whole device name as substring. + * + * Skip extended partitions. + * heuristic: size is 1 + * + * FIXME: skip /dev/{ida,cciss,rd} whole-disk devs + */ + + lens[which] = strlen(ptname); + + /* ends in a digit, clearly a partition, so check */ + if (isdigit(ptname[lens[which] - 1])) { + DBG(DEBUG_DEVNAME, + printf("partition dev %s, devno 0x%04X\n", + ptname, (unsigned int) devs[which])); + + if (sz > 1) + probe_one(cache, ptname, devs[which], 0, + only_if_new); + lens[which] = 0; /* mark as checked */ + } + + /* + * If last was a whole disk and we just found a partition + * on it, remove the whole-disk dev from the cache if + * it exists. + */ + if (lens[last] && !strncmp(ptnames[last], ptname, lens[last])) { + list_for_each_safe(p, pnext, &cache->bic_devs) { + blkid_dev tmp; + + /* find blkid dev for the whole-disk devno */ + tmp = list_entry(p, struct blkid_struct_dev, + bid_devs); + if (tmp->bid_devno == devs[last]) { + DBG(DEBUG_DEVNAME, + printf("freeing %s\n", + tmp->bid_name)); + blkid_free_dev(tmp); + cache->bic_flags |= BLKID_BIC_FL_CHANGED; + break; + } + } + lens[last] = 0; + } + /* + * If last was not checked because it looked like a whole-disk + * dev, and the device's base name has changed, + * check last as well. + */ + if (lens[last] && strncmp(ptnames[last], ptname, lens[last])) { + DBG(DEBUG_DEVNAME, + printf("whole dev %s, devno 0x%04X\n", + ptnames[last], (unsigned int) devs[last])); + probe_one(cache, ptnames[last], devs[last], 0, + only_if_new); + lens[last] = 0; + } + } + + /* Handle the last device if it wasn't partitioned */ + if (lens[which]) + probe_one(cache, ptname, devs[which], 0, only_if_new); + + fclose(proc); + blkid_flush_cache(cache); + return 0; +} + +int blkid_probe_all(blkid_cache cache) +{ + int ret; + + DBG(DEBUG_PROBE, printf("Begin blkid_probe_all()\n")); + ret = probe_all(cache, 0); + cache->bic_time = time(0); + cache->bic_flags |= BLKID_BIC_FL_PROBED; + DBG(DEBUG_PROBE, printf("End blkid_probe_all()\n")); + return ret; +} + +int blkid_probe_all_new(blkid_cache cache) +{ + int ret; + + DBG(DEBUG_PROBE, printf("Begin blkid_probe_all_new()\n")); + ret = probe_all(cache, 1); + DBG(DEBUG_PROBE, printf("End blkid_probe_all_new()\n")); + return ret; +} + + +#ifdef TEST_PROGRAM +int main(int argc, char **argv) +{ + blkid_cache cache = NULL; + int ret; + + blkid_init_debug(DEBUG_ALL); + if (argc != 1) { + fprintf(stderr, "Usage: %s\n" + "Probe all devices and exit\n", argv[0]); + exit(1); + } + if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { + fprintf(stderr, "%s: error creating cache (%d)\n", + argv[0], ret); + exit(1); + } + if (blkid_probe_all(cache) < 0) + printf("%s: error probing devices\n", argv[0]); + + blkid_put_cache(cache); + return (0); +} +#endif diff --git a/shlibs/blkid/src/devno.c b/shlibs/blkid/src/devno.c new file mode 100644 index 000000000..8ffdb835d --- /dev/null +++ b/shlibs/blkid/src/devno.c @@ -0,0 +1,228 @@ +/* + * devno.c - find a particular device by its device number (major/minor) + * + * Copyright (C) 2000, 2001, 2003 Theodore Ts'o + * Copyright (C) 2001 Andreas Dilger + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#include <stdio.h> +#include <string.h> +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <stdlib.h> +#include <string.h> +#if HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#if HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#include <dirent.h> +#if HAVE_ERRNO_H +#include <errno.h> +#endif +#if HAVE_SYS_MKDEV_H +#include <sys/mkdev.h> +#endif + +#include "blkidP.h" + +char *blkid_strndup(const char *s, int length) +{ + char *ret; + + if (!s) + return NULL; + + if (!length) + length = strlen(s); + + ret = malloc(length + 1); + if (ret) { + strncpy(ret, s, length); + ret[length] = '\0'; + } + return ret; +} + +char *blkid_strdup(const char *s) +{ + return blkid_strndup(s, 0); +} + +/* + * This function adds an entry to the directory list + */ +static void add_to_dirlist(const char *name, struct dir_list **list) +{ + struct dir_list *dp; + + dp = malloc(sizeof(struct dir_list)); + if (!dp) + return; + dp->name = blkid_strdup(name); + if (!dp->name) { + free(dp); + return; + } + dp->next = *list; + *list = dp; +} + +/* + * This function frees a directory list + */ +static void free_dirlist(struct dir_list **list) +{ + struct dir_list *dp, *next; + + for (dp = *list; dp; dp = next) { + next = dp->next; + free(dp->name); + free(dp); + } + *list = NULL; +} + +void blkid__scan_dir(char *dirname, dev_t devno, struct dir_list **list, + char **devname) +{ + DIR *dir; + struct dirent *dp; + char path[1024]; + int dirlen; + struct stat st; + + if ((dir = opendir(dirname)) == NULL) + return; + dirlen = strlen(dirname) + 2; + while ((dp = readdir(dir)) != 0) { + if (dirlen + strlen(dp->d_name) >= sizeof(path)) + continue; + + if (dp->d_name[0] == '.' && + ((dp->d_name[1] == 0) || + ((dp->d_name[1] == '.') && (dp->d_name[2] == 0)))) + continue; + + sprintf(path, "%s/%s", dirname, dp->d_name); + if (stat(path, &st) < 0) + continue; + + if (S_ISBLK(st.st_mode) && st.st_rdev == devno) { + *devname = blkid_strdup(path); + DBG(DEBUG_DEVNO, + printf("found 0x%llx at %s (%p)\n", (long long)devno, + path, *devname)); + break; + } + if (list && S_ISDIR(st.st_mode) && !lstat(path, &st) && + S_ISDIR(st.st_mode)) + add_to_dirlist(path, list); + } + closedir(dir); + return; +} + +/* Directories where we will try to search for device numbers */ +static const char *devdirs[] = { "/devices", "/devfs", "/dev", NULL }; + +/* + * This function finds the pathname to a block device with a given + * device number. It returns a pointer to allocated memory to the + * pathname on success, and NULL on failure. + */ +char *blkid_devno_to_devname(dev_t devno) +{ + struct dir_list *list = NULL, *new_list = NULL; + char *devname = NULL; + const char **dir; + + /* + * Add the starting directories to search in reverse order of + * importance, since we are using a stack... + */ + for (dir = devdirs; *dir; dir++) + add_to_dirlist(*dir, &list); + + while (list) { + struct dir_list *current = list; + + list = list->next; + DBG(DEBUG_DEVNO, printf("directory %s\n", current->name)); + blkid__scan_dir(current->name, devno, &new_list, &devname); + free(current->name); + free(current); + if (devname) + break; + /* + * If we're done checking at this level, descend to + * the next level of subdirectories. (breadth-first) + */ + if (list == NULL) { + list = new_list; + new_list = NULL; + } + } + free_dirlist(&list); + free_dirlist(&new_list); + + if (!devname) { + DBG(DEBUG_DEVNO, + printf("blkid: couldn't find devno 0x%04lx\n", + (unsigned long) devno)); + } else { + DBG(DEBUG_DEVNO, + printf("found devno 0x%04llx as %s\n", (long long)devno, devname)); + } + + + return devname; +} + +#ifdef TEST_PROGRAM +int main(int argc, char** argv) +{ + char *devname, *tmp; + int major, minor; + dev_t devno; + const char *errmsg = "Couldn't parse %s: %s\n"; + + blkid_init_debug(DEBUG_ALL); + if ((argc != 2) && (argc != 3)) { + fprintf(stderr, "Usage:\t%s device_number\n\t%s major minor\n" + "Resolve a device number to a device name\n", + argv[0], argv[0]); + exit(1); + } + if (argc == 2) { + devno = strtoul(argv[1], &tmp, 0); + if (*tmp) { + fprintf(stderr, errmsg, "device number", argv[1]); + exit(1); + } + } else { + major = strtoul(argv[1], &tmp, 0); + if (*tmp) { + fprintf(stderr, errmsg, "major number", argv[1]); + exit(1); + } + minor = strtoul(argv[2], &tmp, 0); + if (*tmp) { + fprintf(stderr, errmsg, "minor number", argv[2]); + exit(1); + } + devno = makedev(major, minor); + } + printf("Looking for device 0x%04llx\n", (long long)devno); + devname = blkid_devno_to_devname(devno); + free(devname); + return 0; +} +#endif diff --git a/shlibs/blkid/src/encode.c b/shlibs/blkid/src/encode.c new file mode 100644 index 000000000..d45a292e8 --- /dev/null +++ b/shlibs/blkid/src/encode.c @@ -0,0 +1,288 @@ + +/* + * encode.c - string convertion routines (mostly for compatibility with + * udev/volume_id) + * + * Copyright (C) 2008 Kay Sievers <kay.sievers@vrfy.org> + * Copyright (C) 2009 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <ctype.h> + +#include "blkdev.h" +#include "blkidP.h" + +#define UDEV_ALLOWED_CHARS_INPUT "/ $%?," + +/* 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; +} + +static int 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 */ +static int 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; +} + +/** + * blkid_encode_string: + * @str: input string to be encoded + * @str_enc: output string to store the encoded input string + * @len: maximum size of the output string, which may be + * four times as long as the input string + * + * Encode all potentially unsafe characters of a string to the + * corresponding hex value prefixed by '\x'. + * + * Returns: 0 if the entire string was copied, non-zero otherwise. + **/ +int blkid_encode_string(const char *str, char *str_enc, size_t len) +{ + size_t i, j; + + if (str == NULL || str_enc == NULL || len == 0) + return -1; + + str_enc[0] = '\0'; + for (i = 0, j = 0; str[i] != '\0'; i++) { + int seqlen; + + seqlen = utf8_encoded_valid_unichar(&str[i]); + if (seqlen > 1) { + memcpy(&str_enc[j], &str[i], seqlen); + j += seqlen; + i += (seqlen-1); + } else if (str[i] == '\\' || !is_whitelisted(str[i], NULL)) { + sprintf(&str_enc[j], "\\x%02x", (unsigned char) str[i]); + j += 4; + } else { + str_enc[j] = str[i]; + j++; + } + if (j+3 >= len) + goto err; + } + str_enc[j] = '\0'; + return 0; +err: + return -1; +} + +/** + * blkid_safe_string: + * @str: input string + * @str_safe: output string + * @len: size of output string + * + * Allows plain ascii, hex-escaping and valid utf8. Replaces all whitespaces + * with '_'. + */ +int blkid_safe_string(const char *str, char *str_safe, size_t len) +{ + replace_whitespace(str, str_safe, len); + replace_chars(str_safe, UDEV_ALLOWED_CHARS_INPUT); + return 0; +} diff --git a/shlibs/blkid/src/evaluate.c b/shlibs/blkid/src/evaluate.c new file mode 100644 index 000000000..f0ae12669 --- /dev/null +++ b/shlibs/blkid/src/evaluate.c @@ -0,0 +1,264 @@ +/* + * evaluate.c - very high-level API to evaluate LABELs or UUIDs + * + * This is simular to blkid_get_devname() from resolve.c, but this + * API supports udev /dev/disk/by-{label,uuid} links. + * + * Copyright (C) 2009 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <ctype.h> +#include <sys/types.h> +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#ifdef HAVE_SYS_MKDEV_H +#include <sys/mkdev.h> +#endif +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <stdint.h> +#include <stdarg.h> + +#include "pathnames.h" +#include "canonicalize.h" + +#include "blkdev.h" +#include "blkidP.h" + +/* returns zero when the device has NAME=value (LABEL/UUID) */ +static int verify_tag(const char *devname, const char *name, const char *value) +{ + blkid_probe pr; + int fd = -1, rc = -1; + size_t len; + const char *data; + + pr = blkid_new_probe(); + if (!pr) + return -1; + + blkid_probe_set_request(pr, BLKID_PROBREQ_LABEL | BLKID_PROBREQ_UUID); + + fd = open(devname, O_RDONLY); + if (fd < 0) + goto done; + if (blkid_probe_set_device(pr, fd, 0, 0)) + goto done; + rc = blkid_do_safeprobe(pr); + if (rc) + goto done; + rc = blkid_probe_lookup_value(pr, name, &data, &len); + if (!rc) + rc = memcmp(value, data, len); +done: + DBG(DEBUG_EVALUATE, printf("%s: %s verification %s\n", + devname, name, rc == 0 ? "PASS" : "FAILED")); + if (fd >= 0) + close(fd); + blkid_free_probe(pr); + return rc; +} + +/** + * blkid_send_uevent: + * @devname: absolute path to the device + * + * Returns -1 in case of failure, or 0 on success. + */ +int blkid_send_uevent(const char *devname, const char *action) +{ + char uevent[PATH_MAX]; + struct stat st; + FILE *f; + int rc = -1; + + DBG(DEBUG_EVALUATE, printf("%s: uevent '%s' requested\n", devname, action)); + + if (!devname || !action) + return -1; + if (stat(devname, &st) || !S_ISBLK(st.st_mode)) + return -1; + + snprintf(uevent, sizeof(uevent), "/sys/dev/block/%d:%d/uevent", + major(st.st_rdev), minor(st.st_rdev)); + + f = fopen(uevent, "w"); + if (f) { + rc = 0; + if (fputs(action, f) >= 0) + rc = 0; + fclose(f); + } + DBG(DEBUG_EVALUATE, printf("%s: send uevent %s\n", + uevent, rc == 0 ? "SUCCES" : "FAILED")); + return rc; +} + +static char *evaluate_by_udev(const char *token, const char *value, int uevent) +{ + char dev[PATH_MAX]; + char *path = NULL; + size_t len; + struct stat st; + + DBG(DEBUG_EVALUATE, + printf("evaluating by udev %s=%s\n", token, value)); + + if (!strcmp(token, "UUID")) + strcpy(dev, _PATH_DEV_BYUUID "/"); + else if (!strcmp(token, "LABEL")) + strcpy(dev, _PATH_DEV_BYLABEL "/"); + else { + DBG(DEBUG_EVALUATE, + printf("unsupported token %s\n", token)); + return NULL; /* unsupported tag */ + } + + len = strlen(dev); + if (blkid_encode_string(value, &dev[len], sizeof(dev) - len) != 0) + return NULL; + + DBG(DEBUG_EVALUATE, + printf("expected udev link: %s\n", dev)); + + if (stat(dev, &st)) + goto failed; /* link or device does not exist */ + + if (!S_ISBLK(st.st_mode)) + return NULL; + + path = canonicalize_path(dev); + if (!path) + return NULL; + + if (verify_tag(path, token, value)) + goto failed; + return path; + +failed: + DBG(DEBUG_EVALUATE, printf("failed to evaluate by udev\n")); + + if (uevent && path) + blkid_send_uevent(path, "change"); + free(path); + return NULL; +} + +static char *evaluate_by_scan(const char *token, const char *value, + blkid_cache *cache, struct blkid_config *conf) +{ + blkid_cache c = cache ? *cache : NULL; + char *res; + + DBG(DEBUG_EVALUATE, + printf("evaluating by blkid scan %s=%s\n", token, value)); + + if (!c) { + char *cachefile = blkid_get_cache_filename(conf); + blkid_get_cache(&c, cachefile); + free(cachefile); + } + if (!c) + return NULL; + + res = blkid_get_devname(c, token, value); + + if (cache) + *cache = c; + else + blkid_put_cache(c); + + return res; +} + +/** + * blkid_evaluate_tag: + * @token: token name (e.g "LABEL" or "UUID") + * @value: token data + * @cache: pointer to cache (or NULL when you don't want to re-use the cache) + * + * Returns allocated string with device name. + */ +char *blkid_evaluate_tag(const char *token, const char *value, blkid_cache *cache) +{ + struct blkid_config *conf = NULL; + char *t = NULL, *v = NULL; + char *ret = NULL; + int i; + + if (!token) + return NULL; + + if (!cache || !*cache) + blkid_init_debug(0); + + DBG(DEBUG_EVALUATE, + printf("evaluating %s%s%s\n", token, value ? "=" : "", + value ? value : "")); + + if (!value) { + if (!strchr(token, '=')) { + ret = blkid_strdup(token); + goto out; + } + blkid_parse_tag_string(token, &t, &v); + if (!t || !v) + goto out; + token = t; + value = v; + } + + conf = blkid_read_config(NULL); + if (!conf) + goto out; + + for (i = 0; i < conf->nevals; i++) { + if (conf->eval[i] == BLKID_EVAL_UDEV) + ret = evaluate_by_udev(token, value, conf->uevent); + else if (conf->eval[i] == BLKID_EVAL_SCAN) + ret = evaluate_by_scan(token, value, cache, conf); + if (ret) + break; + } + + DBG(DEBUG_EVALUATE, + printf("%s=%s evaluated as %s\n", token, value, ret)); +out: + blkid_free_config(conf); + free(t); + free(v); + return ret; +} + +#ifdef TEST_PROGRAM +int main(int argc, char *argv[]) +{ + blkid_cache cache = NULL; + char *res; + + if (argc < 3) { + fprintf(stderr, "usage: %s <token> <value>\n", argv[0]); + return EXIT_FAILURE; + } + + blkid_init_debug(0); + + res = blkid_evaluate_tag(argv[1], argv[2], &cache); + if (res) + printf("%s\n", res); + if (cache) + blkid_put_cache(cache); + + return res ? EXIT_SUCCESS : EXIT_FAILURE; +} +#endif diff --git a/shlibs/blkid/src/getsize.c b/shlibs/blkid/src/getsize.c new file mode 100644 index 000000000..10ba7ecf3 --- /dev/null +++ b/shlibs/blkid/src/getsize.c @@ -0,0 +1,207 @@ +/* + * getsize.c --- get the size of a partition. + * + * Copyright (C) 1995, 1995 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE + +/* include this before sys/queues.h! */ +#include "blkidP.h" + +#include <stdio.h> +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#if HAVE_ERRNO_H +#include <errno.h> +#endif +#include <fcntl.h> +#ifdef HAVE_SYS_IOCTL_H +#include <sys/ioctl.h> +#endif +#ifdef HAVE_LINUX_FD_H +#include <linux/fd.h> +#endif +#ifdef HAVE_SYS_DISKLABEL_H +#include <sys/disklabel.h> +#endif +#ifdef HAVE_SYS_DISK_H +#ifdef HAVE_SYS_QUEUE_H +#include <sys/queue.h> /* for LIST_HEAD */ +#endif +#include <sys/disk.h> +#endif +#ifdef __linux__ +#include <sys/utsname.h> +#endif +#if HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + + +#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE) +#define BLKGETSIZE _IO(0x12,96) /* return device size */ +#endif + +#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64) +#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */ +#endif + +#ifdef APPLE_DARWIN +#define BLKGETSIZE DKIOCGETBLOCKCOUNT32 +#endif /* APPLE_DARWIN */ + +static int valid_offset(int fd, blkid_loff_t offset) +{ + char ch; + + if (blkid_llseek(fd, offset, 0) < 0) + return 0; + if (read(fd, &ch, 1) < 1) + return 0; + return 1; +} + +/* + * Returns the number of bytes in a partition + */ +blkid_loff_t blkid_get_dev_size(int fd) +{ + int valid_blkgetsize64 = 1; +#ifdef __linux__ + struct utsname ut; +#endif + unsigned long long size64; + unsigned long size; + blkid_loff_t high, low; +#ifdef FDGETPRM + struct floppy_struct this_floppy; +#endif +#ifdef HAVE_SYS_DISKLABEL_H + int part = -1; + struct disklabel lab; + struct partition *pp; + char ch; + struct stat st; +#endif /* HAVE_SYS_DISKLABEL_H */ + +#ifdef DKIOCGETBLOCKCOUNT /* For Apple Darwin */ + if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) { + if ((sizeof(blkid_loff_t) < sizeof(unsigned long long)) + && (size64 << 9 > 0xFFFFFFFF)) + return 0; /* EFBIG */ + return (blkid_loff_t) size64 << 9; + } +#endif + +#ifdef BLKGETSIZE64 +#ifdef __linux__ + if ((uname(&ut) == 0) && + ((ut.release[0] == '2') && (ut.release[1] == '.') && + (ut.release[2] < '6') && (ut.release[3] == '.'))) + valid_blkgetsize64 = 0; +#endif + if (valid_blkgetsize64 && + ioctl(fd, BLKGETSIZE64, &size64) >= 0) { + if ((sizeof(blkid_loff_t) < sizeof(unsigned long long)) + && ((size64) > 0xFFFFFFFF)) + return 0; /* EFBIG */ + return size64; + } +#endif + +#ifdef BLKGETSIZE + if (ioctl(fd, BLKGETSIZE, &size) >= 0) + return (blkid_loff_t)size << 9; +#endif + +/* tested on FreeBSD 6.1-RELEASE i386 */ +#ifdef DIOCGMEDIASIZE + if (ioctl(fd, DIOCGMEDIASIZE, &size64) >= 0) + return (off_t)size64; +#endif /* DIOCGMEDIASIZE */ + +#ifdef FDGETPRM + if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) + return (blkid_loff_t)this_floppy.size << 9; +#endif +#ifdef HAVE_SYS_DISKLABEL_H + /* + * This code works for FreeBSD 4.11 i386, except for the full device + * (such as /dev/ad0). It doesn't work properly for newer FreeBSD + * though. FreeBSD >= 5.0 should be covered by the DIOCGMEDIASIZE + * above however. + * + * Note that FreeBSD >= 4.0 has disk devices as unbuffered (raw, + * character) devices, so we need to check for S_ISCHR, too. + */ + if ((fstat(fd, &st) >= 0) && (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))) + part = st.st_rdev & 7; + if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) { + pp = &lab.d_partitions[part]; + if (pp->p_size) + return pp->p_size << 9; + } +#endif /* HAVE_SYS_DISKLABEL_H */ + { +#ifdef HAVE_FSTAT64 + struct stat64 st; + if (fstat64(fd, &st) == 0) +#else + struct stat st; + if (fstat(fd, &st) == 0) +#endif + if (S_ISREG(st.st_mode)) + return st.st_size; + } + + + /* + * OK, we couldn't figure it out by using a specialized ioctl, + * which is generally the best way. So do binary search to + * find the size of the partition. + */ + low = 0; + for (high = 1024; valid_offset(fd, high); high *= 2) + low = high; + while (low < high - 1) + { + const blkid_loff_t mid = (low + high) / 2; + + if (valid_offset(fd, mid)) + low = mid; + else + high = mid; + } + return low + 1; +} + +#ifdef TEST_PROGRAM +int main(int argc, char **argv) +{ + long long bytes; + int fd; + + if (argc < 2) { + fprintf(stderr, "Usage: %s device\n" + "Determine the size of a device\n", argv[0]); + return 1; + } + + if ((fd = open(argv[1], O_RDONLY)) < 0) + perror(argv[0]); + + bytes = blkid_get_dev_size(fd); + printf("Device %s has %Ld 1k blocks.\n", argv[1], + (unsigned long long) bytes >> 10); + + return 0; +} +#endif diff --git a/shlibs/blkid/src/list.h b/shlibs/blkid/src/list.h new file mode 100644 index 000000000..c1cbfec59 --- /dev/null +++ b/shlibs/blkid/src/list.h @@ -0,0 +1,179 @@ +#if !defined(_BLKID_LIST_H) && !defined(LIST_HEAD) +#define _BLKID_LIST_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __GNUC__ +#define _INLINE_ static __inline__ +#else /* For Watcom C */ +#define _INLINE_ static inline +#endif + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +_INLINE_ void __list_add(struct list_head * add, + struct list_head * prev, + struct list_head * next) +{ + next->prev = add; + add->next = next; + add->prev = prev; + prev->next = add; +} + +/** + * list_add - add a new entry + * @add: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +_INLINE_ void list_add(struct list_head *add, struct list_head *head) +{ + __list_add(add, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @add: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +_INLINE_ void list_add_tail(struct list_head *add, struct list_head *head) +{ + __list_add(add, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +_INLINE_ void __list_del(struct list_head * prev, + struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * + * list_empty() on @entry does not return true after this, @entry is + * in an undefined state. + */ +_INLINE_ void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +_INLINE_ void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +_INLINE_ int list_empty(struct list_head *head) +{ + return head->next == head; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +_INLINE_ void list_splice(struct list_head *list, struct list_head *head) +{ + struct list_head *first = list->next; + + if (first != list) { + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) + +/** + * list_for_each - iterate over elements in a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_safe - iterate over elements in a list, but don't dereference + * pos after the body is done (in case it is freed) + * @pos: the &struct list_head to use as a loop counter. + * @pnext: the &struct list_head to use as a pointer to the next item. + * @head: the head for your list (not included in iteration). + */ +#define list_for_each_safe(pos, pnext, head) \ + for (pos = (head)->next, pnext = pos->next; pos != (head); \ + pos = pnext, pnext = pos->next) + +#undef _INLINE_ + +#ifdef __cplusplus +} +#endif + +#endif /* _BLKID_LIST_H */ diff --git a/shlibs/blkid/src/llseek.c b/shlibs/blkid/src/llseek.c new file mode 100644 index 000000000..5bd0e5167 --- /dev/null +++ b/shlibs/blkid/src/llseek.c @@ -0,0 +1,142 @@ +/* + * llseek.c -- stub calling the llseek system call + * + * Copyright (C) 1994, 1995, 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE + +#if HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#if HAVE_ERRNO_H +#include <errno.h> +#endif +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef __MSDOS__ +#include <io.h> +#endif + +#include "blkidP.h" + +#ifdef __linux__ + +#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) + +#define my_llseek lseek64 + +#elif defined(HAVE_LLSEEK) +#include <syscall.h> + +#ifndef HAVE_LLSEEK_PROTOTYPE +extern long long llseek(int fd, long long offset, int origin); +#endif + +#define my_llseek llseek + +#else /* ! HAVE_LLSEEK */ + +#if SIZEOF_LONG == SIZEOF_LONG_LONG + +#define llseek lseek + +#else /* SIZEOF_LONG != SIZEOF_LONG_LONG */ + +#include <linux/unistd.h> + +#ifndef __NR__llseek +#define __NR__llseek 140 +#endif + +#ifndef __i386__ +static int _llseek(unsigned int, unsigned long, unsigned long, + blkid_loff_t *, unsigned int); + +static _syscall5(int, _llseek, unsigned int, fd, unsigned long, offset_high, + unsigned long, offset_low, blkid_loff_t *, result, + unsigned int, origin) +#endif + +static blkid_loff_t my_llseek(int fd, blkid_loff_t offset, int origin) +{ + blkid_loff_t result; + int retval; + +#ifndef __i386__ + retval = _llseek(fd, ((unsigned long long) offset) >> 32, + ((unsigned long long)offset) & 0xffffffff, + &result, origin); +#else + retval = syscall(__NR__llseek, fd, ((unsigned long long) offset) >> 32, + ((unsigned long long)offset) & 0xffffffff, + &result, origin); +#endif + return (retval == -1 ? (blkid_loff_t) retval : result); +} + +#endif /* __alpha__ || __ia64__ */ + +#endif /* HAVE_LLSEEK */ + +blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence) +{ + blkid_loff_t result; + static int do_compat = 0; + + if ((sizeof(off_t) >= sizeof(blkid_loff_t)) || + (offset < ((blkid_loff_t) 1 << ((sizeof(off_t)*8) -1)))) + return lseek(fd, (off_t) offset, whence); + + if (do_compat) { + errno = EOVERFLOW; + return -1; + } + + result = my_llseek(fd, offset, whence); + if (result == -1 && errno == ENOSYS) { + /* + * Just in case this code runs on top of an old kernel + * which does not support the llseek system call + */ + do_compat++; + errno = EOVERFLOW; + } + return result; +} + +#else /* !linux */ + +#ifndef EOVERFLOW +#ifdef EXT2_ET_INVALID_ARGUMENT +#define EOVERFLOW EXT2_ET_INVALID_ARGUMENT +#else +#define EOVERFLOW 112 +#endif +#endif + +blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int origin) +{ +#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) + return lseek64 (fd, offset, origin); +#else + if ((sizeof(off_t) < sizeof(blkid_loff_t)) && + (offset >= ((blkid_loff_t) 1 << ((sizeof(off_t)*8) - 1)))) { + errno = EOVERFLOW; + return -1; + } + return lseek(fd, (off_t) offset, origin); +#endif +} + +#endif /* linux */ + + diff --git a/shlibs/blkid/src/probe.c b/shlibs/blkid/src/probe.c new file mode 100644 index 000000000..0e4745aca --- /dev/null +++ b/shlibs/blkid/src/probe.c @@ -0,0 +1,919 @@ +/* + * probe.c - reads tags (LABEL, UUID, FS type, ..) from a block device + * + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <ctype.h> +#include <sys/types.h> +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#ifdef HAVE_SYS_MKDEV_H +#include <sys/mkdev.h> +#endif +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <stdint.h> +#ifdef HAVE_LIBUUID +#include <uuid/uuid.h> +#endif +#include <stdarg.h> + +#include "blkdev.h" +#include "blkidP.h" +#include "probers/probers.h" + +static const struct blkid_idinfo *idinfos[] = +{ + /* RAIDs */ + &linuxraid_idinfo, + &ddfraid_idinfo, + &iswraid_idinfo, + &lsiraid_idinfo, + &viaraid_idinfo, + &silraid_idinfo, + &nvraid_idinfo, + &pdcraid_idinfo, + &highpoint45x_idinfo, + &highpoint37x_idinfo, + &adraid_idinfo, + &jmraid_idinfo, + &lvm2_idinfo, + &lvm1_idinfo, + &luks_idinfo, + + /* Filesystems */ + &vfat_idinfo, + &swsuspend_idinfo, + &swap_idinfo, + &xfs_idinfo, + &ext4dev_idinfo, + &ext4_idinfo, + &ext3_idinfo, + &ext2_idinfo, + &jbd_idinfo, + &reiser_idinfo, + &reiser4_idinfo, + &jfs_idinfo, + &udf_idinfo, + &iso9660_idinfo, + &zfs_idinfo, + &hfsplus_idinfo, + &hfs_idinfo, + &ufs_idinfo, + &hpfs_idinfo, + &sysv_idinfo, + &xenix_idinfo, + &ntfs_idinfo, + &cramfs_idinfo, + &romfs_idinfo, + &minix_idinfo, + &gfs_idinfo, + &gfs2_idinfo, + &ocfs_idinfo, + &ocfs2_idinfo, + &oracleasm_idinfo, + &vxfs_idinfo, + &squashfs_idinfo, + &netware_idinfo, + &btrfs_idinfo +}; + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#endif + +/* filter bitmap macros */ +#define blkid_bmp_wordsize (8 * sizeof(unsigned long)) +#define blkid_bmp_idx_bit(item) (1UL << ((item) % blkid_bmp_wordsize)) +#define blkid_bmp_idx_byte(item) ((item) / blkid_bmp_wordsize) + +#define blkid_bmp_set_item(bmp, item) \ + ((bmp)[ blkid_bmp_idx_byte(item) ] |= blkid_bmp_idx_bit(item)) + +#define blkid_bmp_unset_item(bmp, item) \ + ((bmp)[ bmp_idx_byte(item) ] &= ~bmp_idx_bit(item)) + +#define blkid_bmp_get_item(bmp, item) \ + ((bmp)[ blkid_bmp_idx_byte(item) ] & blkid_bmp_idx_bit(item)) + +#define blkid_bmp_size(max_items) \ + (((max_items) + blkid_bmp_wordsize) / blkid_bmp_wordsize) + +#define BLKID_FLTR_ITEMS ARRAY_SIZE(idinfos) +#define BLKID_FLTR_SIZE blkid_bmp_size(BLKID_FLTR_ITEMS) + + +static int blkid_probe_set_usage(blkid_probe pr, int usage); + +int blkid_known_fstype(const char *fstype) +{ + int i; + + if (!fstype) + return 0; + + for (i = 0; i < ARRAY_SIZE(idinfos); i++) { + const struct blkid_idinfo *id = idinfos[i]; + if (strcmp(id->name, fstype) == 0) + return 1; + } + return 0; +} + +/* + * Returns a pointer to the newly allocated probe struct + */ +blkid_probe blkid_new_probe(void) +{ + blkid_init_debug(0); + return calloc(1, sizeof(struct blkid_struct_probe)); +} + +/* + * Deallocates probe struct, buffers and all allocated + * data that are associated with this probing control struct. + */ +void blkid_free_probe(blkid_probe pr) +{ + if (!pr) + return; + free(pr->fltr); + free(pr->buf); + free(pr->sbbuf); + free(pr); +} + +static void blkid_probe_reset_vals(blkid_probe pr) +{ + memset(pr->vals, 0, sizeof(pr->vals)); + pr->nvals = 0; +} + +void blkid_reset_probe(blkid_probe pr) +{ + if (!pr) + return; + DBG(DEBUG_LOWPROBE, printf("reseting blkid_probe\n")); + if (pr->buf) + memset(pr->buf, 0, pr->buf_max); + pr->buf_off = 0; + pr->buf_len = 0; + pr->idx = 0; + if (pr->sbbuf) + memset(pr->sbbuf, 0, BLKID_SB_BUFSIZ); + pr->sbbuf_len = 0; + blkid_probe_reset_vals(pr); +} + + +/* + * Note that we have two offsets: + * + * 1/ general device offset (pr->off), that's useful for example when we + * probe a partition from whole disk image: + * blkid-low --offset <partition_position> disk.img + * + * 2/ buffer offset (the 'off' argument), that useful for offsets in + * superbloks, ... + * + * That means never use lseek(fd, 0, SEEK_SET), the zero position is always + * pr->off, so lseek(fd, pr->off, SEEK_SET). + * + */ +unsigned char *blkid_probe_get_buffer(blkid_probe pr, + blkid_loff_t off, blkid_loff_t len) +{ + ssize_t ret_read = 0; + + if (off < 0 || len < 0) { + DBG(DEBUG_LOWPROBE, + printf("unexpected offset or length of buffer requested\n")); + return NULL; + } + if (off + len <= BLKID_SB_BUFSIZ) { + if (!pr->sbbuf) { + pr->sbbuf = malloc(BLKID_SB_BUFSIZ); + if (!pr->sbbuf) + return NULL; + } + if (!pr->sbbuf_len) { + if (lseek(pr->fd, pr->off, SEEK_SET) < 0) + return NULL; + ret_read = read(pr->fd, pr->sbbuf, BLKID_SB_BUFSIZ); + if (ret_read < 0) + ret_read = 0; + pr->sbbuf_len = ret_read; + } + if (off + len > pr->sbbuf_len) + return NULL; + return pr->sbbuf + off; + } else { + unsigned char *newbuf = NULL; + + if (len > pr->buf_max) { + newbuf = realloc(pr->buf, len); + if (!newbuf) + return NULL; + pr->buf = newbuf; + pr->buf_max = len; + pr->buf_off = 0; + pr->buf_len = 0; + } + if (newbuf || off < pr->buf_off || + off + len > pr->buf_off + pr->buf_len) { + + if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0) + return NULL; + + ret_read = read(pr->fd, pr->buf, len); + if (ret_read != (ssize_t) len) + return NULL; + pr->buf_off = off; + pr->buf_len = len; + } + return off ? pr->buf + (off - pr->buf_off) : pr->buf; + } +} + +/* + * Assignes the device to probe control struct, resets internal buffers and + * reads 512 bytes from device to the buffers. + * + * Returns -1 in case of failure, or 0 on success. + */ +int blkid_probe_set_device(blkid_probe pr, int fd, + blkid_loff_t off, blkid_loff_t size) +{ + if (!pr) + return -1; + + blkid_reset_probe(pr); + + pr->fd = fd; + pr->off = off; + pr->size = 0; + pr->idx = 0; + + if (size) + pr->size = size; + else { + struct stat sb; + + if (fstat(fd, &sb)) + return -1; + + if (S_ISBLK(sb.st_mode)) + blkdev_get_size(fd, (unsigned long long *) &pr->size); + else + pr->size = sb.st_size; + } + if (!pr->size) + return -1; + + /* read SB to test if the device is readable */ + if (!blkid_probe_get_buffer(pr, 0, 0x200)) { + DBG(DEBUG_LOWPROBE, + printf("failed to prepare a device for low-probing\n")); + return -1; + } + + DBG(DEBUG_LOWPROBE, printf("ready for low-probing, offset=%zd, size=%zd\n", + pr->off, pr->size)); + return 0; +} + +int blkid_probe_set_request(blkid_probe pr, int flags) +{ + if (!pr) + return -1; + pr->probreq = flags; + return 0; +} + +int blkid_probe_reset_filter(blkid_probe pr) +{ + if (!pr) + return -1; + if (pr->fltr) + memset(pr->fltr, 0, BLKID_FLTR_SIZE * sizeof(unsigned long)); + pr->idx = 0; + return 0; +} + +/* + * flag: + * + * BLKID_FLTR_NOTIN - probe all filesystems which are NOT IN names[] + * + * BLKID_FLTR_ONLYIN - probe filesystem which are IN names[] + */ +int blkid_probe_filter_types(blkid_probe pr, int flag, char *names[]) +{ + int i; + + if (!pr || !names) + return -1; + if (!pr->fltr) + pr->fltr = calloc(BLKID_FLTR_SIZE, sizeof(unsigned long)); + else + blkid_probe_reset_filter(pr); + + if (!pr->fltr) + return -1; + + for (i = 0; i < ARRAY_SIZE(idinfos); i++) { + int has = 0; + const struct blkid_idinfo *id = idinfos[i]; + char **n; + + for (n = names; *n; n++) { + if (!strcmp(id->name, *n)) { + has = 1; + break; + } + } + /* The default is enable all filesystems, + * set relevant bitmap bit means disable the filesystem. + */ + if (flag & BLKID_FLTR_ONLYIN) { + if (!has) + blkid_bmp_set_item(pr->fltr, i); + } else if (flag & BLKID_FLTR_NOTIN) { + if (has) + blkid_bmp_set_item(pr->fltr, i); + } + } + DBG(DEBUG_LOWPROBE, printf("a new probing type-filter initialized\n")); + pr->idx = 0; + return 0; +} + +/* + * flag: + * + * BLKID_FLTR_NOTIN - probe all filesystems which are NOT IN "usage" + * + * BLKID_FLTR_ONLYIN - probe filesystem which are IN "usage" + * + * where the "usage" is a set of filesystem according the usage flag (crypto, + * raid, filesystem, ...) + */ +int blkid_probe_filter_usage(blkid_probe pr, int flag, int usage) +{ + int i; + + if (!pr || !usage) + return -1; + if (!pr->fltr) + pr->fltr = calloc(BLKID_FLTR_SIZE, sizeof(unsigned long)); + else + blkid_probe_reset_filter(pr); + + if (!pr->fltr) + return -1; + + for (i = 0; i < ARRAY_SIZE(idinfos); i++) { + const struct blkid_idinfo *id = idinfos[i]; + + if (id->usage & usage) { + if (flag & BLKID_FLTR_NOTIN) + blkid_bmp_set_item(pr->fltr, i); + } else if (flag & BLKID_FLTR_ONLYIN) + blkid_bmp_set_item(pr->fltr, i); + } + DBG(DEBUG_LOWPROBE, printf("a new probing usage-filter initialized\n")); + pr->idx = 0; + return 0; +} + + +int blkid_probe_invert_filter(blkid_probe pr) +{ + int i; + + if (!pr || !pr->fltr) + return -1; + for (i = 0; i < BLKID_FLTR_SIZE; i++) + pr->fltr[i] = ~pr->fltr[i]; + + DBG(DEBUG_LOWPROBE, printf("probing filter inverted\n")); + pr->idx = 0; + return 0; +} + +/* + * The blkid_do_probe() calls the probe functions. This routine could be used + * in a loop when you need to probe for all possible filesystems/raids. + * + * 1/ basic case -- use the first result: + * + * if (blkid_do_probe(pr) == 0) { + * int nvals = blkid_probe_numof_values(pr); + * for (n = 0; n < nvals; n++) { + * if (blkid_probe_get_value(pr, n, &name, &data, &len) == 0) + * printf("%s = %s\n", name, data); + * } + * } + * + * 2/ advanced case -- probe for all signatures (don't forget that some + * filesystems can co-exist on one volume (e.g. CD-ROM). + * + * while (blkid_do_probe(pr) == 0) { + * int nvals = blkid_probe_numof_values(pr); + * ... + * } + * + * The internal probing index (pointer to the last probing function) is + * always reseted when you touch probing filter or set a new device. It + * means you cannot use: + * + * blkid_probe_invert_filter() + * blkid_probe_filter_usage() + * blkid_probe_filter_types() + * blkid_probe_reset_filter() + * blkid_probe_set_device() + * + * in the loop (e.g while()) when you iterate on all signatures. + */ +int blkid_do_probe(blkid_probe pr) +{ + int i = 0; + + if (!pr) + return -1; + + blkid_probe_reset_vals(pr); + + if (pr->idx) + i = pr->idx + 1; + + if (i < 0 && i >= ARRAY_SIZE(idinfos)) + return -1; + + DBG(DEBUG_LOWPROBE, printf("--> starting probing loop\n")); + + for ( ; i < ARRAY_SIZE(idinfos); i++) { + const struct blkid_idinfo *id; + const struct blkid_idmag *mag; + int hasmag = 0; + + pr->idx = i; + + if (pr->fltr && blkid_bmp_get_item(pr->fltr, i)) + continue; + + id = idinfos[i]; + mag = id->magics ? &id->magics[0] : NULL; + + /* try to detect by magic string */ + while(mag && mag->magic) { + int idx; + unsigned char *buf; + + idx = mag->kboff + (mag->sboff >> 10); + buf = blkid_probe_get_buffer(pr, idx << 10, 1024); + + if (buf && !memcmp(mag->magic, + buf + (mag->sboff & 0x3ff), mag->len)) { + DBG(DEBUG_LOWPROBE, printf( + "%s: magic sboff=%u, kboff=%ld\n", + id->name, mag->sboff, mag->kboff)); + hasmag = 1; + break; + } + mag++; + } + + if (hasmag == 0 && id->magics && id->magics[0].magic) + /* magic string(s) defined, but not found */ + continue; + + /* final check by probing function */ + if (id->probefunc) { + DBG(DEBUG_LOWPROBE, printf( + "%s: call probefunc()\n", id->name)); + if (id->probefunc(pr, mag) != 0) + continue; + } + + /* all cheks passed */ + if (pr->probreq & BLKID_PROBREQ_TYPE) + blkid_probe_set_value(pr, "TYPE", + (unsigned char *) id->name, + strlen(id->name) + 1); + if (pr->probreq & BLKID_PROBREQ_USAGE) + blkid_probe_set_usage(pr, id->usage); + + DBG(DEBUG_LOWPROBE, + printf("<-- leaving probing loop (type=%s)\n", id->name)); + return 0; + } + DBG(DEBUG_LOWPROBE, printf("<-- leaving probing loop (failed)\n")); + return 1; +} + +/* + * This is the same function as blkid_do_probe(), but returns only one result + * (cannot be used in while()) and checks for ambivalen results (more + * filesystems on the device) -- in such case returns -2. + */ +int blkid_do_safeprobe(blkid_probe pr) +{ + struct blkid_struct_probe first; + int count = 0; + int intol = 0; + int rc; + + while ((rc = blkid_do_probe(pr)) == 0) { + if (!count) { + /* store the fist result */ + memcpy(first.vals, pr->vals, sizeof(first.vals)); + first.nvals = pr->nvals; + first.idx = pr->idx; + } + if (!(idinfos[pr->idx]->flags & BLKID_IDINFO_TOLERANT)) + intol++; + count++; + } + if (rc < 0) + return rc; /* error */ + if (count > 1 && intol) { + DBG(DEBUG_LOWPROBE, + printf("ERROR: ambivalent result detected (%d filesystems)!\n", + count)); + return -2; /* error, ambivalent result (more FS) */ + } + if (!count) + return 1; /* nothing detected */ + + /* restore the first result */ + memcpy(pr->vals, first.vals, sizeof(first.vals)); + pr->nvals = first.nvals; + pr->idx = first.idx; + + return 0; +} + +int blkid_probe_numof_values(blkid_probe pr) +{ + if (!pr) + return -1; + return pr->nvals; +} + + +static struct blkid_prval *blkid_probe_assign_value( + blkid_probe pr, const char *name) +{ + struct blkid_prval *v; + + if (!name) + return NULL; + if (pr->nvals >= BLKID_PROBVAL_NVALS) + return NULL; + + v = &pr->vals[pr->nvals]; + v->name = name; + pr->nvals++; + + DBG(DEBUG_LOWPROBE, printf("assigning %s\n", name)); + return v; +} + +int blkid_probe_set_value(blkid_probe pr, const char *name, + unsigned char *data, size_t len) +{ + struct blkid_prval *v; + + if (len > BLKID_PROBVAL_BUFSIZ) + len = BLKID_PROBVAL_BUFSIZ; + + v = blkid_probe_assign_value(pr, name); + if (!v) + return -1; + + memcpy(v->data, data, len); + v->len = len; + return 0; +} + +int blkid_probe_vsprintf_value(blkid_probe pr, const char *name, + const char *fmt, va_list ap) +{ + struct blkid_prval *v; + size_t len; + + v = blkid_probe_assign_value(pr, name); + if (!v) + return -1; + + len = vsnprintf((char *) v->data, sizeof(v->data), fmt, ap); + + if (len <= 0) { + pr->nvals--; /* reset the latest assigned value */ + return -1; + } + v->len = len + 1; + return 0; +} + +int blkid_probe_set_version(blkid_probe pr, const char *version) +{ + if (pr->probreq & BLKID_PROBREQ_VERSION) + return blkid_probe_set_value(pr, "VERSION", + (unsigned char *) version, strlen(version) + 1); + return 0; +} + +int blkid_probe_sprintf_version(blkid_probe pr, const char *fmt, ...) +{ + int rc = 0; + + if (pr->probreq & BLKID_PROBREQ_VERSION) { + va_list ap; + + va_start(ap, fmt); + rc = blkid_probe_vsprintf_value(pr, "VERSION", fmt, ap); + va_end(ap); + } + return rc; +} + +static int blkid_probe_set_usage(blkid_probe pr, int usage) +{ + char *u = NULL; + + if (usage & BLKID_USAGE_FILESYSTEM) + u = "filesystem"; + else if (usage & BLKID_USAGE_RAID) + u = "raid"; + else if (usage & BLKID_USAGE_CRYPTO) + u = "crypto"; + else if (usage & BLKID_USAGE_OTHER) + u = "other"; + else + u = "unknown"; + + return blkid_probe_set_value(pr, "USAGE", (unsigned char *) u, strlen(u) + 1); +} + +int blkid_probe_set_label(blkid_probe pr, unsigned char *label, size_t len) +{ + struct blkid_prval *v; + int i; + + if (len > BLKID_PROBVAL_BUFSIZ) + len = BLKID_PROBVAL_BUFSIZ; + + if ((pr->probreq & BLKID_PROBREQ_LABELRAW) && + blkid_probe_set_value(pr, "LABEL_RAW", label, len) < 0) + return -1; + if (!(pr->probreq & BLKID_PROBREQ_LABEL)) + return 0; + v = blkid_probe_assign_value(pr, "LABEL"); + if (!v) + return -1; + + memcpy(v->data, label, len); + v->data[len] = '\0'; + + /* remove trailing whitespace */ + i = strnlen((char *) v->data, len); + while (i--) { + if (!isspace(v->data[i])) + break; + } + v->data[++i] = '\0'; + v->len = i + 1; + return 0; +} + +static size_t encode_to_utf8(int enc, unsigned char *dest, size_t len, + unsigned char *src, size_t count) +{ + size_t i, j; + uint16_t c; + + for (j = i = 0; i + 2 <= count; i += 2) { + if (enc == BLKID_ENC_UTF16LE) + c = (src[i+1] << 8) | src[i]; + else /* BLKID_ENC_UTF16BE */ + c = (src[i] << 8) | src[i+1]; + if (c == 0) { + dest[j] = '\0'; + break; + } else if (c < 0x80) { + if (j+1 >= len) + break; + dest[j++] = (uint8_t) c; + } else if (c < 0x800) { + if (j+2 >= len) + break; + dest[j++] = (uint8_t) (0xc0 | (c >> 6)); + dest[j++] = (uint8_t) (0x80 | (c & 0x3f)); + } else { + if (j+3 >= len) + break; + dest[j++] = (uint8_t) (0xe0 | (c >> 12)); + dest[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f)); + dest[j++] = (uint8_t) (0x80 | (c & 0x3f)); + } + } + dest[j] = '\0'; + return j; +} + +int blkid_probe_set_utf8label(blkid_probe pr, unsigned char *label, + size_t len, int enc) +{ + struct blkid_prval *v; + + if ((pr->probreq & BLKID_PROBREQ_LABELRAW) && + blkid_probe_set_value(pr, "LABEL_RAW", label, len) < 0) + return -1; + if (!(pr->probreq & BLKID_PROBREQ_LABEL)) + return 0; + v = blkid_probe_assign_value(pr, "LABEL"); + if (!v) + return -1; + + v->len = encode_to_utf8(enc, v->data, sizeof(v->data), label, len); + return 0; +} + +/* like uuid_is_null() from libuuid, but works with arbitrary size of UUID */ +static int uuid_is_empty(const unsigned char *buf, size_t len) +{ + int i; + + for (i = 0; i < len; i++) + if (buf[i]) + return 0; + return 1; +} + +int blkid_probe_sprintf_uuid(blkid_probe pr, unsigned char *uuid, + size_t len, const char *fmt, ...) +{ + int rc = -1; + va_list ap; + + if (len > BLKID_PROBVAL_BUFSIZ) + len = BLKID_PROBVAL_BUFSIZ; + + if (uuid_is_empty(uuid, len)) + return 0; + + if ((pr->probreq & BLKID_PROBREQ_UUIDRAW) && + blkid_probe_set_value(pr, "UUID_RAW", uuid, len) < 0) + return -1; + if (!(pr->probreq & BLKID_PROBREQ_UUID)) + return 0; + + va_start(ap, fmt); + rc = blkid_probe_vsprintf_value(pr, "UUID", fmt, ap); + va_end(ap); + + /* convert to lower case (..be paranoid) */ + if (!rc) { + int i; + struct blkid_prval *v = &pr->vals[pr->nvals]; + + for (i = 0; i < v->len; i++) + if (v->data[i] >= 'A' && v->data[i] <= 'F') + v->data[i] = (v->data[i] - 'A') + 'a'; + } + return rc; +} + +/* function to set UUIDs that are in suberblocks stored as strings */ +int blkid_probe_strncpy_uuid(blkid_probe pr, unsigned char *str, size_t len) +{ + struct blkid_prval *v; + + if (str == NULL || *str == '\0') + return -1; + if (!len) + len = strlen((char *) str); + if (len > BLKID_PROBVAL_BUFSIZ) + len = BLKID_PROBVAL_BUFSIZ; + + if ((pr->probreq & BLKID_PROBREQ_UUIDRAW) && + blkid_probe_set_value(pr, "UUID_RAW", str, len) < 0) + return -1; + if (!(pr->probreq & BLKID_PROBREQ_UUID)) + return 0; + + v = blkid_probe_assign_value(pr, "UUID"); + if (v) { + memcpy((char *) v->data, str, len); + *(v->data + len) = '\0'; + v->len = len; + return 0; + } + return -1; +} + +/* default _set_uuid function to set DCE UUIDs */ +int blkid_probe_set_uuid_as(blkid_probe pr, unsigned char *uuid, const char *name) +{ + struct blkid_prval *v; + + if (uuid_is_empty(uuid, 16)) + return 0; + + if (!name) { + if ((pr->probreq & BLKID_PROBREQ_UUIDRAW) && + blkid_probe_set_value(pr, "UUID_RAW", uuid, 16) < 0) + return -1; + if (!(pr->probreq & BLKID_PROBREQ_UUID)) + return 0; + + v = blkid_probe_assign_value(pr, "UUID"); + } else + v = blkid_probe_assign_value(pr, name); + +#ifdef HAVE_LIBUUID + { + uuid_unparse(uuid, (char *) v->data); + v->len = 37; + } +#else + v->len = snprintf(v->data, sizeof(v->data), + "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + uuid[0], uuid[1], uuid[2], uuid[3], + uuid[4], uuid[5], + uuid[6], uuid[7], + uuid[8], uuid[9], + uuid[10], uuid[11], uuid[12], uuid[13], uuid[14],uuid[15]); + v->len++; +#endif + return 0; +} + +int blkid_probe_set_uuid(blkid_probe pr, unsigned char *uuid) +{ + return blkid_probe_set_uuid_as(pr, uuid, NULL); +} + +int blkid_probe_get_value(blkid_probe pr, int num, const char **name, + const char **data, size_t *len) +{ + struct blkid_prval *v; + + if (pr == NULL || num < 0 || num >= pr->nvals) + return -1; + + v = &pr->vals[num]; + if (name) + *name = v->name; + if (data) + *data = (char *) v->data; + if (len) + *len = v->len; + + DBG(DEBUG_LOWPROBE, printf("returning %s value\n", v->name)); + return 0; +} + +int blkid_probe_lookup_value(blkid_probe pr, const char *name, + const char **data, size_t *len) +{ + int i; + + if (pr == NULL || pr->nvals == 0 || name == NULL) + return -1; + + for (i = 0; i < pr->nvals; i++) { + struct blkid_prval *v = &pr->vals[i]; + + if (v->name && strcmp(name, v->name) == 0) { + if (data) + *data = (char *) v->data; + if (len) + *len = v->len; + DBG(DEBUG_LOWPROBE, printf("returning %s value\n", v->name)); + return 0; + } + } + return -1; +} + +int blkid_probe_has_value(blkid_probe pr, const char *name) +{ + if (blkid_probe_lookup_value(pr, name, NULL, NULL) == 0) + return 1; + return 0; +} + diff --git a/shlibs/blkid/src/probers/Makefile.am b/shlibs/blkid/src/probers/Makefile.am new file mode 100644 index 000000000..d8a98ed24 --- /dev/null +++ b/shlibs/blkid/src/probers/Makefile.am @@ -0,0 +1,43 @@ +include $(top_srcdir)/config/include-Makefile.am + +AM_CPPFLAGS += -I$(top_srcdir)/libs/blkid/src + +noinst_LTLIBRARIES = libblkid_probers.la +libblkid_probers_la_SOURCES = \ + probers.h \ + cramfs.c \ + swap.c \ + adaptec_raid.c \ + ddf_raid.c \ + isw_raid.c \ + jmicron_raid.c \ + lsi_raid.c \ + nvidia_raid.c \ + promise_raid.c \ + silicon_raid.c \ + via_raid.c \ + linux_raid.c \ + jfs.c \ + xfs.c \ + ext.c \ + gfs.c \ + ocfs.c \ + reiserfs.c \ + romfs.c \ + ntfs.c \ + hfs.c \ + iso9660.c \ + udf.c \ + vfat.c \ + luks.c \ + highpoint_raid.c \ + vxfs.c \ + minix.c \ + ufs.c \ + hpfs.c \ + squashfs.c \ + netware.c \ + sysv.c \ + btrfs.c \ + lvm.c \ + zfs.c diff --git a/shlibs/blkid/src/probers/adaptec_raid.c b/shlibs/blkid/src/probers/adaptec_raid.c new file mode 100644 index 000000000..5e8b3a758 --- /dev/null +++ b/shlibs/blkid/src/probers/adaptec_raid.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * Inspired by libvolume_id by + * Kay Sievers <kay.sievers@vrfy.org> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdint.h> + +#include "blkidP.h" + +struct adaptec_metadata { + uint32_t b0idcode; + uint8_t lunsave[8]; + uint16_t sdtype; + uint16_t ssavecyl; + uint8_t ssavehed; + uint8_t ssavesec; + uint8_t sb0flags; + uint8_t jbodEnable; + uint8_t lundsave; + uint8_t svpdirty; + uint16_t biosInfo; + uint16_t svwbskip; + uint16_t svwbcln; + uint16_t svwbmax; + uint16_t res3; + uint16_t svwbmin; + uint16_t res4; + uint16_t svrcacth; + uint16_t svwcacth; + uint16_t svwbdly; + uint8_t svsdtime; + uint8_t res5; + uint16_t firmval; + uint16_t firmbln; + uint32_t firmblk; + uint32_t fstrsvrb; + uint16_t svBlockStorageTid; + uint16_t svtid; + uint8_t svseccfl; + uint8_t res6; + uint8_t svhbanum; + uint8_t resver; + uint32_t drivemagic; + uint8_t reserved[20]; + uint8_t testnum; + uint8_t testflags; + uint16_t maxErrorCount; + uint32_t count; + uint32_t startTime; + uint32_t interval; + uint8_t tstxt0; + uint8_t tstxt1; + uint8_t serNum[32]; + uint8_t res8[102]; + uint32_t fwTestMagic; + uint32_t fwTestSeqNum; + uint8_t fwTestRes[8]; + uint8_t smagic[4]; + uint32_t raidtbl; + uint16_t raidline; + uint8_t res9[0xF6]; +}; + +#define AD_SIGNATURE "DPTM" +#define AD_MAGIC 0x37FC4D1E + +static int probe_adraid(blkid_probe pr, const struct blkid_idmag *mag) +{ + uint64_t off; + struct adaptec_metadata *ad; + + if (pr->size < 0x10000) + return -1; + + off = ((pr->size / 0x200)-1) * 0x200; + ad = (struct adaptec_metadata *) + blkid_probe_get_buffer(pr, + off, + sizeof(struct adaptec_metadata)); + if (!ad) + return -1; + if (memcmp(ad->smagic, AD_SIGNATURE, sizeof(AD_SIGNATURE)) != 0) + return -1; + if (ad->b0idcode != be32_to_cpu(AD_MAGIC)) + return -1; + if (blkid_probe_sprintf_version(pr, "%u", ad->resver) != 0) + return -1; + + return 0; +} + +const struct blkid_idinfo adraid_idinfo = { + .name = "adaptec_raid_member", + .usage = BLKID_USAGE_RAID, + .probefunc = probe_adraid, + .magics = BLKID_NONE_MAGIC +}; + + diff --git a/shlibs/blkid/src/probers/btrfs.c b/shlibs/blkid/src/probers/btrfs.c new file mode 100644 index 000000000..3205e3d97 --- /dev/null +++ b/shlibs/blkid/src/probers/btrfs.c @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2009 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdint.h> + +#include "blkidP.h" + +struct btrfs_super_block { + uint8_t csum[32]; + uint8_t fsid[16]; + uint64_t bytenr; + uint64_t flags; + uint8_t magic[8]; + uint64_t generation; + uint64_t root; + uint64_t chunk_root; + uint64_t log_root; + uint64_t log_root_transid; + uint64_t total_bytes; + uint64_t bytes_used; + uint64_t root_dir_objectid; + uint64_t num_devices; + uint32_t sectorsize; + uint32_t nodesize; + uint32_t leafsize; + uint32_t stripesize; + uint32_t sys_chunk_array_size; + uint64_t chunk_root_generation; + uint64_t compat_flags; + uint64_t compat_ro_flags; + uint64_t incompat_flags; + uint16_t csum_type; + uint8_t root_level; + uint8_t chunk_root_level; + uint8_t log_root_level; + struct btrfs_dev_item { + uint64_t devid; + uint64_t total_bytes; + uint64_t bytes_used; + uint32_t io_align; + uint32_t io_width; + uint32_t sector_size; + uint64_t type; + uint64_t generation; + uint64_t start_offset; + uint32_t dev_group; + uint8_t seek_speed; + uint8_t bandwidth; + uint8_t uuid[16]; + uint8_t fsid[16]; + } __attribute__ ((__packed__)) dev_item; + uint8_t label[256]; +} __attribute__ ((__packed__)); + +static int probe_btrfs(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct btrfs_super_block *bfs; + + bfs = blkid_probe_get_sb(pr, mag, struct btrfs_super_block); + if (!bfs) + return -1; + + if (*bfs->label) + blkid_probe_set_label(pr, + (unsigned char *) bfs->label, + sizeof(bfs->label)); + + blkid_probe_set_uuid(pr, bfs->fsid); + blkid_probe_set_uuid_as(pr, bfs->dev_item.uuid, "UUID_SUB"); + + return 0; +} + +const struct blkid_idinfo btrfs_idinfo = +{ + .name = "btrfs", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_btrfs, + .magics = + { + { .magic = "_BHRfS_M", .len = 8, .kboff = 64, .sboff = 0x40 }, + { NULL } + } +}; + diff --git a/shlibs/blkid/src/probers/cramfs.c b/shlibs/blkid/src/probers/cramfs.c new file mode 100644 index 000000000..0ea124b30 --- /dev/null +++ b/shlibs/blkid/src/probers/cramfs.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 1999 by Andries Brouwer + * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o + * Copyright (C) 2001 by Andreas Dilger + * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdint.h> + +#include "blkidP.h" + +struct cramfs_super +{ + uint8_t magic[4]; + uint32_t size; + uint32_t flags; + uint32_t future; + uint8_t signature[16]; + struct cramfs_info + { + uint32_t crc; + uint32_t edition; + uint32_t blocks; + uint32_t files; + } info; + uint8_t name[16]; +}; + +static int probe_cramfs(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct cramfs_super *cs; + + cs = blkid_probe_get_sb(pr, mag, struct cramfs_super); + if (!cs) + return -1; + + blkid_probe_set_label(pr, cs->name, sizeof(cs->name)); + return 0; +} + +const struct blkid_idinfo cramfs_idinfo = +{ + .name = "cramfs", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_cramfs, + .magics = + { + { "\x45\x3d\xcd\x28", 4, 0, 0 }, + { "\x28\xcd\x3d\x45", 4, 0, 0 }, + { NULL } + } +}; + + diff --git a/shlibs/blkid/src/probers/ddf_raid.c b/shlibs/blkid/src/probers/ddf_raid.c new file mode 100644 index 000000000..41d6e1235 --- /dev/null +++ b/shlibs/blkid/src/probers/ddf_raid.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * Inspired by libvolume_id by + * Kay Sievers <kay.sievers@vrfy.org> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdint.h> + +#include "blkidP.h" + +/* http://www.snia.org/standards/home */ +#define DDF_GUID_LENGTH 24 +#define DDF_REV_LENGTH 8 + +struct ddf_header { + uint8_t signature[4]; + uint32_t crc; + uint8_t guid[DDF_GUID_LENGTH]; + uint8_t ddf_rev[DDF_REV_LENGTH]; +} __attribute__((packed)); + +static int probe_ddf(blkid_probe pr, const struct blkid_idmag *mag) +{ + int hdrs[] = { 1, 257 }; + int i; + struct ddf_header *ddf = NULL; + char version[DDF_REV_LENGTH + 1]; + + if (pr->size < 0x30000) + return -1; + + for (i = 0; i < ARRAY_SIZE(hdrs); i++) { + uint64_t off = ((pr->size / 0x200) - hdrs[i]) * 0x200; + + ddf = (struct ddf_header *) blkid_probe_get_buffer(pr, + off, + sizeof(struct ddf_header)); + if (!ddf) + return -1; + + if (memcmp(ddf->signature, "\x11\xde\x11\xde", 4) == 0 || + memcmp(ddf->signature, "\xde\x11\xde\x11", 4) == 0) + break; + ddf = NULL; + } + + if (!ddf) + return -1; + + blkid_probe_strncpy_uuid(pr, ddf->guid, sizeof(ddf->guid)); + + memcpy(version, ddf->ddf_rev, sizeof(ddf->ddf_rev)); + *(version + sizeof(ddf->ddf_rev)) = '\0'; + + if (blkid_probe_set_version(pr, version) != 0) + return -1; + return 0; +} + +const struct blkid_idinfo ddfraid_idinfo = { + .name = "ddf_raid_member", + .usage = BLKID_USAGE_RAID, + .probefunc = probe_ddf, + .magics = BLKID_NONE_MAGIC +}; + + diff --git a/shlibs/blkid/src/probers/ext.c b/shlibs/blkid/src/probers/ext.c new file mode 100644 index 000000000..671e556c0 --- /dev/null +++ b/shlibs/blkid/src/probers/ext.c @@ -0,0 +1,571 @@ +/* + * Copyright (C) 1999, 2001 by Andries Brouwer + * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <stdint.h> +#ifdef __linux__ +#include <sys/utsname.h> +#endif +#include <time.h> + +#include "linux_version.h" +#include "blkidP.h" + +struct ext2_super_block { + uint32_t s_inodes_count; + uint32_t s_blocks_count; + uint32_t s_r_blocks_count; + uint32_t s_free_blocks_count; + uint32_t s_free_inodes_count; + uint32_t s_first_data_block; + uint32_t s_log_block_size; + uint32_t s_dummy3[7]; + unsigned char s_magic[2]; + uint16_t s_state; + uint16_t s_errors; + uint16_t s_minor_rev_level; + uint32_t s_lastcheck; + uint32_t s_checkinterval; + uint32_t s_creator_os; + uint32_t s_rev_level; + uint16_t s_def_resuid; + uint16_t s_def_resgid; + uint32_t s_first_ino; + uint16_t s_inode_size; + uint16_t s_block_group_nr; + uint32_t s_feature_compat; + uint32_t s_feature_incompat; + uint32_t s_feature_ro_compat; + unsigned char s_uuid[16]; + char s_volume_name[16]; + char s_last_mounted[64]; + uint32_t s_algorithm_usage_bitmap; + uint8_t s_prealloc_blocks; + uint8_t s_prealloc_dir_blocks; + uint16_t s_reserved_gdt_blocks; + uint8_t s_journal_uuid[16]; + uint32_t s_journal_inum; + uint32_t s_journal_dev; + uint32_t s_last_orphan; + uint32_t s_hash_seed[4]; + uint8_t s_def_hash_version; + uint8_t s_jnl_backup_type; + uint16_t s_reserved_word_pad; + uint32_t s_default_mount_opts; + uint32_t s_first_meta_bg; + uint32_t s_mkfs_time; + uint32_t s_jnl_blocks[17]; + uint32_t s_blocks_count_hi; + uint32_t s_r_blocks_count_hi; + uint32_t s_free_blocks_hi; + uint16_t s_min_extra_isize; + uint16_t s_want_extra_isize; + uint32_t s_flags; + uint16_t s_raid_stride; + uint16_t s_mmp_interval; + uint64_t s_mmp_block; + uint32_t s_raid_stripe_width; + uint32_t s_reserved[163]; +}; + +/* magic string */ +#define EXT_SB_MAGIC "\123\357" +/* supper block offset */ +#define EXT_SB_OFF 0x400 +/* supper block offset in kB */ +#define EXT_SB_KBOFF (EXT_SB_OFF >> 10) +/* magic string offset within super block */ +#define EXT_MAG_OFF 0x38 + + + +/* for s_flags */ +#define EXT2_FLAGS_TEST_FILESYS 0x0004 + +/* for s_feature_compat */ +#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 + +/* for s_feature_ro_compat */ +#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 +#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 +#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 +#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE 0x0008 +#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010 +#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020 +#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040 + +/* for s_feature_incompat */ +#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 +#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 +#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 +#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 +#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */ +#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 +#define EXT4_FEATURE_INCOMPAT_MMP 0x0100 +#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 + +#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ + EXT2_FEATURE_RO_COMPAT_BTREE_DIR) +#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \ + EXT2_FEATURE_INCOMPAT_META_BG) +#define EXT2_FEATURE_INCOMPAT_UNSUPPORTED ~EXT2_FEATURE_INCOMPAT_SUPP +#define EXT2_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT2_FEATURE_RO_COMPAT_SUPP + +#define EXT3_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ + EXT2_FEATURE_RO_COMPAT_BTREE_DIR) +#define EXT3_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \ + EXT3_FEATURE_INCOMPAT_RECOVER| \ + EXT2_FEATURE_INCOMPAT_META_BG) +#define EXT3_FEATURE_INCOMPAT_UNSUPPORTED ~EXT3_FEATURE_INCOMPAT_SUPP +#define EXT3_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT3_FEATURE_RO_COMPAT_SUPP + + +#ifdef FUCK + +/* for s_flags */ +#define EXT2_FLAGS_TEST_FILESYS 0x0004 + +/* for s_feature_compat */ +#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 + +/* for s_feature_ro_compat */ +#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 +#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 +#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 +#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE 0x0008 +#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010 +#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020 +#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040 + +/* for s_feature_incompat */ +#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 +#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 +#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 +#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 +#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */ +#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 +#define EXT4_FEATURE_INCOMPAT_MMP 0x0100 +#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 + +#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ + EXT2_FEATURE_RO_COMPAT_BTREE_DIR) +#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \ + EXT2_FEATURE_INCOMPAT_META_BG) +#define EXT2_FEATURE_INCOMPAT_UNSUPPORTED ~EXT2_FEATURE_INCOMPAT_SUPP +#define EXT2_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT2_FEATURE_RO_COMPAT_SUPP + +#define EXT3_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ + EXT2_FEATURE_RO_COMPAT_BTREE_DIR) +#define EXT3_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \ + EXT3_FEATURE_INCOMPAT_RECOVER| \ + EXT2_FEATURE_INCOMPAT_META_BG) +#define EXT3_FEATURE_INCOMPAT_UNSUPPORTED (~EXT3_FEATURE_INCOMPAT_SUPP) +#define EXT3_FEATURE_RO_COMPAT_UNSUPPORTED (~EXT3_FEATURE_RO_COMPAT_SUPP) + +#endif + +/* + * Check to see if a filesystem is in /proc/filesystems. + * Returns 1 if found, 0 if not + */ +static int fs_proc_check(const char *fs_name) +{ + FILE *f; + char buf[80], *cp, *t; + + f = fopen("/proc/filesystems", "r"); + if (!f) + return 0; + while (!feof(f)) { + if (!fgets(buf, sizeof(buf), f)) + break; + cp = buf; + if (!isspace(*cp)) { + while (*cp && !isspace(*cp)) + cp++; + } + while (*cp && isspace(*cp)) + cp++; + if ((t = strchr(cp, '\n')) != NULL) + *t = 0; + if ((t = strchr(cp, '\t')) != NULL) + *t = 0; + if ((t = strchr(cp, ' ')) != NULL) + *t = 0; + if (!strcmp(fs_name, cp)) { + fclose(f); + return 1; + } + } + fclose(f); + return (0); +} + +/* + * Check to see if a filesystem is available as a module + * Returns 1 if found, 0 if not + */ +static int check_for_modules(const char *fs_name) +{ +#ifdef __linux__ + struct utsname uts; + FILE *f; + char buf[1024], *cp, *t; + int i; + + if (uname(&uts)) + return 0; + snprintf(buf, sizeof(buf), "/lib/modules/%s/modules.dep", uts.release); + + f = fopen(buf, "r"); + if (!f) + return 0; + while (!feof(f)) { + if (!fgets(buf, sizeof(buf), f)) + break; + if ((cp = strchr(buf, ':')) != NULL) + *cp = 0; + else + continue; + if ((cp = strrchr(buf, '/')) == NULL) + continue; + cp++; + i = strlen(cp); + if (i > 3) { + t = cp + i - 3; + if (!strcmp(t, ".ko")) + *t = 0; + } + if (!strcmp(cp, fs_name)) { + fclose(f); + return 1; + } + } + fclose(f); +#endif /* __linux__ */ + return 0; +} + +/* + * Starting in 2.6.29, ext4 can be used to support filesystems + * without a journal. + */ +#define EXT4_SUPPORTS_EXT2 KERNEL_VERSION(2, 6, 29) + +static int system_supports_ext2(void) +{ + static time_t last_check = 0; + static int ret = -1; + time_t now = time(0); + + if (ret != -1 || (now - last_check) < 5) + return ret; + last_check = now; + ret = (fs_proc_check("ext2") || check_for_modules("ext2")); + return ret; +} + +static int system_supports_ext4(void) +{ + static time_t last_check = 0; + static int ret = -1; + time_t now = time(0); + + if (ret != -1 || (now - last_check) < 5) + return ret; + last_check = now; + ret = (fs_proc_check("ext4") || check_for_modules("ext4")); + return ret; +} + +static int system_supports_ext4dev(void) +{ + static time_t last_check = 0; + static int ret = -1; + time_t now = time(0); + + if (ret != -1 || (now - last_check) < 5) + return ret; + last_check = now; + ret = (fs_proc_check("ext4dev") || check_for_modules("ext4dev")); + return ret; +} +/* + * reads superblock and returns: + * fc = feature_compat + * fi = feature_incompat + * frc = feature_ro_compat + */ +static struct ext2_super_block *ext_get_super( + blkid_probe pr, uint32_t *fc, uint32_t *fi, uint32_t *frc) +{ + struct ext2_super_block *es; + + es = (struct ext2_super_block *) + blkid_probe_get_buffer(pr, EXT_SB_OFF, 0x200); + if (!es) + return NULL; + if (fc) + *fc = le32_to_cpu(es->s_feature_compat); + if (fi) + *fi = le32_to_cpu(es->s_feature_incompat); + if (frc) + *frc = le32_to_cpu(es->s_feature_ro_compat); + + return es; +} + +static void ext_get_info(blkid_probe pr, int ver, struct ext2_super_block *es) +{ + DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n", + le32_to_cpu(es->s_feature_compat), + le32_to_cpu(es->s_feature_incompat), + le32_to_cpu(es->s_feature_ro_compat))); + + if (strlen(es->s_volume_name)) + blkid_probe_set_label(pr, (unsigned char *) es->s_volume_name, + sizeof(es->s_volume_name)); + blkid_probe_set_uuid(pr, es->s_uuid); + + if (le32_to_cpu(es->s_feature_compat) & EXT3_FEATURE_COMPAT_HAS_JOURNAL) + blkid_probe_set_uuid_as(pr, es->s_journal_uuid, "EXT_JOURNAL"); + + if (ver != 2 && (pr->probreq & BLKID_PROBREQ_SECTYPE) && + ((le32_to_cpu(es->s_feature_incompat) & EXT2_FEATURE_INCOMPAT_UNSUPPORTED) == 0)) + blkid_probe_set_value(pr, "SEC_TYPE", + (unsigned char *) "ext2", + sizeof("ext2")); + + blkid_probe_sprintf_version(pr, "%u.%u", + le32_to_cpu(es->s_rev_level), + le16_to_cpu(es->s_minor_rev_level)); +} + + +static int probe_jbd(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct ext2_super_block *es; + uint32_t fi; + + es = ext_get_super(pr, NULL, &fi, NULL); + if (!es) + return -BLKID_ERR_PARAM; + if (!(fi & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) + return -BLKID_ERR_PARAM; + + ext_get_info(pr, 2, es); + return 0; +} + +static int probe_ext2(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct ext2_super_block *es; + uint32_t fc, frc, fi; + + es = ext_get_super(pr, &fc, &fi, &frc); + if (!es) + return -BLKID_ERR_PARAM; + + /* Distinguish between ext3 and ext2 */ + if (fc & EXT3_FEATURE_COMPAT_HAS_JOURNAL) + return -BLKID_ERR_PARAM; + + /* Any features which ext2 doesn't understand */ + if ((frc & EXT2_FEATURE_RO_COMPAT_UNSUPPORTED) || + (fi & EXT2_FEATURE_INCOMPAT_UNSUPPORTED)) + return -BLKID_ERR_PARAM; + + /* + * If ext2 is not present, but ext4 or ext4dev are, then + * disclaim we are ext2 + */ + if (!system_supports_ext2() && + (system_supports_ext4() || system_supports_ext4dev()) && + get_linux_version() >= EXT4_SUPPORTS_EXT2) + return -BLKID_ERR_PARAM; + + ext_get_info(pr, 2, es); + return 0; +} + +static int probe_ext3(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct ext2_super_block *es; + uint32_t fc, frc, fi; + + es = ext_get_super(pr, &fc, &fi, &frc); + if (!es) + return -BLKID_ERR_PARAM; + + /* ext3 requires journal */ + if (!(fc & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) + return -BLKID_ERR_PARAM; + + /* Any features which ext3 doesn't understand */ + if ((frc & EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) || + (fi & EXT3_FEATURE_INCOMPAT_UNSUPPORTED)) + return -BLKID_ERR_PARAM; + + ext_get_info(pr, 3, es); + return 0; +} + + +static int probe_ext4dev(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct ext2_super_block *es; + uint32_t fc, frc, fi; + + es = ext_get_super(pr, &fc, &fi, &frc); + if (!es) + return -BLKID_ERR_PARAM; + + /* Distinguish from jbd */ + if (fi & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) + return -BLKID_ERR_PARAM; + + /* + * If the filesystem does not have a journal and ext2 and ext4 + * is not present, then force this to be detected as an + * ext4dev filesystem. + */ + if (!(fc & EXT3_FEATURE_COMPAT_HAS_JOURNAL) && + !system_supports_ext2() && !system_supports_ext4() && + system_supports_ext4dev() && + get_linux_version() >= EXT4_SUPPORTS_EXT2) + goto force_ext4dev; + + /* + * If the filesystem is marked as OK for use by in-development + * filesystem code, but ext4dev is not supported, and ext4 is, + * then don't call ourselves ext4dev, since we should be + * detected as ext4 in that case. + * + * If the filesystem is marked as in use by production + * filesystem, then it can only be used by ext4 and NOT by + * ext4dev, so always disclaim we are ext4dev in that case. + */ + if (le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) { + if (!system_supports_ext4dev() && system_supports_ext4()) + return -BLKID_ERR_PARAM; + } else + return -BLKID_ERR_PARAM; + +force_ext4dev: + ext_get_info(pr, 4, es); + return 0; +} + +static int probe_ext4(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct ext2_super_block *es; + uint32_t fc, frc, fi; + + es = ext_get_super(pr, &fc, &fi, &frc); + if (!es) + return -1; + + /* Distinguish from jbd */ + if (fi & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) + return -BLKID_ERR_PARAM; + + /* Ext4 has at least one feature which ext3 doesn't understand */ + if (!(frc & EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) && + !(fi & EXT3_FEATURE_INCOMPAT_UNSUPPORTED)) + return -BLKID_ERR_PARAM; + + /* + * If the filesystem does not have a journal and ext2 is not + * present, then force this to be detected as an ext2 + * filesystem. + */ + if (!(fc & EXT3_FEATURE_COMPAT_HAS_JOURNAL) && + !system_supports_ext2() && system_supports_ext4() && + get_linux_version() >= EXT4_SUPPORTS_EXT2) + goto force_ext4; + + /* + * If the filesystem is a OK for use by in-development + * filesystem code, and ext4dev is supported or ext4 is not + * supported, then don't call ourselves ext4, so we can redo + * the detection and mark the filesystem as ext4dev. + * + * If the filesystem is marked as in use by production + * filesystem, then it can only be used by ext4 and NOT by + * ext4dev. + */ + if (le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) { + if (system_supports_ext4dev() || !system_supports_ext4()) + return -BLKID_ERR_PARAM; + } + +force_ext4: + ext_get_info(pr, 4, es); + return 0; +} + +#define BLKID_EXT_MAGICS \ + { \ + { \ + .magic = EXT_SB_MAGIC, \ + .len = sizeof(EXT_SB_MAGIC) - 1, \ + .kboff = EXT_SB_KBOFF, \ + .sboff = EXT_MAG_OFF \ + }, \ + { NULL } \ + } + +const struct blkid_idinfo jbd_idinfo = +{ + .name = "jbd", + .usage = BLKID_USAGE_OTHER, + .probefunc = probe_jbd, + .magics = BLKID_EXT_MAGICS +}; + +const struct blkid_idinfo ext2_idinfo = +{ + .name = "ext2", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_ext2, + .magics = BLKID_EXT_MAGICS +}; + +const struct blkid_idinfo ext3_idinfo = +{ + .name = "ext3", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_ext3, + .magics = BLKID_EXT_MAGICS +}; + +const struct blkid_idinfo ext4_idinfo = +{ + .name = "ext4", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_ext4, + .magics = BLKID_EXT_MAGICS +}; + +const struct blkid_idinfo ext4dev_idinfo = +{ + .name = "ext4dev", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_ext4dev, + .magics = BLKID_EXT_MAGICS +}; + diff --git a/shlibs/blkid/src/probers/gfs.c b/shlibs/blkid/src/probers/gfs.c new file mode 100644 index 000000000..584561cf3 --- /dev/null +++ b/shlibs/blkid/src/probers/gfs.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdint.h> + +#include "blkidP.h" + +/* Common gfs/gfs2 constants: */ +#define GFS_LOCKNAME_LEN 64 + +/* gfs1 constants: */ +#define GFS_FORMAT_FS 1309 +#define GFS_FORMAT_MULTI 1401 +/* gfs2 constants: */ +#define GFS2_FORMAT_FS 1801 +#define GFS2_FORMAT_MULTI 1900 + +struct gfs2_meta_header { + uint32_t mh_magic; + uint32_t mh_type; + uint64_t __pad0; /* Was generation number in gfs1 */ + uint32_t mh_format; + uint32_t __pad1; /* Was incarnation number in gfs1 */ +}; + +struct gfs2_inum { + uint64_t no_formal_ino; + uint64_t no_addr; +}; + +struct gfs2_sb { + struct gfs2_meta_header sb_header; + + uint32_t sb_fs_format; + uint32_t sb_multihost_format; + uint32_t __pad0; /* Was superblock flags in gfs1 */ + + uint32_t sb_bsize; + uint32_t sb_bsize_shift; + uint32_t __pad1; /* Was journal segment size in gfs1 */ + + struct gfs2_inum sb_master_dir; /* Was jindex dinode in gfs1 */ + struct gfs2_inum __pad2; /* Was rindex dinode in gfs1 */ + struct gfs2_inum sb_root_dir; + + char sb_lockproto[GFS_LOCKNAME_LEN]; + char sb_locktable[GFS_LOCKNAME_LEN]; + + struct gfs2_inum __pad3; /* Was quota inode in gfs1 */ + struct gfs2_inum __pad4; /* Was licence inode in gfs1 */ + uint8_t sb_uuid[16]; /* The UUID maybe 0 for backwards compat */ +}; + +static int probe_gfs(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct gfs2_sb *sbd; + + sbd = blkid_probe_get_sb(pr, mag, struct gfs2_sb); + if (!sbd) + return -1; + + if (be32_to_cpu(sbd->sb_fs_format) == GFS_FORMAT_FS && + be32_to_cpu(sbd->sb_multihost_format) == GFS_FORMAT_MULTI) + { + if (*sbd->sb_locktable) + blkid_probe_set_label(pr, + (unsigned char *) sbd->sb_locktable, + sizeof(sbd->sb_locktable)); + + blkid_probe_set_uuid(pr, sbd->sb_uuid); + return 0; + } + + return -1; +} + +static int probe_gfs2(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct gfs2_sb *sbd; + + sbd = blkid_probe_get_sb(pr, mag, struct gfs2_sb); + if (!sbd) + return -1; + + if (be32_to_cpu(sbd->sb_fs_format) == GFS2_FORMAT_FS && + be32_to_cpu(sbd->sb_multihost_format) == GFS2_FORMAT_MULTI) + { + if (*sbd->sb_locktable) + blkid_probe_set_label(pr, + (unsigned char *) sbd->sb_locktable, + sizeof(sbd->sb_locktable)); + blkid_probe_set_uuid(pr, sbd->sb_uuid); + blkid_probe_set_version(pr, "1"); + return 0; + } + return -1; +} + +const struct blkid_idinfo gfs_idinfo = +{ + .name = "gfs", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_gfs, + .magics = + { + { .magic = "\x01\x16\x19\x70", .len = 4, .kboff = 64 }, + { NULL } + } +}; + +const struct blkid_idinfo gfs2_idinfo = +{ + .name = "gfs2", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_gfs2, + .magics = + { + { .magic = "\x01\x16\x19\x70", .len = 4, .kboff = 64 }, + { NULL } + } +}; + diff --git a/shlibs/blkid/src/probers/hfs.c b/shlibs/blkid/src/probers/hfs.c new file mode 100644 index 000000000..4cdef0ee7 --- /dev/null +++ b/shlibs/blkid/src/probers/hfs.c @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2004-2008 Kay Sievers <kay.sievers@vrfy.org> + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <inttypes.h> + +#include "blkidP.h" +#include "md5.h" + +/* HFS / HFS+ */ +struct hfs_finder_info { + uint32_t boot_folder; + uint32_t start_app; + uint32_t open_folder; + uint32_t os9_folder; + uint32_t reserved; + uint32_t osx_folder; + uint8_t id[8]; +} __attribute__((packed)); + +struct hfs_mdb { + uint8_t signature[2]; + uint32_t cr_date; + uint32_t ls_Mod; + uint16_t atrb; + uint16_t nm_fls; + uint16_t vbm_st; + uint16_t alloc_ptr; + uint16_t nm_al_blks; + uint32_t al_blk_size; + uint32_t clp_size; + uint16_t al_bl_st; + uint32_t nxt_cnid; + uint16_t free_bks; + uint8_t label_len; + uint8_t label[27]; + uint32_t vol_bkup; + uint16_t vol_seq_num; + uint32_t wr_cnt; + uint32_t xt_clump_size; + uint32_t ct_clump_size; + uint16_t num_root_dirs; + uint32_t file_count; + uint32_t dir_count; + struct hfs_finder_info finder_info; + uint8_t embed_sig[2]; + uint16_t embed_startblock; + uint16_t embed_blockcount; +} __attribute__((packed)); + + +#define HFS_NODE_LEAF 0xff +#define HFSPLUS_POR_CNID 1 + +struct hfsplus_bnode_descriptor { + uint32_t next; + uint32_t prev; + uint8_t type; + uint8_t height; + uint16_t num_recs; + uint16_t reserved; +} __attribute__((packed)); + +struct hfsplus_bheader_record { + uint16_t depth; + uint32_t root; + uint32_t leaf_count; + uint32_t leaf_head; + uint32_t leaf_tail; + uint16_t node_size; +} __attribute__((packed)); + +struct hfsplus_catalog_key { + uint16_t key_len; + uint32_t parent_id; + uint16_t unicode_len; + uint8_t unicode[255 * 2]; +} __attribute__((packed)); + +struct hfsplus_extent { + uint32_t start_block; + uint32_t block_count; +} __attribute__((packed)); + +#define HFSPLUS_EXTENT_COUNT 8 +struct hfsplus_fork { + uint64_t total_size; + uint32_t clump_size; + uint32_t total_blocks; + struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT]; +} __attribute__((packed)); + +struct hfsplus_vol_header { + uint8_t signature[2]; + uint16_t version; + uint32_t attributes; + uint32_t last_mount_vers; + uint32_t reserved; + uint32_t create_date; + uint32_t modify_date; + uint32_t backup_date; + uint32_t checked_date; + uint32_t file_count; + uint32_t folder_count; + uint32_t blocksize; + uint32_t total_blocks; + uint32_t free_blocks; + uint32_t next_alloc; + uint32_t rsrc_clump_sz; + uint32_t data_clump_sz; + uint32_t next_cnid; + uint32_t write_count; + uint64_t encodings_bmp; + struct hfs_finder_info finder_info; + struct hfsplus_fork alloc_file; + struct hfsplus_fork ext_file; + struct hfsplus_fork cat_file; + struct hfsplus_fork attr_file; + struct hfsplus_fork start_file; +} __attribute__((packed)); + +static int hfs_set_uuid(blkid_probe pr, unsigned char const *hfs_info, size_t len) +{ + static unsigned char const hash_init[16] = { + 0xb3, 0xe2, 0x0f, 0x39, 0xf2, 0x92, 0x11, 0xd6, + 0x97, 0xa4, 0x00, 0x30, 0x65, 0x43, 0xec, 0xac + }; + unsigned char uuid[16]; + struct MD5Context md5c; + + if (memcmp(hfs_info, "\0\0\0\0\0\0\0\0", len) == 0) + return -1; + MD5Init(&md5c); + MD5Update(&md5c, hash_init, 16); + MD5Update(&md5c, hfs_info, len); + MD5Final(uuid, &md5c); + uuid[6] = 0x30 | (uuid[6] & 0x0f); + uuid[8] = 0x80 | (uuid[8] & 0x3f); + return blkid_probe_set_uuid(pr, uuid); +} + +static int probe_hfs(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct hfs_mdb *hfs; + + hfs = blkid_probe_get_sb(pr, mag, struct hfs_mdb); + if (!hfs) + return -1; + + if ((memcmp(hfs->embed_sig, "H+", 2) == 0) || + (memcmp(hfs->embed_sig, "HX", 2) == 0)) + return 1; /* Not hfs, but an embedded HFS+ */ + + hfs_set_uuid(pr, hfs->finder_info.id, sizeof(hfs->finder_info.id)); + + blkid_probe_set_label(pr, hfs->label, hfs->label_len); + return 0; +} + +static int probe_hfsplus(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT]; + struct hfsplus_bnode_descriptor *descr; + struct hfsplus_bheader_record *bnode; + struct hfsplus_catalog_key *key; + struct hfsplus_vol_header *hfsplus; + struct hfs_mdb *sbd; + unsigned int alloc_block_size; + unsigned int alloc_first_block; + unsigned int embed_first_block; + unsigned int off = 0; + unsigned int blocksize; + unsigned int cat_block; + unsigned int ext_block_start; + unsigned int ext_block_count; + unsigned int record_count; + unsigned int leaf_node_head; + unsigned int leaf_node_count; + unsigned int leaf_node_size; + unsigned int leaf_block; + int ext; + uint64_t leaf_off; + unsigned char *buf; + + sbd = blkid_probe_get_sb(pr, mag, struct hfs_mdb); + if (!sbd) + return -1; + + /* Check for a HFS+ volume embedded in a HFS volume */ + if (memcmp(sbd->signature, "BD", 2) == 0) { + if ((memcmp(sbd->embed_sig, "H+", 2) != 0) && + (memcmp(sbd->embed_sig, "HX", 2) != 0)) + /* This must be an HFS volume, so fail */ + return 1; + + alloc_block_size = be32_to_cpu(sbd->al_blk_size); + alloc_first_block = be16_to_cpu(sbd->al_bl_st); + embed_first_block = be16_to_cpu(sbd->embed_startblock); + off = (alloc_first_block * 512) + + (embed_first_block * alloc_block_size); + + buf = blkid_probe_get_buffer(pr, + off + (mag->kboff * 1024), + sizeof(struct hfsplus_vol_header)); + hfsplus = (struct hfsplus_vol_header *) buf; + + } else + hfsplus = blkid_probe_get_sb(pr, mag, + struct hfsplus_vol_header); + + if (!hfsplus) + return -1; + + if ((memcmp(hfsplus->signature, "H+", 2) != 0) && + (memcmp(hfsplus->signature, "HX", 2) != 0)) + return 1; + + hfs_set_uuid(pr, hfsplus->finder_info.id, sizeof(hfsplus->finder_info.id)); + + blocksize = be32_to_cpu(hfsplus->blocksize); + memcpy(extents, hfsplus->cat_file.extents, sizeof(extents)); + cat_block = be32_to_cpu(extents[0].start_block); + + buf = blkid_probe_get_buffer(pr, + off + (cat_block * blocksize), 0x2000); + if (!buf) + return 0; + + bnode = (struct hfsplus_bheader_record *) + &buf[sizeof(struct hfsplus_bnode_descriptor)]; + + leaf_node_head = be32_to_cpu(bnode->leaf_head); + leaf_node_size = be16_to_cpu(bnode->node_size); + leaf_node_count = be32_to_cpu(bnode->leaf_count); + if (leaf_node_count == 0) + return 0; + + leaf_block = (leaf_node_head * leaf_node_size) / blocksize; + + /* get physical location */ + for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) { + ext_block_start = be32_to_cpu(extents[ext].start_block); + ext_block_count = be32_to_cpu(extents[ext].block_count); + if (ext_block_count == 0) + return 0; + + /* this is our extent */ + if (leaf_block < ext_block_count) + break; + + leaf_block -= ext_block_count; + } + if (ext == HFSPLUS_EXTENT_COUNT) + return 0; + + leaf_off = (ext_block_start + leaf_block) * blocksize; + + buf = blkid_probe_get_buffer(pr, off + leaf_off, leaf_node_size); + if (!buf) + return 0; + + descr = (struct hfsplus_bnode_descriptor *) buf; + record_count = be16_to_cpu(descr->num_recs); + if (record_count == 0) + return 0; + + if (descr->type != HFS_NODE_LEAF) + return 0; + + key = (struct hfsplus_catalog_key *) + &buf[sizeof(struct hfsplus_bnode_descriptor)]; + + if (be32_to_cpu(key->parent_id) != HFSPLUS_POR_CNID) + return 0; + + blkid_probe_set_utf8label(pr, key->unicode, + be16_to_cpu(key->unicode_len) * 2, + BLKID_ENC_UTF16BE); + return 0; +} + +const struct blkid_idinfo hfs_idinfo = +{ + .name = "hfs", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_hfs, + .magics = + { + { .magic = "BD", .len = 2, .kboff = 1 }, + { NULL } + } +}; + +const struct blkid_idinfo hfsplus_idinfo = +{ + .name = "hfsplus", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_hfsplus, + .magics = + { + { .magic = "BD", .len = 2, .kboff = 1 }, + { .magic = "H+", .len = 2, .kboff = 1 }, + { .magic = "HX", .len = 2, .kboff = 1 }, + { NULL } + } +}; diff --git a/shlibs/blkid/src/probers/highpoint_raid.c b/shlibs/blkid/src/probers/highpoint_raid.c new file mode 100644 index 000000000..c7c92db44 --- /dev/null +++ b/shlibs/blkid/src/probers/highpoint_raid.c @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * Inspired by libvolume_id by + * Kay Sievers <kay.sievers@vrfy.org> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdint.h> + +#include "blkidP.h" + +struct hpt45x_metadata { + uint32_t magic; +}; + +#define HPT45X_MAGIC_OK 0x5a7816f3 +#define HPT45X_MAGIC_BAD 0x5a7816fd + +static int probe_highpoint45x(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct hpt45x_metadata *hpt; + uint64_t off; + uint32_t magic; + + if (pr->size < 0x10000) + return -1; + + off = ((pr->size / 0x200) - 11) * 0x200; + hpt = (struct hpt45x_metadata *) + blkid_probe_get_buffer(pr, + off, + sizeof(struct hpt45x_metadata)); + if (!hpt) + return -1; + magic = le32_to_cpu(hpt->magic); + if (magic != HPT45X_MAGIC_OK && magic != HPT45X_MAGIC_BAD) + return -1; + return 0; +} + +const struct blkid_idinfo highpoint45x_idinfo = { + .name = "highpoint_raid_member", + .usage = BLKID_USAGE_RAID, + .probefunc = probe_highpoint45x, + .magics = BLKID_NONE_MAGIC +}; + +const struct blkid_idinfo highpoint37x_idinfo = { + .name = "highpoint_raid_member", + .usage = BLKID_USAGE_RAID, + .magics = { + { .magic = "\xf0\x16\x78\x5a", .len = 4, .kboff = 4 }, + { .magic = "\xfd\x16\x78\x5a", .len = 4, .kboff = 4 }, + { NULL } + } +}; + + diff --git a/shlibs/blkid/src/probers/hpfs.c b/shlibs/blkid/src/probers/hpfs.c new file mode 100644 index 000000000..2f5f0d198 --- /dev/null +++ b/shlibs/blkid/src/probers/hpfs.c @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * Inspired by libvolume_id by + * Kay Sievers <kay.sievers@vrfy.org> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdint.h> + +#include "blkidP.h" + +struct hpfs_boot_block +{ + uint8_t jmp[3]; + uint8_t oem_id[8]; + uint8_t bytes_per_sector[2]; + uint8_t sectors_per_cluster; + uint8_t n_reserved_sectors[2]; + uint8_t n_fats; + uint8_t n_rootdir_entries[2]; + uint8_t n_sectors_s[2]; + uint8_t media_byte; + uint16_t sectors_per_fat; + uint16_t sectors_per_track; + uint16_t heads_per_cyl; + uint32_t n_hidden_sectors; + uint32_t n_sectors_l; + uint8_t drive_number; + uint8_t mbz; + uint8_t sig_28h; + uint8_t vol_serno[4]; + uint8_t vol_label[11]; + uint8_t sig_hpfs[8]; + uint8_t pad[448]; + uint8_t magic[2]; +}; + +struct hpfs_super_block +{ + uint8_t magic[4]; + uint8_t magic1[4]; + uint8_t version; +}; + +struct hpfs_spare_super +{ + uint8_t magic[4]; + uint8_t magic1[4]; +}; + + +#define HPFS_SB_OFFSET 0x2000 +#define HPFS_SBSPARE_OFFSET 0x2200 + +static int probe_hpfs(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct hpfs_super_block *hs; + struct hpfs_spare_super *hss; + struct hpfs_boot_block *hbb; + uint8_t version; + + /* super block */ + hs = blkid_probe_get_sb(pr, mag, struct hpfs_super_block); + if (!hs) + return -1; + version = hs->version; + + /* spare super block */ + hss = (struct hpfs_spare_super *) + blkid_probe_get_buffer(pr, + HPFS_SBSPARE_OFFSET, + sizeof(struct hpfs_spare_super)); + if (!hss) + return -1; + if (memcmp(hss->magic, "\x49\x18\x91\xf9", 4) != 0) + return -1; + + /* boot block (with UUID and LABEL) */ + hbb = (struct hpfs_boot_block *) + blkid_probe_get_buffer(pr, + 0, + sizeof(struct hpfs_boot_block)); + if (!hbb) + return -1; + if (memcmp(hbb->magic, "\x55\xaa", 2) == 0 && + memcmp(hbb->sig_hpfs, "HPFS", 4) == 0 && + hbb->sig_28h == 0x28) { + blkid_probe_set_label(pr, hbb->vol_label, sizeof(hbb->vol_label)); + blkid_probe_sprintf_uuid(pr, + hbb->vol_serno, sizeof(hbb->vol_serno), + "%02X%02X-%02X%02X", + hbb->vol_serno[3], hbb->vol_serno[2], + hbb->vol_serno[1], hbb->vol_serno[0]); + } + blkid_probe_sprintf_version(pr, "%u", version); + + return 0; +} + +const struct blkid_idinfo hpfs_idinfo = +{ + .name = "hpfs", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_hpfs, + .magics = + { + { + .magic = "\x49\xe8\x95\xf9", + .len = 4, + .kboff = (HPFS_SB_OFFSET >> 10) + }, + { NULL } + } +}; + + diff --git a/shlibs/blkid/src/probers/iso9660.c b/shlibs/blkid/src/probers/iso9660.c new file mode 100644 index 000000000..ca53e3ae4 --- /dev/null +++ b/shlibs/blkid/src/probers/iso9660.c @@ -0,0 +1,133 @@ +/* + * Copyright (C) 1999 by Andries Brouwer + * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o + * Copyright (C) 2001 by Andreas Dilger + * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * Inspired also by libvolume_id by + * Kay Sievers <kay.sievers@vrfy.org> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdint.h> + +#include "blkidP.h" + +struct iso_volume_descriptor { + unsigned char vd_type; + unsigned char vd_id[5]; + unsigned char vd_version; + unsigned char flags; + unsigned char system_id[32]; + unsigned char volume_id[32]; + unsigned char unused[8]; + unsigned char space_size[8]; + unsigned char escape_sequences[8]; +}; + +#define ISO_SUPERBLOCK_OFFSET 0x8000 +#define ISO_SECTOR_SIZE 0x800 +#define ISO_VD_OFFSET (ISO_SUPERBLOCK_OFFSET + ISO_SECTOR_SIZE) +#define ISO_VD_SUPPLEMENTARY 0x2 +#define ISO_VD_END 0xff +#define ISO_VD_MAX 16 + +struct high_sierra_volume_descriptor { + unsigned char foo[8]; + unsigned char type; + unsigned char id[5]; + unsigned char version; + unsigned char unused1; + unsigned char system_id[32]; + unsigned char volume_id[32]; +}; + +/* old High Sierra format */ +static int probe_iso9660_hsfs(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct high_sierra_volume_descriptor *iso; + + iso = blkid_probe_get_sb(pr, mag, struct high_sierra_volume_descriptor); + if (!iso) + return -1; + + blkid_probe_set_version(pr, "High Sierra"); + blkid_probe_set_label(pr, iso->volume_id, sizeof(iso->volume_id)); + return 0; +} + +/* iso9660 [+ Microsoft Joliet Extension] */ +static int probe_iso9660(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct iso_volume_descriptor *iso; + unsigned char label[32]; + int i; + int off; + + if (strcmp(mag->magic, "CDROM") == 0) + return probe_iso9660_hsfs(pr, mag); + + iso = blkid_probe_get_sb(pr, mag, struct iso_volume_descriptor); + if (!iso) + return -1; + + memcpy(label, iso->volume_id, sizeof(label)); + + /* Joliet Extension */ + off = ISO_VD_OFFSET; + for (i = 0; i < ISO_VD_MAX; i++) { + uint8_t svd_label[64]; + + iso = (struct iso_volume_descriptor *) + blkid_probe_get_buffer(pr, + off, + sizeof(struct iso_volume_descriptor)); + + if (iso == NULL || iso->vd_type == ISO_VD_END) + break; + if (iso->vd_type != ISO_VD_SUPPLEMENTARY) + continue; + + if (memcmp(iso->escape_sequences, "%/@", 3) == 0 || + memcmp(iso->escape_sequences, "%/C", 3) == 0 || + memcmp(iso->escape_sequences, "%/E", 3) == 0) { + + blkid_probe_set_utf8label(pr, + iso->volume_id, + sizeof(svd_label), + BLKID_ENC_UTF16BE); + + blkid_probe_set_version(pr, "Joliet Extension"); + goto has_label; + } + off += ISO_SECTOR_SIZE; + } + + /* Joliet not found, let use standard iso label */ + blkid_probe_set_label(pr, label, sizeof(label)); + +has_label: + return 0; +} + + +const struct blkid_idinfo iso9660_idinfo = +{ + .name = "iso9660", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_iso9660, + .flags = BLKID_IDINFO_TOLERANT, + .magics = + { + { .magic = "CD001", .len = 5, .kboff = 32, .sboff = 1 }, + { .magic = "CDROM", .len = 5, .kboff = 32, .sboff = 9 }, + { NULL } + } +}; + diff --git a/shlibs/blkid/src/probers/isw_raid.c b/shlibs/blkid/src/probers/isw_raid.c new file mode 100644 index 000000000..f9ae7453f --- /dev/null +++ b/shlibs/blkid/src/probers/isw_raid.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * Inspired by libvolume_id by + * Kay Sievers <kay.sievers@vrfy.org> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdint.h> + +#include "blkidP.h" + +struct isw_metadata { + uint8_t sig[32]; + uint32_t check_sum; + uint32_t mpb_size; + uint32_t family_num; + uint32_t generation_num; +}; + +#define ISW_SIGNATURE "Intel Raid ISM Cfg Sig. " + + +static int probe_iswraid(blkid_probe pr, const struct blkid_idmag *mag) +{ + uint64_t off; + struct isw_metadata *isw; + + if (pr->size < 0x10000) + return -1; + + off = ((pr->size / 0x200) - 2) * 0x200; + isw = (struct isw_metadata *) + blkid_probe_get_buffer(pr, + off, + sizeof(struct isw_metadata)); + if (!isw) + return -1; + if (memcmp(isw->sig, ISW_SIGNATURE, sizeof(ISW_SIGNATURE)-1) != 0) + return -1; + if (blkid_probe_sprintf_version(pr, "%6s", + &isw->sig[sizeof(ISW_SIGNATURE)-1]) != 0) + return -1; + + return 0; +} + +const struct blkid_idinfo iswraid_idinfo = { + .name = "isw_raid_member", + .usage = BLKID_USAGE_RAID, + .probefunc = probe_iswraid, + .magics = BLKID_NONE_MAGIC +}; + + diff --git a/shlibs/blkid/src/probers/jfs.c b/shlibs/blkid/src/probers/jfs.c new file mode 100644 index 000000000..5d9b39acd --- /dev/null +++ b/shlibs/blkid/src/probers/jfs.c @@ -0,0 +1,70 @@ +/* + * Copyright (C) 1999 by Andries Brouwer + * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o + * Copyright (C) 2001 by Andreas Dilger + * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <stdint.h> + +#include "blkidP.h" + +struct jfs_super_block { + unsigned char js_magic[4]; + uint32_t js_version; + uint64_t js_size; + uint32_t js_bsize; /* 4: aggregate block size in bytes */ + uint16_t js_l2bsize; /* 2: log2 of s_bsize */ + uint16_t js_l2bfactor; /* 2: log2(s_bsize/hardware block size) */ + uint32_t js_pbsize; /* 4: hardware/LVM block size in bytes */ + uint16_t js_l2pbsize; /* 2: log2 of s_pbsize */ + uint16_t js_pad; /* 2: padding necessary for alignment */ + uint32_t js_dummy2[26]; + unsigned char js_uuid[16]; + unsigned char js_label[16]; + unsigned char js_loguuid[16]; +}; + +static int probe_jfs(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct jfs_super_block *js; + + js = blkid_probe_get_sb(pr, mag, struct jfs_super_block); + if (!js) + return -1; + if (le32_to_cpu(js->js_bsize) != (1 << le16_to_cpu(js->js_l2bsize))) + return 1; + if (le32_to_cpu(js->js_pbsize) != (1 << le16_to_cpu(js->js_l2pbsize))) + return 1; + if ((le16_to_cpu(js->js_l2bsize) - le16_to_cpu(js->js_l2pbsize)) != + le16_to_cpu(js->js_l2bfactor)) + return 1; + + if (strlen((char *) js->js_label)) + blkid_probe_set_label(pr, js->js_label, sizeof(js->js_label)); + blkid_probe_set_uuid(pr, js->js_uuid); + return 0; +} + + +const struct blkid_idinfo jfs_idinfo = +{ + .name = "jfs", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_jfs, + .magics = + { + { .magic = "JFS1", .len = 4, .kboff = 32 }, + { NULL } + } +}; + diff --git a/shlibs/blkid/src/probers/jmicron_raid.c b/shlibs/blkid/src/probers/jmicron_raid.c new file mode 100644 index 000000000..ae852f8ff --- /dev/null +++ b/shlibs/blkid/src/probers/jmicron_raid.c @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * Inspired by libvolume_id by + * Kay Sievers <kay.sievers@vrfy.org> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdint.h> + +#include "blkidP.h" + +struct jm_metadata { + int8_t signature[2]; + uint8_t minor_version; + uint8_t major_version; + uint16_t checksum; +}; + +#define JM_SIGNATURE "JM" + +static int probe_jmraid(blkid_probe pr, const struct blkid_idmag *mag) +{ + uint64_t off; + struct jm_metadata *jm; + + if (pr->size < 0x10000) + return -1; + + off = ((pr->size / 0x200) - 1) * 0x200; + jm = (struct jm_metadata *) + blkid_probe_get_buffer(pr, + off, + sizeof(struct jm_metadata)); + if (!jm) + return -1; + if (memcmp(jm->signature, JM_SIGNATURE, sizeof(JM_SIGNATURE) - 1) != 0) + return -1; + if (blkid_probe_sprintf_version(pr, "%u.%u", + jm->major_version, jm->minor_version) != 0) + return -1; + + return 0; +} + +const struct blkid_idinfo jmraid_idinfo = { + .name = "jmicron_raid_member", + .usage = BLKID_USAGE_RAID, + .probefunc = probe_jmraid, + .magics = BLKID_NONE_MAGIC +}; + + diff --git a/shlibs/blkid/src/probers/linux_raid.c b/shlibs/blkid/src/probers/linux_raid.c new file mode 100644 index 000000000..a5926561d --- /dev/null +++ b/shlibs/blkid/src/probers/linux_raid.c @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * Inspired by libvolume_id by + * Kay Sievers <kay.sievers@vrfy.org> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdint.h> + +#include "blkidP.h" + +struct mdp0_super_block { + uint32_t md_magic; + uint32_t major_version; + uint32_t minor_version; + uint32_t patch_version; + uint32_t gvalid_words; + uint32_t set_uuid0; + uint32_t ctime; + uint32_t level; + uint32_t size; + uint32_t nr_disks; + uint32_t raid_disks; + uint32_t md_minor; + uint32_t not_persistent; + uint32_t set_uuid1; + uint32_t set_uuid2; + uint32_t set_uuid3; +}; + +struct mdp1_super_block { + uint32_t magic; + uint32_t major_version; + uint32_t feature_map; + uint32_t pad0; + uint8_t set_uuid[16]; + uint8_t set_name[32]; +}; + +#define MD_RESERVED_BYTES 0x10000 +#define MD_SB_MAGIC 0xa92b4efc + +static int probe_raid0(blkid_probe pr, off_t off) +{ + struct mdp0_super_block *mdp0; + union { + uint32_t ints[4]; + uint8_t bytes[16]; + } uuid; + + if (pr->size < 0x10000) + return -1; + mdp0 = (struct mdp0_super_block *) + blkid_probe_get_buffer(pr, + off, + sizeof(struct mdp0_super_block)); + if (!mdp0) + return -1; + + memset(uuid.ints, 0, sizeof(uuid.ints)); + + if (le32_to_cpu(mdp0->md_magic) == MD_SB_MAGIC) { + uuid.ints[0] = swab32(mdp0->set_uuid0); + if (le32_to_cpu(mdp0->minor_version >= 90)) { + uuid.ints[1] = swab32(mdp0->set_uuid1); + uuid.ints[2] = swab32(mdp0->set_uuid2); + uuid.ints[3] = swab32(mdp0->set_uuid3); + } + if (blkid_probe_sprintf_version(pr, "%u.%u.%u", + le32_to_cpu(mdp0->major_version), + le32_to_cpu(mdp0->minor_version), + le32_to_cpu(mdp0->patch_version)) != 0) + return -1; + + } else if (be32_to_cpu(mdp0->md_magic) == MD_SB_MAGIC) { + uuid.ints[0] = mdp0->set_uuid0; + if (be32_to_cpu(mdp0->minor_version >= 90)) { + uuid.ints[1] = mdp0->set_uuid1; + uuid.ints[2] = mdp0->set_uuid2; + uuid.ints[3] = mdp0->set_uuid3; + } + if (blkid_probe_sprintf_version(pr, "%u.%u.%u", + be32_to_cpu(mdp0->major_version), + be32_to_cpu(mdp0->minor_version), + be32_to_cpu(mdp0->patch_version)) != 0) + return -1; + } else + return -1; + + if (blkid_probe_set_uuid(pr, (unsigned char *) uuid.bytes) != 0) + return -1; + + return 0; +} + +static int probe_raid1(blkid_probe pr, off_t off) +{ + struct mdp1_super_block *mdp1; + + mdp1 = (struct mdp1_super_block *) + blkid_probe_get_buffer(pr, + off, + sizeof(struct mdp1_super_block)); + if (!mdp1) + return -1; + if (le32_to_cpu(mdp1->magic) != MD_SB_MAGIC) + return -1; + if (le32_to_cpu(mdp1->major_version) != 1) + return -1; + if (blkid_probe_set_uuid(pr, (unsigned char *) mdp1->set_uuid) != 0) + return -1; + if (blkid_probe_set_label(pr, mdp1->set_name, + sizeof(mdp1->set_name)) != 0) + return -1; + + return 0; +} + +int probe_raid(blkid_probe pr, const struct blkid_idmag *mag) +{ + const char *ver = NULL; + + if (pr->size > MD_RESERVED_BYTES) { + /* version 0 at the end of the device */ + uint64_t sboff = (pr->size & ~(MD_RESERVED_BYTES - 1)) + - MD_RESERVED_BYTES; + if (probe_raid0(pr, sboff) == 0) + return 0; + + /* version 1.0 at the end of the device */ + sboff = (pr->size & ~(0x1000 - 1)) - 0x2000; + if (probe_raid1(pr, sboff) == 0) + ver = "1.0"; + } + + if (!ver) { + /* version 1.1 at the start of the device */ + if (probe_raid1(pr, 0) == 0) + ver = "1.1"; + + /* version 1.2 at 4k offset from the start */ + else if (probe_raid1(pr, 0x1000) == 0) + ver = "1.2"; + } + + if (ver) { + blkid_probe_set_version(pr, ver); + return 0; + } + return -1; +} + + +const struct blkid_idinfo linuxraid_idinfo = { + .name = "linux_raid_member", + .usage = BLKID_USAGE_RAID, + .probefunc = probe_raid, + .magics = BLKID_NONE_MAGIC +}; + + diff --git a/shlibs/blkid/src/probers/lsi_raid.c b/shlibs/blkid/src/probers/lsi_raid.c new file mode 100644 index 000000000..d9ac4e12e --- /dev/null +++ b/shlibs/blkid/src/probers/lsi_raid.c @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * Inspired by libvolume_id by + * Kay Sievers <kay.sievers@vrfy.org> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdint.h> + +#include "blkidP.h" + +struct lsi_metadata { + uint8_t sig[6]; +}; + + +#define LSI_SIGNATURE "$XIDE$" + +static int probe_lsiraid(blkid_probe pr, const struct blkid_idmag *mag) +{ + uint64_t off; + struct lsi_metadata *lsi; + + if (pr->size < 0x10000) + return -1; + + off = ((pr->size / 0x200) - 1) * 0x200; + lsi = (struct lsi_metadata *) + blkid_probe_get_buffer(pr, + off, + sizeof(struct lsi_metadata)); + if (!lsi) + return -1; + + if (memcmp(lsi->sig, LSI_SIGNATURE, sizeof(LSI_SIGNATURE)-1) != 0) + return -1; + + return 0; +} + +const struct blkid_idinfo lsiraid_idinfo = { + .name = "lsi_mega_raid_member", + .usage = BLKID_USAGE_RAID, + .probefunc = probe_lsiraid, + .magics = BLKID_NONE_MAGIC +}; + + diff --git a/shlibs/blkid/src/probers/luks.c b/shlibs/blkid/src/probers/luks.c new file mode 100644 index 000000000..2fe4ff3b4 --- /dev/null +++ b/shlibs/blkid/src/probers/luks.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * Inspired by libvolume_id by + * Kay Sievers <kay.sievers@vrfy.org> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <stdint.h> + +#include "blkidP.h" + +#define LUKS_CIPHERNAME_L 32 +#define LUKS_CIPHERMODE_L 32 +#define LUKS_HASHSPEC_L 32 +#define LUKS_DIGESTSIZE 20 +#define LUKS_SALTSIZE 32 +#define LUKS_MAGIC_L 6 +#define UUID_STRING_L 40 + +struct luks_phdr { + uint8_t magic[LUKS_MAGIC_L]; + uint16_t version; + uint8_t cipherName[LUKS_CIPHERNAME_L]; + uint8_t cipherMode[LUKS_CIPHERMODE_L]; + uint8_t hashSpec[LUKS_HASHSPEC_L]; + uint32_t payloadOffset; + uint32_t keyBytes; + uint8_t mkDigest[LUKS_DIGESTSIZE]; + uint8_t mkDigestSalt[LUKS_SALTSIZE]; + uint32_t mkDigestIterations; + uint8_t uuid[UUID_STRING_L]; +}; + +static int probe_luks(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct luks_phdr *header; + + header = blkid_probe_get_sb(pr, mag, struct luks_phdr); + if (header == NULL) + return -1; + + blkid_probe_strncpy_uuid(pr, (unsigned char *) header->uuid, + sizeof(header->uuid)); + blkid_probe_sprintf_version(pr, "%u", le16_to_cpu(header->version)); + return 0; +} + +const struct blkid_idinfo luks_idinfo = +{ + .name = "crypto_LUKS", + .usage = BLKID_USAGE_CRYPTO, + .probefunc = probe_luks, + .magics = + { + { .magic = "LUKS\xba\xbe", .len = 6 }, + { NULL } + } +}; diff --git a/shlibs/blkid/src/probers/lvm.c b/shlibs/blkid/src/probers/lvm.c new file mode 100644 index 000000000..1a4e6bffe --- /dev/null +++ b/shlibs/blkid/src/probers/lvm.c @@ -0,0 +1,133 @@ +/* + * Copyright (C) 1999 by Andries Brouwer + * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o + * Copyright (C) 2001 by Andreas Dilger + * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdint.h> + +#include "blkidP.h" + +#define LVM2_ID_LEN 32 + +struct lvm2_pv_label_header { + /* label_header */ + uint8_t id[8]; /* LABELONE */ + uint64_t sector_xl; /* Sector number of this label */ + uint32_t crc_xl; /* From next field to end of sector */ + uint32_t offset_xl; /* Offset from start of struct to contents */ + uint8_t type[8]; /* LVM2 001 */ + /* pv_header */ + uint8_t pv_uuid[LVM2_ID_LEN]; +} __attribute__ ((packed)); + +#define LVM2_LABEL_SIZE 512 +static unsigned int lvm2_calc_crc(const void *buf, unsigned int size) +{ + static const unsigned int crctab[] = { + 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, + 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, + 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, + 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c + }; + unsigned int i, crc = 0xf597a6cf; + const uint8_t *data = (const uint8_t *) buf; + + for (i = 0; i < size; i++) { + crc ^= *data++; + crc = (crc >> 4) ^ crctab[crc & 0xf]; + crc = (crc >> 4) ^ crctab[crc & 0xf]; + } + return crc; +} + +static int probe_lvm2(blkid_probe pr, const struct blkid_idmag *mag) +{ + int sector = mag->kboff << 1; + struct lvm2_pv_label_header *label; + char *p, *q, uuid[40]; + unsigned int i, b; + unsigned char *buf; + + buf = blkid_probe_get_buffer(pr, + mag->kboff << 10, + 512 + sizeof(struct lvm2_pv_label_header)); + if (!buf) + return -1; + + /* buf is at 0k or 1k offset; find label inside */ + if (memcmp(buf, "LABELONE", 8) == 0) { + label = (struct lvm2_pv_label_header *) buf; + } else if (memcmp(buf + 512, "LABELONE", 8) == 0) { + label = (struct lvm2_pv_label_header *)(buf + 512); + sector++; + } else { + return 1; + } + + if (le64_to_cpu(label->sector_xl) != (unsigned) sector) + return 1; + + if (lvm2_calc_crc(&label->offset_xl, LVM2_LABEL_SIZE - + ((char *) &label->offset_xl - (char *) label)) != + le32_to_cpu(label->crc_xl)) { + DBG(DEBUG_PROBE, + printf("LVM2: label checksum incorrect at sector %d\n", + sector)); + return 1; + } + + for (i = 0, b = 1, p = uuid, q = (char *) label->pv_uuid; i <= 32; + i++, b <<= 1) { + if (b & 0x4444440) + *p++ = '-'; + *p++ = *q++; + } + + uuid[LVM2_ID_LEN+6] = '\0'; + blkid_probe_sprintf_uuid(pr, label->pv_uuid, sizeof(label->pv_uuid), + "%s", uuid); + + /* the mag->magic is the same string as label->type, + * but zero terminated */ + blkid_probe_set_version(pr, mag->magic); + return 0; +} + + +/* NOTE: the original libblkid uses "lvm2pv" as a name */ +const struct blkid_idinfo lvm2_idinfo = +{ + .name = "LVM2_member", + .usage = BLKID_USAGE_RAID, + .probefunc = probe_lvm2, + .magics = + { + { .magic = "LVM2 001", .len = 8, .sboff = 0x218 }, + { .magic = "LVM2 001", .len = 8, .sboff = 0x018 }, + { .magic = "LVM2 001", .len = 8, .kboff = 1, .sboff = 0x018 }, + { .magic = "LVM2 001", .len = 8, .kboff = 1, .sboff = 0x218 }, + { NULL } + } +}; + +const struct blkid_idinfo lvm1_idinfo = +{ + .name = "LVM1_member", + .usage = BLKID_USAGE_RAID, + .magics = + { + { .magic = "HM", .len = 2, .sboff = 0x400 }, + { NULL } + } +}; + + diff --git a/shlibs/blkid/src/probers/minix.c b/shlibs/blkid/src/probers/minix.c new file mode 100644 index 000000000..b29b9a427 --- /dev/null +++ b/shlibs/blkid/src/probers/minix.c @@ -0,0 +1,51 @@ +/* + * Copyright (C) 1999 by Andries Brouwer + * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o + * Copyright (C) 2001 by Andreas Dilger + * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ + +#include "blkidP.h" + +static int probe_minix(blkid_probe pr, const struct blkid_idmag *mag) +{ + /* for more details see magic strings below */ + switch(mag->magic[1]) { + case '\023': + blkid_probe_set_version(pr, "1"); + break; + case '\044': + blkid_probe_set_version(pr, "2"); + break; + case '\115': + blkid_probe_set_version(pr, "3"); + break; + } + return 0; +} + +const struct blkid_idinfo minix_idinfo = +{ + .name = "minix", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_minix, + .magics = + { + /* version 1 */ + { .magic = "\177\023", .len = 2, .kboff = 1, .sboff = 0x10 }, + { .magic = "\217\023", .len = 2, .kboff = 1, .sboff = 0x10 }, + + /* version 2 */ + { .magic = "\150\044", .len = 2, .kboff = 1, .sboff = 0x10 }, + { .magic = "\170\044", .len = 2, .kboff = 1, .sboff = 0x10 }, + + /* version 3 */ + { .magic = "\132\115", .len = 2, .kboff = 1, .sboff = 0x18 }, + { NULL } + } +}; + diff --git a/shlibs/blkid/src/probers/netware.c b/shlibs/blkid/src/probers/netware.c new file mode 100644 index 000000000..722506f87 --- /dev/null +++ b/shlibs/blkid/src/probers/netware.c @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * Inspired by libvolume_id by + * Kay Sievers <kay.sievers@vrfy.org> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdint.h> + +#include "blkidP.h" + +struct netware_super_block { + uint8_t SBH_Signature[4]; + uint16_t SBH_VersionMajor; + uint16_t SBH_VersionMinor; + uint16_t SBH_VersionMediaMajor; + uint16_t SBH_VersionMediaMinor; + uint32_t SBH_ItemsMoved; + uint8_t SBH_InternalID[16]; + uint32_t SBH_PackedSize; + uint32_t SBH_Checksum; + uint32_t supersyncid; + int64_t superlocation[4]; + uint32_t physSizeUsed; + uint32_t sizeUsed; + uint32_t superTimeStamp; + uint32_t reserved0[1]; + int64_t SBH_LoggedPoolDataBlk; + int64_t SBH_PoolDataBlk; + uint8_t SBH_OldInternalID[16]; + uint32_t SBH_PoolToLVStartUTC; + uint32_t SBH_PoolToLVEndUTC; + uint16_t SBH_VersionMediaMajorCreate; + uint16_t SBH_VersionMediaMinorCreate; + uint32_t SBH_BlocksMoved; + uint32_t SBH_TempBTSpBlk; + uint32_t SBH_TempFTSpBlk; + uint32_t SBH_TempFTSpBlk1; + uint32_t SBH_TempFTSpBlk2; + uint32_t nssMagicNumber; + uint32_t poolClassID; + uint32_t poolID; + uint32_t createTime; + int64_t SBH_LoggedVolumeDataBlk; + int64_t SBH_VolumeDataBlk; + int64_t SBH_SystemBeastBlkNum; + uint64_t totalblocks; + uint16_t SBH_Name[64]; + uint8_t SBH_VolumeID[16]; + uint8_t SBH_PoolID[16]; + uint8_t SBH_PoolInternalID[16]; + uint64_t SBH_Lsn; + uint32_t SBH_SS_Enabled; + uint32_t SBH_SS_CreateTime; + uint8_t SBH_SS_OriginalPoolID[16]; + uint8_t SBH_SS_OriginalVolumeID[16]; + uint8_t SBH_SS_Guid[16]; + uint16_t SBH_SS_OriginalName[64]; + uint32_t reserved2[64-(2+46)]; +} __attribute__((__packed__)); + +static int probe_netware(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct netware_super_block *nw; + + nw = blkid_probe_get_sb(pr, mag, struct netware_super_block); + if (!nw) + return -1; + + blkid_probe_set_uuid(pr, nw->SBH_PoolID); + + blkid_probe_sprintf_version(pr, "%u.%02u", + le16_to_cpu(nw->SBH_VersionMediaMajor), + le16_to_cpu(nw->SBH_VersionMediaMinor)); + + return 0; +} + +const struct blkid_idinfo netware_idinfo = +{ + .name = "nss", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_netware, + .magics = + { + { .magic = "SPB5", .len = 4, .kboff = 4 }, + { NULL } + } +}; + + diff --git a/shlibs/blkid/src/probers/ntfs.c b/shlibs/blkid/src/probers/ntfs.c new file mode 100644 index 000000000..55a186a38 --- /dev/null +++ b/shlibs/blkid/src/probers/ntfs.c @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <inttypes.h> + +#include "blkidP.h" + +struct ntfs_super_block { + uint8_t jump[3]; + uint8_t oem_id[8]; + uint8_t bios_parameter_block[25]; + uint16_t unused[2]; + uint64_t number_of_sectors; + uint64_t mft_cluster_location; + uint64_t mft_mirror_cluster_location; + int8_t cluster_per_mft_record; + uint8_t reserved1[3]; + int8_t cluster_per_index_record; + uint8_t reserved2[3]; + uint64_t volume_serial; + uint16_t checksum; +}; + +struct master_file_table_record { + uint32_t magic; + uint16_t usa_ofs; + uint16_t usa_count; + uint64_t lsn; + uint16_t sequence_number; + uint16_t link_count; + uint16_t attrs_offset; + uint16_t flags; + uint32_t bytes_in_use; + uint32_t bytes_allocated; +} __attribute__((__packed__)); + +struct file_attribute { + uint32_t type; + uint32_t len; + uint8_t non_resident; + uint8_t name_len; + uint16_t name_offset; + uint16_t flags; + uint16_t instance; + uint32_t value_len; + uint16_t value_offset; +} __attribute__((__packed__)); + +#define MFT_RECORD_VOLUME 3 +#define MFT_RECORD_ATTR_VOLUME_NAME 0x60 +#define MFT_RECORD_ATTR_VOLUME_INFO 0x70 +#define MFT_RECORD_ATTR_OBJECT_ID 0x40 +#define MFT_RECORD_ATTR_END 0xffffffffu + +static int probe_ntfs(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct ntfs_super_block *ns; + struct master_file_table_record *mft; + struct file_attribute *attr; + unsigned char label_str[129], *cp; + int bytes_per_sector, sectors_per_cluster; + int mft_record_size, attr_off, attr_len; + unsigned int i, attr_type, val_len; + int val_off; + uint64_t nr_clusters; + blkid_loff_t off; + unsigned char *buf_mft, *val; + + ns = blkid_probe_get_sb(pr, mag, struct ntfs_super_block); + if (!ns) + return -1; + + bytes_per_sector = ns->bios_parameter_block[0] + + (ns->bios_parameter_block[1] << 8); + sectors_per_cluster = ns->bios_parameter_block[2]; + + if ((bytes_per_sector < 512) || (sectors_per_cluster == 0)) + return 1; + + if (ns->cluster_per_mft_record < 0) + mft_record_size = 1 << (0 - ns->cluster_per_mft_record); + else + mft_record_size = ns->cluster_per_mft_record * + sectors_per_cluster * bytes_per_sector; + nr_clusters = le64_to_cpu(ns->number_of_sectors) / sectors_per_cluster; + + if ((le64_to_cpu(ns->mft_cluster_location) > nr_clusters) || + (le64_to_cpu(ns->mft_mirror_cluster_location) > nr_clusters)) + return 1; + + off = le64_to_cpu(ns->mft_mirror_cluster_location) * + bytes_per_sector * sectors_per_cluster; + + buf_mft = blkid_probe_get_buffer(pr, off, mft_record_size); + if (!buf_mft) + return 1; + + if (memcmp(buf_mft, "FILE", 4)) + return 1; + + off = le64_to_cpu(ns->mft_cluster_location) * bytes_per_sector * + sectors_per_cluster; + + buf_mft = blkid_probe_get_buffer(pr, off, mft_record_size); + if (!buf_mft) + return 1; + + if (memcmp(buf_mft, "FILE", 4)) + return 1; + + off += MFT_RECORD_VOLUME * mft_record_size; + + buf_mft = blkid_probe_get_buffer(pr, off, mft_record_size); + if (!buf_mft) + return 1; + + if (memcmp(buf_mft, "FILE", 4)) + return 1; + + mft = (struct master_file_table_record *) buf_mft; + + attr_off = le16_to_cpu(mft->attrs_offset); + label_str[0] = 0; + + while (1) { + attr = (struct file_attribute *) (buf_mft + attr_off); + attr_len = le16_to_cpu(attr->len); + attr_type = le32_to_cpu(attr->type); + val_off = le16_to_cpu(attr->value_offset); + val_len = le32_to_cpu(attr->value_len); + + attr_off += attr_len; + + if ((attr_off > mft_record_size) || + (attr_len == 0)) + break; + + if (attr_type == MFT_RECORD_ATTR_END) + break; + + if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) { + if (val_len > sizeof(label_str)) + val_len = sizeof(label_str)-1; + + for (i=0, cp=label_str; i < val_len; i+=2,cp++) { + val = ((uint8_t *) attr) + val_off + i; + *cp = val[0]; + if (val[1]) + *cp = '?'; + } + *cp = 0; + } + } + + blkid_probe_sprintf_uuid(pr, + (unsigned char *) &ns->volume_serial, + sizeof(ns->volume_serial), + "%016" PRIX64, le64_to_cpu(ns->volume_serial)); + if (label_str[0]) + blkid_probe_set_label(pr, label_str, strlen((char *)label_str)); + return 0; +} + + +const struct blkid_idinfo ntfs_idinfo = +{ + .name = "ntfs", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_ntfs, + .magics = + { + { .magic = "NTFS ", .len = 8, .sboff = 3 }, + { NULL } + } +}; + diff --git a/shlibs/blkid/src/probers/nvidia_raid.c b/shlibs/blkid/src/probers/nvidia_raid.c new file mode 100644 index 000000000..76361763c --- /dev/null +++ b/shlibs/blkid/src/probers/nvidia_raid.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> + * + * Inspired by libvolume_id by + * Kay Sievers <kay.sievers@vrfy.org> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdint.h> + +#include "blkidP.h" + +struct nv_metadata { + uint8_t vendor[8]; + uint32_t size; + uint32_t chksum; + uint16_t version; +}; + +#define NVIDIA_SIGNATURE "NVIDIA" + +static int probe_nvraid(blkid_probe pr, const struct blkid_idmag *mag) +{ + uint64_t off; + struct nv_metadata *nv; + + if (pr->size < 0x10000) + return -1; + + off = ((pr->size / 0x200) - 2) * 0x200; + nv = (struct nv_metadata *) + blkid_probe_get_buffer(pr, + off, + sizeof(struct nv_metadata)); + if (!nv) + return -1; + + if (memcmp(nv->vendor, NVIDIA_SIGNATURE, sizeof(NVIDIA_SIGNATURE)-1) != 0) + return -1; + + if (blkid_probe_sprintf_version(pr, "%u", le16_to_cpu(nv->version)) != 0) + return -1; + + return 0; +} + +const struct blkid_idinfo nvraid_idinfo = { + .name = "nvidia_raid_member", + .usage = BLKID_USAGE_RAID, + .probefunc = probe_nvraid, + .magics = BLKID_NONE_MAGIC +}; + + diff --git a/shlibs/blkid/src/probers/ocfs.c b/shlibs/blkid/src/probers/ocfs.c new file mode 100644 index 000000000..f9bd11aae --- /dev/null +++ b/shlibs/blkid/src/probers/ocfs.c @@ -0,0 +1,210 @@ +/* + * Copyright (C) 1999, 2001 by Andries Brouwer + * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdint.h> + +#include "blkidP.h" + +struct ocfs_volume_header { + unsigned char minor_version[4]; + unsigned char major_version[4]; + unsigned char signature[128]; + char mount[128]; + unsigned char mount_len[2]; +} __attribute__((packed)); + +struct ocfs_volume_label { + unsigned char disk_lock[48]; + char label[64]; + unsigned char label_len[2]; + unsigned char vol_id[16]; + unsigned char vol_id_len[2]; +} __attribute__((packed)); + +#define ocfsmajor(o) ( (uint32_t) o.major_version[0] \ + + (((uint32_t) o.major_version[1]) << 8) \ + + (((uint32_t) o.major_version[2]) << 16) \ + + (((uint32_t) o.major_version[3]) << 24)) + +#define ocfsminor(o) ( (uint32_t) o.minor_version[0] \ + + (((uint32_t) o.minor_version[1]) << 8) \ + + (((uint32_t) o.minor_version[2]) << 16) \ + + (((uint32_t) o.minor_version[3]) << 24)) + +#define ocfslabellen(o) ((uint32_t)o.label_len[0] + (((uint32_t) o.label_len[1]) << 8)) +#define ocfsmountlen(o) ((uint32_t)o.mount_len[0] + (((uint32_t) o.mount_len[1]) << 8)) + +struct ocfs2_super_block { + uint8_t i_signature[8]; + uint32_t i_generation; + int16_t i_suballoc_slot; + uint16_t i_suballoc_bit; + uint32_t i_reserved0; + uint32_t i_clusters; + uint32_t i_uid; + uint32_t i_gid; + uint64_t i_size; + uint16_t i_mode; + uint16_t i_links_count; + uint32_t i_flags; + uint64_t i_atime; + uint64_t i_ctime; + uint64_t i_mtime; + uint64_t i_dtime; + uint64_t i_blkno; + uint64_t i_last_eb_blk; + uint32_t i_fs_generation; + uint32_t i_atime_nsec; + uint32_t i_ctime_nsec; + uint32_t i_mtime_nsec; + uint64_t i_reserved1[9]; + uint64_t i_pad1; + uint16_t s_major_rev_level; + uint16_t s_minor_rev_level; + uint16_t s_mnt_count; + int16_t s_max_mnt_count; + uint16_t s_state; + uint16_t s_errors; + uint32_t s_checkinterval; + uint64_t s_lastcheck; + uint32_t s_creator_os; + uint32_t s_feature_compat; + uint32_t s_feature_incompat; + uint32_t s_feature_ro_compat; + uint64_t s_root_blkno; + uint64_t s_system_dir_blkno; + uint32_t s_blocksize_bits; + uint32_t s_clustersize_bits; + uint16_t s_max_slots; + uint16_t s_reserved1; + uint32_t s_reserved2; + uint64_t s_first_cluster_group; + uint8_t s_label[64]; + uint8_t s_uuid[16]; +} __attribute__((packed)); + +struct oracle_asm_disk_label { + char dummy[32]; + char dl_tag[8]; + char dl_id[24]; +} __attribute__((packed)); + +static int probe_ocfs(blkid_probe pr, const struct blkid_idmag *mag) +{ + unsigned char *buf; + struct ocfs_volume_header ovh; + struct ocfs_volume_label ovl; + uint32_t maj, min; + + /* header */ + buf = blkid_probe_get_buffer(pr, mag->kboff << 10, + sizeof(struct ocfs_volume_header)); + if (!buf) + return -1; + memcpy(&ovh, buf, sizeof(ovh)); + + /* label */ + buf = blkid_probe_get_buffer(pr, (mag->kboff << 10) + 512, + sizeof(struct ocfs_volume_label)); + if (!buf) + return -1; + memcpy(&ovl, buf, sizeof(ovl)); + + maj = ocfsmajor(ovh); + min = ocfsminor(ovh); + + if (maj == 1) + blkid_probe_set_value(pr, "SEC_TYPE", + (unsigned char *) "ocfs1", sizeof("ocfs1")); + else if (maj >= 9) + blkid_probe_set_value(pr, "SEC_TYPE", + (unsigned char *) "ntocfs", sizeof("ntocfs")); + + blkid_probe_set_label(pr, (unsigned char *) ovl.label, + ocfslabellen(ovl)); + blkid_probe_set_value(pr, "MOUNT", (unsigned char *) ovh.mount, + ocfsmountlen(ovh)); + blkid_probe_set_uuid(pr, ovl.vol_id); + blkid_probe_sprintf_version(pr, "%u.%u", maj, min); + return 0; +} + +static int probe_ocfs2(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct ocfs2_super_block *osb; + + osb = blkid_probe_get_sb(pr, mag, struct ocfs2_super_block); + if (!osb) + return -1; + + blkid_probe_set_label(pr, (unsigned char *) osb->s_label, sizeof(osb->s_label)); + blkid_probe_set_uuid(pr, osb->s_uuid); + + blkid_probe_sprintf_version(pr, "%u.%u", + le16_to_cpu(osb->s_major_rev_level), + le16_to_cpu(osb->s_minor_rev_level)); + + return 0; +} + +static int probe_oracleasm(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct oracle_asm_disk_label *dl; + + dl = blkid_probe_get_sb(pr, mag, struct oracle_asm_disk_label); + if (!dl) + return -1; + + blkid_probe_set_label(pr, (unsigned char *) dl->dl_id, sizeof(dl->dl_id)); + return 0; +} + + +const struct blkid_idinfo ocfs_idinfo = +{ + .name = "ocfs", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_ocfs, + .magics = + { + { .magic = "OracleCFS", .len = 9, .kboff = 8 }, + { NULL } + } +}; + +const struct blkid_idinfo ocfs2_idinfo = +{ + .name = "ocfs2", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_ocfs2, + .magics = + { + { .magic = "OCFSV2", .len = 6, .kboff = 1 }, + { .magic = "OCFSV2", .len = 6, .kboff = 2 }, + { .magic = "OCFSV2", .len = 6, .kboff = 4 }, + { .magic = "OCFSV2", .len = 6, .kboff = 8 }, + { NULL } + } +}; + +const struct blkid_idinfo oracleasm_idinfo = +{ + .name = "oracleasm", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_oracleasm, + .magics = + { + { .magic = "ORCLDISK", .len = 8, .sboff = 32 }, + { NULL } + } +}; + diff --git a/shlibs/blkid/src/probers/probers.h b/shlibs/blkid/src/probers/probers.h new file mode 100644 index 000000000..c3b227743 --- /dev/null +++ b/shlibs/blkid/src/probers/probers.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#ifndef _BLKID_PROBE_H +#define _BLKID_PROBE_H + +extern const struct blkid_idinfo cramfs_idinfo; +extern const struct blkid_idinfo swap_idinfo; +extern const struct blkid_idinfo swsuspend_idinfo; +extern const struct blkid_idinfo adraid_idinfo; +extern const struct blkid_idinfo ddfraid_idinfo; +extern const struct blkid_idinfo iswraid_idinfo; +extern const struct blkid_idinfo jmraid_idinfo; +extern const struct blkid_idinfo lsiraid_idinfo; +extern const struct blkid_idinfo nvraid_idinfo; +extern const struct blkid_idinfo pdcraid_idinfo; +extern const struct blkid_idinfo silraid_idinfo; +extern const struct blkid_idinfo viaraid_idinfo; +extern const struct blkid_idinfo linuxraid_idinfo; +extern const struct blkid_idinfo ext4dev_idinfo; +extern const struct blkid_idinfo ext4_idinfo; +extern const struct blkid_idinfo ext3_idinfo; +extern const struct blkid_idinfo ext2_idinfo; +extern const struct blkid_idinfo jbd_idinfo; +extern const struct blkid_idinfo jfs_idinfo; +extern const struct blkid_idinfo xfs_idinfo; +extern const struct blkid_idinfo gfs_idinfo; +extern const struct blkid_idinfo gfs2_idinfo; +extern const struct blkid_idinfo romfs_idinfo; +extern const struct blkid_idinfo ocfs_idinfo; +extern const struct blkid_idinfo ocfs2_idinfo; +extern const struct blkid_idinfo oracleasm_idinfo; +extern const struct blkid_idinfo reiser_idinfo; +extern const struct blkid_idinfo reiser4_idinfo; +extern const struct blkid_idinfo hfs_idinfo; +extern const struct blkid_idinfo hfsplus_idinfo; +extern const struct blkid_idinfo ntfs_idinfo; +extern const struct blkid_idinfo iso9660_idinfo; +extern const struct blkid_idinfo udf_idinfo; +extern const struct blkid_idinfo vxfs_idinfo; +extern const struct blkid_idinfo minix_idinfo; +extern const struct blkid_idinfo vfat_idinfo; +extern const struct blkid_idinfo ufs_idinfo; +extern const struct blkid_idinfo hpfs_idinfo; +extern const struct blkid_idinfo lvm2_idinfo; +extern const struct blkid_idinfo lvm1_idinfo; +extern const struct blkid_idinfo luks_idinfo; +extern const struct blkid_idinfo highpoint37x_idinfo; +extern const struct blkid_idinfo highpoint45x_idinfo; +extern const struct blkid_idinfo squashfs_idinfo; +extern const struct blkid_idinfo netware_idinfo; +extern const struct blkid_idinfo sysv_idinfo; +extern const struct blkid_idinfo xenix_idinfo; +extern const struct blkid_idinfo btrfs_idinfo; +extern const struct blkid_idinfo zfs_idinfo; + +#endif /* _BLKID_PROBE_H */ diff --git a/shlibs/blkid/src/probers/promise_raid.c b/shlibs/blkid/src/probers/promise_raid.c new file mode 100644 index 000000000..295400925 --- /dev/null +++ b/shlibs/blkid/src/probers/promise_raid.c @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * Inspired by libvolume_id by + * Kay Sievers <kay.sievers@vrfy.org> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <stdint.h> + +#include "blkidP.h" + +struct promise_metadata { + uint8_t sig[24]; +}; + +#define PDC_CONFIG_OFF 0x1200 +#define PDC_SIGNATURE "Promise Technology, Inc." + +static int probe_pdcraid(blkid_probe pr, const struct blkid_idmag *mag) +{ + unsigned int i; + static unsigned int sectors[] = { + 63, 255, 256, 16, 399, 0 + }; + + if (pr->size < 0x40000) + return -1; + + for (i = 0; sectors[i] != 0; i++) { + uint64_t off; + struct promise_metadata *pdc; + + off = ((pr->size / 0x200) - sectors[i]) * 0x200; + pdc = (struct promise_metadata *) + blkid_probe_get_buffer(pr, + off, + sizeof(struct promise_metadata)); + if (!pdc) + return -1; + + if (memcmp(pdc->sig, PDC_SIGNATURE, + sizeof(PDC_SIGNATURE) - 1) == 0) + return 0; + } + return -1; +} + +const struct blkid_idinfo pdcraid_idinfo = { + .name = "promise_fasttrack_raid_member", + .usage = BLKID_USAGE_RAID, + .probefunc = probe_pdcraid, + .magics = BLKID_NONE_MAGIC +}; + + diff --git a/shlibs/blkid/src/probers/reiserfs.c b/shlibs/blkid/src/probers/reiserfs.c new file mode 100644 index 000000000..29e1faa0f --- /dev/null +++ b/shlibs/blkid/src/probers/reiserfs.c @@ -0,0 +1,126 @@ +/* + * Copyright (C) 1999, 2001 by Andries Brouwer + * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdint.h> + +#include "blkidP.h" + +struct reiserfs_super_block { + uint32_t rs_blocks_count; + uint32_t rs_free_blocks; + uint32_t rs_root_block; + uint32_t rs_journal_block; + uint32_t rs_journal_dev; + uint32_t rs_orig_journal_size; + uint32_t rs_dummy2[5]; + uint16_t rs_blocksize; + uint16_t rs_dummy3[3]; + unsigned char rs_magic[12]; + uint32_t rs_dummy4[5]; + unsigned char rs_uuid[16]; + char rs_label[16]; +}; + +struct reiser4_super_block { + unsigned char rs4_magic[16]; + uint16_t rs4_dummy[2]; + unsigned char rs4_uuid[16]; + unsigned char rs4_label[16]; + uint64_t rs4_dummy2; +}; + +static int probe_reiser(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct reiserfs_super_block *rs; + unsigned int blocksize; + + rs = blkid_probe_get_sb(pr, mag, struct reiserfs_super_block); + if (!rs) + return -1; + + blocksize = le16_to_cpu(rs->rs_blocksize); + + /* The blocksize must be at least 1k */ + if ((blocksize >> 10) == 0) + return -BLKID_ERR_PARAM; + + /* If the superblock is inside the journal, we have the wrong one */ + if (mag->kboff / (blocksize >> 10) > le32_to_cpu(rs->rs_journal_block)) + return -BLKID_ERR_BIG; + + /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */ + if (mag->magic[6] == '2' || mag->magic[6] == '3') { + if (*rs->rs_label) + blkid_probe_set_label(pr, + (unsigned char *) rs->rs_label, + sizeof(rs->rs_label)); + blkid_probe_set_uuid(pr, rs->rs_uuid); + } + + if (mag->magic[6] == '3') + blkid_probe_set_version(pr, "JR"); + else if (mag->magic[6] == '2') + blkid_probe_set_version(pr, "3.6"); + else + blkid_probe_set_version(pr, "3.5"); + + return 0; +} + +static int probe_reiser4(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct reiser4_super_block *rs4; + + rs4 = blkid_probe_get_sb(pr, mag, struct reiser4_super_block); + if (!rs4) + return -1; + + if (*rs4->rs4_label) + blkid_probe_set_label(pr, rs4->rs4_label, sizeof(rs4->rs4_label)); + blkid_probe_set_uuid(pr, rs4->rs4_uuid); + blkid_probe_set_version(pr, "4"); + + return 0; +} + + +const struct blkid_idinfo reiser_idinfo = +{ + .name = "reiser", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_reiser, + .magics = + { + { .magic = "ReIsErFs", .len = 8, .kboff = 8, .sboff = 0x34 }, + { .magic = "ReIsEr2Fs", .len = 9, .kboff = 64, .sboff = 0x34 }, + { .magic = "ReIsEr3Fs", .len = 9, .kboff = 64, .sboff = 0x34 }, + { .magic = "ReIsErFs", .len = 8, .kboff = 64, .sboff = 0x34 }, + { .magic = "ReIsErFs", .len = 8, .kboff = 8, .sboff = 20 }, + { NULL } + } +}; + +const struct blkid_idinfo reiser4_idinfo = +{ + .name = "reiser4", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_reiser4, + .magics = + { + { .magic = "ReIsEr4", .len = 7, .kboff = 64 }, + { NULL } + } +}; + + + + diff --git a/shlibs/blkid/src/probers/romfs.c b/shlibs/blkid/src/probers/romfs.c new file mode 100644 index 000000000..b5c20ab7f --- /dev/null +++ b/shlibs/blkid/src/probers/romfs.c @@ -0,0 +1,51 @@ +/* + * Copyright (C) 1999, 2001 by Andries Brouwer + * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <stdint.h> + +#include "blkidP.h" + +struct romfs_super_block { + unsigned char ros_magic[8]; + uint32_t ros_dummy1[2]; + unsigned char ros_volume[16]; +}; + +static int probe_romfs(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct romfs_super_block *ros; + + ros = blkid_probe_get_sb(pr, mag, struct romfs_super_block); + if (!ros) + return -1; + + if (strlen((char *) ros->ros_volume)) + blkid_probe_set_label(pr, ros->ros_volume, + sizeof(ros->ros_volume)); + return 0; +} + +const struct blkid_idinfo romfs_idinfo = +{ + .name = "romfs", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_romfs, + .magics = + { + { .magic = "-rom1fs-", .len = 8 }, + { NULL } + } +}; + diff --git a/shlibs/blkid/src/probers/silicon_raid.c b/shlibs/blkid/src/probers/silicon_raid.c new file mode 100644 index 000000000..a65d79a83 --- /dev/null +++ b/shlibs/blkid/src/probers/silicon_raid.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> + * + * Inspired by libvolume_id by + * Kay Sievers <kay.sievers@vrfy.org> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <stdint.h> + +#include "blkidP.h" + +struct silicon_metadata { + uint8_t unknown0[0x2E]; + uint8_t ascii_version[0x36 - 0x2E]; + uint8_t diskname[0x56 - 0x36]; + uint8_t unknown1[0x60 - 0x56]; + uint32_t magic; + uint32_t unknown1a[0x6C - 0x64]; + uint32_t array_sectors_low; + uint32_t array_sectors_high; + uint8_t unknown2[0x78 - 0x74]; + uint32_t thisdisk_sectors; + uint8_t unknown3[0x100 - 0x7C]; + uint8_t unknown4[0x104 - 0x100]; + uint16_t product_id; + uint16_t vendor_id; + uint16_t minor_ver; + uint16_t major_ver; +}; + +#define SILICON_MAGIC 0x2F000000 + + +static int probe_silraid(blkid_probe pr, const struct blkid_idmag *mag) +{ + uint64_t off; + struct silicon_metadata *sil; + + if (pr->size < 0x10000) + return -1; + + off = ((pr->size / 0x200) - 1) * 0x200; + + sil = (struct silicon_metadata *) + blkid_probe_get_buffer(pr, off, + sizeof(struct silicon_metadata)); + if (!sil) + return -1; + + if (le32_to_cpu(sil->magic) != SILICON_MAGIC) + return -1; + + if (blkid_probe_sprintf_version(pr, "%u.%u", + le16_to_cpu(sil->major_ver), + le16_to_cpu(sil->minor_ver)) != 0) + return -1; + + return 0; +} + +const struct blkid_idinfo silraid_idinfo = { + .name = "silicon_medley_raid_member", + .usage = BLKID_USAGE_RAID, + .probefunc = probe_silraid, + .magics = BLKID_NONE_MAGIC +}; + + diff --git a/shlibs/blkid/src/probers/squashfs.c b/shlibs/blkid/src/probers/squashfs.c new file mode 100644 index 000000000..74f53bfb6 --- /dev/null +++ b/shlibs/blkid/src/probers/squashfs.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * Inspired by libvolume_id by + * Kay Sievers <kay.sievers@vrfy.org> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdint.h> + +#include "bitops.h" /* swab16() */ +#include "blkidP.h" + +struct sqsh_super_block { + uint32_t s_magic; + uint32_t inodes; + uint32_t bytes_used_2; + uint32_t uid_start_2; + uint32_t guid_start_2; + uint32_t inode_table_start_2; + uint32_t directory_table_start_2; + uint16_t s_major; + uint16_t s_minor; +}; + +static int probe_squashfs(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct sqsh_super_block *sq; + + sq = blkid_probe_get_sb(pr, mag, struct sqsh_super_block); + if (!sq) + return -1; + + if (strcmp(mag->magic, "sqsh") == 0 || + strcmp(mag->magic, "qshs") == 0) + blkid_probe_sprintf_version(pr, "%u.%u", + sq->s_major, + sq->s_minor); + else + blkid_probe_sprintf_version(pr, "%u.%u", + swab16(sq->s_major), + swab16(sq->s_minor)); + return 0; +} + +const struct blkid_idinfo squashfs_idinfo = +{ + .name = "squashfs", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_squashfs, + .magics = + { + { .magic = "sqsh", .len = 4 }, + { .magic = "hsqs", .len = 4 }, /* swap */ + + /* LZMA version */ + { .magic = "qshs", .len = 4 }, + { .magic = "shsq", .len = 4 }, /* swap */ + { NULL } + } +}; + + diff --git a/shlibs/blkid/src/probers/swap.c b/shlibs/blkid/src/probers/swap.c new file mode 100644 index 000000000..86eb94c61 --- /dev/null +++ b/shlibs/blkid/src/probers/swap.c @@ -0,0 +1,149 @@ +/* + * Copyright (C) 1999 by Andries Brouwer + * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o + * Copyright (C) 2001 by Andreas Dilger + * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <stdint.h> + +#include "blkidP.h" + +/* linux-2.6/include/linux/swap.h */ +struct swap_header_v1_2 { + /* char bootbits[1024]; */ /* Space for disklabel etc. */ + uint32_t version; + uint32_t lastpage; + uint32_t nr_badpages; + unsigned char uuid[16]; + unsigned char volume[16]; + uint32_t padding[117]; + uint32_t badpages[1]; +}; + +#define PAGESIZE_MIN 0xff6 /* 4086 (arm, i386, ...) */ +#define PAGESIZE_MAX 0xfff6 /* 65526 (ia64) */ + + +static int swap_set_info(blkid_probe pr, const char *version) +{ + struct swap_header_v1_2 *hdr; + + /* Swap header always located at offset of 1024 bytes */ + hdr = (struct swap_header_v1_2 *) blkid_probe_get_buffer(pr, 1024, + sizeof(struct swap_header_v1_2)); + if (!hdr) + return -1; + + /* SWAPSPACE2 - check for wrong version or zeroed pagecount */ + if (strcmp(version, "2") == 0 && + (hdr->version != 1 || hdr->lastpage == 0)) + return -1; + + /* arbitrary sanity check.. is there any garbage down there? */ + if (hdr->padding[32] == 0 && hdr->padding[33] == 0) { + if (hdr->volume[0] && blkid_probe_set_label(pr, hdr->volume, + sizeof(hdr->volume)) < 0) + return -1; + if (hdr->uuid[0] && blkid_probe_set_uuid(pr, hdr->uuid) < 0) + return -1; + } + + blkid_probe_set_version(pr, version); + return 0; +} + +static int probe_swap(blkid_probe pr, const struct blkid_idmag *mag) +{ + if (!mag) + return -1; + + if (!memcmp(mag->magic, "SWAP-SPACE", mag->len)) { + /* swap v0 doesn't support LABEL or UUID */ + blkid_probe_set_version(pr, "1"); + return 0; + + } else if (!memcmp(mag->magic, "SWAPSPACE2", mag->len)) + return swap_set_info(pr, "2"); + + return -1; +} + +static int probe_swsuspend(blkid_probe pr, const struct blkid_idmag *mag) +{ + if (!mag) + return -1; + if (!memcmp(mag->magic, "S1SUSPEND", mag->len)) + return swap_set_info(pr, "s1suspend"); + if (!memcmp(mag->magic, "S2SUSPEND", mag->len)) + return swap_set_info(pr, "s2suspend"); + if (!memcmp(mag->magic, "ULSUSPEND", mag->len)) + return swap_set_info(pr, "ulsuspend"); + if (!memcmp(mag->magic, "\xed\xc3\x02\xe9\x98\x56\xe5\x0c", mag->len)) + return swap_set_info(pr, "tuxonice"); + + return -1; /* no signature detected */ +} + +const struct blkid_idinfo swap_idinfo = +{ + .name = "swap", + .usage = BLKID_USAGE_OTHER, + .probefunc = probe_swap, + .magics = + { + { "SWAP-SPACE", 10, 0, 0xff6 }, + { "SWAPSPACE2", 10, 0, 0xff6 }, + { "SWAP-SPACE", 10, 0, 0x1ff6 }, + { "SWAPSPACE2", 10, 0, 0x1ff6 }, + { "SWAP-SPACE", 10, 0, 0x3ff6 }, + { "SWAPSPACE2", 10, 0, 0x3ff6 }, + { "SWAP-SPACE", 10, 0, 0x7ff6 }, + { "SWAPSPACE2", 10, 0, 0x7ff6 }, + { "SWAP-SPACE", 10, 0, 0xfff6 }, + { "SWAPSPACE2", 10, 0, 0xfff6 }, + { NULL } + } +}; + + +const struct blkid_idinfo swsuspend_idinfo = +{ + .name = "swsupend", + .usage = BLKID_USAGE_OTHER, + .probefunc = probe_swsuspend, + .magics = + { + { "S1SUSPEND", 9, 0, 0xff6 }, + { "S2SUSPEND", 9, 0, 0xff6 }, + { "ULSUSPEND", 9, 0, 0xff6 }, + { "\xed\xc3\x02\xe9\x98\x56\xe5\x0c", 8, 0, 0xff6 }, + { "S1SUSPEND", 9, 0, 0x1ff6 }, + { "S2SUSPEND", 9, 0, 0x1ff6 }, + { "ULSUSPEND", 9, 0, 0x1ff6 }, + { "\xed\xc3\x02\xe9\x98\x56\xe5\x0c", 8, 0, 0x1ff6 }, + { "S1SUSPEND", 9, 0, 0x3ff6 }, + { "S2SUSPEND", 9, 0, 0x3ff6 }, + { "ULSUSPEND", 9, 0, 0x3ff6 }, + { "\xed\xc3\x02\xe9\x98\x56\xe5\x0c", 8, 0, 0x3ff6 }, + { "S1SUSPEND", 9, 0, 0x7ff6 }, + { "S2SUSPEND", 9, 0, 0x7ff6 }, + { "ULSUSPEND", 9, 0, 0x7ff6 }, + { "\xed\xc3\x02\xe9\x98\x56\xe5\x0c", 8, 0, 0x7ff6 }, + { "S1SUSPEND", 9, 0, 0xfff6 }, + { "S2SUSPEND", 9, 0, 0xfff6 }, + { "ULSUSPEND", 9, 0, 0xfff6 }, + { "\xed\xc3\x02\xe9\x98\x56\xe5\x0c", 8, 0, 0xfff6 }, + { NULL } + } +}; + diff --git a/shlibs/blkid/src/probers/sysv.c b/shlibs/blkid/src/probers/sysv.c new file mode 100644 index 000000000..933163a27 --- /dev/null +++ b/shlibs/blkid/src/probers/sysv.c @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * This is written from sratch according to Linux kernel fs/sysv/super.c file. + * It seems that sysv probing code in libvolume_id and also in the original + * blkid is useless. + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdint.h> + +#include "blkidP.h" + +#define XENIX_NICINOD 100 +#define XENIX_NICFREE 100 + +struct xenix_super_block { + uint16_t s_isize; + uint32_t s_fsize; + uint16_t s_nfree; + uint32_t s_free[XENIX_NICFREE]; + uint16_t s_ninode; + uint16_t s_inode[XENIX_NICINOD]; + uint8_t s_flock; + uint8_t s_ilock; + uint8_t s_fmod; + uint8_t s_ronly; + uint32_t s_time; + uint32_t s_tfree; + uint16_t s_tinode; + uint16_t s_dinfo[4]; + uint8_t s_fname[6]; + uint8_t s_fpack[6]; + uint8_t s_clean; + uint8_t s_fill[371]; + uint32_t s_magic; + uint32_t s_type; +}; + + +#define SYSV_NICINOD 100 +#define SYSV_NICFREE 50 + +struct sysv_super_block +{ + uint16_t s_isize; + uint16_t s_pad0; + uint32_t s_fsize; + uint16_t s_nfree; + uint16_t s_pad1; + uint32_t s_free[SYSV_NICFREE]; + uint16_t s_ninode; + uint16_t s_pad2; + uint16_t s_inode[SYSV_NICINOD]; + uint8_t s_flock; + uint8_t s_ilock; + uint8_t s_fmod; + uint8_t s_ronly; + uint32_t s_time; + uint16_t s_dinfo[4]; + uint32_t s_tfree; + uint16_t s_tinode; + uint16_t s_pad3; + uint8_t s_fname[6]; + uint8_t s_fpack[6]; + uint32_t s_fill[12]; + uint32_t s_state; + uint32_t s_magic; + uint32_t s_type; +}; + +static int probe_xenix(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct xenix_super_block *sb; + + sb = blkid_probe_get_sb(pr, mag, struct xenix_super_block); + if (!sb) + return -1; + blkid_probe_set_label(pr, sb->s_fname, sizeof(sb->s_fname)); + return 0; +} + +#define SYSV_BLOCK_SIZE 1024 + +/* Note that we don't probe for Coherent FS, this FS does not have + * magic string. (It requires to probe fname/fpack field..) + */ +static int probe_sysv(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct sysv_super_block *sb; + int blocks[] = {0, 9, 15, 18}; + int i; + + for (i = 0; i < ARRAY_SIZE(blocks); i++) { + int off = blocks[i] * SYSV_BLOCK_SIZE + SYSV_BLOCK_SIZE/2; + + sb = (struct sysv_super_block *) + blkid_probe_get_buffer(pr, + off, + sizeof(struct sysv_super_block)); + if (!sb) + return -1; + + if (sb->s_magic == cpu_to_le32(0xfd187e20) || + sb->s_magic == cpu_to_be32(0xfd187e20)) { + blkid_probe_set_label(pr, sb->s_fname, sizeof(sb->s_fname)); + return 0; + } + } + return 1; +} + +const struct blkid_idinfo xenix_idinfo = +{ + .name = "xenix", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_xenix, + .magics = + { + { .magic = "\x2b\x55\x44", .len = 3, .kboff = 1, .sboff = 0x400 }, + { .magic = "\x44\x55\x2b", .len = 3, .kboff = 1, .sboff = 0x400 }, + { NULL } + } +}; + +const struct blkid_idinfo sysv_idinfo = +{ + .name = "sysv", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_sysv, + + /* SYSV is BE and LE and superblock could be on four positions. It's + * simpler to probe for the magic string by .probefunc(). + */ + .magics = BLKID_NONE_MAGIC +}; + diff --git a/shlibs/blkid/src/probers/udf.c b/shlibs/blkid/src/probers/udf.c new file mode 100644 index 000000000..5f4046d6d --- /dev/null +++ b/shlibs/blkid/src/probers/udf.c @@ -0,0 +1,159 @@ +/* + * Copyright (C) 1999 by Andries Brouwer + * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o + * Copyright (C) 2001 by Andreas Dilger + * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <stdint.h> + +#include "blkidP.h" + +struct volume_descriptor { + struct descriptor_tag { + uint16_t id; + uint16_t version; + uint8_t checksum; + uint8_t reserved; + uint16_t serial; + uint16_t crc; + uint16_t crc_len; + uint32_t location; + } tag; + union { + struct anchor_descriptor { + uint32_t length; + uint32_t location; + } anchor; + struct primary_descriptor { + uint32_t seq_num; + uint32_t desc_num; + struct dstring { + uint8_t clen; + uint8_t c[31]; + } ident; + } primary; + } type; +}; + +struct volume_structure_descriptor { + uint8_t type; + uint8_t id[5]; + uint8_t version; +}; + +#define UDF_VSD_OFFSET 0x8000 + +static int probe_udf(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct volume_descriptor *vd; + struct volume_structure_descriptor *vsd; + unsigned int bs; + unsigned int b; + unsigned int type; + unsigned int count; + unsigned int loc; + + /* search Volume Sequence Descriptor (VSD) to get the logical + * block size of the volume */ + for (bs = 0x800; bs < 0x8000; bs += 0x800) { + vsd = (struct volume_structure_descriptor *) + blkid_probe_get_buffer(pr, + UDF_VSD_OFFSET + bs, + sizeof(*vsd)); + if (!vsd) + return 1; + if (vsd->id[0] != '\0') + goto nsr; + } + return -1; + +nsr: + /* search the list of VSDs for a NSR descriptor */ + for (b = 0; b < 64; b++) { + vsd = (struct volume_structure_descriptor *) + blkid_probe_get_buffer(pr, + UDF_VSD_OFFSET + (b * bs), + sizeof(*vsd)); + if (!vsd) + return -1; + if (vsd->id[0] == '\0') + return -1; + if (memcmp(vsd->id, "NSR02", 5) == 0) + goto anchor; + if (memcmp(vsd->id, "NSR03", 5) == 0) + goto anchor; + } + return -1; + +anchor: + /* read Anchor Volume Descriptor (AVDP) */ + vd = (struct volume_descriptor *) + blkid_probe_get_buffer(pr, 256 * bs, sizeof(*vd)); + if (!vd) + return -1; + + type = le16_to_cpu(vd->tag.id); + if (type != 2) /* TAG_ID_AVDP */ + return 0; + + /* get desriptor list address and block count */ + count = le32_to_cpu(vd->type.anchor.length) / bs; + loc = le32_to_cpu(vd->type.anchor.location); + + /* pick the primary descriptor from the list */ + for (b = 0; b < count; b++) { + vd = (struct volume_descriptor *) + blkid_probe_get_buffer(pr, (loc + b) * bs, sizeof(*vd)); + if (!vd) + return -1; + + type = le16_to_cpu(vd->tag.id); + if (type == 0) + break; + if (le32_to_cpu(vd->tag.location) != loc + b) + break; + if (type == 1) { /* TAG_ID_PVD */ + uint8_t clen = vd->type.primary.ident.clen; + + if (clen == 8) + blkid_probe_set_label(pr, + vd->type.primary.ident.c, 31); + else if (clen == 16) + blkid_probe_set_utf8label(pr, + vd->type.primary.ident.c, + 31, BLKID_ENC_UTF16BE); + } + } + + return 0; +} + + +const struct blkid_idinfo udf_idinfo = +{ + .name = "udf", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_udf, + .flags = BLKID_IDINFO_TOLERANT, + .magics = + { + { .magic = "BEA01", .len = 5, .kboff = 32, .sboff = 1 }, + { .magic = "BOOT2", .len = 5, .kboff = 32, .sboff = 1 }, + { .magic = "CD001", .len = 5, .kboff = 32, .sboff = 1 }, + { .magic = "CDW02", .len = 5, .kboff = 32, .sboff = 1 }, + { .magic = "NSR02", .len = 5, .kboff = 32, .sboff = 1 }, + { .magic = "NSR03", .len = 5, .kboff = 32, .sboff = 1 }, + { .magic = "TEA01", .len = 5, .kboff = 32, .sboff = 1 }, + { NULL } + } +}; diff --git a/shlibs/blkid/src/probers/ufs.c b/shlibs/blkid/src/probers/ufs.c new file mode 100644 index 000000000..fe9870d84 --- /dev/null +++ b/shlibs/blkid/src/probers/ufs.c @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * Inspired by libvolume_id by + * Kay Sievers <kay.sievers@vrfy.org> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <stdint.h> + +#include "blkidP.h" + +struct ufs_super_block { + uint32_t fs_link; + uint32_t fs_rlink; + uint32_t fs_sblkno; + uint32_t fs_cblkno; + uint32_t fs_iblkno; + uint32_t fs_dblkno; + uint32_t fs_cgoffset; + uint32_t fs_cgmask; + uint32_t fs_time; + uint32_t fs_size; + uint32_t fs_dsize; + uint32_t fs_ncg; + uint32_t fs_bsize; + uint32_t fs_fsize; + uint32_t fs_frag; + uint32_t fs_minfree; + uint32_t fs_rotdelay; + uint32_t fs_rps; + uint32_t fs_bmask; + uint32_t fs_fmask; + uint32_t fs_bshift; + uint32_t fs_fshift; + uint32_t fs_maxcontig; + uint32_t fs_maxbpg; + uint32_t fs_fragshift; + uint32_t fs_fsbtodb; + uint32_t fs_sbsize; + uint32_t fs_csmask; + uint32_t fs_csshift; + uint32_t fs_nindir; + uint32_t fs_inopb; + uint32_t fs_nspf; + uint32_t fs_optim; + uint32_t fs_npsect_state; + uint32_t fs_interleave; + uint32_t fs_trackskew; + uint32_t fs_id[2]; + uint32_t fs_csaddr; + uint32_t fs_cssize; + uint32_t fs_cgsize; + uint32_t fs_ntrak; + uint32_t fs_nsect; + uint32_t fs_spc; + uint32_t fs_ncyl; + uint32_t fs_cpg; + uint32_t fs_ipg; + uint32_t fs_fpg; + struct ufs_csum { + uint32_t cs_ndir; + uint32_t cs_nbfree; + uint32_t cs_nifree; + uint32_t cs_nffree; + } fs_cstotal; + int8_t fs_fmod; + int8_t fs_clean; + int8_t fs_ronly; + int8_t fs_flags; + union { + struct { + int8_t fs_fsmnt[512]; + uint32_t fs_cgrotor; + uint32_t fs_csp[31]; + uint32_t fs_maxcluster; + uint32_t fs_cpc; + uint16_t fs_opostbl[16][8]; + } fs_u1; + struct { + int8_t fs_fsmnt[468]; + uint8_t fs_volname[32]; + uint64_t fs_swuid; + int32_t fs_pad; + uint32_t fs_cgrotor; + uint32_t fs_ocsp[28]; + uint32_t fs_contigdirs; + uint32_t fs_csp; + uint32_t fs_maxcluster; + uint32_t fs_active; + int32_t fs_old_cpc; + int32_t fs_maxbsize; + int64_t fs_sparecon64[17]; + int64_t fs_sblockloc; + struct ufs2_csum_total { + uint64_t cs_ndir; + uint64_t cs_nbfree; + uint64_t cs_nifree; + uint64_t cs_nffree; + uint64_t cs_numclusters; + uint64_t cs_spare[3]; + } fs_cstotal; + struct ufs_timeval { + int32_t tv_sec; + int32_t tv_usec; + } fs_time; + int64_t fs_size; + int64_t fs_dsize; + uint64_t fs_csaddr; + int64_t fs_pendingblocks; + int32_t fs_pendinginodes; + } fs_u2; + } fs_u11; + union { + struct { + int32_t fs_sparecon[53]; + int32_t fs_reclaim; + int32_t fs_sparecon2[1]; + int32_t fs_state; + uint32_t fs_qbmask[2]; + uint32_t fs_qfmask[2]; + } fs_sun; + struct { + int32_t fs_sparecon[53]; + int32_t fs_reclaim; + int32_t fs_sparecon2[1]; + uint32_t fs_npsect; + uint32_t fs_qbmask[2]; + uint32_t fs_qfmask[2]; + } fs_sunx86; + struct { + int32_t fs_sparecon[50]; + int32_t fs_contigsumsize; + int32_t fs_maxsymlinklen; + int32_t fs_inodefmt; + uint32_t fs_maxfilesize[2]; + uint32_t fs_qbmask[2]; + uint32_t fs_qfmask[2]; + int32_t fs_state; + } fs_44; + } fs_u2; + int32_t fs_postblformat; + int32_t fs_nrpos; + int32_t fs_postbloff; + int32_t fs_rotbloff; + uint32_t fs_magic; + uint8_t fs_space[1]; +}; + +#define UFS_MAGIC 0x00011954 +#define UFS2_MAGIC 0x19540119 +#define UFS_MAGIC_FEA 0x00195612 +#define UFS_MAGIC_LFN 0x00095014 + +static int probe_ufs(blkid_probe pr, const struct blkid_idmag *mag) +{ + int offsets[] = { 0, 8, 64, 256 }; + int mags[] = { UFS2_MAGIC, UFS_MAGIC, UFS_MAGIC_FEA, UFS_MAGIC_LFN }; + int i; + uint32_t magic; + struct ufs_super_block *ufs; + + for (i = 0; i < ARRAY_SIZE(offsets); i++) { + uint32_t magLE, magBE; + int y; + + ufs = (struct ufs_super_block *) + blkid_probe_get_buffer(pr, + offsets[i] * 1024, + sizeof(struct ufs_super_block)); + if (!ufs) + return -1; + + magBE = be32_to_cpu(ufs->fs_magic); + magLE = le32_to_cpu(ufs->fs_magic); + + for (y = 0; y < ARRAY_SIZE(mags); y++) { + if (magLE == mags[y] || magBE == mags[y]) { + magic = mags[y]; + goto found; + } + } + } + + return 1; + +found: + if (magic == UFS2_MAGIC) { + blkid_probe_set_version(pr, "2"); + blkid_probe_set_label(pr, ufs->fs_u11.fs_u2.fs_volname, + sizeof(ufs->fs_u11.fs_u2.fs_volname)); + } else + blkid_probe_set_version(pr, "1"); + + return 0; +} + +/* + * According to libvolume_id the UFS superblock could be on four positions. + * The original libblkid has checked one position (.kboff=8) only. + * + * We know four UFS magic strings and UFS could be both little-endian and + * big-endian. ... so we have: + * + * 4 position * 4 string * 2 version = 32 magic strings + * + * It seems simpler to check for these string in probing function that hardcode + * all in the .magic array. + */ +const struct blkid_idinfo ufs_idinfo = +{ + .name = "ufs", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_ufs, + .magics = BLKID_NONE_MAGIC +}; + diff --git a/shlibs/blkid/src/probers/vfat.c b/shlibs/blkid/src/probers/vfat.c new file mode 100644 index 000000000..a83175c0b --- /dev/null +++ b/shlibs/blkid/src/probers/vfat.c @@ -0,0 +1,364 @@ +/* + * Copyright (C) 1999 by Andries Brouwer + * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o + * Copyright (C) 2001 by Andreas Dilger + * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <stdint.h> + +#include "blkidP.h" + +/* Yucky misaligned values */ +struct vfat_super_block { +/* 00*/ unsigned char vs_ignored[3]; +/* 03*/ unsigned char vs_sysid[8]; +/* 0b*/ unsigned char vs_sector_size[2]; +/* 0d*/ uint8_t vs_cluster_size; +/* 0e*/ uint16_t vs_reserved; +/* 10*/ uint8_t vs_fats; +/* 11*/ unsigned char vs_dir_entries[2]; +/* 13*/ unsigned char vs_sectors[2]; +/* 15*/ unsigned char vs_media; +/* 16*/ uint16_t vs_fat_length; +/* 18*/ uint16_t vs_secs_track; +/* 1a*/ uint16_t vs_heads; +/* 1c*/ uint32_t vs_hidden; +/* 20*/ uint32_t vs_total_sect; +/* 24*/ uint32_t vs_fat32_length; +/* 28*/ uint16_t vs_flags; +/* 2a*/ uint8_t vs_version[2]; +/* 2c*/ uint32_t vs_root_cluster; +/* 30*/ uint16_t vs_fsinfo_sector; +/* 32*/ uint16_t vs_backup_boot; +/* 34*/ uint16_t vs_reserved2[6]; +/* 40*/ unsigned char vs_unknown[3]; +/* 43*/ unsigned char vs_serno[4]; +/* 47*/ unsigned char vs_label[11]; +/* 52*/ unsigned char vs_magic[8]; +/* 5a*/ unsigned char vs_dummy2[164]; +/*1fe*/ unsigned char vs_pmagic[2]; +}; + +/* Yucky misaligned values */ +struct msdos_super_block { +/* 00*/ unsigned char ms_ignored[3]; +/* 03*/ unsigned char ms_sysid[8]; +/* 0b*/ unsigned char ms_sector_size[2]; +/* 0d*/ uint8_t ms_cluster_size; +/* 0e*/ uint16_t ms_reserved; +/* 10*/ uint8_t ms_fats; +/* 11*/ unsigned char ms_dir_entries[2]; +/* 13*/ unsigned char ms_sectors[2]; +/* 15*/ unsigned char ms_media; +/* 16*/ uint16_t ms_fat_length; +/* 18*/ uint16_t ms_secs_track; +/* 1a*/ uint16_t ms_heads; +/* 1c*/ uint32_t ms_hidden; +/* 20*/ uint32_t ms_total_sect; +/* 24*/ unsigned char ms_unknown[3]; +/* 27*/ unsigned char ms_serno[4]; +/* 2b*/ unsigned char ms_label[11]; +/* 36*/ unsigned char ms_magic[8]; +/* 3d*/ unsigned char ms_dummy2[192]; +/*1fe*/ unsigned char ms_pmagic[2]; +}; + +struct vfat_dir_entry { + uint8_t name[11]; + uint8_t attr; + uint16_t time_creat; + uint16_t date_creat; + uint16_t time_acc; + uint16_t date_acc; + uint16_t cluster_high; + uint16_t time_write; + uint16_t date_write; + uint16_t cluster_low; + uint32_t size; +}; + +struct fat32_fsinfo { + uint8_t signature1[4]; + uint32_t reserved1[120]; + uint8_t signature2[4]; + uint32_t free_clusters; + uint32_t next_cluster; + uint32_t reserved2[4]; +}; + +/* maximum number of clusters */ +#define FAT12_MAX 0xFF4 +#define FAT16_MAX 0xFFF4 +#define FAT32_MAX 0x0FFFFFF6 + +#define FAT_ATTR_VOLUME_ID 0x08 +#define FAT_ATTR_DIR 0x10 +#define FAT_ATTR_LONG_NAME 0x0f +#define FAT_ATTR_MASK 0x3f +#define FAT_ENTRY_FREE 0xe5 + +static const char *no_name = "NO NAME "; + +static unsigned char *search_fat_label(struct vfat_dir_entry *dir, int count) +{ + int i; + + for (i = 0; i < count; i++) { + if (dir[i].name[0] == 0x00) + break; + + if ((dir[i].name[0] == FAT_ENTRY_FREE) || + (dir[i].cluster_high != 0 || dir[i].cluster_low != 0) || + ((dir[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME)) + continue; + + if ((dir[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == + FAT_ATTR_VOLUME_ID) { + return dir[i].name; + } + } + return 0; +} + +/* + * The FAT filesystem could be without a magic string in superblock + * (e.g. old floppies). This heuristic for FAT detection is inspired + * by libvolume_id and the Linux kernel. + */ +static int probe_fat_nomagic(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct msdos_super_block *ms; + + ms = blkid_probe_get_sb(pr, mag, struct msdos_super_block); + if (!ms) + return -1; + + /* heads check */ + if (ms->ms_heads == 0) + return 1; + + /* cluster size check*/ + if (ms->ms_cluster_size == 0 || + (ms->ms_cluster_size & (ms->ms_cluster_size-1))) + return 1; + + /* media check */ + if (ms->ms_media < 0xf8 && ms->ms_media != 0xf0) + return 1; + + /* fat counts(Linux kernel expects at least 1 FAT table) */ + if (!ms->ms_fats) + return 1; + + /* + * OS/2 and apparently DFSee will place a FAT12/16-like + * pseudo-superblock in the first 512 bytes of non-FAT + * filesystems --- at least JFS and HPFS, and possibly others. + * So we explicitly check for those filesystems at the + * FAT12/16 filesystem magic field identifier, and if they are + * present, we rule this out as a FAT filesystem, despite the + * FAT-like pseudo-header. + */ + if ((memcmp(ms->ms_magic, "JFS ", 8) == 0) || + (memcmp(ms->ms_magic, "HPFS ", 8) == 0)) + return 1; + + return 0; +} + +/* FAT label extraction from the root directory taken from Kay + * Sievers's volume_id library */ +static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct vfat_super_block *vs; + struct msdos_super_block *ms; + struct vfat_dir_entry *dir; + const unsigned char *vol_label = 0, *tmp; + unsigned char *vol_serno; + int maxloop = 100; + uint16_t sector_size, dir_entries, reserved; + uint32_t sect_count, fat_size, dir_size, cluster_count, fat_length; + uint32_t buf_size, start_data_sect, next, root_start, root_dir_entries; + const char *version = NULL; + + + /* non-standard magic strings */ + if (mag->len <= 2 && probe_fat_nomagic(pr, mag) != 0) + return 1; + + vs = blkid_probe_get_sb(pr, mag, struct vfat_super_block); + if (!vs) + return -1; + + ms = blkid_probe_get_sb(pr, mag, struct msdos_super_block); + if (!ms) + return -1; + + /* sector size check */ + tmp = (unsigned char *) &ms->ms_sector_size; + sector_size = tmp[0] + (tmp[1] << 8); + if (sector_size != 0x200 && sector_size != 0x400 && + sector_size != 0x800 && sector_size != 0x1000) + return 1; + + tmp = (unsigned char *) &ms->ms_dir_entries; + dir_entries = tmp[0] + (tmp[1] << 8); + reserved = le16_to_cpu(ms->ms_reserved); + tmp = (unsigned char *) &ms->ms_sectors; + sect_count = tmp[0] + (tmp[1] << 8); + if (sect_count == 0) + sect_count = le32_to_cpu(ms->ms_total_sect); + + fat_length = le16_to_cpu(ms->ms_fat_length); + if (fat_length == 0) + fat_length = le32_to_cpu(vs->vs_fat32_length); + + fat_size = fat_length * ms->ms_fats; + dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) + + (sector_size-1)) / sector_size; + + cluster_count = sect_count - (reserved + fat_size + dir_size); + if (ms->ms_cluster_size == 0) + return 1; + cluster_count /= ms->ms_cluster_size; + + if (cluster_count > FAT32_MAX) + return 1; + + if (ms->ms_fat_length) { + /* the label may be an attribute in the root directory */ + root_start = (reserved + fat_size) * sector_size; + root_dir_entries = vs->vs_dir_entries[0] + + (vs->vs_dir_entries[1] << 8); + + buf_size = root_dir_entries * sizeof(struct vfat_dir_entry); + dir = (struct vfat_dir_entry *) + blkid_probe_get_buffer(pr, root_start, buf_size); + if (dir) + vol_label = search_fat_label(dir, root_dir_entries); + + if (!vol_label || !memcmp(vol_label, no_name, 11)) + vol_label = ms->ms_label; + vol_serno = ms->ms_serno; + + blkid_probe_set_value(pr, "SEC_TYPE", (unsigned char *) "msdos", + sizeof("msdos")); + + if (cluster_count < FAT12_MAX) + version = "FAT12"; + else if (cluster_count < FAT16_MAX) + version = "FAT16"; + } else { + unsigned char *buf; + uint16_t fsinfo_sect; + + /* Search the FAT32 root dir for the label attribute */ + buf_size = vs->vs_cluster_size * sector_size; + start_data_sect = reserved + fat_size; + + version = "FAT32"; + + next = le32_to_cpu(vs->vs_root_cluster); + while (next && --maxloop) { + uint32_t next_sect_off; + uint64_t next_off, fat_entry_off; + int count; + + next_sect_off = (next - 2) * vs->vs_cluster_size; + next_off = (start_data_sect + next_sect_off) * + sector_size; + + dir = (struct vfat_dir_entry *) + blkid_probe_get_buffer(pr, next_off, buf_size); + if (dir == NULL) + break; + + count = buf_size / sizeof(struct vfat_dir_entry); + + vol_label = search_fat_label(dir, count); + if (vol_label) + break; + + /* get FAT entry */ + fat_entry_off = (reserved * sector_size) + + (next * sizeof(uint32_t)); + buf = blkid_probe_get_buffer(pr, fat_entry_off, buf_size); + if (buf == NULL) + break; + + /* set next cluster */ + next = le32_to_cpu(*((uint32_t *) buf) & 0x0fffffff); + } + + if (!vol_label || !memcmp(vol_label, no_name, 11)) + vol_label = vs->vs_label; + vol_serno = vs->vs_serno; + + /* + * FAT32 should have a valid signature in the fsinfo block, + * but also allow all bytes set to '\0', because some volumes + * do not set the signature at all. + */ + fsinfo_sect = le16_to_cpu(vs->vs_fsinfo_sector); + if (fsinfo_sect) { + struct fat32_fsinfo *fsinfo; + + buf = blkid_probe_get_buffer(pr, + fsinfo_sect * sector_size, + sizeof(struct fat32_fsinfo)); + if (buf == NULL) + return -1; + + fsinfo = (struct fat32_fsinfo *) buf; + if (memcmp(fsinfo->signature1, "\x52\x52\x61\x41", 4) != 0 && + memcmp(fsinfo->signature1, "\x00\x00\x00\x00", 4) != 0) + return -1; + if (memcmp(fsinfo->signature2, "\x72\x72\x41\x61", 4) != 0 && + memcmp(fsinfo->signature2, "\x00\x00\x00\x00", 4) != 0) + return -1; + } + } + + if (vol_label && memcmp(vol_label, no_name, 11)) + blkid_probe_set_label(pr, (unsigned char *) vol_label, 11); + + /* We can't just print them as %04X, because they are unaligned */ + blkid_probe_sprintf_uuid(pr, vol_serno, 4, "%02X%02X-%02X%02X", + vol_serno[3], vol_serno[2], vol_serno[1], vol_serno[0]); + + if (version) + blkid_probe_set_version(pr, version); + + return 0; +} + + +const struct blkid_idinfo vfat_idinfo = +{ + .name = "vfat", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_vfat, + .magics = + { + { .magic = "MSWIN", .len = 5, .sboff = 0x52 }, + { .magic = "FAT32 ", .len = 8, .sboff = 0x52 }, + { .magic = "MSDOS", .len = 5, .sboff = 0x36 }, + { .magic = "FAT16 ", .len = 8, .sboff = 0x36 }, + { .magic = "FAT12 ", .len = 8, .sboff = 0x36 }, + { .magic = "\353", .len = 1, }, + { .magic = "\351", .len = 1, }, + { .magic = "\125\252", .len = 2, .sboff = 0x1fe }, + { NULL } + } +}; + diff --git a/shlibs/blkid/src/probers/via_raid.c b/shlibs/blkid/src/probers/via_raid.c new file mode 100644 index 000000000..22022fdd5 --- /dev/null +++ b/shlibs/blkid/src/probers/via_raid.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * Inspired by libvolume_id by + * Kay Sievers <kay.sievers@vrfy.org> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <stdint.h> + +#include "blkidP.h" + +struct via_metadata { + uint16_t signature; + uint8_t version_number; + struct via_array { + uint16_t disk_bit_mask; + uint8_t disk_array_ex; + uint32_t capacity_low; + uint32_t capacity_high; + uint32_t serial_checksum; + } array; + uint32_t serial_checksum[8]; + uint8_t checksum; +}; + +#define VIA_SIGNATURE 0xAA55 + +/* 8 bit checksum on first 50 bytes of metadata. */ +static uint8_t via_checksum(struct via_metadata *v) +{ + uint8_t i = 50, cs = 0; + + while (i--) + cs += ((uint8_t*) v)[i]; + + return cs == v->checksum; +} + +static int probe_viaraid(blkid_probe pr, const struct blkid_idmag *mag) +{ + uint64_t off; + struct via_metadata *v; + + if (pr->size < 0x10000) + return -1; + + off = ((pr->size / 0x200)-1) * 0x200; + + v = (struct via_metadata *) + blkid_probe_get_buffer(pr, + off, + sizeof(struct via_metadata)); + if (!v) + return -1; + if (le16_to_cpu(v->signature) != VIA_SIGNATURE) + return -1; + if (v->version_number > 2) + return -1; + if (!via_checksum(v)) + return -1; + if (blkid_probe_sprintf_version(pr, "%u", v->version_number) != 0) + return -1; + return 0; +} + +const struct blkid_idinfo viaraid_idinfo = { + .name = "via_raid_member", + .usage = BLKID_USAGE_RAID, + .probefunc = probe_viaraid, + .magics = BLKID_NONE_MAGIC +}; + + diff --git a/shlibs/blkid/src/probers/vxfs.c b/shlibs/blkid/src/probers/vxfs.c new file mode 100644 index 000000000..7a27b6c9e --- /dev/null +++ b/shlibs/blkid/src/probers/vxfs.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ + +#include <stdio.h> + +#include "blkidP.h" + +struct vxfs_super_block { + uint32_t vs_magic; + int32_t vs_version; +}; + +static int probe_vxfs(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct vxfs_super_block *vxs; + + vxs = blkid_probe_get_sb(pr, mag, struct vxfs_super_block); + if (!vxs) + return -1; + + blkid_probe_sprintf_version(pr, "%u", (unsigned int) vxs->vs_version); + return 0; +} + + +const struct blkid_idinfo vxfs_idinfo = +{ + .name = "vxfs", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_vxfs, + .magics = + { + { .magic = "\365\374\001\245", .len = 4, .kboff = 1 }, + { NULL } + } +}; + diff --git a/shlibs/blkid/src/probers/xfs.c b/shlibs/blkid/src/probers/xfs.c new file mode 100644 index 000000000..fa7914e29 --- /dev/null +++ b/shlibs/blkid/src/probers/xfs.c @@ -0,0 +1,63 @@ +/* + * Copyright (C) 1999 by Andries Brouwer + * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o + * Copyright (C) 2001 by Andreas Dilger + * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <stdint.h> + +#include "blkidP.h" + +struct xfs_super_block { + unsigned char xs_magic[4]; + uint32_t xs_blocksize; + uint64_t xs_dblocks; + uint64_t xs_rblocks; + uint32_t xs_dummy1[2]; + unsigned char xs_uuid[16]; + uint32_t xs_dummy2[15]; + char xs_fname[12]; + uint32_t xs_dummy3[2]; + uint64_t xs_icount; + uint64_t xs_ifree; + uint64_t xs_fdblocks; +}; + +static int probe_xfs(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct xfs_super_block *xs; + + xs = blkid_probe_get_sb(pr, mag, struct xfs_super_block); + if (!xs) + return -1; + + if (strlen(xs->xs_fname)) + blkid_probe_set_label(pr, (unsigned char *) xs->xs_fname, + sizeof(xs->xs_fname)); + blkid_probe_set_uuid(pr, xs->xs_uuid); + return 0; +} + +const struct blkid_idinfo xfs_idinfo = +{ + .name = "xfs", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_xfs, + .magics = + { + { .magic = "XFSB", .len = 4 }, + { NULL } + } +}; + diff --git a/shlibs/blkid/src/probers/zfs.c b/shlibs/blkid/src/probers/zfs.c new file mode 100644 index 000000000..7d39034f6 --- /dev/null +++ b/shlibs/blkid/src/probers/zfs.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2009 by Andreas Dilger <adilger@sun.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <inttypes.h> + +#include "blkidP.h" + +/* #include <sys/uberblock_impl.h> */ +#define UBERBLOCK_MAGIC 0x00bab10c /* oo-ba-bloc! */ +struct zfs_uberblock { + uint64_t ub_magic; /* UBERBLOCK_MAGIC */ + uint64_t ub_version; /* SPA_VERSION */ + uint64_t ub_txg; /* txg of last sync */ + uint64_t ub_guid_sum; /* sum of all vdev guids */ + uint64_t ub_timestamp; /* UTC time of last sync */ + /*blkptr_t ub_rootbp;*/ /* MOS objset_phys_t */ +}; + +static int probe_zfs(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct zfs_uberblock *ub; + int swab_endian; + uint64_t spa_version; + + ub = blkid_probe_get_sb(pr, mag, struct zfs_uberblock); + if (!ub) + return -1; + + swab_endian = (ub->ub_magic == swab64(UBERBLOCK_MAGIC)); + spa_version = swab_endian ? swab64(ub->ub_version) : ub->ub_version; + + blkid_probe_sprintf_version(pr, "%" PRIu64, spa_version); +#if 0 + /* read nvpair data for pool name, pool GUID from the MOS, but + * unfortunately this is more complex than it could be */ + blkid_probe_set_label(pr, pool_name, pool_len)); + blkid_probe_set_uuid(pr, pool_guid); +#endif + return 0; +} + +const struct blkid_idinfo zfs_idinfo = +{ + .name = "zfs", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_zfs, + .magics = + { + { .magic = "\0\0\x02\xf5\xb0\x07\xb1\x0c", .len = 8, .kboff = 8 }, + { .magic = "\x1c\xb1\x07\xb0\xf5\x02\0\0", .len = 8, .kboff = 8 }, + { .magic = "\0\0\x02\xf5\xb0\x07\xb1\x0c", .len = 8, .kboff = 264 }, + { .magic = "\x0c\xb1\x07\xb0\xf5\x02\0\0", .len = 8, .kboff = 264 }, + { NULL } + } +}; + diff --git a/shlibs/blkid/src/read.c b/shlibs/blkid/src/read.c new file mode 100644 index 000000000..b5e9cd024 --- /dev/null +++ b/shlibs/blkid/src/read.c @@ -0,0 +1,492 @@ +/* + * read.c - read the blkid cache from disk, to avoid scanning all devices + * + * Copyright (C) 2001, 2003 Theodore Y. Ts'o + * Copyright (C) 2001 Andreas Dilger + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#define _XOPEN_SOURCE 600 /* for inclusion of strtoull */ + +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#if HAVE_ERRNO_H +#include <errno.h> +#endif + +#include "blkidP.h" + +#ifdef HAVE_STRTOULL +#define STRTOULL strtoull /* defined in stdlib.h if you try hard enough */ +#else +/* FIXME: need to support real strtoull here */ +#define STRTOULL strtoul +#endif + +#if HAVE_STDLIB_H +#include <stdlib.h> +#endif + +#ifdef TEST_PROGRAM +#define blkid_debug_dump_dev(dev) (debug_dump_dev(dev)) +static void debug_dump_dev(blkid_dev dev); +#endif + +/* + * File format: + * + * <device [<NAME="value"> ...]>device_name</device> + * + * The following tags are required for each entry: + * <ID="id"> unique (within this file) ID number of this device + * <TIME="time"> (ascii time_t) time this entry was last read from disk + * <TYPE="type"> (detected) type of filesystem/data for this partition + * + * The following tags may be present, depending on the device contents + * <LABEL="label"> (user supplied) label (volume name, etc) + * <UUID="uuid"> (generated) universally unique identifier (serial no) + */ + +static char *skip_over_blank(char *cp) +{ + while (*cp && isspace(*cp)) + cp++; + return cp; +} + +static char *skip_over_word(char *cp) +{ + char ch; + + while ((ch = *cp)) { + /* If we see a backslash, skip the next character */ + if (ch == '\\') { + cp++; + if (*cp == '\0') + break; + cp++; + continue; + } + if (isspace(ch) || ch == '<' || ch == '>') + break; + cp++; + } + return cp; +} + +static char *strip_line(char *line) +{ + char *p; + + line = skip_over_blank(line); + + p = line + strlen(line) - 1; + + while (*line) { + if (isspace(*p)) + *p-- = '\0'; + else + break; + } + + return line; +} + +#if 0 +static char *parse_word(char **buf) +{ + char *word, *next; + + word = *buf; + if (*word == '\0') + return NULL; + + word = skip_over_blank(word); + next = skip_over_word(word); + if (*next) { + char *end = next - 1; + if (*end == '"' || *end == '\'') + *end = '\0'; + *next++ = '\0'; + } + *buf = next; + + if (*word == '"' || *word == '\'') + word++; + return word; +} +#endif + +/* + * Start parsing a new line from the cache. + * + * line starts with "<device" return 1 -> continue parsing line + * line starts with "<foo", empty, or # return 0 -> skip line + * line starts with other, return -BLKID_ERR_CACHE -> error + */ +static int parse_start(char **cp) +{ + char *p; + + p = strip_line(*cp); + + /* Skip comment or blank lines. We can't just NUL the first '#' char, + * in case it is inside quotes, or escaped. + */ + if (*p == '\0' || *p == '#') + return 0; + + if (!strncmp(p, "<device", 7)) { + DBG(DEBUG_READ, printf("found device header: %8s\n", p)); + p += 7; + + *cp = p; + return 1; + } + + if (*p == '<') + return 0; + + return -BLKID_ERR_CACHE; +} + +/* Consume the remaining XML on the line (cosmetic only) */ +static int parse_end(char **cp) +{ + *cp = skip_over_blank(*cp); + + if (!strncmp(*cp, "</device>", 9)) { + DBG(DEBUG_READ, printf("found device trailer %9s\n", *cp)); + *cp += 9; + return 0; + } + + return -BLKID_ERR_CACHE; +} + +/* + * Allocate a new device struct with device name filled in. Will handle + * finding the device on lines of the form: + * <device foo=bar>devname</device> + * <device>devname<foo>bar</foo></device> + */ +static int parse_dev(blkid_cache cache, blkid_dev *dev, char **cp) +{ + char *start, *tmp, *end, *name; + int ret; + + if ((ret = parse_start(cp)) <= 0) + return ret; + + start = tmp = strchr(*cp, '>'); + if (!start) { + DBG(DEBUG_READ, + printf("blkid: short line parsing dev: %s\n", *cp)); + return -BLKID_ERR_CACHE; + } + start = skip_over_blank(start + 1); + end = skip_over_word(start); + + DBG(DEBUG_READ, printf("device should be %*s\n", + (int)(end - start), start)); + + if (**cp == '>') + *cp = end; + else + (*cp)++; + + *tmp = '\0'; + + if (!(tmp = strrchr(end, '<')) || parse_end(&tmp) < 0) { + DBG(DEBUG_READ, + printf("blkid: missing </device> ending: %s\n", end)); + } else if (tmp) + *tmp = '\0'; + + if (end - start <= 1) { + DBG(DEBUG_READ, printf("blkid: empty device name: %s\n", *cp)); + return -BLKID_ERR_CACHE; + } + + name = blkid_strndup(start, end-start); + if (name == NULL) + return -BLKID_ERR_MEM; + + DBG(DEBUG_READ, printf("found dev %s\n", name)); + + if (!(*dev = blkid_get_dev(cache, name, BLKID_DEV_CREATE))) { + free(name); + return -BLKID_ERR_MEM; + } + + free(name); + return 1; +} + +/* + * Extract a tag of the form NAME="value" from the line. + */ +static int parse_token(char **name, char **value, char **cp) +{ + char *end; + + if (!name || !value || !cp) + return -BLKID_ERR_PARAM; + + if (!(*value = strchr(*cp, '='))) + return 0; + + **value = '\0'; + *name = strip_line(*cp); + *value = skip_over_blank(*value + 1); + + if (**value == '"') { + end = strchr(*value + 1, '"'); + if (!end) { + DBG(DEBUG_READ, + printf("unbalanced quotes at: %s\n", *value)); + *cp = *value; + return -BLKID_ERR_CACHE; + } + (*value)++; + *end = '\0'; + end++; + } else { + end = skip_over_word(*value); + if (*end) { + *end = '\0'; + end++; + } + } + *cp = end; + + return 1; +} + +/* + * Extract a tag of the form <NAME>value</NAME> from the line. + */ +/* +static int parse_xml(char **name, char **value, char **cp) +{ + char *end; + + if (!name || !value || !cp) + return -BLKID_ERR_PARAM; + + *name = strip_line(*cp); + + if ((*name)[0] != '<' || (*name)[1] == '/') + return 0; + + FIXME: finish this. +} +*/ + +/* + * Extract a tag from the line. + * + * Return 1 if a valid tag was found. + * Return 0 if no tag found. + * Return -ve error code. + */ +static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp) +{ + char *name; + char *value; + int ret; + + if (!cache || !dev) + return -BLKID_ERR_PARAM; + + if ((ret = parse_token(&name, &value, cp)) <= 0 /* && + (ret = parse_xml(&name, &value, cp)) <= 0 */) + return ret; + + /* Some tags are stored directly in the device struct */ + if (!strcmp(name, "DEVNO")) + dev->bid_devno = STRTOULL(value, 0, 0); + else if (!strcmp(name, "PRI")) + dev->bid_pri = strtol(value, 0, 0); + else if (!strcmp(name, "TIME")) + dev->bid_time = STRTOULL(value, 0, 0); + else + ret = blkid_set_tag(dev, name, value, strlen(value)); + + DBG(DEBUG_READ, printf(" tag: %s=\"%s\"\n", name, value)); + + return ret < 0 ? ret : 1; +} + +/* + * Parse a single line of data, and return a newly allocated dev struct. + * Add the new device to the cache struct, if one was read. + * + * Lines are of the form <device [TAG="value" ...]>/dev/foo</device> + * + * Returns -ve value on error. + * Returns 0 otherwise. + * If a valid device was read, *dev_p is non-NULL, otherwise it is NULL + * (e.g. comment lines, unknown XML content, etc). + */ +static int blkid_parse_line(blkid_cache cache, blkid_dev *dev_p, char *cp) +{ + blkid_dev dev; + int ret; + + if (!cache || !dev_p) + return -BLKID_ERR_PARAM; + + *dev_p = NULL; + + DBG(DEBUG_READ, printf("line: %s\n", cp)); + + if ((ret = parse_dev(cache, dev_p, &cp)) <= 0) + return ret; + + dev = *dev_p; + + while ((ret = parse_tag(cache, dev, &cp)) > 0) { + ; + } + + if (dev->bid_type == NULL) { + DBG(DEBUG_READ, + printf("blkid: device %s has no TYPE\n",dev->bid_name)); + blkid_free_dev(dev); + } + + DBG(DEBUG_READ, blkid_debug_dump_dev(dev)); + + return ret; +} + +/* + * Parse the specified filename, and return the data in the supplied or + * a newly allocated cache struct. If the file doesn't exist, return a + * new empty cache struct. + */ +void blkid_read_cache(blkid_cache cache) +{ + FILE *file; + char buf[4096]; + int fd, lineno = 0; + struct stat st; + + if (!cache) + return; + + /* + * If the file doesn't exist, then we just return an empty + * struct so that the cache can be populated. + */ + if ((fd = open(cache->bic_filename, O_RDONLY)) < 0) + return; + if (fstat(fd, &st) < 0) + goto errout; + if ((st.st_mtime == cache->bic_ftime) || + (cache->bic_flags & BLKID_BIC_FL_CHANGED)) { + DBG(DEBUG_CACHE, printf("skipping re-read of %s\n", + cache->bic_filename)); + goto errout; + } + + DBG(DEBUG_CACHE, printf("reading cache file %s\n", + cache->bic_filename)); + + file = fdopen(fd, "r"); + if (!file) + goto errout; + + while (fgets(buf, sizeof(buf), file)) { + blkid_dev dev; + unsigned int end; + + lineno++; + if (buf[0] == 0) + continue; + end = strlen(buf) - 1; + /* Continue reading next line if it ends with a backslash */ + while (buf[end] == '\\' && end < sizeof(buf) - 2 && + fgets(buf + end, sizeof(buf) - end, file)) { + end = strlen(buf) - 1; + lineno++; + } + + if (blkid_parse_line(cache, &dev, buf) < 0) { + DBG(DEBUG_READ, + printf("blkid: bad format on line %d\n", lineno)); + continue; + } + } + fclose(file); + + /* + * Initially we do not need to write out the cache file. + */ + cache->bic_flags &= ~BLKID_BIC_FL_CHANGED; + cache->bic_ftime = st.st_mtime; + + return; +errout: + close(fd); + return; +} + +#ifdef TEST_PROGRAM +static void debug_dump_dev(blkid_dev dev) +{ + struct list_head *p; + + if (!dev) { + printf(" dev: NULL\n"); + return; + } + + printf(" dev: name = %s\n", dev->bid_name); + printf(" dev: DEVNO=\"0x%0llx\"\n", (long long)dev->bid_devno); + printf(" dev: TIME=\"%lld\"\n", (long long)dev->bid_time); + printf(" dev: PRI=\"%d\"\n", dev->bid_pri); + printf(" dev: flags = 0x%08X\n", dev->bid_flags); + + list_for_each(p, &dev->bid_tags) { + blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags); + if (tag) + printf(" tag: %s=\"%s\"\n", tag->bit_name, + tag->bit_val); + else + printf(" tag: NULL\n"); + } + printf("\n"); +} + +int main(int argc, char**argv) +{ + blkid_cache cache = NULL; + int ret; + + blkid_init_debug(DEBUG_ALL); + if (argc > 2) { + fprintf(stderr, "Usage: %s [filename]\n" + "Test parsing of the cache (filename)\n", argv[0]); + exit(1); + } + if ((ret = blkid_get_cache(&cache, argv[1])) < 0) + fprintf(stderr, "error %d reading cache file %s\n", ret, + argv[1] ? argv[1] : BLKID_CACHE_FILE); + + blkid_put_cache(cache); + + return ret; +} +#endif diff --git a/shlibs/blkid/src/resolve.c b/shlibs/blkid/src/resolve.c new file mode 100644 index 000000000..bf13b8648 --- /dev/null +++ b/shlibs/blkid/src/resolve.c @@ -0,0 +1,139 @@ +/* + * resolve.c - resolve names and tags into specific devices + * + * Copyright (C) 2001, 2003 Theodore Ts'o. + * Copyright (C) 2001 Andreas Dilger + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#include <stdio.h> +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <stdlib.h> +#include <fcntl.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "blkidP.h" + +/* + * Find a tagname (e.g. LABEL or UUID) on a specific device. + */ +char *blkid_get_tag_value(blkid_cache cache, const char *tagname, + const char *devname) +{ + blkid_tag found; + blkid_dev dev; + blkid_cache c = cache; + char *ret = NULL; + + DBG(DEBUG_RESOLVE, printf("looking for %s on %s\n", tagname, devname)); + + if (!devname) + return NULL; + + if (!cache) { + if (blkid_get_cache(&c, NULL) < 0) + return NULL; + } + + if ((dev = blkid_get_dev(c, devname, BLKID_DEV_NORMAL)) && + (found = blkid_find_tag_dev(dev, tagname))) + ret = blkid_strdup(found->bit_val); + + if (!cache) + blkid_put_cache(c); + + return ret; +} + +/* + * Locate a device name from a token (NAME=value string), or (name, value) + * pair. In the case of a token, value is ignored. If the "token" is not + * of the form "NAME=value" and there is no value given, then it is assumed + * to be the actual devname and a copy is returned. + */ +char *blkid_get_devname(blkid_cache cache, const char *token, + const char *value) +{ + blkid_dev dev; + blkid_cache c = cache; + char *t = 0, *v = 0; + char *ret = NULL; + + if (!token) + return NULL; + + if (!cache) { + if (blkid_get_cache(&c, NULL) < 0) + return NULL; + } + + DBG(DEBUG_RESOLVE, + printf("looking for %s%s%s %s\n", token, value ? "=" : "", + value ? value : "", cache ? "in cache" : "from disk")); + + if (!value) { + if (!strchr(token, '=')) { + ret = blkid_strdup(token); + goto out; + } + blkid_parse_tag_string(token, &t, &v); + if (!t || !v) + goto out; + token = t; + value = v; + } + + dev = blkid_find_dev_with_tag(c, token, value); + if (!dev) + goto out; + + ret = blkid_strdup(blkid_dev_devname(dev)); + +out: + free(t); + free(v); + if (!cache) { + blkid_put_cache(c); + } + return (ret); +} + +#ifdef TEST_PROGRAM +int main(int argc, char **argv) +{ + char *value; + blkid_cache cache; + + blkid_init_debug(DEBUG_ALL); + if (argc != 2 && argc != 3) { + fprintf(stderr, "Usage:\t%s tagname=value\n" + "\t%s tagname devname\n" + "Find which device holds a given token or\n" + "Find what the value of a tag is in a device\n", + argv[0], argv[0]); + exit(1); + } + if (blkid_get_cache(&cache, "/dev/null") < 0) { + fprintf(stderr, "Couldn't get blkid cache\n"); + exit(1); + } + + if (argv[2]) { + value = blkid_get_tag_value(cache, argv[1], argv[2]); + printf("%s has tag %s=%s\n", argv[2], argv[1], + value ? value : "<missing>"); + } else { + value = blkid_get_devname(cache, argv[1], NULL); + printf("%s has tag %s\n", value ? value : "<none>", argv[1]); + } + blkid_put_cache(cache); + return value ? 0 : 1; +} +#endif diff --git a/shlibs/blkid/src/save.c b/shlibs/blkid/src/save.c new file mode 100644 index 000000000..bbe6f488e --- /dev/null +++ b/shlibs/blkid/src/save.c @@ -0,0 +1,193 @@ +/* + * save.c - write the cache struct to disk + * + * Copyright (C) 2001 by Andreas Dilger + * Copyright (C) 2003 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#ifdef HAVE_SYS_MKDEV_H +#include <sys/mkdev.h> +#endif +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include "blkidP.h" + +static int save_dev(blkid_dev dev, FILE *file) +{ + struct list_head *p; + + if (!dev || dev->bid_name[0] != '/') + return 0; + + DBG(DEBUG_SAVE, + printf("device %s, type %s\n", dev->bid_name, dev->bid_type ? + dev->bid_type : "(null)")); + + fprintf(file, + "<device DEVNO=\"0x%04lx\" TIME=\"%ld\"", + (unsigned long) dev->bid_devno, (long) dev->bid_time); + if (dev->bid_pri) + fprintf(file, " PRI=\"%d\"", dev->bid_pri); + list_for_each(p, &dev->bid_tags) { + blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags); + fprintf(file, " %s=\"%s\"", tag->bit_name,tag->bit_val); + } + fprintf(file, ">%s</device>\n", dev->bid_name); + + return 0; +} + +/* + * Write out the cache struct to the cache file on disk. + */ +int blkid_flush_cache(blkid_cache cache) +{ + struct list_head *p; + char *tmp = NULL; + const char *opened = NULL; + const char *filename; + FILE *file = NULL; + int fd, ret = 0; + struct stat st; + + if (!cache) + return -BLKID_ERR_PARAM; + + if (list_empty(&cache->bic_devs) || + !(cache->bic_flags & BLKID_BIC_FL_CHANGED)) { + DBG(DEBUG_SAVE, printf("skipping cache file write\n")); + return 0; + } + + filename = cache->bic_filename ? cache->bic_filename: BLKID_CACHE_FILE; + + /* If we can't write to the cache file, then don't even try */ + if (((ret = stat(filename, &st)) < 0 && errno != ENOENT) || + (ret == 0 && access(filename, W_OK) < 0)) { + DBG(DEBUG_SAVE, + printf("can't write to cache file %s\n", filename)); + return 0; + } + + /* + * Try and create a temporary file in the same directory so + * that in case of error we don't overwrite the cache file. + * If the cache file doesn't yet exist, it isn't a regular + * file (e.g. /dev/null or a socket), or we couldn't create + * a temporary file then we open it directly. + */ + if (ret == 0 && S_ISREG(st.st_mode)) { + tmp = malloc(strlen(filename) + 8); + if (tmp) { + sprintf(tmp, "%s-XXXXXX", filename); + fd = mkstemp(tmp); + if (fd >= 0) { + file = fdopen(fd, "w"); + opened = tmp; + } + fchmod(fd, 0644); + } + } + + if (!file) { + file = fopen(filename, "w"); + opened = filename; + } + + DBG(DEBUG_SAVE, + printf("writing cache file %s (really %s)\n", + filename, opened)); + + if (!file) { + ret = errno; + goto errout; + } + + list_for_each(p, &cache->bic_devs) { + blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs); + if (!dev->bid_type) + continue; + if ((ret = save_dev(dev, file)) < 0) + break; + } + + if (ret >= 0) { + cache->bic_flags &= ~BLKID_BIC_FL_CHANGED; + ret = 1; + } + + fclose(file); + if (opened != filename) { + if (ret < 0) { + unlink(opened); + DBG(DEBUG_SAVE, + printf("unlinked temp cache %s\n", opened)); + } else { + char *backup; + + backup = malloc(strlen(filename) + 5); + if (backup) { + sprintf(backup, "%s.old", filename); + unlink(backup); + link(filename, backup); + free(backup); + } + rename(opened, filename); + DBG(DEBUG_SAVE, + printf("moved temp cache %s\n", opened)); + } + } + +errout: + free(tmp); + return ret; +} + +#ifdef TEST_PROGRAM +int main(int argc, char **argv) +{ + blkid_cache cache = NULL; + int ret; + + blkid_init_debug(DEBUG_ALL); + if (argc > 2) { + fprintf(stderr, "Usage: %s [filename]\n" + "Test loading/saving a cache (filename)\n", argv[0]); + exit(1); + } + + if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { + fprintf(stderr, "%s: error creating cache (%d)\n", + argv[0], ret); + exit(1); + } + if ((ret = blkid_probe_all(cache)) < 0) { + fprintf(stderr, "error (%d) probing devices\n", ret); + exit(1); + } + cache->bic_filename = blkid_strdup(argv[1]); + + if ((ret = blkid_flush_cache(cache)) < 0) { + fprintf(stderr, "error (%d) saving cache\n", ret); + exit(1); + } + + blkid_put_cache(cache); + + return ret; +} +#endif diff --git a/shlibs/blkid/src/tag.c b/shlibs/blkid/src/tag.c new file mode 100644 index 000000000..0dbe1ff5a --- /dev/null +++ b/shlibs/blkid/src/tag.c @@ -0,0 +1,474 @@ +/* + * tag.c - allocation/initialization/free routines for tag structs + * + * Copyright (C) 2001 Andreas Dilger + * Copyright (C) 2003 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * %End-Header% + */ + +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include "blkidP.h" + +static blkid_tag blkid_new_tag(void) +{ + blkid_tag tag; + + if (!(tag = (blkid_tag) calloc(1, sizeof(struct blkid_struct_tag)))) + return NULL; + + INIT_LIST_HEAD(&tag->bit_tags); + INIT_LIST_HEAD(&tag->bit_names); + + return tag; +} + +#ifdef CONFIG_BLKID_DEBUG +void blkid_debug_dump_tag(blkid_tag tag) +{ + if (!tag) { + printf(" tag: NULL\n"); + return; + } + + printf(" tag: %s=\"%s\"\n", tag->bit_name, tag->bit_val); +} +#endif + +void blkid_free_tag(blkid_tag tag) +{ + if (!tag) + return; + + DBG(DEBUG_TAG, printf(" freeing tag %s=%s\n", tag->bit_name, + tag->bit_val ? tag->bit_val : "(NULL)")); + DBG(DEBUG_TAG, blkid_debug_dump_tag(tag)); + + list_del(&tag->bit_tags); /* list of tags for this device */ + list_del(&tag->bit_names); /* list of tags with this type */ + + free(tag->bit_name); + free(tag->bit_val); + + free(tag); +} + +/* + * Find the desired tag on a device. If value is NULL, then the + * first such tag is returned, otherwise return only exact tag if found. + */ +blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type) +{ + struct list_head *p; + + if (!dev || !type) + return NULL; + + list_for_each(p, &dev->bid_tags) { + blkid_tag tmp = list_entry(p, struct blkid_struct_tag, + bit_tags); + + if (!strcmp(tmp->bit_name, type)) + return tmp; + } + return NULL; +} + +extern int blkid_dev_has_tag(blkid_dev dev, const char *type, + const char *value) +{ + blkid_tag tag; + + if (!dev || !type) + return -1; + + tag = blkid_find_tag_dev(dev, type); + if (!value) + return (tag != NULL); + if (!tag || strcmp(tag->bit_val, value)) + return 0; + return 1; +} + +/* + * Find the desired tag type in the cache. + * We return the head tag for this tag type. + */ +static blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type) +{ + blkid_tag head = NULL, tmp; + struct list_head *p; + + if (!cache || !type) + return NULL; + + list_for_each(p, &cache->bic_tags) { + tmp = list_entry(p, struct blkid_struct_tag, bit_tags); + if (!strcmp(tmp->bit_name, type)) { + DBG(DEBUG_TAG, + printf(" found cache tag head %s\n", type)); + head = tmp; + break; + } + } + return head; +} + +/* + * Set a tag on an existing device. + * + * If value is NULL, then delete the tagsfrom the device. + */ +int blkid_set_tag(blkid_dev dev, const char *name, + const char *value, const int vlength) +{ + blkid_tag t = 0, head = 0; + char *val = 0; + char **dev_var = 0; + + if (!dev || !name) + return -BLKID_ERR_PARAM; + + if (!(val = blkid_strndup(value, vlength)) && value) + return -BLKID_ERR_MEM; + + /* + * Certain common tags are linked directly to the device struct + * We need to know what they are before we do anything else because + * the function name parameter might get freed later on. + */ + if (!strcmp(name, "TYPE")) + dev_var = &dev->bid_type; + else if (!strcmp(name, "LABEL")) + dev_var = &dev->bid_label; + else if (!strcmp(name, "UUID")) + dev_var = &dev->bid_uuid; + + t = blkid_find_tag_dev(dev, name); + if (!value) { + if (t) + blkid_free_tag(t); + } else if (t) { + if (!strcmp(t->bit_val, val)) { + /* Same thing, exit */ + free(val); + return 0; + } + free(t->bit_val); + t->bit_val = val; + } else { + /* Existing tag not present, add to device */ + if (!(t = blkid_new_tag())) + goto errout; + t->bit_name = blkid_strdup(name); + t->bit_val = val; + t->bit_dev = dev; + + list_add_tail(&t->bit_tags, &dev->bid_tags); + + if (dev->bid_cache) { + head = blkid_find_head_cache(dev->bid_cache, + t->bit_name); + if (!head) { + head = blkid_new_tag(); + if (!head) + goto errout; + + DBG(DEBUG_TAG, + printf(" creating new cache tag head %s\n", name)); + head->bit_name = blkid_strdup(name); + if (!head->bit_name) + goto errout; + list_add_tail(&head->bit_tags, + &dev->bid_cache->bic_tags); + } + list_add_tail(&t->bit_names, &head->bit_names); + } + } + + /* Link common tags directly to the device struct */ + if (dev_var) + *dev_var = val; + + if (dev->bid_cache) + dev->bid_cache->bic_flags |= BLKID_BIC_FL_CHANGED; + return 0; + +errout: + if (t) + blkid_free_tag(t); + else + free(val); + if (head) + blkid_free_tag(head); + return -BLKID_ERR_MEM; +} + + +/* + * Parse a "NAME=value" string. This is slightly different than + * parse_token, because that will end an unquoted value at a space, while + * this will assume that an unquoted value is the rest of the token (e.g. + * if we are passed an already quoted string from the command-line we don't + * have to both quote and escape quote so that the quotes make it to + * us). + * + * Returns 0 on success, and -1 on failure. + */ +int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val) +{ + char *name, *value, *cp; + + DBG(DEBUG_TAG, printf("trying to parse '%s' as a tag\n", token)); + + if (!token || !(cp = strchr(token, '='))) + return -1; + + name = blkid_strdup(token); + if (!name) + return -1; + value = name + (cp - token); + *value++ = '\0'; + if (*value == '"' || *value == '\'') { + char c = *value++; + if (!(cp = strrchr(value, c))) + goto errout; /* missing closing quote */ + *cp = '\0'; + } + value = blkid_strdup(value); + if (!value) + goto errout; + + *ret_type = name; + *ret_val = value; + + return 0; + +errout: + free(name); + return -1; +} + +/* + * Tag iteration routines for the public libblkid interface. + * + * These routines do not expose the list.h implementation, which are a + * contamination of the namespace, and which force us to reveal far, far + * too much of our internal implemenation. I'm not convinced I want + * to keep list.h in the long term, anyway. It's fine for kernel + * programming, but performance is not the #1 priority for this + * library, and I really don't like the tradeoff of type-safety for + * performance for this application. [tytso:20030125.2007EST] + */ + +/* + * This series of functions iterate over all tags in a device + */ +#define TAG_ITERATE_MAGIC 0x01a5284c + +struct blkid_struct_tag_iterate { + int magic; + blkid_dev dev; + struct list_head *p; +}; + +extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev) +{ + blkid_tag_iterate iter; + + iter = malloc(sizeof(struct blkid_struct_tag_iterate)); + if (iter) { + iter->magic = TAG_ITERATE_MAGIC; + iter->dev = dev; + iter->p = dev->bid_tags.next; + } + return (iter); +} + +/* + * Return 0 on success, -1 on error + */ +extern int blkid_tag_next(blkid_tag_iterate iter, + const char **type, const char **value) +{ + blkid_tag tag; + + *type = 0; + *value = 0; + if (!iter || iter->magic != TAG_ITERATE_MAGIC || + iter->p == &iter->dev->bid_tags) + return -1; + tag = list_entry(iter->p, struct blkid_struct_tag, bit_tags); + *type = tag->bit_name; + *value = tag->bit_val; + iter->p = iter->p->next; + return 0; +} + +extern void blkid_tag_iterate_end(blkid_tag_iterate iter) +{ + if (!iter || iter->magic != TAG_ITERATE_MAGIC) + return; + iter->magic = 0; + free(iter); +} + +/* + * This function returns a device which matches a particular + * type/value pair. If there is more than one device that matches the + * search specification, it returns the one with the highest priority + * value. This allows us to give preference to EVMS or LVM devices. + */ +extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache, + const char *type, + const char *value) +{ + blkid_tag head; + blkid_dev dev; + int pri; + struct list_head *p; + int probe_new = 0; + + if (!cache || !type || !value) + return NULL; + + blkid_read_cache(cache); + + DBG(DEBUG_TAG, printf("looking for %s=%s in cache\n", type, value)); + +try_again: + pri = -1; + dev = 0; + head = blkid_find_head_cache(cache, type); + + if (head) { + list_for_each(p, &head->bit_names) { + blkid_tag tmp = list_entry(p, struct blkid_struct_tag, + bit_names); + + if (!strcmp(tmp->bit_val, value) && + (tmp->bit_dev->bid_pri > pri) && + !access(tmp->bit_dev->bid_name, F_OK)) { + dev = tmp->bit_dev; + pri = dev->bid_pri; + } + } + } + if (dev && !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) { + dev = blkid_verify(cache, dev); + if (!dev || (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED))) + goto try_again; + } + + if (!dev && !probe_new) { + if (blkid_probe_all_new(cache) < 0) + return NULL; + probe_new++; + goto try_again; + } + + if (!dev && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) { + if (blkid_probe_all(cache) < 0) + return NULL; + goto try_again; + } + return dev; +} + +#ifdef TEST_PROGRAM +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#else +extern char *optarg; +extern int optind; +#endif + +void usage(char *prog) +{ + fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask] device " + "[type value]\n", + prog); + fprintf(stderr, "\tList all tags for a device and exit\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + blkid_tag_iterate iter; + blkid_cache cache = NULL; + blkid_dev dev; + int c, ret, found; + int flags = BLKID_DEV_FIND; + char *tmp; + char *file = NULL; + char *devname = NULL; + char *search_type = NULL; + char *search_value = NULL; + const char *type, *value; + + while ((c = getopt (argc, argv, "m:f:")) != EOF) + switch (c) { + case 'f': + file = optarg; + break; + case 'm': + { + int mask = strtoul (optarg, &tmp, 0); + if (*tmp) { + fprintf(stderr, "Invalid debug mask: %s\n", + optarg); + exit(1); + } + blkid_init_debug(mask); + break; + } + case '?': + usage(argv[0]); + } + if (argc > optind) + devname = argv[optind++]; + if (argc > optind) + search_type = argv[optind++]; + if (argc > optind) + search_value = argv[optind++]; + if (!devname || (argc != optind)) + usage(argv[0]); + + if ((ret = blkid_get_cache(&cache, file)) != 0) { + fprintf(stderr, "%s: error creating cache (%d)\n", + argv[0], ret); + exit(1); + } + + dev = blkid_get_dev(cache, devname, flags); + if (!dev) { + fprintf(stderr, "%s: Can not find device in blkid cache\n", + devname); + exit(1); + } + if (search_type) { + found = blkid_dev_has_tag(dev, search_type, search_value); + printf("Device %s: (%s, %s) %s\n", blkid_dev_devname(dev), + search_type, search_value ? search_value : "NULL", + found ? "FOUND" : "NOT FOUND"); + return(!found); + } + printf("Device %s...\n", blkid_dev_devname(dev)); + + iter = blkid_tag_iterate_begin(dev); + while (blkid_tag_next(iter, &type, &value) == 0) { + printf("\tTag %s has value %s\n", type, value); + } + blkid_tag_iterate_end(iter); + + blkid_put_cache(cache); + return (0); +} +#endif diff --git a/shlibs/blkid/src/tst_types.c b/shlibs/blkid/src/tst_types.c new file mode 100644 index 000000000..ecbc03217 --- /dev/null +++ b/shlibs/blkid/src/tst_types.c @@ -0,0 +1,63 @@ +/* + * This testing program makes sure the stdint.h header file + * + * Copyright (C) 2006 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include <sys/types.h> +#include <stdint.h> + +#include <stdlib.h> +#include <stdio.h> + +int main(int argc, char **argv) +{ + if (sizeof(uint8_t) != 1) { + printf("Sizeof(uint8_t) is %d should be 1\n", + (int)sizeof(uint8_t)); + exit(1); + } + if (sizeof(int8_t) != 1) { + printf("Sizeof(int8_t) is %d should be 1\n", + (int)sizeof(int8_t)); + exit(1); + } + if (sizeof(uint16_t) != 2) { + printf("Sizeof(uint16_t) is %d should be 2\n", + (int)sizeof(uint16_t)); + exit(1); + } + if (sizeof(int16_t) != 2) { + printf("Sizeof(int16_t) is %d should be 2\n", + (int)sizeof(int16_t)); + exit(1); + } + if (sizeof(uint32_t) != 4) { + printf("Sizeof(uint32_t) is %d should be 4\n", + (int)sizeof(uint32_t)); + exit(1); + } + if (sizeof(int32_t) != 4) { + printf("Sizeof(int32_t) is %d should be 4\n", + (int)sizeof(int32_t)); + exit(1); + } + if (sizeof(uint64_t) != 8) { + printf("Sizeof(uint64_t) is %d should be 8\n", + (int)sizeof(uint64_t)); + exit(1); + } + if (sizeof(int64_t) != 8) { + printf("Sizeof(int64_t) is %d should be 8\n", + (int)sizeof(int64_t)); + exit(1); + } + printf("The stdint.h types are correct.\n"); + exit(0); +} + diff --git a/shlibs/blkid/src/verify.c b/shlibs/blkid/src/verify.c new file mode 100644 index 000000000..40ab4c672 --- /dev/null +++ b/shlibs/blkid/src/verify.c @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <time.h> +#include <sys/types.h> +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include "blkidP.h" + +static void blkid_probe_to_tags(blkid_probe pr, blkid_dev dev) +{ + const char *data; + const char *name; + int nvals, n; + size_t len; + + nvals = blkid_probe_numof_values(pr); + + for (n = 0; n < nvals; n++) { + if (blkid_probe_get_value(pr, n, &name, &data, &len) == 0) + blkid_set_tag(dev, name, data, len); + } +} + +/* + * Verify that the data in dev is consistent with what is on the actual + * block device (using the devname field only). Normally this will be + * called when finding items in the cache, but for long running processes + * is also desirable to revalidate an item before use. + * + * If we are unable to revalidate the data, we return the old data and + * do not set the BLKID_BID_FL_VERIFIED flag on it. + */ +blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev) +{ + struct stat st; + time_t diff, now; + char *fltr[2]; + int fd; + + if (!dev) + return NULL; + + now = time(0); + diff = now - dev->bid_time; + + if (stat(dev->bid_name, &st) < 0) { + DBG(DEBUG_PROBE, + printf("blkid_verify: error %s (%d) while " + "trying to stat %s\n", strerror(errno), errno, + dev->bid_name)); + open_err: + if ((errno == EPERM) || (errno == EACCES) || (errno == ENOENT)) { + /* We don't have read permission, just return cache data. */ + DBG(DEBUG_PROBE, printf("returning unverified data for %s\n", + dev->bid_name)); + return dev; + } + blkid_free_dev(dev); + return NULL; + } + + if ((now >= dev->bid_time) && + (st.st_mtime <= dev->bid_time) && + ((diff < BLKID_PROBE_MIN) || + (dev->bid_flags & BLKID_BID_FL_VERIFIED && + diff < BLKID_PROBE_INTERVAL))) + return dev; + + DBG(DEBUG_PROBE, + printf("need to revalidate %s (cache time %lu, stat time %lu,\n\t" + "time since last check %lu)\n", + dev->bid_name, (unsigned long)dev->bid_time, + (unsigned long)st.st_mtime, (unsigned long)diff)); + + + if (!cache->probe) + cache->probe = blkid_new_probe(); + + fd = open(dev->bid_name, O_RDONLY); + if (fd < 0) { + DBG(DEBUG_PROBE, printf("blkid_verify: error %s (%d) while " + "opening %s\n", strerror(errno), errno, + dev->bid_name)); + goto open_err; + } + + if (blkid_probe_set_device(cache->probe, fd, 0, 0)) { + /* failed to read the device */ + close(fd); + blkid_free_dev(dev); + return NULL; + } + + blkid_probe_set_request(cache->probe, + BLKID_PROBREQ_LABEL | BLKID_PROBREQ_UUID | + BLKID_PROBREQ_TYPE | BLKID_PROBREQ_SECTYPE); + + /* + * If we already know the type, then try that first. + */ + if (dev->bid_type) { + blkid_tag_iterate iter; + const char *type, *value; + + fltr[0] = dev->bid_type; + fltr[1] = NULL; + + blkid_probe_filter_types(cache->probe, + BLKID_FLTR_ONLYIN, fltr); + + if (!blkid_do_probe(cache->probe)) + goto found_type; + blkid_probe_invert_filter(cache->probe); + + /* + * Zap the device filesystem information and try again + */ + DBG(DEBUG_PROBE, + printf("previous fs type %s not valid, " + "trying full probe\n", dev->bid_type)); + iter = blkid_tag_iterate_begin(dev); + while (blkid_tag_next(iter, &type, &value) == 0) + blkid_set_tag(dev, type, 0, 0); + blkid_tag_iterate_end(iter); + } + + /* + * Probe for all types. + */ + if (blkid_do_safeprobe(cache->probe)) { + /* found nothing or error */ + blkid_free_dev(dev); + dev = NULL; + } + +found_type: + if (dev) { + dev->bid_devno = st.st_rdev; + dev->bid_time = time(0); + dev->bid_flags |= BLKID_BID_FL_VERIFIED; + cache->bic_flags |= BLKID_BIC_FL_CHANGED; + + blkid_probe_to_tags(cache->probe, dev); + + DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n", + dev->bid_name, (long long)st.st_rdev, dev->bid_type)); + } + + blkid_reset_probe(cache->probe); + blkid_probe_reset_filter(cache->probe); + close(fd); + return dev; +} + +#ifdef TEST_PROGRAM +int main(int argc, char **argv) +{ + blkid_dev dev; + blkid_cache cache; + int ret; + + if (argc != 2) { + fprintf(stderr, "Usage: %s device\n" + "Probe a single device to determine type\n", argv[0]); + exit(1); + } + if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { + fprintf(stderr, "%s: error creating cache (%d)\n", + argv[0], ret); + exit(1); + } + dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL); + if (!dev) { + printf("%s: %s has an unsupported type\n", argv[0], argv[1]); + return (1); + } + printf("TYPE='%s'\n", dev->bid_type ? dev->bid_type : "(null)"); + if (dev->bid_label) + printf("LABEL='%s'\n", dev->bid_label); + if (dev->bid_uuid) + printf("UUID='%s'\n", dev->bid_uuid); + + blkid_free_dev(dev); + return (0); +} +#endif diff --git a/shlibs/blkid/src/version.c b/shlibs/blkid/src/version.c new file mode 100644 index 000000000..838af1146 --- /dev/null +++ b/shlibs/blkid/src/version.c @@ -0,0 +1,56 @@ +/* + * version.c --- Return the version of the blkid library + * + * Copyright (C) 2004 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <string.h> +#include <stdio.h> +#include <ctype.h> + +#include "blkid.h" + +/* LIBBLKID_* defined in the global config.h */ +static const char *lib_version = LIBBLKID_VERSION; /* release version */ +static const char *lib_date = LIBBLKID_DATE; + +int blkid_parse_version_string(const char *ver_string) +{ + const char *cp; + int version = 0; + + for (cp = ver_string; *cp; cp++) { + if (*cp == '.') + continue; + if (!isdigit(*cp)) + break; + version = (version * 10) + (*cp - '0'); + } + return version; +} + +/** + * blkid_get_library_version: + * @ver_string: returns relese version (!= SONAME version) + * @date_string: returns date + * + * Returns release version code. + */ +int blkid_get_library_version(const char **ver_string, + const char **date_string) +{ + if (ver_string) + *ver_string = lib_version; + if (date_string) + *date_string = lib_date; + + return blkid_parse_version_string(lib_version); +} |