diff options
author | Maciej Wereski <m.wereski@partner.samsung.com> | 2014-01-14 13:09:42 +0100 |
---|---|---|
committer | Maciej Wereski <m.wereski@partner.samsung.com> | 2014-07-15 15:41:01 +0200 |
commit | 1a83bfdc08996e745418a22a3c51a5297571cf7d (patch) | |
tree | bda671282cbb4cb13b64e6f57852050db88366c3 | |
parent | f8865ef4b0284f0428c4720ff2a444a63af7221f (diff) | |
download | rpmlint-1a83bfdc08996e745418a22a3c51a5297571cf7d.tar.gz rpmlint-1a83bfdc08996e745418a22a3c51a5297571cf7d.tar.bz2 rpmlint-1a83bfdc08996e745418a22a3c51a5297571cf7d.zip |
Incorporate files from tarball into git
Bug-Tizen: PTREL-604
Change-Id: I41c03fddcaebb56696c338696000541b85405c01
Signed-off-by: Maciej Wereski <m.wereski@partner.samsung.com>
48 files changed, 3469 insertions, 5 deletions
diff --git a/packaging/rpmlint-checks-master.tar.gz b/packaging/rpmlint-checks-master.tar.gz Binary files differdeleted file mode 100644 index 1c173ee..0000000 --- a/packaging/rpmlint-checks-master.tar.gz +++ /dev/null diff --git a/packaging/rpmlint.spec b/packaging/rpmlint.spec index 3ab5e9d..5c740cf 100644 --- a/packaging/rpmlint.spec +++ b/packaging/rpmlint.spec @@ -6,7 +6,6 @@ Summary: Rpm correctness checker Url: http://rpmlint.zarb.org/ Group: Development/Packaging Source0: http://rpmlint.zarb.org/download/rpmlint-%{version}.tar.bz2 -Source1: rpmlint-checks-master.tar.gz Source2: config Source10: rpmgroups.config Source11: pie.config @@ -31,18 +30,21 @@ Rpmlint is a tool to check common errors on rpm packages. Binary and source packages can be checked. %prep -%setup -q -n rpmlint-%{version} -a1 +%setup -q -n rpmlint-%{version} cp %{SOURCE1001} . cp %{SOURCE2} . -# Only move top-level python files -chmod 0755 rpmlint-checks-master/*.py -mv rpmlint-checks-master/*.py . %build make %{?_smp_mflags} +cd rpmlint-checks-master +make %{?_smp_mflags} +cd - %install %make_install +cd rpmlint-checks-master +%make_install +cd - # the provided bash-completion does not work and only prints bash errors rm -rf %{buildroot}%{_sysconfdir}/bash_completion.d mv %{buildroot}%{_sysconfdir}/rpmlint/config %{buildroot}%{_datadir}/rpmlint/config @@ -59,6 +61,8 @@ install -m 644 %{SOURCE12} %{buildroot}/%{_sysconfdir}/rpmlint/ %defattr(-,root,root,0755) %license COPYING %{_bindir}/* +%exclude %{_datadir}/rpmlint/experimental +%exclude %{_datadir}/rpmlint/obsolete %{_datadir}/rpmlint %config(noreplace) %{_sysconfdir}/rpmlint/config %config(noreplace) %{_sysconfdir}/rpmlint/licenses.config diff --git a/rpmlint-checks-master/BashismsCheck.py b/rpmlint-checks-master/BashismsCheck.py new file mode 100644 index 0000000..c851ee1 --- /dev/null +++ b/rpmlint-checks-master/BashismsCheck.py @@ -0,0 +1,47 @@ +############################################################################# +# File : BashismsCheck.py +# Package : rpmlint +# Author : Guido Berhoerster +# Purpose : check /bin/sh shell scripts for bashisms +############################################################################# + +import re +import AbstractCheck +import Config +import Pkg +from Filter import * + +class BashismsCheck(AbstractCheck.AbstractFilesCheck): + RE_BIN_SH = re.compile('#!\s*(/usr)?/bin/sh(\s+|$)') + + def __init__(self): + AbstractCheck.AbstractFilesCheck.__init__(self, "BashismsCheck", ".*") + + def check_file(self, pkg, filename): + try: + f = open(filename) + except: + return + try: + first_line = f.read(256).split("\n")[0] + if self.RE_BIN_SH.match(first_line): + status, output = Pkg.getstatusoutput(["dash", "-n", filename]) + if status == 2: + printWarning(pkg, "bin-sh-syntax-error", filename) + try: + status, output = Pkg.getstatusoutput(["checkbashisms", filename]) + if status == 1: + printInfo(pkg, "potential-bashisms", filename) + except Exception, x: + printError(pkg, 'rpmlint-exception', "%(file)s raised an exception: %(x)s" % {'file':filename, 'x':x}) + finally: + f.close() + +check = BashismsCheck() + +if Config.info: + addDetails('bin-sh-syntax-error', + '''A /bin/sh shell script contains a syntax error.''', + 'potential-bashisms', + '''checkbashisms reported potential bashisms in a /bin/sh shell +script, you might want to manually check this script for bashisms.''') diff --git a/rpmlint-checks-master/BrandingPolicyCheck.py b/rpmlint-checks-master/BrandingPolicyCheck.py new file mode 100644 index 0000000..1424066 --- /dev/null +++ b/rpmlint-checks-master/BrandingPolicyCheck.py @@ -0,0 +1,132 @@ +# vim:sw=4:et +############################################################################# +# File : BrandingPolicyCheck.py +# Package : rpmlint +# Author : Dirk Mueller +# Purpose : Verify that branding related things comply +############################################################################# + +from Filter import * +import AbstractCheck +import rpm +import re +import commands +import stat +import Config +import os +import string +import Pkg + +class BrandingPolicyCheck(AbstractCheck.AbstractCheck): + def __init__(self): + self.map = [] + AbstractCheck.AbstractCheck.__init__(self, "BrandingPolicyCheck") + + def check(self, pkg): + if pkg.isSource(): + return + + pkg_requires = set(map(lambda x: string.split(x[0],'(')[0], pkg.requires())) + pkg_conflicts = set(map(lambda x: x[0], pkg.conflicts())) + + # verify that only generic branding is required by non-branding packages + for r in pkg.requires(): + if (pkg.name.find('-branding-') < 0 and + (r[0].find('-theme-') >= 0 or r[0].find('-branding-') >= 0)): + printError(pkg,'suse-branding-specific-branding-req', r[0]) + if r[0].endswith('branding') or r[0].endswith('theme'): + # XXX: that startswith 1 breaks with openSUSE 20... + if (r[1] != rpm.RPMSENSE_EQUAL or not r[2][1].startswith('1')): + printError(pkg,'suse-branding-unversioned-requires', r[0]) + + # verify that it doesn't conflict with branding + for r in pkg_conflicts: + if r.startswith("otherproviders("): + continue + if r.find('-theme-') >= 0 or r.find('-branding-') >= 0: + printError(pkg,'suse-branding-branding-conflict', r) + + if pkg.name.find('-branding-') < 0: + return + + branding_basename=pkg.name.partition('-branding-')[0] + branding_style=pkg.name.partition('-branding-')[2] + generic_branding = ("%s-branding" % (branding_basename)) + + pkg_provides = set(map(lambda x: string.split(x[0],'(')[0], pkg.provides())) + pkg_supplements = set(map(lambda x: x[0], pkg.supplements())) + + # verify that it only supplements with packageand + found_correct=False + correct_supplement="packageand(%s:branding-%s)" % (branding_basename, branding_style) + for s in pkg_supplements: + if s.startswith('packageand('): + if s != correct_supplement: + printError(pkg,'suse-branding-wrong-branding-supplement', s) + else: + found_correct=True + else: + printError(pkg,'suse-branding-excessive-supplement', s) + + if not found_correct: + printError(pkg,'suse-branding-supplement-missing', correct_supplement) + + # nothing else + for r in pkg.recommends(): + printError(pkg,'suse-branding-excessive-recommends', r[0]) + for r in pkg.suggests(): + printError(pkg,'suse-branding-excessive-suggests', r[0]) + for r in pkg.enhances(): + printError(pkg,'suse-branding-excessive-enhances', r[0]) + + # check for provide foo-branding + branding_provide=None + for p in pkg.provides(): + if p[0] == generic_branding: + branding_provide=p + break + + # check for Conflicts: otherproviders(kde4-kdm-branding) + conflict_prop = "otherproviders(%s)" % (generic_branding) + have_conflict_prop = False + for c in pkg_conflicts: + if c == conflict_prop: + have_conflict_prop = True + break + + if not have_conflict_prop: + printError(pkg,'suse-branding-missing-conflicts', conflict_prop) + + if not branding_provide: + printError(pkg,'suse-branding-no-branding-provide') + else: + if (len(branding_provide) < 2 or branding_provide[1] != rpm.RPMSENSE_EQUAL): + printError(pkg, 'suse-branding-unversioned-provides', branding_provide[0]) + + for r in pkg.requires(): + if r[0].find('-theme-') >= 0 or r[0].find('-branding-') >= 0: + if (r[1] != rpm.RPMSENSE_EQUAL or not r[2][1].startswith('1')): + printError(pkg, 'suse-branding-unversioned-requires', r[0]) + + +check=BrandingPolicyCheck() + +if Config.info: + addDetails( +'suse-branding-specific-branding-req', +"""bla""", +'suse-branding-no-branding-provides', +"""Please add a provides entry similar to 'Provides: %name-branding = %version'.""", +'suse-branding-unversioned-provides', +"""Please make sure that your provides entry reads like 'Provides: %name-branding = %version'.""", +'suse-branding-supplement-missing', +"""branding packages should provide a supplemnent in the form +Supplements: packageand(basepackage:branding-<flavour>) +""", +'suse-branding-unversioned-requires', +"""Please make sure that your requires entry reads like 'Requires: %name-branding = <versionnumber>'.""", +'suse-branding-missing-conflicts', +"""Any branding flavor package that provides the generic branding +must also conflict with all other branding packages via a special +otherproviders()""", +) diff --git a/rpmlint-checks-master/CheckAlternativesGhostFiles.py b/rpmlint-checks-master/CheckAlternativesGhostFiles.py new file mode 100644 index 0000000..8fba5af --- /dev/null +++ b/rpmlint-checks-master/CheckAlternativesGhostFiles.py @@ -0,0 +1,85 @@ +# vim:sw=4:et +############################################################################# +# File : CheckAlternativesGhostFiles.py +# Package : rpmlint +# Author : Michal Vyskocil +# Purpose : Check if files used by update-alternatives are marked as %ghost +############################################################################# + +from Filter import * +import AbstractCheck +import rpm + +class CheckAlternativesGhostFiles(AbstractCheck.AbstractCheck): + + INSTALL="--install" + SLAVE="--slave" + + def __init__(self): + AbstractCheck.AbstractCheck.__init__(self, "CheckAlternativesGhostFiles") + + @classmethod + def read_ghost_files(cls, script): + ghost_files = [] + + if not script or not 'update-alternatives' in script: + return ghost_files + + + for command in ( \ + c.replace('\\\n', '').strip() \ + for c in script.split('update-alternatives') \ + if cls.INSTALL in c): + + #parse install + command_args = [] + for arg in command.split(None): + if not arg.startswith("--"): + command_args.append(arg) + + ghost_files.append(command_args[0]) + + if cls.SLAVE in command: + for sc in ( \ + c.strip() \ + for c in command[command.index(cls.SLAVE):].split(cls.SLAVE) \ + if c.strip() != ''): + + xs = sc.split(None, 2) + ghost_files.append(xs[0]) + + return ghost_files + + def check(self, pkg): + + if pkg.isSource(): + return + + alt_files = [] + for script in (pkg.header[tag] for tag in (rpm.RPMTAG_POSTIN, rpm.RPMTAG_PREIN, rpm.RPMTAG_POSTTRANS)): + alt_files.extend(self.read_ghost_files(script)) + + files = pkg.files() + ghost_files = pkg.ghostFiles() + for af in (af for af in alt_files if not af in ghost_files): + if af in files: + printWarning(pkg, 'generic-name-not-marked-as-ghost %s' % (af)) + else: + printWarning(pkg, 'generic-name-not-in-filelist %s' % af) + + +check=CheckAlternativesGhostFiles() + +if Config.info: + addDetails( + +'generic-name-not-marked-as-ghost', +'''The update-alternatives generic name is not marked as a ghost in the %files section. +This causes problems during update. Mark it as a %ghost in %files section.''', + +'generic-name-not-in-filelist', +'''The update-alternatives generic name is not in a filelist of package. +Add it to list marked as %ghost. Note: this error will be raised, +if you use a hash ($) in file name, use rpm macros in spec file instead.''', + +) diff --git a/rpmlint-checks-master/CheckBuildDate.py b/rpmlint-checks-master/CheckBuildDate.py new file mode 100644 index 0000000..73d025b --- /dev/null +++ b/rpmlint-checks-master/CheckBuildDate.py @@ -0,0 +1,49 @@ +############################################################################# +# File : CheckBuilDate.py +# Package : rpmlint +# Author : Cristian Rodriguez +# Purpose : Check for binaries containing build date +############################################################################# + +from Filter import * +import AbstractCheck +import rpm +import re +import os +import commands +import Config +import stat +import time + +class BuildDateCheck(AbstractCheck.AbstractFilesCheck): + def __init__(self): + AbstractCheck.AbstractFilesCheck.__init__(self, "CheckBuildDate", ".*") + self.looksliketime = re.compile('(2[0-3]|[01]?[0-9]):([0-5]?[0-9]):([0-5]?[0-9])') + self.istoday = re.compile(time.strftime("%b %e %Y")) + + def check_file(self, pkg, filename): + if filename.startswith('/usr/lib/debug') or pkg.isSource(): + return + + if not stat.S_ISREG(pkg.files()[filename].mode): + return + + grep_date = pkg.grep(self.istoday, filename) + + grep_time = pkg.grep(self.looksliketime, filename) + + if len(grep_date): + if len(grep_time): + printError(pkg, "file-contains-date-and-time", filename) + else: + printWarning(pkg, "file-contains-current-date", filename) + +check=BuildDateCheck() + +if Config.info: + addDetails( +'file-contains-current-date', +"""Your file contains the current date, this may cause the package to rebuild in excess.""", +'file-contains-date-and-time', +"""Your file uses __DATE and __TIME__ this causes the package to rebuild when not needed""" +) diff --git a/rpmlint-checks-master/CheckBuildRoot.py b/rpmlint-checks-master/CheckBuildRoot.py new file mode 100644 index 0000000..3e5c144 --- /dev/null +++ b/rpmlint-checks-master/CheckBuildRoot.py @@ -0,0 +1,41 @@ +# vim:sw=4:et +############################################################################# +# File : CheckBuildRoot.py +# Package : rpmlint +# Author : Dirk Mueller, Stephan Kulow +# Purpose : Check for files containing $RPM_BUILD_ROOT +############################################################################# + +from Filter import * +import AbstractCheck +import rpm +import re +import os +import commands +import Config +import stat + +class BuildRootCheck(AbstractCheck.AbstractFilesCheck): + def __init__(self): + AbstractCheck.AbstractFilesCheck.__init__(self, "CheckBuildRoot", ".*") + t = rpm.expandMacro('%buildroot') + for m in ('name', 'version', 'release'): + t = t.replace("%%{%s}" % (m), "[\w\!-\.]{1,20}") + self.build_root_re = re.compile(t) + + def check_file(self, pkg, filename): + if filename.startswith('/usr/lib/debug') or pkg.isSource(): + return + if not stat.S_ISREG(pkg.files()[filename].mode): + return + + if len(pkg.grep(self.build_root_re, filename)): + printError(pkg, "file-contains-buildroot", filename) + +check=BuildRootCheck() + +if Config.info: + addDetails( +'file-contains-buildroot', +"Your file contains traces of $RPM_BUILD_ROOT." +) diff --git a/rpmlint-checks-master/CheckCommonFiles.py b/rpmlint-checks-master/CheckCommonFiles.py new file mode 100644 index 0000000..626d076 --- /dev/null +++ b/rpmlint-checks-master/CheckCommonFiles.py @@ -0,0 +1,89 @@ +# vim:sw=4:et +############################################################################# +# File : CheckCommonFiles.py +# Package : rpmlint +# Author : Dirk Mueller +# Purpose : Check for common files being packaged +############################################################################# + +from Filter import * +import AbstractCheck +import rpm +import re +import commands +import stat +import Config +import os +import string + +class CommonFilesCheck(AbstractCheck.AbstractCheck): + def __init__(self): + self.map = [] + AbstractCheck.AbstractCheck.__init__(self, "CheckCommonFiles") + self.sources_am_re = re.compile('([\w\d_]+_SOURCES\s*=|\s*SUBDIRS\s*=)') + + def check(self, pkg): + + if pkg.isSource(): + return + files = pkg.files() + for f in files.keys(): + if f in pkg.ghostFiles(): + continue + md5 = files[f].md5 + + if len(md5) and md5 in ( + 'c59cbaf0df9bcf35feca0d0f1fc01dae', + 'cf8c4d1a5ab88db006c47ae2b51a6b30', + '5d4638159851671944108691f23e4f28', + '0d6be33865b76025c20b48bcac87adb7'): + printError(pkg, "generic-build-instructions", f) + + # bnc 379919 + #if len(md5) and md5 in ( + # '94d55d512a9ba36caa9b7df079bae19f'): + # printError(pkg, "duplicated-file-gpl-v2", f) + + #if len(md5) and md5 in ( + # 'd32239bcb673463ab874e80d47fae504'): + # printError(pkg, "duplicated-file-gpl-v3", f) + + # bsd causes the false positive COPYING.BSD + if len(md5) and f.rsplit('/',1)[1][0].lower() == 'r' and f.rsplit('.',1)[-1].lower() in ( + 'aix', 'bsd', 'dos', 'hpux', 'irix', 'os2', 'mac', 'macos', 'tru64', + 'sco', 'vms', 'win32', 'win', 'solaris'): + printWarning(pkg, "non-linux-readme", f) + + if f.endswith("/Makefile.am") and f[:-3] + ".in" in files and f in pkg.docFiles(): + if not len(pkg.grep(self.sources_am_re, f)): + printError(pkg, "makefile-junk", f) + printError(pkg, "makefile-junk", f[:-3] + ".in") + if f[:-3] in files: + printError(pkg, "makefile-junk", f[:-3]) + +check=CommonFilesCheck() + +if Config.info: + addDetails( +'generic-build-instructions', +"""Your package contains a file that contains the FSF generic +configure/make/make install instructions. Those are useless +for a binary package. Consider removing it to save 3kb of rpm size.""", +'duplicated-file-gpl-v3', +"""Your package contains a file that contains the FSF GPLv3 +license. If you really have to ship it, consider symlinking it +from the licenses package.""", +'duplicated-file-gpl-v2', +"""Your package contains a file that contains the FSF GPLv2 +license. If you really have to ship it, consider symlinking it +from the licenses package.""", +'non-linux-readme', +"""Your package contains a file that contains instructions +for non-linux platforms. They're most likely unneccessary bloat, +consider removing them from your package.""", +'makefile-junk', +"""Your package contains makefiles that only make sense in a +source package. Did you package a complete directory from the +tarball by using %doc? Consider removing Makefile* from this +directory at the end of your %install section to reduce package bloat.""" +) diff --git a/rpmlint-checks-master/CheckDBUSServices.py b/rpmlint-checks-master/CheckDBUSServices.py new file mode 100644 index 0000000..4a93371 --- /dev/null +++ b/rpmlint-checks-master/CheckDBUSServices.py @@ -0,0 +1,57 @@ +# vim:sw=4:et +############################################################################# +# File : CheckDBUSServices.py +# Package : rpmlint +# Author : Ludwig Nussel +# Purpose : Check for DBUS services that are not authorized by the security team +############################################################################# + +# http://techbase.kde.org/Development/Tutorials/D-Bus/Autostart_Services + +from Filter import * +import AbstractCheck +import re +import os +import string + +SERVICES_WHITELIST = Config.getOption('DBUSServices.WhiteList', ()) # set of file names + +# need to end with / so we don't catch directories +_dbus_system_paths = [ + "/usr/share/dbus-1/system-services/", + "/etc/dbus-1/system.d/" +] + +class DBUSServiceCheck(AbstractCheck.AbstractCheck): + def __init__(self): + AbstractCheck.AbstractCheck.__init__(self, "CheckDBUSServices") + + def check(self, pkg): + global SERVICES_WHITELIST + global _dbus_system_paths + + if pkg.isSource(): + return + + files = pkg.files() + + for f in files: + if f in pkg.ghostFiles(): + continue + + for p in _dbus_system_paths: + if f.startswith(p): + + bn = f[len(p):] + if not bn in SERVICES_WHITELIST: + printError(pkg, "suse-dbus-unauthorized-service", f) + +check=DBUSServiceCheck() + +if Config.info: + addDetails( +'suse-dbus-unauthorized-service', +"""The package installs a DBUS system service file. If the package +is intended for inclusion in any SUSE product please open a bug +report to request review of the service by the security team.""", +) diff --git a/rpmlint-checks-master/CheckDBusPolicy.py b/rpmlint-checks-master/CheckDBusPolicy.py new file mode 100644 index 0000000..69c4efd --- /dev/null +++ b/rpmlint-checks-master/CheckDBusPolicy.py @@ -0,0 +1,80 @@ +# vim:sw=4:et +############################################################################# +# File : CheckDBusPolicy.py +# Package : rpmlint +# Author : Ludwig Nussel +# Purpose : Check for broken DBus policies +############################################################################# + +# causes extraction of package if it contains files in /etc/dbus-1/system.d/ + +from Filter import * +import AbstractCheck +from xml.dom.minidom import parse + +class DBusPolicyCheck(AbstractCheck.AbstractCheck): + def __init__(self): + AbstractCheck.AbstractCheck.__init__(self, "CheckDBusPolicy") + + def check(self, pkg): + + if pkg.isSource(): + return + + files = pkg.files() + + for f in files: + if f in pkg.ghostFiles(): + continue + + # catch xml exceptions + try: + if f.startswith("/etc/dbus-1/system.d/"): + send_policy_seen = False + lf = pkg.dirName() + f + xml = parse(lf) + for p in xml.getElementsByTagName("policy"): + for allow in p.getElementsByTagName("allow"): + if ( allow.hasAttribute('send_interface') \ + or allow.hasAttribute('send_member') \ + or allow.hasAttribute('send_path')) \ + and not allow.hasAttribute('send_destination'): + send_policy_seen = True + printError(pkg, 'dbus-policy-allow-without-destination', "%(file)s: %(xml)s" % { 'file':f, 'xml':allow.toxml() }) + elif allow.hasAttribute('send_destination'): + send_policy_seen = True + + if allow.hasAttribute('receive_sender') \ + or allow.hasAttribute('receive_interface'): + printInfo(pkg, 'dbus-policy-allow-receive', "%(file)s: %(xml)s" % { 'file':f, 'xml':allow.toxml() }) + + for deny in p.getElementsByTagName("deny"): + if ( deny.hasAttribute('send_interface') \ + and not deny.hasAttribute('send_destination')): + printError(pkg, 'dbus-policy-deny-without-destination', "%(file)s: %(xml)s" % { 'file':f, 'xml':deny.toxml() }) + + if not send_policy_seen: + printError(pkg, 'dbus-policy-missing-allow', "%(file)s does not allow communication" % { 'file':f }) + + except Exception, x: + printError(pkg, 'rpmlint-exception', "%(file)s raised an exception: %(x)s" % {'file':f, 'x':x}) + continue + +check=DBusPolicyCheck() + +if Config.info: + addDetails( +'dbus-policy-allow-without-destination', +"""'allow' directives must always specify a 'send_destination'""", +'dbus-policy-allow-receive', +"""allow receive_* is normally not needed as that is the default""", +'dbus-policy-deny-without-destination', +"""'deny' directives must always specify a 'send_destination' otherwise messages to other services could be blocked""", +'dbus-policy-missing-allow', +"""every dbus config normally needs a line of the form +<allow send_destination="org.foo.bar"/> +or similar. If that is missing the service will not work with a dbus that uses +deny as default policy""", +'rpmlint-exception', +"""A python exception was raised which prevents further analysis""", +) diff --git a/rpmlint-checks-master/CheckExecDocs.py b/rpmlint-checks-master/CheckExecDocs.py new file mode 100644 index 0000000..2d544cf --- /dev/null +++ b/rpmlint-checks-master/CheckExecDocs.py @@ -0,0 +1,97 @@ +# vim:sw=4:et +#--------------------------------------------------------------- +# Module : rpmlint +# File : CheckExecDocs.py +# Author : Stephan Kulow, Dirk Mueller +# Purpose : Check for executable files in %doc +#--------------------------------------------------------------- + +from Filter import * +import AbstractCheck +import rpm +import re +import commands +import stat +import Config +import os +import string + +def ignore_pkg(name): + if name.startswith('bundle-'): + return True + if name.find('-devel') != -1: + return True + if name.find('-doc') != -1: + return True + + return False + +def lang_ignore_pkg(name): + if ignore_pkg(name): + return True + if name.endswith('-locale'): + return True + if name.find('-trans-') != -1: + return True + + return False + +class ExecDocsCheck(AbstractCheck.AbstractCheck): + def __init__(self): + self.map = [] + AbstractCheck.AbstractCheck.__init__(self, "CheckExecDocs") + + def check(self, pkg): + + if pkg.isSource(): + return + + files = pkg.files() + complete_size=0 + lang_size=0 + for f, pkgfile in files.items(): + if stat.S_ISREG(pkgfile.mode): + complete_size += pkgfile.size + if pkgfile.lang != '': + lang_size += pkgfile.size + + doc_size=0 + for f in pkg.docFiles(): + if stat.S_ISREG(files[f].mode): + doc_size += files[f].size + + if doc_size * 2 >= complete_size \ + and doc_size > 100*1024 and (complete_size - doc_size) * 20 > complete_size \ + and not ignore_pkg(pkg.name): + printWarning(pkg, "package-with-huge-docs", ("%3d%%" % (doc_size * 100 / complete_size)) ) + + if lang_size * 2 >= complete_size \ + and lang_size > 100*1024 and (complete_size - lang_size) * 20 > complete_size \ + and not lang_ignore_pkg(pkg.name): + printWarning(pkg, "package-with-huge-translation", ("%3d%%" % (lang_size * 100 / complete_size))) + + for f in pkg.docFiles(): + mode=files[f].mode + if not stat.S_ISREG(mode) or not mode & 0111: + continue + for ext in ['txt', 'gif', 'jpg', 'html', 'pdf', 'ps', 'pdf.gz', 'ps.gz']: + if f.endswith("." + ext): + printError(pkg, 'executable-docs', f) + + for name in ['README', 'NEWS', 'COPYING', 'AUTHORS']: + if f.endswith("/" + name): + printError(pkg, 'executable-docs', f) + +check=ExecDocsCheck() + +if Config.info: + addDetails( +'executable-docs', +"Documentation should not be executable.", +'package-with-huge-docs', +"""More than half the size of your package is documentation. +Consider splitting it into a -doc subpackage.""", +'package-with-huge-translation', +"""More than half the size of your package is language-specific. +Consider splitting it into a -lang subpackage.""" +) diff --git a/rpmlint-checks-master/CheckFilelist.py b/rpmlint-checks-master/CheckFilelist.py new file mode 100644 index 0000000..fbc0af0 --- /dev/null +++ b/rpmlint-checks-master/CheckFilelist.py @@ -0,0 +1,387 @@ +# vim:sw=4:et +############################################################################# +# File : CheckFilelist.py +# Package : rpmlint +# Author : Ludwig Nussel +# Purpose : Check for wrongly packaged files and FHS violations +############################################################################# + +from Filter import * +import AbstractCheck +import re +import os +import string +import fnmatch +from rpm import RPMTAG_VENDOR + +_defaulterror = 'tizen-filelist-forbidden' +_defaultmsg = '%(file)s is not allowed in Tizen' + +def notnoarch(pkg): + return pkg.arch != 'noarch' + +def isfilesystem(pkg): + return pkg.name == 'filesystem' + +def isdebuginfo(pkg): + if pkg.name.endswith('-debuginfo') \ + or pkg.name.endswith('-debuginfo-32bit') \ + or pkg.name.endswith('-debuginfo-64bit') \ + or pkg.name.endswith('-debugsource') \ + or pkg.name.endswith('-debug'): + return True + +def notsymlink(pkg, f): + mode = pkg.files()[f].mode + type = (mode>>12)&017 + return type != 012 + +def ghostfile(pkg, f): + ghosts = pkg.ghostFiles() + return f in ghosts + +_goodprefixes = ( + '/bin/', + '/boot/', + '/etc/', + '/lib/', + '/lib64/', + '/media/', + # SUSE policy handled in separate check + '/opt/', + '/sbin/', + '/srv/', + # SUSE policy handled in separate check + '/usr/X11R6/', + '/usr/bin/', + '/usr/games/', + '/usr/include/', + '/usr/lib/', + '/usr/lib64/', + '/usr/libexec/', + '/usr/sbin/', + '/usr/share/', + # actually only linux is allowed by fhs + '/usr/src/linux', + '/usr/src/debug/', + '/usr/src/packages/', + '/var/account/', + '/var/cache/', + '/var/crash/', + '/var/games/', + '/var/lib/', + '/var/lock/', + '/var/log/', + '/var/mail/', + '/var/opt/', + '/var/run/', + '/var/spool/', + '/var/yp/', + # those are not in FHS! + '/var/adm/', + '/var/nis/', + '/emul/', + ) + +# computed from goodprefixes. +# Directories that are only allowed to have defined subdirs (such as /usr) +_restricteddirs = set() + +_checks = [ + { + 'bad': [ + '*/.xvpics', + '*.orig', + '*.orig.gz', + '/usr/share/*/.libs*', + '/usr/share/*/.deps*', + '/var/adm/setup', + '/etc/httpd/*', + '/etc/init.d/*/*', + '/usr/share/locale/LC_MESSAGES', + ], + }, + { + 'error': 'tizen-filelist-forbidden-perl-dir', + 'details': '''perl files installed a non-vendor installed path, + which is not allowed in SUSE.''', + 'bad': [ + '/usr/lib/perl5/site_perl/*', + ], + }, + { + 'error': 'tizen-filelist-forbidden-backup-file', + 'details': 'backup files (e.g. files ending in ~, .swp or .bak) are not allowed', + 'bad': [ + '*~', + '*.bak', + '*/.*.swp', + ], + 'ignorefileif': ghostfile, + }, + { + 'error': 'tizen-filelist-forbidden-devel-in-lib', + 'details': 'please move la files, static libs and .so symlinks to /usr/lib(64)', + 'bad': [ + "/lib/*.la", + "/lib/*.a", + "/lib64/*.la", + "/lib64/*.a", + ] + }, + { + 'error': 'tizen-filelist-forbidden-devel-in-lib', + 'details': 'please move la files, static libs and .so symlinks to /usr/lib(64)', + 'good': [ + # exception for pam + "/lib/security/*.so", + "/lib64/security/*.so", + ], + 'bad': [ + "/lib/*.so", + "/lib64/*.so", + ], + # some libs without proper soname are packaged directly + 'ignorefileif': notsymlink, + }, + { + 'error': 'tizen-filelist-forbidden-fhs23', + 'msg': '%(file)s is not allowed in FHS 2.3', + 'details': 'see http://www.pathname.com/fhs/ to find a better location', + 'bad': [ + "/etc/X11/app-defaults/*", + "/usr/local/man/*/*", + "/var/lib/games", + "/var/lib/games/*", + "/usr/sbin/*/*", + "/sbin/init.d", + "/sbin/init.d/*", + "/bin/*/*", + ] + }, + { + 'error': 'tizen-filelist-forbidden-srv', + 'details': """Please use /srv for ftp and http data""", + 'bad': [ + '/usr/local/ftp', + '/usr/local/http', + ], + }, + { + 'error': 'tizen-filelist-forbidden-games', + 'details': """static data has to be in /usr/share/games, variable in /var/games""", + 'bad': [ + '/usr/games/bin', + '/usr/games/lib', + '/usr/games/*/*', + ], + }, + { + 'error': 'tizen-filelist-forbidden-noarch', + 'msg': '%(file)s is not allowed in a noarch package', + 'bad': [ + '/lib64', + '/lib64/*', + '/usr/lib64', + '/usr/lib64/*', + '/usr/X11R6/lib64', + '/usr/X11R6/lib64/*', + '/opt/gnome/lib64', + '/opt/gnome/lib64/*', + '/opt/kde3/lib64', + '/opt/kde3/lib64/*', + '/usr/lib/pkgconfig/*', + '/usr/lib/perl5/vendor_perl/5.*/*-linux-*/*', + ], + 'ignorepkgif': notnoarch, + }, + { + 'error': 'tizen-filelist-forbidden-debuginfo', + 'msg': '%(file)s may only be packaged in the -debuginfo subpackage', + 'bad': [ + '/usr/lib/debug/*', + ], + 'ignorepkgif': isdebuginfo, + }, + { + 'error': 'tizen-filelist-forbidden-locale', + 'details': """Please use nb or nb_NO (and nn for nynorsk)""" + """see https://bugzilla.novell.com/show_bug.cgi?id=42748""", + 'bad': [ + '/opt/gnome/share/locale/no', + '/opt/gnome/share/locale/no/*', + '/opt/kde3/share/locale/no', + '/opt/kde3/share/locale/no/*', + '/usr/share/locale/no', + '/usr/share/locale/no/*', + '/usr/share/vim/*/lang/no', + '/usr/share/vim/*/lang/no/*', + ], + }, + { + 'error': 'tizen-filelist-forbidden-xorg', + 'details': """Please use the updated paths for Xorg 7.1 and above""", + 'bad': [ + '/usr/X11R6/*', + ], + 'ignorepkgif': isfilesystem, + }, + { + 'error': 'tizen-filelist-forbidden-opt', + 'details': """/opt may not be used by a distribution. It is reserved for 3rd party packagers""", + }, + { + 'error': 'tizen-filelist-forbidden-systemd-userdirs', + 'details': """This directory is for user files, use the system directory under /usr/lib""", + 'bad': [ + '/etc/systemd/*', + '/etc/modules-load.d/*', + '/etc/tmpfiles.d/*', + ], + }, + ] + +class FilelistCheck(AbstractCheck.AbstractCheck): + def __init__(self): + AbstractCheck.AbstractCheck.__init__(self, "CheckFilelist") + import re + + _restricteddirs.add('/') + for d in _goodprefixes: + if d.count('/') > 2: + _restricteddirs.add(d[0:-1].rpartition('/')[0]) + + for check in _checks: + if 'good' in check: + for i in range(len(check['good'])): + pattern = check['good'][i] + if '*' in pattern: + r = fnmatch.translate(pattern) + check['good'][i] = re.compile(r) + + if 'bad' in check: + for i in range(len(check['bad'])): + pattern = check['bad'][i] + if '*' in pattern: + r = fnmatch.translate(pattern) + check['bad'][i] = re.compile(r) + + def check(self, pkg): + global _checks + global _defaultmsg + global _defaulterror + global _goodprefixes + global _restricteddirs + + if pkg.isSource(): + return + + files = pkg.files() + + if not files: + printWarning(pkg, 'tizen-filelist-empty', 'packages without any files are discouraged in TIZEN') + return + + for check in _checks: + + if 'ignorepkgif' in check: + if check['ignorepkgif'](pkg): + continue + + if 'msg' in check: + msg = check['msg'] + else: + msg = _defaultmsg + + if 'error' in check: + error = check['error'] + else: + error = _defaulterror + + if 'good' in check or 'bad' in check: + for f in files.keys(): + ok = False + if 'good' in check: + for g in check['good']: + if (not isinstance(g, str) and g.match(f)) or g == f: + ok = True + break + if ok: + continue + + if 'bad' in check: + for b in check['bad']: + if 'ignorefileif' in check: + if check['ignorefileif'](pkg, f): + continue + if (not isinstance(b, str) and b.match(f)) or b == f: + printError(pkg, error, msg % { 'file':f } ) + + invalidfhs = set() + invalidopt = set() + + if pkg.header[RPMTAG_VENDOR] and pkg.header[RPMTAG_VENDOR].find('TIZEN') != -1: + isSUSE = True + else: + isSUSE = False + + # the checks here only warn about a directory once rather + # than reporting potentially hundreds of files individually + for f, pkgfile in files.items(): + type = (pkgfile.mode>>12)&017 + + # append / to directories + if type == 04: + f += '/' + + if not f.startswith(_goodprefixes): + base = f.rpartition('/') + pfx = None + # find the first invalid path component (/usr/foo/bar/baz -> /usr) + while base[0] and not base[0].startswith(_goodprefixes) and not base[0] in _restricteddirs: + pfx = base[0] + base = base[0].rpartition('/') + + if not pfx: + invalidfhs.add(f) + else: + invalidfhs.add(pfx) + + if f.startswith('/opt'): + try: + provider = f.split('/')[2] + except: + continue + # legacy exception + if provider == 'kde3': + continue + if isSUSE and (provider == 'suse' or provider == 'novell'): + continue + + d = '/opt/'+provider + invalidopt.add(d) + + for f in invalidfhs: + printError(pkg, 'tizen-filelist-forbidden-fhs23', "%(file)s is not allowed in FHS 2.3" % { 'file': f }) + + for f in invalidopt: + printError(pkg, 'tizen-filelist-forbidden-opt', '%(file)s is not allowed for official SUSE packages' % { 'file': f }) + +check=FilelistCheck() + +if Config.info: + for check in _checks: + + if not 'details' in check: + continue + + if not 'error' in check: + continue + + addDetails('tizen-filelist-forbidden', """ +Your package installs files or directories in a location that have +previously been blacklisted. Please have a look at the particular +file and see if the SUSE Packaging Guidelines propose a better place +on where to install the file or not install it at all.""") + + addDetails(check['error'], check['details']) diff --git a/rpmlint-checks-master/CheckGNOMEMacros.py b/rpmlint-checks-master/CheckGNOMEMacros.py new file mode 100644 index 0000000..bdfd6bd --- /dev/null +++ b/rpmlint-checks-master/CheckGNOMEMacros.py @@ -0,0 +1,185 @@ +# vim:sw=4:et +############################################################################# +# File : CheckGNOMEMacros.py +# Package : rpmlint +# Author : Vincent Untz +# Purpose : Check for GNOME related packaging errors +############################################################################# + +import re +import string + +import rpm + +from Filter import * +import AbstractCheck +import Config + +## FIXME +# Maybe detect packages installing icons in other themes than hicolor and not +# updating the icon cache for those themes? + +_gnome_post_postun_checks = [ + ('glib2-gsettings-schema', + re.compile('^/usr/share/glib-2.0/schemas/.+\.gschema.xml$'), + 'glib2-tools', + re.compile('^[^#]*glib-compile-schemas', re.MULTILINE), + True), + + ('glib2-gio-module', + re.compile('^/usr/lib(?:64)?/gio/modules/'), + 'glib2-tools', + re.compile('^[^#]*gio-querymodules', re.MULTILINE), + True), + + ('gdk-pixbuf-loader', + re.compile('^/usr/lib(?:64)?/gdk-pixbuf-2.0/[^/]+/loaders/'), + 'gdk-pixbuf-query-loaders', + re.compile('^[^#]*gdk-pixbuf-query-loaders', re.MULTILINE), + True), + + ('gtk2-immodule', + re.compile('^/usr/lib(?:64)?/gtk-2.0/[^/]+/immodules/'), + 'gtk2', + re.compile('^[^#]*gtk-query-immodules-2.0', re.MULTILINE), + True), + + ('gtk3-immodule', + re.compile('^/usr/lib(?:64)?/gtk-3.0/[^/]+/immodules/'), + 'gtk3-tools', + re.compile('^[^#]*gtk-query-immodules-3.0', re.MULTILINE), + True), + + # Not fatal since it would make too many things fail + ('hicolor-icon-cache', + re.compile('^/usr/share/icons/hicolor/'), + None, + re.compile('^[^#]*gtk-update-icon-cache', re.MULTILINE), + False), + + ('mime-database', + re.compile('^/usr/share/mime/packages/.+\.xml$'), + None, + re.compile('^[^#]*update-mime-database', re.MULTILINE), + True), + + # Not fatal since it would make too many things fail + ('desktop-database', + re.compile('^/usr/share/applications/.+\.desktop$'), + None, + re.compile('^[^#]*update-desktop-database', re.MULTILINE), + False) +] + +_gnome_gconf_filename_re = re.compile('^/usr/share/GConf/schemas/.+\.schemas$') +_gnome_gconf_sciptlet_re = re.compile('^[^#]*gconftool-2', re.MULTILINE) + +class GNOMECheck(AbstractCheck.AbstractCheck): + + def __init__(self): + AbstractCheck.AbstractCheck.__init__(self, "CheckGNOMEMacros") + + def check(self, pkg): + + if pkg.isSource(): + return + + ghosts = pkg.ghostFiles() + + pkg_requires = set(map(lambda x: string.split(x[0],'(')[0], pkg.requires())) + postin = pkg[rpm.RPMTAG_POSTIN] or pkg[rpm.RPMTAG_POSTINPROG] + postun = pkg[rpm.RPMTAG_POSTUN] or pkg[rpm.RPMTAG_POSTUNPROG] + posttrans = pkg[rpm.RPMTAG_POSTTRANS] or pkg[rpm.RPMTAG_POSTTRANSPROG] + + for filename in (x for x in pkg.files() if x not in ghosts): + for (name, file_re, required, post_re, fatal) in _gnome_post_postun_checks: + if fatal: + gnomePrint = printError + else: + gnomePrint = printWarning + + if file_re.search(filename): + if required and required not in pkg_requires: + gnomePrint(pkg, 'suse-' + name + '-missing-requires', filename) + if not postin or not post_re.search(postin): + gnomePrint(pkg, 'suse-' + name + '-missing-postin', filename) + if not postun or not post_re.search(postun): + gnomePrint(pkg, 'suse-' + name + '-missing-postun', filename) + + if _gnome_gconf_filename_re.search(filename): + if not ((postin and _gnome_gconf_sciptlet_re.search(postin)) or + (posttrans and _gnome_gconf_sciptlet_re.search(posttrans))): + printError(pkg, 'suse-gconf-schema-missing-scriptlets', filename) + + +check=GNOMECheck() + +if Config.info: + addDetails( +'suse-glib2-gsettings-schema-missing-requires', +'''A GSettings schema is in your package, but there is no dependency for the tool to recompile the schema database. Use %glib2_gsettings_schema_requires.''', + +'suse-glib2-gsettings-schema-missing-postin', +'''A GSettings schema is in your package, but the schema database is not recompiled in the %post scriptlet. Use %glib2_gsettings_schema_post.''', + +'suse-glib2-gsettings-schema-missing-postun', +'''A GSettings schema is in your package, but the schema database is not recompiled in the %postun scriptlet. Use %glib2_gsettings_schema_postun.''', + +'suse-glib2-gio-module-missing-requires', +'''A GIO module is in your package, but there is no dependency for the tool to rebuild the GIO module cache. Use %glib2_gio_module_requires.''', + +'suse-glib2-gio-module-missing-postin', +'''A GIO module is in your package, but the GIO module cache is not rebuilt in the %post scriptlet. Use %glib2_gio_module_post.''', + +'suse-glib2-gio-module-missing-postun', +'''A GIO module is in your package, but the GIO module cache is not rebuilt in the %postun scriptlet. Use %glib2_gio_module_postun.''', + +'suse-gdk-pixbuf-loader-missing-requires', +'''A gdk-pixbuf loader is in your package, but there is no dependency for the tool to rebuild the gdk-pixbuf loader cache. Use %gdk_pixbuf_loader_requires.''', + +'suse-gdk-pixbuf-loader-missing-postin', +'''A gdk-pixbuf loader is in your package, but the gdk-pixbuf loader cache is not rebuilt in the %post scriptlet. Use %gdk_pixbuf_loader_post.''', + +'suse-gdk-pixbuf-loader-missing-postun', +'''A gdk-pixbuf loader is in your package, but the gdk-pixbuf loader cache is not rebuilt in the %postun scriptlet. Use %gdk_pixbuf_loader_postun.''', + +'suse-gtk2-immodule-missing-requires', +'''A GTK+ 2 IM module is in your package, but there is no dependency for the tool to rebuild the GTK+ 2 IM module cache. Use %gtk2_immodule_requires.''', + +'suse-gtk2-immodule-missing-postin', +'''A GTK+ 2 IM module is in your package, but the GTK+ 2 IM module cache is not rebuilt in the %post scriptlet. Use %gtk2_immodule_post.''', + +'suse-gtk2-immodule-missing-postun', +'''A GTK+ 2 IM module is in your package, but the GTK+ 2 IM module cache is not rebuilt in the %postun scriptlet. Use %gtk2_immodule_postun.''', + +'suse-gtk3-immodule-missing-requires', +'''A GTK+ 3 IM module is in your package, but there is no dependency for the tool to rebuild the GTK+ 3 IM module cache. Use %gtk3_immodule_requires.''', + +'suse-gtk3-immodule-missing-postin', +'''A GTK+ 3 IM module is in your package, but the GTK+ 3 IM module cache is not rebuilt in the %post scriptlet. Use %gtk3_immodule_post.''', + +'suse-gtk3-immodule-missing-postun', +'''A GTK+ 3 IM module is in your package, but the GTK+ 3 IM module cache is not rebuilt in the %postun scriptlet. Use %gtk3_immodule_postun.''', + +'suse-hicolor-icon-cache-missing-postin', +'''An icon for the hicolor theme is in your package, but the hicolor icon cache is not rebuilt in the %post scriptlet. Use %icon_theme_cache_post.''', + +'suse-hicolor-icon-cache-missing-postun', +'''An icon for the hicolor theme is in your package, but the hicolor icon cache is not rebuilt in the %postun scriptlet. Use %icon_theme_cache_postun.''', + +'suse-mime-database-missing-postin', +'''A MIME definition is in your package, but the MIME database is not rebuilt in the %post scriptlet. Use %mime_database_post.''', + +'suse-mime-database-missing-postun', +'''A MIME definition is in your package, but the MIME database is not rebuilt in the %postun scriptlet. Use %mime_database_postun.''', + +'suse-desktop-database-missing-postin', +'''A desktop file is in your package, but the desktop database is not rebuilt in the %post scriptlet. Use %desktop_database_post.''', + +'suse-desktop-database-missing-postun', +'''A desktop file is in your package, but the desktop database is not rebuilt in the %postun scriptlet. Use %desktop_database_postun.''', + +'suse-gconf-schema-missing-scriptlets', +'''A GConf schema is in your package, but the GConf configuration is not updated by scriptlets. Please use the gconf RPM macros.''' + +) diff --git a/rpmlint-checks-master/CheckIconSizes.py b/rpmlint-checks-master/CheckIconSizes.py new file mode 100644 index 0000000..3a8cc96 --- /dev/null +++ b/rpmlint-checks-master/CheckIconSizes.py @@ -0,0 +1,51 @@ +# vim:sw=4:et +############################################################################# +# File : CheckIconSizes.py +# Package : rpmlint +# Author : Dirk Mueller +# Purpose : Check for common scaling errors in icons +############################################################################# + +from Filter import * +import AbstractCheck +import rpm +import re +import commands +import stat +import Config +import os +import string + +class IconSizesCheck(AbstractCheck.AbstractCheck): + def __init__(self): + AbstractCheck.AbstractCheck.__init__(self, "CheckIconSizes") + self.file_size_regex = re.compile('/icons/[^/]+/(\d+)x(\d+)/') + self.info_size_regex = re.compile('(\d+) x (\d+)') + + def check(self, pkg): + + if pkg.isSource(): + return + + for fname, pkgfile in pkg.files().items(): + res = self.file_size_regex.search(fname) + if res: + sizes = (res.group(1), res.group(2)) + res = self.info_size_regex.search(pkgfile.magic) + if res: + actualsizes = (res.group(1), res.group(2)) + + if abs(int(sizes[0])-int(actualsizes[0])) > 2 or \ + abs(int(sizes[1])-int(actualsizes[1])) > 2: + printError(pkg,"wrong-icon-size", fname, "expected:", + "x".join(sizes), "actual:", "x".join(actualsizes)) + + +check=IconSizesCheck() + +if Config.info: + addDetails( +'wrong-icon-size', +"""Your icon file is installed in a fixed-size directory, but has a largely incorrect size. +Some desktop environments (e.g. GNOME) display them incorrectly.""" +) diff --git a/rpmlint-checks-master/CheckInitScripts.py b/rpmlint-checks-master/CheckInitScripts.py new file mode 100644 index 0000000..9bd1bde --- /dev/null +++ b/rpmlint-checks-master/CheckInitScripts.py @@ -0,0 +1,114 @@ +# vim:sw=4:et +############################################################################# +# File : CheckInitScripts.py +# Package : rpmlint +# Author : Dirk Mueller +# Purpose : Check for common mistakes in init scripts +############################################################################# + +from Filter import * +import AbstractCheck +import rpm +import re +import commands +import stat +import Config +import os +import string + +insserv_regex=re.compile('^\s*sbin/insserv', re.MULTILINE) +preun_regex=re.compile('^\s*/etc/init.d/\S+ stop', re.MULTILINE) + +class CheckInitScripts(AbstractCheck.AbstractFilesCheck): + def __init__(self): + AbstractCheck.AbstractFilesCheck.__init__(self, "CheckInitScripts", "/etc/init.d/.*") + + def check(self, pkg): + + if pkg.isSource(): + return + + files = pkg.files() + bins_list = filter(lambda f: (f.startswith("/usr/bin") \ + or f.startswith("/usr/sbin")) and stat.S_ISREG(files[f].mode), files.keys()) + + for f, pkgfile in files.items(): + + if f in pkg.ghostFiles() or not stat.S_ISREG(pkgfile.mode) or not f.startswith("/etc/init.d/"): + continue + + boot_script = f.startswith('/etc/init.d/boot.') + + input_f = file(pkg.dirName() + '/' + f, "r") + found_remote_fs = False + for l in input_f: + if l.startswith('# Required-Start') or l.startswith('# Should-Start'): + for dep in l.split()[2:]: + if dep.startswith('$') and dep not in ('$local_fs', + '$named', + '$network', + '$portmap', + '$remote_fs', + '$syslog', + '$time', + '$null', + '$ALL'): + printError(pkg, "init-script-undefined-dependency", f, dep) + if dep in ('portmap', 'syslog', 'named', 'network', 'ntp', 'ntpd', 'xntpd'): + printWarning(pkg, "init-script-non-var-dependency", f, dep) + if dep in ('$remote_fs'): + found_remote_fs = True + if l.startswith('# X-UnitedLinux-Should'): + printWarning(pkg, "obsolete-init-keyword", f, l) + if l.startswith('# Default-Start'): + for dep in l.split()[2:]: + if boot_script and dep not in ('B', 'S'): + printError(pkg, "init-script-boot_d", f) + if not boot_script and dep in ('B'): + printError(pkg, "init-script-not-boot_d", f, dep) + if dep == '4': + printError(pkg, "init-script-runlevel-4", f) + + if not found_remote_fs and bins_list: + printWarning(pkg, "non-remote_fs-dependency", f) + + +check=CheckInitScripts() + +if Config.info: + addDetails( +'init-script-undefined-dependency', +"""Your package contains a /etc/init.d script that specifies a +dependency that is not listed in /etc/insserv.conf. Check for +typos.""", + +'init-script-non-var-dependency', +"""Your package contains a /etc/init.d script that specifies +a hardcoded dependency that likely should be a variable dependency. +For example portmap should actually be $portmap, and similar.""", +'obsolete-init-keyword', + +"""Your package contains a /etc/init.d script that specifies +an obsolete keyword, like X-UnitedLinux-Should-Start. Consider +using the LSB equivalent Should-Start instead.""", + +'init-script-boot_d', +"""The init script has a "boot." prefix but actually lacks 'B' in +'Default-Start'. Either rename the script or add +'B' to 'Default-Start'""", + +'init-script-not-boot_d', +"""The init script specifies that it should be run in level 'B' but +doesn't have a "boot." prefix. Either rename the script or remove +the 'B' from 'Default-Start'""", + +'non-remote_fs-dependency', +"""Your package contains a /etc/init.d script that does not specify +$remote_fs as a start dependency, but the package also contains +files packaged in /usr. Make sure that your start script does not +call any of them, or add the missing $remote_fs dependency.""", + +'init-script-runlevel-4', +"""The init script refers to runlevel 4 which is admin defined. No +distribution script must use it. Remove '4' from 'Default-Start'.""", +) diff --git a/rpmlint-checks-master/CheckKDE4Deps.py b/rpmlint-checks-master/CheckKDE4Deps.py new file mode 100644 index 0000000..c150c8b --- /dev/null +++ b/rpmlint-checks-master/CheckKDE4Deps.py @@ -0,0 +1,119 @@ +# vim:sw=4:et +############################################################################# +# File : CheckKDE4Deps.py +# Package : rpmlint +# Author : Dirk Mueller +# Purpose : Check for KDE4 related packaging errors +############################################################################# + +from Filter import * +import AbstractCheck +import rpm +import re +import os +import string +import commands +import Config +import Pkg +import stat + +_kde4_pimlibs=( + "libgpgme++-pth.so.1.1.0", + "libgpgme++-pthread.so.1.1.0", + "libgpgme++.so.1.1.0", + "libkabc.so.4", + "libkabc_file_core.so.4", + "libkblog.so.4", + "libkcal.so.4", + "libkimap.so.4", + "libkldap.so.4", + "libkmime.so.4", + "libkpimidentities.so.4", + "libkpimutils.so.4", + "libkresources.so.4", + "libktnef.so.4", + "libkxmlrpcclient.so.4", + "libmailtransport.so.4", + "libqgpgme.so.1.0.0", + "libsyndication.so.4" +) + +_kde4_libkdepim4 = ( + "libkdepim.so.4", + "libkontactinterfaces.so.4", + "libkleopatraclientcore.so.0.2.0", + "libkleopatraclientgui.so.0.2.0", +) + +_kde4_libakonadi4 = ( + "libakonadi-kde.so.4", + "libakonadi-kabc.so.4", + "libakonadi-kcal.so.4", + "libakonadi-kmime.so.4", + "libakonadiprotocolinternals.so.1", +) + +class KDE4Check(AbstractCheck.AbstractCheck): + def __init__(self): + AbstractCheck.AbstractCheck.__init__(self, "CheckKDE4Deps") + + def check(self, pkg): + + if pkg.isSource(): + return + + pkg_requires = set(map(lambda x: string.split(x[0],'(')[0], pkg.requires())) + + if not "libkdecore.so.5" in pkg_requires: + return + + if not pkg.name.startswith("lib"): + if not "kdebase4-runtime" in pkg_requires: + printError(pkg,"suse-kde4-missing-runtime-dependency") + + kdepimlibs4_dep=False + for r in pkg_requires: + if r in _kde4_pimlibs: + kdepimlibs4_dep=True + break + + libkdepim4_dep=False + for r in pkg_requires: + if r in _kde4_libkdepim4: + libkdepim4_dep =True + break + + libakonadi4_dep=False + for r in pkg_requires: + if r in _kde4_libakonadi4: + libakonadi4_dep =True + break + + if not pkg.name.startswith("lib"): + if "kdepimlibs4" in pkg_requires and not kdepimlibs4_dep: + printError(pkg,"suse-kde4-excessive-dependency", "%kde4_pimlibs_requires") + if not "kdepimlibs4" in pkg_requires and kdepimlibs4_dep: + printError(pkg,"suse-kde4-missing-dependency", "%kde4_pimlibs_requires") + + if "libkdepim4" in pkg_requires and not libkdepim4_dep: + printError(pkg,"suse-kde4-excessive-dependency", "libkdepim4") + if not "libkdepim4" in pkg_requires and libkdepim4_dep: + printError(pkg,"suse-kde4-missing-dependency", "libkdepim4") + + if "akonadi-runtime" in pkg_requires and not libakonadi4_dep: + printError(pkg,"suse-kde4-excessive-dependency", "%kde4_akonadi_requires") + if not "akonadi-runtime" in pkg_requires and libakonadi4_dep: + printError(pkg,"suse-kde4-missing-dependency", "%kde4_akonadi_requires") + + +check=KDE4Check() + +if Config.info: + addDetails('suse-kde4-missing-runtime-dependency', +"""Please add %kde4_runtime_requires to the (sub-)package to have the right versioned +dependency on the KDE version it was built against.""", +'suse-kde4-missing-dependency', +"""The package builds against a KDE4 related library, but it is missing the runtime +depencency macro. please add the suggested macro to the (sub-)package listing in +the spec file.""" +) diff --git a/rpmlint-checks-master/CheckLogrotate.py b/rpmlint-checks-master/CheckLogrotate.py new file mode 100644 index 0000000..7a5ac4d --- /dev/null +++ b/rpmlint-checks-master/CheckLogrotate.py @@ -0,0 +1,97 @@ +# vim:sw=4:et +############################################################################# +# File : CheckLogrotate.py +# Package : rpmlint +# Author : Ludwig Nussel +# Purpose : Check for insecure logrotate directories +############################################################################# + +from Filter import * +import AbstractCheck +import re +import os +import string + +class LogrotateCheck(AbstractCheck.AbstractCheck): + def __init__(self): + AbstractCheck.AbstractCheck.__init__(self, "CheckLogrotate") + + def check(self, pkg): + if pkg.isSource(): + return + + files = pkg.files() + dirs = {} + + for f, pkgfile in files.items(): + if f in pkg.ghostFiles(): + continue + + if f.startswith("/etc/logrotate.d/"): + try: + for n, o in self.parselogrotateconf(pkg.dirName(), f).items(): + if n in dirs and dirs[n] != o: + printError(pkg, "logrotate-duplicate", n) + else: + dirs[n] = o + except Exception, x: + printError(pkg, 'rpmlint-exception', "%(file)s raised an exception: %(x)s" % {'file':f, 'x':x}) + + for d in sorted(dirs.keys()): + if not d in files: + if d != '/var/log': + printError(pkg, 'suse-logrotate-log-dir-not-packaged', d) + continue + mode = files[d].mode&0777 + if files[d].user != 'root' and (dirs[d] is None or dirs[d][0] != files[d].user): + printError(pkg, 'suse-logrotate-user-writable-log-dir', \ + "%s %s:%s %04o"%(d, files[d].user, files[d].group, mode)) + elif files[d].group != 'root' and mode&020 and (dirs[d] is None or dirs[d][1] != files[d].group): + printError(pkg, 'suse-logrotate-user-writable-log-dir', \ + "%s %s:%s %04o"%(d, files[d].user, files[d].group, mode)) + + # extremely primitive logrotate parser + def parselogrotateconf(self, root, f): + dirs = {} + fd = open('/'.join((root, f))) + currentdirs = [] + for line in fd.readlines(): + line = line.strip() + if line.startswith('#'): + continue + if not currentdirs: + if line.endswith('{'): + insection = True + for logfile in line.split(' '): + logfile = logfile.strip() + if len(logfile) == 0 or logfile == '{': + continue + dn = os.path.dirname(logfile) + if not dn in dirs: + currentdirs.append(dn) + dirs[dn] = None + else: + if line.endswith('}'): + currentdirs = [] + elif line.startswith("su "): + a = line.split(" ") + for dn in currentdirs: + dirs[dn] = (a[1], a[2]) + return dirs + + +check=LogrotateCheck() + +if Config.info: + addDetails( +'suse-logrotate-duplicate', +"""There are dupliated logrotate entries with different settings for +the specified file""", +'suse-logrotate-user-writable-log-dir', +"""The log directory is writable by unprivileged users. Please fix +the permissions so only root can write there or add the 'su' option +to your logrotate config""", +'suse-logrotate-log-dir-not-packaged', +"""Please add the specified directory to the file list to be able to +check permissions""" +) diff --git a/rpmlint-checks-master/CheckPAMModules.py b/rpmlint-checks-master/CheckPAMModules.py new file mode 100644 index 0000000..af54bbc --- /dev/null +++ b/rpmlint-checks-master/CheckPAMModules.py @@ -0,0 +1,49 @@ +# vim:sw=4:et +############################################################################# +# File : CheckPAMModules.py +# Package : rpmlint +# Author : Ludwig Nussel +# Purpose : Check for pam modules that are not authorized by the security team +############################################################################# + +from Filter import * +import AbstractCheck +import re +import os +import string + +PAM_WHITELIST = Config.getOption('PAMModules.WhiteList', ()) # set of file names + +pam_module_re = re.compile('^(?:/usr)?/lib(?:64)?/security/([^/]+\.so)$') + +class PAMModulesCheck(AbstractCheck.AbstractCheck): + def __init__(self): + AbstractCheck.AbstractCheck.__init__(self, "CheckPAMModules") + + def check(self, pkg): + global PAM_WHITELIST + + if pkg.isSource(): + return + + files = pkg.files() + + for f in files: + if f in pkg.ghostFiles(): + continue + + m = pam_module_re.match(f) + if m: + bn = m.groups()[0] + if not bn in PAM_WHITELIST: + printError(pkg, "suse-pam-unauthorized-module", bn) + +check=PAMModulesCheck() + +if Config.info: + addDetails( +'suse-pam-unauthorized-module', +"""The package installs a PAM module. If the package +is intended for inclusion in any SUSE product please open a bug +report to request review of the service by the security team.""", +) diff --git a/rpmlint-checks-master/CheckPkgConfig.py b/rpmlint-checks-master/CheckPkgConfig.py new file mode 100644 index 0000000..f2cf40a --- /dev/null +++ b/rpmlint-checks-master/CheckPkgConfig.py @@ -0,0 +1,63 @@ +# vim:sw=4:et +#--------------------------------------------------------------- +# Module : rpmlint +# File : CheckPkgConfig +# Author : Stephan Kulow, Dirk Mueller +# Purpose : Check for errors in Pkgconfig files +#--------------------------------------------------------------- + +from Filter import * +import AbstractCheck +import rpm +import re +import commands +import Config +import os +import stat + +class PkgConfigCheck(AbstractCheck.AbstractFilesCheck): + def __init__(self): + AbstractCheck.AbstractFilesCheck.__init__(self, "CheckPkgConfig", ".*/pkgconfig/.*\.pc$") + # currently causes too many failures (2008-03-05) + #self.suspicious_dir=re.compile('(?:/usr/src/\w+/BUILD|/var/tmp|/tmp|/home|\@\w{1,50}\@)') + self.suspicious_dir=re.compile('(?:/usr/src/\w+/BUILD|/var/tmp|/tmp|/home)') + + def check(self, pkg): + # check for references to /lib when in lib64 mode + if pkg.arch in ('x86_64', 'ppc64', 's390x'): + self.wronglib_dir=re.compile('-L/usr/lib\\b') + else: + self.wronglib_dir=re.compile('-L/usr/lib64\\b') + + AbstractCheck.AbstractFilesCheck.check(self, pkg) + + + def check_file(self, pkg, filename): + if pkg.isSource() or not stat.S_ISREG(pkg.files()[filename].mode): + return + + if pkg.grep(self.suspicious_dir, filename): + printError(pkg, "invalid-pkgconfig-file", filename) + + pc_file=file(pkg.dirName() + "/" + filename, "r") + for l in pc_file: + if l.startswith('Libs:') and self.wronglib_dir.search(l): + printError(pkg, 'pkgconfig-invalid-libs-dir', filename, l) + +check=PkgConfigCheck() + +if Config.info: + addDetails( +'invalid-pkgconfig-file', +'''Your .pc file appears to be invalid. Possible causes are: +- it contains traces of $RPM_BUILD_ROOT or $RPM_BUILD_DIR. +- it contains unreplaced macros (@have_foo@) +- it references invalid paths (e.g. /home or /tmp) + +Please double-check and report false positives. +''', +'pkgconfig-invalid-libs-dir', +''' Your .pc file contains -L/usr/lib or -L/lib and is built for a lib64 target, +or contains references to -L/usr/lib64 or -L/lib64 and is built for a lib target. +Please remove the wrong library paths from the pc file.''' +) diff --git a/rpmlint-checks-master/CheckPolkitPrivs.py b/rpmlint-checks-master/CheckPolkitPrivs.py new file mode 100644 index 0000000..31409e5 --- /dev/null +++ b/rpmlint-checks-master/CheckPolkitPrivs.py @@ -0,0 +1,153 @@ +# vim:sw=4:et +############################################################################# +# File : CheckPolkitPrivs.py +# Package : rpmlint +# Author : Ludwig Nussel +# Purpose : Check for /etc/polkit-default-privs violations +############################################################################# + +from Filter import * +import AbstractCheck +import Config +import re +import os +from xml.dom.minidom import parse + +POLKIT_PRIVS_WHITELIST = Config.getOption('PolkitPrivsWhiteList', ()) # set of file names +POLKIT_PRIVS_FILES = Config.getOption('PolkitPrivsFiles', [ "/etc/polkit-default-privs.standard" ]) + +class PolkitCheck(AbstractCheck.AbstractCheck): + def __init__(self): + AbstractCheck.AbstractCheck.__init__(self, "CheckPolkitPrivs") + self.privs = {} + + for filename in POLKIT_PRIVS_FILES: + if os.path.exists(filename): + self._parsefile(filename) + + def _parsefile(self,filename): + for line in file(filename): + line = line.split('#')[0].split('\n')[0] + if len(line): + line = re.split(r'\s+', line) + priv = line[0] + value = line[1] + + self.privs[priv] = value + + def check(self, pkg): + + if pkg.isSource(): + return + + files = pkg.files() + + permfiles = {} + # first pass, find additional files + for f in files: + if f in pkg.ghostFiles(): + continue + + if f.startswith("/etc/polkit-default-privs.d/"): + + bn = f[28:] + if not bn in POLKIT_PRIVS_WHITELIST: + printError(pkg, "polkit-unauthorized-file", f) + + if bn.endswith(".restrictive") or bn.endswith(".standard") or bn.endswith(".relaxed"): + bn = bn.split('.')[0] + + if not bn in permfiles: + permfiles[bn] = 1 + + for f in permfiles: + f = pkg.dirName() + "/etc/polkit-default-privs.d/" + f + + if os.path.exists(f+".restrictive"): + self._parsefile(f + ".restrictive") + elif os.path.exists(f+".standard"): + self._parsefile(f + ".standard") + elif os.path.exists(f+".relaxed"): + self._parsefile(f + ".relaxed") + else: + self._parsefile(f) + + + for f in files: + if f in pkg.ghostFiles(): + continue + + # catch xml exceptions + try: + if f.startswith("/usr/share/PolicyKit/policy/")\ + or f.startswith("/usr/share/polkit-1/actions/"): + xml = parse(pkg.dirName() + f) + for a in xml.getElementsByTagName("action"): + action = a.getAttribute('id') + if not action in self.privs: + iserr = 0 + foundno = 0 + foundundef = 0 + settings = {} + try: + defaults = a.getElementsByTagName("defaults")[0] + for i in defaults.childNodes: + if not i.nodeType == i.ELEMENT_NODE: + continue + + if i.nodeName in ('allow_any', 'allow_inactive', 'allow_active'): + settings[i.nodeName] = i.firstChild.data + + except: + iserr = 1 + + for i in ('allow_any', 'allow_inactive', 'allow_active'): + if not i in settings: + foundundef = 1 + settings[i] = '??' + elif settings[i].find("auth_admin") != 0: + if settings[i] == 'no': + foundno = 1 + else: + iserr = 1 + + if iserr: + printError(pkg, 'polkit-unauthorized-privilege', '%s (%s:%s:%s)' % (action, \ + settings['allow_any'], settings['allow_inactive'], settings['allow_active'])) + else: + printInfo(pkg, 'polkit-untracked-privilege', '%s (%s:%s:%s)' % (action, \ + settings['allow_any'], settings['allow_inactive'], settings['allow_active'])) + + if foundno or foundundef: + printInfo(pkg, + 'polkit-cant-acquire-privilege', '%s (%s:%s:%s)' % (action, \ + settings['allow_any'], settings['allow_inactive'], settings['allow_active'])) + + except Exception, x: + printError(pkg, 'rpmlint-exception', "%(file)s raised an exception: %(x)s" % {'file':f, 'x':x}) + continue + +check=PolkitCheck() + +if Config.info: + addDetails( +'polkit-unauthorized-file', +"""If the package is intended for inclusion in any SUSE product +please open a bug report to request review of the package by the +security team""", +'polkit-unauthorized-privilege', +"""The package allows unprivileged users to carry out privileged +operations without authentication. This could cause security +problems if not done carefully. If the package is intended for +inclusion in any SUSE product please open a bug report to request +review of the package by the security team""", +'polkit-untracked-privilege', +"""The privilege is not listed in /etc/polkit-default-privs.* +which makes it harder for admins to find. If the package is intended +for inclusion in any SUSE product please open a bug report to +request review of the package by the security team""", +'polkit-cant-acquire-privilege', +"""Usability can be improved by allowing users to acquire privileges +via authentication. Use e.g. 'auth_admin' instead of 'no' and make +sure to define 'allow_any'. This is an issue only if the privilege +is not listed in /etc/polkit-default-privs.*""") diff --git a/rpmlint-checks-master/CheckSUIDPermissions.py b/rpmlint-checks-master/CheckSUIDPermissions.py new file mode 100644 index 0000000..b05d2ed --- /dev/null +++ b/rpmlint-checks-master/CheckSUIDPermissions.py @@ -0,0 +1,271 @@ +# vim:sw=4:et +############################################################################# +# File : CheckSUIDPermissions.py +# Package : rpmlint +# Author : Ludwig Nussel +# Purpose : Check for /etc/permissions violations +############################################################################# + +from Filter import * +import AbstractCheck +import re +import os +import string +import rpm + +_permissions_d_whitelist = ( +"lprng", +"lprng.paranoid", +"mail-server", +"mail-server.paranoid", +"postfix", +"postfix.paranoid", +"sendmail", +"sendmail.paranoid", +"squid", +"texlive", +"texlive.texlive", +) + +class SUIDCheck(AbstractCheck.AbstractCheck): + def __init__(self): + AbstractCheck.AbstractCheck.__init__(self, "CheckSUIDPermissions") + self.perms = {} + files = [ "/etc/permissions", "/etc/permissions.secure" ] + + for file in files: + if os.path.exists(file): + self._parsefile(file) + + def _parsefile(self,file): + lnr = 0 + lastfn = None + for line in open(file): + lnr+=1 + line = line.split('#')[0].split('\n')[0] + line = line.lstrip() + if not len(line): + continue + + if line.startswith("+capabilities "): + line = line[len("+capabilities "):] + if lastfn: + self.perms[lastfn]['fscaps'] = line + continue + + line = re.split(r'\s+', line) + if len(line) == 3: + fn = line[0] + owner = line[1].replace('.', ':') + mode = line[2] + + self.perms[fn] = { "owner" : owner, "mode" : int(mode,8)&07777} + # for permissions that don't change and therefore + # don't need special handling + if file == '/etc/permissions': + self.perms[fn]['static'] = True + else: + print >>sys.stderr, "invalid line %d " % lnr + + def check(self, pkg): + global _permissions_d_whitelist + + if pkg.isSource(): + return + + files = pkg.files() + + permfiles = {} + # first pass, find and parse permissions.d files + for f in files.keys(): + if f in pkg.ghostFiles(): + continue + + if f.startswith("/etc/permissions.d/"): + + bn = f[19:] + if not bn in _permissions_d_whitelist: + printError(pkg, "permissions-unauthorized-file", f) + + bn = bn.split('.')[0] + if not bn in permfiles: + permfiles[bn] = 1 + + for f in permfiles: + f = pkg.dirName() + "/etc/permissions.d/" + f + if os.path.exists(f+".secure"): + self._parsefile(f + ".secure") + else: + self._parsefile(f) + + need_set_permissions = False + found_suseconfig = False + # second pass, find permissions violations + for f, pkgfile in files.items(): + + if pkgfile.filecaps: + printError(pkg, 'permissions-fscaps', '%(file)s has fscaps "%(caps)s"' % \ + { 'file':f, 'caps':pkgfile.filecaps}) + + mode = pkgfile.mode + owner = pkgfile.user+':'+pkgfile.group + +# S_IFSOCK 014 socket +# S_IFLNK 012 symbolic link +# S_IFREG 010 regular file +# S_IFBLK 006 block device +# S_IFDIR 004 directory +# S_IFCHR 002 character device +# S_IFIFO 001 FIFO + type = (mode>>12)&017; + mode &= 07777 + need_verifyscript = False + if f in self.perms or (type == 04 and f+"/" in self.perms): + if type == 012: + printWarning(pkg, "permissions-symlink", f) + continue + + need_verifyscript = True + + m = 0 + o = "invalid" + if type == 04: + if f in self.perms: + printWarning(pkg, 'permissions-dir-without-slash', f) + else: + f += '/' + + if type == 010 and mode&0111: + # pie binaries have 'shared object' here + if 'ELF' in pkgfile.magic and not 'shared object' in pkgfile.magic: + printError(pkg, 'non-position-independent-executable', f) + + m = self.perms[f]['mode'] + o = self.perms[f]['owner'] + + if mode != m: + printError(pkg, 'permissions-incorrect', '%(file)s has mode 0%(mode)o but should be 0%(m)o' % \ + { 'file':f, 'mode':mode, 'm':m }) + + if owner != o: + printError(pkg, 'permissions-incorrect-owner', '%(file)s belongs to %(owner)s but should be %(o)s' % \ + { 'file':f, 'owner':owner, 'o':o }) + + elif type != 012: + + if f+'/' in self.perms: + printWarning(pkg, 'permissions-file-as-dir', f+' is a file but listed as directory') + + if mode&06000: + need_verifyscript = True + msg = '%(file)s is packaged with setuid/setgid bits (0%(mode)o)' % { 'file':f, 'mode':mode } + if type != 04: + printError(pkg, 'permissions-file-setuid-bit', msg) + else: + printWarning(pkg, 'permissions-directory-setuid-bit', msg) + + if type == 010: + if not 'shared object' in pkgfile.magic: + printError(pkg, 'non-position-independent-executable', f) + + if mode&02: + need_verifyscript = True + printError(pkg, 'permissions-world-writable', \ + '%(file)s is packaged with world writable permissions (0%(mode)o)' % \ + { 'file':f, 'mode':mode }) + + script = pkg[rpm.RPMTAG_POSTIN] or pkg.scriptprog(pkg[rpm.RPMTAG_POSTINPROG]) + found = False + if script: + for line in script.split("\n"): + if "chkstat -n" in line and f in line: + found = True + break + + if "SuSEconfig --module permissions" in line: + found = True + found_suseconfig = True + break + + if need_verifyscript and \ + (not f in self.perms or not 'static' in self.perms[f]): + + if not script or not found: + printError(pkg, 'permissions-missing-postin', \ + "missing %%set_permissions %s in %%post" % f) + + need_set_permissions = True + script = pkg[rpm.RPMTAG_VERIFYSCRIPT] or pkg[rpm.RPMTAG_VERIFYSCRIPTPROG] + + found = False + if script: + for line in script.split("\n"): + if "/chkstat" in line and f in line: + found = True + break + + if not script or not found: + printWarning(pkg, 'permissions-missing-verifyscript', \ + "missing %%verify_permissions -e %s" % f) + + + if need_set_permissions: + if not 'permissions' in map(lambda x: x[0], pkg.prereq()): + printError(pkg, 'permissions-missing-requires', \ + "missing 'permissions' in PreReq") + + if found_suseconfig: + printInfo(pkg, 'permissions-suseconfig-obsolete', \ + "%run_permissions is obsolete") + +check=SUIDCheck() + +if Config.info: + addDetails( +'permissions-unauthorized-file', +"""If the package is intended for inclusion in any SUSE product +please open a bug report to request review of the package by the +security team""", +'permissions-symlink', +"""permissions handling for symlinks is useless. Please contact +security@suse.de to remove the entry.""", +'permissions-dir-without-slash', +"""the entry in the permissions file refers to a directory. Please +contact security@suse.de to append a slash to the entry in order to +avoid security problems.""", +'permissions-file-as-dir', +"""the entry in the permissions file refers to a directory but the +package actually contains a file. Please contact security@suse.de to +remove the slash.""", +'permissions-incorrect', +"""please use the %attr macro to set the correct permissions.""", +'permissions-incorrect-owner', +"""please use the %attr macro to set the correct ownership.""", +'permissions-file-setuid-bit', +"""If the package is intended for inclusion in any SUSE product +please open a bug report to request review of the program by the +security team""", +'permissions-directory-setuid-bit', +"""If the package is intended for inclusion in any SUSE product +please open a bug report to request review of the package by the +security team""", +'permissions-world-writable', +"""If the package is intended for inclusion in any SUSE product +please open a bug report to request review of the package by the +security team""", +'permissions-fscaps', +"""Packaging file capabilities is currently not supported. Please +use normal permissions instead. You may contact the security team to +request an entry that sets capabilities in /etc/permissions +instead.""", +'permissions-missing-postin', +"""Please add an appropriate %post section""", +'permissions-missing-requires', +"""Please add \"PreReq: permissions\"""", +'permissions-missing-verifyscript', +"""Please add a %verifyscript section""", +'permissions-suseconfig-obsolete', +"""The %run_permissions macro calls SuSEconfig which sets permissions for all +files in the system. Please use %set_permissions <filename> instead +to only set permissions for files contained in this package""", +) diff --git a/rpmlint-checks-master/DuplicatesCheck.py b/rpmlint-checks-master/DuplicatesCheck.py new file mode 100644 index 0000000..764dec5 --- /dev/null +++ b/rpmlint-checks-master/DuplicatesCheck.py @@ -0,0 +1,100 @@ +# vim:sw=4:et +############################################################################# +# File : DuplicatesCheck.py +# Package : rpmlint +# Author : Stephan Kulow +# Purpose : Check for duplicate files being packaged separately +############################################################################# + +from Filter import * +import AbstractCheck +import rpm +import re +import commands +import stat +import Config +import os +import string + +def get_prefix(file): + pathlist = string.split(file, '/') + if len(pathlist) == 3: + return "/".join(pathlist[0:2]) + + return "/".join(pathlist[0:3]) + +class DuplicatesCheck(AbstractCheck.AbstractCheck): + def __init__(self): + self.map = [] + AbstractCheck.AbstractCheck.__init__(self, "DuplicatesCheck") + + def check(self, pkg): + + if pkg.isSource(): + return + + md5s = {} + sizes = {} + files = pkg.files() + configFiles = pkg.configFiles() + + for f, pkgfile in files.items(): + if f in pkg.ghostFiles(): + continue + + if not stat.S_ISREG(pkgfile.mode): + continue + + md5s.setdefault(pkgfile.md5, set()).add(f) + sizes[pkgfile.md5] = pkgfile.size + + sum=0 + for f in md5s: + duplicates=md5s[f] + if len(duplicates) == 1: continue + + one=duplicates.pop() + one_is_config = False + if one in configFiles: + one_is_config = True + + partition=get_prefix(one) + + st = os.stat(pkg.dirName() + '/' + one) + diff = 1 + len(duplicates) - st[stat.ST_NLINK] + if diff <= 0: + for dupe in duplicates: + if partition != get_prefix(dupe): + printError(pkg,"hardlink-across-partition",one,dupe) + if one_is_config and dupe in configFiles: + printError(pkg,"hardlink-across-config-files",one,dupe) + continue + + for dupe in duplicates: + if partition != get_prefix(dupe): + diff = diff - 1 + sum += sizes[f] * diff + if sizes[f] and diff > 0: + printWarning(pkg, 'files-duplicate', one,":".join(duplicates)) + + if sum > 100000: + printError(pkg, 'files-duplicated-waste', sum) + +check=DuplicatesCheck() + +if Config.info: + addDetails( +'files-duplicated-waste', +"""Your package contains duplicated files that are not hard- or symlinks. +You should use the %fdupes macro to link the files to one.""", +'hardlink-across-partition', +"""Your package contains two files that are apparently hardlinked and +that are likely on different partitions. Installation of such an RPM will fail +due to RPM being unable to unpack the hardlink. do not hardlink across +the first two levels of a path, e.g. between /srv/ftp and /srv/www or +/etc and /usr. """, +'hardlink-across-config-files', +"""Your package contains two config files that are apparently hardlinked. +Hardlinking a config file is probably not what you want. Please double +check and report false positives.""" +) diff --git a/rpmlint-checks-master/KMPPolicyCheck.py b/rpmlint-checks-master/KMPPolicyCheck.py new file mode 100644 index 0000000..ce20f5d --- /dev/null +++ b/rpmlint-checks-master/KMPPolicyCheck.py @@ -0,0 +1,90 @@ +# vim:sw=4:et +############################################################################# +# File : KMPPolicyCheck.py +# Package : rpmlint +# Author : Dirk Mueller +# Purpose : Verify that kmp's have proper dependencies +############################################################################# + +from Filter import * +import AbstractCheck +import rpm +import re +import commands +import stat +import Config +import os +import string +import Pkg + +class KMPPolicyCheck(AbstractCheck.AbstractCheck): + def __init__(self): + self.map = [] + AbstractCheck.AbstractCheck.__init__(self, "KMPPolicyCheck") + + def check(self, pkg): + if pkg.isSource() or pkg.name.find('-kmp-') < 0: + return + + pkg_requires = set(map(lambda x: string.split(x[0],'(')[0], pkg.requires())) + pkg_conflicts = set(map(lambda x: string.split(x[0],'(')[0], pkg.conflicts())) + + kernel_flavour="kernel-" + pkg.name.partition('-kmp-')[2] + + # verify that Requires: kernel_flavour is present + have_requires=False + for r in pkg_requires: + if r == kernel_flavour: + have_requires = True + break + + if not have_requires: + printError(pkg, 'suse-policy-kmp-missing-requires', kernel_flavour) + + # verify that exactly one enhances on the kernel flavor is present + if len(pkg.enhances()) > 1: + printError(pkg, 'suse-policy-kmp-excessive-enhances', str(pkg.enhances())) + elif len(pkg.enhances()) < 1: + printError(pkg, 'suse-policy-kmp-missing-enhances', kernel_flavour) + + # check that only modalias supplements are present + have_only_modalias=True + have_modalias=False + have_proper_suppl=False + for s in pkg.supplements(): + if s[0].startswith('modalias('): + have_modalias = True + continue + if s[0].startswith('packageand(%s:' % (kernel_flavour)): + have_proper_suppl = True + continue + + printWarning(pkg, 'suse-policy-kmp-excessive-supplements', s[0]) + have_only_modalias = False + + if not have_modalias and not have_proper_suppl: + printError(pkg, 'suse-policy-kmp-missing-supplements') + +check=KMPPolicyCheck() + +if Config.info: + addDetails( +'suse-policy-kmp-missing-requires', +"""Make sure you have extended '%suse_kernel_module_package' by + '-p %_sourcedir/preamble', a file named 'preamble' as source and there + specified 'Requires: kernel-%1'. + """, +'suse-policy-kmp-excessive-enhances', +""" """, +'suse-policy-kmp-missing-enhances', +"""Make sure you have extended '%suse_kernel_module_package' by + '-p %_sourcedir/preamble', a file named 'preamble' as source and there + specified 'Enhances: kernel-%1'. + """, +'suse-policy-kmp-excessive-supplements', +""" """, +'suse-policy-kmp-missing-supplements', +"""Make sure your 'BuildRequires:' include 'kernel-syms' and 'module-init-tools' +for proper dependencies to be built. +""", +) diff --git a/rpmlint-checks-master/LibraryPolicyCheck.py b/rpmlint-checks-master/LibraryPolicyCheck.py new file mode 100644 index 0000000..5d1b4f1 --- /dev/null +++ b/rpmlint-checks-master/LibraryPolicyCheck.py @@ -0,0 +1,477 @@ +# vim:sw=4:et +############################################################################# +# File : LibraryPolicyCheck.py +# Package : rpmlint +# Author : Richard Guenther +# Purpose : Verify shared library packaging policy rules +############################################################################# + +from Filter import * +import AbstractCheck +import rpm +import re +import commands +import stat +import Config +import os +import string +import Pkg + +_policy_legacy_exceptions = ( + "libacl1", + "libaio1", + "libalut0", + "libapr-1-0", + "libaprutil-1-0", + "libartskde1", + "libattr1", + "libcdaudio1", + "libcdk4", + "libcheck0", + "libchewing3", + "libchm0", + "libclucene0", + "libdar4", + "libdbh-4_5-4", + "libdbus-qt-1-1", + "libdm0", + "libdns_sd1", + "libefence0", + "libEMF1", + "libevolutionglue", + "libf2c0", + "libffi4", + "libflaim5_2", + "libfontenc1", + "libfreeradius-client2", + "libgcc_s1", + "libgcc_s4", # only for hppa + "libgconfmm-2_6-1", + "libgfortran3", + "libgif4", + "libgimpprint1", + "libgladesharpglue-2", + "libglibsharpglue-2", + "libgltt0", + "libglut3", + "libGLw1", + "libgmcop1", + "libgnet-2_0-0", + "libgnomecanvasmm-2_6-1", + "libgnomecups-1_0-1", + "libgnomemm-2_6-1", + "libgnomeprintui-2-2-0", + "libgnomesharpglue-2", + "libgnomeuimm-2_6-1", + "libgomp1", + "libgsfglue", + "libgsf-gnome-1-114", + "libgtksourceview-1_0-0", + "libgtkspell0", + "libhangul0", + "libICE6", + "libid3-3_8-3", + "libid3tag0", + "libidn11", + "libiec61883-0", + "libieee1284-3", + "libilbc0", + "libind_helper0", + "libiterm1", + "libjackasyn0", + "libkakasi2", + "libkeyutils1", + "libksba8", + "liblo0", + "libmal0", + "libmcrypt4", + "libmdbodbc0", + "libmeanwhile1", + "libmhash2", + "libmikmod2", + "libmng1", + "libnet6-1_3-0", + "libnl1", + "libnscd1", + "libobjc3", + "libodbcinstQ1", + "liboil-0_3-0", + "liboop4", + "libopenal0", + "libopenal1", + "libpgeasy3", + "libportaudio2", + "libqnotify0", + "libQt3Support4", + "libqtc1", + "libqtsharp0", + "libQtSql4", + "libquadmath0", + "librdf0", + "librsync1", + "libsamplerate0", + "libsecprog0", + "libsexy2", + "libsigc-1_2-5", + "libSM6", + "libsndfile1", + "libstdc++6", + "libstroke0", + "libthai0", + "libutempter0", + "libvisual-0_4-0", + "libXau6", + "libxclass0_9_2", + "libXdmcp6", + "libXext6", + "libxfce4util4", + "libxfcegui4-4", + "libXfixes3", + "libxflaim3_2", + "libXiterm1", + "libxkbfile1", + "libxml2-2", + "libXp6", + "libXprintUtil1", + "libXrender1", + "libXt6", + "libXv1", + "libz1", + "libzio0" +) + +_essential_dependencies = ( + "ld-linux.so.2", + "libacl.so.1", + "libanl.so.1", + "libanonymous.so.2", + "libattr.so.1", + "libaudit.so.0", + "libauparse.so.0", + "libBrokenLocale.so.1", + "libbz2.so.1", + "libcidn.so.1", + "libck-connector.so.0", + "libcom_err.so.2", + "libcrack.so.2", + "libcrypto.so.0.9.8", + "libcrypt.so.1", + "libc.so.6", + "libdbus-1.so.3", + "libdbus-glib-1.so.2", + "libdes425.so.3", + "libdl.so.2", + "libexpat.so.1", + "libform.so.5", + "libformw.so.5", + "libgcc_s.so.1", + "libgcrypt.so.11", + "libgdbm_compat.so.3", + "libgdbm.so.3", + "libgfortran3", + "libgio-2.0.so.0", + "libglib-2.0.so.0", + "libgmodule-2.0.so.0", + "libgobject-2.0.so.0", + "libgpg-error.so.0", + "libgssapi_krb5.so.2", + "libgssrpc.so.4", + "libgthread-2.0.so.0", + "libhal.so.1", + "libhal-storage.so.1", + "libhd.so.14", + "libhistory.so.5", + "libk5crypto.so.3", + "libkadm5clnt.so.5", + "libkadm5srv.so.5", + "libkdb5.so.4", + "libkeyutils.so.1", + "libkrb4.so.2", + "libkrb5.so.3", + "libkrb5support.so.0", + "libksba.so.8", + "liblber-2.4.so.2", + "libldap-2.4.so.2", + "libldap_r-2.4.so.2", + "liblogin.so.2", + "liblog_syslog.so.1", + "libltdl.so.3", + "libmagic.so.1", + "libmenu.so.5", + "libmenuw.so.5", + "libm.so.6", + "libncurses.so.5", + "libncursesw.so.5", + "libnscd.so.1", + "libnsl.so.1", + "libnss_compat.so.2", + "libnss_dns.so.2", + "libnss_files.so.2", + "libnss_hesiod.so.2", + "libnss_nisplus.so.2", + "libnss_nis.so.2", + "libopenct.so.1", + "libopensc.so.2", + "libpamc.so.0", + "libpam_misc.so.0", + "libpam.so.0", + "libpanel.so.5", + "libpanelw.so.5", + "libparted-1.8.so.8", + "libpcrecpp.so.0", + "libpcreposix.so.0", + "libpcre.so.0", + "libpcsclite.so.1", + "libpkcs15init.so.2", + "libpolkit-dbus.so.2", + "libpolkit-grant.so.2", + "libpolkit.so.2", + "libpopt.so.0", + "libpthread.so.0", + "libpth.so.20", + "libreadline.so.5", + "libresmgr.so.0.9.8", + "libresmgr.so.1", + "libresolv.so.2", + "librt.so.1", + "libsasl2.so.2", + "libsasldb.so.2", + "libscconf.so.2", + "libslp.so.1", + "libsmbios.so.1", + "libssl.so.0.9.8", + "libss.so.2", + "libstdc++.so.6", + "libthread_db.so.1", + "libtic.so.5", + "libusb-0.1.so.4", + "libusbpp-0.1.so.4", + "libutil.so.1", + "libuuid.so.1", + "libvolume_id.so.0", + "libwrap.so.0", + "libX11.so.6", + "libX11-xcb.so.1", + "libXau.so.6", + "libxcb-composite.so.0", + "libxcb-damage.so.0", + "libxcb-dpms.so.0", + "libxcb-glx.so.0", + "libxcb-randr.so.0", + "libxcb-record.so.0", + "libxcb-render.so.0", + "libxcb-res.so.0", + "libxcb-screensaver.so.0", + "libxcb-shape.so.0", + "libxcb-shm.so.0", + "libxcb.so.1", + "libxcb-sync.so.0", + "libxcb-xevie.so.0", + "libxcb-xf86dri.so.0", + "libxcb-xfixes.so.0", + "libxcb-xinerama.so.0", + "libxcb-xlib.so.0", + "libxcb-xprint.so.0", + "libxcb-xtest.so.0", + "libxcb-xvmc.so.0", + "libxcb-xv.so.0", + "libxcrypt.so.1", + "libzio.so.0", + "libz.so.1", +) + +from BinariesCheck import BinaryInfo + +def libname_from_soname (soname): + libname = string.split(soname, '.so.') + if len(libname) == 2: + if libname[0][-1:].isdigit(): + libname = string.join(libname, '-') + else: + libname = string.join(libname, '') + else: + libname = soname[:-3] + libname = libname.replace('.', '_') + return libname + +class LibraryPolicyCheck(AbstractCheck.AbstractCheck): + def __init__(self): + self.map = [] + AbstractCheck.AbstractCheck.__init__(self, "LibraryPolicyCheck") + + def check(self, pkg): + global _policy_legacy_exceptions + + if pkg.isSource(): + return + + # Only check unsuffixed lib* packages + if pkg.name.endswith('-devel') or pkg.name.endswith('-doc'): + return + + files = pkg.files() + + # Search for shared libraries in this package + libs = set() + libs_needed = set() + libs_to_dir = dict() + dirs = set() + reqlibs = set() + pkg_requires = set(map(lambda x: string.split(x[0],'(')[0], pkg.requires())) + + for f, pkgfile in files.items(): + if f.find('.so.') != -1 or f.endswith('.so'): + filename = pkg.dirName() + '/' + f + try: + if stat.S_ISREG(files[f].mode) and 'ELF' in pkgfile.magic: + bi = BinaryInfo(pkg, filename, f, False, True) + libs_needed = libs_needed.union(bi.needed) + if bi.soname != 0: + lib_dir = string.join(f.split('/')[:-1], '/') + libs.add(bi.soname) + libs_to_dir[bi.soname] = lib_dir + dirs.add(lib_dir) + if bi.soname in pkg_requires: + # But not if the library is used by the pkg itself + # This avoids program packages with their own private lib + # FIXME: we'd need to check if somebody else links to this lib + reqlibs.add(bi.soname) + except: + pass + pass + + std_dirs = dirs.intersection(('/lib', '/lib64', '/usr/lib', '/usr/lib64', + '/opt/kde3/lib', '/opt/kde3/lib64')) + + non_std_dirs = dirs.difference(std_dirs) + + # If this is a program package (all libs it provides are + # required by itself), bail out + if not pkg.name.startswith("lib") and len(libs.difference(reqlibs)) == 0: + return + + std_lib_package = False + if pkg.name.startswith("lib") and pkg.name[-1].isdigit(): + std_lib_package = True + + # ignore libs in a versioned non_std_dir + if std_lib_package: + for lib in libs.copy(): + lib_dir = libs_to_dir[lib] + if lib_dir.startswith("/opt/kde3"): + continue + for lib_part in lib_dir.split('/'): + if len(lib_part) == 0: + continue + if lib_part[-1].isdigit() and not lib_part.endswith("lib64"): + libs.remove(lib) + break + + # Check for non-versioned libs in a std lib package + if std_lib_package: + for lib in libs.copy(): + if not lib[-1].isdigit(): + printWarning(pkg, "shlib-unversioned-lib", lib) + libs.remove(lib) + + # If this package should be or should be splitted into shlib + # package(s) + if len(libs) > 0 and len(std_dirs) > 0: + # If the package contains a single shlib, name after soname + if len(libs) == 1: + soname = libs.copy().pop() + libname = libname_from_soname (soname) + if libname.startswith('lib') and pkg.name != libname and \ + pkg.name != libname + "-mini": + if libname in _policy_legacy_exceptions: + printWarning(pkg, 'shlib-legacy-policy-name-error', libname) + else: + printError(pkg, 'shlib-policy-name-error', libname) + + elif not pkg.name[-1:].isdigit(): + printError(pkg, 'shlib-policy-missing-suffix') + + if (not pkg.name.startswith('lib')) or pkg.name.endswith('-lang'): + return + + if not libs: + if pkg.name in _policy_legacy_exceptions: + printWarning(pkg, 'shlib-legacy-policy-missing-lib', pkg.name) + else: + printError(pkg, 'shlib-policy-missing-lib') + + # Verify no non-lib stuff is in the package + dirs = set() + for f in files: + if os.path.isdir(pkg.dirName()+f): + dirs.add(f) + + # Verify shared lib policy package doesn't have hard dependency on non-lib packages + if std_lib_package: + for dep in pkg.requires(): + if (dep[0].startswith('rpmlib(') or dep[0].startswith('config(')): + continue + if (dep[1] & (rpm.RPMSENSE_GREATER | rpm.RPMSENSE_EQUAL)) == rpm.RPMSENSE_EQUAL: + printWarning(pkg, "shlib-fixed-dependency", Pkg.formatRequire(dep[0], dep[1], dep[2])) + + # Verify non-lib stuff does not add dependencies + if libs: + for dep in pkg_requires.difference(_essential_dependencies): + if dep.find('.so.') != -1 and not dep in libs and not dep in libs_needed: + printError(pkg, 'shlib-policy-excessive-dependency', dep) + + # Check for non-versioned directories beyond sysdirs in package + sysdirs = [ '/lib', '/lib64', '/usr/lib', '/usr/lib64', + '/usr/share/doc/packages', '/usr/share' ] + cdirs = set() + for sysdir in sysdirs: + done = set() + for dir in dirs: + if dir.startswith(sysdir + '/'): + ssdir = string.split(dir[len(sysdir)+1:],'/')[0] + if not ssdir[-1].isdigit(): + cdirs.add(sysdir+'/'+ssdir) + done.add(dir) + dirs = dirs.difference(done) + map(lambda dir: printError(pkg, 'shlib-policy-nonversioned-dir', dir), cdirs) + +check=LibraryPolicyCheck() + +if Config.info: + addDetails( +'shlib-policy-missing-suffix', +"""Your package containing shared libraries does not end in a digit and +should probably be split.""", +'shlib-policy-devel-file', +"""Your shared library package contains development files. Split them into +a -devel subpackage.""", +'shlib-policy-name-error', +"""Your package contains a single shared library but is not named after its SONAME.""", +'shlib-policy-nonversioned-dir', +"""Your shared library package contains non-versioned directories. Those will not +allow to install multiple versions of the package in parallel.""", +'shlib-legacy-policy-name-error', +"""Your shared library package is not named after its SONAME, but it has been added to the list +of legacy exceptions. Please do not rename the package until SONAME changes, but if you have +to rename it for another reason, make sure you name it correctly.""", +'shlib-policy-excessive-dependency', +"""Your package starts with 'lib' as part of its name, but also contains binaries +that have more dependencies than those that already required by the libraries. +Those binaries should probably not be part of the library package, but split into +a seperate one to reduce the additional dependencies for other users of this library.""", +'shlib-policy-missing-lib', +"""Your package starts with 'lib' as part of its name, but does not provide +any libraries. It must not be called a lib-package then. Give it a more +sensible name.""", +'shlib-fixed-dependency', +"""Your shared library package requires a fixed version of another package. The +intention of the Shared Library Policy is to allow parallel installation of +multiple versions of the same shared library, hard dependencies likely make that +impossible. Please remove this dependency and instead move it to the runtime uses +of your library.""", +'shlib-unversioned-lib', +"""Your package matches the Shared Library Policy Naming Scheme but contains an +unversioned library. Therefore it is very unlikely that your package can be installed +in parallel to another version of this library package. Consider moving unversioned +parts into a runtime package.""" +) diff --git a/rpmlint-checks-master/Makefile b/rpmlint-checks-master/Makefile new file mode 100644 index 0000000..ade37b7 --- /dev/null +++ b/rpmlint-checks-master/Makefile @@ -0,0 +1,46 @@ +LIBDIR=/usr/share/rpmlint + +PYTHON = python + +DEFAULT = *.py +EXPERIMENTAL = experimental/*.py +OBSOLETE = obsolete/*.py +TEST = test/*/*.spec + +all: default experimental obsolete + +default: + if [ "x${COMPILE_PYC}" = "x1" ] ; then \ + $(PYTHON) -m py_compile *.py ; \ + fi + $(PYTHON) -O -m py_compile *.py + +experimental: + if [ "x${COMPILE_PYC}" = "x1" ] ; then \ + $(PYTHON) -m py_compile $(EXPERIMENTAL) ; \ + fi + $(PYTHON) -O -m py_compile $(EXPERIMENTAL) + +obsolete: + if [ "x${COMPILE_PYC}" = "x1" ] ; then \ + $(PYTHON) -m py_compile $(OBSOLETE) ; \ + fi + $(PYTHON) -O -m py_compile $(OBSOLETE) + +clean: + rm -f *~ *.pyc *.pyo + rm -f experimemntal/*~ experimental/*.pyc experimental/*.pyo + rm -f obsolete/*~ obsolete/*.pyc obsolete/*.pyo + +install: all + mkdir -p $(DESTDIR)$(LIBDIR)/experimental + mkdir -p $(DESTDIR)$(LIBDIR)/obsolete + -cp -p *.pyc $(DESTDIR)$(LIBDIR) + cp -p *.py *.pyo $(DESTDIR)$(LIBDIR) + -cp -p experimental/*.pyc $(DESTDIR)$(LIBDIR)/experimental + cp -p experimental/*.py experimental/*.pyo $(DESTDIR)$(LIBDIR)/experimental + -cp -p obsolete/*.pyc $(DESTDIR)$(LIBDIR)/obsolete + cp -p obsolete/*.py obsolete/*.pyo $(DESTDIR)$(LIBDIR)/obsolete + +.PHONY: all clean experimental install obsolete + diff --git a/rpmlint-checks-master/experimental/CheckStaticLibraries.py b/rpmlint-checks-master/experimental/CheckStaticLibraries.py new file mode 100644 index 0000000..f5a0710 --- /dev/null +++ b/rpmlint-checks-master/experimental/CheckStaticLibraries.py @@ -0,0 +1,61 @@ +# vim:sw=4:et +############################################################################# +# File : CheckStaticLibraries.py +# Package : rpmlint +# Author : Dirk Mueller +# Purpose : Check for binaries containing copies of common libs +############################################################################# + +from Filter import * +import AbstractCheck +import rpm +import re +import os +import commands +import Config +import stat + +class StaticLibrariesCheck(AbstractCheck.AbstractFilesCheck): + def __init__(self): + AbstractCheck.AbstractFilesCheck.__init__(self, "CheckStaticLibs", ".*") + self.staticlibsre = re.compile( + '(?:ruby - Copyright \(C\) 1993-%d Yukihiro Matsumoto|' + # ruby + 'inflate (\d.\d.\d) Copyright 1995-\d+ Mark Adler|' + + 'deflate (\d.\d.\d) Copyright 1995-\d+ Jean-loup Gailly|' + #zlib + 'Berkeley DB: DB 1\.85\'s recno bfname field is not supported|' + # db 4.4 + 'close shared connections - see dbus_connection_close|' + # dbus + 'I can\'t handle hardcopy terminals|' + # ncurses + 'readline_callback_read_char\(\) called with no handler|' + # readline + 'EXT2FS Library version \d.\d+|' + # libext2fs + 'requested feature requires XML_DTD support in Expat|' + # libexpat + 'Julian Seward, 15 February 2005|' + # libbz2 + 'option type (%d) not implemented in popt|' + # libpopt + '\(key - \(char *\) 0\) % __alignof__ \(md5_uint32\) == 0|' + # libcrypt + 'Copyright \(C\) \d+, Thomas G. Lane|' + # libjpeg + 'Copyright \(c\) 1995-1996 Guy Eric Schalnat, Group 42, Inc|' + # libpng + 'tag to <libexif-devel@lists.sourceforge.net>|' + # libexif + 'authorization function - should be SQLITE_OK|' + # libsqlite + 'Copyright \(c\) 1988-1996 Sam Leffler|' + # libtiff + 'this version of PCRE is not compiled with PCRE_UTF8 support', + # libpcre + 'Too many heap sections: Increase MAXHINCR or MAX_HEAP_SECTS', #gc + ')') + + def check_file(self, pkg, filename): + if filename.startswith('/usr/lib/debug') or pkg.isSource(): + return + + if not stat.S_ISREG(pkg.files()[filename][0]): + return + + grep_result = pkg.grep(self.staticlibsre, filename) + + if len(grep_result): + printError(pkg, "file-contains-system-library", filename, grep_result) + +check=StaticLibrariesCheck() + +if Config.info: + addDetails( +'file-contains-system-library', +"Your file contains traces of a system library that should be linked dynamically." +) diff --git a/rpmlint-checks-master/experimental/CheckUnusedLibs.py b/rpmlint-checks-master/experimental/CheckUnusedLibs.py new file mode 100644 index 0000000..7d975a3 --- /dev/null +++ b/rpmlint-checks-master/experimental/CheckUnusedLibs.py @@ -0,0 +1,59 @@ +# vim:sw=4:et +############################################################################# +# File : CheckUnusedLibs.py +# Package : rpmlint +# Author : Dirk Mueller +# Purpose : Check for binaries linking unused libraries +############################################################################# +# XXX: the check can not reliably work as binaries in the package +# could require libraries the package itself provides. + +from Filter import * +import AbstractCheck +import rpm +import re +import os +import string +import commands +import Config +import Pkg +import stat + +class UnusedLibsCheck(AbstractCheck.AbstractCheck): + def __init__(self): + AbstractCheck.AbstractCheck.__init__(self, "CheckUnusedLibs") + + def check(self, pkg): + + if pkg.isSource(): + return; + + files = pkg.files() + + for fname, pkgfile in files.items(): + + if pkgfile.is_ghost: + continue + + if fname.startswith('/usr/lib/debug') or \ + not stat.S_ISREG(pkgfile.mode) or \ + string.find(pkgfile.magic, 'ELF') == -1: + continue + + ret, output = Pkg.getstatusoutput(['ldd', '-r', '-u', pkgfile.path]) + for l in output.split('\n'): + l = l.lstrip() + if not l.startswith('/'): + continue + lib = l.rsplit('/')[-1] + if lib in ('libdl.so.2', 'libm.so.6', 'libpthread.so.0'): + continue + printError(pkg, 'elf-binary-unused-dependency', fname, lib) + +check=UnusedLibsCheck() + +if Config.info: + addDetails( +'elf-binary-unused-dependency', +"Your ELF binary links a library that is not used." +) diff --git a/rpmlint-checks-master/mkchanges b/rpmlint-checks-master/mkchanges new file mode 100755 index 0000000..eee31c5 --- /dev/null +++ b/rpmlint-checks-master/mkchanges @@ -0,0 +1,7 @@ +#!/bin/sh +# create log suitable for c&p into rpm changes file +if [ -z "$1" ]; then + set -- remotes/origin/master..master +fi +# no idea why it always prints those commit lines +git rev-list --pretty=format:" - %s" "$@" |grep -v ^commit diff --git a/rpmlint-checks-master/obsolete/DesktopTranslationCheck.py b/rpmlint-checks-master/obsolete/DesktopTranslationCheck.py new file mode 100644 index 0000000..6287999 --- /dev/null +++ b/rpmlint-checks-master/obsolete/DesktopTranslationCheck.py @@ -0,0 +1,48 @@ +# vim:sw=4:et +#--------------------------------------------------------------- +# Module : rpmlint +# File : DesktopTranslationCheck.py +# Author : Dirk Mueller +# Purpose : Check for untranslated desktop files +#--------------------------------------------------------------- + +from Filter import * +import AbstractCheck +import rpm +import re +import commands +import Config + +desktop_re=re.compile('(services|applets)/.*\.desktop$') + +class DesktopCheck(AbstractCheck.AbstractFilesCheck): + def __init__(self): + AbstractCheck.AbstractFilesCheck.__init__(self, "DesktopTranslationCheck", ".*\.desktop$") + + def check_file(self, pkg, filename): + if pkg.isSource() or filename in pkg.ghostFiles(): + return + + try: + f = open(pkg.dirName() + '/' + filename) + except Exception, e: + printWarning(pkg, "read-error", e) + return 0 + + found_desktop_group=False + for line in f: + if line.startswith('X-SuSE-translate='): + return + if line.startswith('[Desktop Entry]'): + found_desktop_group=True + if found_desktop_group: + printWarning(pkg, "untranslated-desktop-file", filename) + +check=DesktopCheck() + +if Config.info: + addDetails( +'untranslated-desktop-file', +"""Your desktop file hasn't been handled by %suse_update_desktop_file +Please use it to make the desktop file translate-able by Novell translations.""" +) diff --git a/rpmlint-checks-master/singlecheck b/rpmlint-checks-master/singlecheck new file mode 100755 index 0000000..87c900d --- /dev/null +++ b/rpmlint-checks-master/singlecheck @@ -0,0 +1,19 @@ +#!/bin/bash +set -e +opt_all= +if [ "$1" = "--all" ]; then + opt_all=1 + shift +fi +config=`mktemp` +trap "rm -f $config" EXIT +check="$1" +check=${check%.py} +shift +cat config >> "$config" +echo "Config.resetChecks()" >> $config +if [ -n "$opt_all" ]; then + echo "Config._filters = []" >> $config +fi +echo "addCheck(\"$check\")" >> $config +rpmlint -i -f $config -C $PWD "$@" diff --git a/rpmlint-checks-master/tests/CheckFilelists/cvs-bad.spec b/rpmlint-checks-master/tests/CheckFilelists/cvs-bad.spec new file mode 100644 index 0000000..577a5df --- /dev/null +++ b/rpmlint-checks-master/tests/CheckFilelists/cvs-bad.spec @@ -0,0 +1,26 @@ +Name: cvs-bad +Version: 0 +Release: 0 +Group: Development/Tools/Building +Summary: Bar +License: GPL +BuildRoot: %_tmppath/%name-%version-build + +%description +%_target +%_target_cpu + +%install +install -D -m 644 /etc/motd %buildroot/usr/lib/foo/.cvsignore +install -D -m 644 /etc/motd %buildroot/usr/lib/foo/CVS/foo +install -D -m 644 /etc/motd %buildroot/usr/lib/foo/bla,v +install -D -m 644 /etc/motd %buildroot/usr/lib/foo/RCS/asd + +%clean +rm -rf %buildroot + +%files +%defattr(-,root,root) +/usr/lib/* + +%changelog diff --git a/rpmlint-checks-master/tests/CheckFilelists/debug.spec b/rpmlint-checks-master/tests/CheckFilelists/debug.spec new file mode 100644 index 0000000..e5d7892 --- /dev/null +++ b/rpmlint-checks-master/tests/CheckFilelists/debug.spec @@ -0,0 +1,21 @@ +Name: debug +Version: 0 +Release: 0 +Group: Development/Tools/Building +Summary: Bar +License: GPL +BuildRoot: %_tmppath/%name-%version-build + +%description +%_target +%_target_cpu + +%install +install -D -m 755 /bin/sh %buildroot/usr/lib/debug/sh + +%clean +rm -rf %buildroot + +%files +%defattr(-,root,root) +/usr/lib/debug diff --git a/rpmlint-checks-master/tests/CheckFilelists/empty.spec b/rpmlint-checks-master/tests/CheckFilelists/empty.spec new file mode 100644 index 0000000..6feb9f8 --- /dev/null +++ b/rpmlint-checks-master/tests/CheckFilelists/empty.spec @@ -0,0 +1,17 @@ +Name: empty +Version: 0 +Release: 0 +Group: Development/Tools/Building +Summary: Bar +License: GPL +BuildRoot: %_tmppath/%name-%version-build + +%description +%_target +%_target_cpu + +%clean +rm -rf %buildroot + +%files +%defattr(-,root,root) diff --git a/rpmlint-checks-master/tests/CheckFilelists/fail-cd1.spec b/rpmlint-checks-master/tests/CheckFilelists/fail-cd1.spec new file mode 100644 index 0000000..a89e8cd --- /dev/null +++ b/rpmlint-checks-master/tests/CheckFilelists/fail-cd1.spec @@ -0,0 +1,23 @@ +Name: fail-cd1 +Version: 0 +Release: 0 +Group: Development/Tools/Building +Summary: Bar +License: GPL +BuildRoot: %_tmppath/%name-%version-build + +%description +%_target +%_target_cpu + +%install +install -D -m 644 /etc/motd %buildroot/CD1/test + +%clean +rm -rf %buildroot + +%files +%defattr(-,root,root) +/CD1/* + +%changelog diff --git a/rpmlint-checks-master/tests/CheckFilelists/fhs.spec b/rpmlint-checks-master/tests/CheckFilelists/fhs.spec new file mode 100644 index 0000000..8b998d7 --- /dev/null +++ b/rpmlint-checks-master/tests/CheckFilelists/fhs.spec @@ -0,0 +1,21 @@ +Name: fhs +Version: 0 +Release: 0 +Group: Development/Tools/Building +Summary: Bar +License: GPL +BuildRoot: %_tmppath/%name-%version-build + +%description +%_target +%_target_cpu + +%install +install -D -m 755 /bin/sh %buildroot/sbin/init.d/foo + +%clean +rm -rf %buildroot + +%files +%defattr(-,root,root) +/sbin/init.d diff --git a/rpmlint-checks-master/tests/CheckFilelists/game.spec b/rpmlint-checks-master/tests/CheckFilelists/game.spec new file mode 100644 index 0000000..9da63e0 --- /dev/null +++ b/rpmlint-checks-master/tests/CheckFilelists/game.spec @@ -0,0 +1,22 @@ +Name: game +Version: 0 +Release: 0 +Group: Development/Tools/Building +Summary: Bar +License: GPL +BuildRoot: %_tmppath/%name-%version-build + +%description +%_target +%_target_cpu + +%install +install -D -m 755 /bin/sh %buildroot/usr/games/foo +install -D -m 755 /bin/sh %buildroot/usr/games/lib/blub + +%clean +rm -rf %buildroot + +%files +%defattr(-,root,root) +/usr/games/* diff --git a/rpmlint-checks-master/tests/CheckFilelists/lib.spec b/rpmlint-checks-master/tests/CheckFilelists/lib.spec new file mode 100644 index 0000000..fd69f2c --- /dev/null +++ b/rpmlint-checks-master/tests/CheckFilelists/lib.spec @@ -0,0 +1,21 @@ +Name: lib +Version: 0 +Release: 0 +Group: Development/Tools/Building +Summary: Bar +License: GPL +BuildRoot: %_tmppath/%name-%version-build + +%description +%_target +%_target_cpu + +%install +install -D -m 644 /etc/motd %buildroot/lib64/libsh.la + +%clean +rm -rf %buildroot + +%files +%defattr(-,root,root) +/lib64/* diff --git a/rpmlint-checks-master/tests/CheckFilelists/lib64.spec b/rpmlint-checks-master/tests/CheckFilelists/lib64.spec new file mode 100644 index 0000000..047d260 --- /dev/null +++ b/rpmlint-checks-master/tests/CheckFilelists/lib64.spec @@ -0,0 +1,22 @@ +Name: lib64 +Version: 0 +Release: 0 +Group: Development/Tools/Building +Summary: Bar +License: GPL +BuildRoot: %_tmppath/%name-%version-build +BuildArch: noarch + +%description +%_target +%_target_cpu + +%install +install -D -m 755 /lib/ld-linux.so.2 %buildroot/lib64/ld-linux.so.2 + +%clean +rm -rf %buildroot + +%files +%defattr(-,root,root) +/lib64/ld-linux.so.2 diff --git a/rpmlint-checks-master/tests/CheckFilelists/opt1-bad.spec b/rpmlint-checks-master/tests/CheckFilelists/opt1-bad.spec new file mode 100644 index 0000000..28bc388 --- /dev/null +++ b/rpmlint-checks-master/tests/CheckFilelists/opt1-bad.spec @@ -0,0 +1,21 @@ +Name: opt1-bad +Version: 0 +Release: 0 +Group: Development/Tools/Building +Summary: Bar +License: GPL +BuildRoot: %_tmppath/%name-%version-build + +%description +%_target +%_target_cpu + +%install +install -D -m 644 /etc/motd %buildroot/opt/foo/blah + +%clean +rm -rf %buildroot + +%files +%defattr(-,root,root) +/opt/* diff --git a/rpmlint-checks-master/tests/CheckFilelists/opt2-good.spec b/rpmlint-checks-master/tests/CheckFilelists/opt2-good.spec new file mode 100644 index 0000000..50c575f --- /dev/null +++ b/rpmlint-checks-master/tests/CheckFilelists/opt2-good.spec @@ -0,0 +1,23 @@ +Name: opt2-good +Version: 0 +Release: 0 +Group: Development/Tools/Building +Summary: Bar +License: GPL +BuildRoot: %_tmppath/%name-%version-build +Vendor: xxSUSE yy + +%description +%_target +%_target_cpu + +%install +install -D -m 644 /etc/motd %buildroot/opt/novell/blah +install -D -m 644 /etc/motd %buildroot/opt/suse/blub + +%clean +rm -rf %buildroot + +%files +%defattr(-,root,root) +/opt/* diff --git a/rpmlint-checks-master/tests/CheckFilelists/opt3-kde3-good.spec b/rpmlint-checks-master/tests/CheckFilelists/opt3-kde3-good.spec new file mode 100644 index 0000000..f03d827 --- /dev/null +++ b/rpmlint-checks-master/tests/CheckFilelists/opt3-kde3-good.spec @@ -0,0 +1,21 @@ +Name: opt2-kde3-good +Version: 0 +Release: 0 +Group: Development/Tools/Building +Summary: Bar +License: GPL +BuildRoot: %_tmppath/%name-%version-build + +%description +%_target +%_target_cpu + +%install +install -D -m 644 /etc/motd %buildroot/opt/kde3/blah + +%clean +rm -rf %buildroot + +%files +%defattr(-,root,root) +/opt/* diff --git a/rpmlint-checks-master/tests/CheckFilelists/skelcd-good.spec b/rpmlint-checks-master/tests/CheckFilelists/skelcd-good.spec new file mode 100644 index 0000000..ffcc590 --- /dev/null +++ b/rpmlint-checks-master/tests/CheckFilelists/skelcd-good.spec @@ -0,0 +1,23 @@ +Name: skelcd-good +Version: 0 +Release: 0 +Group: Development/Tools/Building +Summary: Bar +License: GPL +BuildRoot: %_tmppath/%name-%version-build + +%description +%_target +%_target_cpu + +%install +install -D -m 644 /etc/motd %buildroot/CD1/test1 + +%clean +rm -rf %buildroot + +%files +%defattr(-,root,root) +/CD1/* + +%changelog diff --git a/rpmlint-checks-master/tests/CheckFilelists/srv.spec b/rpmlint-checks-master/tests/CheckFilelists/srv.spec new file mode 100644 index 0000000..75e36fa --- /dev/null +++ b/rpmlint-checks-master/tests/CheckFilelists/srv.spec @@ -0,0 +1,21 @@ +Name: srv +Version: 0 +Release: 0 +Group: Development/Tools/Building +Summary: Bar +License: GPL +BuildRoot: %_tmppath/%name-%version-build + +%description +%_target +%_target_cpu + +%install +install -D -m 755 /bin/sh %buildroot/usr/local/ftp/foo + +%clean +rm -rf %buildroot + +%files +%defattr(-,root,root) +/usr/local/ftp diff --git a/rpmlint-checks-master/tests/CheckFilelists/sysconfig-bad.spec b/rpmlint-checks-master/tests/CheckFilelists/sysconfig-bad.spec new file mode 100644 index 0000000..d3ec1c2 --- /dev/null +++ b/rpmlint-checks-master/tests/CheckFilelists/sysconfig-bad.spec @@ -0,0 +1,21 @@ +Name: sysconfig-bad +Version: 0 +Release: 0 +Group: Development/Tools/Building +Summary: Bar +License: GPL +BuildRoot: %_tmppath/%name-%version-build + +%description +%_target +%_target_cpu + +%install +install -D -m 644 /etc/motd %buildroot/etc/sysconfig/foo + +%clean +rm -rf %buildroot + +%files +%defattr(-,root,root) +/etc/sysconfig/* diff --git a/rpmlint-checks-master/tests/CheckFilelists/usr-bad.spec b/rpmlint-checks-master/tests/CheckFilelists/usr-bad.spec new file mode 100644 index 0000000..590e818 --- /dev/null +++ b/rpmlint-checks-master/tests/CheckFilelists/usr-bad.spec @@ -0,0 +1,21 @@ +Name: usr-bad +Version: 0 +Release: 0 +Group: Development/Tools/Building +Summary: Bar +License: GPL +BuildRoot: %_tmppath/%name-%version-build + +%description +%_target +%_target_cpu + +%install +install -D -m 644 /etc/motd %buildroot/usr/qvm/test + +%clean +rm -rf %buildroot + +%files +%defattr(-,root,root) +/usr/* diff --git a/rpmlint-checks-master/tests/CheckFilelists/usr-src-2-bad.spec b/rpmlint-checks-master/tests/CheckFilelists/usr-src-2-bad.spec new file mode 100644 index 0000000..ed84c1b --- /dev/null +++ b/rpmlint-checks-master/tests/CheckFilelists/usr-src-2-bad.spec @@ -0,0 +1,21 @@ +Name: usr-src-2-bad +Version: 0 +Release: 0 +Group: Development/Tools/Building +Summary: Bar +License: GPL +BuildRoot: %_tmppath/%name-%version-build + +%description +%_target +%_target_cpu + +%install +install -D -m 644 /etc/motd %buildroot/usr/src/foo/test + +%clean +rm -rf %buildroot + +%files +%defattr(-,root,root) +/usr/src/* diff --git a/rpmlint-checks-master/tests/CheckFilelists/usr-src-bad.spec b/rpmlint-checks-master/tests/CheckFilelists/usr-src-bad.spec new file mode 100644 index 0000000..0e247c1 --- /dev/null +++ b/rpmlint-checks-master/tests/CheckFilelists/usr-src-bad.spec @@ -0,0 +1,21 @@ +Name: usr-src-bad +Version: 0 +Release: 0 +Group: Development/Tools/Building +Summary: Bar +License: GPL +BuildRoot: %_tmppath/%name-%version-build + +%description +%_target +%_target_cpu + +%install +install -D -m 644 /etc/motd %buildroot/usr/src/test + +%clean +rm -rf %buildroot + +%files +%defattr(-,root,root) +/usr/src/* diff --git a/rpmlint-checks-master/tests/CheckFilelists/yast2.spec b/rpmlint-checks-master/tests/CheckFilelists/yast2.spec new file mode 100644 index 0000000..2b7fa31 --- /dev/null +++ b/rpmlint-checks-master/tests/CheckFilelists/yast2.spec @@ -0,0 +1,21 @@ +Name: yast2 +Version: 0 +Release: 0 +Group: Development/Tools/Building +Summary: Bar +License: GPL +BuildRoot: %_tmppath/%name-%version-build + +%description +%_target +%_target_cpu + +%install +install -D -m 755 /bin/sh %buildroot/usr/lib/YaST2/foo.ycp + +%clean +rm -rf %buildroot + +%files +%defattr(-,root,root) +/usr/lib/YaST2 |