aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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))