diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/.github/workflows/ci.yml b/packages/pyblkid/opengnsys-pyblkid-0.3/.github/workflows/ci.yml new file mode 100644 index 0000000..a7a0e2a --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/.github/workflows/ci.yml @@ -0,0 +1,22 @@ +name: CI + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Install dependencies + run: | + sudo apt-get -qq update + sudo apt-get -y -qq install python3-pkgconfig + sudo apt-get -y -qq install libblkid-dev libblkid1 python3-dev + - name: Run tests + run: sudo make test diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/.github/workflows/codeql-analysis.yml b/packages/pyblkid/opengnsys-pyblkid-0.3/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000..f18aee6 --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/.github/workflows/codeql-analysis.yml @@ -0,0 +1,44 @@ +name: "CodeQL" + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-22.04 + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'cpp', 'python' ] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + + - name: Install build dependencies + run: | + sudo apt-get -qq update + sudo apt-get -y -qq install python3-pkgconfig + sudo apt-get -y -qq install libblkid-dev libblkid1 python3-dev + - name: Build + run: | + make + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/.gitignore b/packages/pyblkid/opengnsys-pyblkid-0.3/.gitignore new file mode 100644 index 0000000..1da7567 --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/.gitignore @@ -0,0 +1,6 @@ +env/ +build/ + +tests/__pycache__/* + +tests/*.img diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/LICENSE b/packages/pyblkid/opengnsys-pyblkid-0.3/LICENSE new file mode 100644 index 0000000..8000a6f --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/LICENSE @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random + Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/MANIFEST.in b/packages/pyblkid/opengnsys-pyblkid-0.3/MANIFEST.in new file mode 100644 index 0000000..ffc631f --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/MANIFEST.in @@ -0,0 +1,5 @@ +include LICENSE README.md +include MANIFEST.in +include Makefile +recursive-include src *.h +recursive-include tests *.py diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/Makefile b/packages/pyblkid/opengnsys-pyblkid-0.3/Makefile new file mode 100644 index 0000000..cb10d58 --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/Makefile @@ -0,0 +1,35 @@ +# Copyright (C) 2020 Red Hat, Inc. +# +# 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, see . + +PYTHON ?= python3 + + +default: all + +all: + @$(PYTHON) setup.py build + +test: all + @env PYTHONPATH=$$(find $$(pwd) -name "*.so" | head -n 1 | xargs dirname):src \ + $(PYTHON) -m unittest discover -v + +run-ipython: all + @env PYTHONPATH=$$(find $$(pwd) -name "*.so" | head -n 1 | xargs dirname):src i$(PYTHON) + +run-root-ipython: all + @sudo env PYTHONPATH=$$(find $$(pwd) -name "*.so" | head -n 1 | xargs dirname):src i$(PYTHON) + +clean: + -rm -r build diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/README.md b/packages/pyblkid/opengnsys-pyblkid-0.3/README.md new file mode 100644 index 0000000..0cc57a1 --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/README.md @@ -0,0 +1,38 @@ +# pylibblkid + +[![PyPI version](https://badge.fury.io/py/pylibblkid.svg)](https://badge.fury.io/py/pylibblkid) + +Python bindings for libblkid library. + +## Usage examples + +### Probing a device +```python +import blkid + +pr = blkid.Probe() +pr.set_device("/dev/sda1") + +pr.enable_superblocks(True) +pr.set_superblocks_flags(blkid.SUBLKS_TYPE | blkid.SUBLKS_USAGE | blkid.SUBLKS_UUID) + +pr.do_safeprobe() + +# print device properties as a dictionary +print(dict(pr)) +``` + +### Searching for device with specified label +```python +import blkid + +cache = blkid.Cache() +cache.probe_all() + +dev = cache.find_device("LABEL", "mylabel") + +# if found print found device and its properties +if dev: + print(dev.devname) + print(dev.tags) +``` diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/pyproject.toml b/packages/pyblkid/opengnsys-pyblkid-0.3/pyproject.toml new file mode 100644 index 0000000..3725998 --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools", "pkgconfig"] +build-backend = "setuptools.build_meta" diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/setup.py b/packages/pyblkid/opengnsys-pyblkid-0.3/setup.py new file mode 100644 index 0000000..0019dac --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/setup.py @@ -0,0 +1,78 @@ +# Copyright (C) 2020 Red Hat, Inc. +# +# 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, see . + +import sys + +import pkgconfig +from setuptools import Extension, setup + +pkgs = pkgconfig.list_all() +if "blkid" not in pkgs: + print("Please install libblkid-dev or libblkid-devel") + exit(1) + +vers = sys.version_info +if f"python-{vers.major}.{vers.minor}" not in pkgs: + print("Please install python3-dev or python3-devel") + exit(1) + + +# define macros for blkid releases +macros = [] +blkid_releases = ['2.24', '2.25', '2.30', '2.31', '2.36', '2.37', '2.39', '2.40'] +for blkid_ver in blkid_releases: + if pkgconfig.installed("blkid", f">= {blkid_ver}"): + ver_list = blkid_ver.split('.') + full_release = '_'.join(ver_list) + macros.append((f"HAVE_BLKID_{full_release}", "1")) + if len(ver_list) > 2: + major_minor = '_'.join(ver_list[:2]) + macros.append((f"HAVE_BLKID_{major_minor}", "1")) + + +with open("README.md", "r") as f: + long_description = f.read() + + +def main(): + setup(name="pylibblkid", + version="0.3", + description="Python interface for the libblkid C library", + long_description=long_description, + long_description_content_type="text/markdown", + author="Vojtech Trefny", + author_email="vtrefny@redhat.com", + url="http://github.com/vojtechtrefny/pyblkid", + ext_modules=[Extension("blkid", + sources=["src/pyblkid.c", + "src/topology.c", + "src/partitions.c", + "src/cache.c", + "src/probe.c",], + include_dirs=["/usr/include"], + libraries=["blkid"], + library_dirs=["/usr/lib"], + define_macros=macros, + extra_compile_args=["-std=c99", "-Wall", "-Wextra", "-Werror"])], + classifiers=["Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)", + "Programming Language :: C", + "Programming Language :: Python :: 3", + "Operating System :: POSIX :: Linux"]) + + +if __name__ == "__main__": + main() diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/src/cache.c b/packages/pyblkid/opengnsys-pyblkid-0.3/src/cache.c new file mode 100644 index 0000000..66bd6af --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/src/cache.c @@ -0,0 +1,336 @@ +/* + * Copyright (C) 2020 Red Hat, Inc. + * + * 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, see . + * + */ + +#include "cache.h" + +#include +#include + +#define UNUSED __attribute__((unused)) + + +PyObject *Cache_new (PyTypeObject *type, PyObject *args UNUSED, PyObject *kwargs UNUSED) { + CacheObject *self = (CacheObject*) type->tp_alloc (type, 0); + + if (self) + self->cache = NULL; + + return (PyObject *) self; +} + +int Cache_init (CacheObject *self UNUSED, PyObject *args, PyObject *kwargs) { + char *filename = NULL; + char *kwlist[] = { "filename", NULL }; + int ret = 0; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "|s", kwlist, &filename)) { + return -1; + } + + ret = blkid_get_cache (&(self->cache), filename); + if (ret < 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to get cache"); + return -1; + } + + return 0; +} + +void Cache_dealloc (CacheObject *self) { + Py_TYPE (self)->tp_free ((PyObject *) self); +} + +PyDoc_STRVAR(Cache_probe_all__doc__, +"probe_all (removable=False, new_only=False)\n\n" +"Probes all block devices.\n\n" +"With removable=True also adds removable block devices to cache. Don't forget that " +"removable devices could be pretty slow. It's very bad idea to call this function by default." +"With new_only=True this will scan only newly connected devices."); +static PyObject *Cache_probe_all (CacheObject *self, PyObject *args, PyObject *kwargs) { + bool removable = false; + bool new = false; + char *kwlist[] = { "removable", "new_only", NULL }; + int ret = 0; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "|pp", kwlist, &removable, &new)) { + return NULL; + } + + if (new) { + ret = blkid_probe_all_new (self->cache); + if (ret < 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to probe new devices"); + return NULL; + } + } else { + ret = blkid_probe_all (self->cache); + if (ret < 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to probe block devices"); + return NULL; + } + + if (removable) { + ret = blkid_probe_all_removable (self->cache); + if (ret < 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to probe removable devices"); + return NULL; + } + } + } + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(Cache_gc__doc__, +"gc\n\n" +"Removes garbage (non-existing devices) from the cache."); +static PyObject *Cache_gc (CacheObject *self, PyObject *Py_UNUSED (ignored)) { + blkid_gc_cache (self->cache); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(Cache_get_device__doc__, +"get_device (name)\n\n" +"Get device from cache.\n\n"); +static PyObject *Cache_get_device (CacheObject *self, PyObject *args, PyObject *kwargs) { + const char *name = NULL; + char *kwlist[] = { "name", NULL }; + blkid_dev device = NULL; + DeviceObject *dev_obj = NULL; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s", kwlist, &name)) + return NULL; + + device = blkid_get_dev (self->cache, name, BLKID_DEV_FIND); + if (device == NULL) + Py_RETURN_NONE; + + dev_obj = PyObject_New (DeviceObject, &DeviceType); + if (!dev_obj) { + PyErr_SetString (PyExc_MemoryError, "Failed to create a new Device object"); + return NULL; + } + + dev_obj->device = device; + dev_obj->cache = self->cache; + + return (PyObject *) dev_obj; +} + +PyDoc_STRVAR(Cache_find_device__doc__, +"find_device (tag, value)\n\n" +"Returns a device which matches a particular tag/value pair.\n" +" If there is more than one device that matches the search specification, " +"it returns the one with the highest priority\n\n"); +static PyObject *Cache_find_device (CacheObject *self, PyObject *args, PyObject *kwargs) { + const char *tag = NULL; + const char *value = NULL; + char *kwlist[] = { "tag", "value", NULL }; + blkid_dev device = NULL; + DeviceObject *dev_obj = NULL; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "ss", kwlist, &tag, &value)) + return NULL; + + device = blkid_find_dev_with_tag (self->cache, tag, value); + if (device == NULL) + Py_RETURN_NONE; + + dev_obj = PyObject_New (DeviceObject, &DeviceType); + if (!dev_obj) { + PyErr_SetString (PyExc_MemoryError, "Failed to create a new Device object"); + return NULL; + } + + dev_obj->device = device; + dev_obj->cache = self->cache; + + return (PyObject *) dev_obj; +} + +static PyMethodDef Cache_methods[] = { + {"probe_all", (PyCFunction)(void(*)(void)) Cache_probe_all, METH_VARARGS|METH_KEYWORDS, Cache_probe_all__doc__}, + {"gc", (PyCFunction) Cache_gc, METH_NOARGS, Cache_gc__doc__}, + {"get_device", (PyCFunction)(void(*)(void)) Cache_get_device, METH_VARARGS|METH_KEYWORDS, Cache_get_device__doc__}, + {"find_device", (PyCFunction)(void(*)(void)) Cache_find_device, METH_VARARGS|METH_KEYWORDS, Cache_find_device__doc__}, + {NULL, NULL, 0, NULL}, +}; + +static PyObject *Cache_get_devices (CacheObject *self, PyObject *Py_UNUSED (ignored)) { + blkid_dev_iterate iter; + blkid_dev device = NULL; + DeviceObject *dev_obj = NULL; + PyObject *list = NULL; + + list = PyList_New (0); + if (!list) { + PyErr_NoMemory (); + return NULL; + } + + iter = blkid_dev_iterate_begin (self->cache); + while (blkid_dev_next (iter, &device) == 0) { + dev_obj = PyObject_New (DeviceObject, &DeviceType); + if (!dev_obj) { + PyErr_NoMemory (); + return NULL; + } + dev_obj->device = device; + dev_obj->cache = self->cache; + PyList_Append (list, (PyObject *) dev_obj); + Py_DECREF (dev_obj); + + } + blkid_dev_iterate_end(iter); + + return (PyObject *) list; +} + +static PyGetSetDef Cache_getseters[] = { + {"devices", (getter) Cache_get_devices, NULL, "returns all devices in the cache", NULL}, + {NULL, NULL, NULL, NULL, NULL} +}; + +PyTypeObject CacheType = { + PyVarObject_HEAD_INIT (NULL, 0) + .tp_name = "blkid.Cache", + .tp_basicsize = sizeof (CacheObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_new = Cache_new, + .tp_dealloc = (destructor) Cache_dealloc, + .tp_init = (initproc) Cache_init, + .tp_methods = Cache_methods, + .tp_getset = Cache_getseters, +}; + +/*********************** DEVICE ***********************/ +PyObject *Device_new (PyTypeObject *type, PyObject *args UNUSED, PyObject *kwargs UNUSED) { + DeviceObject *self = (DeviceObject*) type->tp_alloc (type, 0); + + if (self) { + self->device = NULL; + self->cache = NULL; + } + + return (PyObject *) self; +} + +int Device_init (DeviceObject *self UNUSED, PyObject *args UNUSED, PyObject *kwargs UNUSED) { + return 0; +} + +void Device_dealloc (DeviceObject *self) { + Py_TYPE (self)->tp_free ((PyObject *) self); +} + +PyDoc_STRVAR(Device_verify__doc__, +"verify\n\n" +"Verify that the data in device is consistent with what is on the actual" +"block device. 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."); +static PyObject *Device_verify (DeviceObject *self, PyObject *Py_UNUSED (ignored)) { + self->device = blkid_verify (self->cache, self->device); + + Py_RETURN_NONE; +} + +static PyMethodDef Device_methods[] = { + {"verify", (PyCFunction) Device_verify, METH_NOARGS, Device_verify__doc__}, + {NULL, NULL, 0, NULL}, +}; + +static PyObject *Device_get_devname (DeviceObject *self, PyObject *Py_UNUSED (ignored)) { + const char *name = blkid_dev_devname (self->device); + + if (!name) + Py_RETURN_NONE; + + return PyUnicode_FromString (name); +} + +static PyObject *Device_get_tags (DeviceObject *self, PyObject *Py_UNUSED (ignored)) { + blkid_tag_iterate iter; + const char *type = NULL; + const char *value = NULL; + PyObject *dict = NULL; + PyObject *py_value = NULL; + + dict = PyDict_New (); + if (!dict) { + PyErr_NoMemory (); + return NULL; + } + + iter = blkid_tag_iterate_begin (self->device); + while (blkid_tag_next (iter, &type, &value) == 0) { + py_value = PyUnicode_FromString (value); + if (py_value == NULL) { + Py_INCREF (Py_None); + py_value = Py_None; + } + + PyDict_SetItemString (dict, type, py_value); + Py_DECREF (py_value); + } + blkid_tag_iterate_end(iter); + + return (PyObject *) dict; +} + +static PyObject *Device_str (PyObject *self) { + char *str = NULL; + int ret = 0; + PyObject *py_str = NULL; + intptr_t id = (intptr_t) self; + PyObject *py_name = PyObject_GetAttrString (self, "devname"); + + ret = asprintf (&str, "blkid.Device instance (0x%" PRIxPTR "): %s", id, PyUnicode_AsUTF8 (py_name)); + + Py_DECREF (py_name); + + if (ret < 0) + Py_RETURN_NONE; + + py_str = PyUnicode_FromString (str); + + free (str); + + return py_str; +} + +static PyGetSetDef Device_getseters[] = { + {"devname", (getter) Device_get_devname, NULL, "returns the name previously used for Cache.get_device.", NULL}, + {"tags", (getter) Device_get_tags, NULL, "returns all tags for this device.", NULL}, + {NULL, NULL, NULL, NULL, NULL} +}; + +PyTypeObject DeviceType = { + PyVarObject_HEAD_INIT (NULL, 0) + .tp_name = "blkid.Device", + .tp_basicsize = sizeof (DeviceObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_new = Device_new, + .tp_dealloc = (destructor) Device_dealloc, + .tp_init = (initproc) Device_init, + .tp_methods = Device_methods, + .tp_getset = Device_getseters, + .tp_str = Device_str, +}; diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/src/cache.h b/packages/pyblkid/opengnsys-pyblkid-0.3/src/cache.h new file mode 100644 index 0000000..33b526d --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/src/cache.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2020 Red Hat, Inc. + * + * 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, see . + * + */ +#ifndef CACHE_H +#define CACHE_H + +#include + +#include + +typedef struct { + PyObject_HEAD + blkid_cache cache; +} CacheObject; + +extern PyTypeObject CacheType; + +PyObject *Cache_new (PyTypeObject *type, PyObject *args, PyObject *kwargs); +int Cache_init (CacheObject *self, PyObject *args, PyObject *kwargs); +void Cache_dealloc (CacheObject *self); + +typedef struct { + PyObject_HEAD + blkid_dev device; + blkid_cache cache; +} DeviceObject; + +extern PyTypeObject DeviceType; + +#endif /* CACHE_H */ diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/src/partitions.c b/packages/pyblkid/opengnsys-pyblkid-0.3/src/partitions.c new file mode 100644 index 0000000..5778afc --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/src/partitions.c @@ -0,0 +1,534 @@ +/* + * Copyright (C) 2020 Red Hat, Inc. + * + * 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, see . + * + */ + +#include "partitions.h" + +#include + +#define UNUSED __attribute__((unused)) + + +/*********************** PARTLIST ***********************/ +PyObject *Partlist_new (PyTypeObject *type, PyObject *args UNUSED, PyObject *kwargs UNUSED) { + PartlistObject *self = (PartlistObject*) type->tp_alloc (type, 0); + + if (self) + self->Parttable_object = NULL; + + return (PyObject *) self; +} + +int Partlist_init (PartlistObject *self UNUSED, PyObject *args UNUSED, PyObject *kwargs UNUSED) { + return 0; +} + +void Partlist_dealloc (PartlistObject *self) { + if (self->Parttable_object) + Py_DECREF (self->Parttable_object); + + Py_TYPE (self)->tp_free ((PyObject *) self); +} + +PyObject *_Partlist_get_partlist_object (blkid_probe probe) { + PartlistObject *result = NULL; + blkid_partlist partlist = NULL; + + if (!probe) { + PyErr_SetString (PyExc_RuntimeError, "internal error"); + return NULL; + } + + partlist = blkid_probe_get_partitions (probe); + if (!partlist) { + PyErr_SetString (PyExc_RuntimeError, "Failed to get partitions"); + return NULL; + } + + result = PyObject_New (PartlistObject, &PartlistType); + if (!result) { + PyErr_SetString (PyExc_MemoryError, "Failed to create a new Partlist object"); + return NULL; + } + Py_INCREF (result); + + result->partlist = partlist; + result->Parttable_object = NULL; + + return (PyObject *) result; +} + +PyDoc_STRVAR(Partlist_get_partition__doc__, +"get_partition (number)\n\n" +"Get partition by number.\n\n" +"It's possible that the list of partitions is *empty*, but there is a valid partition table on the disk.\n" +"This happen when on-disk details about partitions are unknown or the partition table is empty."); +static PyObject *Partlist_get_partition (PartlistObject *self, PyObject *args, PyObject *kwargs) { + char *kwlist[] = { "number", NULL }; + int partnum = 0; + int numof = 0; + blkid_partition blkid_part = NULL; + PartitionObject *result = NULL; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "i", kwlist, &partnum)) { + return NULL; + } + + numof = blkid_partlist_numof_partitions (self->partlist); + if (numof < 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to get number of partitions"); + return NULL; + } + + if (partnum > numof) { + PyErr_Format (PyExc_RuntimeError, "Cannot get partition %d, partition table has only %d partitions", partnum, numof); + return NULL; + } + + blkid_part = blkid_partlist_get_partition (self->partlist, partnum); + if (!blkid_part) { + PyErr_Format (PyExc_RuntimeError, "Failed to get partition %d", partnum); + return NULL; + } + + result = PyObject_New (PartitionObject, &PartitionType); + if (!result) { + PyErr_SetString (PyExc_MemoryError, "Failed to create a new Partition object"); + return NULL; + } + + result->number = partnum; + result->partition = blkid_part; + result->Parttable_object = NULL; + + return (PyObject *) result; +} + +#ifdef HAVE_BLKID_2_25 +PyDoc_STRVAR(Partlist_get_partition_by_partno__doc__, +"get_partition_by_partno(number)\n\n" +"Get partition by partition number.\n\n" +"This does not assume any order of partitions and correctly handles \"out of order\" " +"partition tables. partition N is located after partition N+1 on the disk."); +static PyObject *Partlist_get_partition_by_partno (PartlistObject *self, PyObject *args, PyObject *kwargs) { + char *kwlist[] = { "number", NULL }; + int partno = 0; + blkid_partition blkid_part = NULL; + PartitionObject *result = NULL; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "i", kwlist, &partno)) { + return NULL; + } + + blkid_part = blkid_partlist_get_partition_by_partno (self->partlist, partno); + if (!blkid_part) { + PyErr_Format (PyExc_RuntimeError, "Failed to get partition %d", partno); + return NULL; + } + + result = PyObject_New (PartitionObject, &PartitionType); + if (!result) { + PyErr_NoMemory (); + return NULL; + } + + result->number = partno; + result->partition = blkid_part; + result->Parttable_object = NULL; + + return (PyObject *) result; +} +#endif + +static int _Py_Dev_Converter (PyObject *obj, void *p) { +#ifdef HAVE_LONG_LONG + *((dev_t *)p) = PyLong_AsUnsignedLongLong (obj); +#else + *((dev_t *)p) = PyLong_AsUnsignedLong (obj); +#endif + if (PyErr_Occurred ()) + return 0; + return 1; +} + +#ifdef HAVE_LONG_LONG + #define _PyLong_FromDev PyLong_FromLongLong +#else + #define _PyLong_FromDev PyLong_FromLong +#endif + +PyDoc_STRVAR(Partlist_devno_to_partition__doc__, +"devno_to_partition (devno)\n\n" +"Get partition by devno.\n"); +static PyObject *Partlist_devno_to_partition (PartlistObject *self, PyObject *args, PyObject *kwargs) { + dev_t devno = 0; + char *kwlist[] = { "devno", NULL }; + blkid_partition blkid_part = NULL; + PartitionObject *result = NULL; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "O&:devno_to_devname", kwlist, _Py_Dev_Converter, &devno)) + return NULL; + + blkid_part = blkid_partlist_devno_to_partition (self->partlist, devno); + if (!blkid_part) { + PyErr_Format (PyExc_RuntimeError, "Failed to get partition %zu", devno); + return NULL; + } + + result = PyObject_New (PartitionObject, &PartitionType); + if (!result) { + PyErr_NoMemory (); + return NULL; + } + + result->number = blkid_partition_get_partno (blkid_part); + result->partition = blkid_part; + result->Parttable_object = NULL; + + return (PyObject *) result; +} + +static PyMethodDef Partlist_methods[] = { + {"get_partition", (PyCFunction)(void(*)(void)) Partlist_get_partition, METH_VARARGS|METH_KEYWORDS, Partlist_get_partition__doc__}, +#ifdef HAVE_BLKID_2_25 + {"get_partition_by_partno", (PyCFunction)(void(*)(void)) Partlist_get_partition_by_partno, METH_VARARGS|METH_KEYWORDS, Partlist_get_partition_by_partno__doc__}, +#endif + {"devno_to_partition", (PyCFunction)(void(*)(void)) Partlist_devno_to_partition, METH_VARARGS|METH_KEYWORDS, Partlist_devno_to_partition__doc__}, + {NULL, NULL, 0, NULL}, +}; + +static PyObject *Partlist_get_table (PartlistObject *self, PyObject *Py_UNUSED (ignored)) { + if (self->Parttable_object) { + Py_INCREF (self->Parttable_object); + return self->Parttable_object; + } + + self->Parttable_object = _Parttable_get_parttable_object (self->partlist); + + return self->Parttable_object; +} + +static PyObject *Partlist_get_numof_partitions (PartlistObject *self, PyObject *Py_UNUSED (ignored)) { + int ret = 0; + + ret = blkid_partlist_numof_partitions (self->partlist); + if (ret < 0) { + PyErr_SetString (PyExc_MemoryError, "Failed to get number of partitions"); + return NULL; + } + + return PyLong_FromLong (ret); +} + + +static PyGetSetDef Partlist_getseters[] = { + {"table", (getter) Partlist_get_table, NULL, "binary interface for partition table on the device", NULL}, + {"numof_partitions", (getter) Partlist_get_numof_partitions, NULL, "number of partitions in the list", NULL}, + {NULL, NULL, NULL, NULL, NULL} +}; + +PyTypeObject PartlistType = { + PyVarObject_HEAD_INIT (NULL, 0) + .tp_name = "blkid.Partlist", + .tp_basicsize = sizeof (PartlistObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_new = Partlist_new, + .tp_dealloc = (destructor) Partlist_dealloc, + .tp_init = (initproc) Partlist_init, + .tp_methods = Partlist_methods, + .tp_getset = Partlist_getseters, +}; + + +/*********************** PARTTABLE ***********************/ +PyObject *Parttable_new (PyTypeObject *type, PyObject *args UNUSED, PyObject *kwargs UNUSED) { + ParttableObject *self = (ParttableObject*) type->tp_alloc (type, 0); + + return (PyObject *) self; +} + +int Parttable_init (ParttableObject *self UNUSED, PyObject *args UNUSED, PyObject *kwargs UNUSED) { + return 0; +} + +void Parttable_dealloc (ParttableObject *self) { + Py_TYPE (self)->tp_free ((PyObject *) self); +} + +PyObject *_Parttable_get_parttable_object (blkid_partlist partlist) { + ParttableObject *result = NULL; + blkid_parttable table = NULL; + + if (!partlist) { + PyErr_SetString(PyExc_RuntimeError, "internal error"); + return NULL; + } + + table = blkid_partlist_get_table (partlist); + if (!table) { + PyErr_SetString (PyExc_RuntimeError, "Failed to get partitions"); + return NULL; + } + + result = PyObject_New (ParttableObject, &ParttableType); + if (!result) { + PyErr_SetString (PyExc_MemoryError, "Failed to create a new Parttable object"); + return NULL; + } + Py_INCREF (result); + + result->table = table; + + return (PyObject *) result; +} + +PyDoc_STRVAR(Parttable_get_parent__doc__, +"get_parent ()\n\n" +"Parent for nested partition tables."); +static PyObject *Parttable_get_parent (ParttableObject *self, PyObject *Py_UNUSED (ignored)) { + blkid_partition blkid_part = NULL; + PartitionObject *result = NULL; + + blkid_part = blkid_parttable_get_parent (self->table); + if (!blkid_part) + Py_RETURN_NONE; + + result = PyObject_New (PartitionObject, &PartitionType); + if (!result) { + PyErr_SetString (PyExc_MemoryError, "Failed to create a new Partition object"); + return NULL; + } + + result->number = 0; + result->partition = blkid_part; + + return (PyObject *) result; +} + +static PyMethodDef Parttable_methods[] = { + {"get_parent", (PyCFunction)(void(*)(void)) Parttable_get_parent, METH_NOARGS, Parttable_get_parent__doc__}, + {NULL, NULL, 0, NULL}, +}; + +static PyObject *Parrtable_get_type (ParttableObject *self, PyObject *Py_UNUSED (ignored)) { + const char *pttype = blkid_parttable_get_type (self->table); + + return PyUnicode_FromString (pttype); +} + +static PyObject *Parrtable_get_id (ParttableObject *self, PyObject *Py_UNUSED (ignored)) { + const char *ptid = blkid_parttable_get_id (self->table); + + return PyUnicode_FromString (ptid); +} + +static PyObject *Parrtable_get_offset (ParttableObject *self, PyObject *Py_UNUSED (ignored)) { + blkid_loff_t offset = blkid_parttable_get_offset (self->table); + + return PyLong_FromLongLong (offset); +} + +static PyGetSetDef Parttable_getseters[] = { + {"type", (getter) Parrtable_get_type, NULL, "partition table type (type name, e.g. 'dos', 'gpt', ...)", NULL}, + {"id", (getter) Parrtable_get_id, NULL, "GPT disk UUID or DOS disk ID (in hex format)", NULL}, + {"offset", (getter) Parrtable_get_offset, NULL, "position (in bytes) of the partition table", NULL}, + {NULL, NULL, NULL, NULL, NULL} +}; + +PyTypeObject ParttableType = { + PyVarObject_HEAD_INIT (NULL, 0) + .tp_name = "blkid.Parttable", + .tp_basicsize = sizeof (ParttableObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_new = Parttable_new, + .tp_dealloc = (destructor) Parttable_dealloc, + .tp_init = (initproc) Parttable_init, + .tp_methods = Parttable_methods, + .tp_getset = Parttable_getseters, +}; + +/*********************** PARTITION ***********************/ +PyObject *Partition_new (PyTypeObject *type, PyObject *args UNUSED, PyObject *kwargs UNUSED) { + PartitionObject *self = (PartitionObject*) type->tp_alloc (type, 0); + + if (self) + self->Parttable_object = NULL; + + return (PyObject *) self; +} + +int Partition_init (PartitionObject *self, PyObject *args, PyObject *kwargs) { + char *kwlist[] = { "number", NULL }; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "i", kwlist, &(self->number))) { + return -1; + } + + self->partition = NULL; + + return 0; +} + +void Partition_dealloc (PartitionObject *self) { + if (self->Parttable_object) + Py_DECREF (self->Parttable_object); + + Py_TYPE (self)->tp_free ((PyObject *) self); +} + +static PyObject *Partition_get_type (PartitionObject *self, PyObject *Py_UNUSED (ignored)) { + int type = blkid_partition_get_type (self->partition); + + return PyLong_FromLong (type); +} + +static PyObject *Partition_get_type_string (PartitionObject *self, PyObject *Py_UNUSED (ignored)) { + const char *type = blkid_partition_get_type_string (self->partition); + + return PyUnicode_FromString (type); +} + +static PyObject *Partition_get_uuid (PartitionObject *self, PyObject *Py_UNUSED (ignored)) { + const char *uuid = blkid_partition_get_uuid (self->partition); + + return PyUnicode_FromString (uuid); +} + +static PyObject *Partition_get_is_extended (PartitionObject *self, PyObject *Py_UNUSED (ignored)) { + int extended = blkid_partition_is_extended (self->partition); + + if (extended == 1) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + +static PyObject *Partition_get_is_logical (PartitionObject *self, PyObject *Py_UNUSED (ignored)) { + int logical = blkid_partition_is_logical (self->partition); + + if (logical == 1) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + +static PyObject *Partition_get_is_primary (PartitionObject *self, PyObject *Py_UNUSED (ignored)) { + int primary = blkid_partition_is_primary (self->partition); + + if (primary == 1) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + +static PyObject *Partition_get_name (PartitionObject *self, PyObject *Py_UNUSED (ignored)) { + const char *name = blkid_partition_get_name (self->partition); + + return PyUnicode_FromString (name); +} + +static PyObject *Partition_get_flags (PartitionObject *self, PyObject *Py_UNUSED (ignored)) { + unsigned long long flags = blkid_partition_get_flags (self->partition); + + return PyLong_FromUnsignedLongLong (flags); +} + +static PyObject *Partition_get_partno (PartitionObject *self, PyObject *Py_UNUSED (ignored)) { + int partno = blkid_partition_get_partno (self->partition); + + return PyLong_FromLong (partno); +} + +static PyObject *Partition_get_size (PartitionObject *self, PyObject *Py_UNUSED (ignored)) { + blkid_loff_t size = blkid_partition_get_size (self->partition); + + return PyLong_FromLongLong (size); +} + +static PyObject *Partition_get_start (PartitionObject *self, PyObject *Py_UNUSED (ignored)) { + blkid_loff_t start = blkid_partition_get_start (self->partition); + + return PyLong_FromLongLong (start); +} + +PyObject *_Partition_get_parttable_object (blkid_partition partition) { + ParttableObject *result = NULL; + blkid_parttable table = NULL; + + if (!partition) { + PyErr_SetString(PyExc_RuntimeError, "internal error"); + return NULL; + } + + table = blkid_partition_get_table (partition); + if (!table) { + PyErr_SetString (PyExc_RuntimeError, "Failed to get partition table"); + return NULL; + } + + result = PyObject_New (ParttableObject, &ParttableType); + if (!result) { + PyErr_SetString (PyExc_MemoryError, "Failed to create a new Parttable object"); + return NULL; + } + Py_INCREF (result); + + result->table = table; + + return (PyObject *) result; +} + +static PyObject *Partition_get_table (PartitionObject *self, PyObject *Py_UNUSED (ignored)) { + if (self->Parttable_object) { + Py_INCREF (self->Parttable_object); + return self->Parttable_object; + } + + self->Parttable_object = _Partition_get_parttable_object (self->partition); + + return self->Parttable_object; +} + +static PyGetSetDef Partition_getseters[] = { + {"type", (getter) Partition_get_type, NULL, "partition type", NULL}, + {"type_string", (getter) Partition_get_type_string, NULL, "partition type string, note the type string is supported by a small subset of partition tables (e.g Mac and EFI GPT)", NULL}, + {"uuid", (getter) Partition_get_uuid, NULL, "partition UUID string if supported by PT (e.g. GPT)", NULL}, + {"is_extended", (getter) Partition_get_is_extended, NULL, "returns whether the partition is extendedor not ", NULL}, + {"is_logical", (getter) Partition_get_is_logical, NULL, "returns whether the partition is logical or not", NULL}, + {"is_primary", (getter) Partition_get_is_primary, NULL, "returns whether the partition is primary or not", NULL}, + {"name", (getter) Partition_get_name, NULL, "partition name string if supported by PT (e.g. Mac)", NULL}, + {"flags", (getter) Partition_get_flags, NULL, "partition flags (or attributes for gpt)", NULL}, + {"partno", (getter) Partition_get_partno, NULL, "proposed partition number (e.g. 'N' from sda'N') or -1 in case of error", NULL}, + {"size", (getter) Partition_get_size, NULL, "size of the partition (in 512-sectors)", NULL}, + {"start", (getter) Partition_get_start, NULL, "start of the partition (in 512-sectors)", NULL}, + {"table", (getter) Partition_get_table, NULL, "partition table object (usually the same for all partitions, except nested partition tables)", NULL}, + {NULL, NULL, NULL, NULL, NULL} +}; + +PyTypeObject PartitionType = { + PyVarObject_HEAD_INIT (NULL, 0) + .tp_name = "blkid.Partition", + .tp_basicsize = sizeof (PartitionObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_new = Partition_new, + .tp_dealloc = (destructor) Partition_dealloc, + .tp_init = (initproc) Partition_init, + .tp_getset = Partition_getseters, +}; diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/src/partitions.h b/packages/pyblkid/opengnsys-pyblkid-0.3/src/partitions.h new file mode 100644 index 0000000..b68f91d --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/src/partitions.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2020 Red Hat, Inc. + * + * 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, see . + * + */ +#ifndef PARTITIONS_H +#define PARTITIONS_H + +#include + +#include + +typedef struct { + PyObject_HEAD + blkid_partlist partlist; + PyObject *Parttable_object; +} PartlistObject; + +extern PyTypeObject PartlistType; + +PyObject *Partlist_new (PyTypeObject *type, PyObject *args, PyObject *kwargs); +int Partlist_init (PartlistObject *self, PyObject *args, PyObject *kwargs); +void Partlist_dealloc (PartlistObject *self); + +PyObject *_Partlist_get_partlist_object (blkid_probe probe); + + +typedef struct { + PyObject_HEAD + blkid_parttable table; +} ParttableObject; + +extern PyTypeObject ParttableType; + +PyObject *Parttable_new (PyTypeObject *type, PyObject *args, PyObject *kwargs); +int Parttable_init (ParttableObject *self, PyObject *args, PyObject *kwargs); +void Parttable_dealloc (ParttableObject *self); + +PyObject *_Parttable_get_parttable_object (blkid_partlist partlist); + +typedef struct { + PyObject_HEAD + int number; + blkid_partition partition; + PyObject *Parttable_object; +} PartitionObject; + +extern PyTypeObject PartitionType; + +PyObject *Partition_new (PyTypeObject *type, PyObject *args, PyObject *kwargs); +int Partition_init (PartitionObject *self, PyObject *args, PyObject *kwargs); +void Partition_dealloc (PartitionObject *self); + +PyObject *_Partition_get_parttable_object (blkid_partition partition); + +#endif /* PARTITIONS_H */ diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/src/probe.c b/packages/pyblkid/opengnsys-pyblkid-0.3/src/probe.c new file mode 100644 index 0000000..e4a2e7b --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/src/probe.c @@ -0,0 +1,959 @@ +/* + * Copyright (C) 2020 Red Hat, Inc. + * + * 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, see . + * + */ + +#include "probe.h" +#include "topology.h" +#include "partitions.h" + +#include +#include +#include +#include + +#define UNUSED __attribute__((unused)) + + +PyObject *Probe_new (PyTypeObject *type, PyObject *args UNUSED, PyObject *kwargs UNUSED) { + ProbeObject *self = (ProbeObject*) type->tp_alloc (type, 0); + + if (self) { + self->probe = NULL; + self->fd = -1; + self->topology = NULL; + self->partlist = NULL; + } + + return (PyObject *) self; +} + +int Probe_init (ProbeObject *self, PyObject *args UNUSED, PyObject *kwargs UNUSED) { + if (self->probe) + blkid_free_probe (self->probe); + + self->probe = blkid_new_probe (); + if (!self->probe) { + PyErr_SetString (PyExc_MemoryError, "Failed to create new Probe."); + return -1; + } + + return 0; +} + +void Probe_dealloc (ProbeObject *self) { + if (!self->probe) + /* if init fails */ + return; + + if (self->fd > 0) + close (self->fd); + + if (self->topology) + Py_DECREF (self->topology); + + if (self->partlist) + Py_DECREF (self->partlist); + + blkid_free_probe (self->probe); + Py_TYPE (self)->tp_free ((PyObject *) self); +} + +PyDoc_STRVAR(Probe_set_device__doc__, +"set_device (device, flags=os.O_RDONLY|os.O_CLOEXEC, offset=0, size=0)\n\n" +"Assigns the device to probe control struct, resets internal buffers and resets the current probing.\n\n" +"'flags' define flags for the 'open' system call. By default the device will be opened as read-only.\n" +"'offset' and 'size' specify begin and size of probing area (zero means whole device/file)"); +static PyObject *Probe_set_device (ProbeObject *self, PyObject *args, PyObject *kwargs) { + int ret = 0; + char *kwlist[] = { "device", "flags", "offset", "size", NULL }; + char *device = NULL; + blkid_loff_t offset = 0; + blkid_loff_t size = 0; + int flags = O_RDONLY|O_CLOEXEC; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s|iKK", kwlist, &device, &flags, &offset, &size)) { + return NULL; + } + + self->fd = open (device, flags); + if (self->fd == -1) { + PyErr_Format (PyExc_OSError, "Failed to open device '%s': %s", device, strerror (errno)); + return NULL; + } + + ret = blkid_probe_set_device (self->probe, self->fd, offset, size); + if (ret != 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to set device"); + return NULL; + } + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(Probe_enable_superblocks__doc__, +"enable_superblocks (enable)\n\n" \ +"Enables/disables the superblocks probing for non-binary interface."); +static PyObject *Probe_enable_superblocks (ProbeObject *self, PyObject *args, PyObject *kwargs) { + int ret = 0; + bool enable = false; + char *kwlist[] = { "enable", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "p", kwlist, &enable)) { + return NULL; + } + + ret = blkid_probe_enable_superblocks (self->probe, enable); + if (ret != 0) { + PyErr_Format (PyExc_RuntimeError, "Failed to %s superblocks probing", enable ? "enable" : "disable"); + return NULL; + } + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(Probe_set_superblocks_flags__doc__, +"set_superblocks_flags (flags)\n\n" \ +"Sets probing flags to the superblocks prober. This function is optional, the default are blkid.SUBLKS_DEFAULTS flags.\n" +"Use blkid.SUBLKS_* constants for the 'flags' argument."); +static PyObject *Probe_set_superblocks_flags (ProbeObject *self, PyObject *args, PyObject *kwargs) { + int ret = 0; + int flags = 0; + char *kwlist[] = { "flags", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &flags)) { + return NULL; + } + + ret = blkid_probe_set_superblocks_flags (self->probe, flags); + if (ret != 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to set partition flags"); + return NULL; + } + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(Probe_filter_superblocks_type__doc__, +"filter_superblocks_type (flag, names)\n\n" \ +"Filter superblocks prober results based on type.\n" +"blkid.FLTR_NOTIN - probe for all items which are NOT IN names\n" +"blkid.FLTR_ONLYIN - probe for items which are IN names\n" +"names: array of probing function names (e.g. 'vfat')."); +static PyObject *Probe_filter_superblocks_type (ProbeObject *self, PyObject *args, PyObject *kwargs) { + int ret = 0; + int flag = 0; + PyObject *pynames = NULL; + PyObject *pystring = NULL; + Py_ssize_t len = 0; + char **names = NULL; + char *kwlist[] = { "flag", "names", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iO", kwlist, &flag, &pynames)) { + return NULL; + } + + if (!PySequence_Check (pynames)) { + PyErr_SetString (PyExc_AttributeError, "Failed to parse list of names for filter"); + return NULL; + } + + len = PySequence_Size (pynames); + if (len < 1) { + PyErr_SetString (PyExc_AttributeError, "Failed to parse list of names for filter"); + return NULL; + } + + names = malloc(sizeof (char *) * (len + 1)); + if (!names) { + PyErr_NoMemory (); + return NULL; + } + + for (Py_ssize_t i = 0; i < len; i++) { + pystring = PyUnicode_AsEncodedString (PySequence_GetItem (pynames, i), "utf-8", "replace"); + names[i] = strdup (PyBytes_AsString (pystring)); + Py_DECREF (pystring); + } + names[len] = NULL; + + ret = blkid_probe_filter_superblocks_type (self->probe, flag, names); + if (ret != 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to set probe filter"); + for (Py_ssize_t i = 0; i < len; i++) + free(names[i]); + free (names); + return NULL; + } + + for (Py_ssize_t i = 0; i < len; i++) + free(names[i]); + free (names); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(Probe_filter_superblocks_usage__doc__, +"filter_superblocks_usage (flag, usage)\n\n" \ +"Filter superblocks prober results based on usage.\n" +"blkid.FLTR_NOTIN - probe for all items which are NOT IN names\n" +"blkid.FLTR_ONLYIN - probe for items which are IN names\n" +"usage: blkid.USAGE_* flags"); +static PyObject *Probe_filter_superblocks_usage (ProbeObject *self, PyObject *args, PyObject *kwargs) { + int ret = 0; + int flag = 0; + int usage = 0; + char *kwlist[] = { "flag", "usage", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii", kwlist, &flag, &usage)) { + return NULL; + } + + ret = blkid_probe_filter_superblocks_usage (self->probe, flag, usage); + if (ret != 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to set probe filter"); + return NULL; + } + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(Probe_invert_superblocks_filter__doc__, +"invert_superblocks_filter ()\n\n" +"This function inverts superblocks probing filter.\n"); +static PyObject *Probe_invert_superblocks_filter (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + int ret = 0; + + ret = blkid_probe_invert_superblocks_filter (self->probe); + if (ret != 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to invert superblock probing filter"); + return NULL; + } + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(Probe_reset_superblocks_filter__doc__, +"reset_superblocks_filter ()\n\n" +"This function resets superblocks probing filter.\n"); +static PyObject *Probe_reset_superblocks_filter (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + int ret = 0; + + ret = blkid_probe_reset_superblocks_filter (self->probe); + if (ret != 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to reset superblock probing filter"); + return NULL; + } + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(Probe_enable_partitions__doc__, +"enable_partitions (enable)\n\n" \ +"Enables/disables the partitions probing for non-binary interface."); +static PyObject *Probe_enable_partitions (ProbeObject *self, PyObject *args, PyObject *kwargs) { + int ret = 0; + bool enable = false; + char *kwlist[] = { "enable", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "p", kwlist, &enable)) { + return NULL; + } + + ret = blkid_probe_enable_partitions (self->probe, enable); + if (ret != 0) { + PyErr_Format (PyExc_RuntimeError, "Failed to %s partitions probing", enable ? "enable" : "disable"); + return NULL; + } + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(Probe_set_partitions_flags__doc__, +"set_partitions_flags (flags)\n\n" \ +"Sets probing flags to the partitions prober. This function is optional.\n" +"Use blkid.PARTS_* constants for the 'flags' argument."); +static PyObject *Probe_set_partitions_flags (ProbeObject *self, PyObject *args, PyObject *kwargs) { + int ret = 0; + int flags = 0; + char *kwlist[] = { "flags", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &flags)) { + return NULL; + } + + ret = blkid_probe_set_partitions_flags (self->probe, flags); + if (ret != 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to set superblock flags"); + return NULL; + } + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(Probe_filter_partitions_type__doc__, +"filter_partitions_type (flag, names)\n\n" \ +"Filter partitions prober results based on type.\n" +"blkid.FLTR_NOTIN - probe for all items which are NOT IN names\n" +"blkid.FLTR_ONLYIN - probe for items which are IN names\n" +"names: array of probing function names (e.g. 'vfat')."); +static PyObject *Probe_filter_partitions_type (ProbeObject *self, PyObject *args, PyObject *kwargs) { + int ret = 0; + int flag = 0; + PyObject *pynames = NULL; + PyObject *pystring = NULL; + Py_ssize_t len = 0; + char **names = NULL; + char *kwlist[] = { "flag", "names", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iO", kwlist, &flag, &pynames)) { + return NULL; + } + + if (!PySequence_Check (pynames)) { + PyErr_SetString (PyExc_AttributeError, "Failed to parse list of names for filter"); + return NULL; + } + + len = PySequence_Size (pynames); + if (len < 1) { + PyErr_SetString (PyExc_AttributeError, "Failed to parse list of names for filter"); + return NULL; + } + + names = malloc(sizeof (char *) * (len + 1)); + if (!names) { + PyErr_NoMemory (); + return NULL; + } + + for (Py_ssize_t i = 0; i < len; i++) { + pystring = PyUnicode_AsEncodedString (PySequence_GetItem (pynames, i), "utf-8", "replace"); + names[i] = strdup (PyBytes_AsString (pystring)); + Py_DECREF (pystring); + } + names[len] = NULL; + + ret = blkid_probe_filter_partitions_type (self->probe, flag, names); + if (ret != 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to set probe filter"); + for (Py_ssize_t i = 0; i < len; i++) + free(names[i]); + free (names); + return NULL; + } + + for (Py_ssize_t i = 0; i < len; i++) + free(names[i]); + free (names); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(Probe_invert_partitions_filter__doc__, +"invert_partitions_filter ()\n\n" +"This function inverts partitions probing filter.\n"); +static PyObject *Probe_invert_partitions_filter (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + int ret = 0; + + ret = blkid_probe_invert_partitions_filter (self->probe); + if (ret != 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to invert superblock probing filter"); + return NULL; + } + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(Probe_reset_partitions_filter__doc__, +"reset_partitions_filter ()\n\n" +"This function resets partitions probing filter.\n"); +static PyObject *Probe_reset_partitions_filter (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + int ret = 0; + + ret = blkid_probe_reset_partitions_filter (self->probe); + if (ret != 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to reset superblock probing filter"); + return NULL; + } + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(Probe_enable_topology__doc__, +"enable_topology (enable)\n\n" \ +"Enables/disables the topology probing for non-binary interface."); +static PyObject *Probe_enable_topology (ProbeObject *self, PyObject *args, PyObject *kwargs) { + int ret = 0; + bool enable = false; + char *kwlist[] = { "enable", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "p", kwlist, &enable)) { + return NULL; + } + + ret = blkid_probe_enable_topology (self->probe, enable); + if (ret != 0) { + PyErr_Format (PyExc_RuntimeError, "Failed to %s topology probing", enable ? "enable" : "disable"); + return NULL; + } + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(Probe_lookup_value__doc__, +"lookup_value (name)\n\n" \ +"Assigns the device to probe control struct, resets internal buffers and resets the current probing."); +static PyObject *Probe_lookup_value (ProbeObject *self, PyObject *args, PyObject *kwargs) { + int ret = 0; + char *kwlist[] = { "name", NULL }; + char *name = NULL; + const char *value = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name)) { + return NULL; + } + + ret = blkid_probe_lookup_value (self->probe, name, &value, NULL); + if (ret != 0) { + PyErr_Format (PyExc_RuntimeError, "Failed to lookup '%s'", name); + return NULL; + } + + return PyBytes_FromString (value); +} + +PyDoc_STRVAR(Probe_do_safeprobe__doc__, +"do_safeprobe ()\n\n" +"This function gathers probing results from all enabled chains and checks for ambivalent results" +"(e.g. more filesystems on the device).\n" +"Returns True on success, False if nothing is detected.\n\n" +"Note about superblocks chain -- the function does not check for filesystems when a RAID signature is detected.\n" +"The function also does not check for collision between RAIDs. The first detected RAID is returned.\n" +"The function checks for collision between partition table and RAID signature -- it's recommended to " +"enable partitions chain together with superblocks chain.\n"); +static PyObject *Probe_do_safeprobe (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + int ret = 0; + + if (self->fd < 0) { + PyErr_SetString (PyExc_ValueError, "No device set"); + return NULL; + } + + if (self->topology) { + Py_DECREF (self->topology); + self->topology = NULL; + } + + if (self->partlist) { + Py_DECREF (self->partlist); + self->partlist = NULL; + } + + ret = blkid_do_safeprobe (self->probe); + if (ret < 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to safeprobe the device"); + return NULL; + } + + if (ret == 0) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + +PyDoc_STRVAR(Probe_do_fullprobe__doc__, +"do_fullprobe ()\n\n" +"Returns True on success, False if nothing is detected.\n" +"This function gathers probing results from all enabled chains. Same as do_safeprobe() but " +"does not check for collision between probing result."); +static PyObject *Probe_do_fullprobe (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + int ret = 0; + + if (self->fd < 0) { + PyErr_SetString (PyExc_ValueError, "No device set"); + return NULL; + } + + if (self->topology) { + Py_DECREF (self->topology); + self->topology = NULL; + } + + if (self->partlist) { + Py_DECREF (self->partlist); + self->partlist = NULL; + } + + ret = blkid_do_fullprobe (self->probe); + if (ret < 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to fullprobe the device"); + return NULL; + } + + if (ret == 0) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + +PyDoc_STRVAR(Probe_do_probe__doc__, +"do_probe ()\n\n" +"Calls probing functions in all enabled chains. The superblocks chain is enabled by default.\n" +"Returns True on success, False if nothing is detected.\n\n" +"The do_probe() stores result from only one probing function. It's necessary to call this routine " +"in a loop to get results from all probing functions in all chains. The probing is reset by " +"reset_probe() or by filter functions."); +static PyObject *Probe_do_probe (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + int ret = 0; + + if (self->fd < 0) { + PyErr_SetString (PyExc_ValueError, "No device set"); + return NULL; + } + + if (self->topology) { + Py_DECREF (self->topology); + self->topology = NULL; + } + + if (self->partlist) { + Py_DECREF (self->partlist); + self->partlist = NULL; + } + + ret = blkid_do_probe (self->probe); + if (ret < 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to probe the device"); + return NULL; + } + + if (ret == 0) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + +PyDoc_STRVAR(Probe_step_back__doc__, +"step_back ()\n\n" +"This function move pointer to the probing chain one step back -- it means that the previously " +"used probing function will be called again in the next Probe.do_probe() call.\n" +"This is necessary for example if you erase or modify on-disk superblock according to the " +"current libblkid probing result.\n" +"Note that Probe.hide_range() changes semantic of this function and cached buffers are " +"not reset, but library uses in-memory modified buffers to call the next probing function."); +static PyObject *Probe_step_back (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + int ret = 0; + + ret = blkid_probe_step_back (self->probe); + if (ret < 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to step back the probe"); + return NULL; + } + + Py_RETURN_NONE; +} + +#ifdef HAVE_BLKID_2_31 +PyDoc_STRVAR(Probe_reset_buffers__doc__, +"reset_buffers ()\n\n" +"libblkid reuse all already read buffers from the device. The buffers may be modified by Probe.hide_range().\n" +"This function reset and free all cached buffers. The next Probe.do_probe() will read all data from the device."); +static PyObject *Probe_reset_buffers (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + int ret = 0; + + ret = blkid_probe_reset_buffers (self->probe); + if (ret != 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to reset buffers"); + return NULL; + } + + Py_RETURN_NONE; +} +#endif + +PyDoc_STRVAR(Probe_reset_probe__doc__, +"reset_probe ()\n\n" +"Zeroize probing results and resets the current probing (this has impact to do_probe() only).\n" +"This function does not touch probing filters and keeps assigned device."); +static PyObject *Probe_reset_probe (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + blkid_reset_probe (self->probe); + + if (self->topology) { + Py_DECREF (self->topology); + self->topology = NULL; + } + + if (self->partlist) { + Py_DECREF (self->partlist); + self->partlist = NULL; + } + + Py_RETURN_NONE; +} + +#ifdef HAVE_BLKID_2_31 +PyDoc_STRVAR(Probe_hide_range__doc__, +"hide_range (offset, length)\n\n" \ +"This function modifies in-memory cached data from the device. The specified range is zeroized. " +"This is usable together with Probe.step_back(). The next Probe.do_probe() will not see specified area.\n" +"Note that this is usable for already (by library) read data, and this function is not a way " +"how to hide any large areas on your device.\n" +"The function Probe.reset_buffers() reverts all."); +static PyObject *Probe_hide_range (ProbeObject *self, PyObject *args, PyObject *kwargs) { + int ret = 0; + char *kwlist[] = { "offset", "length", NULL }; + uint64_t offset = 0; + uint64_t length = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii", kwlist, &offset, &length)) { + return NULL; + } + + ret = blkid_probe_hide_range (self->probe, offset, length); + if (ret != 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to hide range"); + return NULL; + } + + Py_RETURN_NONE; +} +#endif + +#ifdef HAVE_BLKID_2_40 +PyDoc_STRVAR(Probe_wipe_all__doc__, +"wipe_all ()\n\n" +"This function erases all detectable signatures from probe. The probe has to be open in O_RDWR mode. " +"All other necessary configurations will be enabled automatically."); +static PyObject *Probe_wipe_all (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + int ret = 0; + + ret = blkid_wipe_all (self->probe); + if (ret < 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to probe the device"); + return NULL; + } + + Py_RETURN_NONE; +} +#endif + +PyDoc_STRVAR(Probe_do_wipe__doc__, +"do_wipe (dryrun=False)\n\n" +"This function erases the current signature detected by the probe. The probe has to be open in " +"O_RDWR mode, blkid.SUBLKS_MAGIC or/and blkid.PARTS_MAGIC flags has to be enabled (if you want " +"to erase also superblock with broken check sums then use blkid.SUBLKS_BADCSUM too).\n\n" +"After successful signature removing the probe prober will be moved one step back and the next " +"do_probe() call will again call previously called probing function. All in-memory cached data " +"from the device are always reset."); +static PyObject *Probe_do_wipe (ProbeObject *self, PyObject *args, PyObject *kwargs) { + int ret = 0; + char *kwlist[] = { "dryrun", NULL }; + bool dryrun = false; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|p", kwlist, &dryrun)) { + return NULL; + } + + ret = blkid_do_wipe (self->probe, dryrun); + if (ret != 0) { + PyErr_Format (PyExc_RuntimeError, "Failed to wipe the device: %s", strerror (errno)); + return NULL; + } + + Py_RETURN_NONE; +} + +static PyObject * probe_to_dict (ProbeObject *self) { + PyObject *dict = NULL; + int ret = 0; + int nvalues = 0; + const char *name = NULL; + const char *value = NULL; + PyObject *py_value = NULL; + + ret = blkid_probe_numof_values (self->probe); + if (ret < 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to get probe results"); + return NULL; + } + nvalues = ret; + + dict = PyDict_New (); + if (!dict) { + PyErr_NoMemory (); + return NULL; + } + + for (int i = 0; i < nvalues; i++) { + ret = blkid_probe_get_value (self->probe, i, &name, &value, NULL); + if (ret < 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to get probe results"); + return NULL; + } + + py_value = PyUnicode_FromString (value); + if (py_value == NULL) { + Py_INCREF (Py_None); + py_value = Py_None; + } + + PyDict_SetItemString (dict, name, py_value); + Py_DECREF (py_value); + } + + return dict; +} + +PyDoc_STRVAR(Probe_items__doc__, +"items ()\n"); +static PyObject *Probe_items (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + PyObject *dict = probe_to_dict (self); + + if (PyErr_Occurred ()) + return NULL; + + PyObject *ret = PyDict_Items (dict); + PyDict_Clear (dict); + + return ret; +} + +PyDoc_STRVAR(Probe_values__doc__, +"values ()\n"); +static PyObject *Probe_values (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + PyObject *dict = probe_to_dict (self); + + if (PyErr_Occurred ()) + return NULL; + + PyObject *ret = PyDict_Values (dict); + PyDict_Clear (dict); + + return ret; +} + +PyDoc_STRVAR(Probe_keys__doc__, +"keys ()\n"); +static PyObject *Probe_keys (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + PyObject *dict = probe_to_dict (self); + + if (PyErr_Occurred ()) + return NULL; + + PyObject *ret = PyDict_Keys (dict); + PyDict_Clear (dict); + + return ret; +} + +static PyMethodDef Probe_methods[] = { + {"set_device", (PyCFunction)(void(*)(void)) Probe_set_device, METH_VARARGS|METH_KEYWORDS, Probe_set_device__doc__}, + {"do_safeprobe", (PyCFunction) Probe_do_safeprobe, METH_NOARGS, Probe_do_safeprobe__doc__}, + {"do_fullprobe", (PyCFunction) Probe_do_fullprobe, METH_NOARGS, Probe_do_fullprobe__doc__}, + {"do_probe", (PyCFunction) Probe_do_probe, METH_NOARGS, Probe_do_probe__doc__}, + {"step_back", (PyCFunction) Probe_step_back, METH_NOARGS, Probe_step_back__doc__}, +#ifdef HAVE_BLKID_2_31 + {"reset_buffers", (PyCFunction) Probe_reset_buffers, METH_NOARGS, Probe_reset_buffers__doc__}, +#endif + {"reset_probe", (PyCFunction) Probe_reset_probe, METH_NOARGS, Probe_reset_probe__doc__}, +#ifdef HAVE_BLKID_2_31 + {"hide_range", (PyCFunction)(void(*)(void)) Probe_hide_range, METH_VARARGS|METH_KEYWORDS, Probe_hide_range__doc__}, +#endif +#ifdef HAVE_BLKID_2_40 + {"wipe_all", (PyCFunction) Probe_wipe_all, METH_NOARGS, Probe_wipe_all__doc__}, +#endif + {"do_wipe", (PyCFunction)(void(*)(void)) Probe_do_wipe, METH_VARARGS|METH_KEYWORDS, Probe_do_wipe__doc__}, + {"enable_partitions", (PyCFunction)(void(*)(void)) Probe_enable_partitions, METH_VARARGS|METH_KEYWORDS, Probe_enable_partitions__doc__}, + {"set_partitions_flags", (PyCFunction)(void(*)(void)) Probe_set_partitions_flags, METH_VARARGS|METH_KEYWORDS, Probe_set_partitions_flags__doc__}, + {"filter_partitions_type", (PyCFunction)(void(*)(void)) Probe_filter_partitions_type, METH_VARARGS|METH_KEYWORDS, Probe_filter_partitions_type__doc__}, + {"invert_partitions_filter", (PyCFunction) Probe_invert_partitions_filter, METH_NOARGS, Probe_invert_partitions_filter__doc__}, + {"reset_partitions_filter", (PyCFunction) Probe_reset_partitions_filter, METH_NOARGS, Probe_reset_partitions_filter__doc__}, + {"enable_topology", (PyCFunction)(void(*)(void)) Probe_enable_topology, METH_VARARGS|METH_KEYWORDS, Probe_enable_topology__doc__}, + {"enable_superblocks", (PyCFunction)(void(*)(void)) Probe_enable_superblocks, METH_VARARGS|METH_KEYWORDS, Probe_enable_superblocks__doc__}, + {"filter_superblocks_type", (PyCFunction)(void(*)(void)) Probe_filter_superblocks_type, METH_VARARGS|METH_KEYWORDS, Probe_filter_superblocks_type__doc__}, + {"filter_superblocks_usage", (PyCFunction)(void(*)(void)) Probe_filter_superblocks_usage, METH_VARARGS|METH_KEYWORDS, Probe_filter_superblocks_usage__doc__}, + {"set_superblocks_flags", (PyCFunction)(void(*)(void)) Probe_set_superblocks_flags, METH_VARARGS|METH_KEYWORDS, Probe_set_superblocks_flags__doc__}, + {"invert_superblocks_filter", (PyCFunction) Probe_invert_superblocks_filter, METH_NOARGS, Probe_invert_superblocks_filter__doc__}, + {"reset_superblocks_filter", (PyCFunction) Probe_reset_superblocks_filter, METH_NOARGS, Probe_reset_superblocks_filter__doc__}, + {"lookup_value", (PyCFunction)(void(*)(void)) Probe_lookup_value, METH_VARARGS|METH_KEYWORDS, Probe_lookup_value__doc__}, + {"items", (PyCFunction) Probe_items, METH_NOARGS, Probe_items__doc__}, + {"values", (PyCFunction) Probe_values, METH_NOARGS, Probe_values__doc__}, + {"keys", (PyCFunction) Probe_keys, METH_NOARGS, Probe_keys__doc__}, + {NULL, NULL, 0, NULL} +}; + +static PyObject *Probe_get_devno (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + dev_t devno = blkid_probe_get_devno (self->probe); + + return PyLong_FromUnsignedLong (devno); +} + +static PyObject *Probe_get_fd (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + return PyLong_FromLong (self->fd); +} + +static PyObject *Probe_get_offset (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + blkid_loff_t offset = blkid_probe_get_offset (self->probe); + + return PyLong_FromLongLong (offset); +} + +static PyObject *Probe_get_sectors (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + blkid_loff_t sectors = blkid_probe_get_sectors (self->probe); + + return PyLong_FromLongLong (sectors); +} + +static PyObject *Probe_get_size (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + blkid_loff_t size = blkid_probe_get_size (self->probe); + + return PyLong_FromLongLong (size); +} + +static PyObject *Probe_get_sector_size (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + unsigned int sector_size = blkid_probe_get_sectorsize (self->probe); + + return PyLong_FromUnsignedLong (sector_size); +} + +#ifdef HAVE_BLKID_2_30 +static int Probe_set_sector_size (ProbeObject *self, PyObject *value, void *closure UNUSED) { + unsigned int sector_size = 0; + int ret = 0; + + if (!PyLong_Check (value)) { + PyErr_SetString (PyExc_TypeError, "Invalid argument"); + + return -1; + } + + sector_size = PyLong_AsLong (value); + + ret = blkid_probe_set_sectorsize (self->probe, sector_size); + if (ret != 0) { + PyErr_Format (PyExc_RuntimeError, "Failed to set sector size"); + return -1; + } + + return 0; +} +#endif + +static PyObject *Probe_get_wholedisk_devno (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + dev_t devno = blkid_probe_get_wholedisk_devno (self->probe); + + return PyLong_FromUnsignedLong (devno); +} + +static PyObject *Probe_get_is_wholedisk (ProbeObject *self __attribute__((unused)), PyObject *Py_UNUSED (ignored)) { + int wholedisk = blkid_probe_is_wholedisk (self->probe); + + return PyBool_FromLong (wholedisk); +} + +static PyObject *Probe_get_topology (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + if (self->topology) { + Py_INCREF (self->topology); + return self->topology; + } + + self->topology = _Topology_get_topology_object (self->probe); + + return self->topology; +} + +static PyObject *Probe_get_partitions (ProbeObject *self, PyObject *Py_UNUSED (ignored)) { + if (self->partlist) { + Py_INCREF (self->partlist); + return self->partlist; + } + + self->partlist = _Partlist_get_partlist_object (self->probe); + + return self->partlist; +} + +static PyGetSetDef Probe_getseters[] = { + {"devno", (getter) Probe_get_devno, NULL, "block device number, or 0 for regular files", NULL}, + {"fd", (getter) Probe_get_fd, NULL, "file descriptor for assigned device/file or -1 in case of error", NULL}, + {"offset", (getter) Probe_get_offset, NULL, "offset of probing area as defined by Probe.set_device() or -1 in case of error", NULL}, + {"sectors", (getter) Probe_get_sectors, NULL, "512-byte sector count or -1 in case of error", NULL}, + {"size", (getter) Probe_get_size, NULL, "size of probing area as defined by Probe.set_device()", NULL}, +#ifdef HAVE_BLKID_2_30 + {"sector_size", (getter) Probe_get_sector_size, (setter) Probe_set_sector_size, "block device logical sector size (BLKSSZGET ioctl, default 512).", NULL}, +#else + {"sector_size", (getter) Probe_get_sector_size, NULL, "block device logical sector size (BLKSSZGET ioctl, default 512).", NULL}, +#endif + {"wholedisk_devno", (getter) Probe_get_wholedisk_devno, NULL, "device number of the wholedisk, or 0 for regular files", NULL}, + {"is_wholedisk", (getter) Probe_get_is_wholedisk, NULL, "True if the device is whole-disk, False otherwise", NULL}, + {"topology", (getter) Probe_get_topology, NULL, "binary interface for topology values", NULL}, + {"partitions", (getter) Probe_get_partitions, NULL, "binary interface for partitions", NULL}, + {NULL, NULL, NULL, NULL, NULL} +}; + +static Py_ssize_t Probe_len (ProbeObject *self) { + int ret = 0; + + ret = blkid_probe_numof_values (self->probe); + if (ret < 0) + return 0; + + return (Py_ssize_t) ret; + +} + +static PyObject * Probe_getitem (ProbeObject *self, PyObject *item) { + int ret = 0; + const char *key = NULL; + const char *value = NULL; + + if (!PyUnicode_Check (item)) { + PyErr_SetObject(PyExc_KeyError, item); + return NULL; + } + + key = PyUnicode_AsUTF8 (item); + + ret = blkid_probe_lookup_value (self->probe, key, &value, NULL); + if (ret != 0) { + PyErr_SetObject (PyExc_KeyError, item); + return NULL; + } + + return PyBytes_FromString (value); +} + + + +PyMappingMethods ProbeMapping = { + .mp_length = (lenfunc) Probe_len, + .mp_subscript = (binaryfunc) Probe_getitem, +}; + +PyTypeObject ProbeType = { + PyVarObject_HEAD_INIT (NULL, 0) + .tp_name = "blkid.Probe", + .tp_basicsize = sizeof (ProbeObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_new = Probe_new, + .tp_dealloc = (destructor) Probe_dealloc, + .tp_init = (initproc) Probe_init, + .tp_methods = Probe_methods, + .tp_getset = Probe_getseters, + .tp_as_mapping = &ProbeMapping, +}; diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/src/probe.h b/packages/pyblkid/opengnsys-pyblkid-0.3/src/probe.h new file mode 100644 index 0000000..055aaa0 --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/src/probe.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 Red Hat, Inc. + * + * 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, see . + * + */ +#ifndef PROBE_H +#define PROBE_H + +#include + +#include + +typedef struct { + PyObject_HEAD + blkid_probe probe; + PyObject *topology; + PyObject *partlist; + int fd; +} ProbeObject; + +extern PyTypeObject ProbeType; + +PyObject *Probe_new (PyTypeObject *type, PyObject *args, PyObject *kwargs); +int Probe_init (ProbeObject *self, PyObject *args, PyObject *kwargs); +void Probe_dealloc (ProbeObject *self); + +#endif /* PROBE_H */ diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/src/pyblkid.c b/packages/pyblkid/opengnsys-pyblkid-0.3/src/pyblkid.c new file mode 100644 index 0000000..c254473 --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/src/pyblkid.c @@ -0,0 +1,631 @@ +/* + * Copyright (C) 2020 Red Hat, Inc. + * + * 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, see . + * + */ + +#include "pyblkid.h" +#include "probe.h" +#include "topology.h" +#include "partitions.h" +#include "cache.h" + +#include +#include +#include + +#define UNUSED __attribute__((unused)) + + +PyDoc_STRVAR(Blkid_init_debug__doc__, +"init_debug (mask)\n\n" +"If the mask is not specified then this function reads LIBBLKID_DEBUG environment variable to get the mask.\n" +"Already initialized debugging stuff cannot be changed. It does not have effect to call this function twice.\n\n" +"Use '0xffff' to enable full debugging.\n"); +static PyObject *Blkid_init_debug (PyObject *self UNUSED, PyObject *args, PyObject *kwargs) { + int mask = 0; + char *kwlist[] = { "mask", NULL }; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "|i", kwlist, &mask)) + return NULL; + + blkid_init_debug (mask); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(Blkid_known_fstype__doc__, +"known_fstype (fstype)\n\n" +"Returns whether fstype is a known filesystem type or not.\n"); +static PyObject *Blkid_known_fstype (PyObject *self UNUSED, PyObject *args, PyObject *kwargs) { + const char *fstype = NULL; + char *kwlist[] = { "fstype", NULL }; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s", kwlist, &fstype)) + return NULL; + + return PyBool_FromLong (blkid_known_fstype (fstype)); +} + +PyDoc_STRVAR(Blkid_send_uevent__doc__, +"send_uevent (devname, action)\n\n"); +static PyObject *Blkid_send_uevent (PyObject *self UNUSED, PyObject *args, PyObject *kwargs) { + const char *devname = NULL; + const char *action = NULL; + char *kwlist[] = { "devname", "action", NULL }; + int ret = 0; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "ss", kwlist, &devname, &action)) + return NULL; + + ret = blkid_send_uevent (devname, action); + if (ret < 0) { + PyErr_Format (PyExc_RuntimeError, "Failed to send %s uevent do device '%s'", action, devname); + return NULL; + } + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(Blkid_known_pttype__doc__, +"known_pttype (pttype)\n\n" +"Returns whether pttype is a known partition type or not.\n"); +static PyObject *Blkid_known_pttype (PyObject *self UNUSED, PyObject *args, PyObject *kwargs) { + const char *pttype = NULL; + char *kwlist[] = { "pttype", NULL }; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s", kwlist, &pttype)) + return NULL; + + return PyBool_FromLong (blkid_known_pttype (pttype)); +} + +static int _Py_Dev_Converter (PyObject *obj, void *p) { +#ifdef HAVE_LONG_LONG + *((dev_t *)p) = PyLong_AsUnsignedLongLong (obj); +#else + *((dev_t *)p) = PyLong_AsUnsignedLong (obj); +#endif + if (PyErr_Occurred ()) + return 0; + return 1; +} + +#ifdef HAVE_LONG_LONG + #define _PyLong_FromDev PyLong_FromLongLong +#else + #define _PyLong_FromDev PyLong_FromLong +#endif + +PyDoc_STRVAR(Blkid_devno_to_devname__doc__, +"devno_to_devname (devno)\n\n" +"This function finds the pathname to a block device with a given device number.\n"); +static PyObject *Blkid_devno_to_devname (PyObject *self UNUSED, PyObject *args, PyObject *kwargs) { + dev_t devno = 0; + char *kwlist[] = { "devno", NULL }; + char *devname = NULL; + PyObject *ret = NULL; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "O&:devno_to_devname", kwlist, _Py_Dev_Converter, &devno)) + return NULL; + + devname = blkid_devno_to_devname (devno); + if (!devname) { + PyErr_SetString (PyExc_RuntimeError, "Failed to get devname"); + return NULL; + } + + ret = PyUnicode_FromString (devname); + free (devname); + + return ret; +} + +PyDoc_STRVAR(Blkid_devno_to_wholedisk__doc__, +"devno_to_wholedisk (devno)\n\n" +"This function uses sysfs to convert the devno device number to the name and devno of the whole disk."); +static PyObject *Blkid_devno_to_wholedisk (PyObject *self UNUSED, PyObject *args, PyObject *kwargs) { + dev_t devno = 0; + dev_t diskdevno = 0; + char *kwlist[] = { "devno", NULL }; +#ifdef HAVE_BLKID_2_28 + char diskname[32]; +#else + char diskname[PATH_MAX]; +#endif + int ret = 0; + PyObject *tuple = NULL; + PyObject *py_name = NULL; + PyObject *py_devno = NULL; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "O&:devno_to_wholedisk", kwlist, _Py_Dev_Converter, &devno)) + return NULL; + +#ifdef HAVE_BLKID_2_28 + ret = blkid_devno_to_wholedisk (devno, diskname, 32, &diskdevno); +#else + ret = blkid_devno_to_wholedisk (devno, diskname, PATH_MAX, &diskdevno); +#endif + if (ret != 0) { + PyErr_SetString (PyExc_RuntimeError, "Failed to get whole disk name"); + return NULL; + } + + tuple = PyTuple_New (2); + + py_name = PyUnicode_FromString (diskname); + if (py_name == NULL) { + Py_INCREF (Py_None); + py_name = Py_None; + } + PyTuple_SetItem (tuple, 0, py_name); + + py_devno = _PyLong_FromDev (diskdevno); + if (py_devno == NULL) { + Py_INCREF (Py_None); + py_devno = Py_None; + } + PyTuple_SetItem (tuple, 1, py_devno); + + return tuple; +} + +PyDoc_STRVAR(Blkid_parse_version_string__doc__, +"parse_version_string (version)\n\n" +"Convert version string (e.g. '2.16.0') to release version code (e.g. '2160').\n"); +static PyObject *Blkid_parse_version_string (PyObject *self UNUSED, PyObject *args, PyObject *kwargs) { + char *ver_str = NULL; + char *kwlist[] = { "version", NULL }; + int ret = 0; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s", kwlist, &ver_str)) + return NULL; + + ret = blkid_parse_version_string (ver_str); + + return PyLong_FromLong (ret); +} + +PyDoc_STRVAR(Blkid_get_library_version__doc__, +"get_library_version ()\n\n" +"Returns tuple of release version code (int), version string and date.\n"); +static PyObject *Blkid_get_library_version (ProbeObject *self UNUSED, PyObject *Py_UNUSED (ignored)) { + const char *ver_str = NULL; + const char *date = NULL; + int ver_code = 0; + PyObject *ret = NULL; + PyObject *py_code = NULL; + PyObject *py_ver = NULL; + PyObject *py_date = NULL; + + ver_code = blkid_get_library_version (&ver_str, &date); + + ret = PyTuple_New (3); + + py_code = PyLong_FromLong (ver_code); + PyTuple_SetItem (ret, 0, py_code); + + py_ver = PyUnicode_FromString (ver_str); + if (py_ver == NULL) { + Py_INCREF (Py_None); + py_ver = Py_None; + } + PyTuple_SetItem (ret, 1, py_ver); + + py_date = PyUnicode_FromString (date); + if (py_date == NULL) { + Py_INCREF (Py_None); + py_date = Py_None; + } + PyTuple_SetItem (ret, 2, py_date); + + return ret; +} + +PyDoc_STRVAR(Blkid_parse_tag_string__doc__, +"parse_tag_string (tag)\n\n" +"Parse a 'NAME=value' string, returns tuple of type and value.\n"); +static PyObject *Blkid_parse_tag_string (PyObject *self UNUSED, PyObject *args, PyObject *kwargs) { + char *tag_str = NULL; + char *kwlist[] = { "tag", NULL }; + int ret = 0; + char *type = NULL; + char *value = NULL; + PyObject *py_type = NULL; + PyObject *py_value = NULL; + PyObject *tuple = NULL; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s", kwlist, &tag_str)) + return NULL; + + ret = blkid_parse_tag_string (tag_str, &type, &value); + if (ret < 0) { + PyErr_Format (PyExc_RuntimeError, "Failed to parse tag '%s'", tag_str); + return NULL; + } + + tuple = PyTuple_New (2); + + py_type = PyUnicode_FromString (type); + if (py_type == NULL) { + Py_INCREF (Py_None); + py_type = Py_None; + } + PyTuple_SetItem (tuple, 0, py_type); + free (type); + + py_value = PyUnicode_FromString (value); + if (py_value == NULL) { + Py_INCREF (Py_None); + py_value = Py_None; + } + PyTuple_SetItem (tuple, 1, py_value); + free (value); + + return tuple; +} + +PyDoc_STRVAR(Blkid_get_dev_size__doc__, +"get_dev_size (device)\n\n" +"Returns size (in bytes) of the block device or size of the regular file.\n"); +static PyObject *Blkid_get_dev_size (PyObject *self UNUSED, PyObject *args, PyObject *kwargs) { + char *device = NULL; + char *kwlist[] = { "device", NULL }; + blkid_loff_t ret = 0; + int fd = 0; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s", kwlist, &device)) + return NULL; + + fd = open (device, O_RDONLY|O_CLOEXEC); + if (fd == -1) { + PyErr_Format (PyExc_OSError, "Failed to open device '%s': %s", device, strerror (errno)); + return NULL; + } + + ret = blkid_get_dev_size (fd); + if (ret == 0) { + PyErr_Format (PyExc_RuntimeError, "Failed to get size of device '%s'", device); + close (fd); + return NULL; + } + + close (fd); + return PyLong_FromLongLong (ret); +} + +PyDoc_STRVAR(Blkid_encode_string__doc__, +"encode_string (string)\n\n" +"Encode all potentially unsafe characters of a string to the corresponding hex value prefixed by '\\x'.\n"); +static PyObject *Blkid_encode_string (PyObject *self UNUSED, PyObject *args, PyObject *kwargs) { + char *string = NULL; + char *kwlist[] = { "string", NULL }; + char *encoded_string = NULL; + int ret = 0; + size_t inlen = 0; + size_t outlen = 0; + PyObject *py_ret = NULL; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s", kwlist, &string)) + return NULL; + + inlen = strlen (string); + outlen = inlen * 4; + encoded_string = malloc (sizeof (char) * (outlen + 1 )); + + ret = blkid_encode_string (string, encoded_string, outlen); + if (ret != 0) { + PyErr_Format (PyExc_RuntimeError, "Failed to encode string"); + free (encoded_string); + return NULL; + } + + py_ret = PyUnicode_FromString (encoded_string); + free (encoded_string); + + return py_ret; +} + +PyDoc_STRVAR(Blkid_safe_string__doc__, +"safe_string (string)\n\n" +"Allows plain ascii, hex-escaping and valid utf8. Replaces all whitespaces with '_'.\n"); +static PyObject *Blkid_safe_string (PyObject *self UNUSED, PyObject *args, PyObject *kwargs) { + char *string = NULL; + char *kwlist[] = { "string", NULL }; + char *safe_string = NULL; + int ret = 0; + size_t inlen = 0; + size_t outlen = 0; + PyObject *py_ret = NULL; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s", kwlist, &string)) + return NULL; + + inlen = strlen (string); + outlen = inlen * 4; + safe_string = malloc (sizeof (char) * (outlen + 1 )); + + ret = blkid_safe_string (string, safe_string, outlen); + if (ret != 0) { + PyErr_Format (PyExc_RuntimeError, "Failed to make safe string"); + free (safe_string); + return NULL; + } + + py_ret = PyUnicode_FromString (safe_string); + free (safe_string); + + return py_ret; +} + +#ifdef HAVE_BLKID_2_30 +PyDoc_STRVAR(Blkid_partition_types__doc__, +"partition_types ()\n\n" +"List of supported partition types.\n"); +static PyObject *Blkid_partition_types (ProbeObject *self UNUSED, PyObject *Py_UNUSED (ignored)) { + PyObject *ret = NULL; + PyObject *py_name = NULL; + size_t idx = 0; + const char *name = NULL; + + ret = PyList_New (0); + + while (blkid_partitions_get_name (idx++, &name) == 0) { + py_name = PyUnicode_FromString (name); + if (py_name != NULL) + PyList_Append (ret, py_name); + } + + return ret; +} +#endif + +PyDoc_STRVAR(Blkid_superblocks__doc__, +"superblocks ()\n\n" +"List of supported superblocks.\n"); +static PyObject *Blkid_superblocks (ProbeObject *self UNUSED, PyObject *Py_UNUSED (ignored)) { + PyObject *ret = NULL; + PyObject *py_name = NULL; + size_t idx = 0; + const char *name = NULL; + + ret = PyList_New (0); + + while (blkid_superblocks_get_name (idx++, &name, NULL) == 0) { + py_name = PyUnicode_FromString (name); + if (py_name != NULL) + PyList_Append (ret, py_name); + } + + return ret; +} + +PyDoc_STRVAR(Blkid_evaluate_tag__doc__, +"evaluate_tag (token, value)\n\n" +"Get device name that match the specified token (e.g \"LABEL\" or \"UUID\") and token value.\n" +"The evaluation could be controlled by the /etc/blkid.conf config file. The default is to try \"udev\" and then \"scan\" method.\n"); +static PyObject *Blkid_evaluate_tag (PyObject *self UNUSED, PyObject *args, PyObject *kwargs) { + char *token = NULL; + char *value = NULL; + char *kwlist[] = { "token", "value", NULL }; + PyObject *py_ret = NULL; + char *ret = NULL; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "ss", kwlist, &token, &value)) + return NULL; + + + ret = blkid_evaluate_tag (token, value, NULL); + if (ret == NULL) { + Py_INCREF (Py_None); + py_ret = Py_None; + } else { + py_ret = PyUnicode_FromString (ret); + free (ret); + } + + return py_ret; +} + +PyDoc_STRVAR(Blkid_evaluate_spec__doc__, +"evaluate_spec (spec)\n\n" +"Get device name that match the unparsed tag (e.g. \"LABEL=foo\") or path (e.g. /dev/dm-0)\n" +"The evaluation could be controlled by the /etc/blkid.conf config file. The default is to try \"udev\" and then \"scan\" method.\n"); +static PyObject *Blkid_evaluate_spec (PyObject *self UNUSED, PyObject *args, PyObject *kwargs) { + char *spec = NULL; + char *kwlist[] = { "spec", NULL }; + PyObject *py_ret = NULL; + char *ret = NULL; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s", kwlist, &spec)) + return NULL; + + + ret = blkid_evaluate_spec (spec, NULL); + if (ret == NULL) { + Py_INCREF (Py_None); + py_ret = Py_None; + } else { + py_ret = PyUnicode_FromString (ret); + free (ret); + } + + return py_ret; +} + +static PyMethodDef BlkidMethods[] = { + {"init_debug", (PyCFunction)(void(*)(void)) Blkid_init_debug, METH_VARARGS|METH_KEYWORDS, Blkid_init_debug__doc__}, + {"known_fstype", (PyCFunction)(void(*)(void)) Blkid_known_fstype, METH_VARARGS|METH_KEYWORDS, Blkid_known_fstype__doc__}, + {"send_uevent", (PyCFunction)(void(*)(void)) Blkid_send_uevent, METH_VARARGS|METH_KEYWORDS, Blkid_send_uevent__doc__}, + {"devno_to_devname", (PyCFunction)(void(*)(void)) Blkid_devno_to_devname, METH_VARARGS|METH_KEYWORDS, Blkid_devno_to_devname__doc__}, + {"devno_to_wholedisk", (PyCFunction)(void(*)(void)) Blkid_devno_to_wholedisk, METH_VARARGS|METH_KEYWORDS, Blkid_devno_to_wholedisk__doc__}, + {"known_pttype", (PyCFunction)(void(*)(void)) Blkid_known_pttype, METH_VARARGS|METH_KEYWORDS, Blkid_known_pttype__doc__}, + {"parse_version_string", (PyCFunction)(void(*)(void)) Blkid_parse_version_string, METH_VARARGS|METH_KEYWORDS, Blkid_parse_version_string__doc__}, + {"get_library_version", (PyCFunction) Blkid_get_library_version, METH_NOARGS, Blkid_get_library_version__doc__}, + {"parse_tag_string", (PyCFunction)(void(*)(void)) Blkid_parse_tag_string, METH_VARARGS|METH_KEYWORDS, Blkid_parse_tag_string__doc__}, + {"get_dev_size", (PyCFunction)(void(*)(void)) Blkid_get_dev_size, METH_VARARGS|METH_KEYWORDS, Blkid_get_dev_size__doc__}, + {"encode_string", (PyCFunction)(void(*)(void)) Blkid_encode_string, METH_VARARGS|METH_KEYWORDS, Blkid_encode_string__doc__}, + {"safe_string", (PyCFunction)(void(*)(void)) Blkid_safe_string, METH_VARARGS|METH_KEYWORDS, Blkid_safe_string__doc__}, +#ifdef HAVE_BLKID_2_30 + {"partition_types", (PyCFunction) Blkid_partition_types, METH_NOARGS, Blkid_partition_types__doc__}, +#endif + {"superblocks", (PyCFunction) Blkid_superblocks, METH_NOARGS, Blkid_superblocks__doc__}, + {"evaluate_tag", (PyCFunction)(void(*)(void)) Blkid_evaluate_tag, METH_VARARGS|METH_KEYWORDS, Blkid_evaluate_tag__doc__}, + {"evaluate_spec", (PyCFunction)(void(*)(void)) Blkid_evaluate_spec, METH_VARARGS|METH_KEYWORDS, Blkid_evaluate_spec__doc__}, + {NULL, NULL, 0, NULL} +}; + +static struct PyModuleDef blkidmodule = { + PyModuleDef_HEAD_INIT, + .m_name = "blkid", + .m_doc = "Python interface for the libblkid C library", + .m_size = -1, + .m_methods = BlkidMethods, +}; + +PyMODINIT_FUNC PyInit_blkid (void) { + PyObject *module = NULL; + + if (PyType_Ready (&ProbeType) < 0) + return NULL; + + if (PyType_Ready (&TopologyType) < 0) + return NULL; + + if (PyType_Ready (&PartlistType) < 0) + return NULL; + + if (PyType_Ready (&ParttableType) < 0) + return NULL; + + if (PyType_Ready (&PartitionType) < 0) + return NULL; + + if (PyType_Ready (&CacheType) < 0) + return NULL; + + if (PyType_Ready (&DeviceType) < 0) + return NULL; + + module = PyModule_Create (&blkidmodule); + if (!module) + return NULL; + + PyModule_AddIntConstant (module, "FLTR_NOTIN", BLKID_FLTR_NOTIN); + PyModule_AddIntConstant (module, "FLTR_ONLYIN", BLKID_FLTR_ONLYIN); + + PyModule_AddIntConstant (module, "DEV_CREATE", BLKID_DEV_CREATE); + PyModule_AddIntConstant (module, "DEV_FIND", BLKID_DEV_FIND); + PyModule_AddIntConstant (module, "DEV_NORMAL", BLKID_DEV_NORMAL); + PyModule_AddIntConstant (module, "DEV_VERIFY", BLKID_DEV_VERIFY); + + PyModule_AddIntConstant (module, "PARTS_ENTRY_DETAILS", BLKID_PARTS_ENTRY_DETAILS); + PyModule_AddIntConstant (module, "PARTS_FORCE_GPT", BLKID_PARTS_FORCE_GPT); + PyModule_AddIntConstant (module, "PARTS_MAGIC", BLKID_PARTS_MAGIC); + +#ifdef HAVE_BLKID_2_24 + PyModule_AddIntConstant (module, "SUBLKS_BADCSUM", BLKID_SUBLKS_BADCSUM); +#endif + PyModule_AddIntConstant (module, "SUBLKS_DEFAULT", BLKID_SUBLKS_DEFAULT); +#ifdef HAVE_BLKID_2_39 + PyModule_AddIntConstant (module, "SUBLKS_FSINFO", BLKID_SUBLKS_FSINFO); +#endif + PyModule_AddIntConstant (module, "SUBLKS_LABEL", BLKID_SUBLKS_LABEL); + PyModule_AddIntConstant (module, "SUBLKS_LABELRAW", BLKID_SUBLKS_LABELRAW); + PyModule_AddIntConstant (module, "SUBLKS_MAGIC", BLKID_SUBLKS_MAGIC); + PyModule_AddIntConstant (module, "SUBLKS_SECTYPE", BLKID_SUBLKS_SECTYPE); + PyModule_AddIntConstant (module, "SUBLKS_TYPE", BLKID_SUBLKS_TYPE); + PyModule_AddIntConstant (module, "SUBLKS_USAGE", BLKID_SUBLKS_USAGE); + PyModule_AddIntConstant (module, "SUBLKS_UUID", BLKID_SUBLKS_UUID); + PyModule_AddIntConstant (module, "SUBLKS_UUIDRAW", BLKID_SUBLKS_UUIDRAW); + PyModule_AddIntConstant (module, "SUBLKS_VERSION", BLKID_SUBLKS_VERSION); + + PyModule_AddIntConstant (module, "USAGE_CRYPTO", BLKID_USAGE_CRYPTO); + PyModule_AddIntConstant (module, "USAGE_FILESYSTEM", BLKID_USAGE_FILESYSTEM); + PyModule_AddIntConstant (module, "USAGE_OTHER", BLKID_USAGE_OTHER); + PyModule_AddIntConstant (module, "USAGE_RAID", BLKID_USAGE_RAID); + + Py_INCREF (&ProbeType); + if (PyModule_AddObject (module, "Probe", (PyObject *) &ProbeType) < 0) { + Py_DECREF (&ProbeType); + Py_DECREF (module); + return NULL; + } + + Py_INCREF (&TopologyType); + if (PyModule_AddObject (module, "Topology", (PyObject *) &TopologyType) < 0) { + Py_DECREF (&ProbeType); + Py_DECREF (&TopologyType); + Py_DECREF (module); + return NULL; + } + + Py_INCREF (&PartlistType); + if (PyModule_AddObject (module, "Partlist", (PyObject *) &PartlistType) < 0) { + Py_DECREF (&ProbeType); + Py_DECREF (&TopologyType); + Py_DECREF (&PartlistType); + Py_DECREF (module); + return NULL; + } + + Py_INCREF (&ParttableType); + if (PyModule_AddObject (module, "Parttable", (PyObject *) &ParttableType) < 0) { + Py_DECREF (&ProbeType); + Py_DECREF (&TopologyType); + Py_DECREF (&PartlistType); + Py_DECREF (&ParttableType); + Py_DECREF (module); + return NULL; + } + + Py_INCREF (&PartitionType); + if (PyModule_AddObject (module, "Partition", (PyObject *) &PartitionType) < 0) { + Py_DECREF (&ProbeType); + Py_DECREF (&TopologyType); + Py_DECREF (&PartlistType); + Py_DECREF (&ParttableType); + Py_DECREF (&PartitionType); + Py_DECREF (module); + return NULL; + } + + Py_INCREF (&CacheType); + if (PyModule_AddObject (module, "Cache", (PyObject *) &CacheType) < 0) { + Py_DECREF (&ProbeType); + Py_DECREF (&TopologyType); + Py_DECREF (&PartlistType); + Py_DECREF (&ParttableType); + Py_DECREF (&PartitionType); + Py_DECREF (&CacheType); + Py_DECREF (module); + return NULL; + } + + Py_INCREF (&DeviceType); + if (PyModule_AddObject (module, "Device", (PyObject *) &DeviceType) < 0) { + Py_DECREF (&ProbeType); + Py_DECREF (&TopologyType); + Py_DECREF (&PartlistType); + Py_DECREF (&ParttableType); + Py_DECREF (&PartitionType); + Py_DECREF (&CacheType); + Py_DECREF (&DeviceType); + Py_DECREF (module); + return NULL; + } + + return module; +} diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/src/pyblkid.h b/packages/pyblkid/opengnsys-pyblkid-0.3/src/pyblkid.h new file mode 100644 index 0000000..d42bee0 --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/src/pyblkid.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2020 Red Hat, Inc. + * + * 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, see . + * + */ +#ifndef PYBLKID_H +#define PYBLKID_H + +#include + +extern PyMODINIT_FUNC PyInit_blkid (void); + +#endif /* PYBLKID_H */ diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/src/topology.c b/packages/pyblkid/opengnsys-pyblkid-0.3/src/topology.c new file mode 100644 index 0000000..bf74c92 --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/src/topology.c @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2020 Red Hat, Inc. + * + * 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, see . + * + */ + +#include "topology.h" + +#include + +#define UNUSED __attribute__((unused)) + + +PyObject *Topology_new (PyTypeObject *type, PyObject *args UNUSED, PyObject *kwargs UNUSED) { + TopologyObject *self = (TopologyObject*) type->tp_alloc (type, 0); + + return (PyObject *) self; +} + +int Topology_init (TopologyObject *self UNUSED, PyObject *args UNUSED, PyObject *kwargs UNUSED) { + return 0; +} + +void Topology_dealloc (TopologyObject *self) { + Py_TYPE (self)->tp_free ((PyObject *) self); +} + +PyObject *_Topology_get_topology_object (blkid_probe probe) { + TopologyObject *result = NULL; + blkid_topology topology = NULL; + + if (!probe) { + PyErr_SetString(PyExc_RuntimeError, "internal error"); + return NULL; + } + + topology = blkid_probe_get_topology (probe); + if (!topology) { + PyErr_SetString (PyExc_RuntimeError, "Failed to get topology"); + return NULL; + } + + result = PyObject_New (TopologyObject, &TopologyType); + if (!result) { + PyErr_SetString (PyExc_MemoryError, "Failed to create a new Topology object"); + return NULL; + } + Py_INCREF (result); + + result->topology = topology; + + return (PyObject *) result; +} + +static PyObject *Topology_get_alignment_offset (TopologyObject *self, PyObject *Py_UNUSED (ignored)) { + unsigned long alignment_offset = blkid_topology_get_alignment_offset (self->topology); + + return PyLong_FromUnsignedLong (alignment_offset); +} + +static PyObject *Topology_get_logical_sector_size (TopologyObject *self, PyObject *Py_UNUSED (ignored)) { + unsigned long logical_sector_size = blkid_topology_get_logical_sector_size (self->topology); + + return PyLong_FromUnsignedLong (logical_sector_size); +} + +static PyObject *Topology_get_minimum_io_size (TopologyObject *self, PyObject *Py_UNUSED (ignored)) { + unsigned long minimum_io_size = blkid_topology_get_minimum_io_size (self->topology); + + return PyLong_FromUnsignedLong (minimum_io_size); +} + +static PyObject *Topology_get_optimal_io_size (TopologyObject *self, PyObject *Py_UNUSED (ignored)) { + unsigned long optimal_io_size = blkid_topology_get_optimal_io_size (self->topology); + + return PyLong_FromUnsignedLong (optimal_io_size); +} + +static PyObject *Topology_get_physical_sector_size (TopologyObject *self, PyObject *Py_UNUSED (ignored)) { + unsigned long physical_sector_size = blkid_topology_get_physical_sector_size (self->topology); + + return PyLong_FromUnsignedLong (physical_sector_size); +} + +#ifdef HAVE_BLKID_2_36 +static PyObject *Topology_get_dax (TopologyObject *self, PyObject *Py_UNUSED (ignored)) { + int dax = blkid_topology_get_dax (self->topology); + + if (dax == 1) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} +#endif + +#ifdef HAVE_BLKID_2_39 +static PyObject *Topology_get_diskseq (TopologyObject *self, PyObject *Py_UNUSED (ignored)) { + uint64_t diskseq = blkid_topology_get_diskseq (self->topology); + + return PyLong_FromUnsignedLongLong (diskseq); +} +#endif + +static PyGetSetDef Topology_getseters[] = { + {"alignment_offset", (getter) Topology_get_alignment_offset, NULL, "alignment offset in bytes or 0", NULL}, + {"logical_sector_size", (getter) Topology_get_logical_sector_size, NULL, "logical sector size (BLKSSZGET ioctl) in bytes or 0", NULL}, + {"minimum_io_size", (getter) Topology_get_minimum_io_size, NULL, "minimum io size in bytes or 0", NULL}, + {"optimal_io_size", (getter) Topology_get_optimal_io_size, NULL, "optimal io size in bytes or 0", NULL}, + {"physical_sector_size", (getter) Topology_get_physical_sector_size, NULL, "logical sector size (BLKSSZGET ioctl) in bytes or 0", NULL}, +#ifdef HAVE_BLKID_2_36 + {"dax", (getter) Topology_get_dax, NULL, "whether DAX is supported or not", NULL}, +#endif +#ifdef HAVE_BLKID_2_39 + {"diskseq", (getter) Topology_get_diskseq, NULL, "disk sequence number", NULL}, +#endif + {NULL, NULL, NULL, NULL, NULL} +}; + +PyTypeObject TopologyType = { + PyVarObject_HEAD_INIT (NULL, 0) + .tp_name = "blkid.Topology", + .tp_basicsize = sizeof (TopologyObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_new = Topology_new, + .tp_dealloc = (destructor) Topology_dealloc, + .tp_init = (initproc) Topology_init, + .tp_getset = Topology_getseters, +}; diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/src/topology.h b/packages/pyblkid/opengnsys-pyblkid-0.3/src/topology.h new file mode 100644 index 0000000..acd6e83 --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/src/topology.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 Red Hat, Inc. + * + * 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, see . + * + */ +#ifndef TOPOLOGY_H +#define TOPOLOGY_H + +#include + +#include + +typedef struct { + PyObject_HEAD + blkid_topology topology; +} TopologyObject; + +extern PyTypeObject TopologyType; + +PyObject *Topology_new (PyTypeObject *type, PyObject *args, PyObject *kwargs); +int Topology_init (TopologyObject *self, PyObject *args, PyObject *kwargs); +void Topology_dealloc (TopologyObject *self); + +PyObject *_Topology_get_topology_object (blkid_probe probe); + +#endif /* TOPOLOGY_H */ diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/tests/__init__.py b/packages/pyblkid/opengnsys-pyblkid-0.3/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/tests/gpt.img.xz b/packages/pyblkid/opengnsys-pyblkid-0.3/tests/gpt.img.xz new file mode 100644 index 0000000..9a085b4 Binary files /dev/null and b/packages/pyblkid/opengnsys-pyblkid-0.3/tests/gpt.img.xz differ diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/tests/test.img.xz b/packages/pyblkid/opengnsys-pyblkid-0.3/tests/test.img.xz new file mode 100644 index 0000000..7d170e2 Binary files /dev/null and b/packages/pyblkid/opengnsys-pyblkid-0.3/tests/test.img.xz differ diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/tests/test_blkid.py b/packages/pyblkid/opengnsys-pyblkid-0.3/tests/test_blkid.py new file mode 100644 index 0000000..3ee78fa --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/tests/test_blkid.py @@ -0,0 +1,98 @@ +import os +import unittest + +from . import utils + +import blkid + + +class BlkidTestCase(unittest.TestCase): + + test_image = "test.img.xz" + loop_dev = None + + @classmethod + def setUpClass(cls): + test_dir = os.path.abspath(os.path.dirname(__file__)) + cls.loop_dev = utils.loop_setup(os.path.join(test_dir, cls.test_image)) + + @classmethod + def tearDownClass(cls): + if cls.loop_dev: + utils.loop_teardown(cls.loop_dev) + + def test_blkid(self): + self.assertTrue(blkid.known_fstype("ext4")) + self.assertFalse(blkid.known_fstype("not-a-filesystem")) + + self.assertTrue(blkid.known_pttype("dos")) + self.assertFalse(blkid.known_fstype("not-a-partition-table")) + + self.assertEqual(blkid.parse_version_string("2.16.0"), 2160) + + code, version, date = blkid.get_library_version() + self.assertGreater(code, 0) + self.assertIsNotNone(version) + self.assertIsNotNone(date) + + ttype, tvalue = blkid.parse_tag_string("NAME=test") + self.assertEqual(ttype, "NAME") + self.assertEqual(tvalue, "test") + + size = blkid.get_dev_size(self.loop_dev) + self.assertEqual(size, 2097152) # test.img is 2 MiB + + # dos should be always supported so we can use it here to test + if hasattr(blkid, "partition_types"): + types = blkid.partition_types() + self.assertIn("dos", types) + + # ext4 should be always supported so we can use it here to test + supers = blkid.superblocks() + self.assertIn("ext4", supers) + + def test_uevent(self): + with self.assertRaises(RuntimeError): + blkid.send_uevent("not-a-device", "change") + + blkid.send_uevent(self.loop_dev, "change") + + def test_devname(self): + sysfs_path = "/sys/block/%s/dev" % os.path.basename(self.loop_dev) + major_minor = utils.read_file(sysfs_path).strip() + major, minor = major_minor.split(":") + devno = os.makedev(int(major), int(minor)) + + devpath = blkid.devno_to_devname(devno) + self.assertEqual(devpath, self.loop_dev) + + # we don't have a partition so let's just ask for the disk name and devno + (dname, ddevno) = blkid.devno_to_wholedisk(devno) + self.assertEqual(dname, os.path.basename(self.loop_dev)) + self.assertEqual(ddevno, devno) + + def test_safe_encode_string(self): + string = "aaaaaa" + safe_string = blkid.safe_string(string) + encoded_string = blkid.encode_string(string) + self.assertEqual(string, safe_string) + self.assertEqual(string, encoded_string) + + string = "aa aaa" + safe_string = blkid.safe_string(string) + encoded_string = blkid.encode_string(string) + self.assertEqual(safe_string, "aa_aaa") + self.assertEqual(encoded_string, "aa\\x20aaa") + + def test_tags(self): + device = blkid.evaluate_tag("LABEL", "test-ext3") + self.assertEqual(device, self.loop_dev) + + device = blkid.evaluate_tag("LABEL", "definitely-not-a-valid-label") + self.assertIsNone(device) + + device = blkid.evaluate_spec("LABEL=test-ext3") + self.assertEqual(device, self.loop_dev) + + device = blkid.evaluate_spec("LABEL=definitely-not-a-valid-label") + self.assertIsNone(device) diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/tests/test_cache.py b/packages/pyblkid/opengnsys-pyblkid-0.3/tests/test_cache.py new file mode 100644 index 0000000..4923133 --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/tests/test_cache.py @@ -0,0 +1,68 @@ +import os +import unittest +import tempfile + +from . import utils + +import blkid + + +@unittest.skipUnless(os.geteuid() == 0, "requires root access") +class CacheTestCase(unittest.TestCase): + + test_image = "test.img.xz" + loop_dev = None + cache_file = None + + @classmethod + def setUpClass(cls): + test_dir = os.path.abspath(os.path.dirname(__file__)) + cls.loop_dev = utils.loop_setup(os.path.join(test_dir, cls.test_image)) + + _, cls.cache_file = tempfile.mkstemp() + + @classmethod + def tearDownClass(cls): + if cls.loop_dev: + utils.loop_teardown(cls.loop_dev) + + if cls.cache_file: + os.remove(cls.cache_file) + + def test_cache(self): + cache = blkid.Cache(filename=self.cache_file) + cache.probe_all() + cache.probe_all(removable=True) + cache.gc() + + device = cache.get_device(self.loop_dev) + self.assertIsNotNone(device) + self.assertEqual(device.devname, self.loop_dev) + + device = cache.find_device("LABEL", "not-in-cache") + self.assertIsNone(device) + + device = cache.find_device("LABEL", "test-ext3") + self.assertIsNotNone(device) + self.assertEqual(device.devname, self.loop_dev) + + self.assertIsNotNone(device.tags) + self.assertIn("UUID", device.tags.keys()) + self.assertEqual(device.tags["UUID"], "35f66dab-477e-4090-a872-95ee0e493ad6") + self.assertIn("LABEL", device.tags.keys()) + self.assertEqual(device.tags["LABEL"], "test-ext3") + self.assertIn("TYPE", device.tags.keys()) + self.assertEqual(device.tags["TYPE"], "ext3") + + self.assertTrue(cache.devices) + self.assertIn(self.loop_dev, [d.devname for d in cache.devices]) + + device.verify() + self.assertIsNotNone(device) + self.assertEqual(device.devname, self.loop_dev) + + # we don't have new devices, so just a sanity check + cache.probe_all(new_only=True) + +if __name__ == "__main__": + unittest.main() diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/tests/test_partitions.py b/packages/pyblkid/opengnsys-pyblkid-0.3/tests/test_partitions.py new file mode 100644 index 0000000..8984522 --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/tests/test_partitions.py @@ -0,0 +1,140 @@ +import os +import unittest + +from . import utils + +import blkid + + +@unittest.skipUnless(os.geteuid() == 0, "requires root access") +class PartitionsTestCase(unittest.TestCase): + + test_image = "gpt.img.xz" + loop_dev = None + + @classmethod + def setUpClass(cls): + test_dir = os.path.abspath(os.path.dirname(__file__)) + cls.loop_dev = utils.loop_setup(os.path.join(test_dir, cls.test_image)) + + @classmethod + def tearDownClass(cls): + if cls.loop_dev: + utils.loop_teardown(cls.loop_dev) + + def test_partlist(self): + pr = blkid.Probe() + pr.set_device(self.loop_dev) + + pr.enable_partitions(True) + + ret = pr.do_safeprobe() + self.assertTrue(ret) + + plist = pr.partitions + self.assertEqual(plist.numof_partitions, 5) + + def test_partitions_filter(self): + pr = blkid.Probe() + pr.set_device(self.loop_dev) + + pr.enable_partitions(True) + + ret = pr.do_safeprobe() + self.assertTrue(ret) + self.assertEqual(pr.partitions.numof_partitions, 5) + + pr.filter_partitions_type(blkid.FLTR_ONLYIN, ["gpt"]) + ret = pr.do_safeprobe() + self.assertTrue(ret) + self.assertEqual(pr.partitions.numof_partitions, 5) + + pr.filter_partitions_type(blkid.FLTR_ONLYIN, ["gpt", "dos"]) + ret = pr.do_safeprobe() + self.assertTrue(ret) + self.assertEqual(pr.partitions.numof_partitions, 5) + + pr.filter_partitions_type(blkid.FLTR_NOTIN, ["gpt"]) + ret = pr.do_safeprobe() + self.assertFalse(ret) + with self.assertRaises(RuntimeError): + pr.partitions + + pr.invert_partitions_filter() + ret = pr.do_safeprobe() + self.assertTrue(ret) + self.assertEqual(pr.partitions.numof_partitions, 5) + + pr.filter_partitions_type(blkid.FLTR_NOTIN, ["gpt"]) + ret = pr.do_safeprobe() + self.assertFalse(ret) + with self.assertRaises(RuntimeError): + pr.partitions + + pr.reset_partitions_filter() + ret = pr.do_safeprobe() + self.assertTrue(ret) + self.assertEqual(pr.partitions.numof_partitions, 5) + + def test_partition_table(self): + pr = blkid.Probe() + pr.set_device(self.loop_dev) + + pr.enable_partitions(True) + + ret = pr.do_safeprobe() + self.assertTrue(ret) + + self.assertIsNotNone(pr.partitions) + self.assertIsNotNone(pr.partitions.table) + + self.assertEqual(pr.partitions.table.type, "gpt") + self.assertEqual(pr.partitions.table.id, "dd27f98d-7519-4c9e-8041-f2bfa7b1ef61") + self.assertEqual(pr.partitions.table.offset, 512) + + nested = pr.partitions.table.get_parent() + self.assertIsNone(nested) + + def test_partition(self): + pr = blkid.Probe() + pr.set_device(self.loop_dev) + + pr.enable_partitions(True) + + ret = pr.do_safeprobe() + self.assertTrue(ret) + + self.assertIsNotNone(pr.partitions) + + part = pr.partitions.get_partition(0) + self.assertEqual(part.type, 0) + self.assertEqual(part.type_string, "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7") + self.assertEqual(part.uuid, "1dcf10bc-637e-4c52-8203-087ae10a820b") + self.assertTrue(part.is_primary) + self.assertFalse(part.is_extended) + self.assertFalse(part.is_logical) + self.assertEqual(part.name, "ThisIsName") + self.assertEqual(part.flags, 0) + self.assertEqual(part.partno, 1) + self.assertEqual(part.start, 34) + self.assertEqual(part.size, 2014) + + if not hasattr(pr.partitions, "get_partition_by_partno"): + return + + part = pr.partitions.get_partition_by_partno(1) + self.assertEqual(part.uuid, "1dcf10bc-637e-4c52-8203-087ae10a820b") + + # no nested partition table here, just the gpt + table = part.table + self.assertEqual(table.type, "gpt") + + # devno_to_part + disk_name = os.path.basename(self.loop_dev) + sysfs_path = "/sys/block/%s/%s/dev" % (disk_name, disk_name + "p" + str(part.partno)) + major_minor = utils.read_file(sysfs_path).strip() + major, minor = major_minor.split(":") + devno = os.makedev(int(major), int(minor)) + + part = pr.partitions.devno_to_partition(devno) + self.assertEqual(part.uuid, "1dcf10bc-637e-4c52-8203-087ae10a820b") diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/tests/test_probe.py b/packages/pyblkid/opengnsys-pyblkid-0.3/tests/test_probe.py new file mode 100644 index 0000000..bee8bd9 --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/tests/test_probe.py @@ -0,0 +1,292 @@ +import os +import unittest + +from . import utils + +import blkid + + +@unittest.skipUnless(os.geteuid() == 0, "requires root access") +class ProbeTestCase(unittest.TestCase): + + test_image = "test.img.xz" + loop_dev = None + + @classmethod + def setUpClass(cls): + test_dir = os.path.abspath(os.path.dirname(__file__)) + cls.loop_dev = utils.loop_setup(os.path.join(test_dir, cls.test_image)) + + cls.ver_code, _version, _date = blkid.get_library_version() + + @classmethod + def tearDownClass(cls): + if cls.loop_dev: + utils.loop_teardown(cls.loop_dev) + + def test_probe(self): + pr = blkid.Probe() + pr.set_device(self.loop_dev) + + self.assertEqual(pr.offset, 0) + self.assertEqual(pr.sectors, 4096) + self.assertEqual(pr.sector_size, 512) + self.assertEqual(pr.size, pr.sectors * pr.sector_size) + + self.assertGreater(pr.fd, 0) + self.assertNotEqual(pr.devno, 0) + self.assertNotEqual(pr.wholedisk_devno, 0) + + self.assertTrue(pr.is_wholedisk) + + if self.ver_code >= 2300: + pr.sector_size = 4096 + self.assertEqual(pr.sector_size, 4096) + else: + with self.assertRaises(AttributeError): + pr.sector_size = 4096 + + pr.reset_probe() + + def test_probing(self): + pr = blkid.Probe() + + with self.assertRaises(ValueError): + pr.do_probe() + + pr.set_device(self.loop_dev) + + pr.enable_superblocks(True) + pr.set_superblocks_flags(blkid.SUBLKS_TYPE | blkid.SUBLKS_USAGE | blkid.SUBLKS_MAGIC) + + ret = pr.do_probe() + self.assertTrue(ret) + + usage = pr.lookup_value("USAGE") + self.assertEqual(usage, b"filesystem") + + pr.step_back() + ret = pr.do_probe() + self.assertTrue(ret) + + usage = pr.lookup_value("USAGE") + self.assertEqual(usage, b"filesystem") + + if hasattr(pr, "reset_buffers"): + pr.reset_buffers() + + pr.step_back() + ret = pr.do_probe() + self.assertTrue(ret) + + usage = pr.lookup_value("USAGE") + self.assertEqual(usage, b"filesystem") + + if hasattr(pr, "hide_range"): + offset = pr.lookup_value("SBMAGIC_OFFSET") + magic = pr.lookup_value("SBMAGIC") + pr.hide_range(int(offset), len(magic)) + + pr.step_back() + ret = pr.do_probe() + self.assertFalse(ret) + + with self.assertRaises(RuntimeError): + usage = pr.lookup_value("USAGE") + + def test_safe_probing(self): + pr = blkid.Probe() + pr.set_device(self.loop_dev) + + pr.enable_superblocks(True) + pr.set_superblocks_flags(blkid.SUBLKS_TYPE | blkid.SUBLKS_USAGE | blkid.SUBLKS_UUID) + + # not probed yet, len should be 0 + self.assertEqual(len(pr), 0) + self.assertFalse(pr.keys()) + self.assertFalse(pr.values()) + self.assertFalse(pr.items()) + + ret = pr.do_safeprobe() + self.assertTrue(ret) + + # three or more items should be in the probe now + self.assertGreaterEqual(len(pr), 3) + + usage = pr.lookup_value("USAGE") + self.assertEqual(usage, b"filesystem") + + usage = pr["USAGE"] + self.assertEqual(usage, b"filesystem") + + fstype = pr.lookup_value("TYPE") + self.assertEqual(fstype, b"ext3") + + fstype = pr["TYPE"] + self.assertEqual(fstype, b"ext3") + + fsuuid = pr.lookup_value("UUID") + self.assertEqual(fsuuid, b"35f66dab-477e-4090-a872-95ee0e493ad6") + + fsuuid = pr["UUID"] + self.assertEqual(fsuuid, b"35f66dab-477e-4090-a872-95ee0e493ad6") + + keys = pr.keys() + self.assertIn("USAGE", keys) + self.assertIn("TYPE", keys) + self.assertIn("UUID", keys) + + values = pr.values() + self.assertIn("filesystem", values) + self.assertIn("ext3", values) + self.assertIn("35f66dab-477e-4090-a872-95ee0e493ad6", values) + + items = pr.items() + self.assertIn(("USAGE", "filesystem"), items) + self.assertIn(("TYPE", "ext3"), items) + self.assertIn(("UUID", "35f66dab-477e-4090-a872-95ee0e493ad6"), items) + + def test_probe_filter_type(self): + pr = blkid.Probe() + pr.set_device(self.loop_dev) + + pr.enable_superblocks(True) + pr.set_superblocks_flags(blkid.SUBLKS_TYPE | blkid.SUBLKS_USAGE | blkid.SUBLKS_UUID) + + pr.filter_superblocks_type(blkid.FLTR_ONLYIN, ["ext3", "ext4"]) + ret = pr.do_safeprobe() + self.assertTrue(ret) + + fstype = pr.lookup_value("TYPE") + self.assertEqual(fstype, b"ext3") + + pr.filter_superblocks_type(blkid.FLTR_NOTIN, ["ext3", "ext4"]) + ret = pr.do_safeprobe() + self.assertFalse(ret) + + with self.assertRaises(RuntimeError): + fstype = pr.lookup_value("TYPE") + + pr.filter_superblocks_type(blkid.FLTR_NOTIN, ["vfat", "ntfs"]) + ret = pr.do_safeprobe() + self.assertTrue(ret) + + fstype = pr.lookup_value("TYPE") + self.assertEqual(fstype, b"ext3") + + # invert the filter + pr.invert_superblocks_filter() + ret = pr.do_safeprobe() + self.assertFalse(ret) + + with self.assertRaises(RuntimeError): + fstype = pr.lookup_value("TYPE") + + # reset to default + pr.reset_superblocks_filter() + ret = pr.do_safeprobe() + self.assertTrue(ret) + + fstype = pr.lookup_value("TYPE") + self.assertEqual(fstype, b"ext3") + + def test_probe_filter_usage(self): + pr = blkid.Probe() + pr.set_device(self.loop_dev) + + pr.enable_superblocks(True) + pr.set_superblocks_flags(blkid.SUBLKS_TYPE | blkid.SUBLKS_USAGE | blkid.SUBLKS_UUID) + + pr.filter_superblocks_usage(blkid.FLTR_ONLYIN, blkid.USAGE_FILESYSTEM) + pr.do_safeprobe() + + usage = pr.lookup_value("USAGE") + self.assertEqual(usage, b"filesystem") + + pr.filter_superblocks_usage(blkid.FLTR_NOTIN, blkid.USAGE_FILESYSTEM | blkid.USAGE_CRYPTO) + pr.do_safeprobe() + + with self.assertRaises(RuntimeError): + usage = pr.lookup_value("USAGE") + + pr.filter_superblocks_usage(blkid.FLTR_NOTIN, blkid.USAGE_RAID | blkid.USAGE_CRYPTO) + pr.do_safeprobe() + + usage = pr.lookup_value("USAGE") + self.assertEqual(usage, b"filesystem") + + # invert the filter + pr.invert_superblocks_filter() + pr.do_safeprobe() + + with self.assertRaises(RuntimeError): + usage = pr.lookup_value("USAGE") + + # reset to default + pr.reset_superblocks_filter() + pr.do_safeprobe() + + usage = pr.lookup_value("USAGE") + self.assertEqual(usage, b"filesystem") + + def test_topology(self): + pr = blkid.Probe() + pr.set_device(self.loop_dev) + + pr.enable_superblocks(True) + pr.set_superblocks_flags(blkid.SUBLKS_TYPE | blkid.SUBLKS_USAGE | blkid.SUBLKS_UUID) + + pr.enable_topology(True) + + ret = pr.do_safeprobe() + self.assertTrue(ret) + + self.assertIsNotNone(pr.topology) + + self.assertEqual(pr.topology.alignment_offset, 0) + self.assertEqual(pr.topology.logical_sector_size, 512) + self.assertEqual(pr.topology.minimum_io_size, 512) + self.assertEqual(pr.topology.optimal_io_size, 0) + self.assertEqual(pr.topology.physical_sector_size, 512) + + if self.ver_code >= 2360: + self.assertFalse(pr.topology.dax) + else: + with self.assertRaises(AttributeError): + self.assertIsNone(pr.topology.dax) + + +@unittest.skipUnless(os.geteuid() == 0, "requires root access") +class WipeTestCase(unittest.TestCase): + + test_image = "test.img.xz" + loop_dev = None + + def setUp(self): + test_dir = os.path.abspath(os.path.dirname(__file__)) + self.loop_dev = utils.loop_setup(os.path.join(test_dir, self.test_image)) + + def tearDown(self): + test_dir = os.path.abspath(os.path.dirname(__file__)) + if self.loop_dev: + utils.loop_teardown(self.loop_dev, + filename=os.path.join(test_dir, self.test_image)) + + def test_wipe(self): + pr = blkid.Probe() + pr.set_device(self.loop_dev, flags=os.O_RDWR) + + pr.enable_superblocks(True) + pr.set_superblocks_flags(blkid.SUBLKS_TYPE | blkid.SUBLKS_USAGE | blkid.SUBLKS_MAGIC) + + while pr.do_probe(): + pr.do_wipe(False) + + pr.reset_probe() + + ret = pr.do_probe() + self.assertFalse(ret) + + +if __name__ == "__main__": + unittest.main() diff --git a/packages/pyblkid/opengnsys-pyblkid-0.3/tests/utils.py b/packages/pyblkid/opengnsys-pyblkid-0.3/tests/utils.py new file mode 100644 index 0000000..668f73e --- /dev/null +++ b/packages/pyblkid/opengnsys-pyblkid-0.3/tests/utils.py @@ -0,0 +1,43 @@ +import os +import subprocess + + +def run_command(command): + res = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + + out, err = res.communicate() + if res.returncode != 0: + output = out.decode().strip() + "\n\n" + err.decode().strip() + else: + output = out.decode().strip() + return (res.returncode, output) + + +def read_file(filename): + with open(filename, "r") as f: + content = f.read() + return content + + +def loop_setup(filename): + if filename.endswith(".xz") and not os.path.exists(filename[:-3]): + ret, out = run_command("xz --decompress --keep %s" % filename) + if ret != 0: + raise RuntimeError("Failed to decompress file %s: %s" % (filename, out)) + filename = filename[:-3] + + ret, out = run_command("losetup --show --partscan -f %s" % filename) + if ret != 0: + raise RuntimeError("Failed to create loop device from %s: %s" % (filename, out)) + return out + + +def loop_teardown(loopdev, filename=None): + ret, out = run_command("losetup -d %s" % loopdev) + if ret != 0: + raise RuntimeError("Failed to detach loop device %s: %s" % (loopdev, out)) + + # remove the extracted test file + if filename and filename.endswith(".xz") and os.path.exists(filename[:-3]): + os.remove(filename[:-3]) diff --git a/packages/pyblkid/opengnsys-pyblkid_0.3.orig.tar.xz b/packages/pyblkid/opengnsys-pyblkid_0.3.orig.tar.xz new file mode 100644 index 0000000..a9b34c7 Binary files /dev/null and b/packages/pyblkid/opengnsys-pyblkid_0.3.orig.tar.xz differ