aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBryn M. Reeves <bmr@redhat.com>2018-09-07 13:11:03 -0400
committerBryn M. Reeves <bmr@redhat.com>2018-09-10 15:46:47 +0100
commit322f4a517ae336cc1443f9a399a0d15d45ec48b9 (patch)
tree9d295540adbe4be3b13ad85fb58021f0c8bc3e00
parentd84c1cd6dedf51a8ed7b1a511585c0ac2db0f083 (diff)
downloadsos-322f4a517ae336cc1443f9a399a0d15d45ec48b9.tar.gz
[archive] add link follow-up to FileCacheArchive.add_link()
Creating a link may trigger further actions in the archive: if the link target is a regular file, we must copy that file into the archive, and if the target is a symbolic link, then we must create that link, and copy in the link target. Handle this by calling add_file() or (recursively) add_link() in order to create the missing pieces of the symlink chain. These operations must take place outside of the path lock since they do not modify the archive namespace and will call methods of the Archive object that will attempt to re-acquire this lock. Resolves: #1404 Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
-rw-r--r--sos/archive.py38
1 files changed, 35 insertions, 3 deletions
diff --git a/sos/archive.py b/sos/archive.py
index c256a01f..6db398fc 100644
--- a/sos/archive.py
+++ b/sos/archive.py
@@ -403,6 +403,7 @@ class FileCacheArchive(Archive):
% (dest, self._archive_root))
def add_link(self, source, link_name):
+ self.log_debug("adding symlink at '%s' -> '%s'" % (link_name, source))
with self._path_lock:
dest = self._check_path(link_name, P_LINK)
if not dest:
@@ -410,10 +411,41 @@ class FileCacheArchive(Archive):
if not os.path.lexists(dest):
os.symlink(source, dest)
- self.log_debug("added symlink at '%s' to '%s' in archive '%s'"
- % (dest, source, self._archive_root))
+ self.log_debug("added symlink at '%s' to '%s' in archive '%s'"
+ % (dest, source, self._archive_root))
+
+ # Follow-up must be outside the path lock: we recurse into
+ # other monitor methods that will attempt to reacquire it.
+
+ source_dir = os.path.dirname(link_name)
+ host_source = os.path.join(source_dir, source)
+ if not os.path.exists(self.dest_path(host_source)):
+ if os.path.islink(host_source):
+ link_dir = os.path.dirname(link_name)
+ link_name = os.path.normpath(os.path.join(link_dir, source))
+ dest_dir = os.path.dirname(link_name)
+ source = os.path.join(dest_dir, os.readlink(link_name))
+ source = os.path.relpath(source)
+ self.log_debug("Adding link %s -> %s for link follow up" %
+ (link_name, source))
+ self.add_link(source, link_path)
+ elif os.path.isdir(host_source):
+ self.log_debug("Adding dir %s for link follow up" % source)
+ self.add_dir(host_source)
+ elif os.path.isfile(host_source):
+ self.log_debug("Adding file %s for link follow up" % source)
+ self.add_file(host_source)
+ else:
+ self.log_debug("No link follow up: source=%s link_name=%s" %
+ (source, link_name))
- def add_dir(self, path):
+
+ def add_dir(self, path, copy=False):
+ """Create a directory in the archive.
+
+ :param path: the path in the host file system to add
+ """
+ # Establish path structure
with self._path_lock:
self._check_path(path, P_DIR)