├── .SRCINFO ├── Interface.h ├── LICENSE ├── Makefile ├── PKGBUILD ├── README ├── TODO ├── actions.c ├── ala.c ├── arm.c ├── cJSON.c ├── cJSON.h ├── main.c └── variables.h /.SRCINFO: -------------------------------------------------------------------------------- 1 | # Generated by mksrcinfo v8 2 | # Thu Dec 31 14:16:44 UTC 2015 3 | pkgbase = downgrader 4 | pkgdesc = Powerful packages downgrader for Archlinux. Works with libalpm, ARM and pacman logs 5 | pkgver = 1.8.0 6 | pkgrel = 3 7 | url = https://github.com/DimaSmirnov/Archlinux-downgrader 8 | arch = i686 9 | arch = x86_64 10 | license = GPL 11 | optdepends = sudo: for installation via sudo 12 | source = downgrader-1.8.0::http://www.igus.lv/downgrader/downgrader.tar.xz 13 | 14 | pkgname = downgrader 15 | 16 | -------------------------------------------------------------------------------- /Interface.h: -------------------------------------------------------------------------------- 1 | void ShowHelpWindow() { 2 | printf("\nDowngrader, version %s\n",VERSION); 3 | printf(" usage: downgrader [ -h ] [-q] [ -a ] \n"); 4 | printf(" options:\n"); 5 | printf(" -h \n"); 6 | printf(" -q \n"); 7 | printf(" -a \n"); 8 | } 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | 3 | Version 3, 29 June 2007 4 | 5 | Copyright © 2007 Free Software Foundation, Inc. 6 | 7 | Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The GNU General Public License is a free, copyleft license for software and other kinds of works. 12 | The licenses for most software and other practical works are designed to take away your freedom to share and 13 | change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share 14 | and change all versions of a program--to make sure it remains free software for all its users. We, the Free 15 | Software Foundation, use the GNU General Public License for most of our software; it applies also to any other 16 | work released this way by its authors. You can apply it to your programs, too. 17 | 18 | When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed 19 | to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), 20 | that you receive source code or can get it if you want it, that you can change the software or use pieces of it 21 | in new free programs, and that you know you can do these things. 22 | 23 | To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. 24 | Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities 25 | to respect the freedom of others. 26 | 27 | For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the 28 | same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them 29 | these terms so they know their rights. 30 | 31 | Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you 32 | this License giving you legal permission to copy, distribute and/or modify it. 33 | 34 | For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. 35 | For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems 36 | will not be attributed erroneously to authors of previous versions. 37 | 38 | Some devices are designed to deny users access to install or run modified versions of the software inside them, although 39 | the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the 40 | software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely 41 | where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those 42 | products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains 43 | in future versions of the GPL, as needed to protect the freedom of users. 44 | 45 | Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development 46 | and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents 47 | applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be 48 | used to render the program non-free. 49 | 50 | The precise terms and conditions for copying, distribution and modification follow. 51 | 52 | TERMS AND CONDITIONS 53 | 54 | 0. Definitions. 55 | “This License” refers to version 3 of the GNU General Public License. 56 | 57 | “Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. 58 | 59 | “The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. 60 | “Licensees” and “recipients” may be individuals or organizations. 61 | 62 | To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, 63 | other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a 64 | work “based on” the earlier work. 65 | 66 | A “covered work” means either the unmodified Program or a work based on the Program. 67 | 68 | To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily 69 | liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. 70 | Propagation includes copying, distribution (with or without modification), making available to the public, and in some 71 | countries other activities as well. 72 | 73 | To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction 74 | with a user through a computer network, with no transfer of a copy, is not conveying. 75 | 76 | An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and 77 | prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is 78 | no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under 79 | this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such 80 | as a menu, a prominent item in the list meets this criterion. 81 | 82 | 1. Source Code. 83 | The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any 84 | non-source form of a work. 85 | 86 | A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, 87 | in the case of interfaces specified for a particular programming language, one that is widely used among developers working 88 | in that language. 89 | 90 | The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the 91 | normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use 92 | of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the 93 | public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, 94 | and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, 95 | or an object code interpreter used to run it. 96 | 97 | The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an 98 | executable work) run the object code and to modify the work, including scripts to control those activities. However, it does 99 | not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified 100 | in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition 101 | files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that 102 | the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and 103 | other parts of the work. 104 | 105 | The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding 106 | Source. 107 | 108 | The Corresponding Source for a work in source code form is that same work. 109 | 110 | 2. Basic Permissions. 111 | All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the 112 | stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output 113 | from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This 114 | License acknowledges your rights of fair use or other equivalent, as provided by copyright law. 115 | 116 | You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise 117 | remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively 118 | for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in 119 | conveying all material for which you do not control copyright. Those thus making or running the covered works for you must 120 | do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of 121 | your copyrighted material outside their relationship with you. 122 | 123 | Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; 124 | section 10 makes it unnecessary. 125 | 126 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 127 | No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations 128 | under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention 129 | of such measures. 130 | 131 | When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent 132 | such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim 133 | any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or 134 | third parties' legal rights to forbid circumvention of technological measures. 135 | 136 | 4. Conveying Verbatim Copies. 137 | You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously 138 | and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and 139 | any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; 140 | and give all recipients a copy of this License along with the Program. 141 | 142 | You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 143 | 144 | 5. Conveying Modified Source Versions. 145 | You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under 146 | the terms of section 4, provided that you also meet all of these conditions: 147 | 148 | a) The work must carry prominent notices stating that you modified it, and giving a relevant date. 149 | b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. 150 | This requirement modifies the requirement in section 4 to “keep intact all notices”. 151 | c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License 152 | will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless 153 | of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such 154 | permission if you have separately received it. 155 | d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive 156 | interfaces that do not display Appropriate Legal Notices, your work need not make them do so. 157 | A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered 158 | work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, 159 | is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the 160 | compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License 161 | to apply to the other parts of the aggregate. 162 | 163 | 6. Conveying Non-Source Forms. 164 | You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable 165 | Corresponding Source under the terms of this License, in one of these ways: 166 | 167 | a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the 168 | Corresponding Source fixed on a durable physical medium customarily used for software interchange. 169 | b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written 170 | offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to 171 | give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is 172 | covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your 173 | reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network 174 | server at no charge. 175 | c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative 176 | is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with 177 | subsection 6b. 178 | d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the 179 | Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the 180 | Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source 181 | may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain 182 | clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the 183 | Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. 184 | e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding 185 | Source of the work are being offered to the general public at no charge under subsection 6d. 186 | A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not 187 | be included in conveying the object code work. 188 | 189 | A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, 190 | family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product 191 | is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, 192 | “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the 193 | way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product 194 | regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only 195 | significant mode of use of the product. 196 | 197 | “Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to 198 | install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. 199 | The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered 200 | with solely because modification has been made. 201 | 202 | If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs 203 | as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or 204 | for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be 205 | accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability 206 | to install modified object code on the User Product (for example, the work has been installed in ROM). 207 | 208 | The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or 209 | updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or 210 | installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network 211 | or violates the rules and protocols for communication across the network. 212 | 213 | Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly 214 | documented (and with an implementation available to the public in source code form), and must require no special password or key for 215 | unpacking, reading or copying. 216 | 217 | 7. Additional Terms. 218 | “Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. 219 | Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the 220 | extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used 221 | separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. 222 | 223 | When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of 224 | it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place 225 | additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. 226 | 227 | Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright 228 | holders of that material) supplement the terms of this License with terms: 229 | 230 | a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or 231 | b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal 232 | Notices displayed by works containing it; or 233 | c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in 234 | reasonable ways as different from the original version; or 235 | d) Limiting the use for publicity purposes of names of licensors or authors of the material; or 236 | e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or 237 | f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) 238 | with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on 239 | those licensors and authors. 240 | All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as 241 | you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further 242 | restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under 243 | this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction 244 | does not survive such relicensing or conveying. 245 | 246 | If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the 247 | additional terms that apply to those files, or a notice indicating where to find the applicable terms. 248 | 249 | Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; 250 | the above requirements apply either way. 251 | 252 | 8. Termination. 253 | You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or 254 | modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the 255 | third paragraph of section 11). 256 | 257 | However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, 258 | unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails 259 | to notify you of the violation by some reasonable means prior to 60 days after the cessation. 260 | 261 | Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation 262 | by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright 263 | holder, and you cure the violation prior to 30 days after your receipt of the notice. 264 | 265 | Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you 266 | under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses 267 | for the same material under section 10. 268 | 269 | 9. Acceptance Not Required for Having Copies. 270 | You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered 271 | work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. 272 | However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe 273 | copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance 274 | of this License to do so. 275 | 276 | 10. Automatic Licensing of Downstream Recipients. 277 | Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify 278 | and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. 279 | 280 | An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing 281 | an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that 282 | transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or 283 | could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in 284 | interest, if the predecessor has it or can get it with reasonable efforts. 285 | 286 | You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you 287 | may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate 288 | litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, 289 | selling, offering for sale, or importing the Program or any portion of it. 290 | 291 | 11. Patents. 292 | A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. 293 | The work thus licensed is called the contributor's “contributor version”. 294 | 295 | A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or 296 | hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor 297 | version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. 298 | For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements 299 | of this License. 300 | 301 | Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, 302 | to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. 303 | 304 | In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a 305 | patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent 306 | license to a party means to make such an agreement or commitment not to enforce a patent against the party. 307 | 308 | If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for 309 | anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily 310 | accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of 311 | the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this 312 | License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for 313 | the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would 314 | infringe one or more identifiable patents in that country that you have reason to believe are valid. 315 | 316 | If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a 317 | covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify 318 | or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the 319 | covered work and works based on it. 320 | 321 | A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is 322 | conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a 323 | covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which 324 | you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, 325 | to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of 326 | the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products 327 | or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior 328 | to 28 March 2007. 329 | 330 | Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may 331 | otherwise be available to you under applicable patent law. 332 | 333 | 12. No Surrender of Others' Freedom. 334 | If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, 335 | they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously 336 | your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For 337 | example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, 338 | the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 339 | 340 | 13. Use with the GNU Affero General Public License. 341 | Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed 342 | under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms 343 | of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General 344 | Public License, section 13, concerning interaction through a network will apply to the combination as such. 345 | 346 | 14. Revised Versions of this License. 347 | The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such 348 | new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. 349 | 350 | Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General 351 | Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that 352 | numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version 353 | number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. 354 | 355 | If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's 356 | public statement of acceptance of a version permanently authorizes you to choose that version for the Program. 357 | 358 | Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any 359 | author or copyright holder as a result of your choosing to follow a later version. 360 | 361 | 15. Disclaimer of Warranty. 362 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE 363 | COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, 364 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK 365 | AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL 366 | NECESSARY SERVICING, REPAIR OR CORRECTION. 367 | 368 | 16. Limitation of Liability. 369 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES 370 | AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL 371 | DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED 372 | INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH 373 | HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 374 | 375 | 17. Interpretation of Sections 15 and 16. 376 | If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their 377 | terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection 378 | with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. 379 | 380 | END OF TERMS AND CONDITIONS 381 | 382 | How to Apply These Terms to Your New Programs 383 | 384 | If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is 385 | to make it free software which everyone can redistribute and change under these terms. 386 | 387 | To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most 388 | effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where 389 | the full notice is found. 390 | 391 | 392 | Copyright (C) 393 | 394 | This program is free software: you can redistribute it and/or modify 395 | it under the terms of the GNU General Public License as published by 396 | the Free Software Foundation, either version 3 of the License, or 397 | (at your option) any later version. 398 | 399 | This program is distributed in the hope that it will be useful, 400 | but WITHOUT ANY WARRANTY; without even the implied warranty of 401 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 402 | GNU General Public License for more details. 403 | 404 | You should have received a copy of the GNU General Public License 405 | along with this program. If not, see . 406 | Also add information on how to contact you by electronic and paper mail. 407 | 408 | If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: 409 | 410 | Copyright (C) 411 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 412 | This is free software, and you are welcome to redistribute it 413 | under certain conditions; type `show c' for details. 414 | The hypothetical commands `show w' and `show c' should show the appropriate parts of the 415 | General Public License. Of course, your program's commands might be different; 416 | for a GUI interface, you would use an “about box”. 417 | 418 | You should also get your employer (if you work as a programmer) or school, if any, to 419 | sign a “copyright disclaimer” for the program, if necessary. For more information on this, 420 | and how to apply and follow the GNU GPL, see . 421 | 422 | The GNU General Public License does not permit incorporating your program into 423 | proprietary programs. If your program is a subroutine library, you may consider 424 | it more useful to permit linking proprietary applications with the library. If this is what 425 | you want to do, use the GNU Lesser General Public License instead of this License. But first, 426 | please read . 427 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | downgrader: main.o 2 | g++ main.o cJSON.c -lalpm -lcurl -o downgrader 3 | 4 | main.o: main.c Interface.h ala.c arm.c actions.c variables.h 5 | gcc -g -c main.c -o main.o -std=c99 -Wno-implicit-function-declaration 6 | 7 | install: downgrader 8 | strip -s downgrader 9 | cp downgrader /usr/sbin/downgrader 10 | 11 | -------------------------------------------------------------------------------- /PKGBUILD: -------------------------------------------------------------------------------- 1 | # Author: Dmitriy Smirnov 2 | pkgname=downgrader 3 | pkgver=2.0.0 4 | pkgrel=3 5 | pkgdesc="Powerful packages downgrader for Archlinux. Works with libalpm, ARM and pacman logs" 6 | arch=('i686' 'x86_64') 7 | license=("GPL") 8 | _gitname=Archlinux-downgrader 9 | 10 | url="https://github.com/DimaSmirnov/Archlinux-downgrader" 11 | source=("git://github.com/DimaSmirnov/Archlinux-downgrader.git") 12 | md5sums=('SKIP') 13 | 14 | # install=$pkgname.install 15 | 16 | build() { 17 | cd $_gitname 18 | make 19 | } 20 | 21 | package() { 22 | cd $_gitname 23 | install -D -m755 downgrader "$pkgdir/usr/bin/downgrader" 24 | } 25 | 26 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Powerful package for Arch Linux distribution, powered by libalpm. Helps to downgrade packages, if last installed version is unstable. Works with Cache, ALA, ARM and pacman logs. 2 | 3 | AUR package: https://aur.archlinux.org/packages/downgrader/ 4 | 5 | --- LICENSE --- 6 | This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 7 | This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 8 | You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. 9 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | 1. Multiple packages downgrade 2 | 2. History of downgrading 3 | -------------------------------------------------------------------------------- /actions.c: -------------------------------------------------------------------------------- 1 | int DowngradePackage( char *package) { 2 | 3 | int isincache = IsPackageInLogs(package); // Here also parsing pacman.log and using flag actions.package_never_upgraded 4 | if (isincache) { 5 | if (!silent) { sprintf(tmp_string, "Downgrading from Cache, to version %s\n",install_version); dgr_output(tmp_string); } 6 | system(install_command); 7 | return 0; 8 | } 9 | strcpy(install_version,installed_pkg_ver); 10 | if (WITH_ALA) { 11 | int showpkgs = PrepareView(package); 12 | int i=1; 13 | //sprintf(tmp_string, "%d: %s-%s %s\n", i+1, user_pkgs[i].name, user_pkgs[i].version, user_pkgs[i].repo); dgr_output(tmp_string); 14 | if (!silent) { sprintf(tmp_string, "Downgrade %s from ALA to version %s\n", package,user_pkgs[i].version); dgr_output(tmp_string); } 15 | strcpy(install_command,"sudo pacman -U "); strcat(install_command,user_pkgs[i].link); 16 | //printf("%s\n", install_command); //DEBUG 17 | system(install_command); 18 | return 0; 19 | } 20 | if (WITH_ARM) { 21 | ret = IsPackageInArm(package, install_version); 22 | if (arm_pkgs[ret].link) { 23 | if (!silent) { sprintf(tmp_string, "Downgrade %s from ARM to version %s\n", package,arm_pkgs[ret+2].version); dgr_output(tmp_string); } 24 | strcpy(install_command,"sudo pacman -U "); strcat(install_command,arm_pkgs[ret+2].link); 25 | system(install_command); 26 | return 0; 27 | } 28 | } 29 | return 1; 30 | } 31 | char* GetChoiseForPackage( char *package) { 32 | 33 | int showpkgs = PrepareView(package); // Готовим массив со списком пакетов для отображения пользователю 34 | 35 | for (int i=0;i> Please enter package number, [q] to quit "); 42 | scanf ("%s",tmp_string); 43 | return tmp_string; 44 | } 45 | int IsPackageAvailable(char *package) { 46 | alpm_siglevel_t siglevel=0; 47 | 48 | db = alpm_register_syncdb(alpm_handle, "core", siglevel); 49 | pkg = alpm_db_get_pkg(db,(const char*)package); 50 | const char *pkgr= alpm_pkg_get_url(pkg); 51 | if (pkgr) { int i = IsPackageInstalled(package); if (i==1) { installed_pkg_ver = alpm_pkg_get_version(pkg); 52 | //printf ("1. installed_pkg_ver: %s\n", installed_pkg_ver); //DEBUG 53 | return 0; } else return 1; } 54 | db = alpm_register_syncdb(alpm_handle, "extra", siglevel); 55 | pkg = alpm_db_get_pkg(db,(const char*)package); 56 | pkgr= alpm_pkg_get_url(pkg); 57 | if (pkgr) { int i = IsPackageInstalled(package); if (i==1) { installed_pkg_ver = alpm_pkg_get_version(pkg); 58 | //printf ("2. installed_pkg_ver: %s\n", installed_pkg_ver); //DEBUG 59 | return 0; } else return 1; } 60 | db = alpm_register_syncdb(alpm_handle, "community", siglevel); 61 | pkg = alpm_db_get_pkg(db,(const char*)package); 62 | pkgr= alpm_pkg_get_url(pkg); 63 | if (pkgr) { int i = IsPackageInstalled(package); if (i==1) { installed_pkg_ver = alpm_pkg_get_version(pkg); 64 | //printf ("3. installed_pkg_ver: %s\n", installed_pkg_ver); //DEBUG 65 | return 0; } else return 1; } 66 | db = alpm_register_syncdb(alpm_handle, "multilib", siglevel); 67 | pkg = alpm_db_get_pkg(db,(const char*)package); 68 | pkgr= alpm_pkg_get_url(pkg); 69 | if (pkgr) { int i = IsPackageInstalled(package); if (i==1) { installed_pkg_ver = alpm_pkg_get_version(pkg); 70 | //printf ("4. installed_pkg_ver: %s\n", installed_pkg_ver); //DEBUG 71 | return 0; } else return 1; } 72 | return 2; 73 | 74 | // return 0 - pkg available 75 | // return 1 - pkg not installed 76 | // return 2 - wrong pkg name 77 | } 78 | 79 | int IsPackageInstalled(char *package) { 80 | 81 | db = alpm_get_localdb(alpm_handle); 82 | pkg = alpm_db_get_pkg(db,(const char*)package); 83 | if (alpm_pkg_get_name(pkg)) return 1; 84 | else return 0; 85 | } 86 | 87 | int PrepareView(char *package) { 88 | int cntr=0; 89 | 90 | counter--; 91 | user_pkgs = realloc(user_pkgs, (pkgsinala+2+pkgsinarm)*sizeof(struct user_packs)); 92 | //printf ("installed_pkg_ver: %s\n", installed_pkg_ver); //DEBUG 93 | //sprintf(tmp_string, "counter: %d\n",counter); dgr_output(tmp_string); // DEBUG 94 | 95 | if (WITH_ALA && pkgsinala) { // Создаем список пакетов для вывода по ALA 96 | while (counter) { 97 | //printf ("::: ala_pkgs[counter].version: %s\n", ala_pkgs[counter].version); //DEBUG 98 | strcpy(user_pkgs[cntr].name,ala_pkgs[counter].name); 99 | strcpy(user_pkgs[cntr].version,ala_pkgs[counter].version); 100 | 101 | sprintf(tmp_string,"%s-%s", user_pkgs[cntr].name, user_pkgs[cntr].version); 102 | ret = IsPackageInCache(tmp_string); 103 | //printf ("user_pkgs[cntr].version: %s", user_pkgs[cntr].version); //DEBUG 104 | 105 | if (!strcmp(user_pkgs[cntr].version, installed_pkg_ver)) { 106 | strcpy(user_pkgs[cntr].link,ala_pkgs[counter].full_path); 107 | strcpy(user_pkgs[cntr].repo," [installed]"); 108 | } 109 | else if (ret==1) { 110 | strcpy(user_pkgs[cntr].link,full_path_to_packet); 111 | strcpy(user_pkgs[cntr].repo," (from cache)"); 112 | } 113 | else { 114 | strcpy(user_pkgs[cntr].link,ala_pkgs[counter].full_path); 115 | strcpy(user_pkgs[cntr].repo," (from ALA)"); 116 | } 117 | cntr++; 118 | counter--; 119 | } 120 | } 121 | if (WITH_ARM && pkgsinarm) { // Создаем список пакетов для вывода по ARM 122 | while (pkgsinarm) { 123 | strcpy(user_pkgs[cntr].name,arm_pkgs[cntr].name); 124 | strcpy(user_pkgs[cntr].version,arm_pkgs[cntr].version); 125 | 126 | sprintf(tmp_string,"%s-%s", user_pkgs[cntr].name, user_pkgs[cntr].version); 127 | ret = IsPackageInCache(tmp_string); 128 | if (!strcmp(user_pkgs[cntr].version, installed_pkg_ver)) { 129 | if (ret==1) strcpy(user_pkgs[cntr].link,full_path_to_packet); 130 | else strcpy(user_pkgs[cntr].link,ala_pkgs[cntr].full_path); 131 | strcpy(user_pkgs[cntr].repo," [installed]"); 132 | } 133 | else if (ret==1) { 134 | strcpy(user_pkgs[cntr].link,full_path_to_packet); 135 | strcpy(user_pkgs[cntr].repo," (from cache)"); 136 | } 137 | else { 138 | strcpy(user_pkgs[cntr].link,arm_pkgs[cntr].full_path); 139 | strcpy(user_pkgs[cntr].repo," (from ARM)"); 140 | } 141 | cntr++; 142 | } 143 | } 144 | return cntr-1; 145 | } 146 | 147 | int IsPackageInLogs(char *package) { 148 | 149 | for (;pacmanlog_length>0;pacmanlog_length--) { 150 | if (!strcmp(package,pkgs[pacmanlog_length].name) && !strcmp("upgraded",pkgs[pacmanlog_length].action)) { // found necessary package 151 | if (strcmp(pkgs[pacmanlog_length].cur_version, pkgs[pacmanlog_length].prev_version)) { // if the same version - search next 152 | strcpy (full_path_to_packet,"/var/cache/pacman/pkg/"); 153 | strcat (full_path_to_packet,package); 154 | strcat (full_path_to_packet,"-"); 155 | strcat (full_path_to_packet,pkgs[pacmanlog_length].prev_version); 156 | strcat (full_path_to_packet,"-"); 157 | strcat (full_path_to_packet,architecture); 158 | strcat (full_path_to_packet,".pkg.tar.xz"); 159 | //printf("full_path_to_packet: %s\n",full_path_to_packet); //DEBUG 160 | break; // Package upgraded at least 1 time 161 | } 162 | } 163 | } 164 | //printf("1: %s\n",full_path_to_packet); //DEBUG 165 | strcpy(install_version,pkgs[pacmanlog_length].prev_version); 166 | 167 | ptr = full_path_to_packet; 168 | i_com = str_replace(ptr,":","%3A"); 169 | strcpy(full_path_to_packet,i_com); // unescape symbol ":" for pkg "go" for example 170 | 171 | if(access(full_path_to_packet, F_OK) != -1) { // previous version available in cache 172 | strcpy(tmp_string,"sudo pacman -U "); // install 173 | strcat(tmp_string,full_path_to_packet); 174 | strcpy(install_command,tmp_string); 175 | //printf("install_command: %s\n",install_command); //DEBUG 176 | return 1; 177 | } 178 | else return 0; 179 | } 180 | 181 | int IsPackageInCache(char *package) { 182 | 183 | sprintf(full_path_to_packet,"/var/cache/pacman/pkg/%s-%s.pkg.tar.xz", package, architecture); 184 | 185 | ptr = full_path_to_packet; 186 | i_com = str_replace(ptr,":","%3A"); 187 | strcpy(full_path_to_packet,i_com); // unescape symbol ":" for pkg "go" for example 188 | //printf("%s\n",full_path_to_packet); //DEBUG 189 | 190 | if(access(full_path_to_packet, F_OK) != -1) { return 1; }// package in cache 191 | else return 0; 192 | } 193 | 194 | size_t curl_handler(char *data, size_t size, size_t nmemb, void *userp) { 195 | 196 | size_t realsize = size * nmemb; 197 | struct curl_MemoryStruct *mem = (struct curl_MemoryStruct *)userp; 198 | mem->memory = realloc(mem->memory, mem->size + realsize + 1); 199 | memcpy(&(mem->memory[mem->size]), data, realsize); 200 | mem->size += realsize; 201 | mem->memory[mem->size] = 0; 202 | return realsize; 203 | } 204 | 205 | int IsPackageInAur(char *package) { 206 | 207 | chunk.memory = malloc(1); 208 | chunk.size = 0; 209 | curl_global_init(CURL_GLOBAL_ALL); 210 | curl = curl_easy_init(); 211 | sprintf(tmp_string,"https://aur.archlinux.org/rpc.php?type=search&arg=%s",package); 212 | curl_easy_setopt(curl, CURLOPT_URL, tmp_string); 213 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_handler); 214 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); 215 | curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0"); 216 | result = curl_easy_perform(curl); 217 | if(result != CURLE_OK) { 218 | dgr_output ("Please check you internet connection. AUR reading error\n"); 219 | return -1; // Exit with error 220 | } 221 | //// Parsing AUR response 222 | cJSON *root = cJSON_Parse(chunk.memory); 223 | cJSON *item = cJSON_GetObjectItem(root,"results"); 224 | for (int i=0;ivaluestring; 227 | if (!strcmp(str,package)) return 1; // package in AUR 228 | } 229 | cJSON_Delete(root); 230 | curl_easy_cleanup(curl); 231 | curl_global_cleanup(); 232 | if(chunk.memory) free(chunk.memory); 233 | return 0; // package not in AUR 234 | } 235 | 236 | void ReadPacmanLog() { 237 | char *buff = NULL; 238 | size_t len; 239 | char *date, *time, *operat, *pack_name, *cur_version, *prev_version, *fake; 240 | int i=0; 241 | 242 | loglines_counter=0; 243 | pFile=fopen("/var/log/pacman.log","r"); 244 | while (!feof(pFile)) { // Count lines q-ty in pacman.log 245 | getline(&buff, &len, pFile); 246 | loglines_counter++; 247 | } 248 | rewind(pFile); 249 | pkgs = calloc(1, sizeof(struct packs)); 250 | pkgs = realloc(pkgs, loglines_counter * sizeof(struct packs)); 251 | 252 | loglines_counter=0; 253 | while (!feof(pFile)) { // Count lines q-ty in pacman.log 254 | getline(&buff, &len, pFile); 255 | date = strtok(buff," "); 256 | date++; 257 | time = strtok(NULL,"] "); 258 | fake = strtok(NULL," "); 259 | operat = strtok(NULL," "); 260 | pack_name = strtok(NULL," "); 261 | //printf("Line: %d, operat: %s\n",i, operat); // DEBUG: 262 | if (!operat) continue; 263 | if (!strcmp(operat,"upgraded")) { 264 | //printf("Upgraded: %s, line: %d\n", pack_name, i+1); //DEBUG: 265 | prev_version = strtok(NULL," "); 266 | prev_version++; 267 | cur_version = strtok(NULL," "); 268 | cur_version = strtok(NULL,")"); 269 | strcpy(pkgs[loglines_counter].date,date); 270 | strcpy(pkgs[loglines_counter].time,time); 271 | strcpy(pkgs[loglines_counter].name,pack_name); 272 | strcpy(pkgs[loglines_counter].action,operat); 273 | strcpy(pkgs[loglines_counter].cur_version,cur_version); 274 | strcpy(pkgs[loglines_counter].prev_version,prev_version); 275 | loglines_counter++; 276 | //printf ("date: %s, time: %s, operat: %s, pack_name: %s\n", date, time, operat, pack_name); //DEBUG 277 | } 278 | i++; 279 | } 280 | fclose(pFile); 281 | pacmanlog_length =loglines_counter; 282 | //printf ("pacman log contain %d lines\n", pacmanlog_length); //DEBUG 283 | } 284 | 285 | int dgr_output(char *string) { 286 | printf("%s",string); 287 | 288 | return 0; 289 | } 290 | 291 | int Initialization(char *package) { 292 | 293 | openlog("downgrader", LOG_PID|LOG_CONS, LOG_USER); 294 | alpm_handle = NULL; 295 | alpm_handle = alpm_initialize("/","/var/lib/pacman/",0); 296 | if(!alpm_handle) { dgr_output("Libalpm initialize error!\n"); return 1; } 297 | db = alpm_get_localdb(alpm_handle); 298 | pkg = alpm_db_get_pkg(db,(const char*)package); 299 | pkgname = alpm_pkg_get_name(pkg); 300 | 301 | if(sizeof(void*) == 4) architecture = (char *)"i686"; // architecture of machine 302 | else if (sizeof(void*) == 8) architecture = (char *)"x86_64"; 303 | user_pkgs = calloc(1, sizeof(struct user_packs)); 304 | 305 | ret = IsPackageAvailable(package); 306 | if (ret==2) { // Wrong package name 307 | int ret1 = IsPackageInAur(package); // check AUR 308 | if (ret1>0) { if(!silent) { sprintf(tmp_string, "Package '%s' in AUR. Downgrade impossible.\n", package); dgr_output(tmp_string); return 1; } } 309 | else { if(!silent) { sprintf(tmp_string, "Package '%s' not available. Please check package name\n", package); dgr_output(tmp_string); return 1; } } 310 | } 311 | else if (ret==1) { if(!silent) { sprintf(tmp_string, "Package '%s' not installed.\n", package); dgr_output(tmp_string); return 1; } } 312 | pkgsinala=pkgsinarm=0; 313 | ReadPacmanLog(); 314 | 315 | if (WITH_ALA) { 316 | //dgr_output ("Reading ALA, "); //DEBUG 317 | ala_pkgs = calloc(1, sizeof(struct ala_packs)); 318 | pkgsinala = ReadALA(package); 319 | //printf ("in ALA %d packages\n", pkgsinala); //DEBUG 320 | if (!pkgsinala) dgr_output ("No packages in ALA! Disable\n"); 321 | } 322 | if (WITH_ARM) { 323 | arm_pkgs = calloc(1, sizeof(struct arm_packs)); 324 | pkgsinarm = ReadArm(package); 325 | if (!pkgsinarm) dgr_output ("No packages in ARM! Disable\n"); 326 | } 327 | if (!pkgsinala && !pkgsinarm) { dgr_output ("No source for packages. Terminating\n"); return 1; } 328 | return 0; 329 | } 330 | 331 | int Deinitialization() { 332 | alpm_release(alpm_handle); 333 | free (pkgs); 334 | free (user_pkgs); 335 | if (pkgsinarm) free (arm_pkgs); 336 | if (pkgsinala) free (ala_pkgs); 337 | closelog(); 338 | return 0; 339 | } 340 | 341 | char *str_replace(char *str, char *orig, char *rep) { 342 | static char buffer[4096]; 343 | char *p; 344 | 345 | if(!(p = strstr(str, orig))) return str; 346 | 347 | strncpy(buffer, str, p-str); 348 | buffer[p-str] = '\0'; 349 | sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig)); 350 | 351 | return buffer; 352 | } 353 | -------------------------------------------------------------------------------- /ala.c: -------------------------------------------------------------------------------- 1 | int ReadALA(char *package) { 2 | char substr[2]; 3 | char ala_path[150], tmp_string2[200]; 4 | char *fullpkg, *ptr; 5 | 6 | strcpy(tmp_string,package); 7 | strncpy(substr, package, 1); 8 | substr[1]='\0'; 9 | sprintf (ala_path, "https://archive.archlinux.org/packages/%s/%s/",substr,tmp_string); 10 | strcpy(package,tmp_string); 11 | 12 | chunk.memory = malloc(1); 13 | chunk.size = 0; 14 | curl_global_init(CURL_GLOBAL_ALL); 15 | curl = curl_easy_init(); 16 | curl_easy_setopt(curl, CURLOPT_URL, ala_path); 17 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_handler); 18 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); 19 | result = curl_easy_perform(curl); 20 | if(result != CURLE_OK) { 21 | dgr_output ("Please check you internet connection. ALA reading error\n"); 22 | return -1; // Exit with error 23 | } 24 | curl_easy_cleanup(curl); 25 | curl_global_cleanup(); 26 | pkginala=counter=0; 27 | 28 | str = chunk.memory; 29 | char *pch = strstr(str,tmp_string); 30 | while (pch!=NULL) { pkginala++; pch = strstr(pch+3,tmp_string); } 31 | pkginala = pkginala/2; 32 | ala_pkgs = realloc(ala_pkgs, (pkginala+1)*sizeof(struct ala_packs)); 33 | //sprintf(tmp_string2, "Packages in ALA: %d\n",pkginala); dgr_output(tmp_string2); // DEBUG 34 | if (pkginala<1) return 0; 35 | 36 | str = chunk.memory; 37 | str = strtok(str, "<"); 38 | counter++; 39 | while(str = strtok(NULL, "<")) { 40 | if (strstr(str,"href=") && strstr(str,tmp_string)) { //printf("%d: %s\n",counter, str); // DEBUG 41 | strtok(NULL, "="); fullpkg = strtok(NULL, ">"); 42 | fullpkg++; fullpkg[strlen(fullpkg)-5]='\0'; //printf("%d: %s\n",counter, fullpkg); // DEBUG 43 | if (ptr=strstr(fullpkg,architecture)) { 44 | strcpy(ala_pkgs[counter].full_name,fullpkg); //printf("%d: ala_pkgs[counter].full_name = %s\n",counter, ala_pkgs[counter].full_name); // DEBUG 45 | sprintf(tmp_string2,"%s%s",ala_path, fullpkg); 46 | strcpy(ala_pkgs[counter].full_path,tmp_string2); //printf("%d: ala_pkgs[counter].full_path = %s\n",counter, ala_pkgs[counter].full_path); // DEBUG 47 | int a = strlen(package); strcpy(tmp_string2,fullpkg); tmp_string2[a]='\0'; 48 | strcpy(ala_pkgs[counter].name,tmp_string2); //printf("%d: ala_pkgs[counter].name = %s\n",counter, ala_pkgs[counter].name); // DEBUG 49 | a=ptr-fullpkg; fullpkg[a-1] = '\0'; a = strlen(package); fullpkg = fullpkg+a+1; 50 | 51 | ptr = str_replace(fullpkg,"%3A",":"); // unescape symbol ":" for pkg "go" for example 52 | strcpy(ala_pkgs[counter].version, ptr); //printf("%d: ala_pkgs[counter].version = %s\n",counter, ala_pkgs[counter].version); // DEBUG 53 | 54 | counter++; 55 | } 56 | } 57 | } 58 | return counter; 59 | } 60 | 61 | int IsPackageInAla(char* package, char *version) { 62 | int ala_flag=0; 63 | char t_pack[100]; 64 | 65 | sprintf(t_pack,"%s-%s",package,version); 66 | for(tmpint=0;strlen(ala_pkgs[tmpint].full_name)>0;tmpint++) { 67 | if (strstr(ala_pkgs[tmpint].full_name,t_pack)) { 68 | ala_flag=1; break; 69 | } 70 | } 71 | if (ala_flag==1) return tmpint; // Возвращает номер в массиве ALA 72 | else return 0; // или 0 если пакет не найден 73 | } 74 | 75 | -------------------------------------------------------------------------------- /arm.c: -------------------------------------------------------------------------------- 1 | int ReadArm(char *package) { 2 | int counter; 3 | 4 | chunk.memory = malloc(1); 5 | chunk.size = 0; 6 | curl_global_init(CURL_GLOBAL_ALL); 7 | curl = curl_easy_init(); 8 | sprintf (tmp_string,"http://repo-arm.archlinuxcn.org/search?arch=%s&pkgname=%s",architecture,package); 9 | curl_easy_setopt(curl, CURLOPT_URL, tmp_string); 10 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_handler); 11 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); 12 | result = curl_easy_perform(curl); 13 | if(result != CURLE_OK) { 14 | dgr_output ("Please check you internet connection. ARM reading error\n"); 15 | return -1; // Exit with error 16 | } 17 | curl_easy_cleanup(curl); 18 | curl_global_cleanup(); 19 | counter=0; 20 | str = chunk.memory; 21 | 22 | char *pch = strchr(str,'\n'); 23 | while (pch!=NULL) { counter++; pch=strchr(pch+1,'\n'); } 24 | //sprintf(tmp_string, "1. Packages in ARM: %d (with testing)\n",counter); dgr_output(tmp_string); // DEBUG 25 | arm_pkgs = realloc(arm_pkgs, (counter+1)*sizeof(struct arm_packs)); 26 | pkgsinarm = counter; 27 | if (!pkgsinarm) return 0; 28 | counter=0; 29 | str = chunk.memory; 30 | str = strtok(str, "\n"); 31 | strcpy(arm_pkgs[counter].full_path,str); 32 | counter++; 33 | for (;str = strtok(NULL, "\n"); counter++) { 34 | strcpy(arm_pkgs[counter].full_path,str); 35 | //printf("%d: string: %s\n",counter, arm_pkgs[counter].full_path); // DEBUG 36 | } 37 | counter=0; 38 | int notest_cntr=1; 39 | while (counter0;tmpint++) { 70 | if (strstr(arm_pkgs[tmpint].full_path,t_pack)) { 71 | arm_flag=1; 72 | break; 73 | } 74 | } 75 | if (arm_flag==1) return tmpint; // Возвращает номер в массиве arm 76 | else return 0; // или 0 если пакет не найден 77 | } 78 | -------------------------------------------------------------------------------- /cJSON.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Dave Gamble 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | /* cJSON */ 24 | /* JSON parser in C. */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "cJSON.h" 34 | 35 | static const char *ep; 36 | 37 | const char *cJSON_GetErrorPtr() {return ep;} 38 | 39 | static int cJSON_strcasecmp(const char *s1,const char *s2) 40 | { 41 | if (!s1) return (s1==s2)?0:1;if (!s2) return 1; 42 | for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; 43 | return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); 44 | } 45 | 46 | static void *(*cJSON_malloc)(size_t sz) = malloc; 47 | static void (*cJSON_free)(void *ptr) = free; 48 | 49 | static char* cJSON_strdup(const char* str) 50 | { 51 | size_t len; 52 | char* copy; 53 | 54 | len = strlen(str) + 1; 55 | if (!(copy = (char*)cJSON_malloc(len))) return 0; 56 | memcpy(copy,str,len); 57 | return copy; 58 | } 59 | 60 | void cJSON_InitHooks(cJSON_Hooks* hooks) 61 | { 62 | if (!hooks) { /* Reset hooks */ 63 | cJSON_malloc = malloc; 64 | cJSON_free = free; 65 | return; 66 | } 67 | 68 | cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; 69 | cJSON_free = (hooks->free_fn)?hooks->free_fn:free; 70 | } 71 | 72 | /* Internal constructor. */ 73 | static cJSON *cJSON_New_Item() 74 | { 75 | cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); 76 | if (node) memset(node,0,sizeof(cJSON)); 77 | return node; 78 | } 79 | 80 | /* Delete a cJSON structure. */ 81 | void cJSON_Delete(cJSON *c) 82 | { 83 | cJSON *next; 84 | while (c) 85 | { 86 | next=c->next; 87 | if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); 88 | if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); 89 | if (c->string) cJSON_free(c->string); 90 | cJSON_free(c); 91 | c=next; 92 | } 93 | } 94 | 95 | /* Parse the input text to generate a number, and populate the result into item. */ 96 | static const char *parse_number(cJSON *item,const char *num) 97 | { 98 | double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; 99 | 100 | /* Could use sscanf for this? */ 101 | if (*num=='-') sign=-1,num++; /* Has sign? */ 102 | if (*num=='0') num++; /* is zero */ 103 | if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ 104 | if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */ 105 | if (*num=='e' || *num=='E') /* Exponent? */ 106 | { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */ 107 | while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */ 108 | } 109 | 110 | n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ 111 | 112 | item->valuedouble=n; 113 | item->valueint=(int)n; 114 | item->type=cJSON_Number; 115 | return num; 116 | } 117 | 118 | /* Render the number nicely from the given item into a string. */ 119 | static char *print_number(cJSON *item) 120 | { 121 | char *str; 122 | double d=item->valuedouble; 123 | if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) 124 | { 125 | str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ 126 | if (str) sprintf(str,"%d",item->valueint); 127 | } 128 | else 129 | { 130 | str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */ 131 | if (str) 132 | { 133 | if (fabs(floor(d)-d)<=DBL_EPSILON) sprintf(str,"%.0f",d); 134 | else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); 135 | else sprintf(str,"%f",d); 136 | } 137 | } 138 | return str; 139 | } 140 | 141 | /* Parse the input text into an unescaped cstring, and populate item. */ 142 | static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; 143 | static const char *parse_string(cJSON *item,const char *str) 144 | { 145 | const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; 146 | if (*str!='\"') {ep=str;return 0;} /* not a string! */ 147 | 148 | while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ 149 | 150 | out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ 151 | if (!out) return 0; 152 | 153 | ptr=str+1;ptr2=out; 154 | while (*ptr!='\"' && *ptr) 155 | { 156 | if (*ptr!='\\') *ptr2++=*ptr++; 157 | else 158 | { 159 | ptr++; 160 | switch (*ptr) 161 | { 162 | case 'b': *ptr2++='\b'; break; 163 | case 'f': *ptr2++='\f'; break; 164 | case 'n': *ptr2++='\n'; break; 165 | case 'r': *ptr2++='\r'; break; 166 | case 't': *ptr2++='\t'; break; 167 | case 'u': /* transcode utf16 to utf8. */ 168 | sscanf(ptr+1,"%4x",&uc);ptr+=4; /* get the unicode char. */ 169 | 170 | if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; // check for invalid. 171 | 172 | if (uc>=0xD800 && uc<=0xDBFF) // UTF16 surrogate pairs. 173 | { 174 | if (ptr[1]!='\\' || ptr[2]!='u') break; // missing second-half of surrogate. 175 | sscanf(ptr+3,"%4x",&uc2);ptr+=6; 176 | if (uc2<0xDC00 || uc2>0xDFFF) break; // invalid second-half of surrogate. 177 | uc=0x10000 | ((uc&0x3FF)<<10) | (uc2&0x3FF); 178 | } 179 | 180 | len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; 181 | 182 | switch (len) { 183 | case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 184 | case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 185 | case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 186 | case 1: *--ptr2 =(uc | firstByteMark[len]); 187 | } 188 | ptr2+=len; 189 | break; 190 | default: *ptr2++=*ptr; break; 191 | } 192 | ptr++; 193 | } 194 | } 195 | *ptr2=0; 196 | if (*ptr=='\"') ptr++; 197 | item->valuestring=out; 198 | item->type=cJSON_String; 199 | return ptr; 200 | } 201 | 202 | /* Render the cstring provided to an escaped version that can be printed. */ 203 | static char *print_string_ptr(const char *str) 204 | { 205 | const char *ptr;char *ptr2,*out;int len=0;unsigned char token; 206 | 207 | if (!str) return cJSON_strdup(""); 208 | ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;} 209 | 210 | out=(char*)cJSON_malloc(len+3); 211 | if (!out) return 0; 212 | 213 | ptr2=out;ptr=str; 214 | *ptr2++='\"'; 215 | while (*ptr) 216 | { 217 | if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++; 218 | else 219 | { 220 | *ptr2++='\\'; 221 | switch (token=*ptr++) 222 | { 223 | case '\\': *ptr2++='\\'; break; 224 | case '\"': *ptr2++='\"'; break; 225 | case '\b': *ptr2++='b'; break; 226 | case '\f': *ptr2++='f'; break; 227 | case '\n': *ptr2++='n'; break; 228 | case '\r': *ptr2++='r'; break; 229 | case '\t': *ptr2++='t'; break; 230 | default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */ 231 | } 232 | } 233 | } 234 | *ptr2++='\"';*ptr2++=0; 235 | return out; 236 | } 237 | /* Invote print_string_ptr (which is useful) on an item. */ 238 | static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);} 239 | 240 | /* Predeclare these prototypes. */ 241 | static const char *parse_value(cJSON *item,const char *value); 242 | static char *print_value(cJSON *item,int depth,int fmt); 243 | static const char *parse_array(cJSON *item,const char *value); 244 | static char *print_array(cJSON *item,int depth,int fmt); 245 | static const char *parse_object(cJSON *item,const char *value); 246 | static char *print_object(cJSON *item,int depth,int fmt); 247 | 248 | /* Utility to jump whitespace and cr/lf */ 249 | static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;} 250 | 251 | /* Parse an object - create a new root, and populate. */ 252 | cJSON *cJSON_Parse(const char *value) 253 | { 254 | cJSON *c=cJSON_New_Item(); 255 | ep=0; 256 | if (!c) return 0; /* memory fail */ 257 | 258 | if (!parse_value(c,skip(value))) {cJSON_Delete(c);return 0;} 259 | return c; 260 | } 261 | 262 | /* Render a cJSON item/entity/structure to text. */ 263 | char *cJSON_Print(cJSON *item) {return print_value(item,0,1);} 264 | char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);} 265 | 266 | /* Parser core - when encountering text, process appropriately. */ 267 | static const char *parse_value(cJSON *item,const char *value) 268 | { 269 | if (!value) return 0; /* Fail on null. */ 270 | if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; } 271 | if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } 272 | if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; } 273 | if (*value=='\"') { return parse_string(item,value); } 274 | if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); } 275 | if (*value=='[') { return parse_array(item,value); } 276 | if (*value=='{') { return parse_object(item,value); } 277 | 278 | ep=value;return 0; /* failure. */ 279 | } 280 | 281 | /* Render a value to text. */ 282 | static char *print_value(cJSON *item,int depth,int fmt) 283 | { 284 | char *out=0; 285 | if (!item) return 0; 286 | switch ((item->type)&255) 287 | { 288 | case cJSON_NULL: out=cJSON_strdup("null"); break; 289 | case cJSON_False: out=cJSON_strdup("false");break; 290 | case cJSON_True: out=cJSON_strdup("true"); break; 291 | case cJSON_Number: out=print_number(item);break; 292 | case cJSON_String: out=print_string(item);break; 293 | case cJSON_Array: out=print_array(item,depth,fmt);break; 294 | case cJSON_Object: out=print_object(item,depth,fmt);break; 295 | } 296 | return out; 297 | } 298 | 299 | /* Build an array from input text. */ 300 | static const char *parse_array(cJSON *item,const char *value) 301 | { 302 | cJSON *child; 303 | if (*value!='[') {ep=value;return 0;} /* not an array! */ 304 | 305 | item->type=cJSON_Array; 306 | value=skip(value+1); 307 | if (*value==']') return value+1; /* empty array. */ 308 | 309 | item->child=child=cJSON_New_Item(); 310 | if (!item->child) return 0; /* memory fail */ 311 | value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */ 312 | if (!value) return 0; 313 | 314 | while (*value==',') 315 | { 316 | cJSON *new_item; 317 | if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ 318 | child->next=new_item;new_item->prev=child;child=new_item; 319 | value=skip(parse_value(child,skip(value+1))); 320 | if (!value) return 0; /* memory fail */ 321 | } 322 | 323 | if (*value==']') return value+1; /* end of array */ 324 | ep=value;return 0; /* malformed. */ 325 | } 326 | 327 | /* Render an array to text */ 328 | static char *print_array(cJSON *item,int depth,int fmt) 329 | { 330 | char **entries; 331 | char *out=0,*ptr,*ret;int len=5; 332 | cJSON *child=item->child; 333 | int numentries=0,i=0,fail=0; 334 | 335 | /* How many entries in the array? */ 336 | while (child) numentries++,child=child->next; 337 | /* Allocate an array to hold the values for each */ 338 | entries=(char**)cJSON_malloc(numentries*sizeof(char*)); 339 | if (!entries) return 0; 340 | memset(entries,0,numentries*sizeof(char*)); 341 | /* Retrieve all the results: */ 342 | child=item->child; 343 | while (child && !fail) 344 | { 345 | ret=print_value(child,depth+1,fmt); 346 | entries[i++]=ret; 347 | if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1; 348 | child=child->next; 349 | } 350 | 351 | /* If we didn't fail, try to malloc the output string */ 352 | if (!fail) out=(char*)cJSON_malloc(len); 353 | /* If that fails, we fail. */ 354 | if (!out) fail=1; 355 | 356 | /* Handle failure. */ 357 | if (fail) 358 | { 359 | for (i=0;itype=cJSON_Object; 385 | value=skip(value+1); 386 | if (*value=='}') return value+1; /* empty array. */ 387 | 388 | item->child=child=cJSON_New_Item(); 389 | if (!item->child) return 0; 390 | value=skip(parse_string(child,skip(value))); 391 | if (!value) return 0; 392 | child->string=child->valuestring;child->valuestring=0; 393 | if (*value!=':') {ep=value;return 0;} /* fail! */ 394 | value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ 395 | if (!value) return 0; 396 | 397 | while (*value==',') 398 | { 399 | cJSON *new_item; 400 | if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ 401 | child->next=new_item;new_item->prev=child;child=new_item; 402 | value=skip(parse_string(child,skip(value+1))); 403 | if (!value) return 0; 404 | child->string=child->valuestring;child->valuestring=0; 405 | if (*value!=':') {ep=value;return 0;} /* fail! */ 406 | value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ 407 | if (!value) return 0; 408 | } 409 | 410 | if (*value=='}') return value+1; /* end of array */ 411 | ep=value;return 0; /* malformed. */ 412 | } 413 | 414 | /* Render an object to text. */ 415 | static char *print_object(cJSON *item,int depth,int fmt) 416 | { 417 | char **entries=0,**names=0; 418 | char *out=0,*ptr,*ret,*str;int len=7,i=0,j; 419 | cJSON *child=item->child; 420 | int numentries=0,fail=0; 421 | /* Count the number of entries. */ 422 | while (child) numentries++,child=child->next; 423 | /* Allocate space for the names and the objects */ 424 | entries=(char**)cJSON_malloc(numentries*sizeof(char*)); 425 | if (!entries) return 0; 426 | names=(char**)cJSON_malloc(numentries*sizeof(char*)); 427 | if (!names) {cJSON_free(entries);return 0;} 428 | memset(entries,0,sizeof(char*)*numentries); 429 | memset(names,0,sizeof(char*)*numentries); 430 | 431 | /* Collect all the results into our arrays: */ 432 | child=item->child;depth++;if (fmt) len+=depth; 433 | while (child) 434 | { 435 | names[i]=str=print_string_ptr(child->string); 436 | entries[i++]=ret=print_value(child,depth,fmt); 437 | if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1; 438 | child=child->next; 439 | } 440 | 441 | /* Try to allocate the output string */ 442 | if (!fail) out=(char*)cJSON_malloc(len); 443 | if (!out) fail=1; 444 | 445 | /* Handle failure */ 446 | if (fail) 447 | { 448 | for (i=0;ichild;int i=0;while(c)i++,c=c->next;return i;} 474 | cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;} 475 | cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;} 476 | 477 | /* Utility for array list handling. */ 478 | static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} 479 | /* Utility for handling references. */ 480 | static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;} 481 | 482 | /* Add item to array/object. */ 483 | void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} 484 | void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} 485 | void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));} 486 | void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} 487 | 488 | cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; 489 | if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;} 490 | void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} 491 | cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;} 492 | void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));} 493 | 494 | /* Replace array/object items with new ones. */ 495 | void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return; 496 | newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem; 497 | if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);} 498 | void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}} 499 | 500 | /* Create basic types: */ 501 | cJSON *cJSON_CreateNull() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} 502 | cJSON *cJSON_CreateTrue() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} 503 | cJSON *cJSON_CreateFalse() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} 504 | cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;} 505 | cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;} 506 | cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;} 507 | cJSON *cJSON_CreateArray() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} 508 | cJSON *cJSON_CreateObject() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} 509 | 510 | /* Create Arrays: */ 511 | cJSON *cJSON_CreateIntArray(int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 512 | cJSON *cJSON_CreateFloatArray(float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 513 | cJSON *cJSON_CreateDoubleArray(double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 514 | cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} 515 | -------------------------------------------------------------------------------- /cJSON.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Dave Gamble 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef cJSON__h 24 | #define cJSON__h 25 | 26 | #ifdef __cplusplus 27 | extern "C" 28 | { 29 | #endif 30 | 31 | /* cJSON Types: */ 32 | #define cJSON_False 0 33 | #define cJSON_True 1 34 | #define cJSON_NULL 2 35 | #define cJSON_Number 3 36 | #define cJSON_String 4 37 | #define cJSON_Array 5 38 | #define cJSON_Object 6 39 | 40 | #define cJSON_IsReference 256 41 | 42 | /* The cJSON structure: */ 43 | typedef struct cJSON { 44 | struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ 45 | struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ 46 | 47 | int type; /* The type of the item, as above. */ 48 | 49 | char *valuestring; /* The item's string, if type==cJSON_String */ 50 | int valueint; /* The item's number, if type==cJSON_Number */ 51 | double valuedouble; /* The item's number, if type==cJSON_Number */ 52 | 53 | char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ 54 | } cJSON; 55 | 56 | typedef struct cJSON_Hooks { 57 | void *(*malloc_fn)(size_t sz); 58 | void (*free_fn)(void *ptr); 59 | } cJSON_Hooks; 60 | 61 | /* Supply malloc, realloc and free functions to cJSON */ 62 | extern void cJSON_InitHooks(cJSON_Hooks* hooks); 63 | 64 | 65 | /* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ 66 | extern cJSON *cJSON_Parse(const char *value); 67 | /* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ 68 | extern char *cJSON_Print(cJSON *item); 69 | /* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ 70 | extern char *cJSON_PrintUnformatted(cJSON *item); 71 | /* Delete a cJSON entity and all subentities. */ 72 | extern void cJSON_Delete(cJSON *c); 73 | 74 | /* Returns the number of items in an array (or object). */ 75 | extern int cJSON_GetArraySize(cJSON *array); 76 | /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ 77 | extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); 78 | /* Get item "string" from object. Case insensitive. */ 79 | extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); 80 | 81 | /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ 82 | extern const char *cJSON_GetErrorPtr(); 83 | 84 | /* These calls create a cJSON item of the appropriate type. */ 85 | extern cJSON *cJSON_CreateNull(); 86 | extern cJSON *cJSON_CreateTrue(); 87 | extern cJSON *cJSON_CreateFalse(); 88 | extern cJSON *cJSON_CreateBool(int b); 89 | extern cJSON *cJSON_CreateNumber(double num); 90 | extern cJSON *cJSON_CreateString(const char *string); 91 | extern cJSON *cJSON_CreateArray(); 92 | extern cJSON *cJSON_CreateObject(); 93 | 94 | /* These utilities create an Array of count items. */ 95 | extern cJSON *cJSON_CreateIntArray(int *numbers,int count); 96 | extern cJSON *cJSON_CreateFloatArray(float *numbers,int count); 97 | extern cJSON *cJSON_CreateDoubleArray(double *numbers,int count); 98 | extern cJSON *cJSON_CreateStringArray(const char **strings,int count); 99 | 100 | /* Append item to the specified array/object. */ 101 | extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); 102 | extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); 103 | /* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ 104 | extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); 105 | extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); 106 | 107 | /* Remove/Detatch items from Arrays/Objects. */ 108 | extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); 109 | extern void cJSON_DeleteItemFromArray(cJSON *array,int which); 110 | extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); 111 | extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); 112 | 113 | /* Update array items. */ 114 | extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); 115 | extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); 116 | 117 | #define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) 118 | #define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) 119 | #define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) 120 | #define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) 121 | #define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) 122 | 123 | #ifdef __cplusplus 124 | } 125 | #endif 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "cJSON.h" 10 | 11 | #define MAX_PKGS_FOR_USER 30 12 | #define WITH_ALA 1 13 | #define WITH_ARM 0 14 | #define VERSION "2.0.0-3" 15 | 16 | 17 | #include "variables.h" 18 | #include "Interface.h" 19 | #include "actions.c" 20 | #include "ala.c" 21 | #include "arm.c" 22 | 23 | int main(int argc, char **argv) { 24 | char *package; 25 | int param, single=0; 26 | int quiet_downgrade; 27 | 28 | if (argc==2) package = argv[1]; 29 | else if (argc==3) package = argv[2]; 30 | else { ShowHelpWindow(); return 0; } 31 | while ((param = getopt (argc, argv, "q:ha")) != -1) 32 | switch (param) { 33 | case 'h':{ ShowHelpWindow(); return 0; } 34 | case 'q':{ silent = 1; break; } 35 | case 'a':{ single = 1; break; } 36 | } 37 | init = Initialization(package); 38 | if (init) return -1; 39 | 40 | if (single) { // Downgrade single package 41 | sprintf(tmp_string,"Downgrade package: %s",package); 42 | syslog(LOG_INFO, tmp_string); 43 | sprintf (full, "\033[1;%dm %s \033[0m \n", 31, tmp_string); 44 | dgr_output(full); 45 | if (!quiet_downgrade) { sprintf (tmp_string, "Installed version: %s\n",installed_pkg_ver); dgr_output(tmp_string);} 46 | int down_result = DowngradePackage(package); 47 | } 48 | else { // Show possible packages list when downgrade 49 | int pac_num; 50 | sprintf(tmp_string,"Downgrade package: %s",package); 51 | syslog(LOG_INFO, tmp_string); 52 | sprintf (full, "\033[1;%dm %s \033[0m \n", 31, tmp_string); 53 | dgr_output(full); 54 | str = GetChoiseForPackage(package); 55 | if (!strcmp(str,"q")) { Deinitialization(); return 0; } 56 | else pac_num = atoi(str); 57 | if (pac_num>MAX_PKGS_FOR_USER) { Deinitialization(); return 0; } 58 | strcpy(install_command,"sudo pacman -U "); strcat(install_command, user_pkgs[pac_num-1].link); 59 | //printf ("%s\n",install_command); // DEBUG 60 | system(install_command); 61 | } 62 | Deinitialization(); 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /variables.h: -------------------------------------------------------------------------------- 1 | typedef enum { 2 | DGR_NO_PKG_IN_ARM = 1, 3 | DGR_NO_PKG_IN_AUR = 2, 4 | DGR_PKG_NOT_INSTALL = 3, 5 | DGR_READ_ARM_ERROR = 4, 6 | DGR_READ_AUR_ERROR = 5 7 | } DwgrRetSatus; 8 | 9 | typedef struct _dgr_data { 10 | char string1[500]; 11 | int int1; 12 | } dgr_data; 13 | dgr_data DgrData; 14 | // DgrData.int1 =3; 15 | 16 | int Initialization(char *); 17 | int Deinitialization(); 18 | int IsPackageAvailable( char *); 19 | int IsPackageInLogs( char *); 20 | int IsPackageInCache( char *); 21 | int IsPackageInAur( char *); 22 | int IsPackageInArm( char *, char *); 23 | int IsPackageInstalled(char *); 24 | void ReadPacmanLog(); 25 | int ReadArm(char *); 26 | int ReadALA(char *); 27 | int IsPackageInAla(char*, char *); 28 | int PrepareView(char *); 29 | int DowngradePackage( char *); 30 | char* GetChoiseForPackage( char *); 31 | char* str_replace(char*,char*,char*); 32 | int dgr_output( char *); 33 | 34 | alpm_handle_t *alpm_handle; 35 | alpm_db_t *db; 36 | alpm_pkg_t *pkg; 37 | 38 | char *ptr, *i_com; 39 | char *str, *architecture; 40 | const char *pkgname; 41 | char full_path_to_packet[300], tmp_string[200], full[500]; 42 | char install_command[300]; // Команда для установки 43 | char install_version[30]; // Версия пакета для установки 44 | const char* installed_pkg_ver; // Текущая установленная версия 45 | long int pacmanlog_length; 46 | int ret, loglines_counter; 47 | int tmpint, pkgsinarm, pkgsinala, pkginala, init; 48 | int single, silent, counter; 49 | FILE *pFile; 50 | 51 | struct packs{ // -- Действия с пакетами из логов пакмана 52 | char name[50]; // название пакета 53 | char date[10]; // дата операции 54 | char time[20]; // время операции 55 | char action[20]; // название операции (upgraded, installed, removed) 56 | char cur_version[50]; // предыдущая версия 57 | char prev_version[50]; // предыдущая версия 58 | } *pkgs; 59 | //struct packs *pkgs; 60 | struct arm_packs{ // -- список пакетов в ARM 61 | char full_path[400]; // полный адрес до пакета 62 | char version[20]; // Version of package 63 | char name[50]; // Name of package 64 | char repository[20]; // Repository of package 65 | char link[100]; //Link for download 66 | int pkg_release; //Package release 67 | } *arm_pkgs; 68 | //struct arm_packs *arm_pkgs; 69 | struct ala_packs{ // -- список пакетов в ALA 70 | char full_path[400]; // полный адрес до пакета 71 | char name[50]; // Name of package (with version and release) 72 | char version[10]; // Version of package 73 | char full_name[50]; // Name of package with version and .tar.xz 74 | } *ala_pkgs; 75 | //struct ala_packs *ala_pkgs; 76 | struct user_packs{ // -- Список пакетов для вывода пользователю 77 | char name[50]; // название пакета 78 | char version[10]; // Version of package 79 | char link[200]; //Link for download 80 | char repo[20]; // ARM, ALA, Cache 81 | } *user_pkgs; 82 | //struct user_packs *user_pkgs; 83 | 84 | struct curl_MemoryStruct { 85 | char *memory; 86 | size_t size; 87 | }; 88 | struct curl_MemoryStruct chunk; 89 | CURL *curl; 90 | CURLcode result; 91 | --------------------------------------------------------------------------------