Hi Richard,
Thanks for going through it. You're right that it needed sending
differently, and the problem was worse than the format: Gmail sent it as
HTML, so the text part the BTS shows lost every tab and leading space and
could never have applied, and nothing was attached despite what I wrote.
Sorry about that.
Here it is again as three attached patches with DEP-3 headers, against
1:3.2.4~rc1-3.5. tiger has no Salsa repository and is still source format
1.0 without a patch system, so they apply in order with patch -p1. They
also apply to the debian branch on Savannah, and would go into
debian/patches as they are. Only systems/Linux/2 changes: Linux/3 and
Linux/4 are symlinks to it, not copies as I said before.
0001 is the fix itself: the symlink test now looks at "${dir%/}", so /bin
rather than /bin/. On trixie and sid that alone is enough, because packages
there list their files under /usr.
0002 quotes the file name given to dpkg -S.
0003 handles packages that still list /bin or /sbin paths: bookworm, Ubuntu
24.04, and older or third-party packages anywhere.
On your points:
1. The header comment and the which/command -v change are gone. The second
only touched a comment and had no business in this patch.
2. Quoting: every variable the patches touch is quoted now. Looking at that
turned up a real bug, which is 0002. With Tiger_DPKG_Optimize=N the
unquoted $file in "$DPKG -S $file" split a name with a space into two
patterns, so a stray "/usr/bin/x file" was looked up as "/usr/bin/x" and
"file", the second matched packaged paths, and the stray file was not
reported.
3. /lib and the other usrmerge paths: ${file#/usr} stripped /usr from any
path, so /usr/lib/foo would have been retried as /lib/foo. But your
question showed me a worse problem: in the dpkg -S lookup the retry ran
whether or not /usr was merged. On an unmerged system a stray /usr/bin/su
beside the packaged /bin/su counted as owned, and that is exactly the file
this check exists to catch, since /usr/bin comes before /bin in PATH. 0003
now takes each of bin, sbin, lib, lib32, lib64, libo32 and libx32, counts
it as aliased only when /X is a symlink to the same directory as /usr/X,
and rewrites or retries only those. The lib directories never reach the
lookup in practice (/usr/lib is not scanned, per the NOTE in the script,
and /lib is skipped as a symlink), but one rule for all of them is simpler
than a list of exceptions.
4. Adding the second temporary file, I found the dpkg -S path never deleted
the first one, and while dpkg-packages.list is left in the work directory
safe_temp refuses to run the check again (init009e). Both are now deleted
after either lookup.
Testing: each release's own tiger package in a fresh container, with a
stray /usr/sbin/stray-test and a stray "/usr/bin/x file" added (and on
bullseye a copy of /bin/su as /usr/bin/su), then the check run with
Tiger_DPKG_Optimize=Y and with N. lin001w warnings with Y:
sid: 1,884 before, 3 after
trixie: 1,876 before, 3 after
bookworm: 1,765 before, 3 after
Ubuntu 24.04: 1,905 before, 3 after
Ubuntu 20.04, which also has lib32 and libx32 links: 1,805 before, 3 after
bullseye, not merged: 4 before, 4 after
The three are the two stray files and Docker's own /usr/sbin/policy-rc.d;
on bullseye the fourth is /usr/bin/su. With N the patched check reports
exactly the same. My first version missed the file with a space there, and
on bullseye /usr/bin/su as well. checkbashisms is clean, and ShellCheck's
only new warning is for test -ef, which dash supports.
On whether anyone is looking: every upload since September 2020 has been an
NMU, so I've kept these small enough for one. If a debdiff would help
whoever uploads, I can send one.
Andrei Trimbitas
Description: deb_nopackfiles: do not scan through the merged-/usr links
The check skips directories that are symbolic links, but it tested the
dirlist entries as written, and with the trailing slash "[ -L /bin/ ]"
follows the link and is false. On a merged-/usr system the check
therefore scanned /bin, /sbin and /lib as well as /usr/bin and /usr/sbin,
and through /lib all of /usr/lib, which it deliberately leaves out: 1,884
lin001w warnings in a fresh sid container.
.
On trixie and sid this alone fixes the bug, since packages there list
their files under /usr.
Author: Andrei Trimbitas <[email protected]>
Bug-Debian: https://bugs.debian.org/1111306
Forwarded: no
Last-Update: 2026-10-29
---
diff --git a/systems/Linux/2/deb_nopackfiles b/systems/Linux/2/deb_nopackfiles
index a4cbb79..8b3b594 100755
--- a/systems/Linux/2/deb_nopackfiles
+++ b/systems/Linux/2/deb_nopackfiles
@@ -118,7 +118,7 @@ dirlist="/bin/ /usr/bin/ /sbin/ /usr/sbin/ /lib/ /usr/X11R6/bin"
okdirs=""
# Before using dirlist we are going to determine which values are ok
for dir in $dirlist ; do
- if [ -d $dir ] && [ ! -L $dir ] ; then
+ if [ -d "$dir" ] && [ ! -L "${dir%/}" ] ; then
if [ -n "$okdirs" ] ; then
okdirs="$dir $okdirs"
else
Description: deb_nopackfiles: quote the file name given to dpkg -S
With Tiger_DPKG_Optimize=N a name with a space was split into two
patterns: a stray "/usr/bin/x file" became "/usr/bin/x" and "file",
dpkg -S matched "file" against packaged paths, and the stray file was
not reported.
Author: Andrei Trimbitas <[email protected]>
Forwarded: no
Last-Update: 2026-10-29
---
diff --git a/systems/Linux/2/deb_nopackfiles b/systems/Linux/2/deb_nopackfiles
index 8b3b594..3202635 100755
--- a/systems/Linux/2/deb_nopackfiles
+++ b/systems/Linux/2/deb_nopackfiles
@@ -140,7 +140,7 @@ then
# We are not using -maxdepth here, but we could...
while read file
do
- pack=`$DPKG -S $file 2>/dev/null`
+ pack=`$DPKG -S "$file" 2>/dev/null`
[ "$pack" = "" ] && {
message WARN lin001w "" "File \`$file' does not belong to any package."
}
Description: deb_nopackfiles: accept files dpkg lists under their aliased name
Packages built before the move to /usr list their files as /bin/foo or
/sbin/foo, and on a merged-/usr system the check finds them as
/usr/bin/foo. With only the first patch that still leaves 125 false
lin001w warnings on bookworm and 11 on Ubuntu 24.04, and on newer
releases the same happens for any older or third-party package.
.
For each of /bin, /sbin, /lib, /lib32, /lib64, /libo32 and /libx32 that
is a symbolic link to the same directory under /usr, the optimised lookup
rewrites the package lists and the diversions to the /usr name, and the
dpkg -S lookup also tries the aliased name. Where /usr is not merged
nothing is rewritten and there is no second lookup, so a stray
/usr/bin/su beside the packaged /bin/su is still reported.
.
The temporary files are now deleted after either lookup: the dpkg -S
lookup never deleted dpkg-packages.list, and while it exists safe_temp
refuses to run the check again (init009e).
Author: Andrei Trimbitas <[email protected]>
Bug-Debian: https://bugs.debian.org/1111306
Forwarded: no
Last-Update: 2026-10-29
---
diff --git a/systems/Linux/2/deb_nopackfiles b/systems/Linux/2/deb_nopackfiles
index 3202635..e999244 100755
--- a/systems/Linux/2/deb_nopackfiles
+++ b/systems/Linux/2/deb_nopackfiles
@@ -108,8 +108,8 @@ then
haveallcmds DPKG || exit 1
fi
-safe_temp $WORKDIR/dpkg-packages.list
-trap 'delete $WORKDIR/dpkg-packages.list ; exit 1' 1 2 3 15
+safe_temp $WORKDIR/dpkg-packages.list $WORKDIR/dpkg-diversions.list
+trap 'delete $WORKDIR/dpkg-packages.list $WORKDIR/dpkg-diversions.list ; exit 1' 1 2 3 15
# NOTE: /usr/lib cannot be added here since quite a lot of packages
# will compile stuff there on installation which will result in a
@@ -132,6 +132,16 @@ if [ -z "$dirlist" ]; then
exit 1
fi
+# On merged-/usr systems /bin, /sbin, /lib and the other aliased
+# directories are symbolic links into /usr, and dpkg may have recorded
+# a file under either name
+aliased=""
+for dir in bin sbin lib lib32 lib64 libo32 libx32 ; do
+ if [ -L "/$dir" ] && [ "/$dir" -ef "/usr/$dir" ] ; then
+ aliased="$aliased $dir"
+ fi
+done
+
# We have two options here, use dpkg (non-optimal but on the safe side)
# or use grep (optimal but not on the safe side)
if [ "$Tiger_DPKG_Optimize" = "N" ]
@@ -141,6 +151,15 @@ then
while read file
do
pack=`$DPKG -S "$file" 2>/dev/null`
+ # dpkg may list it by its aliased name, /bin/foo
+ if [ "$pack" = "" ] ; then
+ for dir in $aliased ; do
+ case $file in
+ /usr/$dir/*)
+ pack=`$DPKG -S "${file#/usr}" 2>/dev/null` ;;
+ esac
+ done
+ fi
[ "$pack" = "" ] && {
message WARN lin001w "" "File \`$file' does not belong to any package."
}
@@ -148,18 +167,24 @@ then
else
# Alternative (optimal but not following standard way)
seddirlist=`echo $dirlist | $SED -e 's/ /\\\\\|/g; s/\//\\\\\//g'`
+ # Give files recorded under an aliased name, /bin/foo, their /usr name
+ usrmerge=""
+ for dir in $aliased ; do
+ usrmerge="$usrmerge -e s,^/$dir/,/usr/$dir/,"
+ done
$FIND /var/lib/dpkg/info -name "*.list" -exec cat {} \; |
- $SED -ne "/^\($seddirlist\)/p" > $WORKDIR/dpkg-packages.list
+ $SED -n $usrmerge -e "/^\($seddirlist\)/p" > $WORKDIR/dpkg-packages.list
+ $SED -e '' $usrmerge /var/lib/dpkg/diversions > $WORKDIR/dpkg-diversions.list
$FIND $dirlist -type f 2>/dev/null |
# We are not using -maxdepth here, but we could...
$GREP -x -F -v -f $WORKDIR/dpkg-packages.list |
# To search for diversions
- $GREP -x -F -v -f /var/lib/dpkg/diversions |
+ $GREP -x -F -v -f $WORKDIR/dpkg-diversions.list |
while read file
do
message WARN lin001w "" "File \`$file' does not belong to any package."
done
- delete $WORKDIR/dpkg-packages.list
fi
+delete $WORKDIR/dpkg-packages.list $WORKDIR/dpkg-diversions.list
exit 0