#!/bin/sh # sbopkglint test, must be sourced by sbopkglint (not run standalone). # PKG, PRGNAM, VERSION, ARCH are set by sbopkglint. also the current # directory is the root of the installed package tree. ####################################################################### # these directories are allowed to exist in the package, but they # must be mode 0755 and owned by root:root. if a dir from this list # exists but is empty, that's an error. if a top-level directory # exists that's *not* in this list (such as /dev), that's an error. topleveldirs="bin boot etc lib lib64 opt sbin srv usr var run" # these directories are *required* to exist, and must be mode 0755, root:root. # if a dir from this list exists but is empty, that's an error. note # that the install/ dir no longer exists by the time we run (installpkg # deleted it already); slack-desc is checked by the pre-doinst test. requireddirs="usr/doc/$PRGNAM-$VERSION" # these directories are the only ones allowed to exist directly under /usr. # do not include X11R6 or local here, and do not include dirs which are # symlinks on Slackware (X11 adm dict spool tmp). # don't list (x86_64|i586|etc)-slackware-linux, it's checked separately. usrdirs="bin doc games include info lib lib64 libexec man sbin share src x86_64-slackware-linux dict" # these directories *must not* exist. no need to list top-level dirs here, # the topleveldirs check already catches those. also, don't list stuff caught # by the $usrdirs check (e.g. usr/local, usr/etc, usr/man1). baddirs="etc/ld.so.conf.d usr/share/doc usr/share/man usr/share/info" # these directories may only contain files with +x permissions. in # other words, no non-executable files may live here. note that # bindirs is a subset of fileonlydirs. bindirs="bin usr/bin sbin usr/sbin usr/games" # these directories may exist, but must contain only files or symlinks, # and must be mode 0755, root:root. I thought usr/share/pixmaps # belonged here, but quite a few packages create subdirs there for # images required at runtime that aren't the app icon. fileonlydirs="$bindirs usr/man/man1 usr/man/man2 usr/man/man3 usr/man/man4 usr/man/man5 usr/man/man6 usr/man/man7 usr/man/man8 usr/man/man9 usr/man/manl usr/man/mann usr/lib/pkgconfig usr/lib64/pkgconfig usr/share/pkgconfig" # these directories may exist, but must contain only subdirectories # (no files, symlinks, devices, etc). "." (the top-level package dir) # doesn't need to be included here; it's checked separately. nofiledirs="usr usr/doc usr/share usr/man usr/doc/HTML usr/share/terminfo" # these directories may exist but must not have executable files # anywhere under them. I would put usr/doc and etc here, but too many # packages break that rule. usr/share/applications is listed here, # even though Slackware's KDE packages (erroneously) install .desktop # files +x. noexecdirs="usr/include usr/man usr/share/pixmaps usr/share/icons usr/share/applications usr/share/appdata usr/share/mime usr/share/mime-info usr/share/glib-2.0 usr/doc/HTML usr/share/terminfo usr/lib/pkgconfig usr/lib64/pkgconfig usr/share/pkgconfig" # these files must exist, unless -s option given. requiredfiles="usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild" # these files must not exist. badfiles="\ usr/lib64/perl5/perllocal.pod \ usr/lib/perl5/perllocal.pod \ usr/share/perl5/perllocal.pod \ usr/share/perl5/vendor_perl/perllocal.pod \ etc/passwd \ etc/passwd.new \ etc/shadow \ etc/shadow.new \ etc/group \ etc/group.new \ etc/gshadow \ etc/gshadow.new \ etc/ld.so.conf" ####################################################################### # include 'hidden' files/dirs in * wildcard expansion. shopt -s dotglob dir_ok() { [ -d "$1" ] && \ [ "$( stat -c '%A %U %G' "$1" )" = "drwxr-xr-x root root" ] } dir_empty() { [ "$( find "$1" -mindepth 1 -maxdepth 1 )" = "" ] } warn_badperms() { warn "bad permissions/owner (should be 0755 root:root): $1" } if LANG=C echo "$PRGNAM" | grep -q [^-._+A-Za-z0-9]; then warn "package name has invalid characters, only A-Z, a-z, 0-9, - + . _ are allowed"; fi for i in *; do if [ ! -d "$i" ]; then warn "package root dir contains non-directory: $i" elif ! echo "$topleveldirs" | grep -q "\\<$i\\>"; then warn "package root dir contains non-standard directory: $i" elif ! dir_ok "$i"; then warn_badperms "$i" elif dir_empty "$i"; then warn "package contains empty top-level directory: $i" fi done for i in usr/*; do if [ -e "$i" ]; then case "$i" in *-slackware-linux) ;; # OK *) if ! echo "$usrdirs" | grep -q "\\<$( basename $i )\\>"; then warn "nonstandard directory in /usr: $i" fi ;; esac fi done for i in $requireddirs; do if [ ! -d "$i" ]; then warn "missing required directory: $i" elif ! dir_ok "$i"; then warn_badperms "$i" fi done for i in $baddirs; do if [ -d "$i" ]; then warn "forbidden directory exists: $i" elif [ -e "$i" ]; then warn "forbidden directory exists as a non-directory: $i" fi done # 20220414 bkw: don't complain about broken symlinks here, they get checked elsewhere. for i in $fileonlydirs; do [ -d "$i" ] || continue dir_ok "$i" || warn_badperms "$i" find_warnfiles "$i should only contain files, not:" \ -L "$i" -mindepth 1 -maxdepth 1 \! \( -type l -o -type f \) done for i in $bindirs; do [ -d "$i" ] || continue find_warnfiles "$i should only contain executable files, not:" \ -L "$i" -mindepth 1 -maxdepth 1 -type f \! -perm /0111 done for i in $nofiledirs; do [ -d "$i" ] || continue dir_ok "$i" || warn_badperms "$i" find_warnfiles "$i should only contain directories, not:" \ -L "$i" -mindepth 1 -maxdepth 1 \! -type d done if [ -z "$SLACKBUILD_MISSING_OK" ]; then for i in $requiredfiles; do [ -f "$i" ] || warn "missing required file: $i" done fi for i in $noexecdirs; do [ -d "$i" ] || continue find_warnfiles "$i should not contain files with executable permission:" \ "$i" -type f -a -perm /0111 done for i in $badfiles; do [ -e "$i" ] && warn "forbidden file: $i" done # 20220414 bkw: absolute symlinks used to be an error, but there are just # too many packages that use them. so only flag them if they're broken links. # 20230627 bkw: note absolute symlinks outside the package. used in my own # smc build, for instance. up to the human to decide whether it's a problem. find . -type l -lname '/*' | while read f; do target="$( readlink "$f" | sed 's,^/*,,' )" if [ ! -e "$target" ]; then if [ -e "/$target" ]; then ls -bld "$f" > .outlinks.$$ else ls -bld "$f" > .badlinks.$$ fi fi done if [ -s .badlinks.$$ ]; then warn "package contains broken absolute symlinks:" cat .badlinks.$$ fi if [ -s .outlinks.$$ ]; then note "package contains symlinks outside the package (which is OK, if intentional):" cat .outlinks.$$ fi rm -f .badlinks.$$ .outlinks.$$ find_warnfiles "package contains broken relative symlinks:" \ -L . -type l \! -lname '/*' # 20230320 bkw: empty directories. this isn't an error, just a note, and # we ignore any empty dirs under /var because lots of packages need these. # 20241008 bkw: ignore empty bin sbin usr/bin usr/sbin, these are caught below. find_warnfiles --note "package contains empty dirs, are these necessary?" \ . -type d -a -empty \ -a \! -path "./var/*" \ -a \! -path ./bin \ -a \! -path ./sbin \ -a \! -path ./usr/bin \ -a \! -path ./usr/sbin # 20241008 bkw: if any of /bin /sbin /usr/bin or /usr/sbin exists, they must # not be empty. for i in bin sbin usr/bin usr/sbin; do if [ -e $i -a -z "$( ls -bld $i/* 2>/dev/null )" ]; then warn "package contains empty $i directory, this is probably a bug in the script." fi done find_warnfiles "package contains files owned by UID/GID >= 1000" \ . \( -uid +999 -o -gid +999 \)