aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBryn M. Reeves <bmr@redhat.com>2014-07-04 14:29:11 +0100
committerBryn M. Reeves <bmr@redhat.com>2014-07-04 14:45:34 +0100
commit4dbba1371ada73ccf0bd1c05ebb3d161d3bd7d08 (patch)
treeb1b57623a0b35b6ee1219260c28a10f59b28928e
parent65c47f29b469f4b622dea4f01bbc3931fce8450f (diff)
downloadsos-4dbba1371ada73ccf0bd1c05ebb3d161d3bd7d08.tar.gz
[archive, plugin] handle special file system nodes
Historically sos has ignored all types of file system node that are not regular files or directories. Add support for collecting block, character, fifo and socket special nodes by creating matching nodes in the archive and propagating permissions from the host file system. Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
-rw-r--r--sos/archive.py10
-rw-r--r--sos/plugins/__init__.py30
2 files changed, 36 insertions, 4 deletions
diff --git a/sos/archive.py b/sos/archive.py
index bfc8a120..c38e5f64 100644
--- a/sos/archive.py
+++ b/sos/archive.py
@@ -79,6 +79,9 @@ class Archive(object):
def add_dir(self, path):
raise NotImplementedError
+ def add_node(self, path, mode, device):
+ raise NotImplementedError
+
def get_tmp_dir(self):
"""Return a temporary directory that clients of the archive may
use to write content to. The content of the path is guaranteed
@@ -180,6 +183,13 @@ class FileCacheArchive(Archive):
def add_dir(self, path):
self.makedirs(path)
+ def add_node(self, path, mode, device):
+ dest = self.dest_path(path)
+ self._check_path(dest)
+ if not os.path.exists(dest):
+ os.mknod(dest, mode, device)
+ shutil.copystat(path, dest)
+
def _makedirs(self, path, mode=0o700):
os.makedirs(path, mode)
diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py
index eac78153..4c34bda9 100644
--- a/sos/plugins/__init__.py
+++ b/sos/plugins/__init__.py
@@ -63,6 +63,20 @@ def mangle_command(command):
def _path_in_path_list(path, path_list):
return any(p in path for p in path_list)
+def _node_type(st):
+ """ return a string indicating the type of special node represented by
+ the stat buffer st (block, character, fifo, socket).
+ """
+ _types = [
+ ( stat.S_ISBLK, "block device" ),
+ ( stat.S_ISCHR, "character device" ),
+ ( stat.S_ISFIFO, "named pipe" ),
+ ( stat.S_ISSOCK, "socket" )
+ ]
+ for t in _types:
+ if t[0](st.st_mode):
+ return t[1]
+
class Plugin(object):
""" This is the base class for sosreport plugins. Plugins should subclass
this and set the class variables where applicable.
@@ -276,6 +290,12 @@ class Plugin(object):
def is_forbidden_path(self, path):
return _path_in_path_list(path, self.forbidden_paths)
+ def copy_node(self, path, st):
+ dev_maj = os.major(st.st_rdev)
+ dev_min = os.minor(st.st_rdev)
+ mode = st.st_mode
+ self.archive.add_node(path, mode, os.makedev(dev_maj, dev_min))
+
# Methods for copying files and shelling out
def do_copy_path(self, srcpath, dest=None):
# pylint: disable-msg = R0912
@@ -305,10 +325,12 @@ class Plugin(object):
self.copy_dir(srcpath)
return
- # filter out device nodes
- if stat.S_ISBLK(st.st_mode) or stat.S_ISCHR(st.st_mode):
- devtype = "block" if stat.S_ISBLK(stat.st_mode) else "character"
- self.log_debug("skipping %s device node %s" % (devtype, srcpath))
+ # handle special nodes (block, char, fifo, socket)
+ if not (stat.S_ISREG(st.st_mode) or stat.S_ISDIR(st.st_mode)):
+ ntype = _node_type(st)
+ self.log_debug("creating %s node at archive:'%s'" % (ntype, srcpath))
+ self.copy_node(srcpath, st)
+ return
# if we get here, it's definitely a regular file (not a symlink or dir)
self.log_debug("copying path '%s' to archive:'%s'" % (srcpath,dest))