diff options
author | Bryn M. Reeves <bmr@redhat.com> | 2018-09-07 13:11:03 -0400 |
---|---|---|
committer | Bryn M. Reeves <bmr@redhat.com> | 2018-09-10 15:46:47 +0100 |
commit | 322f4a517ae336cc1443f9a399a0d15d45ec48b9 (patch) | |
tree | 9d295540adbe4be3b13ad85fb58021f0c8bc3e00 | |
parent | d84c1cd6dedf51a8ed7b1a511585c0ac2db0f083 (diff) | |
download | sos-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.py | 38 |
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) |