Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:dgarcia:staging
inst-source-utils
inst-source-utils-2023.11.08.obscpio
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File inst-source-utils-2023.11.08.obscpio of Package inst-source-utils
07070100000000000081A4000000000000000000000001654BBDF90000464B000000000000000000000000000000000000002500000000inst-source-utils-2023.11.08/COPYING GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Steet, Fifth Floor, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, 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 or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's 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 give any other recipients of the Program a copy of this License along with the Program. 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 Program or any portion of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, 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 Program, 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 Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) 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; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, 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 executable. However, as a special exception, the source code 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. If distribution of executable or 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 counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program 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. 5. 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 Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program 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 to this License. 7. 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 Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program 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 Program. 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. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program 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. 9. The Free Software Foundation may publish revised and/or new versions of the 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 Program 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 Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, 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 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 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 Programs 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 to make it free software which everyone can redistribute and change under these terms. 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 effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. <one line to give the program's name and a brief idea of what it does.> Copyright (C) <year> <name of author> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. <signature of Ty Coon>, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. 07070100000001000081A4000000000000000000000001654BBDF900003AB9000000000000000000000000000000000000003700000000inst-source-utils-2023.11.08/inst-source-utils.changes------------------------------------------------------------------- Wed Nov 8 16:06:01 UTC 2023 - Dirk Müller <dmueller@suse.com> - update to 2023.11.08: - Handle zstd repos in rezip_repo_rsyncable ------------------------------------------------------------------- Tue Aug 1 17:55:46 CET 2023 - meissner@suse.de - added a small perl helper to create updateinfos on your own - added some help ------------------------------------------------------------------- Wed Apr 27 10:19:51 UTC 2022 - Dirk Müller <dmueller@suse.com> - fix URL - use %%license tag ------------------------------------------------------------------- Thu Sep 9 16:49:31 UTC 2021 - Marcus Rueckert <mrueckert@suse.de> - update to 2021.09.09 (boo#1178224) - This should fix generating changelogs for trees with multiple images. ------------------------------------------------------------------- Mon Dec 10 16:33:02 CET 2018 - ro@suse.de - add pattern-category also to susedata, not just susedata_i18n ------------------------------------------------------------------- Wed Dec 5 14:55:50 UTC 2018 - Adrian Schröter <adrian@suse.de> - Add pattern-category (fate#323785) ------------------------------------------------------------------- Fri Apr 6 10:02:20 UTC 2018 - adrian@suse.de - add support for transalted EULA ------------------------------------------------------------------- Tue Mar 13 12:27:40 UTC 2018 - adrian@suse.de - new susedata i18n structure - move source to git ------------------------------------------------------------------- Tue Feb 27 15:17:48 CET 2018 - ro@suse.de - mk_changelog: do not use localtime call for min_date (bnc#1081766) ------------------------------------------------------------------- Fri Jul 28 13:26:40 CEST 2017 - ro@suse.de - drop requires for recode ------------------------------------------------------------------- Tue Jul 26 12:07:52 CEST 2016 - ro@suse.de - ABXML: add diskusage data to susedata xml structure (fate#320517) ------------------------------------------------------------------- Mon May 2 17:46:57 CEST 2016 - ro@suse.de - RPMQ: add infrastructure for HEADERSTART and EXTRA - create_package_descr: use infrastucture to allow running with only rpm headers instead of full rpms (bnc#978085) ------------------------------------------------------------------- Wed Dec 9 16:01:55 CET 2015 - ro@suse.de - update rezip_repo_rsyncable again: fix up filenames if they are checksum prefixed, do not change timestamps of the files recompressed (bnc#958511) ------------------------------------------------------------------- Tue Dec 8 12:10:41 CET 2015 - ro@suse.de - rezip_repo_rsyncable: add "-n" option for gzip ------------------------------------------------------------------- Tue Oct 27 15:10:49 CET 2015 - ro@suse.de - mk_listings: set LC_CTYPE (bnc#910388) - ABXML.pm: add endoflife in product structure ------------------------------------------------------------------- Tue Mar 18 16:40:34 CET 2014 - ro@suse.de - update create_package_descr: fix utf8 handling thanks to mls ------------------------------------------------------------------- Fri Mar 14 02:38:32 CET 2014 - ro@suse.de - create_sha1sums: skip content file actions if content file does not exist ------------------------------------------------------------------- Wed Mar 12 17:56:59 CET 2014 - ro@suse.de - fix bogus code in rezip-repo-rsyncable ------------------------------------------------------------------- Wed Mar 5 14:34:28 CET 2014 - ro@suse.de - bump version number and add automatic to pre_checkin.sh ------------------------------------------------------------------- Tue Mar 4 16:47:58 CET 2014 - ro@suse.de - add ABXML.pm and ABStructured.pm - rewrite rezip_repo_rsyncable to keep checksum type - add requires for perl-XML-Parser ------------------------------------------------------------------- Tue Feb 25 15:36:18 CET 2014 - ro@suse.de - fix typo in last change ------------------------------------------------------------------- Wed Feb 19 17:51:38 CET 2014 - ro@suse.de - update create_package_descr: also recognize new rpm tags for Suggests and Enhances (thanks to mls for the patch) ------------------------------------------------------------------- Fri Sep 20 11:57:36 CEST 2013 - ro@suse.de - also add Requires(pre) and Requires(post) to Prq sections ------------------------------------------------------------------- Wed Apr 3 12:03:43 CEST 2013 - ro@suse.de - remove pdb code from create_package_descr - create_sha1sums: replace "which" by "type -p" - create_repo_for_patch.sh: same change - RPMQ: fix for name-version-release > 64 characters ------------------------------------------------------------------- Fri Jan 25 01:23:46 CET 2013 - ro@suse.de - use "strict" for create_package_descr - add support for -e (eula_dir) parameter in create_package_descr ------------------------------------------------------------------- Wed Dec 5 13:27:11 CET 2012 - ro@suse.de - update create_md5sums to get the key files witout a pubring.gpg ------------------------------------------------------------------- Thu Sep 13 16:15:54 CEST 2012 - ro@suse.de - add recent fixes ------------------------------------------------------------------- Wed Feb 29 10:55:46 CET 2012 - ro@suse.de - mk_changelog: calculate time (two years ago) differently to avoid error on leap days. ------------------------------------------------------------------- Thu Feb 2 11:10:39 UTC 2012 - adrian@suse.de - write SHA256 sums into CHECKSUMS file ------------------------------------------------------------------- Sun Oct 16 19:55:51 UTC 2011 - lars@linux-schulserver.de - to too much quoting in create_package_descr ------------------------------------------------------------------- Fri Oct 14 17:04:57 UTC 2011 - lrupp@suse.de - handle spaces in path in create_package_descr (bnc#604730) ------------------------------------------------------------------- Wed May 25 08:18:37 UTC 2011 - adrian@suse.de - fix header generation for SHA256 mode (no SHA1 tag) ------------------------------------------------------------------- Thu May 5 12:20:17 CEST 2011 - ro@suse.de - create_sha1sum and create_sha1sums now understand option "-2" to use/create sha256sum(s) ------------------------------------------------------------------- Thu Apr 28 18:25:28 CEST 2011 - ro@suse.de - add option -D to use sha256 checksums in create_package_descr ------------------------------------------------------------------- Wed Mar 17 11:52:48 CET 2010 - ro@suse.de - add requires to recode ------------------------------------------------------------------- Mon Feb 22 12:11:17 CET 2010 - ro@suse.de - create_package_descr: output a little statistic ------------------------------------------------------------------- Wed Jan 27 14:52:59 UTC 2010 - adrian@suse.de - add Requires to gpg2 to fix product media signing ------------------------------------------------------------------- Mon Nov 2 13:41:07 CET 2009 - ro@suse.de - add rezip_repo_rsyncable - update create_package_descr: - skip deltarpms - write comment with cmdline only once - do not warn for missing pdb data - update: create_repo_for_patch.sh - add sources if wanted - update: create_sha1sums - clear LANG LANGUAGE - update: createpatch - major overhaul - update: RPMQ.pm - add PRETRANS,POSTTRANS, ..., FILEDIGESTALGO ------------------------------------------------------------------- Mon Oct 12 23:14:14 CEST 2009 - lrupp@suse.de - fix bnc#546152: create_sha1sums fails to find custom gpg-key on non-english systems - fix create_package_descr to work with delta-rpms in path ------------------------------------------------------------------- Fri Aug 7 19:47:34 CEST 2009 - lrupp@suse.de - create_package_descr: disable debug output for missing pdb data - create_repo_for_patch.sh: complete rework (thanks to Ulf Lange) fixes bnc #506357 - RPMQ.pm: added the following RPM-tags PRETRANS, POSTTRANS, PRETRANSPROG, POSTTRANSPROG, DISTTAG, FILEDIGESTALGOS, FILEDIGESTALGO - createpatch: first part of the code rewrite is done New options: -l|--logfile => write output to logfile -b|--basedir => obsoletes old script behavior -c|--configfile => use options from configfile ------------------------------------------------------------------- Mon Jul 13 12:40:12 CEST 2009 - ug@suse.de - remove the "PATTERNS" line from the created add_on (create_update_source) ------------------------------------------------------------------- Fri Mar 6 11:58:45 CET 2009 - ro@suse.de - create_package_descr: add -Q option to disable Shr tag ------------------------------------------------------------------- Wed Feb 25 11:10:27 CET 2009 - lrupp@suse.de - create_package_descr: more help text for the -T XTAGS_FILE - create_sha1sum, create_md5sums - fix bnc#460894: handle multiple arguments ------------------------------------------------------------------- Fri Jan 23 12:33:54 CET 2009 - jcborn@suse.de - added gen-s390-cd-kernel.pl because it is required to create bootable S/390 media with kiwi-isntsource ------------------------------------------------------------------- Mon Nov 24 15:12:14 CET 2008 - ro@suse.de - update create_package_descr ------------------------------------------------------------------- Mon Nov 24 13:53:46 CET 2008 - lrupp@suse.de - fix pathnames ------------------------------------------------------------------- Thu Nov 20 12:42:40 CET 2008 - ro@suse.de - create_package_descr: add -T option for xtags file format: "packagename: literal text" so that "literal text" will be directly included for the package data ------------------------------------------------------------------- Thu Nov 13 00:14:01 CET 2008 - ro@suse.de - mk_listings: exclude .cr-cache and .snapshot ------------------------------------------------------------------- Thu Oct 16 17:54:47 CEST 2008 - lrupp@suse.de - create_sha1sums: + also put the GPG key in each slideshow directory ------------------------------------------------------------------- Thu Oct 16 15:00:19 CEST 2008 - ro@suse.de - create_package_descr: + add "-V" option to also put the vendor for each rpm in the generated metadata ------------------------------------------------------------------- Thu Oct 9 17:46:48 CEST 2008 - lrupp@suse.de - quick fix for bnc#409927: - create_sha1sums: + create SHA1SUM files and sign them in the slideshow directory - added create_sha1sum which is a copy of create_md5sums (can't use create_sha1sum_s_ as this name is already in use) - removed NoSource tags ------------------------------------------------------------------- Mon Jul 21 19:02:27 CEST 2008 - lrupp@suse.de - create_directory_yast: + add "-f" option to overwrite existing directory.yast files - create_md5sums: + small code cleanups only - create_package_descr: + added option -F (do file list: packages.FL) + added option -B (add requires for src packages) + fix warning message if -x is not specified (typo) + EXTRA_REQUIRES_FILE option switched from -p to -r - create_repo_for_patch.sh: + fix quoting - create_sha1sums: + added option "-x" to add additional meta files in content file + beetter check for repomd.xml + added "-n" option to skip re-signing - mk_changelog: + small code cleanup ------------------------------------------------------------------- Fri May 16 16:52:36 CEST 2008 - ro@suse.de - patches upstreamed ------------------------------------------------------------------- Thu May 15 15:09:25 CEST 2008 - schwab@suse.de - Fix syntax and quoting bugs. ------------------------------------------------------------------- Fri Feb 1 15:03:24 CET 2008 - lrupp@suse.de - fix file permissions (fixes bnc#357313 and bnc#351070) - handle also boot/*/config boot/*/common (create_sha1sums) - fix path to REPOFILE (create_sha1sums) ------------------------------------------------------------------- Tue Dec 11 14:30:39 CET 2007 - lrupp@suse.de - added mk_changelog (for add-on creator) - add fallback mode for createpatch (see #308684) ------------------------------------------------------------------- Wed Sep 26 20:38:37 CEST 2007 - ro@suse.de - remove dependency to createrepo for now ------------------------------------------------------------------- Wed Sep 26 12:20:24 CEST 2007 - lrupp@suse.de - fixes for Bug #308684: + require createrepo + be more secure in bash ------------------------------------------------------------------- Tue Jul 17 02:08:14 CEST 2007 - lrupp@suse.de - createpatch: use CONFIRMATION_FILE as description to make clear, that this creates a confirmation popup for the user (#205534) ------------------------------------------------------------------- Fri Jul 13 11:21:25 CEST 2007 - lrupp@suse.de - create_md5sums: + fix typo in usage - create_package_descr: + search data in main package for xxbit packages + add license notes as confirmlic so YaST can display them even in plain text mode - create_sha1sums: added to generate the SHA1SUMs in content file - createpatch: + support "license_to_confirm": add an EULA to the patch, read from the file specified (see #205534 for details) + beautify usage message + added @packagelist to condition - mk_listings: + handle whitespaces in directory names + use --rsyncable as gzip option: `rsync' program can take advantage of similarities during sync over network + replace standard Names (CD,DVD,inst-source) + use '--nodigest --nosignature' for rpm queries if supported + re-create hardlinks from basedir to CD-dir if CD*/*.gz exists ------------------------------------------------------------------- Tue May 15 15:55:26 CEST 2007 - ories@suse.de - added support for adding supplements tag (#262859, #256038) - added support for overwriting the default freshens value - fixed one \" escaping typo - do not delete product.xml ------------------------------------------------------------------- Thu Mar 15 18:20:28 CET 2007 - lrupp@suse.de - patched copy-sources.sh ------------------------------------------------------------------- Tue Mar 13 12:06:48 CET 2007 - lrupp@suse.de - fixed source again - fixed script, too ------------------------------------------------------------------- Fri Mar 9 10:39:06 CET 2007 - lrupp@suse.de - fixed source tarball ------------------------------------------------------------------- Mon Mar 5 15:24:17 CET 2007 - lrupp@suse.de - add package to SLE10-SP1 tree (#250860) ------------------------------------------------------------------- Mon Feb 26 14:17:43 CET 2007 - lrupp@suse.de - fixed #214273 : inst-source-utils perl module in subdir of /usr/bin is questionable/ugly ------------------------------------------------------------------- Thu Oct 19 20:07:28 CEST 2006 - lrupp@suse.de - Obsolete only autoyast-utils <= 2.14.6 ------------------------------------------------------------------- Fri Oct 13 18:02:18 CEST 2006 - lrupp@suse.de - Initial version 07070100000002000081A4000000000000000000000001654BBDF90000068D000000000000000000000000000000000000003400000000inst-source-utils-2023.11.08/inst-source-utils.spec# # spec file for package inst-source-utils # # Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed # upon. The license for this file, and modifications and additions to the # file, is the same license as for the pristine package itself (unless the # license for the pristine package is not an Open Source License, in which # case the license is the MIT License). An "Open Source License" is a # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. # Please submit bugfixes or comments via http://bugs.opensuse.org/ # Name: inst-source-utils Summary: Utilities for creating customized installation sources License: GPL-2.0-or-later Group: System/YaST Version: 2023.11.08 Release: 0 Url: https://en.opensuse.org/Inst-source-utils BuildArch: noarch Requires: gpg2 Obsoletes: autoyast2-utils <= 2.14.10 Provides: autoyast2-utils = 2.14.10 Recommends: create-repo-utils Requires: perl-XML-Parser Requires: zstd Source: %name-%version.tar.xz Source1: split.pl %description Utilities supporting autoinstallation and creation of customized installation sources. Have a look at http://en.opensuse.org/Inst-source-utils for a detailed description of each script. %prep %setup -q %build %install install -d -m 755 %{buildroot}/%{_prefix} cp -a usr %{buildroot}/ %files %license COPYING %_bindir/* %defattr(644,root,root,755) %_datadir/%name %changelog 07070100000003000041ED000000000000000000000004654BBDF900000000000000000000000000000000000000000000002100000000inst-source-utils-2023.11.08/usr07070100000004000041ED000000000000000000000002654BBDF900000000000000000000000000000000000000000000002500000000inst-source-utils-2023.11.08/usr/bin07070100000005000081ED000000000000000000000001654BBDF900000498000000000000000000000000000000000000003700000000inst-source-utils-2023.11.08/usr/bin/compress_susetags#!/usr/bin/perl use strict; use File::stat; my $rsyncable = ""; my $arg = shift @ARGV; my $tmpdir = `mktemp -d /tmp/mk_listings.XXXXXX`; chomp ($tmpdir); if ( $arg ) { die("need an argument") unless ( -d $arg ); } if ( $arg !~ /^\// ) { my $pwd = `pwd`; chomp ($pwd); $arg = "$pwd/$arg"; } system (`touch "$tmpdir/fff"`); system (`gzip -f --rsyncable "$tmpdir/fff" >/dev/null 2>/dev/null`); if ( -f "$tmpdir/fff.gz" ) { $rsyncable = "--rsyncable"; } system (`rm -f "$tmpdir/fff" "$tmpdir/fff.gz"`); for my $packfile (glob("$arg/packages*"),glob("$arg/*.pat")) { next if ( $packfile !~ /^[A-Z0-9\-\._]*$/i ); next unless ( -f "$packfile" || -l "$packfile" ); next if ( $packfile =~ /\.gz$/ ); if ( -l "$packfile" ) { my $l = `readlink $packfile`; chomp ($l); next if ( $packfile =~ /\.gz$/ ); $l .= ".gz" unless ( $l =~ /\.gz$/ ); system ("rm", "-f", $packfile ); system ("ln", "-s", "-f", $l, $packfile.'.gz'); next; } system ("gzip", "-f", "-9", $rsyncable, $packfile); } system("rm", "-r", "-f", $tmpdir); system("rm", "-f", "$arg/patterns"); chdir($arg); system("ls *.pat *.pat.gz > patterns 2>/dev/null"); 07070100000006000081ED000000000000000000000001654BBDF9000006F3000000000000000000000000000000000000003B00000000inst-source-utils-2023.11.08/usr/bin/create_directory.yast#!/bin/bash # # Copyright (C) 2006 Novell Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., # 51 Franklin Street, # Fifth Floor, # Boston, MA 02110-1301, # USA. # # $Id: create_directory.yast,v 1.3 2008/06/25 12:10:43 lrupp Exp lrupp $ # FORCE="no" function usage (){ echo echo "Usage: $(basename $0) [-f] <targetdir>" echo echo " f : force - recreates existing files" echo echo " Creates the file directory.yast in each subdirectory." echo " YaST needs this file during Network installation to" echo " \"see\" the content of the directory if the server" echo " doesn't support directory listings." echo exit $1 } if [ -z "$1" ]; then usage 1; fi while getopts 'fh' OPTION; do case $OPTION in f) FORCE="yes" ;; h) usage 1; ;; esac done shift $(( OPTIND - 1 )) DIR="$1" test -d "$DIR" || { echo "ERROR: directory $DIR not found" >&2 usage 1 } for i in $(ls "$DIR") ; do case "$i" in *directory.yast) if [ "$FORCE" != "yes" ]; then continue fi ;; esac if test -d "$DIR/$i" ; then echo "$i/" else echo "$i" fi done > "$DIR/directory.yast" 07070100000007000081ED000000000000000000000001654BBDF900000DE2000000000000000000000000000000000000003400000000inst-source-utils-2023.11.08/usr/bin/create_md5sums#!/bin/bash # # Copyright (C) 2006 Novell Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., # 51 Franklin Street, # Fifth Floor, # Boston, MA 02110-1301, # USA. # # $Id: create_md5sums 110 2009-03-06 15:30:14Z lrupp $ # function usage (){ echo echo "Usage: `basename $0` [--meta] <targetdir>" echo " --meta : also create MD5SUMS.meta file" echo " --quiet: don't output anything" echo echo " Creates MD5SUMS files in each subdirectory." echo " Sometimes useful for debugging inst-source problems ;-)" echo exit $1 } function output(){ if [ "$QUIET" != "yes" ]; then echo "$1" fi } if [ -z "$1" ]; then usage 1; fi if [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]] ; then usage 0; fi unset LANGUAGE unset LANG export LC_ALL=POSIX umask 022 CREATE_META= QUIET="no" if test "x$1" = "x--meta"; then CREATE_META=1 shift fi if test "x$1" = "x--quiet"; then QUIET="yes" shift fi ROOTDIRS="$*" TMPFILE=$(mktemp /tmp/.create_md5sums.XXXXXX) MYPWD=$(pwd) for ROOTDIR in "$@" ; do case "$ROOTDIR" in /*) ;; *) ROOTDIR="$MYPWD/$ROOTDIR" ;; esac test -d "$ROOTDIR" || { echo "WARNING: $ROOTDIR is not a directory. Skipping it." } find "$ROOTDIR" -type d | while read DIR; do cd "$DIR" unset FILES NFILES=0 for FILE in * ; do test -f "$FILE" || continue test -L "$FILE" && continue test -n "$MD5SUMS_SKIPFILES" && { IS_SKIP=false set -f for i in $MD5SUMS_SKIPFILES ; do set +f case "$FILE" in ($i) IS_SKIP=true break ;; esac done set +f test $IS_SKIP = true && continue } case "$FILE" in (*.swp|MD5SUMS*|SHA1SUMS*) continue ;; (*) FILES[$[++NFILES]]="$FILE" ;; esac done if [ $NFILES -eq 0 ]; then rm -f MD5SUMS* else echo -n > $TMPFILE for FILE in "${FILES[@]}"; do md5sum "$FILE" >> $TMPFILE; done test -e MD5SUMS || touch MD5SUMS cmp -s $TMPFILE MD5SUMS || { mv $TMPFILE MD5SUMS chmod 644 MD5SUMS output "INFO: created MD5SUMS in $DIR" } if test -n "$CREATE_META"; then test -e MD5SUMS.meta || touch MD5SUMS.meta md5sum MD5SUMS > $TMPFILE cmp -s $TMPFILE MD5SUMS.meta || { mv $TMPFILE MD5SUMS.meta chmod 644 MD5SUMS.meta output "INFO: created MD5SUMS.meta in $DIR" } fi rm -f $TMPFILE fi done done 07070100000008000081ED000000000000000000000001654BBDF900005AEB000000000000000000000000000000000000003A00000000inst-source-utils-2023.11.08/usr/bin/create_package_descr#!/usr/bin/perl # # Copyright (C) 2006 Novell Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., # 51 Franklin Street, # Fifth Floor, # Boston, MA 02110-1301, # USA. # # $Id: create_package_descr,v 1.29 2008/06/24 18:42:26 lrupp Exp lrupp $ # BEGIN { $abuild_base_dir = "/usr/share/inst-source-utils"; unshift @INC, "$abuild_base_dir/modules"; } $| = 1; use File::stat; use FileHandle; use strict; use RPMQ; use Digest::MD5 (); use Encode; my (@DATADIRS,@IGNOREDIRS,@LANGUAGES,%SEEN_PACKAGE,%IGNORE_PACKAGE,@SHA_CACHEDIR); my %lang_alias = ( "czech"=>"cs", "english"=>"en", "french"=>"fr", "german"=>"de", "italian"=>"it", "russian" => "ru", "spanish"=>"es", "hungarian"=>"hu" ); my %tag_short = ("description"=>"Des","notice"=>"Ins","delnotice"=>"Del"); my $ignored_packages = ""; my $ignore_sources = "0"; my $ignore_symlinks = "0"; my $prefer_yastdescr = "0"; my $add_licenses = "0"; my $do_checksums = "0"; my $do_sha256 = "0"; my $do_keywords = "0"; my $have_sha_cache = 0; my $do_file_list = 0; my $maxdepth = 255; my $src_requires = 0; my $default_lang="english"; my $add_vendor = 0; my $allow_shr = 1; my %used_fallbacks; my $checksum_binary = "sha1sum"; my $unused_data_dir = ""; my $eula_data_dir = ""; my $ignore_file = ""; my $ignore_dir = ""; my $output_dir = ""; my $extra_requires = ""; my $extra_provides = ""; my $extra_tags = ""; my $with_links = ""; my $use_headers = "0"; my %xprovlist; my %xreqlist; my %xtaglist; my %pkg_lang; sub usage { my $exit_code=shift || 1; print "Usage: create_package_descr [OPTIONS]\n"; print " [-d DATADIR1 [-d DATADIR2 [... ] ] ] (default cwd)\n"; print " [-e EULA_DIR ]\n"; print " [-x EXTRA_PROV_FILE ]\n"; print " [-r EXTRA_REQUIRES_FILE]\n"; print " [-i IGNORE_DIR [ -i IGNORE_DIR [... ] ] ]\n"; print " [-I IGNORE_FILE ]\n"; print " [-l LANG1 [-l LANG2 [... ] ] (default $default_lang)\n"; print " [-o OUTPUT_DIR ] (default `cwd`/setup/descr)\n"; print " [-c CACHE_DIR ] (default none)\n"; print " [-M MAXDEPTH ] (default $maxdepth, depth for du-file)\n"; print " [-T XTAGS_FILE ] (extra tags for the packages file)\n"; print " [-Z ] (add_licenses)\n"; print " [-V ] (add_vendor for each rpm)\n"; print " [-S ] (ignore_sources)\n"; print " [-P ] (prefer_yastdescr)\n"; print " [-L ] (ignore_symlinks)\n"; print " [-C ] (do_checksums)\n"; print " [-D ] (do_sha256_checksums)\n"; print " [-K ] (do_keywords)\n"; print " [-F ] (do_file_list)\n"; print " [-B ] (add requires for src packages)\n\n"; print " [-Q ] (never use Shr tags)\n"; print " [-H ] (Use headers)\n\n"; print " Note: the -T option allows to add additional tags to the\n"; print " resulting packages file.\n"; print " The file should contain the package name, a colon and\n"; print " a whitespace. Afterwards, additional tags in one line\n"; print " (newlines can be produced via \\n).\n"; print " Example: 3ddiag: +Kwd:\\nsupport_l3\\n-Kwd:\n"; exit $exit_code; } sub filter_weak { my ($r, $tn, $tf) = @_; my @tf = @{$r->{$tf} || []}; my @res; for (@{$r->{$tn}}) { push @res, $_ unless (shift @tf) & 0x8000000; } return @res; } sub filter_strong { my ($r, $tn, $tf) = @_; my @tf = @{$r->{$tf} || []}; my @res; for (@{$r->{$tn}}) { push @res, $_ if (shift @tf) & 0x8000000; } return @res; } my @SAVEARGS; for (@ARGV) { push @SAVEARGS, $_; } while ( my $arg = shift ( @ARGV ) ) { if ( $arg eq "-d" ) { push @DATADIRS , shift @ARGV ; } elsif ( $arg eq "-B" ) { $src_requires = 1; } elsif ( $arg eq "-V" ) { $add_vendor = 1; } elsif ( $arg eq "-C" ) { $do_checksums = "1"; } elsif ( $arg eq "-D" ) { $do_checksums = "1"; $do_sha256 = "1"; $checksum_binary = "sha256sum"; } elsif ( $arg eq "-F" ) { $do_file_list = 1; } elsif ( $arg eq "-H" ) { $use_headers = 1; } elsif ( $arg eq "-I" ) { $ignore_file = shift @ARGV ; } elsif ( $arg eq "-K" ) { $do_keywords = "1"; } elsif ( $arg eq "-L" ) { $ignore_symlinks = "1"; } elsif ( $arg eq "-M" ) { $maxdepth = shift @ARGV ; } elsif ( $arg eq "-P" ) { $prefer_yastdescr = "1"; } elsif ( $arg eq "-S" ) { $ignore_sources = "1"; } elsif ( $arg eq "-Z" ) { $add_licenses = "1" ; } elsif ( $arg eq "-Q" ) { $allow_shr = 0; } elsif ( $arg eq "-c" ) { push @SHA_CACHEDIR , shift @ARGV ; } elsif ( $arg eq "-i" ) { push @IGNOREDIRS, shift @ARGV ; } elsif ( $arg eq "-l" ) { push @LANGUAGES , shift @ARGV ; } elsif (( $arg eq "-h" ) || ( $arg eq "--help" )) { shift @ARGV ; usage(0); } elsif ( $arg eq "-o" ) { $output_dir = shift @ARGV ; } elsif ( $arg eq "-p" ) { $unused_data_dir = shift @ARGV ; } elsif ( $arg eq "-e" ) { $eula_data_dir = shift @ARGV ; } elsif ( $arg eq "-r" ) { $extra_requires = shift @ARGV ; } elsif ( $arg eq "-x" ) { $extra_provides = shift @ARGV ; } elsif ( $arg eq "-T" ) { $extra_tags = shift @ARGV ; } else { print STDERR "\nunknown parameter $arg\n\n"; usage(1); } } if ( $ignore_symlinks eq "1" ) { $with_links = "-type f"; } else { $with_links = ""; } for (@SHA_CACHEDIR) { $have_sha_cache++ if ( -d $_ ); } push @DATADIRS , "." unless ( @DATADIRS ); push @LANGUAGES , "$default_lang" unless ( @LANGUAGES ); $output_dir = "./setup/descr/" unless ( $output_dir ); print "INFO: datadirs : ".join(",",@DATADIRS)."\n"; print "INFO: languages : ".join(",",@LANGUAGES)."\n"; print "INFO: output dir : $output_dir\n"; if ( $extra_provides ) { if ( -f $extra_provides ) { print "INFO: extra_provides : $extra_provides\n"; %xprovlist = %{ReadFileToHash( $extra_provides )}; } else { print "WARNING: extra_provides : file $extra_provides not found!\n"; } } else { print "WARNING: -x not specified\n"; print "WARNING: this means all provides like /bin/sh will be missing\n"; } if ( $extra_requires ) { if ( -f $extra_requires ) { print "INFO: extra_requires : $extra_requires\n"; %xreqlist = %{ReadFileToHash( $extra_requires )}; } else { print "WARNING: extra_requires : file $extra_requires not found!\n"; } } if ( $extra_tags ) { if ( -f $extra_tags ) { print "INFO: extra_tags : $extra_tags\n"; %xtaglist = %{ReadFileToHash( $extra_tags )}; } else { print "WARNING: extra_tags : file $extra_tags not found!\n"; } } unless ( -d "$output_dir" ) { print "INFO: creating output directory $output_dir\n"; mkdir_p("$output_dir"); } if ( @IGNOREDIRS ) { foreach $ignore_dir (@IGNOREDIRS) { if ( -d "$ignore_dir" && opendir ( IGNDIR, "$ignore_dir") ) { while ( my $ign = readdir( IGNDIR ) ) { next if ( $ign =~ /^\./ ); $IGNORE_PACKAGE{$ign} = "yes"; } closedir ( IGNDIR ); print "INFO: ignoring packages listed in directory $ignore_dir\n"; } } } if ( "$ignore_file" ) { if ( -f "$ignore_file" && open ( IGNFILE, "$ignore_file" ) ) { while ( my $ign = <IGNFILE> ) { chomp ( $ign ); $IGNORE_PACKAGE{$ign} = "yes"; } close ( IGNFILE ); print "INFO: ignoring packages listed in file $ignore_file\n"; } } if ( $ignore_sources eq "1" ) { print "WARNING: ignoring all source packages\n"; } my $pkg_main = OpenFileWrite ( "$output_dir/packages" ); WriteSEntry( $pkg_main, "Ver", "2.0" ); foreach my $lang (@LANGUAGES) { $pkg_lang{$lang} = OpenFileWrite ( "$output_dir/packages.$lang_alias{$lang}" ); WriteSEntry( $pkg_lang{$lang}, "Ver", "2.0" ); } my $pkg_du = OpenFileWrite ( "$output_dir/packages.DU" ); my $pkg_fl = OpenFileWrite ( "$output_dir/packages.FL" ) if $do_file_list; WriteSEntry( $pkg_du, "Ver", "2.0" ); WriteSEntry( $pkg_fl, "Ver", "2.0" ) if $do_file_list; my $media_number = 0; my $allcounter = 0; my $wrote_comment = 0; foreach my $datapath (@DATADIRS) { $media_number++; open ( FIND, "find '$datapath' -maxdepth 2 $with_links -name \"*.[rs]pm\" -print | sort |" ); my @pkg_arr = (); my @src_arr = (); while ( <FIND> ) { chomp ( $_ ); next if (/\.delta\.rpm$/); if ( /\.spm$/ || /src\.rpm$/ ) { push @src_arr, $_; } else { push @pkg_arr, $_; } } close ( FIND ); foreach my $package (@pkg_arr,@src_arr) { $allcounter++; print "INFO: CD$media_number - Pkg: $allcounter\r" if ( -t STDOUT ); my $filespec = "$package"; chomp ( $filespec ); $filespec =~ /\/([^\/]*)$/; my $filename = $1; my $filesize; # name, version, release, arch, obsolete, requires, provides, # conflicts, copyright, group, buildtime, size, sourcerpm my %res = RPMQ::rpmq_many("$package", 1000, 1001, 1002, 1022, 1090, 1114, 1115, 1047, 1112, 1113, 1049, 1048, 1050, 1054, 1053, 1055, 1156, 1157, 1158, 1159, 1160, 1161, 1027, 1116, 1117, 1118, 1030, 1028, 1095, 1096, 1014, 1016, 1006, 1009, 1044, 1004, 1005, 1011, 1124, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, "HEADERSTART", "SIGTAG_SIZE", "EXTRA" ); # skip delta rpms (if PAYLOADFORMAT eq drpm) next if ($res{1124}[0] && $res{1124}[0] eq "drpm"); # my $data = $res{"SIGTAG_SIZE"}[0]; my $header = $res{"HEADERSTART"}[0]; my @depexcl = $res{1054}; my @prereq = rpmq_add_req_flagsvers(\%res, 1049, 1048, 1050); # requires RPMQ::rpmq_add_flagsvers(\%res, 1047, 1112, 1113); # provides RPMQ::rpmq_add_flagsvers(\%res, 1090, 1114, 1115); # obsoletes RPMQ::rpmq_add_flagsvers(\%res, 1054, 1053, 1055); # conflicts RPMQ::rpmq_add_flagsvers(\%res, 1156, 1158, 1157) if $res{1156}; # oldsuggests RPMQ::rpmq_add_flagsvers(\%res, 1159, 1161, 1160) if $res{1159}; # oldenhances RPMQ::rpmq_add_flagsvers(\%res, 5046, 5048, 5047) if $res{5046}; # recommends RPMQ::rpmq_add_flagsvers(\%res, 5049, 5051, 5050) if $res{5049}; # suggests RPMQ::rpmq_add_flagsvers(\%res, 5052, 5054, 5053) if $res{5052}; # supplements RPMQ::rpmq_add_flagsvers(\%res, 5055, 5057, 5056) if $res{5055}; # enhances my $rpm_name = $res{1000}[0]; if ( $IGNORE_PACKAGE{$rpm_name} && $IGNORE_PACKAGE{$rpm_name} eq "yes" ) { $ignored_packages .= " $rpm_name"; next; } my @pack_path = split('/',"$package"); pop @pack_path; # filename pop @pack_path; # dirname / rpm-arch my $pack_basedir = join('/',@pack_path); my $checksum = ""; my $dummy = ""; my $hash = ""; my $DULIST; my $FLIST; my $file_arch; my %pacdata; if ( $use_headers eq "1" ){ $filesize = $res{'EXTRA'}[0]{size}; } else { $filesize = $data + $header; } my $srcrpm = $res{1044}[0]; $srcrpm =~ s/^(.*)-([^-]*)-([^-]*)\.([^\.]*)\.rpm$/$1 $2 $3 $4/; if ($do_checksums eq "1" && $use_headers ne "1") { if ( $have_sha_cache ne "0" ) { my %qq = RPMQ::rpmq_many("$package", qw{SIGTAG_GPG SIGTAG_PGP SIGTAG_SHA1}); if ( %qq ) { for (qw{SIGTAG_GPG SIGTAG_PGP SIGTAG_SHA1}) { $hash .= join('', @{$qq{$_} || []}); } $hash = Digest::MD5::md5_hex($hash); } for (@SHA_CACHEDIR) { if ( -f "$_/$rpm_name-$hash" ) { open ( CSC, "< $_/$rpm_name-$hash" ); $checksum = <CSC>; chomp ($checksum); close ( CSC ); #print "INFO: re_using checksum for $package ($checksum)\n"; } } if ($do_sha256 eq "1") { $checksum = "" unless length($checksum) == 64; } else { $checksum = "" unless length($checksum) == 40; } } if ( ! $checksum ) { if ( $res{1044}[0] || $ignore_sources eq "0") { ($checksum,$dummy) = split('\s+',`$checksum_binary '$package'`); if ( $have_sha_cache eq "1" ) { open ( CSC, "> $SHA_CACHEDIR[0]/$rpm_name-$hash" ); print CSC $checksum; close ( CSC ); #print "INFO: wrote checksum for $package ($checksum)\n"; } } } } if ($use_headers eq "1") { if ($checksum_binary == "sha1sum") { $checksum = $res{'EXTRA'}[0]{sha1}; }elsif ($checksum_binary == "sha256sum"){ $checksum = $res{'EXTRA'}[0]{sha256}; } } if ( $res{1044}[0] ) { ($DULIST,$FLIST) = RpmToDulist($maxdepth, \%res, ''); $file_arch = $res{1022}[0]; } else { next if ( $ignore_sources eq "1" ); # has no source, so it is a source if ( $filename =~ /\.spm$/ ) { $file_arch = "src"; } else { $file_arch = "$filename"; $file_arch =~ s/^.*\.([^\.]*)\.rpm$/$1/; } ($DULIST,$FLIST) = RpmToDulist($maxdepth, \%res, 'usr/src/packages/'); } my %x_prov = (); if ( $xprovlist{"$rpm_name.$file_arch"} ) { foreach my $xprov (split('\s', $xprovlist{"$rpm_name.$file_arch"} )) { $x_prov{$xprov} = 1; } } # should be else if, but merging both is needed right now if ( $xprovlist{$rpm_name} ) { foreach my $xprov (split('\s', $xprovlist{$rpm_name} )) { $x_prov{$xprov} = 1; } } # add createrepo-style file provides (/etc/*,*bin/*,/usr/lib/sendmail) foreach $filename (@{$res{1027}}) { $x_prov{$filename} = 1 if ( $filename =~ /^\/etc\// || $filename =~ /bin\// || $filename eq "/usr/lib/sendmail" ); } push @{$res{1047}}, sort keys %x_prov; # adding additional requires for a package (but not for src packages) if ($xreqlist{$rpm_name} && $res{1044}[0]) { foreach my $xreq (split('\s', $xreqlist{$rpm_name} )) { push (@{$res{1049}},$xreq); } } WriteSeparator( $pkg_main ); WriteComment( $pkg_main, @SAVEARGS ) unless $wrote_comment; WriteSeparator( $pkg_main ) unless $wrote_comment; $wrote_comment = 1; WriteSEntry( $pkg_main, "Pkg", "$res{1000}[0] $res{1001}[0] $res{1002}[0] $file_arch"); if ($do_sha256 eq "1") { WriteSEntry( $pkg_main, "Cks", "SHA256 $checksum") if ($checksum); } else { WriteSEntry( $pkg_main, "Cks", "SHA1 $checksum") if ($checksum); } if ( $res{1044}[0] ) { # has src, so it's a binary package WriteMEntry( $pkg_main, "Req", @{$res{1049}} ); WriteMEntry( $pkg_main, "Prq", @prereq ); WriteMEntry( $pkg_main, "Prv", @{$res{1047}} ); WriteMEntry( $pkg_main, "Con", @{$res{1054}} ); WriteMEntry( $pkg_main, "Obs", @{$res{1090}} ); WriteMEntry( $pkg_main, "Rec", @{$res{5046}} ) if $res{5046}; WriteMEntry( $pkg_main, "Rec", filter_strong(\%res, 1156, 1158)) if !$res{5046} && $res{1156}; WriteMEntry( $pkg_main, "Sug", @{$res{5049}} ) if $res{5049}; WriteMEntry( $pkg_main, "Sug", filter_weak(\%res, 1156, 1158)) if !$res{5049} && $res{1156}; WriteMEntry( $pkg_main, "Sup", @{$res{5052}} ) if $res{5052}; WriteMEntry( $pkg_main, "Sup", filter_strong(\%res, 1159, 1161)) if !$res{5052} && $res{1159}; WriteMEntry( $pkg_main, "Enh", @{$res{5055}} ) if $res{5055}; WriteMEntry( $pkg_main, "Enh", filter_weak(\%res, 1159, 1161)) if !$res{5055} && $res{1159}; WriteSEntry( $pkg_main, "Grp", $res{1016}[0] ); WriteSEntry( $pkg_main, "Lic", $res{1014}[0] ); WriteSEntry( $pkg_main, "Vnd", $res{1011}[0] ) if $add_vendor; WriteSEntry( $pkg_main, "Src", $srcrpm ); WriteSEntry( $pkg_main, "Tim", $res{1006}[0] ); WriteSEntry( $pkg_main, "Loc", "$media_number $filename"); } else { WriteMEntry( $pkg_main, "Req", @{$res{1049}} ) if $src_requires; WriteSEntry( $pkg_main, "Loc", "$media_number $filename $file_arch"); } WriteSEntry( $pkg_main, "Siz", "$filesize $res{1009}[0]" ); WriteAnyEntry( $pkg_main, $xtaglist{$rpm_name} ) if ($xtaglist{$rpm_name} && $res{1044}[0]); if ($SEEN_PACKAGE{"$rpm_name $res{1001}[0] $res{1002}[0]"} && $allow_shr) { my $found_in = $SEEN_PACKAGE{"$rpm_name $res{1001}[0] $res{1002}[0]"}; WriteSEntry( $pkg_main, "Shr", "$res{1000}[0] $res{1001}[0] $res{1002}[0] $found_in"); } else { foreach my $lang (@LANGUAGES) { WriteSeparator( $pkg_lang{$lang} ); WriteSEntry( $pkg_lang{$lang}, "Pkg", "$res{1000}[0] $res{1001}[0] $res{1002}[0] $file_arch"); WriteSEntry( $pkg_lang{$lang}, "Sum", "$res{1004}[0]" ); WriteMEntry( $pkg_lang{$lang}, "Des", split('\n', $res{1005}[0] )); if ( $add_licenses eq "1" && -f "$eula_data_dir/$rpm_name.en") { open (LIC,"$eula_data_dir/$rpm_name.en"); my @license = <LIC>; close (LIC); WriteMEntry( $pkg_lang{$lang}, "Eul", @license); } } } WriteSeparator( $pkg_du ); WriteSEntry( $pkg_du, "Pkg", "$res{1000}[0] $res{1001}[0] $res{1002}[0] $file_arch"); WriteMEntry( $pkg_du, "Dir", @{$DULIST} ); if ($do_file_list) { WriteSeparator( $pkg_fl ); WriteSEntry( $pkg_fl, "Pkg", "$res{1000}[0] $res{1001}[0] $res{1002}[0] $file_arch"); WriteMEntry( $pkg_fl, "Fls", @{$FLIST} ); } $SEEN_PACKAGE{"$rpm_name $res{1001}[0] $res{1002}[0]"} = $file_arch unless $SEEN_PACKAGE{"$rpm_name $res{1001}[0] $res{1002}[0]"}; } } print "INFO: processed $allcounter packages in $media_number volumes\n"; if ( $ignored_packages ) { print "INFO: following packages were ignored: $ignored_packages\n"; } close ( $pkg_main ); foreach my $lang (@LANGUAGES) { close ( "$pkg_lang{$lang}" ); } close ( $pkg_du ); close ( $pkg_fl ) if $do_file_list; ##################################################################### ##################################################################### sub mkdir_p { my $dir = shift; return 1 if -d "$dir"; if ($dir =~ /^(.*)\//) { mkdir_p("$1") || return undef; } return undef if !mkdir("$dir", 0777); return 1; } sub OpenFileWrite { my $filename = shift; my ($FH) = new FileHandle; open ($FH, ">$filename") || die "ERROR: can't write output file $filename"; return $FH; } sub OpenFileRead { my $filename = shift; my ($FH) = new FileHandle; open ($FH, "<$filename") || die "ERROR: can't read input file $filename"; return $FH; } sub ReadFileToHash { my ($filename) = @_; my (%temp); my $FH = OpenFileRead( "$filename" ); while (<$FH>) { chomp ($_); last if ( $_ =~ /^:END/ ); next if ( $_ =~ /^\#/ ); next if ( $_ =~ /^\s$/ ); my ($le,$ri) = split (/:/, $_, 2 ); $le =~ s/^\s*(.*)\s*$/$1/; $ri =~ s/^\s*(.*)\s*$/$1/; $ri =~ s/\\n/\n/g; $temp{$le}=$ri; } close ($FH); \%temp; } sub WriteSeparator { my ($FH) = shift; print $FH "##----------------------------------------\n"; } sub WriteComment { my ($FH,@XX) = @_; print $FH "## ".join(" ",@XX)."\n"; } sub utf8ify { my ($value) = @_; eval { Encode::_utf8_on($value); $value = encode('UTF-8', $value, Encode::FB_CROAK); }; if ($@) { Encode::_utf8_off($value); $value = encode('UTF-8', $value, Encode::FB_DEFAULT); } Encode::_utf8_off($value); return $value; } sub WriteAnyEntry { my ($FH,$value) = @_; $value = utf8ify($value) if $value =~ /[\200-\377]/s; print $FH "$value\n"; } sub WriteSEntry { my ($FH,$tag,$value) = @_; if ( $value ) { $value = utf8ify($value) if $value =~ /[\200-\377]/s; print $FH "=$tag: $value\n"; } } sub WriteMEntry { my ($FH,$tag,@value) = @_; if ( @value && $value[0] ) { my $value = join("\n", @value); $value = utf8ify($value) if $value =~ /[\200-\377]/s; print $FH "+$tag:\n$value\n-$tag:\n"; } } sub RpmToDulist { my $maxdepth = shift; my $res = shift; my $prefix = shift; if (!$res->{1027}) { my @newfl = (); my @di = @{$res->{1116} || []}; for (@{$res->{1117} || []}) { my $di = shift @di; push @newfl, $res->{1118}->[$di] . $_; } $res->{1027} = [ @newfl ]; } my @modes = @{$res->{1030} || []}; my @devs = @{$res->{1095} || []}; my @inos = @{$res->{1096} || []}; my @names = @{$res->{1027} || []}; my @sizes = @{$res->{1028} || []}; my %seen = (); my %dirnum = (); my %subdirnum = (); my %dirsize = (); my %subdirsize = (); my ($name, $first); my @flist = (); for $name (@names) { my $mode = shift @modes; my $dev = shift @devs; my $ino = shift @inos; my $size = shift @sizes; # strip leading slash # prefix is either empty or ends in / $name =~ s/^\///; $name = "$prefix$name"; push @flist, "/$name"; # check if regular file next if ($mode & 0170000) != 0100000; # don't count hardlinks twice next if $seen{"$dev $ino"}; $seen{"$dev $ino"} = 1; # rounded size in kbytes $size = int ($size / 1024) + 1; $name = '' unless $name =~ s/\/[^\/]*$//; if ( ($name =~ tr/\///) < $maxdepth ) { $dirsize{"$name/"} += $size; $dirnum{"$name/"} += 1; $subdirsize{"$name/"} ||= 0; # so we get all keys } # traverse though path stripping components from the back $name =~ s/\/[^\/]*$// while ( ($name =~ tr/\///) > $maxdepth ); while ($name ne '') { $name = '' unless $name =~ s/\/[^\/]*$//; $subdirsize{"$name/"} += $size; $subdirnum{"$name/"} += 1; } } my @dulist = (); for $name (sort keys %subdirsize) { next unless $dirsize{$name} || $subdirsize{$name}; $dirsize{$name} ||= 0; $subdirsize{$name} ||= 0; $dirnum{$name} ||= 0; $subdirnum{$name} ||= 0; push @dulist, "$name $dirsize{$name} $subdirsize{$name} $dirnum{$name} $subdirnum{$name}"; } return \@dulist,\@flist; } sub rpmq_add_req_flagsvers { my $res = shift; my $name = shift; my $flags = shift; my $vers = shift; my @prereq = (); return unless $res; my @flags = @{$res->{$flags} || []}; my @vers = @{$res->{$vers} || []}; for (@{$res->{$name}}) { if (@flags && ($flags[0] & 0xe) && @vers) { $_ .= ' '; $_ .= '<' if $flags[0] & 2; $_ .= '>' if $flags[0] & 4; $_ .= '=' if $flags[0] & 8; $_ .= " $vers[0]"; } # set on RPMSENSE_PREREQ, RPMSENSE_SCRIPT_PRE and RPMSENSE_SCRIPT_POST if ( $flags[0] & (64+512+1024) ) { push ( @prereq, $_ ); } shift @flags; shift @vers; } return @prereq; } 07070100000009000081ED000000000000000000000001654BBDF900001E83000000000000000000000000000000000000003E00000000inst-source-utils-2023.11.08/usr/bin/create_repo_for_patch.sh#!/bin/bash # # create_repo_for_patch.sh # # Copyright (C) 2006 Novell Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., # 51 Franklin Street, # Fifth Floor, # Boston, MA 02110-1301, # USA. # # $Id: create_repo_for_patch.sh 182 2009-08-07 17:39:16Z lrupp $ # MYSTART=$(pwd) PATCHESFILE="patches.xml" PREFIX="patch-" DEBUG="" SIGN_ID="" RPMDIR="$(pwd)" REPODIR="$(pwd)" PREFIX="patch-" INCSRC="" function usage (){ echo echo "Usage: $(basename $0) [options] <source directory containing RPMs> <target directory>" echo " -h : help (this message)" echo " -p : patch files (if not located in <target_directory>)" echo " -P : prefix for patchfiles (default: $PREFIX)" echo " -S : detached sign the repomd.xml file" echo " -l : set symlink to source directory" echo " -s : include source rpms" echo " -I <KEY_ID> : key-id to use for signing the repomd.xml file, if not given" echo " gpg will try to use the default signing key" echo " -v : be verbose" echo echo " example: $0 -S /srv/install/ ." echo echo "WARING: $(basename $0) will delete all files except patch files in <target directory> !" echo exit $1 } function check_binary(){ local BINARY=$(type -p $1 2>/dev/null) if [ x"$BINARY" = x"" ]; then echo "ERROR: $1 not found! Please install the missing package first!" >&2 exit 3 fi if [ -x "$BINARY" ]; then echo "$BINARY" else echo "ERROR: $BINARY found but is not executable - please fix!" >&2 exit 3 fi } if [ ! "$1" ]; then usage 1 fi while getopts 'hvSI:p:P:ls' OPTION ; do case $OPTION in h) usage 0 ;; p) PATCHDIR="$OPTARG" ;; P) PREFIX="$OPTARG" ;; l) LINKRPM="1" ;; s) INCSRC="1" ;; S) SIGN="yes" ;; I) SIGN_ID="$OPTARG" ;; v) DEBUG="1" ;; *) usage 1 ;; esac done shift $(( OPTIND - 1 )) RPMDIR="$1" REPODIR="$2" CREATEREPO=$(check_binary "createrepo") if [ $? != 0 ]; then exit fi if [ -z "$RPMDIR" ]; then echo "ERROR: source directory not defined" >&2 usage 1 fi if [ -z "$REPODIR" ]; then echo "ERROR: target directory not defined" >&2 usage 1 fi if [ -d "$REPODIR/repodata.tmp" ]; then echo "ERROR: $REPODIR/repodata.tmp exists - exiting" >&2 exit 1 fi mkdir -p "$REPODIR/repodata.tmp" || { echo "ERROR: Cannot create ${REPODIR}/repodata.tmp"; exit 5; } PATCHDIR=${PATCHDIR-/$RPMDIR} echo "INFO: --- Looking for Patches in Patchdirectory: ${PATCHDIR}" for i in $(find "${PATCHDIR}/" -name "${PREFIX}*"); do [ "$DEBUG" ] && echo "INFO: Copying patch: $i" cp "$i" "$REPODIR/repodata.tmp/" || { echo "ERROR: Cannot copy $i" >&2; exit 7; } PATCHFILES="$PATCHFILES $(basename $i)" done [ -d "$REPODIR/repodata" ] && rm -r "$REPODIR/repodata" [ -d "$REPODIR/.olddata" ] && rm -r "$REPODIR/.olddata" mkdir "$REPODIR/repodata" if [ "${LINKRPM}" ]; then echo "INFO: --- Linking rpms from ${RPMDIR}" ln -s "${RPMDIR}/rpm" ${REPODIR} || echo "WARNING: Cannot create link to ${REPODIR}" >&2 else echo "INFO: --- Copying RPMs from $RPMDIR" [ -d "${REPODIR}/rpm" ] && rm -r $REPODIR/rpm/* [ "$INCSRC" ] && mkdir -p "$REPODIR/rpm/src/" fi for patchfile in $(ls "$REPODIR"/repodata.tmp/${PREFIX}*); do patch=$(basename "$patchfile") for rpmfile in $(grep "location href" "$patchfile" | cut -d "\"" -f2); do arch_dir=$(dirname "$rpmfile" | xargs basename) if [ "${LINKRPM}" ]; then continue # do not copy files else [ -d "$REPODIR/rpm/$arch_dir" ] || mkdir -p "$REPODIR/rpm/$arch_dir" fi if [[ $rpmfile == *.delta.rpm ]]; then continue; fi if [[ $rpmfile == *.patch.rpm ]]; then continue; fi [ "$DEBUG" ] && echo "INFO: Copying file: $RPMDIR/$rpmfile to $REPODIR/rpm/$arch_dir/" cp -a "$RPMDIR/$rpmfile" "$REPODIR/rpm/$arch_dir/" 2>/dev/null || { echo "ERROR: Cannot copy $RPMDIR/$rpmfile" >&2; exit 8; } if ! [ "${INCSRC}" ]; then continue; fi # Include source files? SRCRPM=$(rpm -qp --nodigest --nosignature --qf "%{SOURCERPM}" "$RPMDIR/$rpmfile") [ "$DEBUG" ] && echo "INFO: Copying file: ${RPMDIR}/rpm/src/${SRCRPM}" cp -a "$RPMDIR/rpm/src/$SRCRPM" "$REPODIR/rpm/src/" 2>/dev/null || echo "WARNING: Cannot copy source rpm ${RPMDIR}/rpm/src/${SRCRPM}" >&2 done done # # createrepo # echo "INFO: --- Creating repodata with createrepo" if [ "$DEBUG" ]; then echo "INFO: Running command: ${CREATEREPO} -p -x "*.delta.rpm" -x "*.patch.rpm" $REPODIR" $CREATEREPO -p -x "*.delta.rpm" -x "*.patch.rpm" "$REPODIR" 2>/dev/null 1>&2 else $CREATEREPO -q -x "*.delta.rpm" -x "*.patch.rpm" "$REPODIR" 2>/dev/null 1>&2 fi # # patches.xml # echo "INFO: --- Creating new file $REPODIR/repodata/$PATCHESFILE" echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" > "$REPODIR/repodata/$PATCHESFILE" echo "<patches xmlns=\"http://novell.com/package/metadata/suse/patches\">" >> "$REPODIR/repodata/$PATCHESFILE" for patch in $(ls "$REPODIR/repodata.tmp"/patch*); do patchname=$(basename "$patch") patchid=$(basename "$patchname" .xml) sha1=$(sha1sum "$patch" | awk '" " { print $1 }') mv "$REPODIR/repodata.tmp/$patchname" "$REPODIR/repodata/" || next; echo " <patch id=\"$patchid\">" >> "$REPODIR/repodata/$PATCHESFILE" echo " <checksum type=\"sha\">$sha1</checksum>" >> "$REPODIR/repodata/$PATCHESFILE" echo " <location href=\"repodata/$patchname\"/>" >> "$REPODIR/repodata/$PATCHESFILE" echo " </patch>" >> "$REPODIR/repodata/$PATCHESFILE" done echo "</patches>" >> "$REPODIR/repodata/$PATCHESFILE" # # repomd.xml # echo "INFO: --- patching $REPODIR/repodata/repomd.xml" sha1=$(sha1sum "$REPODIR/repodata/$PATCHESFILE" | awk '" " { print $1 }') timestamp=$(date +"%Y%m%d%H") cat >"$REPODIR/repodata.tmp/repomd.xml.patch$$" <<EOF <data type="patches"> <location href="repodata/patches.xml"/> <checksum type="sha">$sha1</checksum> <timestamp>$timestamp</timestamp> <open-checksum type="sha">$sha1</open-checksum> </data> </repomd> EOF sed -i '/.*<\/repomd>.*/d' "$REPODIR/repodata/repomd.xml" || { echo 'ERROR: sed command failed!' >&2; exit 9; } cat "$REPODIR/repodata.tmp/repomd.xml.patch$$" >> "$REPODIR/repodata/repomd.xml" rm -r "$REPODIR/repodata.tmp" # # repomd.xml.key # if [ "$SIGN" == "yes" ]; then echo "INFO: --- Signing repomd.xml" if [ "${SIGN_ID}" = "" ]; then if [ -f "/etc/sign.conf" ]; then [ "$DEBUG" ] && echo "INFO: Try to sign with key from /etc/sign.conf" if [ -x $(type -p sign) ]; then $(type -p sign) -d "$REPODIR/repodata/repomd.xml" else echo "ERROR: Could not execute 'sign'" >&2 exit 1; fi else gpg -a -b "${REPODIR}/repodata/repomd.xml" fi SIGN_ID=$(gpg --verify "${REPODIR}/repodata/repomd.xml.asc" 2>&1 | sed -ne "s/.* ID //p") else gpg -a -b --default-key ${SIGN_ID} "${REPODIR}/repodata/repomd.xml" fi echo "INFO: with Key-ID: ${SIGN_ID}" gpg -a --export ${SIGN_ID} > "${REPODIR}/repodata/repomd.xml.key" fi 0707010000000A000081ED000000000000000000000001654BBDF900000E21000000000000000000000000000000000000003400000000inst-source-utils-2023.11.08/usr/bin/create_sha1sum#!/bin/bash # # Copyright (C) 2008 Novell Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., # 51 Franklin Street, # Fifth Floor, # Boston, MA 02110-1301, # USA. # # $Id: create_sha1sum 1012 2013-02-17 10:49:03Z lrupp $ # function usage (){ echo echo "Usage: `basename $0` [--meta] <targetdir>" echo " --meta : also create MD5SUMS.meta file" echo " --quiet: don't output anything" echo echo " Creates SHA1SUMS files in each subdirectory." echo " Sometimes useful for debugging inst-source problems ;-)" echo exit $1 } function output(){ if [ "$QUIET" != "yes" ]; then echo "$1" fi } unset LANGUAGE unset LANG export LC_ALL=POSIX umask 022 CREATE_META= QUIET="no" CHECKSUM="sha1sum" CHECKSUM_F="SHA1SUMS" while test -n "$1" ; do case $1 in --) shift ; break ;; -h|--help) usage 0 ;; -m|--meta) CREATE_META=1 ; shift ;; -q|--quiet) QUIET="yes" ; shift ;; -2) CHECKSUM="sha256sum" ; CHECKSUM_F="CHECKSUMS" ; shift ;; *) break ;; esac done if [ -z "$1" ]; then usage 1; fi TMPFILE=$(mktemp /tmp/.create_sha1sums.XXXXXX) MYPWD=$(pwd) for ROOTDIR in "$@" ; do case "$ROOTDIR" in /*) ;; *) ROOTDIR="$MYPWD/$ROOTDIR" ;; esac test -d "$ROOTDIR" || { echo "WARNING: $ROOTDIR is not a directory. Skipping it." >&2 } find "$ROOTDIR" -type d | while read DIR; do cd "$DIR" unset FILES NFILES=0 for FILE in * ; do test -f "$FILE" || continue test -L "$FILE" && continue test -n "$SHA1SUM_SKIPFILES" && { IS_SKIP=false set -f for i in $SHA1SUM_SKIPFILES ; do set +f case "$FILE" in ($i) IS_SKIP=true break ;; esac done set +f test $IS_SKIP = true && continue } case "$FILE" in (*.swp|SHA1SUMS*|CHECKSUMS*|MD5SUMS*) continue ;; (*) FILES[$[++NFILES]]="$FILE" ;; esac done if [ $NFILES -eq 0 ]; then rm -f SHA1SUMS* CHECKSUMS* else echo -n > $TMPFILE for FILE in "${FILES[@]}"; do $CHECKSUM "$FILE" >> $TMPFILE done test -e $CHECKSUM_F || touch $CHECKSUM_F cmp -s $TMPFILE $CHECKSUM_F || { mv $TMPFILE $CHECKSUM_F chmod 644 $CHECKSUM_F output "INFO: created $CHECKSUM_F in $DIR" } if test -n "$CREATE_META"; then test -e $CHECKSUM_F.meta || touch $CHECKSUM_F.meta $CHECKSUM $CHECKSUM_F > $TMPFILE cmp -s $TMPFILE $CHECKSUM_F.meta || { mv $TMPFILE $CHECKSUM_F.meta chmod 644 $CHECKSUM_F.meta output "INFO: created $CHECKSUM_F.meta in $DIR" } fi rm -f $TMPFILE fi done done 0707010000000B000081ED000000000000000000000001654BBDF900001366000000000000000000000000000000000000003500000000inst-source-utils-2023.11.08/usr/bin/create_sha1sums#!/bin/bash # # Copyright (C) 2007 Novell Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License 2 # as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., # 51 Franklin Street, # Fifth Floor, # Boston, MA 02110-1301, # USA. # # $Id: create_sha1sums 1012 2013-02-17 10:49:03Z lrupp $ # SIGN="yes" SIGN_OPTS="" INCLUDE_SHA1SUMS="no" EXTRA="no" CHECKSUM="sha1sum" CHECKSUM_T="SHA1" CHECKSUM_F="SHA1SUMS" CHECKSUM_O="" unset LANGUAGE unset LANG export LC_ALL=POSIX umask 022 function usage() { echo "Usage: `basename $0` [OPTIONS] <CD-Rootdir>" echo " -n : don't re-sign the generated files" echo " -m : include SHA1SUMS files (or CHECKSUMS files for others)" echo " -2 : use sha256 instead of sha1" echo " -x : add sha1sums for extra files" echo echo " (re-)creates the SHA*SUM lines in the content file" echo " and signs the content and products file" exit $1 } function signit(){ if [ "$(type -p sign 2>/dev/null)" != "" ]; then # if sign -t ; then sign $SIGN_OPTS -d $1 sign $SIGN_OPTS -p > $1.key # else # : > $1.asc # cp //keys/default $1.key # fi else gpg -a -b $1 KEY_ID=`gpg -b < /dev/null | gpg --list-packets | sed -n -e "/^:signature/s@.*keyid @@p"` gpg --export --armor $KEY_ID > $1.key fi } while getopts 'hnmx2s:' OPTION ; do case $OPTION in h) usage 0 ;; m) INCLUDE_SHA1SUMS="yes" ;; n) SIGN="no" ;; s) SIGN_OPTS=$OPTARG ;; x) EXTRA="yes" ;; 2) CHECKSUM="sha256sum" CHECKSUM_T="SHA256" CHECKSUM_F="CHECKSUMS" CHECKSUM_O="-2" ;; esac done shift $(( OPTIND - 1 )) if [ ! "$1" ]; then usage 1 fi CDS_PRIM=$1 if [ "$1" = "." ]; then CDS_PRIM=$(pwd) fi if [ -f $CDS_PRIM/content ] ; then # prepare content file CONTTMP=$(mktemp $CDS_PRIM/content-XXXXXX) grep -v "^META " $CDS_PRIM/content | grep -v "^KEY " | grep -v "^HASH SHA" > $CONTTMP mv $CONTTMP $CDS_PRIM/content # add pattern and packages files to content file DESCRDIR=`grep DESCRDIR $CDS_PRIM/content | awk '" " { print $2 }'` if [ -z "$DESCRDIR" ]; then DESCRDIR="suse/setup/descr" fi if test -d $CDS_PRIM/$DESCRDIR ; then pushd $CDS_PRIM/$DESCRDIR >/dev/null rm -f *.asc $CHECKSUM * 2>/dev/null | grep -v "MD5SUMS" | grep -v "directory.yast" | sed -e "s@^@META $CHECKSUM_T @" >> $CDS_PRIM/content popd >/dev/null fi pushd $CDS_PRIM >/dev/null if [ "$EXTRA" = "yes" ] ; then for i in license.tar.gz control.xml installation.xml media.1/info.txt media.1/license.zip y2update.tgz driverupdate; do test -f $i || continue $CHECKSUM $i 2>/dev/null | sed -e "s@^@HASH $CHECKSUM_T @" >> $CDS_PRIM/content done for i in boot/*/* boot/*/loader/linux boot/*/loader/initrd boot/*/loader/*.spl docu/* images/* ; do test -f $i || continue $CHECKSUM $i 2>/dev/null | sed -e "s@^@HASH $CHECKSUM_T @" >> $CDS_PRIM/content done # check if we need to include additional files for > 11.0 if grep -q CONTENTSTYLE $CDS_PRIM/content; then DATADIR=$(grep DATADIR content | awk '" " { print $2 }') if [ -d "$CDS_PRIM/$DATADIR/setup/slide" ]; then SLIDESHOWDIR="$CDS_PRIM/$DATADIR/setup/slide" fi if test -n "$SLIDESHOWDIR" -a -d "$SLIDESHOWDIR" ; then /usr/bin/create_sha1sum $CHECKSUM_O --quiet "$SLIDESHOWDIR" fi if [ $SIGN = "yes" ]; then for sha1sumfile in $(find $SLIDESHOWDIR -name $CHECKSUM_F); do signit "$sha1sumfile" done fi fi fi if [ "$INCLUDE_SHA1SUMS" = "yes" ]; then for i in $(find $CDS_PRIM/ -name $CHECKSUM_F | sed -e "s|./||"); do test -f $i || continue $CHECKSUM $i 2>/dev/null | sed -e "s@^@HASH $CHECKSUM_T @" >> $CDS_PRIM/content done fi # add gpg-key files to content file $CHECKSUM gpg-pubkey-* 2>/dev/null | sed -e "s@^@KEY $CHECKSUM_T @" >> $CDS_PRIM/content popd >/dev/null fi # signing part if [ $SIGN = "yes" ]; then REPOFILE=`find $CDS_PRIM -type f -name repomd.xml 2>/dev/null` REPOFILE=${REPOFILE##$CDS_PRIM} REPOFILE=${REPOFILE##/} for file in content media.1/products $REPOFILE; do test -f $CDS_PRIM/${file}.asc && rm -f $CDS_PRIM/${file}.asc test -f $CDS_PRIM/${file} || continue signit $CDS_PRIM/${file} done fi # make sure everything is readable for all for file in content media.1/products $REPOFILE; do for xfile in $CDS_PRIM/$file* ; do test -e $xfile || continue chmod 644 $xfile done done 0707010000000C000081ED000000000000000000000001654BBDF9000014E0000000000000000000000000000000000000003D00000000inst-source-utils-2023.11.08/usr/bin/create_update_source.sh#!/bin/sh # # Copyright (C) 2006 Novell Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., # 51 Franklin Street, # Fifth Floor, # Boston, MA 02110-1301, # USA. # # This script creates an additional source in an existing tree to accomodate # update packages without changing the original product tree. # The script will only create the directory structure and the needed meta files. # # After running this script, you have to copy the packages into # # <source>/updates/suse/<arch> # # and run the script # # /usr/bin/create_package_descr -x setup/descr/EXTRA_PROV \ # # in the data directory (<source>/updates/suse) # after that do "cd setup/descr" and then: # for i in *; do echo -n "META SHA1 "; sha1sum $i|awk '{ORS=""; print $1}'; echo -n " "; basename $i; done # copy the output to the end of the updates/content file # # # Anas Nashif # Uwe Gansert (uwe.gansert@suse.de) # # Version 20060925 (uwe.gansert@suse.de) # - replaced =~ by grep to be compatible to pre bash 3.0 # # Version 20060420 (uwe.gansert@suse.de) # - suppress META SHA1 lines in the content file # # Version 20060418 (uwe.gansert@suse.de) # - added support for add-on products of SLES10/SL10.1 # # Version 20051207 (uwe.gansert@suse.de) # - added missing $SOURCE for the copy of the EXTRA_PROV file # thanx to Ian Grant # SOURCE=$1 ECHO="" UPDATES="$SOURCE/updates" NAME="Updates" tmpcontent=`mktemp /var/tmp/content-XXXXXX` if [ -z "$SOURCE" ]; then echo echo "Argument missing, Provide the root of the installation source as" echo "the first argument" echo exit 1 fi echo "Creating $UPDATES.." if test -d $UPDATES ; then echo echo "$UPDATES already exists, aborting"; echo exit 1 fi function create_dy() { test -d $1 || return; for i in `ls $1` ; do case $i in *directory.yast) continue ;; esac if test -d "$1/$i" ; then echo "$i/" else echo "$i" fi done > $1/directory.yast } if [ -f $SOURCE/content ] ; then while read KEY VALUE ; do case $KEY in DATADIR) DATADIR=$VALUE echo $KEY $VALUE ;; PRODUCT) echo $KEY $VALUE $NAME ;; DESCRDIR) DESCRDIR=$VALUE echo $KEY $VALUE ;; DISTPRODUCT) DISTPRODUCT=$VALUE echo "$KEY SuSE-Linux-Updates" ;; DISTVERSION) DISTVERSION=$VALUE ;; META) if [ -z "`echo -n $VALUE | grep SHA1`" ]; then echo $KEY $VALUE fi; ;; ARCH.*) if test -z "$ARCH"; then ARCH=$VALUE fi echo $KEY $VALUE ;; *) echo $KEY $VALUE esac done < $SOURCE/content > $tmpcontent DISTVERSION=`echo $DISTVERSION | tr '-' '#'` DISTIDENT="$DISTPRODUCT-$DISTVERSION" for i in $SOURCE/media.? ; do test -d $i || continue { read VENDOR read CREATIONDATE } < $i/media done fi $ECHO mkdir -p $UPDATES/$DATADIR $ECHO mkdir -p $UPDATES/media.1 for arch in $ARCH; do $ECHO mkdir -p $UPDATES/$DATADIR/$arch done $ECHO mkdir -p $UPDATES/$DESCRDIR if [ -f "$SOURCE/$DESCRDIR/EXTRA_PROV" ]; then $ECHO cp $SOURCE/$DESCRDIR/EXTRA_PROV $UPDATES/$DESCRDIR else echo "$DESCRDIR/EXTRA_PROV not found, trying to find it elsewhere..." find -name EXTRA_PROV -exec cp {} $UPDATES/$DESCRDIR \; fi $ECHO mkdir -p $UPDATES/media.1 { echo "SuSE Linux AG" date +%Y%m%d%H%M%S echo 1 } > $UPDATES/media.1/media { echo "/ $DISTPRODUCT-$NAME" } > $UPDATES/media.1/products if [ -x /usr/bin/create_package_descr ]; then create_package_descr -x $UPDATES/$DESCRDIR/EXTRA_PROV -d $UPDATES/$DATADIR \ -o $UPDATES/$DESCRDIR fi ( cd $UPDATES create_dy . for j in boot boot/loader $DESCRDIR media.1 ; do create_dy $j done if [ -d $DESCRDIR/../slide ] ; then for j in `find $DESCRDIR/../slide -type d ` ; do create_dy $j done fi ) mkdir -p $SOURCE/yast updates=`basename $UPDATES` if [ -f "$SOURCE/yast/order" ]; then if grep -q $updates $SOURCE/yast/order ; then echo echo "order/instorder already in place, not touching them" echo else CREATE_ORDER=1 fi else CREATE_ORDER=1 fi if [ "$CREATE_ORDER" = 1 ]; then echo "/$updates /$updates" >> $SOURCE/yast/order echo "/" >> $SOURCE/yast/order echo "/$updates" >> $SOURCE/yast/instorder echo "/" >> $SOURCE/yast/instorder fi cp $tmpcontent $UPDATES/content chmod a+r $UPDATES/content rm -f $tmpcontent 0707010000000D000081ED000000000000000000000001654BBDF900000CE0000000000000000000000000000000000000003700000000inst-source-utils-2023.11.08/usr/bin/create_updateinfo#!/usr/bin/perl -w use strict; use Getopt::Long; use IO::File; use XML::Writer; my $title = "empty title"; my $id = "unset"; my $description = "empty"; my $severity = "moderate"; my $type = "recommended"; my @references = (); GetOptions ( "type=s" => \$type, "title=s" => \$title, "id=s" => \$id, "severity=s" => \$severity, "description=s" => \$description, "reference=s" => \@references, ) or die("Error in command line arguments.\nUsage: $0 --type security|recommended --title TITLE --id ID --severity low|moderate|important|critical --description MULTILINETEXT --reference CVE-YEAR-ID LIST-OF-RPMS"); my %update = (); my $output = IO::File->new(">output.xml"); my $writer = XML::Writer->new(OUTPUT => $output, NEWLINES => 1, ENCODING => "utf-8"); # <update from="maint-coord@suse.de" status="stable" type="recommended" version="1"> $writer->startTag("update", "from" => "maint-coord\@suse.de", "status" => "stable", "type" => $type, "version" => "1" ); # <id>SUSE-SLE-Module-Basesystem-15-SP4-2022-1864</id> $writer->dataElement("id",$id); # <title>Recommended update for leveldb</title> $writer->dataElement("title",$title); # <severity>low</severity> $writer->dataElement("severity",$severity); # <release>SUSE Updates SLE-Module-Basesystem 15-SP4 x86 64</release> $writer->dataElement("release","FILLMEIN"); # <issued date="1653635267"/> $writer->dataElement("issueddate",time); if (@references) { # <references> $writer->startTag("references"); # <reference href="https://bugzilla.suse.com/show_bug.cgi?id=1197742" id="1197742" title="FTBFS: leveldb won't compile on SP4" type="bugzilla"/> foreach my $xref (@references) { $writer->startTag("reference", "href" => "https://www.suse.com/security/cve/$xref", "id" => $xref, "title" => "https://www.suse.com/security/cve/$xref", "type" => "cve", ); $writer->endTag("reference"); } # </references> $writer->endTag("references"); } # <description>This update for leveldb fixes the following issue: #- fix tests (bsc#1197742) #</description> $writer->dataElement("description",$description); $writer->startTag("pkglist"); $writer->startTag("collection"); # <pkglist> # <collection> foreach my $pkg (@ARGV) { my $xpkg = $pkg; my $name = -1; my $version = -1; my $release = -1; $xpkg =~ s#.*/##; $xpkg =~ /^(.*)-([^-]*)-([^-]*)\.[^.]*\.rpm$/; $name = $1; $version = $2; $release = $3; $writer->startTag("package", "epoch" => "0", "version" => $version, "release" => $release, "name" => $name, "src" => $pkg, ); $writer->dataElement("filename",$xpkg); $writer->endTag("package"); } # <package name="leveldb" epoch="0" version="1.18" release="150000.3.3.1" arch="src" src="src/leveldb-1.18-150000.3.3.1.src.rpm"> # <filename>leveldb-1.18-150000.3.3.1.src.rpm</filename> # </package> # <package name="libleveldb1" epoch="0" version="1.18" release="150000.3.3.1" arch="x86_64" src="x86_64/libleveldb1-1.18-150000.3.3.1.x86_64.rpm"> # <filename>libleveldb1-1.18-150000.3.3.1.x86_64.rpm</filename> # </package> # </collection> # </pkglist> $writer->endTag("collection"); $writer->endTag("pkglist"); # </update> $writer->endTag("update"); $writer->end(); $output->close(); 1; 0707010000000E000081ED000000000000000000000001654BBDF90000AD6A000000000000000000000000000000000000003100000000inst-source-utils-2023.11.08/usr/bin/createpatch#!/usr/bin/perl # # Copyright (C) 2006 Novell Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., # 51 Franklin Street, # Fifth Floor, # Boston, MA 02110-1301, # USA. # # $Id: createpatch 186 2009-08-07 18:00:30Z lrupp $ # BEGIN { $abuild_base_dir = "/usr/share/inst-source-utils"; unshift @INC, "$abuild_base_dir/modules"; } $| = 1; use strict; use Cwd; use Data::Dumper; use File::stat; use File::Temp qw/ tempdir /; use RPMQ; use Time::localtime; use Getopt::Long; # cleanup the environment $ENV{'PATH'}='/bin:/usr/bin:/sbin:/usr/sbin:'; $ENV{'BASH_ENV'}=''; $ENV{'ENV'}=''; $ENV{"LC_ALL"} = "C"; our $DEBUG=0; our %config; $config{'basedir'} = cwd(); $config{'category'} = "recommended"; $config{'do_signing'} = 0; $config{'do_susedata'} = 0; $config{'license_file'} = ""; $config{'patch_name'} = "usefirst"; $config{'patch_version'} = 0; $config{'patch_summary'} = ""; $config{'patch_description'} = ""; $config{'sign_id'} = ""; $config{'update_repo'} = 0; $config{'loglevel'} = 7; my $patch_id = `hostname -d`; $config{'patch_id'} = chomp($patch_id); our %patchinfo_data=(); our $print_help=""; our $configfile=""; our @packagelist; our @patchsupplements; our @pkgrefresh; our $LOCKFILE="/var/tmp/createpatch.lock"; ############################################################################### # Functions ############################################################################### sub usage { my $exitcode=shift || 1; print <<EOF $0 Usage Information: $0 [OPTION] ... -b <base_dir> : is the base directory to the repository. -c <CONFIGFILE> : file containing the option/values mentioned below Notes: * use the fullnames as option * values in config file overwrite commandline values! -e|--do_susedata : create special susedata.xml files -i <PATCH_ID> : Patch id, needs to be unique in world, will be prefixed by "hostname -d" as default followed by the name of the first package. Dots in "hostname -d" will be converted to "_"s. -n <PATCH_NAME> : required parameter, terse patch name, like aaa_base -v <PATCH_VERSION> : default to "0"/first non-existant if not given -s <PATCH_SUMMARY> : default to the package summary of the first RPM specified on the command line -d <PATCH_DESCRTIPON> : Long description, defaults to the package description of the first RPM specified on commandline -C <CATEGORY> : Category for the patch. Defaults to recommended. Possible values: security, recommended, optional -u : run createrepo to update repository and take care of keeping the patch*xml files - use when augmenting existing repository with new patches. -s : Create special susedata.xml files -S : detached sign the repomd.xml file -I <KEY_ID> : key-id to use for signing the repomd.xml file, if not given gpg will use the default signing key -L <CONFIRMATION_FILE> : add a confirmation request (EULA or Reboot request) to the patch, read from the file specified --validate : use xmllint to validate the resulting xml file -p <rpm_basename>[,rpm_basename...] : List of RPMs for this patch. You need at least one. --patchsupplements <PATCH_NAME>[,PATCH_NAME] : List of patches which are supplemented by this patch --pkgfreshens rpm_basename : optional parameter which will override the default freshens value EOF ; exit $exitcode; } sub parsePrimaryXml ($) { my $data=shift; my @package_data; my %packdata; my $field = "package"; my $lastfield = "package"; # start extremely primitive xml parser ;) for (@$data){ next if ( /^<\?xml/ ); for (split ('>',$_)) { $_ =~ s/^\s*(.*?)\s*$/$1/s; if ( /^<([^\ ]*)\ (.*)/ ) { $lastfield = $1; $field .= ".$lastfield"; my $trail = $2; my $field_ends = 0; $field_ends = 1 if ( $trail =~ /\/$/ ); $trail =~ s/\/$//; for (split('\ ',$trail)) { my ($key,$val) = split ('=',$_); $val =~ s/^\"(.*)\"$/$1/; $packdata{"$field.$key"} = $val; #print "'$field.$key' val = \"".$packdata{"$field.$key"}."\" (3)\n"; } if ( $field_ends ) { if ( $field =~ /\./ ) { $field =~ s/\.[^\.]*$//; $lastfield = $field; $lastfield =~ s/^.*([^\.]*)$/$1/; } else { $field = "package"; $lastfield = "package"; if ($packdata{'package.name'}) { my %pack_data_tmp = %packdata; push @package_data, \%pack_data_tmp; } %packdata = (); } } } elsif ( /^<\/(.*)/ ) { if ( $field =~ /\./ ) { $field =~ s/\.[^\.]*$//; $lastfield = $field; $lastfield =~ s/^.*([^\.]*)$/$1/; } else { $field = "package"; $lastfield = "package"; if ($packdata{'package.name'}) { my %pack_data_tmp = %packdata; push @package_data, \%pack_data_tmp; } %packdata = (); } } elsif ( /^<([^\ >]*)/ ) { my $tfield = $1; if ( $tfield !~ /\/$/ ) { $field .= ".$tfield"; $lastfield = $tfield; } } elsif ( /^([^<]*)<\/$lastfield/ ) { $packdata{"$field"} = $1; #print "'$field' val = \"".$packdata{"$field"}."\" (2)\n"; if ( $field =~ /\./ ) { $field =~ s/\.[^\.]*$//; $lastfield = $field; $lastfield =~ s/^.*([^\.]*)$/$1/; } else { $field = "package"; $lastfield = "package"; if ($packdata{'package.name'}) { my %pack_data_tmp = %packdata; push @package_data, \%pack_data_tmp; } %packdata = (); } } elsif ( /^(.*)=(.*)$/ ) { my $key = $1; my $val = $2; $val =~ s/^\"(.*)\"$/$1/; $packdata{"$field.$key"} = $val; #print "'$field.$key' val = \"".$packdata{"$field.$key"}."\" lastfield = \"$lastfield\" (1)\n"; } } } # end extremely primitive xml parser ;) # for debugging only print "parsePrimaryXml: ".Dumper($package_data[0]) if ($DEBUG); return \@package_data; } sub updateRepo ($) { my $basedir=shift; my $res=0; my $savedir=tempdir( "createpatch-XXXXXX", TMPDIR => 1, CLEANUP => 1 ); if (! -x '/usr/bin/createrepo'){ warn "/usr/bin/createrepo not found or not executable.\n"; warn "Please check if package createrepo is installed on your system.\n"; return 1; } if ( opendir ( DIR, "$basedir")){ for (readdir(DIR)) { unlink "$basedir/repodata/$_" if ( /\.key$/ || /\.asc$/ ); next unless ( /^patch/ || /^product/ ); if ( /^patches.xml/ ) { unlink "$basedir/repodata/patches.xml"; next; } link "$basedir/repodata/$_","$savedir/$_"; unlink "$basedir/repodata/$_"; } closedir (DIR); } $res=system("/usr/bin/createrepo -x \"*.patch.rpm\" -x \"*.delta.rpm\" $basedir 1>&2 2>/dev/null"); print "createrepo: $res - by running /usr/bin/createrepo -x \"*.patch.rpm\" -x \"*.delta.rpm\" $basedir 1>&2 2>/dev/null\n" if ($DEBUG); if ( opendir ( DIR, "$savedir" ) ) { for (readdir(DIR)) { link "$savedir/$_","$basedir/repodata/$_"; unlink "$savedir/$_"; } closedir (DIR); } return $res; } sub GeneratePatchesXml($) { my ($patches_directory) = @_; opendir(PDIR,"$patches_directory"); my @all_patches = grep {/^patch-.*\.xml$/} readdir(PDIR); closedir(PDIR); if (@all_patches) { open (NEWDIR,">$patches_directory/patches.xml"); print NEWDIR "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; print NEWDIR "<patches xmlns=\"http://novell.com/package/metadata/suse/patches\">\n"; my $pdirname = $patches_directory; $pdirname =~ s/^.*\///; for my $current_patch (@all_patches) { my ($checksum,$dummy) = split('\s+',`sha1sum "$patches_directory/$current_patch"`); my $category = ""; if ($patches_directory =~ /\/you/) { open(PATCH,"$patches_directory/$current_patch"); my @TMP = <PATCH>; close(PATCH); chomp(@TMP); $category = (grep { /<category>/ } @TMP)[0]; if ($category) { $category =~ s/^\s+//; $category =~ s/\s+$//; $category = " $category\n"; } LOG("$current_patch: $category",7); } $current_patch =~ s/.xml$//; my $name = $current_patch; $name =~ s/^patch-//; print NEWDIR " <patch id=\"$name\">\n"; print NEWDIR " <checksum type=\"sha\">$checksum</checksum>\n"; print NEWDIR " <location href=\"$pdirname/$current_patch.xml\"/>\n$category"; print NEWDIR " </patch>\n"; } print NEWDIR "</patches>\n"; close (NEWDIR); } else { LOG("GeneratePatchesXml: no patches found, removing patches.xml",3); unlink "$patches_directory/patches.xml"; } } sub GenerateRepomdXml($) { my ($patches_directory) = @_; opendir(PDIR,"$patches_directory"); my @all_patches = grep {/\.xml(\.gz)?$/} readdir(PDIR); closedir(PDIR); open (NEWDIR,">$patches_directory/repomd.xml"); print NEWDIR "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; print NEWDIR "<repomd xmlns=\"http://linux.duke.edu/metadata/repo\">\n"; my $pdirname = $patches_directory; $pdirname =~ s/^.*\///; for (@all_patches) { next if (/^patch-/); next if (/^repomd/); my ($checksum,$dummy) = split('\s+',`sha1sum "$patches_directory/$_"`); my $o_checksum = $checksum; if ( /\.gz/ ) { ($o_checksum,my $dummy) = split('\s+',`gzip -dc "$patches_directory/$_" | sha1sum`); } my $timestamp = stat("$patches_directory/$_")->mtime; my $filename = $_; $_ =~ s/.xml(\.gz)?$//; print NEWDIR " <data type=\"$_\">\n"; print NEWDIR " <location href=\"$pdirname/$filename\"/>\n"; print NEWDIR " <checksum type=\"sha\">$checksum</checksum>\n"; print NEWDIR " <timestamp>$timestamp</timestamp>\n"; print NEWDIR " <open-checksum type=\"sha\">$o_checksum</open-checksum>\n"; print NEWDIR " </data>\n"; } print NEWDIR "</repomd>\n"; close ( NEWDIR ); } sub xml_escape($) { my ($text) = @_; $text =~ s/&/&/sg; $text =~ s/</</sg; $text =~ s/>/>/sg; $text =~ s/"/"/sg; #$text =~ s/([\x80-\xff])/$1 lt "\xC0" ? "\xC2$1" : "\xC3".chr(ord($1)-64)/ge; return $text; } # poor mans utf8 converter sub to_xml_utf8 { my ($in_text) = @_; my $text = xml_escape($in_text); $text =~ s/([\x80-\xff])/$1 lt "\xC0" ? "\xC2$1" : "\xC3".chr(ord($1)-64)/ge; return $text; } sub trim($){ my $string = shift; $string =~ s/^\s*//; $string =~ s/\s*$//; return $string; } sub ParseConfig($) { my $conf = shift; my %config; open(CONF,"$conf") or die ("Could not open $conf: $!\n"); while (<CONF>){ next if (/^#/); next if /^\s*$/; my ($tag, $data); if (/=/){ ($tag,$data)=split(/\s*=\s*/, $_, 2); $tag=trim($tag); $data=trim($data); } elsif (/:/){ ($tag,$data) = split(/\s*:\s*/, $_, 2); $tag=trim($tag); $data=trim($data); } elsif (/ /){ ($tag, $data) = split(/\s*/, $_, 2); $tag=trim($tag); $data=trim($data); } $config{$tag}="$data"; } close(CONF); return \%config; } sub writePatchFile($$$) { my $configref=shift; my $repodata=shift; my $package_dataref=shift; my %config=%$configref; my @package_data=@$package_dataref; if ($#packagelist ge 0) { my $timestamp = time; my $iteration = $config{'patch_version'}; while ( -f "$repodata/patch-$config{'patch_id'}-$config{'patch_name'}-$iteration.xml" ) { warn ("patch-$config{'patch_id'}-$config{'patch_name'}-$iteration.xml does already exist, increasing version\n"); $iteration++; } # patch header, mostly static my $patch_text = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; $patch_text .= "<patch\n xmlns=\"http://novell.com/package/metadata/suse/patch\"\n"; $patch_text .= " xmlns:yum=\"http://linux.duke.edu/metadata/common\"\n"; $patch_text .= " xmlns:rpm=\"http://linux.duke.edu/metadata/rpm\"\n"; $patch_text .= " xmlns:suse=\"http://novell.com/package/metadata/suse/common\"\n"; $patch_text .= " patchid=\"$config{'patch_id'}-$config{'patch_name'}-$iteration\"\n timestamp=\"$timestamp\"\n engine=\"1.0\">\n"; $patch_text .= " <yum:name>$config{'patch_id'}-$config{'patch_name'}</yum:name>\n"; $patch_text .= " <summary lang=\"en\">".xml_escape($config{'patch_summary'})."</summary>\n"; $patch_text .= " <description lang=\"en\">".xml_escape($config{'patch_description'})."</description>\n"; $patch_text .= " <yum:version ver=\"$iteration\" rel=\"0\"/>\n"; $patch_text .= " <rpm:requires>\n"; my %seen_already; for (@package_data) { # this package wanted in patch ? my $pack_name = $_->{'package.name'}; my $long_name = $_->{'package.location.href'}; $long_name =~ s/^.*\/([^\/]*)/$1/; next unless grep { $_ eq $pack_name || $_ eq $long_name } @packagelist; # duplicate filter next if ( $seen_already{"$_->{'package.name'}-$_->{'package.version.epoch'}-$_->{'package.version.ver'}-$_->{'package.version.rel'}"} ); $seen_already{"$_->{'package.name'}-$_->{'package.version.epoch'}-$_->{'package.version.ver'}-$_->{'package.version.rel'}"} = 1; # make the patch require the atom associated with this package $patch_text .= " <rpm:entry kind=\"atom\" name=\"$_->{'package.name'}\""; $patch_text .= " epoch=\"$_->{'package.version.epoch'}\""; $patch_text .= " ver=\"$_->{'package.version.ver'}\""; $patch_text .= " rel=\"$_->{'package.version.rel'}\" flags=\"EQ\"/>\n"; } $patch_text .= " </rpm:requires>\n"; # do we have any supplements tags at all if ($#patchsupplements ge 0){ $patch_text .= " <rpm:supplements>\n"; for (@patchsupplements){ $patch_text .= " <rpm:entry kind=\"patch\" name=\"$_\"/>\n"; } $patch_text .= " </rpm:supplements>\n"; } $patch_text .=" <category>$config{'category'}</category>\n"; if ( $config{'license_file'} && -f "$config{'license_file'}" ) { $patch_text .= " <license-to-confirm>\n"; open ( LIC, "< $config{'license_file'}"); while ( <LIC> ) { $patch_text .= xml_escape($_); } close ( LIC ); $patch_text .= " </license-to-confirm>\n"; } $patch_text .= " <atoms>\n"; for (@package_data) { # this package wanted in patch ? my $pack_name = $_->{'package.name'}; my $long_name = $_->{'package.location.href'}; my $freshens; $long_name =~ s/^.*\/([^\/]*)/$1/; next unless grep { $_ eq $pack_name || $_ eq $long_name } @packagelist; # create atom data, mostly just copies from primary package data $patch_text .= " <package xmlns=\"http://linux.duke.edu/metadata/common\" type=\"rpm\">\n"; $patch_text .= " <name>$_->{'package.name'}</name>\n"; $patch_text .= " <arch>$_->{'package.arch'}</arch>\n"; $patch_text .= " <version epoch=\"$_->{'package.version.epoch'}\" ver=\"$_->{'package.version.ver'}\" rel=\"$_->{'package.version.rel'}\"/>\n"; $patch_text .= " <checksum type=\"sha\" pkgid=\"YES\">$_->{'package.checksum'}</checksum>\n"; $patch_text .= " <time file=\"$_->{'package.time.file'}\" build=\"$_->{'package.time.build'}\"/>\n"; $patch_text .= " <size package=\"$_->{'package.size.package'}\" installed=\"$_->{'package.size.installed'}\" archive=\"$_->{'package.size.archive'}\"/>\n"; $patch_text .= " <location href=\"$_->{'package.location.href'}\"/>\n"; # here starts the association of the atom to the real package $patch_text .= " <format>\n <rpm:requires>\n"; $patch_text .= " <rpm:entry kind=\"package\""; $patch_text .= " name=\"$_->{'package.name'}\""; $patch_text .= " epoch=\"$_->{'package.version.epoch'}\""; $patch_text .= " ver=\"$_->{'package.version.ver'}\""; $patch_text .= " rel=\"$_->{'package.version.rel'}\""; $patch_text .= " flags=\"GE\"/>\n"; $patch_text .= " </rpm:requires>\n"; # now have the atom pulled in, if this package is installed on the system $patch_text .= " <suse:freshens>\n"; # do we need to override the freshens tag if ($#pkgrefresh ge 0){ for(@pkgrefresh){ $patch_text .= " <suse:entry kind=\"package\" name=\"$_\"/>\n"; } } else{ $patch_text .= " <suse:entry kind=\"package\" name=\"$_->{'package.name'}\"/>\n"; } $patch_text .= " </suse:freshens>\n </format>\n </package>\n"; } $patch_text .= " </atoms>\n</patch>\n"; open ( PATCH, "> $repodata/patch-$config{'patch_id'}-$config{'patch_name'}-$iteration.xml"); print PATCH $patch_text; close ( PATCH ); } } # # write out the xml file and gzip it, atomic # sub UpdateXmlFile { my ($patches_directory,$xname,$data) = @_; open ( PRIMARY, "| gzip > $patches_directory/$xname.xml.gz.new"); print PRIMARY "$data->{header}\n"; # actually faster this way according to testing for (@{$data->{newdata}}) { print PRIMARY "$_\n" if defined $_; } print PRIMARY "$data->{footer}\n"; close ( PRIMARY ); rename ( "$patches_directory/$xname.xml.gz.new", "$patches_directory/$xname.xml.gz"); unlink ("$patches_directory/$xname.xml") if ( -f "$patches_directory/$xname.xml" ); } # # extremely primitive xml input: split records at "<package " # sub ReadXmlFile { my ($patches_directory,$xname,$dataname) = @_; my @PRIMARY; if ( -f "$patches_directory/$xname.xml.gz" ) { open ( PRIMARY, "zcat $patches_directory/$xname.xml.gz |"); } else { open ( PRIMARY, "$patches_directory/$xname.xml"); } { local $/ = "<package "; @PRIMARY = <PRIMARY>; chomp (@PRIMARY); } close ( PRIMARY ); unless ( $PRIMARY[1] ) { $PRIMARY[0] =~ s/<\/$dataname>//g; push @PRIMARY, "nil></package>\n</$dataname>"; } my $header_primary = shift(@PRIMARY); $header_primary =~ s/^\s*(.*?)\s*$/$1/s; my $footer_primary = $PRIMARY[$#PRIMARY]; $PRIMARY[$#PRIMARY] =~ s/<\/package\>.*$/<\/package\>/s; $footer_primary =~ s/^.*<\/package>//s; $footer_primary =~ s/^\s*(.*?)\s*$/$1/s; return ($header_primary,$footer_primary,\@PRIMARY); } sub cleanup(){ unlink "$LOCKFILE" if ( -f "$LOCKFILE"); } # simple logfile writer sub LOG { my $entry = shift; my $level = shift || 1; my $xtime=`date`; chomp($xtime); if ( $level lt $config{'loglevel'} ){ print OUTPUT_LOG "$xtime: $entry\n"; } print "$xtime: $entry\n" if ($DEBUG); } # # helper functions for GetPackageDataFromRpm # # only weak deps (enhances, suggests) sub filter_weak { my ($tn, $tf) = @_; my @tf = @{$tf || []}; my @res; for (@{$tn || []}) { push @res, $_ unless (shift @tf) & 0x8000000; } return @res; } # only strong ones (recommends, supplements) sub filter_strong { my ($tn, $tf) = @_; my @tf = @{$tf || []}; my @res; for (@{$tn || []}) { push @res, $_ if (shift @tf) & 0x8000000; } return @res; } # combine deps and their relations and flags sub add_flagsvers_special { my $res = shift; my $name = shift; my $flags = shift; my $vers = shift; my $filter = shift; my @raw_dep_names = @{$res->{$name} || []}; my @raw_dep_flags = @{$res->{$flags} || []}; my @raw_dep_vers = @{$res->{$vers} || []}; if ($filter && @raw_dep_flags) { @raw_dep_names = $filter->(\@raw_dep_names, \@raw_dep_flags); @raw_dep_vers = $filter->(\@raw_dep_vers, \@raw_dep_flags); @raw_dep_flags = $filter->(\@raw_dep_flags, \@raw_dep_flags); } my @raw_provides = (); for (@raw_dep_names) { my %prov_line = (); $prov_line{'name'} = $_; my ($epoch, $version) = $raw_dep_vers[0] =~ /^(?:(\d+):)?(.*?)$/; my $release = ''; ($version, $release) = ($1, $2) if $version =~ /^(.*)-(.*?)$/; $prov_line{'epoch'} = $epoch; $prov_line{'ver'} = $version; $prov_line{'rel'} = $release; if (@raw_dep_flags && ($raw_dep_flags[0] & 0xe) && @raw_dep_vers) { my @rels = qw{FALSE FALSE LT LT GT GT NE NE EQ EQ LE LE GE GE TRUE TRUE}; $prov_line{'flags'} = $rels[$raw_dep_flags[0] & 0xe]; } if (@raw_dep_flags && $raw_dep_flags[0] & 64) { $prov_line{'pre'} = 1; } shift @raw_dep_flags; shift @raw_dep_vers; push @raw_provides, \%prov_line; } return \@raw_provides; } # find out all about the given package sub GetPackageDataFromRpm { my ($package_file) = @_; my %package_data = (); my $dummy = ""; $package_data{"fullpath"} = $package_file; $package_file =~ /.*\/([^\/]*)$/; $package_data{"basename"} = $1; $package_data{"filesize"} = stat($package_file)->size; $package_data{"filetime"} = stat($package_file)->mtime; ($package_data{"checksum_sha"},$dummy) = split('\s+',`sha1sum $package_file`); my %res = RPMQ::rpmq_many($package_file,'NAME','EPOCH','VERSION','RELEASE','SIZE','BUILDTIME','GROUP','ARCH','LICENSE', 'SOURCERPM','PROVIDENAME','PROVIDEFLAGS','PROVIDEVERSION', 'REQUIRENAME','REQUIREFLAGS','REQUIREVERSION', 'CONFLICTNAME','CONFLICTFLAGS','CONFLICTVERSION', 'OBSOLETENAME','OBSOLETEFLAGS','OBSOLETEVERSION', 'SUGGESTSNAME','SUGGESTSFLAGS','SUGGESTSVERSION', 'ENHANCESNAME','ENHANCESFLAGS','ENHANCESVERSION', 'FILENAMES','FILEMODES','SUMMARY','DESCRIPTION','HEADERSTART','HEADEREND', 'CHANGELOGTIME','CHANGELOGNAME','CHANGELOGTEXT','PACKAGER','VENDOR','URL', 'ARCHIVESIZE','SIGTAG_PAYLOADSIZE','BUILDHOST'); $package_data{"name"} = ($res{'NAME'} || [])->[0]; $package_data{"epoch"} = ($res{'EPOCH'} || [])->[0]; $package_data{"epoch"} = "0" unless ($package_data{"epoch"}); $package_data{"version_only"} = ($res{'VERSION'} || [])->[0]; $package_data{"release"} = ($res{'RELEASE'} || [])->[0]; $package_data{"version"} = "$package_data{version_only}-$package_data{release}"; $package_data{"rpmsize"} = ($res{'SIZE'} || [])->[0]; $package_data{"archivesize"} = ($res{'ARCHIVESIZE'} || [])->[0]; $package_data{"archivesize"} = ($res{'SIGTAG_PAYLOADSIZE'} || [])->[0] unless ($package_data{"archivesize"}); $package_data{"buildtime"} = ($res{'BUILDTIME'} || [])->[0]; $package_data{"rpmgroup"} = ($res{'GROUP'} || [])->[0]; $package_data{"rpmarch"} = ($res{'ARCH'} || [])->[0]; $package_data{"license"} = ($res{'LICENSE'} || [])->[0]; $package_data{"sourcerpm"} = ($res{'SOURCERPM'} || [])->[0]; $package_data{"packager"} = ($res{'PACKAGER'} || [])->[0]; $package_data{"vendor"} = ($res{'VENDOR'} || [])->[0]; $package_data{"url"} = ($res{'URL'} || [])->[0]; $package_data{"rpmarch"} = "src" unless ( $package_data{"sourcerpm"} ); $package_data{"headerstart"} = $res{'HEADERSTART'}; $package_data{"headerend"} = $res{'HEADEREND'}; $package_data{"summary"} = ($res{'SUMMARY'} || [])->[0]; $package_data{"buildhost"} = ($res{'BUILDHOST'} || [])->[0]; $package_data{"description"} = join(' ',@{$res{'DESCRIPTION'}}); my @dirs = (); my @files = (); for (@{$res{'FILENAMES'}}) { if ( @{$res{'FILEMODES'}}[0] & 0040000 ) { push @dirs, $_; } else { push @files, $_; } shift @{$res{FILEMODES}} } $package_data{"rpmlistdirs"} = \@dirs; $package_data{"rpmlistfiles"} = \@files; # raw deps $package_data{"providesraw"} = add_flagsvers_special(\%res,'PROVIDENAME','PROVIDEFLAGS','PROVIDEVERSION'); $package_data{"requiresraw"} = add_flagsvers_special(\%res,'REQUIRENAME','REQUIREFLAGS','REQUIREVERSION'); $package_data{"conflictsraw"} = add_flagsvers_special(\%res,'CONFLICTNAME','CONFLICTFLAGS','CONFLICTVERSION'); $package_data{"obsoletesraw"} = add_flagsvers_special(\%res,'OBSOLETENAME','OBSOLETEFLAGS','OBSOLETEVERSION'); $package_data{"supplementsraw"} = add_flagsvers_special(\%res,'ENHANCESNAME','ENHANCESFLAGS','ENHANCESVERSION', \&filter_strong); $package_data{"enhancesraw"} = add_flagsvers_special(\%res,'ENHANCESNAME','ENHANCESFLAGS','ENHANCESVERSION', \&filter_weak); $package_data{"recommendsraw"} = add_flagsvers_special(\%res,'SUGGESTSNAME','SUGGESTSFLAGS','SUGGESTSVERSION', \&filter_strong); $package_data{"suggestsraw"} = add_flagsvers_special(\%res,'SUGGESTSNAME','SUGGESTSFLAGS','SUGGESTSVERSION', \&filter_weak); # cooked deps RPMQ::rpmq_add_flagsvers(\%res,'PROVIDENAME','PROVIDEFLAGS','PROVIDEVERSION'); RPMQ::rpmq_add_flagsvers(\%res,'REQUIRENAME','REQUIREFLAGS','REQUIREVERSION'); $package_data{"provides"} = join(' ',@{$res{'PROVIDENAME'}}); $package_data{"requires"} = join(' ',@{$res{'REQUIRENAME'}}); $package_data{"provides"} =~ s/\s+/ /g; $package_data{"provides"} =~ s/\s+$//g; $package_data{"requires"} =~ s/\s+/ /g; $package_data{"requires"} =~ s/\s+$//g; $package_data{"changelogtime"} = $res{'CHANGELOGTIME'}; $package_data{"changelogname"} = $res{'CHANGELOGNAME'}; $package_data{"changelogname"} =~ s/^- //; $package_data{"changelogtext"} = $res{'CHANGELOGTEXT'}; return %package_data; } sub ReadFileToHash($){ my $file=shift; my %temp; open(FILE,"< $file") or return undef; while (<FILE>){ chomp; last if $_ =~ /^:END/ ; next if ( $_ =~ /^\#/ ); next if ( $_ =~ /^\s$/ ); my ($le,$ri) = split (/:/,$_,2); $le=trim($le); $ri=trim($ri); $ri=~ s/\\n/\n/g; $temp{$le}=$ri; } close(FILE); return \%temp; } # # create package information in xml format as given for repomd # sub PackageDataToXML { my ($curpack) = @_; my $boilerplate .= " <package xmlns=\"http://linux.duke.edu/metadata/common\" type=\"rpm\">\n"; my $header = " <name>".$curpack->{"name"}."</name>\n"; $header .= " <arch>".$curpack->{"rpmarch"}."</arch>\n"; $header .= " <version epoch=\"$curpack->{epoch}\" ver=\"$curpack->{version_only}\" rel=\"$curpack->{release}\"/>\n"; $header .= " <checksum type=\"sha\" pkgid=\"YES\">".$curpack->{"checksum_sha"}."</checksum>\n"; $header .= " <summary lang=\"en\">".to_xml_utf8($curpack->{summary})."</summary>\n"; $header .= " <description lang=\"en\">".to_xml_utf8($curpack->{description})."</description>\n"; $header .= " <packager>$curpack->{packager}</packager>\n"; $header .= " <url>".to_xml_utf8($curpack->{url})."</url>\n"; $header .= " <time file=\"$curpack->{filetime}\" build=\"$curpack->{buildtime}\"/>\n"; $header .= " <size package=\"$curpack->{filesize}\" installed=\"$curpack->{rpmsize}\" archive=\"$curpack->{archivesize}\"/>\n"; $header .= " <location href=\"rpm/$curpack->{rpmarch}/$curpack->{basename}\"/>\n"; # ## FORMAT START # my $data = " <rpm:license>$curpack->{license}</rpm:license>\n"; $data .= " <rpm:vendor>$curpack->{vendor}</rpm:vendor>\n"; $data .= " <rpm:group>$curpack->{rpmgroup}</rpm:group>\n"; $data .= " <rpm:buildhost>$curpack->{buildhost}</rpm:buildhost>\n"; if ( $curpack->{sourcerpm} ) { $data .= " <rpm:sourcerpm>$curpack->{sourcerpm}</rpm:sourcerpm>\n"; } else { $data .= " <rpm:sourcerpm/>\n"; } $data .= " <rpm:header-range start=\"$curpack->{headerstart}\" end=\"$curpack->{headerend}\"/>\n"; for my $dep_type (qw{provides requires conflicts obsoletes suggests enhances recommends supplements}) { my $dep_list = $curpack->{"${dep_type}raw"}; if ($dep_list && @$dep_list) { $data .= " <rpm:$dep_type>\n"; for my $dep_data (@$dep_list) { $data .= " <rpm:entry"; # name,epoch,ver,rel,pre,flags for (qw{name flags epoch ver rel pre}) { $data .= " $_=\"$dep_data->{$_}\"" if defined ($dep_data->{$_}) && $dep_data->{$_} ne ""; } $data .= "/>\n"; } $data .= " </rpm:$dep_type>\n"; } } for (grep {/.*bin\/.*/ || /^\/etc\/.*/} @{$curpack->{rpmlistdirs}} ) { $data .= " <file type=\"dir\">$_</file>\n"; } for (grep {/.*bin\/.*/ || /^\/usr\/lib\/sendmail$/ || /^\/etc\/.*/} @{$curpack->{rpmlistfiles}} ) { $data .= " <file>$_</file>\n"; } # ## FORMAT END # my $filelist = ""; for (@{$curpack->{rpmlistdirs}}) { $filelist .= " <file type=\"dir\">".to_xml_utf8($_)."</file>\n"; } for (@{$curpack->{rpmlistfiles}}) { $filelist .= " <file>".to_xml_utf8($_)."</file>\n"; } return ($boilerplate , $header, $data, $filelist); } # # regenerate the updateinfo.xml.gz file: scan all updateinfo-foo.xml and include literally # sub GenerateUpdateinfoXml { my ($patches_directory) = @_; opendir(PDIR,"$patches_directory/../repoparts"); my @all_files = readdir(PDIR); my @all_patches = grep {/^updateinfo-.*\.xml$/} @all_files; my @all_deltas = grep {/^deltainfo-.*\.xml$/} @all_files; closedir(PDIR); if (@all_patches) { # concat for updateinfo open (NEWDIR,"| gzip > $patches_directory/updateinfo.xml.gz.new"); print NEWDIR "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; print NEWDIR "<updates xmlns=\"http://novell.com/package/metadata/suse/updateinfo\">\n"; for my $current_patch (@all_patches) { open (PATCH, "< $patches_directory/../repoparts/$current_patch"); print NEWDIR join('',grep {$_ !~ /^<.xml version/} <PATCH>); close (PATCH); } print NEWDIR "</updates>\n"; close (NEWDIR); my $xname = "updateinfo"; rename ( "$patches_directory/$xname.xml.gz.new", "$patches_directory/$xname.xml.gz"); unlink ("$patches_directory/$xname.xml") if ( -f "$patches_directory/$xname.xml" ); # concat for deltainfo open (NEWDIR,"| gzip > $patches_directory/deltainfo.xml.gz.new"); print NEWDIR "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; print NEWDIR "<deltainfo>\n"; for my $current_delta (@all_deltas) { open (PATCH, "< $patches_directory/../repoparts/$current_delta"); print NEWDIR join('',grep {$_ !~ /^<.xml version/} <PATCH>); close (PATCH); } print NEWDIR "</deltainfo>\n"; close (NEWDIR); $xname = "deltainfo"; rename ( "$patches_directory/$xname.xml.gz.new", "$patches_directory/$xname.xml.gz"); unlink ("$patches_directory/$xname.xml") if ( -f "$patches_directory/$xname.xml" ); unlink ("$patches_directory/patches.xml") if ( -f "$patches_directory/patches.xml" ); } else { LOG ("GenerateUpdateinfoXml: no updates found, removing updateinfo.xml",2); unlink "$patches_directory/updateinfo.xml"; unlink "$patches_directory/updateinfo.xml.gz"; } } ############################################################################### # Main ############################################################################### Getopt::Long::Configure('bundling'); GetOptions( 'h|help' => \$print_help, 'b|basedir=s' => \$config{'basedir'}, 'c|configfile=s' => \$configfile, 'C|category=s' => \$config{'category'}, 'e|do_susedata' => \$config{'do_susedata'}, 'i|patch_id=s' => \$config{'patch_id'}, 'l|logfile=s' => \$config{'logfile'}, 'k|keywordfile=s' => \$config{'keywordfile'}, 'n|patch_name=s' => \$config{'patch_name'}, 'v|patch_version=i' => \$config{'patch_version'}, 's|patch_summary=s' => \$config{'patch_summary'}, 'd|patch_description=s' => \$config{'patch_description'}, 'u|update_repo' => \$config{'update_repo'}, 'S|do_signing' => \$config{'do_signing'}, 'I|sign_id=s' => \$config{'sign_id'}, 'L|license_file=s' => \$config{'license_file'}, 'p|packagelist=s' => \@packagelist, 'patchsupplements=s' => \@patchsupplements, 'pkgfreshens=s' => \@pkgrefresh, ); usage(0) if ($print_help); if ("$configfile" ne ""){ if (-r "$configfile"){ my $configref=ParseConfig("$configfile"); %config=%$configref; } else { die ("Could not open $configfile\n"); } } $config{'patch_id'} =~ s/\./_/g; #die ("Lockfile ($LOCKFILE) already exists at ".ctime()."\n") if (-f "$LOCKFILE"); #open (LOCK,">$LOCKFILE") || die "Cannot write lockfile $LOCKFILE : $!\n"; #print LOCK "$$\n"; #close(LOCK); $::SIG{"__DIE__"} = sub { die (@_) if $^S; \&cleanup; }; open ( OUTPUT_LOG , ">>$config{'logfile'}"); select (OUTPUT_LOG); $| = 1; select (STDOUT); my $repodata = "$config{'basedir'}/repodata"; my $first_package = ""; if ( @packagelist && $packagelist[0] ){ $first_package = $packagelist[0]; @packagelist=split(/,/,join(',',@packagelist)); } @patchsupplements=split(/,/,join(',',@patchsupplements)) if ( @patchsupplements ); @pkgrefresh=split(/,/,join(',',@pkgrefresh)) if (@pkgrefresh); if ( $config{'patch_name'} eq "usefirst" ) { $config{'patch_name'} = "$first_package" if ( "$first_package" ); } if ($DEBUG){ print "config: ".Data::Dumper->Dump([\%config]); for (@patchsupplements){ print "patchsupplements : $_\n"; } for (@pkgrefresh){ print "pkgrefresh : $_\n"; } for (@packagelist){ print "packagelist : $_\n"; } } LOG("Start creation for $repodata",1); my $res=updateRepo("$config{'basedir'}") if ($config{'update_repo'}); die "Could not update the Repository\n" if ($res); if ( -f "$repodata/primary.xml.gz" ) { open ( PRIMARY, "zcat $repodata/primary.xml.gz |") || warn ("Could not open primary.xml.gz : $!\n"); } else { open ( PRIMARY, "$repodata/primary.xml") || warn ("Could not open primary.xml : $!\n"); } my @PRIMARY; { local $/ = "<package "; @PRIMARY = <PRIMARY>; chomp (@PRIMARY); } close ( PRIMARY ); my $package_dataref=parsePrimaryXml(\@PRIMARY); my @package_data=@$package_dataref; for (@package_data) { my $pack_name = $_->{'package.name'}; my $long_name = $_->{'package.location.href'}; $long_name =~ s/^.*\/([^\/]*)/$1/; next unless ( $pack_name eq $first_package || $long_name eq $first_package ); # primitive approach: use summary and description of the first package found $config{'patch_summary'} = $_->{'package.summary'} unless ($config{'patch_summary'}); $config{'patch_description'} = $_->{'package.description'} unless ($config{'patch_description'}); } if ($config{'do_susedata'}){ my %xfiles = ( 'susedata' => 'susedata', 'primary' => 'metadata', 'filelists' => 'filelists', 'other' => 'otherdata', ); our %data; for my $name (sort(keys %xfiles)){ my $tag = $xfiles{$name}; if ( ! -f "$repodata/$name.xml.gz" && ! -f "$repodata/$name.xml"){ open (IDXFILE, ">$repodata/$name.xml") || die "Could not open $repodata/$name.xml : $!\n"; print IDXFILE "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; print IDXFILE "<$tag xmlns=\"http://linux.duke.edu/metadata/$name\" packages=\"0\">\n"; print IDXFILE "<package nil></package></$tag>\n"; close ( IDXFILE ); } ($data{"${name}_header"},$data{"${name}_footer"},$data{"${name}_data"}) = ReadXmlFile("$repodata","$name","$tag"); } my $number_packages = 0; my $number_discarded = 0; my %seen_rpms = (); my %stat_all_rpms = (); my @rpm_dirs; if (opendir(D, "$repodata/../rpm")) { @rpm_dirs = grep {!/^\./} readdir(D); closedir D; } for my $rpm_dir (@rpm_dirs) { if (opendir(D, "$repodata/../rpm/$rpm_dir")) { for (grep { /^[^\.].*\.rpm/ } readdir(D)) { $stat_all_rpms{"$repodata/../rpm/$rpm_dir/$_"} = lstat("$repodata/../rpm/$rpm_dir/$_"); } closedir D; } } LOG("Starting susedata creation",5); my $valid_pkgids; for my $index (0...$#{$data{'primary_data'}}) { my $filename = $data{'primary_data'}->[$index]; my $pkgid = $data{'primary_data'}->[$index]; # $filename =~ s/^[\s\S]*<location href="([^"]*)"[\s\S]*$/$1/; $pkgid =~ s/^[\s\S]*<checksum type="sha" pkgid="YES">([^<]*)<[\s\S]*$/$1/; my $filebase = $filename; $filebase =~ s/^.*\///; # my $pack_ok = 0; my $f_stat = $stat_all_rpms{"$repodata/../$filename"}; # get file time if ( $f_stat ) { my $fil_time = $f_stat->mtime; my $rec_time = $data{'primary_data'}->[$index]; $rec_time =~ s/.*time file=\"([^\"]*).*/$1/s; $pack_ok = 1 if ( $rec_time eq $fil_time ); LOG("$filename $rec_time $fil_time",5) unless $pack_ok; } if ( $pack_ok && $data{'filelists_data'}->[$index] && $data{'other_data'}->[$index] && $data{'filelists_data'}->[$index] =~ /pkgid="$pkgid"/ && $data{'other_data'}->[$index] =~ /pkgid="$pkgid"/ ) { $data{'primary_data'}->[$index] =~ s/\s+$//s; $data{'primary_data'}->[$index] = " <package ".$data{'primary_data'}->[$index]; $data{'filelists_data'}->[$index] =~ s/\s+$//s; $data{'filelists_data'}->[$index] = "<package ".$data{'filelists_data'}->[$index]; $data{'other_data'}->[$index] =~ s/\s+$//s; $data{'other_data'}->[$index] = "<package ".$data{'other_data'}->[$index]; $seen_rpms{$filename} = 1; $number_packages += 1; $valid_pkgids->{$pkgid} = 1; } else { undef $data{'primary_data'}->[$index]; undef $data{'filelists_data'}->[$index]; undef $data{'other_data'}->[$index]; $number_discarded += 1; LOG("discarding data for $filename",3); } } for my $index (0...$#{$data{'suse_data'}}) { my $pkgid = $data{'suse_data'}->[$index]; $pkgid =~ s/^.*pkgid=\"([^\"]*)\".*$/$1/s; if ($valid_pkgids->{$pkgid}) { $data{'suse_data'}->[$index] =~ s/\s+$//s; $data{'suse_data'}->[$index] = " <package ".$data{'suse_data'}->[$index]; } else { undef $data{'suse_data'}->[$index]; LOG("discarding susedata for **$pkgid**",3); } } LOG("re-using data for $number_packages rpms, discarded data for $number_discarded rpms (".($#{$data{'primary_data'}} + 1).")",3); for my $current_rpm (keys %stat_all_rpms) { my $short = $current_rpm; $short =~ s/$repodata\/..\///; # next if ( $seen_rpms{$short} ); # next if (S_ISLNK($stat_all_rpms{$current_rpm}->mode)); next if ( $current_rpm =~ /\.patch\.rpm$/ ); next if ( $current_rpm =~ /\.delta\.rpm$/ ); my $filebase = $current_rpm; $filebase =~ s/^.*\///; LOG("adding data for $current_rpm",3); my %curpack = GetPackageDataFromRpm($current_rpm); if ($config{'license_file'} && -f "$config{'license_file'}"){ my @lic_text=(); open (LIC,"< $config{'license_file'}"); while (<LIC>){ push @lic_text, xml_escape($_); } close(LIC); $curpack{'confirmlic'}=join("\n",@lic_text); } my ($a1,$a2,$a3,$a4) = PackageDataToXML(\%curpack); my $package_header = "<package pkgid=\"".$curpack{'checksum_sha'}."\" name=\"".$curpack{'name'}."\" arch=\"".$curpack{'rpmarch'}."\"\>\n"; $package_header .= "<version epoch=\"".$curpack{'epoch'}."\" ver=\"".$curpack{'version_only'}."\" rel=\"".$curpack{'release'}."\"/>\n"; my $suse_data_entry = $package_header; # license to confirm... my $conf_lic = ""; if ($curpack{'confirmlic'}){ $conf_lic = " <suse:license-to-confirm>\n".to_xml_utf8($curpack{'confirmlic'})."\n </suse:license-to-confirm>\n"; $suse_data_entry .= "<eula>\n".to_xml_utf8($curpack{'confirmlic'})."\n </eula>\n"; LOG("adding eula to $current_rpm to susedata",5); } # support keywords... my %keyword_data=(); if ($config{'keywordfile'}){ my $keywords=ReadFileToHash("$config{'keywordfile'}") if ($config{'keywordfile'}); %keyword_data=%$keywords; print "$filebase has keyword" if (defined($keyword_data{$filebase})); if ($keyword_data{$curpack{'name'}}) { for (@{$keyword_data{$curpack{'name'}}}) { $suse_data_entry .= "<keyword>".$_."</keyword>\n"; } } } push @{$data{'suse_data'}}, "$suse_data_entry</package>"; push @{$data{'primary_data'}}, "$a1$a2 <format>\n$a3 </format>\n$conf_lic </package>"; push @{$data{'filelists_data'}}, "$package_header$a4</package>"; my $other_entry; for (@{$curpack{'changelogtime'}}) { $other_entry .= "<changelog author=\"".to_xml_utf8(@{$curpack{'changelogname'}}[0])."\" date=\"".$_."\">"; $other_entry .= to_xml_utf8(@{$curpack{'changelogtext'}}[0])."</changelog>\n"; shift @{$curpack{'changelogname'}}; shift @{$curpack{'changelogtext'}}; } push @{$data{'other_data'}}, "$package_header$other_entry</package>";; $number_packages += 1; } } else { writePatchFile(\%config,$repodata,\@package_data); GeneratePatchesXml($repodata); } GenerateRepomdXml($repodata); unlink "$repodata/repomd.xml.asc"; unlink "$repodata/repomd.xml.key"; if ( $config{'do_signing'} ) { if ( $config{'sign_id'} ) { system("gpg -a -b --default-key \"$config{'sign_id'}\" $repodata/repomd.xml"); } else { system("gpg -a -b $repodata/repomd.xml"); $config{'sign_id'} = `gpg --verify $repodata/repomd.xml.asc 2>&1 | sed -ne "s/.* ID //p"`; chomp ($config{'sign_id'}); } system("gpg -a --export \"$config{'sign_id'}\" > $repodata/repomd.xml.key") if ( $config{'sign_id'} ); } LOG("Finished creation for $repodata",1); close (OUTPUT_LOG); cleanup(); #system("//bin/sign -d $patches_directory/repomd.xml"); #system("cp $patchinfo_lib_dir/public-key $patches_directory/repomd.xml.key"); # Logfile: # $Log: createpatch.pl,v $ # Revision 1.6 2009/04/27 09:02:13 lrupp # - enable keywords support # - added PackageDataToXML() # - use/fillup suse_data primary_data filelists_data # # Revision 1.5 2009/04/17 15:13:47 lrupp # - weekend :-) # # Revision 1.4 2009/04/17 08:15:28 lrupp # - new writePatchFile() # - remove validate option: we always produce valid metadata ;-) # - add logfile and lockfile # # Revision 1.3 2009/04/16 16:00:27 lrupp # - use %config for all configuration now # - be backwarts compatible: allow basedir as argument without option # - added configfile option # # Revision 1.2 2009/04/16 14:09:02 lrupp # - use temdir for update_repo # - new parsePrimaryXml() # - use Getopt for config options # # Revision 1.1 2009/04/16 13:34:01 lrupp # Initial revision # # Revision 1.5 2007/12/11 13:42:01 lrupp # - added "license-to-confirm" # - check for createrepo and warn user if not exist # # Revision 1.4 2007/07/13 08:44:35 lrupp # addad @packagelist to condition # # Revision 1.3 2007/05/15 15:59:21 lrupp # beautify usage message # # 0707010000000F000081ED000000000000000000000001654BBDF9000012CD000000000000000000000000000000000000003B00000000inst-source-utils-2023.11.08/usr/bin/gen-s390-cd-kernel.pl#!/usr/bin/perl -w # # Generates a bootable CD-ROM for S/390 # # Copyright (C) 2006 Novell Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., # 51 Franklin Street, # Fifth Floor, # Boston, MA 02110-1301, # USA. # # $Id: gen-s390-cd-kernel.pl 107 2009-03-06 11:48:14Z ro $ use FileHandle; use Getopt::Long; use strict; # Help text # sub help($) { my $exitcode = shift || 1; print "Usage: $0 <OPTIONS> - generate a kernel image for CD-ROM boot\n"; print "SYNOPSIS: $0 [--initrd=file] \n"; print " [--parmfile=file] [--outfile=file] \n"; print " [--kernel=file] [--cmdline=string] \n"; exit $exitcode; } # Parse command line options my ($initrd, $image, $parmfile, $outfile, $cmdline ) = ('/boot/initrd','/boot/image', '', '/tmp/image.cd', 'root=/dev/sda2'); Getopt::Long::Configure ("bundling"); eval { unless (GetOptions ( 'i|initrd=s' => \$initrd, 'k|kernel=s' => \$image, 'p|parmfile=s' => \$parmfile, 'o|outfile=s' => \$outfile, 'c|cmdline=s' => \$cmdline, 'h|help' => sub { help(0); } )) { help(1); } }; if ($@) { print "$@"; help(1); } # Open input files sysopen(image_fh,$image,O_RDONLY) or die "Cannot open $image: $!\n"; sysopen(initrd_fh,$initrd,O_RDONLY) or die "Cannot $initrd: $!\n"; my $image_size = (stat(image_fh))[7]; my $initrd_size = (stat(initrd_fh))[7]; # Get the size of the input files printf("%s: offset 0x%x len 0x%x (%d blocks)\n", $image, 0, $image_size, ($image_size >> 12) + 1); # The kernel appearently needs some free space above the # actual image (bss? stack?), so use this hard-coded # limit (from include/asm-s390/setup.h) # my $initrd_offset = (($image_size >> 12) + 1) << 12; my $initrd_offset = 0x800000; my $boot_size = ((($initrd_offset + $initrd_size) >> 12) + 1 ) << 12; printf("%s: offset 0x%x len 0x%x (%d blocks)\n", $initrd, $initrd_offset, $initrd_size, ($initrd_size >>12) + 1); printf("%s: len 0x%x (%d blocks)\n", $outfile, $initrd_offset + $initrd_size, $boot_size / 4096); # Get the kernel command line arguments $cmdline .= " " if ($cmdline ne ""); if ($parmfile ne "") { my $line; $cmdline = ''; open(parm_fh,$parmfile) or die "Cannot open $parmfile: $!\n"; while($line=<parm_fh>) { chomp $line; $cmdline .= $line . " "; } close(parm_fh); } if ($cmdline ne "") { chop $cmdline; } # Max length for the kernel command line is 896 bytes die "Kernel commandline too long (". length($cmdline) ." bytes)\n" if (length($cmdline) >= 896); # Now create the image file. sysopen(out_fh,$outfile,O_RDWR|O_CREAT|O_TRUNC) or die "Cannot open $outfile: $!\n"; # First fill the entire size with zeroes sysopen(null_fh,"/dev/zero",O_RDONLY) or die "Cannot open /dev/zero: $!\n"; my $buffer=""; my $blocks_read=0; while ($blocks_read < ($boot_size >> 12)) { sysread(null_fh,$buffer, 4096); syswrite(out_fh,$buffer); $blocks_read += 1; } print "Read $blocks_read blocks from /dev/zero\n"; close(null_fh); # Now copy the image file to location 0 sysseek(out_fh,0,0); $blocks_read = 0; while (sysread(image_fh,$buffer, 4096) != 0) { syswrite(out_fh,$buffer,4096); $blocks_read += 1; } print "Read $blocks_read blocks from $image\n"; close(image_fh); # Then the initrd to location specified by initrd_offset sysseek(out_fh,$initrd_offset,0); $blocks_read = 0; while (sysread(initrd_fh,$buffer, 4096) != 0) { syswrite(out_fh,$buffer,4096); $blocks_read += 1; } print "Read $blocks_read blocks from $initrd\n"; close(initrd_fh); # Now for the real black magic. # If we are loading from CD-ROM or HMC, the kernel is already loaded # in memory by the first loader itself. print "Setting boot loader control to 0x10000\n"; sysseek(out_fh,4,0 ); syswrite(out_fh,pack("N",0x80010000),4); print "Writing kernel commandline (". length($cmdline) ." bytes):\n$cmdline\n"; sysseek(out_fh,0x10480,0); syswrite(out_fh,$cmdline,length($cmdline)); print "Setting initrd parameter: offset $initrd_offset size $initrd_size\n"; sysseek(out_fh,0x1040C,0); syswrite(out_fh,pack("N",$initrd_offset),4); sysseek(out_fh,0x10414,0); syswrite(out_fh,pack("N",$initrd_size),4); close(out_fh); 07070100000010000081ED000000000000000000000001654BBDF9000016FD000000000000000000000000000000000000003200000000inst-source-utils-2023.11.08/usr/bin/mk_changelog#!/usr/bin/perl # Copyright (C) 2006 Novell Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., # 51 Franklin Street, # Fifth Floor, # Boston, MA 02110-1301, # USA. # BEGIN { unshift @INC, "/usr/share/inst-source-utils/modules"; } $| = 1; use strict; use Cwd; use Time::localtime; use Time::Local; use RPMQ; # current date minus two years my $min_date = time - 2*365*24*3600; my %month_to_num = (Jan=>0,Feb=>1,Mar=>2,Apr=>3,May=>4,Jun=>5,Jul=>6,Aug=>7,Sep=>8,Oct=>9,Nov=>10,Dec=>11); my $delimiter = "------------------------------------------------------------------"; my $actual = 0; my $skip_rest = 0; my %entries = (); my %packages = (); my $announce_string = ""; # environment my $current_client = $ARGV[0]; chomp ( $current_client = getcwd ) unless ( $current_client ); my $root_on_cd = $ENV{"ROOT_ON_CD"}; $root_on_cd = "suse" unless ($root_on_cd); my $cds_prim = ""; my @pactreeCDall = (); if ( -d "$current_client/DVD1/$root_on_cd" ) { $cds_prim = "$current_client/DVD1"; for my $i (1...9) { push @pactreeCDall, "$current_client/DVD$i/$root_on_cd" if ( -d "$current_client/DVD$i/$root_on_cd" ); } } elsif ( -d "$current_client/CD1/$root_on_cd" ) { $cds_prim = "$current_client/CD1"; for my $i (1...9) { push @pactreeCDall, "$current_client/CD$i/$root_on_cd" if ( -d "$current_client/CD$i/$root_on_cd" ); } } else { $cds_prim = "$current_client"; push @pactreeCDall, "$current_client/$root_on_cd"; } my $distro = $ENV{"BBASENAME"}; $distro = "all" unless ($distro); #print "cds_prim is $cds_prim\n"; #print "distro is $distro\n"; sub process_line { my ($myline,$package) = @_; chomp ($myline); next if ($myline =~ /^--$/); next if ($myline =~ /^=========================================*$/); if ($myline =~ /^\* .* - .*\@.*/) { my @datarray = split ( ' ',$myline); my $last_actual = $actual; if ( $datarray[4] < 1980 || $datarray[3] < 1 || $datarray[2] < 0 || $datarray[4] > 2100 || $datarray[3] > 31 || $datarray[2] > 11 ) { $datarray[2] = 1; $datarray[3] = 1; $datarray[4] = 1; warn ("invalid date line in $package: $myline\n"); } my $monthnum = $month_to_num{$datarray[2]}; $actual = timelocal ( 0,0,0,$datarray[3],$monthnum, $datarray[4]-1900); if ( $actual < $min_date ) { $skip_rest = 1; next; } if ( $last_actual ne $actual ) { $entries{$actual} .= "\n$announce_string\n"; } next; } if ($myline =~ /^\s*-/) { $myline =~ s/^\s*(\S*)/$1/; $myline =~ s/(\S*)\s*$/$1/; $entries{$actual} .= " $myline\n"; next; } if ($myline =~ /\S/) { $myline =~ s/^\s*(\S*)/$1/; $myline =~ s/(\S*)\s*$/$1/; $entries{$actual} .= " $myline\n"; } } my $findstr .= join(" ",@pactreeCDall); my $lasttime = ""; #print "findstr = $findstr\n"; my %allrpms = (); open ( RPMLIST , "find $findstr -maxdepth 4 -name \"*.rpm\" -print |"); while ( my $myrpm = <RPMLIST> ) { chomp ($myrpm); my $basename = $myrpm; $basename =~ s/^.*\///; $allrpms{$basename} = $myrpm; } close ( RPMLIST ); my $all_num = keys (%allrpms); my $cur_num = 0; for my $myrpm (sort (keys (%allrpms))) { my $myfile = $allrpms{$myrpm}; $cur_num++; print "$all_num - $cur_num\r" if ( -t STDOUT ); chomp ( $myfile ); next unless ( -f $myfile ); next unless ( $myfile =~ /\.rpm$/ ); my $basename = $myfile; $basename =~ s/^.*\///; # NAME and SOURCERPM my %p_res = RPMQ::rpmq_many($myfile,1000,1044); my $package_r = ($p_res{1000} || [])->[0]; my $srcrpm = ($p_res{1044} || [])->[0]; next unless ($srcrpm); my $package = $srcrpm; $package =~ s/-[^-]*-[^-]*$//; next if ( $packages{$srcrpm} ); $packages{$srcrpm} = 1; $announce_string = "++++ $package:\n"; # CHANGELOGTIME, CHANGELOGTEXT my %c_res = RPMQ::rpmq_many($myfile,1080,1082); for my $mytime (@{$c_res{1080} || []}) { last if ( $mytime < $min_date ); $entries{$mytime} .= "\n$announce_string\n" if ( $lasttime ne $mytime ); $lasttime = $mytime; for my $myline (split("\n",@{$c_res{1082} || []}[0])) { $myline =~ s/^\s*(\S*)/$1/; $myline =~ s/(\S*)\s*$/$1/; if ( $myline =~ /^-/ ) { $entries{$mytime} .= " $myline\n"; } else { $entries{$mytime} .= " $myline\n"; } } shift @{$c_res{1082} || []}; } } #print "\n"; unlink "$cds_prim/ChangeLog"; open ( CHANGELOG , "> $cds_prim/ChangeLog" ); my $clog = "Changelog.$distro -----------------"; my $clog_len = length ( $clog ); my $clog_rest = 25 - $clog_len; my $mydate = `date`; chomp ($mydate); print CHANGELOG "$delimiter\n"; printf CHANGELOG "--- %.25s %s ------\n" , $clog , $mydate; print CHANGELOG "$delimiter\n"; foreach my $key (sort {0+$b <=> 0+$a} (keys %entries)) { my $ltime = localtime $key; my $kyear = $ltime->year + 1900; my $kmon = $ltime->mon + 1; my $kmon_ascii = (qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec))[$ltime->mon]; my $kday = $ltime->mday; print CHANGELOG "$delimiter\n------------------ $kyear-$kmon-$kday - $kmon_ascii $kday $kyear -------------------\n$delimiter\n"; print CHANGELOG "$entries{$key}\n"; } close ( CHANGELOG ); 07070100000011000081ED000000000000000000000001654BBDF90000234D000000000000000000000000000000000000003100000000inst-source-utils-2023.11.08/usr/bin/mk_listings#!/usr/bin/perl # # Copyright (C) 2007 Novell Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License 2 # as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., # 51 Franklin Street, # Fifth Floor, # Boston, MA 02110-1301, # USA. # # $Id$ sub cp { my $from = shift; my $to = shift; $to =~ s/\/+$//; if (-d $to) { return undef unless $from =~ /([^\/]+)$/; $to = $to ne '' ? "$to/$1" : "$1"; } return 1 if "$to" eq "$from"; if (!open(FROM, "<$from")) { error("cp: $from: $!\n"); return undef; } unlink("$to"); if (!open(TO, ">$to")) { my $errno = $!; close FROM; $! = $errno; error("cp: $to: $!\n"); return undef; } my $l; while ($l = <FROM>) { print TO $l; } close FROM; if (!close(TO)) { error("cp: $to: $!\n"); return undef; } return 1; } sub usage { print <<EOF Usage: $0 [directory] Creates the files ls-lR.gz, INDEX.gz and ARCHIVES.gz in the directory. Containing all content of all files in the directory and his sub- directories. Useful for searching for special files on the media using tools like pin or just zgrep. EOF ; exit $_[0] || 0; } if (( $ARGV[1] eq "-h" ) || ( $ARGV[1] eq "--help" )){ usage(0); } $ENV{'LC_CTYPE'}="en_US.UTF-8"; my $rsyncable = ""; my $arg = shift @ARGV; my $tmpdir = `mktemp -d /tmp/mk_listings.XXXXXX`; chomp ($tmpdir); if ( "$arg" ) { usage(1) unless ( -d "$arg" ); } if ( "$arg" !~ /^\// ) { $pwd = `pwd`; chomp ($pwd); $arg = "$pwd/$arg"; } $arg=~ s/ /\\ /g; my $cd_replace = "/CD"; my $arg_base = "$arg"; $arg_base =~ s/^.*\/([^\/]*)$/$1/; $cd_replace = "/DVD" if ( "$arg_base" =~ /-dvd(.*)/ ); $cd_replace = "/inst-source" if ( "$arg_base" =~ /^stable-oss/ ); system (`touch "$tmpdir/fff"`); system (`gzip --rsyncable "$tmpdir/fff" >/dev/null 2>/dev/null`); if ( -f "$tmpdir/fff.gz" ) { $rsyncable = "--rsyncable"; } system (`rm -f "$tmpdir/fff" "$tmpdir/fff.gz"`); print "INFO: creating ls-lR.gz, INDEX.gz and ARCHIVES.gz\n"; open ( FINDALL , "cd \"$arg\" ; find . -type f | grep -vE \"allrpms|\.cr-cache|\.snapshot\" |"); my @FINDALL = <FINDALL>; close ( FINDALL ); my @FINDALL2 = @FINDALL; my @FIND_RPMS = (); my @FIND_TARZ = (); my @FIND_TARBZ = (); my @FIND_TAR = (); my @FIND_DEB = (); for (@FINDALL) { push @FIND_RPMS, $_ if ( /\.rpm$/ || /\.spm$/ ); push @FIND_TARZ, $_ if ( /\.tar.gz$/ || /\.tar.Z$/ || /\.tgz$/ || /\.tar.z$/ || /\.taz$/ ); push @FIND_TARBZ, $_ if ( /\.tar.bz2$/ || /\.tbz$/ ); push @FIND_TAR, $_ if ( /\.tar$/ ); push @FIND_DEB, $_ if ( /\.deb$/ ); } open ( ARCHIVES, "| gzip $rsyncable > $tmpdir/ARCHIVES.gz"); print ARCHIVES <<EOF; --------------------------------------------------------------------- --------------------------------------------------------------------- --------------- Here comes contents of all files: ------------------- ------ *.rpm *.tar.gz *.tar.Z *.tgz *.taz *.tar.z *.tar *.deb ------- ------------------ found in any subdirectory ------------------------ --------------------------------------------------------------------- --------------------------------------------------------------------- EOF my $curnum = 0; my $all_num = $#FIND_RPMS + $#FIND_TARZ + $#FIND_TARBZ + $#FIND_TAR + $#FIND_DEB + 5; for (@FIND_RPMS) { $curnum++; print "$curnum/$all_num\r" if ( -t STDOUT ); my $filename = "$_"; chomp($filename); my $print_name = "$filename"; $print_name =~ s/\/CD/$cd_replace/; print ARCHIVES "-----------------------------------------------------------------\n"; print ARCHIVES "---> $print_name\n"; print ARCHIVES "-----------------------------------------------------------------\n"; my $nodigest = ""; if ( !system("rpm --nodigest 2>/dev/null") ) { $nodigest = "--nodigest --nosignature"; } $filename=~ s/ /\\ /g; open (RPML,"rpm $nodigest -qpilv \"$arg/$filename\"|"); while (<RPML>) { print ARCHIVES "$print_name: $_"; } close (RPML); print ARCHIVES "-----------------------------------------------------------------\n"; print ARCHIVES "-----------------------------------------------------------------\n"; print ARCHIVES "-----------------------------------------------------------------\n"; } for (@FIND_TARZ) { $curnum++; print "$curnum/$all_num\r" if ( -t STDOUT ); my $filename = "$_"; chomp($filename); my $print_name = "$filename"; $print_name =~ s/\/CD/$cd_replace/; print ARCHIVES "-----------------------------------------------------------------\n"; print ARCHIVES "---> $print_name\n"; print ARCHIVES "-----------------------------------------------------------------\n"; open (TARL,"tar ztvf \"$arg/$filename\"|"); while (<TARL>) { print ARCHIVES "$print_name: $_"; } close (TARL); print ARCHIVES "-----------------------------------------------------------------\n"; print ARCHIVES "-----------------------------------------------------------------\n"; print ARCHIVES "-----------------------------------------------------------------\n"; } for (@FIND_TARBZ) { $curnum++; print "$curnum/$all_num\r" if ( -t STDOUT ); my $filename = "$_"; chomp($filename); my $print_name = "$filename"; $print_name =~ s/\/CD/$cd_replace/; print ARCHIVES "-----------------------------------------------------------------\n"; print ARCHIVES "---> $print_name\n"; print ARCHIVES "-----------------------------------------------------------------\n"; open (TARL,"tar jtvf \"$arg/$filename\"|"); while (<TARL>) { print ARCHIVES "$print_name: $_"; } close (TARL); print ARCHIVES "-----------------------------------------------------------------\n"; print ARCHIVES "-----------------------------------------------------------------\n"; print ARCHIVES "-----------------------------------------------------------------\n"; } for (@FIND_TAR) { $curnum++; print "$curnum/$all_num\r" if ( -t STDOUT ); my $filename = "$_"; chomp($filename); my $print_name = "$filename"; $print_name =~ s/\/CD/$cd_replace/; print ARCHIVES "-----------------------------------------------------------------\n"; print ARCHIVES "---> $print_name\n"; print ARCHIVES "-----------------------------------------------------------------\n"; open (TARL,"tar tvf \"$arg/$filename\"|"); while (<TARL>) { print ARCHIVES "$print_name: $_"; } close (TARL); print ARCHIVES "-----------------------------------------------------------------\n"; print ARCHIVES "-----------------------------------------------------------------\n"; print ARCHIVES "-----------------------------------------------------------------\n"; } for (@FIND_DEB) { $curnum++; print "$curnum/$all_num\r" if ( -t STDOUT ); my $filename = "$_"; chomp($filename); my $print_name = "$filename"; $print_name =~ s/\/CD/$cd_replace/; print ARCHIVES "-----------------------------------------------------------------\n"; print ARCHIVES "---> $print_name\n"; print ARCHIVES "-----------------------------------------------------------------\n"; open (DEBL,"ar pf \"$arg/$filename\" data.tar.gz | tar tzvf -|"); while (<DEBL>) { print ARCHIVES "$print_name: $_"; } close (DEBL); print ARCHIVES "-----------------------------------------------------------------\n"; print ARCHIVES "-----------------------------------------------------------------\n"; print ARCHIVES "-----------------------------------------------------------------\n"; } close (ARCHIVES); cp ("$tmpdir/ARCHIVES.gz","$arg/ARCHIVES.gz"); open ( LSLR , "cd \"$arg\" ; ls -lR |" ); open ( LSLRZ, "| gzip $rsyncable > $tmpdir/ls-lR.gz"); while (<LSLR>) { next if ( /\.listing$/ ); $_ =~ s/\/CD/$cd_replace/; print LSLRZ "$_"; } close (LSLR); close (LSLRZ); cp ("$tmpdir/ls-lR.gz","$arg/ls-lR.gz"); open ( INDEX, "| gzip $rsyncable > $tmpdir/INDEX.gz"); for (@FINDALL2) { next if ( /\.listing$/ ); $_ =~ s/\/CD/$cd_replace/; print INDEX "$_"; } close (INDEX); cp ("$tmpdir/INDEX.gz","$arg/INDEX.gz"); system("rm -rf $tmpdir"); if ( -d "$arg/CD1" ) { unlink "$arg/CD1/ARCHIVES.gz" if ( -f "$arg/CD1/ARCHIVES.gz" ); link "$arg/ARCHIVES.gz","$arg/CD1/ARCHIVES.gz"; } for (1...9) { next unless ( -d "$arg/CD$_" ); unlink "$arg/CD$_/INDEX.gz" if ( -f "$arg/CD$_/INDEX.gz" ); link "$arg/INDEX.gz", "$arg/CD$_/INDEX.gz"; unlink "$arg/CD$_/ls-lR.gz" if ( -f "$arg/CD$_/ls-lR.gz" ); link "$arg/ls-lR.gz","$arg/CD$_/ls-lR.gz"; } 07070100000012000081ED000000000000000000000001654BBDF900001AA0000000000000000000000000000000000000003600000000inst-source-utils-2023.11.08/usr/bin/packages2eula.pl#! /usr/bin/perl -w # # packages2eula.pl -- generates a concatenated EULA.txt from a packages file # # (C) 2007, jw@suse.de, Novell Inc. # Distributable under GPLv2 or GPLv3. # # This implements https://keeper.suse.de/webfate/match/id?value=302018 # # $Id: packages2eula.pl,v 1.4 2007/08/06 17:35:36 jw Exp jw $ # $Log: packages2eula.pl,v $ # Revision 1.4 2007/08/06 17:35:36 jw # do not modify EULA.txt if no licenses found. (did append = = END = =) before. # # Revision 1.3 2007/08/06 17:34:57 jw # *** empty log message *** # # Revision 1.2 2007/08/06 17:34:02 jw # *** empty log message *** # # Revision 1.1 2007/06/05 12:24:39 root # Initial revision # use Data::Dumper; my $version = '1.1'; my $verbose = 1; my $in_file; my $out_file; my $packages_file_def = 'suse/setup/descr/packages.en'; my $packages_file; my $with_content = 1; my $with_listing = 1; my $translation_archive = "/media.1/licenses.zip"; while (defined (my $arg = shift)) { if ($arg !~ m{^-.}) { unshift @ARGV, $arg; last } elsif ($arg =~ m{^(-h|--help|-\?)}) { exit usage(); } elsif ($arg =~ m{^--?v}) { $verbose++; } elsif ($arg =~ m{^--?q}) { $verbose = 0; } elsif ($arg =~ m{^--?i}) { $in_file = shift; } elsif ($arg =~ m{^--?o}) { $out_file = shift; } elsif ($arg =~ m{^--?p}) { $packages_file = shift; } elsif ($arg =~ m{^--?c}) { $with_content = !$with_content; } elsif ($arg =~ m{^--?l}) { $with_listing = !$with_listing; } else { exit usage("unknown option $arg"); } } $out_file ||= '-'; $in_file = $out_file if !$in_file and $out_file ne '-'; $out_file = $in_file if $out_file eq '='; unless (defined $packages_file) { $packages_file = $packages_file_def; # default from current dir. unless (-f $packages_file) # try relative to $in_file { ($packages_file = ($in_file||'')) =~ s{[^/]+$}{}; $packages_file .= $packages_file_def; } unless (-f $packages_file) # try relative to $out_file { ($packages_file = ($out_file||'')) =~ s{[^/]+$}{}; $packages_file .= $packages_file_def; } } exit usage("need at least one of -i or -o\n") unless $in_file and $out_file; print "using packages_file: $packages_file\n" if $verbose; open P, "<", $packages_file or die "cannot read $packages_file: $!\n"; my $pkg; my %eul; my $name = ''; while (defined(my $line = <P>)) { chomp $line; next if $line =~ m{^#}; if ($line =~ m{^([+=])(\w+):\s*(.*)$}) { my ($sign, $key, $val) = ($1,$2,$3); if ($sign eq '+') { while (defined($line = <P>)) { last if $line =~ m{^\-$key:\s*$}; $val .= $line; } } if ($key eq 'Pkg') { $val =~ s{\s+$}{}; my @n = split /\s+/, $val; $name = "$n[0]-$n[1]-$n[2]"; $pkg->{$name}{name} = $n[0]; $pkg->{$name}{version} = $n[1]; $pkg->{$name}{release} = $n[2]; $pkg->{$name}{arch} = $n[3]; } elsif ($key =~ m{(Eul|Sum)}) { next unless $name; # packages.en starts with "=Ver: 2.0" $pkg->{$name}{$key} = decode_richtext($val); push @{$eul{$pkg->{$name}{$key}}{pkg}}, $name if $key eq 'Eul'; } # ignore all other keys. } } close P; # find license titles for my $e (keys %eul) { my $head = ''; while ($e =~ m{^(.*)$}mg) { my $h = $1; $h =~ s{^\s+}{}; $h =~ s{\s+$}{}; next unless length $h; $head .= "\n$h"; last if good_title($head); } $eul{$e}{head} = $head; $eul{$e}{body} = $e; } # sort by title my @eul = sort { lc $a->{head} cmp lc $b->{head} } values %eul; undef %eul; for my $i (0..$#eul) { $eul[$i]{app} = sprintf "APPENDIX_%d", $i+1; $eul[$i]{lst} = $with_listing ? "(" . join(' ', sort @{$eul[$i]{pkg}}) . ")\n\t" : ""; } # preload the $in_file, in case in_file and out_file are identical. open IN, "<", $in_file or die "$0: failed to read $in_file: $!\n"; my $novell_eula = join '', <IN>; close IN; if ($novell_eula =~ m{= = = = = = = = = \s+Content:\n.*\s+APPENDIX_\d\n}s and $novell_eula =~ m{= = = = = = = = = END( =)+\s*$}s) { warn "\nWARNING: Looks like Appendices are already present in $in_file.\n\n"; exit 0; } open OUT, ">$out_file" or die "$0: failed to open $out_file: $!\n"; # 1) copy input EULA text verbatim. print OUT $novell_eula; # 2) append a content listing, if desired if ($with_content and scalar @eul) { print OUT "\n".("= " x 33)."\n"; print OUT "\nContent:\n"; for my $e (@eul) { print OUT "$e->{head}\n\t$e->{lst} See $e->{app}\n"; } print OUT "\n"; } # 3) append each EULA with a separtion line containing AppendixN # so that we can jump directly. for my $e (@eul) { print OUT "\n".("= " x 14).$e->{app}.(" =" x 13)."\n$e->{lst}\n"; print OUT $e->{body}; } print OUT "\n".("= " x 16)."END".(" =" x 15)."\n" if scalar @eul; close OUT or die "could not write $out_file: $!\n"; printf STDERR "%d Appendices written.\n", scalar @eul if $verbose; exit 0; ############################################################ # get EULA header: first line, plus second text line # if the word 'license' oder 'agreement' are not in first. # but only 'End User License Agreement' is insufficient. sub good_title { my ($text) = @_; return 0 unless $text =~ m{(license|licence|agreement)}i; $text =~ s{(license|licence|agreement|end|user)}{}gi; return 0 if $text =~ m{^\s*$}s; return 1; } sub decode_richtext { my ($txt) = @_; return $txt unless $txt =~ s{^\Q<!-- DT:Rich -->\E}{}; $txt =~ s{<p>\s*}{\n}g; $txt =~ s{</p>\s*}{\n}g; $txt =~ s{"}{"}g; $txt =~ s{'}{'}g; $txt =~ s{<ol>\s*}{\n}g; $txt =~ s{<li>\s*}{ * }g; $txt =~ s{</li>\s*}{}g; $txt =~ s{</ol>\s*}{\n}g; $txt =~ s{</\w+>\s*}{}g; $txt =~ s{^\s+}{}g; $txt =~ s{\s+$}{}g; return $txt; } sub usage { my ($msg) = @_; print STDERR qq{$0 V$version usage: encoding [options] [file] valid options are: -h Print this online help -v Be more verbose. Default $verbose -q Be quiet -i inputEULA.txt Defaults to the same name as given with -o -o outputEULA.txt Defaults to stdout, if also -i is given. Use -o = for inplace modification. -p packages_file Defaults to '$packages_file_def'; tested also relative to -i and -o argument. -c Toggle writing of a content table. Default: $with_content. -l Toggle writing of package listing corresponding to the added EULAs. Default: $with_listing. }; print STDERR "\nERROR: $msg\n" if $msg; return 0; } 07070100000013000081ED000000000000000000000001654BBDF900000E8C000000000000000000000000000000000000003A00000000inst-source-utils-2023.11.08/usr/bin/rezip_repo_rsyncable#!/usr/bin/perl BEGIN { $abuild_base_dir = "/usr/share/inst-source-utils"; unshift @INC, "$abuild_base_dir/modules"; } use strict; use File::stat; use ABStructured ':bytes'; use ABXML; use Digest; sub GenerateRepomdXml { my ($repodir) = @_; my $repobase = $repodir; $repobase =~ s/\/repodata//; open (REPOMD, "<", "$repodir/repomd.xml"); my $repomd_raw = join("",<REPOMD>); close (REPOMD); my $repomd = XMLin($ABXML::repomd, $repomd_raw); for my $record (@{$repomd->{'data'}}) { my $filename = $record->{'location'}->{'href'}; my $checksumstring = $record->{'checksum'}->{'type'}; my $checksumtype = uc($checksumstring); $checksumtype =~ s/([0-9]+)/-$1/; $checksumtype .= "-1" unless $checksumtype =~ /[0-9]/; next unless open(REC, "<", "$repobase/$filename"); my $ctx = Digest->new($checksumtype); $ctx->addfile(*REC); my $newfilechksum = $ctx->hexdigest(); close (REC); if ($filename =~ /^([^\/]*\/)?[0-9a-f][0-9a-f]*-(.*)\.(gz|zst)$/) { my $new_filename = "$1$newfilechksum-$2.$3"; rename ("$repobase/$filename","$repobase/$new_filename"); $filename = $new_filename; $record->{'location'}->{'href'} = $filename; } my $nstat = stat("$repobase/$filename"); my $newfiletime = $nstat->mtime; my $newfilesize = $nstat->size; $record->{'checksum'} = { 'type' => $checksumstring, '_content' => $newfilechksum }; $record->{'timestamp'} = $newfiletime; $record->{'size'} = $newfilesize if $record->{'size'}; } open (REPOMD, ">", "$repodir/repomd.xml"); print REPOMD "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; print REPOMD XMLout($ABXML::repomd, $repomd); close (REPOMD); } my $rsyncable = ""; my $arg = shift @ARGV; my $tmpdir = `mktemp -d /tmp/rezip_repo_rsyncable.XXXXXX`; chomp ($tmpdir); if ( $arg ) { die("need an argument") unless ( -d $arg ); } if ( $arg !~ /^\// ) { my $pwd = `pwd`; chomp ($pwd); $arg = "$pwd/$arg"; } $arg .= "/repodata" unless $arg =~ /\/repodata/; system ("touch", "$tmpdir/fff"); system ("gzip --rsyncable \"$tmpdir/fff\" >/dev/null 2>/dev/null"); if ( -f "$tmpdir/fff.gz" ) { $rsyncable = "--rsyncable"; } unlink ("$tmpdir/fff"); unlink ("$tmpdir/fff.gz"); if ( $rsyncable ) { my @ZSTDED = glob("$arg/*.zst"); for (@ZSTDED) { system ("touch", "--reference", "$_", "$_.timestamp"); system ("zstd", "--rm", "-q", "-d", "-f", $_); $_ =~ s/\.zst$//; # createrepo_c 1.0.0 sets -9 explicitly. as rsyncable adds # a few bytes, we increase to -10, which adds about 18% runtime # but improves 0.9% the compression - which compensates for rsyncable system ("zstd", "--rm", "-q", "-10", "--rsyncable", "-n", $_); system ("touch", "--reference", "$_.zst.timestamp", "$_.zst"); unlink ("$_.zst.timestamp"); } my @GZIPPED = glob("$arg/*.gz"); for (@GZIPPED) { system ("touch", "--reference", "$_", "$_.timestamp"); system ("gunzip", "-f", $_); $_ =~ s/\.gz$//; system ("gzip", "-9", "-n", $rsyncable, $_); system ("touch", "--reference", "$_.gz.timestamp", "$_.gz"); unlink ("$_.gz.timestamp"); } my $has_sign = ""; $has_sign = "1" if ( -f "$arg/repomd.xml.asc" ); system ("cp", "-a", "$arg/repomd.xml.key", $tmpdir) if ( -f "$arg/repomd.xml.key" ); if ( -f "$arg/repomd.xml" ) { GenerateRepomdXml($arg); } if ( $has_sign ) { unlink "$arg/repomd.xml.asc"; system ("sign", "-d", "$arg/repomd.xml"); } if ( -f "$tmpdir/repomd.xml.key" ) { system ("cp", "-a", "$tmpdir/repomd.xml.key", $arg); } if ( -f "$arg/MD5SUMS" ) { system ("create_md5sums", $arg); } } system("rm", "-r", "-f", $tmpdir); 07070100000014000041ED000000000000000000000003654BBDF900000000000000000000000000000000000000000000002700000000inst-source-utils-2023.11.08/usr/share07070100000015000041ED000000000000000000000003654BBDF900000000000000000000000000000000000000000000003900000000inst-source-utils-2023.11.08/usr/share/inst-source-utils07070100000016000041ED000000000000000000000002654BBDF900000000000000000000000000000000000000000000004100000000inst-source-utils-2023.11.08/usr/share/inst-source-utils/modules07070100000017000081A4000000000000000000000001654BBDF9000034CC000000000000000000000000000000000000005100000000inst-source-utils-2023.11.08/usr/share/inst-source-utils/modules/ABStructured.pm package ABStructured; use vars qw($VERSION @ISA @EXPORT); require Exporter; @ISA = qw(Exporter); @EXPORT = qw(XMLin XMLinfile XMLout); $VERSION = '1.0'; use XML::Parser; use Encode; use strict; our $bytes; sub import { $bytes = 1 if grep {$_ eq ':bytes'} @_; __PACKAGE__->export_to_level(1, grep {$_ ne ':bytes'} @_); } sub _workin { my ($how, $out, $ain, @in) = @_; my @how = @$how; my $am = shift @how; my %known = map {ref($_) ? (!@$_ ? () : (ref($_->[0]) ? $_->[0]->[0] : $_->[0] => $_)) : ($_=> $_)} @how; for my $a (keys %$ain) { die("unknown attribute: $a\n") unless $known{$a}; if (ref($known{$a})) { die("attribute '$a' must be element\n") if @{$known{$a}} > 1 || ref($known{$a}->[0]); push @{$out->{$a}}, $ain->{$a}; } else { die("attribute '$a' must be singleton\n") if exists $out->{$a}; $out->{$a} = $ain->{$a}; Encode::_utf8_off($out->{$a}) if $bytes; } } while (@in) { my ($e, $v) = splice(@in, 0, 2); my $ke = $known{$e}; if ($e eq '0') { next if $v =~ /^\s*$/s; die("element '$am' contains content\n") unless $known{'_content'}; Encode::_utf8_off($v) if $bytes; $v =~ s/\s+$/ /s; $v =~ s/^\s+/ /s; if (exists $out->{'_content'}) { $out->{'_content'} =~ s/ $//s if $v =~ /^ /s; $out->{'_content'} .= $v; } else { $out->{'_content'} = $v; } next; } if (!$ke && $known{''}) { $ke = $known{''}; $v = [{}, $e, $v]; $e = ''; } die("unknown element: $e\n") unless $ke; if (!ref($ke)) { push @$v, '0', '' if @$v == 1; die("element '$e' contains attributes @{[keys %{$v->[0]}]}\n") if %{$v->[0]}; die("element '$e' has subelements\n") if $v->[1] ne '0'; die("element '$e' must be singleton\n") if exists $out->{$e}; Encode::_utf8_off($v->[2]) if $bytes; $out->{$e} = $v->[2]; } elsif (@$ke == 1 && !ref($ke->[0])) { push @$v, '0', '' if @$v == 1; die("element '$e' contains attributes\n") if %{$v->[0]}; die("element '$e' has subelements\n") if $v->[1] ne '0'; Encode::_utf8_off($v->[2]) if $bytes; push @{$out->{$e}}, $v->[2]; } else { if (@$ke == 1) { push @{$out->{$e}}, {}; _workin($ke->[0], $out->{$e}->[-1], @$v); } else { die("element '$e' must be singleton\n") if exists $out->{$e}; $out->{$e} = {}; _workin($ke, $out->{$e}, @$v); } } } if (exists $out->{'_content'}) { $out->{'_content'} =~ s/^ //s; $out->{'_content'} =~ s/ $//s; } } sub _escape { my ($d) = @_; $d =~ s/&/&/sg; $d =~ s/</</sg; $d =~ s/>/>/sg; $d =~ s/"/"/sg; return $d; } sub _workout { my ($how, $d, $indent) = @_; my @how = @$how; my $am = _escape(shift @how); my $ret = "$indent<$am"; my $inelem; my %d2 = %$d; my $gotel = 0; if ($am eq '') { $ret = ''; $gotel = $inelem = 1; $indent = substr($indent, 2); } for my $e (@how) { if (!$inelem && !ref($e) && $e ne '_content') { next unless exists $d2{$e}; $ret .= _escape(" $e=").'"'._escape($d2{$e}).'"'; delete $d2{$e}; next; } $inelem = 1; next if ref($e) && !@$e; # magic inelem marker my $en = $e; $en = $en->[0] if ref($en); $en = $en->[0] if ref($en); next unless exists $d2{$en}; my $ee = _escape($en); if (!ref($e) && $e eq '_content' && !$gotel) { $gotel = 2; # special marker to strip indent $ret .= ">"._escape($d2{$e})."\n"; delete $d2{$e}; next; } $ret .= ">\n" unless $gotel; $gotel = 1; if (!ref($e)) { die("'$e' must be scalar\n") if ref($d2{$e}); if ($e eq '_content') { my $c = $d2{$e}; $ret .= "$indent "._escape("$c\n"); delete $d2{$e}; next; } if (defined($d2{$e})) { $ret .= "$indent <$ee>"._escape($d2{$e})."</$ee>\n"; } else { $ret .= "$indent <$ee/>\n"; } delete $d2{$e}; next; } elsif (@$e == 1 && !ref($e->[0])) { die("'$en' must be array\n") unless UNIVERSAL::isa($d2{$en}, 'ARRAY'); for my $se (@{$d2{$en}}) { $ret .= "$indent <$ee>"._escape($se)."</$ee>\n"; } delete $d2{$en}; } elsif (@$e == 1) { die("'$en' must be array\n") unless UNIVERSAL::isa($d2{$en}, 'ARRAY'); for my $se (@{$d2{$en}}) { die("'$en' must be array of hashes\n") unless UNIVERSAL::isa($se, 'HASH'); $ret .= _workout($e->[0], $se, "$indent "); } delete $d2{$en}; } else { die("'$en' must be hash\n") unless UNIVERSAL::isa($d2{$en}, 'HASH'); $ret .= _workout($e, $d2{$en}, "$indent "); delete $d2{$en}; } } die("excess hash entries: ".join(', ', sort keys %d2)."\n") if %d2; if ($gotel == 2 && $ret =~ s/\n$//s) { $ret .= "</$am>\n" unless $am eq ''; } elsif ($gotel) { $ret .= "$indent</$am>\n" unless $am eq ''; } else { $ret .= " />\n"; } return $ret; } package ABStructured::saxparser; sub new { return bless []; } sub start_document { my ($self) = @_; $self->[0] = []; } sub start_element { my ($self, $e) = @_; my %as = map {$_->{'Name'} => $_->{'Value'}} values %{$e->{'Attributes'} || {}}; push @{$self->[0]}, $e->{'Name'}, [ $self->[0], \%as ]; $self->[0] = $self->[0]->[-1]; } sub end_element { my ($self) = @_; $self->[0] = shift @{$self->[0]}; } sub characters { my ($self, $c) = @_; my $cl = $self->[0]; if (@$cl > 2 && $cl->[-2] eq '0') { $cl->[-1] .= $c->{'Data'}; } else { push @$cl, '0' => $c->{'Data'}; } } sub end_document { my ($self) = @_; return $self->[0]; } package ABStructured; my $xmlinparser; sub _xmlparser { my ($str) = @_; my $p = new XML::Parser(Style => 'Tree'); return $p->parse($str); } sub _saxparser { my ($str) = @_; my $handler = new ABStructured::saxparser; my $sp = XML::SAX::ParserFactory->parser('Handler' => $handler); if (ref(\$str) eq 'GLOB' || UNIVERSAL::isa($str, 'IO::Handle')) { return $sp->parse_file($str); } return $sp->parse_string($str); } sub _chooseparser { eval { require XML::SAX; }; my $saxok; if (!$@) { $saxok = 1; my $parsers = XML::SAX->parsers(); return \&_saxparser if $parsers && @$parsers && (@$parsers > 1 || $parsers->[0]->{'Name'} ne 'XML::SAX::PurePerl'); } eval { require XML::Parser; }; return \&_xmlparser unless $@; return \&_saxparser if $saxok; die("ABStructured needs either XML::SAX or XML::Parser\n"); } sub XMLin { my ($dtd, $str) = @_; $xmlinparser = _chooseparser() unless defined $xmlinparser; my $d = $xmlinparser->($str); my $out = {}; $d = ['', [{}, @$d]] if $dtd->[0] eq ''; die("document element must be '$dtd->[0]', was '$d->[0]'\n") if $d->[0] ne $dtd->[0]; _workin($dtd, $out, @{$d->[1]}); return $out; } sub XMLinfile { my ($dtd, $fn) = @_; local *F; open(F, '<', $fn) || die("$fn: $!\n"); my $out = XMLin($dtd, *F); close F; return $out; } sub XMLout { my ($dtd, $d) = @_; die("parameter is not a hash\n") unless UNIVERSAL::isa($d, 'HASH'); if ($dtd->[0] eq '') { die("excess hash elements\n") if keys %$d > 1; for my $el (@$dtd) { return _workout($el, $d->{$el->[0]}, '') if ref($el) && $d->{$el->[0]}; } die("no match for alternative\n"); } return _workout($dtd, $d, ''); } 1; __END__ =head1 NAME ABStructured - simple conversion API from XML to perl structures and back =head1 SYNOPSIS use ABStructured; $dtd = [ 'element' => 'attribute1', 'attribute2', [], 'element1', [ 'element2' ], [ 'element3' => ... ], [[ 'element4' => ... ]], ]; $hashref = XMLin($dtd, $xmlstring); $hashref = XMLinfile($dtd, $filename_or_glob); $xmlstring = XMLout($dtd, $hashref); =head1 DESCRIPTION The ABStructured module provides a way to convert xml data into a predefined perl data structure and back to xml. Unlike with modules like XML::Simple it is an error if the xml data does not match the provided skeleton (the "dtd"). Another advantage is that the order of the attributes and elements is taken from the dtd when converting back to xml. =head2 XMLin() The XMLin() function takes the dtd and a string as arguments and returns a hash reference containing the data. =head2 XMLinfile() This function works like C<XMLin()>, but takes a filename or a file descriptor glob as second argument. =head2 XMLout() C<XMLout()> provides the reverse operation to C<XMLin()>, it takes a dtd and a hash reference as arguments and returns an XML string. =head1 The DTD The dtd parameter specifies the structure of the allowed xml data. It consists of nested perl arrays. =head2 simple attributes and elements The very simple example for a dtd is: $dtd = [ 'user' => 'login', 'password', ]; This dtd will accept/create XML like: <user login="foo" password="bar" /> XMLin doesn't care if "login" or "password" are attributes or elements, so <user> <login>foo</login> <password>bar</password> </user> is also valid input (but doesn't get re-created by C<XMLout()>). =head2 multiple elements of the same name If an element may appear multiple times, it must be declared as an array in the dtd: $dtd = [ 'user' => 'login', [ 'favorite_fruits' ], ]; XMLin will create an array reference as value in this case, even if the xml data contains only one element. Valid XML looks like: <user login="foo"> <favorite_fruits>apple</favorite_fruits> <favorite_fruits>peach</favorite_fruits> </user> As attributes may not appear multiple times, XMLout will create elements for this case. Note also that all attributes must come before the first element, thus the first array in the dtd ends the attribute list. As an example, the following dtd $dtd = [ 'user' => 'login', [ 'favorite_fruits' ], 'password', ]; will create xml like: <user login="foo"> <favorite_fruits>apple</favorite_fruits> <favorite_fruits>peach</favorite_fruits> <password>bar</password> </user> "login" is translated to an attribute and "password" to an element. You can use an empty array reference to force the end of the attribute list, e.g.: $dtd = [ 'user' => [], 'login', 'password', ]; will translate to <user> <login>foo</login> <password>bar</password> </user> instead of <user login="foo" password="bar" /> =head2 sub-elements sub-elements are elements that also contain attributes or other elements. They are specified in the dtd as arrays with more than one element. Here is an example: $dtd = [ 'user' => 'login', [ 'address' => 'street', 'city', ], ]; Valid xml for this dtd looks like: <user login="foo"> <address street="broadway 7" city="new york" /> </user> It is sometimes useful to specify such dtds in multiple steps: $addressdtd = [ 'address' => 'street', 'city', ]; $dtd = [ 'user' => 'login', $addressdtd, ]; =head2 multiple sub-elements with the same name As with simple elements, one can allow sub-elements to occur multiple times. C<XMLin()> creates an array of hash references in this case. The dtd specification uses an array reference to an array for this case, for example: $dtd = [ 'user' => 'login', [[ 'address' => 'street', 'city', ]], ]; Or, with the $addressdtd definition used in the previous example: $dtd = [ 'user' => 'login', [ $addressdtd ], ]; Accepted XML is: <user login="foo"> <address street="broadway 7" city="new york" /> <address street="rural road 12" city="tempe" /> </user> =head2 the _content pseudo-element All of the non-whitespace parts between elements get collected into a single "_content" element. As example, <user login="foo"> <address street="broadway 7" city="new york"/>hello <address street="rural road 12" city="tempe"/>world </user> would set the _content element to C<hello world> (the dtd must allow a _content element, of course). If the dtd is $dtd = [ 'user' => 'login', [ $addressdtd ], '_content', ]; the xml string created by XMLout() will be: <user login="foo"> <address street="broadway 7" city="new york" /> <address street="rural road 12" city="tempe" /> hello world </user> The exact input cannot be re-created, as the positions and the fragmentation of the content data is lost. =head1 SEE ALSO B<ABStructured> requires either L<XML::Parser> or L<XML::SAX>. =head1 COPYRIGHT Copyright 2006 Michael Schroeder E<lt>mls@suse.deE<gt> This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 07070100000018000081A4000000000000000000000001654BBDF90000297B000000000000000000000000000000000000004A00000000inst-source-utils-2023.11.08/usr/share/inst-source-utils/modules/ABXML.pm package ABXML; our $opstatus = [ 'status' => 'code', [], 'summary', 'details', ]; our $patchinfodir = [ 'patchinfodir' => 'name', [[ 'entry' => 'name', 'md5', 'status', 'docu', ]] ]; our $patchinfo = [ 'patchinfo' => [], 'Filename', 'MD5SUM', 'ISSUEDATE', 'FILEOWNER', 'PACKAGER', 'ARCH', 'CATEGORY', 'INDICATIONS', 'CONTRAINDICATIONS', 'PRE', 'POST', 'ScriptsInline', 'License', 'Confirm', 'UpdateOnlyInstalled', 'ForceInstall', 'RebootNeeded', 'ReloginSuggested', 'AlwaysInstallPackages', 'InstallOnly', 'PATCHFILENAME', 'LEAVEOLDRPMS', 'PRE_DE', 'POST_DE', 'SUMMARY', 'SUMMARY_DE', 'SWAMPID', 'SUBSWAMPID', 'SWAMPSTATUS', 'APPROVED', 'RATING', 'BS-REQUESTID', [ 'DISTRIBUTION' ], [ 'PACKAGE' ], [ 'PACKAGE-GA' ], [ 'SCRIPT' ], [ 'PRESCRIPT' ], [ 'POSTSCRIPT' ], [ 'CD-Produkt-Name' ], [ 'CD-Produkt-Version' ], [ 'BUGZILLA' ], [ 'CVE' ], [ 'UPDATESCRIPT' ], [ 'OBSOLETES' ], [ 'REQUIRES' ], [ 'Freshens' ], [ 'IMAGE' ], [ 'FILES' ], [ 'DESCRIPTION' ], [ 'DESCRIPTION_DE' ], [ 'DIRECTORIES' ], ]; our $patchdocu = [ 'patchdocu' => [], 'description', 'keywords', 'abstract', 'swampid', 'priority', 'lastchanged', [ 'bugzilla' => [ 'bnum', ] ], [ 'products' => [[ 'product', => [], 'name', 'longname', 'source', 'patchname', ]], ], [ 'body', => [], 'html', 'ascii', 'description', ], ]; our $approve_pi = [ 'approve_pi' => [], 'user', 'behalf', 'md5sum', ]; our $reject_pi = [ 'reject_pi' => [], 'user', 'reason', 'md5sum', ]; our $maintlist = [ 'maintlist' => [], 'package', 'type', [ 'DISTRIBUTION' ], ]; our @rpm_entry = ( [[ 'rpm:entry' => 'kind', 'name', 'flags', 'epoch', 'ver', 'rel', 'pre', ]], ); our @rpm_entry_2 = ( [[ 'rpm:entry' => 'kind', 'name', 'epoch', 'ver', 'rel', 'pre', 'flags', ]], ); our @suse_entry = ( [[ 'suse:entry' => 'kind', 'name', 'flags', 'epoch', 'ver', 'rel', 'pre', ]], ); our $repomd = [ 'repomd' => 'xmlns', 'xmlns:rpm', 'xmlns:suse', [], 'revision', [ 'tags' => [ 'content' ], [ 'repo' ], [[ 'distro' => 'cpeid', '_content', ]], ], [[ 'data' => 'type', [ 'location' => 'href', ], [ 'checksum' => 'type', '_content', ], 'timestamp', 'size', 'open-size', [ 'header-checksum' => 'type', '_content', ], [ 'header-size' => '_content', ], [ 'open-checksum' => 'type', '_content', ], ]], ]; our $primary = [ 'metadata' => 'xmlns', 'xmlns:rpm', 'xmlns:suse', 'packages', [[ 'package' => 'xmlns', 'type', [], 'name', 'arch', [ 'version' => 'epoch', 'ver', 'rel', ], [[ 'checksum', => 'type', 'pkgid', '_content', ]], [[ 'summary' => 'lang', '_content', ]], [[ 'description' => 'lang', '_content', ]], 'packager', 'url', [ 'time' => 'file', 'build', ], [ 'size' => 'package', 'installed', 'archive', ], [ 'location' => 'xml:base', 'href', ], [ 'format' => [], 'rpm:license', 'rpm:vendor', 'rpm:group', 'rpm:buildhost', 'rpm:sourcerpm', [ 'rpm:header-range' => 'start', 'end', ], [ 'rpm:provides' => @rpm_entry ], [ 'rpm:requires' => @rpm_entry ], [ 'rpm:conflicts' => @rpm_entry ], [ 'rpm:obsoletes' => @rpm_entry ], [ 'rpm:suggests' => @rpm_entry ], [ 'rpm:recommends' => @rpm_entry ], [ 'rpm:supplements' => @rpm_entry ], [ 'rpm:enhances' => @rpm_entry ], [[ 'file' => 'type', '_content', ]], ], 'suse:license-to-confirm', ]], ]; our $susedata = [ 'susedata' => 'xmlns', 'packages', [[ 'package' => 'pkgid', 'name', 'arch', [ 'version' => 'epoch', 'ver', 'rel', ], 'eula', 'pattern-category', [[ 'keyword' => '_content', ]], [ 'diskusage' => [ 'dirs' => [[ 'dir' => 'name', 'size', 'count', ]], ], ], ]], ]; our $susedata_i18n = [ 'susedata' => 'xmlns', 'packages', [[ 'package' => 'pkgid', 'name', 'arch', [ 'version' => 'epoch', 'ver', 'rel', ], [ 'summary' => 'lang', [], '_content', ], [ 'description' => 'lang', [], '_content', ], [ 'pattern-category' => 'lang', [], '_content', ], 'eula', ]], ]; our $filelists = [ 'filelists' => 'xmlns', 'packages', [[ 'package' => 'pkgid', 'name', 'arch', [ 'version' => 'epoch', 'ver', 'rel', ], [[ 'file' => 'type', '_content', ]], ]], ]; our $otherdata = [ 'otherdata' => 'xmlns', 'packages', [], [[ 'package' => 'pkgid', 'name', 'arch', [], [ 'version' => 'epoch', 'ver', 'rel', ], [[ 'changelog' => 'author', 'date', '_content', ]], ]], ]; our $suseinfo = [ 'suseinfo' => 'xmlns', [], 'expire', ]; our $patch_zypp = [ 'patch' => 'xmlns', 'xmlns:yum', 'xmlns:rpm', 'xmlns:suse', 'patchid', 'timestamp', 'engine', [], 'yum:name', [[ 'summary' => 'lang', '_content', ]], [[ 'description' => 'lang', '_content', ]], [ 'yum:version' => 'ver', 'rel', ], [ 'rpm:provides' => @rpm_entry_2 ], [ 'rpm:requires' => @rpm_entry_2 ], [ 'rpm:conflicts' => @rpm_entry_2 ], [ 'rpm:obsoletes' => @rpm_entry_2 ], [ 'rpm:suggests' => @rpm_entry_2 ], [ 'rpm:enhances' => @rpm_entry_2 ], [ 'rpm:recommends' => @rpm_entry_2 ], [ 'rpm:supplements' => @rpm_entry_2 ], 'reboot-needed', 'package-manager', 'category', [ 'update-script' => [], 'do', [ 'do-location' => 'href', ], [ 'do-checksum' => 'type', '_content', ], ], [[ 'license-to-confirm', 'lang', '_content', ]], [ 'atoms' => [[ 'package' => 'xmlns', 'type', [], 'name', 'arch', [ 'version' => 'epoch', 'ver', 'rel', ], [[ 'checksum', => 'type', 'pkgid', '_content', ]], [ 'time' => 'file', 'build', ], [ 'size' => 'package', 'installed', 'archive', ], [ 'location' => 'xml:base', 'href', ], [ 'format' => [ 'rpm:provides' => @rpm_entry_2 ], [ 'rpm:requires' => @rpm_entry_2 ], [ 'rpm:conflicts' => @rpm_entry_2 ], [ 'rpm:obsoletes' => @rpm_entry_2 ], [ 'rpm:suggests' => @rpm_entry_2 ], [ 'rpm:enhances' => @rpm_entry_2 ], [ 'rpm:recommends' => @rpm_entry_2 ], [ 'rpm:supplements' => @rpm_entry_2 ], [ 'suse:freshens' => @suse_entry ], 'install-only', ], [ 'pkgfiles' => 'xmlns', [[ 'patchrpm' => [ 'location' => 'href', ], [[ 'checksum', => 'type', 'pkgid', '_content', ]], [ 'time' => 'file', 'build', ], [ 'size' => 'package', 'installed', 'archive', ], [[ 'base-version' => 'epoch', 'ver', 'rel', ]], ]], [[ 'deltarpm' => [ 'location' => 'href', ], [[ 'checksum', => 'type', 'pkgid', '_content', ]], [ 'time' => 'file', 'build', ], [ 'size' => 'package', 'installed', 'archive', ], [ 'base-version' => 'epoch', 'ver', 'rel', 'md5sum', 'buildtime', 'sequence_info', ], ]], ], ]], [[ 'message' => 'xmlns', 'yum:name', [ 'yum:version' => 'epoch', 'ver', 'rel', ], [ 'text' => 'lang', '_content', ], [ 'rpm:requires' => 'pre', @rpm_entry_2 ], [ 'suse:freshens' => @suse_entry ], ]], [[ 'script' => 'xmlns', 'yum:name', [ 'yum:version' => 'epoch', 'ver', 'rel', ], 'do', [ 'do-location' => 'href', ], [ 'do-checksum' => 'type', '_content', ], [ 'rpm:requires' => 'pre', @rpm_entry_2 ], [ 'suse:freshens' => @suse_entry ], ]], ], ]; our $patch_sat = [ 'update' => 'status', 'from', 'type', 'version', [], 'id', 'title', 'severity', 'release', [ 'issued' => 'date', ], [ 'references' => [[ 'reference' => 'href', 'id', 'title', 'type', ]], ], [ 'description' => '_content', ], [ 'pkglist' => [ 'collection' => [[ 'package' => 'name', 'arch', 'version', 'release', [], 'filename', 'reboot_suggested', 'relogin_suggested', 'restart_suggested', ]], ], ], ]; our $bsinfo; if ($BSXML::request) { $bsinfo = [ 'bsinfo' => 'instance', $BSXML::request, ]; }; our $prodfile = [ 'product' => 'id', 'schemeversion', [], 'vendor', 'name', 'version', 'baseversion', 'patchlevel', 'migrationtarget', 'release', 'arch', 'endoflife', 'productline', [ 'register' => [], 'target', 'release', [ 'repositories' => [[ 'repository' => 'path', ]], ], ], [ 'upgrades' => [], [ 'upgrade' => [], 'name', 'summary', 'product', 'notify', 'status', ], ], 'updaterepokey', 'summary', 'shortsummary', 'description', [ 'linguas' => [[ 'language' => '_content' ]], ], [ 'urls' => [[ 'url' => 'name', '_content', ]], ], [ 'buildconfig' => 'producttheme', 'betaversion', 'allowresolving', 'mainproduct', ], [ 'installconfig' => 'defaultlang', 'datadir', 'descriptiondir', [], [ 'releasepackage' => 'name', 'flag', 'version', 'release', ], 'distribution', [ 'obsoletepackage' ], ], 'runtimeconfig', ]; our $productsfile = [ 'products' => [[ 'product' => [], 'name', [ 'version' => 'ver', 'rel', 'epoch', ], 'arch', 'vendor', 'summary', 'description', ]], ]; our $patchprotocol = [ 'protocol' => [], 'title', 'suse', 'descr', [[ 'product' => 'name', 'version', 'arch', 'maint', [], 'marketing', 'path', 'nppid', [[ 'package' => 'type', 'path', 'name', ]], [[ 'metadata' => 'type', 'cat', 'path', 'name', ]], ]], 'had_errors', ]; our $patches = [ 'patches' => 'xmlns', [[ 'patch' => 'id', [], [ 'checksum' => 'type', '_content', ], [ 'location' => 'href', ], 'category', ]], ]; 1; 07070100000019000081A4000000000000000000000001654BBDF900003783000000000000000000000000000000000000004900000000inst-source-utils-2023.11.08/usr/share/inst-source-utils/modules/RPMQ.pm# # RPMQ.pm -- a simple query API for RPM-files. # # Copyright (C) 2006 Novell Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., # 51 Franklin Street, # Fifth Floor, # Boston, MA 02110-1301, # USA. # # Revision: $Revision$ # # ........... mls all basic query functions, # 2004-11-24, jw renamed from RPM.pm to RPMQ.pm to avoid name-clash with cpan modules. # added %STAG, the following methods now accept numeric AND symbolic tags: # %ref = RPMQ::rpmq_many($file, @tags); # @val = RPMQ::rpmq($filename, $tag); # 2004-11-25, mls add support for signature header queries require Data::Dumper; package RPMQ; my %STAG = ( "HEADERIMAGE" => 61, "HEADERSIGNATURES" => 62, "HEADERIMMUTABLE" => 63, "HEADERREGIONS" => 64, "HEADERI18NTABLE" => 100, "SIGSIZE" => 256+1, "SIGLEMD5_1" => 256+2, # /*!< internal - obsolete */ "SIGPGP" => 256+3, "SIGLEMD5_2" => 256+4, # /*!< internal - obsolete */ "SIGMD5" => 256+5, "SIGGPG" => 256+6, "SIGPGP5" => 256+7, # /*!< internal - obsolete */ "BADSHA1_1" => 256+8, "BADSHA1_2" => 256+9, "PUBKEYS" => 256+10, "DSAHEADER" => 256+11, "RSAHEADER" => 256+12, "SHA1HEADER" => 256+13, "SIGTAG_SIZE" => 1000, # /*!< internal Header+Payload size in bytes. */ "SIGTAG_LEMD5_1" => 1001, # /*!< internal Broken MD5, take 1 @deprecated legacy. */ "SIGTAG_PGP" => 1002, # /*!< internal PGP 2.6.3 signature. */ "SIGTAG_LEMD5_2" => 1003, # /*!< internal Broken MD5, take 2 @deprecated legacy. */ "SIGTAG_MD5" => 1004, # /*!< internal MD5 signature. */ "SIGTAG_GPG" => 1005, # /*!< internal GnuPG signature. */ "SIGTAG_PGP5" => 1006, # /*!< internal PGP5 signature @deprecated legacy. */ "SIGTAG_PAYLOADSIZE" => 1007, # /*!< internal uncompressed payload size in bytes. */ "SIGTAG_BADSHA1_1" => 256+8, # /*!< internal Broken SHA1, take 1. */ "SIGTAG_BADSHA1_2" => 256+9, # /*!< internal Broken SHA1, take 2. */ "SIGTAG_SHA1" => 256+13, # /*!< internal sha1 header digest. */ "SIGTAG_DSA" => 256+11, # /*!< internal DSA header signature. */ "SIGTAG_RSA" => 256+12, # /*!< internal RSA header signature. */ "NAME" => 1000, "VERSION" => 1001, "RELEASE" => 1002, "EPOCH" => 1003, "SERIAL" => 1003, "SUMMARY" => 1004, "DESCRIPTION" => 1005, "BUILDTIME" => 1006, "BUILDHOST" => 1007, "INSTALLTIME" => 1008, "SIZE" => 1009, "DISTRIBUTION" => 1010, "VENDOR" => 1011, "GIF" => 1012, "XPM" => 1013, "LICENSE" => 1014, "COPYRIGHT" => 1014, "PACKAGER" => 1015, "GROUP" => 1016, "SOURCE" => 1018, "PATCH" => 1019, "URL" => 1020, "OS" => 1021, "ARCH" => 1022, "PREIN" => 1023, "POSTIN" => 1024, "PREUN" => 1025, "POSTUN" => 1026, "OLDFILENAMES" => 1027, "FILESIZES" => 1028, "FILESTATES" => 1029, "FILEMODES" => 1030, "FILERDEVS" => 1033, "FILEMTIMES" => 1034, "FILEMD5S" => 1035, "FILELINKTOS" => 1036, "FILEFLAGS" => 1037, "FILEUSERNAME" => 1039, "FILEGROUPNAME" => 1040, "ICON" => 1043, "SOURCERPM" => 1044, "FILEVERIFYFLAGS" => 1045, "ARCHIVESIZE" => 1046, "PROVIDENAME" => 1047, "PROVIDES" => 1047, "REQUIREFLAGS" => 1048, "REQUIRENAME" => 1049, "REQUIREVERSION" => 1050, "NOSOURCE" => 1051, "NOPATCH" => 1052, "CONFLICTFLAGS" => 1053, "CONFLICTNAME" => 1054, "CONFLICTVERSION" => 1055, "EXCLUDEARCH" => 1059, "EXCLUDEOS" => 1060, "EXCLUSIVEARCH" => 1061, "EXCLUSIVEOS" => 1062, "RPMVERSION" => 1064, "TRIGGERSCRIPTS" => 1065, "TRIGGERNAME" => 1066, "TRIGGERVERSION" => 1067, "TRIGGERFLAGS" => 1068, "TRIGGERINDEX" => 1069, "VERIFYSCRIPT" => 1079, "CHANGELOGTIME" => 1080, "CHANGELOGNAME" => 1081, "CHANGELOGTEXT" => 1082, "PREINPROG" => 1085, "POSTINPROG" => 1086, "PREUNPROG" => 1087, "POSTUNPROG" => 1088, "BUILDARCHS" => 1089, "OBSOLETENAME" => 1090, "OBSOLETES" => 1090, "VERIFYSCRIPTPROG" => 1091, "TRIGGERSCRIPTPROG" => 1092, "COOKIE" => 1094, "FILEDEVICES" => 1095, "FILEINODES" => 1096, "FILELANGS" => 1097, "PREFIXES" => 1098, "INSTPREFIXES" => 1099, "SOURCEPACKAGE" => 1106, "PROVIDEFLAGS" => 1112, "PROVIDEVERSION" => 1113, "OBSOLETEFLAGS" => 1114, "OBSOLETEVERSION" => 1115, "DIRINDEXES" => 1116, "BASENAMES" => 1117, "DIRNAMES" => 1118, "OPTFLAGS" => 1122, "DISTURL" => 1123, "PAYLOADFORMAT" => 1124, "PAYLOADCOMPRESSOR" => 1125, "PAYLOADFLAGS" => 1126, "INSTALLCOLOR" => 1127, "INSTALLTID" => 1128, "REMOVETID" => 1129, "RHNPLATFORM" => 1131, "PLATFORM" => 1132, "PATCHESNAME" => 1133, "PATCHESFLAGS" => 1134, "PATCHESVERSION" => 1135, "CACHECTIME" => 1136, "CACHEPKGPATH" => 1137, "CACHEPKGSIZE" => 1138, "CACHEPKGMTIME" => 1139, "FILECOLORS" => 1140, "FILECLASS" => 1141, "CLASSDICT" => 1142, "FILEDEPENDSX" => 1143, "FILEDEPENDSN" => 1144, "DEPENDSDICT" => 1145, "SOURCEPKGID" => 1146, "PRETRANS" => 1151, "POSTTRANS" => 1152, "PRETRANSPROG" => 1153, "POSTTRANSPROG" => 1154, "DISTTAG" => 1155, "SUGGESTSNAME" => 1156, "SUGGESTSVERSION" => 1157, "SUGGESTSFLAGS" => 1158, "ENHANCESNAME" => 1159, "ENHANCESVERSION" => 1160, "ENHANCESFLAGS" => 1161, "FILEDIGESTALGOS" => 1177, "FILEDIGESTALGO" => 5011, ); sub RPMSENSE_MISSINGOK () { 0x80000 } sub RPMSENSE_STRONG () { 0x8000000 } sub rpmpq { my $rpm = shift; local *RPM; return undef unless open(RPM, "< $rpm"); my $head; if (sysread(RPM, $head, 75) < 11) { close RPM; return undef; } close RPM; my $name = unpack('@10Z65', $head); return $name if length($name) < 65; my %q = rpmq_many($rpm, 'NAME', 'VERSION', 'RELEASE'); return "$q{'NAME'}->[0]-$q{'VERSION'}->[0]-$q{'RELEASE'}->[0]"; } sub rpmq { my $rpm = shift; my $stag = shift; my %ret = rpmq_many($rpm, $stag); return @{$ret{$stag} || [undef]}; } # do not mix numeric tags with symbolic tags. # special symbolic tag 'FILENAME' exists. sub rpmq_many { my $rpm = shift; my @stags = @_; my @sigtags = grep {/^SIGTAG_/} @stags; @stags = grep {!/^SIGTAG_/} @stags; my $dosigs = @sigtags && !@stags; @stags = @sigtags if $dosigs; my %vtags = map {$_ => 1} @stags; my $need_filenames = $vtags{'FILENAMES'}; push @stags, 'BASENAMES', 'DIRNAMES', 'DIRINDEXES', 'OLDFILENAMES' if $need_filenames; @stags = grep { $_ ne 'FILENAMES' } @stags if $need_filenames; my %stags = map {0+($STAG{$_} or $_) => $_} @stags; my ($magic, $sigtype, $headmagic, $cnt, $cntdata, $lead, $head, $index, $data, $tag, $type, $offset, $count); local *RPM; if (ref($rpm) eq 'ARRAY') { ($headmagic, $cnt, $cntdata) = unpack('N@8NN', $rpm->[0]); if ($headmagic != 0x8eade801) { warn("Bad rpm\n"); return (); } if (length($rpm->[0]) < 16 + $cnt * 16 + $cntdata) { warn("Bad rpm\n"); return (); } $index = substr($rpm->[0], 16, $cnt * 16); $data = substr($rpm->[0], 16 + $cnt * 16, $cntdata); } else { if (ref($rpm) eq 'GLOB') { *RPM = $rpm; } elsif (!open(RPM, "<$rpm")) { warn("$rpm: $!\n"); return (); } if (read(RPM, $lead, 96) != 96) { warn("Bad rpm $rpm\n"); close RPM; return (); } ($magic, $sigtype) = unpack('N@78n', $lead); if ($magic != 0xedabeedb || $sigtype != 5) { warn("Bad rpm $rpm\n"); close RPM; return (); } if (read(RPM, $head, 16) != 16) { warn("Bad rpm $rpm\n"); close RPM; return (); } ($headmagic, $cnt, $cntdata) = unpack('N@8NN', $head); if ($headmagic != 0x8eade801) { warn("Bad rpm $rpm\n"); close RPM; return (); } if (read(RPM, $index, $cnt * 16) != $cnt * 16) { warn("Bad rpm $rpm\n"); close RPM; return (); } $cntdata = ($cntdata + 7) & ~7; if (read(RPM, $data, $cntdata) != $cntdata) { warn("Bad rpm $rpm\n"); close RPM; return (); } } my %res = (); if (@sigtags && !$dosigs) { %res = &rpmq_many(["$head$index$data"], @sigtags); } if (ref($rpm) eq 'ARRAY' && !$dosigs && @stags && @$rpm > 1) { my %res2 = &rpmq_many([ $rpm->[1] ], @stags); %res = (%res, %res2); return %res; } if ($vtags{'HEADERSTART'}) { $res{'HEADERSTART'} = [ 96 + 16 + 16 * $cnt + $cntdata ]; } if (ref($rpm) ne 'ARRAY' && !$dosigs && @stags) { if (read(RPM, $head, 16) != 16) { warn("Bad rpm $rpm\n"); close RPM; return (); } ($headmagic, $cnt, $cntdata) = unpack('N@8NN', $head); if ($headmagic != 0x8eade801) { warn("Bad rpm $rpm\n"); close RPM; return (); } if (read(RPM, $index, $cnt * 16) != $cnt * 16) { warn("Bad rpm $rpm\n"); close RPM; return (); } if (read(RPM, $data, $cntdata) != $cntdata) { warn("Bad rpm $rpm\n"); close RPM; return (); } } if ($vtags{'HEADEREND'}) { $res{'HEADEREND'} = ($res{'HEADERSTART'} || 0) + 16 + 16 * $cnt + $cntdata; @stags = grep {$_ ne 'HEADERSTART' && $_ ne 'HEADEREND'} @stags; } if ($vtags{'EXTRA'}) { my $offset = 96 + 16 + 16 * $cnt + $cntdata; my $extradata; read(RPM, $extradata, 1024, $offset); chomp($extradata); my %extras = map{split /\:/, $_}(split / /, $extradata); $res{'EXTRA'} = [\%extras]; close RPM; } close RPM if ref($rpm) ne 'ARRAY'; return %res unless @stags; # nothing to do while($cnt-- > 0) { ($tag, $type, $offset, $count, $index) = unpack('N4a*', $index); $tag = 0+$tag; if ($stags{$tag}) { eval { my $otag = $stags{$tag}; if ($type == 0) { $res{$otag} = [ '' ]; } elsif ($type == 1) { $res{$otag} = [ unpack("\@${offset}c$count", $data) ]; } elsif ($type == 2) { $res{$otag} = [ unpack("\@${offset}c$count", $data) ]; } elsif ($type == 3) { $res{$otag} = [ unpack("\@${offset}n$count", $data) ]; } elsif ($type == 4) { $res{$otag} = [ unpack("\@${offset}N$count", $data) ]; } elsif ($type == 5) { $res{$otag} = [ undef ]; } elsif ($type == 6) { $res{$otag} = [ unpack("\@${offset}Z*", $data) ]; } elsif ($type == 7) { $res{$otag} = [ unpack("\@${offset}a$count", $data) ]; } elsif ($type == 8 || $type == 9) { my $d = unpack("\@${offset}a*", $data); my @res = split("\0", $d, $count + 1); $res{$otag} = [ splice @res, 0, $count ]; } else { $res{$otag} = [ undef ]; } }; if ($@) { warn("Bad rpm $rpm: $@\n"); return (); } } } if ($need_filenames) { if ($res{'OLDFILENAMES'}) { $res{'FILENAMES'} = [ @{$res{'OLDFILENAMES'}} ]; } else { my $i = 0; $res{'FILENAMES'} = [ map {"$res{'DIRNAMES'}->[$res{'DIRINDEXES'}->[$i++]]$_"} @{$res{'BASENAMES'}} ]; } } return %res; } sub rpmq_add_flagsvers { my $res = shift; my $name = shift; my $flags = shift; my $vers = shift; my $addx = shift; return unless $res; my @flags = @{$res->{$flags} || []}; my @vers = @{$res->{$vers} || []}; for (@{$res->{$name}}) { $_ = "?$_" if $addx && $flags[0] & 0x80000; $_ = "#$_" if $addx && $flags[0] & 0x8000000; if (@flags && ($flags[0] & 0xe) && @vers) { $_ .= ' '; $_ .= '<' if $flags[0] & 2; $_ .= '>' if $flags[0] & 4; $_ .= '=' if $flags[0] & 8; $_ .= " $vers[0]"; } shift @flags; shift @vers; } } sub rpmq_provreq { my $rpm = shift; my @prov = (); my @req = (); my $r; my %res = rpmq_many($rpm, 1047, 1049, 1048, 1050, 1112, 1113); rpmq_add_flagsvers(\%res, 1047, 1112, 1113); rpmq_add_flagsvers(\%res, 1049, 1048, 1050); return $res{1047}, $res{1049}; } 1; __END__ =head1 NAME RPMQ - a simple query-API for RPM-files =head1 SYNOPSIS use RPMQ; $rpmname = RPMQ::rpmpq($rpmfile); # returns "name-version-rel" %r = RPMQ::rpmq_many($rpmfile, @tags); # returns hash of array-refs @v = RPMQ::rpmq($rpmfile, $tag); # returns array-ref ($prov, $req) = RPMQ::rpmq_provreq($rpmfile); # returns 2 array-refs %r = RPMQ::rpmq_many($rpmfile, qw{REQUIRENAME REQUIREFLAGS REQUIREVERSION}); RPMQ::rpmq_add_flagsvers(\%r, qw{REQUIRENAME REQUIREFLAGS REQUIREVERSION}); print join "\n", @{$r{REQUIRENAME}}, ""; =head1 DESCRIPTION Common tag names are: "NAME" => 1000, "VERSION" => 1001, "RELEASE" => 1002, "SUMMARY" => 1004, "DESCRIPTION" => 1005, "BUILDTIME" => 1006, "BUILDHOST" => 1007, "SIZE" => 1009, "COPYRIGHT" => 1014, "ARCH" => 1022, "SOURCERPM" => 1044, "DISTURL" => 1123, The additional tag 'FILENAMES' is also understood by rpmq_many() and rpmq(). It returns a list of full filenames (like OLDFILENAMES did in rpm3) constructed from DIRNAMES, DIRINDEXES and BASENAMES. =cut 07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!405 blocks
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor