core: optimize PrivilegeHelper::runElevated()

Using std::function is overkill

Change-Id: I0e60592aea1b2fb82c3ea780701dae5e129a9810
diff --git a/core/privilege-helper.cpp b/core/privilege-helper.cpp
index b0ca116..edc8336 100644
--- a/core/privilege-helper.cpp
+++ b/core/privilege-helper.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017,  Regents of the University of California,
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -29,8 +29,6 @@
 #include <pwd.h>
 #include <grp.h>
 
-#include <sstream>
-
 namespace nfd {
 
 NFD_LOG_INIT("PrivilegeHelper");
@@ -58,80 +56,63 @@
 
   // workflow from man getpwnam_r
 
-  if (!groupName.empty())
-    {
-      static int groupSize = ::sysconf(_SC_GETGR_R_SIZE_MAX);
+  if (!groupName.empty()) {
+    static long groupSize = ::sysconf(_SC_GETGR_R_SIZE_MAX);
 
-      if (groupSize == -1)
-        {
-          groupSize = FALLBACK_GROUP_BUFFER_SIZE;
-        }
+    if (groupSize == -1)
+      groupSize = FALLBACK_GROUP_BUFFER_SIZE;
 
-      std::vector<char> groupBuffer(groupSize);
-      struct group group;
-      struct group* groupResult = 0;
+    std::vector<char> groupBuffer(groupSize);
+    struct group group;
+    struct group* groupResult = nullptr;
 
-      int errorCode = getgrnam_r(groupName.c_str(), &group,
-                                 &groupBuffer[0], groupSize, &groupResult);
+    int errorCode = getgrnam_r(groupName.data(), &group,
+                               &groupBuffer[0], groupBuffer.size(), &groupResult);
 
-      while (errorCode == ERANGE)
-        {
-          if (groupBuffer.size() * 2 > MAX_GROUP_BUFFER_SIZE)
-            {
-              throw PrivilegeHelper::Error("Cannot allocate large enough buffer for struct group");
-            }
+    while (errorCode == ERANGE) {
+      if (groupBuffer.size() * 2 > MAX_GROUP_BUFFER_SIZE)
+        throw Error("Cannot allocate large enough buffer for struct group");
 
-          groupBuffer.resize(groupBuffer.size() * 2);
+      groupBuffer.resize(groupBuffer.size() * 2);
 
-          errorCode = getgrnam_r(groupName.c_str(), &group,
-                                 &groupBuffer[0], groupBuffer.size(), &groupResult);
-        }
-
-      if (errorCode != 0 || !groupResult)
-        {
-          throw PrivilegeHelper::Error("Failed to get gid for \"" + groupName + "\"");
-        }
-
-      s_normalGid = group.gr_gid;
+      errorCode = getgrnam_r(groupName.data(), &group,
+                             &groupBuffer[0], groupBuffer.size(), &groupResult);
     }
 
-  if (!userName.empty())
-    {
-      static int passwdSize = ::sysconf(_SC_GETPW_R_SIZE_MAX);
+    if (errorCode != 0 || !groupResult)
+      throw Error("Failed to get gid for \"" + groupName + "\"");
 
-      if (passwdSize == -1)
-        {
-          passwdSize = FALLBACK_PASSWD_BUFFER_SIZE;
-        }
+    s_normalGid = group.gr_gid;
+  }
 
-      std::vector<char> passwdBuffer(passwdSize);
-      struct passwd passwd;
-      struct passwd* passwdResult = 0;
+  if (!userName.empty()) {
+    static long passwdSize = ::sysconf(_SC_GETPW_R_SIZE_MAX);
 
-      int errorCode =
-        getpwnam_r(userName.c_str(), &passwd,
-                   &passwdBuffer[0], passwdBuffer.size(), &passwdResult);
+    if (passwdSize == -1)
+      passwdSize = FALLBACK_PASSWD_BUFFER_SIZE;
 
-      while (errorCode == ERANGE)
-        {
-          if (passwdBuffer.size() * 2 > MAX_PASSWD_BUFFER_SIZE)
-            {
-              throw PrivilegeHelper::Error("Cannot allocate large enough buffer for struct passwd");
-            }
+    std::vector<char> passwdBuffer(passwdSize);
+    struct passwd passwd;
+    struct passwd* passwdResult = nullptr;
 
-          passwdBuffer.resize(passwdBuffer.size() * 2);
+    int errorCode = getpwnam_r(userName.data(), &passwd,
+                               &passwdBuffer[0], passwdBuffer.size(), &passwdResult);
 
-          errorCode = getpwnam_r(userName.c_str(), &passwd,
-                                 &passwdBuffer[0], passwdBuffer.size(), &passwdResult);
-        }
+    while (errorCode == ERANGE) {
+      if (passwdBuffer.size() * 2 > MAX_PASSWD_BUFFER_SIZE)
+        throw Error("Cannot allocate large enough buffer for struct passwd");
 
-      if (errorCode != 0 || !passwdResult)
-        {
-          throw PrivilegeHelper::Error("Failed to get uid for \"" + userName + "\"");
-        }
+      passwdBuffer.resize(passwdBuffer.size() * 2);
 
-      s_normalUid = passwd.pw_uid;
+      errorCode = getpwnam_r(userName.data(), &passwd,
+                             &passwdBuffer[0], passwdBuffer.size(), &passwdResult);
     }
+
+    if (errorCode != 0 || !passwdResult)
+      throw Error("Failed to get uid for \"" + userName + "\"");
+
+    s_normalUid = passwd.pw_uid;
+  }
 #else
   if (!userName.empty() || !groupName.empty()) {
     throw Error("Dropping and raising privileges is not supported on this platform");
@@ -145,21 +126,11 @@
 #ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
   NFD_LOG_TRACE("dropping to effective gid=" << s_normalGid);
   if (::setegid(s_normalGid) != 0)
-    {
-      std::stringstream error;
-      error << "Failed to drop to effective gid=" << s_normalGid;
-
-      throw PrivilegeHelper::Error(error.str());
-    }
+    throw Error("Failed to drop to effective gid=" + to_string(s_normalGid));
 
   NFD_LOG_TRACE("dropping to effective uid=" << s_normalUid);
   if (::seteuid(s_normalUid) != 0)
-    {
-      std::stringstream error;
-      error << "Failed to drop to effective uid=" << s_normalUid;
-
-      throw PrivilegeHelper::Error(error.str());
-    }
+    throw Error("Failed to drop to effective uid=" + to_string(s_normalUid));
 
   NFD_LOG_INFO("dropped to effective uid=" << ::geteuid() << " gid=" << ::getegid());
 #else
@@ -173,42 +144,16 @@
 #ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
   NFD_LOG_TRACE("elevating to effective uid=" << s_privilegedUid);
   if (::seteuid(s_privilegedUid) != 0)
-    {
-      std::stringstream error;
-      error << "Failed to elevate to effective uid=" << s_privilegedUid;
-
-      throw PrivilegeHelper::Error(error.str());
-    }
+    throw Error("Failed to elevate to effective uid=" + to_string(s_privilegedUid));
 
   NFD_LOG_TRACE("elevating to effective gid=" << s_privilegedGid);
   if (::setegid(s_privilegedGid) != 0)
-    {
-      std::stringstream error;
-      error << "Failed to elevate to effective gid=" << s_privilegedGid;
+    throw Error("Failed to elevate to effective gid=" + to_string(s_privilegedGid));
 
-      throw PrivilegeHelper::Error(error.str());
-    }
   NFD_LOG_INFO("elevated to effective uid=" << ::geteuid() << " gid=" << ::getegid());
 #else
   NFD_LOG_WARN("Elevating privileges is not supported on this platform");
 #endif // HAVE_PRIVILEGE_DROP_AND_ELEVATE
 }
 
-void
-PrivilegeHelper::runElevated(function<void()> f)
-{
-  raise();
-
-  try
-    {
-      f();
-    }
-  catch (...)
-    {
-      drop();
-      throw;
-    }
-  drop();
-}
-
 } // namespace nfd
diff --git a/core/privilege-helper.hpp b/core/privilege-helper.hpp
index 7ddbafc..bbf08e2 100644
--- a/core/privilege-helper.hpp
+++ b/core/privilege-helper.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2015,  Regents of the University of California,
+/*
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -35,7 +35,6 @@
 class PrivilegeHelper
 {
 public:
-
   /** \brief represents a serious seteuid/gid failure
    *
    *  This should only be caught by main as part of a graceful program termination.
@@ -53,7 +52,7 @@
     const char*
     what() const
     {
-      return m_whatMessage.c_str();
+      return m_whatMessage.data();
     }
 
   private:
@@ -66,11 +65,22 @@
   static void
   drop();
 
+  template<class F>
   static void
-  runElevated(function<void()> f);
+  runElevated(F&& f)
+  {
+    raise();
+    try {
+      f();
+    }
+    catch (...) {
+      drop();
+      throw;
+    }
+    drop();
+  }
 
 PUBLIC_WITH_TESTS_ELSE_PRIVATE:
-
   static void
   raise();