lintpkg is a tool for checking common errors in slackware packages. It can be used for example to test downloaded packages for common packaging mistakes, or to check a package you created yourself for things you might have missed. By default all available checks are performed, but specific checks can be performed using command line parameters.
lintpkg is heavily based on rpmlint and tries to keep compatibility to it where possible in order to make integration into CI systems that already support rpmlint simple. It does however also try to keep close to the other pkgtools of slackware.
At this point there is no install script provided as it's not really necessary. lintpkg will look for checks by default in one of two locations:
- a "checks" directory within the same directory as the "lintpkg" script
- /usr/share/lintpkg/checks as a global location
The first one takes precedence, so running lintpkg from a git checkout always uses the checks from that checkout.
Alternatively you can tell lintpkg to use checks from a different location using
lintpkg --checkdir /path/to/checks
Currently lintpkg ships with a small set of checks:
- Binaries in wrong architecture paths (architecture_check)
- Directories that should not be used for packages (disallowed_dirs_check)
- Icon theme cache update in doinst.sh (icon_check)
- Correct path for and compression of info pages (info_check)
- Correct path for and compression of man pages (man_check)
- Correct folder permissions under /usr and /etc (permissions_check)
- Correct formatting of the slack-desc file (slack_desc_check)
- Existence of an /install directory within the package (install_dir_check)
- Correct ownership of system directories (ownership_check)
- Leftover symlinks in the package, not handled by doinst.sh (symlink_check)
- Package created with tar-1.13 (tar113_check)
- Unstripped binaries (unstripped_binaries_check)
- Binaries under /usr/share (usr_share_check)
- Valid libtool archives (shared_libraries_check)
More checks and comments on existing ones welcome :)
Not every rule applies to every package. Overrides make an exception to a rule for a package. Overridden rules are not reported and don't count as errors or warnings, but the summary lists how many errors, warnings and notices were overridden. Use --show-overrides to report them anyway, together with where the override came from and the reason for it.
lintpkg reads the overrides for a package from usr/share/lintpkg/overrides/ within the package itself. If the package doesn't ship that file, lintpkg uses its own overrides for the package, from an "overrides" directory next to the checks (/usr/share/lintpkg/overrides when installed), or from the directory given with --overridedir. The two are never combined.
Each line of an overrides file names a rule by its message identifier and, for rules about a file or directory, the path to override it for, as it will be installed:
# Binary needs to retain debugging info to be useful
unstripped-binary /usr/bin/foo
unstripped-binary /usr/lib64/libfoo.so.1
# The icons are only used by the application itself
missing-icon-cache-update hicolor
For rules that aren't about a path, the argument is optional. Without it, the rule is overridden for the whole package. With it, the rule is only overridden for that argument, like the icon theme above.
A comment directly above an override gives the reason for it, and also applies to the overrides directly following it, until the next empty line or comment.
Overrides for rules the package doesn't violate are reported as unused-override errors, so they can be removed once they are no longer needed. If an override is given more than once, only the first one is used. Use --ignore-unused-overrides to not report unused overrides.
Depending on the result of the checks lintpkg will return with different exit codes:
- 0: No errors
- 1: Unspecified error
- 64: One or more error/warning messages are printed (overridden messages don't count)
Writing checks is intentionally kept rather simple. A check needs to provide two functions:
The check() function performs the actual tests that should be performed on the package. All necessary information is available in global variables:
- $WORKING_DIR - This is the location of the uncompressed package content
- $PKG_FULLNAME - This is the full name of the package, sans the file extension
- $PKG_NAME - This is the name of the package
- $PKG_VERSION - This is the version of the package
- $PKG_ARCH - This is the architecture the package was built for
- $PKG_BUILD - This is the build number of the package
- $PKG_EXTENSION - This is the compression format used by the package
- $PKG_LISTING - This contains a list of all files and folders contained in the package
- $PKG_DETAILED_LISTING - This contains a list of all files and folders contained in the package, including ownership and permission information
Additionally there are several functions one can use for reporting issues. All of these take variable arguments, where the first is the messageid of the issue, and any further argument is additional optional information.
Issues about a file or directory within the package should be reported with the log_path_* functions instead. They take the path of the offending file or directory as second argument, followed by any additional optional information. The path can be given relative to $WORKING_DIR, as listed in the package, or as it will be installed, and is always reported as it will be installed (e.g. /usr/bin/foo).
- log_error() logs an issue as an error.
- log_warning() logs an issue as a warning.
- log_notice() logs an issue as a notice.
- log_path_error() logs an issue about a path as an error.
- log_path_warning() logs an issue about a path as a warning.
- log_path_notice() logs an issue about a path as a notice.
The info() function is used for providing detailed information on the issues that the check() function can raise. It's only argument is the messageid of an issue.