pkgcheck
Integrity checker for Slackware Linux: verifies that the files recorded by each package
in /var/log/packages/ really exist on the system.
- Bulk extraction of
FILE LIST:sections with ripgrep in a single pass (Python fallback ifrgnot found). - Parallel verification with
ThreadPoolExecutor(broken symbolic links count as present:os.lstatis used). - Distinguishes missing files, backup-only (
.bak/.orig) and no access (requires root), as well as.newconfigs pending review. - Decodes the octal escapes (
\NNN) Slackware uses for names with non-ASCII bytes and discards sections after the FILE LIST (e.g.REQUIRES:). - Excludes install scripts (
install/) and pseudo-filesystems (dev/,sys/,proc/,run/,tmp/,var/tmp,var/cache,var/spool,var/log,mnt,media, …) withvar/log/packagesexception. - Reports files with verification errors too (JSON
files_errors/ERRORSlog section). - Finds orphan files not owned by any package (
--orphans) and diffs two runs (--diffwith--list-logs). - Shell completion for bash/zsh/fish (
--completion). - Live progress and report with rich; summary + breakdown per package.
- Automatic log in
/var/log/pkgcheck/pkgcheck-<date>.log(.jsonwith--json). - Internationalized interface (7 languages) with automatic OS locale detection.
Requirements
- Python 3.12+
- uv
- ripgrep (
rg) recommended (falls back to Python scan if missing)
Getting started
uv sync # creates .venv and installs the project and its dependencies
uv run pkgcheck --version
It can also be run as a module: uv run python -m pkgcheck.
Usage
sudo uv run pkgcheck # analyzes /var/log/packages and writes the log
sudo uv run pkgcheck --json # writes the log in JSON format (.json)
uv run pkgcheck --no-elevate --json # without root: only prints the JSON to stdout
uv run pkgcheck --workers 16 # adjusts the parallelism
uv run pkgcheck --packages-dir /mnt/root/var/log/packages
sudo uv run pkgcheck --check-libs-deps # also checks library dependencies (ldd)
sudo uv run pkgcheck --check-libs-deps --check-libs-symbols # + undefined symbols (nm -D)
uv run pkgcheck --orphans --orphans-root / # lists untracked files
uv run pkgcheck --list-logs # lists existing logs
uv run pkgcheck --diff --from latest --to /var/log/pkgcheck/pkgcheck-...json --json
uv run pkgcheck --completion bash > /etc/bash_completion.d/pkgcheck
Library dependencies (--check-libs-deps)
Inspired by Gentoo's revdep-rebuild, this optional check verifies that every
installed ELF binary and shared library has all of its dynamic library
dependencies present on the system. For each ELF file ldd is run (in parallel)
and any not found dependency is flagged:
- The broken binary/library and the owning package are reported.
- A best-effort guess is made for which installed package should provide each
missing library (matched by library basename; it may be
Nonewhen the soname does not match any installed file). - Results are grouped by package in the
broken_libssection of the JSON report ({package: [{binary, missing, provided_by}]}) and in the text log underBROKEN LIBRARY DEPS:.
Requires ldd (present on Slackware/glibc). It is opt-in because running ldd
over the whole system is expensive.
Undefined symbols (--check-libs-symbols)
An optional, extra mode (mirrors revdep-rebuild's -u / SEARCH_SYMBOLS). After
collecting the set of dynamic symbols exported by the installed libraries using
nm -D, it flags binaries that import symbols no installed library provides. It
requires --check-libs-deps and the nm tool (binutils), and is prone to
false positives (lazy binding, dlopen-loaded libraries, symbol versioning).
Results appear in the undefined_symbols JSON key and the UNDEFINED SYMBOLS
log section.
Root privileges
Some protected files (e.g. /var/spool/atjobs, /root) can only be checked with root
privileges. If the process is not running as root:
- In an interactive terminal you are asked whether to re-run with sudo.
--elevatere-runs withsudowithout asking.--no-elevate(or--quiet, or non-interactive output) verifies only what is accessible and warns.
Install scripts and pseudo-filesystems
Entries under install/ (install/doinst.sh, install/slack-desc,
install/douninst.sh, install/slack-required) are metadata that Slackware does not
leave on disk, so they are excluded from the analysis and shown as an informational
counter.
The pseudo-filesystems and ephemeral paths (dev/, sys/, proc/, run/, tmp/, var/run/, var/tmp/, var/cache/, var/spool/, var/lock/, var/log/ (except var/log/packages/), var/lib/slackpkg/, mnt/, media/, srv/, lost+found/) are also
not tracked: their entries (e.g. the device nodes of the devs package) are dynamic and
do not persist. More prefixes can be added with --exclude. Ripgrep is preferred but a pure-Python fallback is used if rg is not found.
Pending new configs (.new)
Slackware records configs with the .new suffix in FILE LIST (e.g.
etc/ssl/openssl.cnf.new). On install, the package script renames the file to the
name without suffix (.new → ``); if that file already existed on the system, it keeps
the .new suffix and it is left pending review by the user.
pkgcheck honors this semantics:
foo.conf.newrecorded andfoo.confpresent → installed correctly (not reported).foo.conf.newpresent on disk → reported as pending review (the new version awaits your decision).foo.conf.newrecorded but with no trace → missing.
The suffix is adjusted with --new-suffix (default .new). The detail appears in the
report (key files_pending_new in JSON) and in the console tree.
Backup-only files
If a recorded path does not exist but a backup-suffix variant (.bak or .orig) does,
it is reported as backup-only instead of missing. The set of suffixes is adjusted with
--backup-suffixes. The per-package detail appears in the report (key files_backup in
JSON), not in the console tree.
Orphan files (--orphans)
With --orphans pkgcheck also reports files present on disk but not owned by any package (e.g. make install leftovers). The scan walks --orphans-root (default /) and excludes the pseudo-filesystems above plus home/ and any --exclude. Results appear in summary.orphans and orphans JSON key and in the ORPHANS text section and console tree.
Log listing and diff (--list-logs, --diff)
--list-logsprints a table of existing logs in/var/log/pkgcheck/(idx, date, fmt, size, path).--diff --from PATH --to PATH(orlatest/latest-1aliases) diffs two JSON reports (missing,files_backup, ...,orphans,broken_libs). In text mode it shows+ added/- removedper package; with--jsonit prints a JSON diff. Text logs (.log) are not diffable.
Shell completion (--completion)
--completion bash|zsh|fish prints a completion script to stdout. Example: pkgcheck --completion bash > /etc/bash_completion.d/pkgcheck.
Automatic log
Each run writes a log in /var/log/pkgcheck/ (the directory is created if it does not
exist) with the convention:
pkgcheck-dd-mm-yyyy-hh-mm-ss.log # plain text (default)
pkgcheck-dd-mm-yyyy-hh-mm-ss.json # with --json
- Requires root privileges: the default run uses
sudo, so the log is saved automatically. If it cannot be written, a warning is shown and the analysis continues. - With
--no-elevate(or non-interactive output without root) no file is saved: the result is only shown on screen (rich in text mode; with--jsononly the JSON document is printed to stdout). - With
--json, progress and process messages go to stderr (scan phases, progress bar and completion line), so stdout is reserved for the JSON document (no-elevate) or the confirmation of the saved log (root). In text mode progress is shown in the console itself. - If two runs collide on the same second, a numeric suffix is added
(
pkgcheck-<date>-1.log,-2, ...).
The JSON document includes a timestamp (ISO 8601), generator, version, summary
and the per-package indexes missing, files_backup, files_pending_new, no_access
and files_errors. With --check-libs-deps the broken_libs index is added, and with
--check-libs-symbols also undefined_symbols. These keys are stable and never localized.
Internationalization
The interface, the help and the text log are localized according to the operating system
language. Supported languages: en (base), es, pt, fr, de, zh (Simplified
Chinese) and ja.
Precedence for choosing the language:
--lang {en,es,pt,fr,de,zh,ja}PKGCHECK_LANGenvironment variable- OS locale (
LC_ALL,LC_MESSAGESorLANG) - English (default)
Translations live in src/pkgcheck/locales/{lang}.json (English → language mapping). To
add a new language, create locales/xx.json with the same keys translated; if a key is
missing, the English text is shown. The report JSON keys (missing, files_backup, ...)
are not localized: they are the stable API.
Arguments
| Argument | Description |
|---|---|
--packages-dir |
Directory with the records (default /var/log/packages). |
--workers N |
Verification threads (default: auto). |
--json |
Writes the log in JSON format (.json) instead of text. |
--max-rows N |
Limits the per-package console breakdown. |
--exclude PREFIX |
Additional prefix to exclude (repeatable or comma-separated). |
--backup-suffixes |
Backup suffixes detected as backup-only (default .bak,.orig). |
--new-suffix |
New-config suffix pending review (default .new). |
--lang LANG |
Interface language (en,es,pt,fr,de,zh,ja); detects the OS language. |
--check-libs-deps |
Also checks that every installed ELF binary/library has all its dynamic |
library dependencies present (ldd; revdep-rebuild style). |
|
--check-libs-symbols |
Also checks installed binaries for undefined dynamic symbols not |
provided by any installed library using nm -D (requires `--check-libs- |
|
| deps`; may report false positives). | |
--orphans |
Also list orphan files not owned by any package. |
--orphans-root |
Root for --orphans scan (default /). |
--list-logs |
List existing logs in /var/log/pkgcheck and exit. |
--diff |
Diff two JSON logs (requires --from/--to, supports latest). |
--from PATH |
First log for --diff. |
--to PATH |
Second log for --diff. |
--completion |
Generate shell completion (bash/zsh/fish) and exit. |
--quiet |
Hides progress and breakdown; only prints the summary. |
--elevate |
Re-runs with sudo if root privileges are not available. |
--no-elevate |
Does not ask for root privileges; only verifies what is accessible. |
--version |
Shows the version. |
Code quality
make check # lint + format-check + typecheck + test
make coverage # tests with coverage (>=80%)
make audit # pip-audit
uv run ruff check
uv run ruff format --check
uv run mypy src
uv run coverage run -m unittest discover -s tests && uv run coverage report
Tooling: ruff (E,F,W,I,UP,B,SIM,C4,RET,ARG,RUF,S,ANN,PTH,T20,D), mypy --strict,
coverage (branch, fail_under 90, total 93%), pip-audit, pre-commit.
Contributing
See CONTRIBUTING.md for development setup, uv sync --group dev,
and pre-commit install.
Changelog
See CHANGELOG.md.
Security
--check-libs-deps runs ldd which executes the target via the dynamic loader
(LD_TRACE). Only run on trusted installations; see src/pkgcheck/libdeps.py note.
Metadata
Release files for slackware-pkgcheck 1.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| slackware_pkgcheck-1.0.2.tar.gz | 135.9 kB | Without provenance | Details for slackware_pkgcheck-1.0.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| slackware_pkgcheck-1.0.2-py3-none-any.whl | Python 3 | none | any | Details for slackware_pkgcheck-1.0.2-py3-none-any.whl |
Total release size: 199.6 kB
Release files / slackware_pkgcheck-1.0.2.tar.gz
| Download URL | slackware_pkgcheck-1.0.2.tar.gz |
|---|---|
| Size | 135.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ed8d30f817334e5d797efbd5073fe7fc0721691057360b64d2c486eb5112adbb
|
|
BLAKE2b-256 checksum How to use checksums |
18a799307a5b4c7f281c7197039e691440c67e2e3816b511212b69df506839a7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|
Release files / slackware_pkgcheck-1.0.2-py3-none-any.whl
| Download URL | slackware_pkgcheck-1.0.2-py3-none-any.whl |
|---|---|
| Size | 63.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a9d8058dd313f2af199216179f410df51a736f4bbfc77caef9f1b52d1fe6d742
|
|
BLAKE2b-256 checksum How to use checksums |
f87d2e4054b7c4bd1dcbe3a35827d6747c7502a1f5ebb3254cd8c737641b0dfa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|
Security for slackware-pkgcheck 1.0.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.