From 4dbba1371ada73ccf0bd1c05ebb3d161d3bd7d08 Mon Sep 17 00:00:00 2001 From: "Bryn M. Reeves" Date: Fri, 4 Jul 2014 14:29:11 +0100 Subject: [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 --- sos/archive.py | 10 ++++++++++ sos/plugins/__init__.py | 30 ++++++++++++++++++++++++++---- 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)) -- cgit