[Piuparts-devel] Bug#648784: [PATCH 2/2] fix symlink resolution inside paths

Andreas Beckmann debian at abeckmann.de
Wed Nov 16 03:24:34 UTC 2011


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 <debian at 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 <holger at 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






More information about the Piuparts-devel mailing list