Blame SOURCES/sos-bz1026962-plugin-limit-names-to-pc_name_max.patch

e75bc7
From 48a99c95078bab306cb56bb1a05420d88bf15a64 Mon Sep 17 00:00:00 2001
e75bc7
From: "Bryn M. Reeves" <bmr@redhat.com>
e75bc7
Date: Mon, 20 Oct 2014 16:12:01 +0100
e75bc7
Subject: [PATCH] [plugin] limit names to PC_NAME_MAX
e75bc7
e75bc7
Commit 8bf7b0c removed the truncation of mangled command names to
e75bc7
64 chars. This causes problems for some plugins (e.g. Issue #415)
e75bc7
that generate long enough command lines to hit system name length
e75bc7
limits.
e75bc7
e75bc7
Instead of arbitrarily limiting to 64 characters limit to the
e75bc7
lesser of the archive format limit (if present) or the value of
e75bc7
PC_NAME_MAX for any intermediate FileCacheArchive path.
e75bc7
e75bc7
Signed-off-by: Bryn M. Reeves <bmr@redhat.com>
e75bc7
---
e75bc7
 sos/archive.py          | 18 ++++++++++++++++++
e75bc7
 sos/plugins/__init__.py |  7 ++++---
e75bc7
 tests/plugin_tests.py   | 12 ++++++++----
e75bc7
 3 files changed, 30 insertions(+), 7 deletions(-)
e75bc7
e75bc7
diff --git a/sos/archive.py b/sos/archive.py
e75bc7
index 2e42bbd..6063625 100644
e75bc7
--- a/sos/archive.py
e75bc7
+++ b/sos/archive.py
e75bc7
@@ -98,6 +98,12 @@ class Archive(object):
e75bc7
         to be included in the generated archive."""
e75bc7
         raise NotImplementedError
e75bc7
 
e75bc7
+    def name_max(self):
e75bc7
+        """Return the maximum file name length this archive can support.
e75bc7
+        This is the lesser of the name length limit of the archive
e75bc7
+        format and any temporary file system based cache."""
e75bc7
+        raise NotImplementedError
e75bc7
+
e75bc7
     def get_archive_path(self):
e75bc7
         """Return a string representing the path to the temporary
e75bc7
         archive. For archive classes that implement in-line handling
e75bc7
@@ -206,6 +212,13 @@ class FileCacheArchive(Archive):
e75bc7
     def _makedirs(self, path, mode=0o700):
e75bc7
         os.makedirs(path, mode)
e75bc7
 
e75bc7
+    def name_max(self):
e75bc7
+        if 'PC_NAME_MAX' in os.pathconf_names:
e75bc7
+            pc_name_max = os.pathconf_names['PC_NAME_MAX']
e75bc7
+            return os.pathconf(self._archive_root, pc_name_max)
e75bc7
+        else:
e75bc7
+            return 255
e75bc7
+
e75bc7
     def get_tmp_dir(self):
e75bc7
         return self._archive_root
e75bc7
 
e75bc7
@@ -355,6 +368,11 @@ class TarFileArchive(FileCacheArchive):
e75bc7
     def name(self):
e75bc7
         return "%s.%s" % (self._name, self._suffix)
e75bc7
 
e75bc7
+    def name_max(self):
e75bc7
+        # GNU Tar format supports unlimited file name length. Just return
e75bc7
+        # the limit of the underlying FileCacheArchive.
e75bc7
+        return super(TarFileArchive, self).name_max()
e75bc7
+
e75bc7
     def _build_archive(self):
e75bc7
         # python2.6 TarFile lacks the filter parameter
e75bc7
         if not six.PY3 and sys.version_info[1] < 7:
e75bc7
diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py
e75bc7
index 3e39100..b289144 100644
e75bc7
--- a/sos/plugins/__init__.py
e75bc7
+++ b/sos/plugins/__init__.py
e75bc7
@@ -42,11 +42,11 @@ def regex_findall(regex, fname):
e75bc7
         return []
e75bc7
 
e75bc7
 
e75bc7
-def _mangle_command(command):
e75bc7
-    # FIXME: this can be improved
e75bc7
+def _mangle_command(command, name_max):
e75bc7
     mangledname = re.sub(r"^/(usr/|)(bin|sbin)/", "", command)
e75bc7
     mangledname = re.sub(r"[^\w\-\.\/]+", "_", mangledname)
e75bc7
     mangledname = re.sub(r"/", ".", mangledname).strip(" ._-")
e75bc7
+    mangledname = mangledname[0:name_max]
e75bc7
     return mangledname
e75bc7
 
e75bc7
 
e75bc7
@@ -518,7 +518,8 @@ class Plugin(object):
e75bc7
         return grep(regexp, *fnames)
e75bc7
 
e75bc7
     def _mangle_command(self, exe):
e75bc7
-        return _mangle_command(exe)
e75bc7
+        name_max = self.archive.name_max()
e75bc7
+        return _mangle_command(exe, name_max)
e75bc7
 
e75bc7
     def _make_command_filename(self, exe):
e75bc7
         """The internal function to build up a filename based on a command."""
e75bc7
diff --git a/tests/plugin_tests.py b/tests/plugin_tests.py
e75bc7
index 817e4f2..f73a003 100644
e75bc7
--- a/tests/plugin_tests.py
e75bc7
+++ b/tests/plugin_tests.py
e75bc7
@@ -115,10 +115,14 @@ class PluginToolTests(unittest.TestCase):
e75bc7
         self.assertEquals(matches, [])
e75bc7
 
e75bc7
     def test_mangle_command(self):
e75bc7
-        self.assertEquals("foo", _mangle_command("/usr/bin/foo"))
e75bc7
-        self.assertEquals("foo_-x", _mangle_command("/usr/bin/foo -x"))
e75bc7
-        self.assertEquals("foo_--verbose", _mangle_command("/usr/bin/foo --verbose"))
e75bc7
-        self.assertEquals("foo_.path.to.stuff", _mangle_command("/usr/bin/foo /path/to/stuff"))
e75bc7
+        name_max = 255
e75bc7
+        self.assertEquals("foo", _mangle_command("/usr/bin/foo", name_max))
e75bc7
+        self.assertEquals("foo_-x", _mangle_command("/usr/bin/foo -x", name_max))
e75bc7
+        self.assertEquals("foo_--verbose", _mangle_command("/usr/bin/foo --verbose", name_max))
e75bc7
+        self.assertEquals("foo_.path.to.stuff", _mangle_command("/usr/bin/foo /path/to/stuff", name_max))
e75bc7
+        longcmd ="foo is " + "a" * 256 + " long_command"
e75bc7
+        expected = longcmd[0:name_max].replace(' ', '_')
e75bc7
+        self.assertEquals(expected, _mangle_command(longcmd, name_max))
e75bc7
 
e75bc7
 
e75bc7
 class PluginTests(unittest.TestCase):
e75bc7
-- 
e75bc7
1.9.3
e75bc7