From cc5313646f61a5272073bfac012e7bf6c1367311 Mon Sep 17 00:00:00 2001 From: "Bryn M. Reeves" Date: Fri, 30 Nov 2012 16:55:15 +0000 Subject: Fix symlink handling in doCopyFileOrDir() Symlinks need special treatment when we're copying them into the report. The target path stored in the report must always be relative but we need to pass an absolute path for the target to the recursive doCopyFileOrDir() call that picks up the target for us. There are further problems with the current code but these cannot be fixed trivially: symbolic links to directories are currently ignored but are fundamental to the layout of file systems like sys (and to a lesser extent proc). Supporting this properly requires an algorithm that can cope with arbitrary symlink loops in the tree being copied and that correctly copies-in any links that may point outside of the tree currently being copied. See Issues #71, #72 for more details. --- sos/plugins/__init__.py | 49 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py index edd7b73e..63adc94c 100644 --- a/sos/plugins/__init__.py +++ b/sos/plugins/__init__.py @@ -196,31 +196,50 @@ class Plugin(object): return False def copy_symlink(self, srcpath, sub=None): - link = os.readlink(srcpath) - if not os.path.isabs(link): - link = os.path.normpath( - os.path.join( - os.path.dirname(srcpath), - link) - ) - - if os.path.isdir(link): - self.soslog.debug("link %s is a directory, skipping..." % link) + # the target stored in the original symlink + linkdest = os.readlink(srcpath) + self.soslog.debug("copying link %s pointing to %s with sub=%s" + % (srcpath, linkdest, sub)) + + if os.path.isdir(linkdest): + self.soslog.debug("link %s is a directory, skipping..." + % linkdest) return - dest = link + # adjust the target used inside the report to always be relative + if os.path.isabs(linkdest): + adjdest = os.path.relpath(linkdest, + os.path.dirname(srcpath)) + self.soslog.debug("made link target %s relative as %s" + % (linkdest, adjdest)) + else: + adjdest = linkdest if sub: old, new = sub - dest = srcpath.replace(old, new) + adjdest = srcpath.replace(old, new) + + self.archive.add_link(adjdest,srcpath) + + # copy the symlink target translating relative targets + # to absolute paths to pass to doCopyFileOrDir. + self.soslog.debug("copying target %s for link %s" + % (linkdest, srcpath)) - self.archive.add_file(link, dest=dest) + if(os.path.isabs(linkdest)): + self.doCopyFileOrDir(linkdest) + else: + absdest = os.path.normpath(os.path.join( + os.path.dirname(srcpath), linkdest)) + self.soslog.debug("normalized link target %s as %s" + %(linkdest, absdest)) + self.doCopyFileOrDir(absdest) self.copiedFiles.append({ 'srcpath':srcpath, - 'dstpath':dest, + 'dstpath':srcpath, 'symlink':"yes", - 'pointsto':link}) + 'pointsto':linkdest}) def copy_dir(self, srcpath, sub=None): for afile in os.listdir(srcpath): -- cgit