Blame SOURCES/0015-plugin-limit-names-to-PC_NAME_MAX.patch

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