is_broken_symlink() fails to properly resolve e.g. $ROOT/etc/motd -> /var/run/motd $ROOT/var/run -> /run and reports a broken link even if $ROOT/run/motd exists.
Adds a canonicalize_path() method that does not only look for symlinks at the end of the path but also as intermediate parts. (does not properly handle /../, /./, //) This should fix about 30000 incorrect warnings on piatti. Signed-off-by: Andreas Beckmann <deb...@abeckmann.de> --- debian/changelog | 7 +++++++ piuparts.py | 21 ++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index 7842e04..52cd242 100644 --- a/debian/changelog +++ b/debian/changelog @@ -27,6 +27,13 @@ piuparts (0.42) UNRELEASED; urgency=low - Replace deprecated os.popen2 with subprocess.Popen. (Closes: #640646) - add some more logging. + [ Andreas Beckmann ] + * piuparts.py: + - Fix resolving absolute symlinks of intermediate directory components, + i.e. /var/run -> /run while checking /etc/motd -> /var/run/motd. + Solves about 30000 false positives of + 'Broken symlinks: /etc/motd -> /var/run/motd'. (Closes: #648784) + -- Holger Levsen <hol...@debian.org> Sun, 28 Aug 2011 09:50:12 +0200 piuparts (0.41) unstable; urgency=low diff --git a/piuparts.py b/piuparts.py index 5f015fe..1de475b 100644 --- a/piuparts.py +++ b/piuparts.py @@ -474,8 +474,8 @@ def make_metapackage(name, depends, conflicts): return os.path.join(tmpdir, name) + '.deb' -def is_broken_symlink(root, dirpath, filename): - """Is symlink dirpath+filename broken? +def canonicalize_path(root, pathname): + """Canonicalize a path name, simulating chroot at 'root'. When resolving the symlink, pretend (similar to chroot) that root is the root of the filesystem. Note that this does NOT work completely @@ -486,17 +486,32 @@ def is_broken_symlink(root, dirpath, filename): """ - pathname = os.path.join(dirpath, filename) + #print "CANONICALIZE: %s %s" % (root, pathname) i = 0 while os.path.islink(pathname): if i >= 10: # let's avoid infinite loops... return True i += 1 target = os.readlink(pathname) + #print "LINK: %s -> %s" % (pathname, target) if os.path.isabs(target): pathname = os.path.join(root, target[1:]) # Assume Unix filenames else: pathname = os.path.join(os.path.dirname(pathname), target) + #print "FOLLOW: %s" % pathname + (dn, bn) = os.path.split(pathname) + #print "DN: %s BN: %s" % (dn, bn) + if pathname != root and dn != root: + dn = canonicalize_path(root, dn) + pathname = os.path.join(dn, bn) + #print "RETURN: %s EXISTS: %s" % (pathname, os.path.exists(pathname)) + return pathname + + +def is_broken_symlink(root, dirpath, filename): + """Is symlink dirpath+filename broken?""" + + pathname = canonicalize_path(root, os.path.join(dirpath, filename)) # The symlink chain, if any, has now been resolved. Does the target # exist? -- 1.7.7.1 -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org