diff --git a/common/UserIdentity.cpp b/common/UserIdentity.cpp index c72c97b43024de4ab7748921d25c6f859ca01301..350523e4fdfd0114b9fbb7890f1f6a5b0a39b8cd 100644 --- a/common/UserIdentity.cpp +++ b/common/UserIdentity.cpp @@ -19,14 +19,15 @@ #include "common/UserIdentity.hpp" #include <limits> +#include <unistd.h> #include <ostream> //------------------------------------------------------------------------------ // constructor //------------------------------------------------------------------------------ cta::UserIdentity::UserIdentity() throw(): - uid(std::numeric_limits<decltype(uid)>::max()), - gid(std::numeric_limits<decltype(gid)>::max()) {} + uid(std::numeric_limits<uid_t>::max()), + gid(std::numeric_limits<gid_t>::max()) {} //------------------------------------------------------------------------------ // constructor diff --git a/common/Utils.cpp b/common/Utils.cpp index c6f2c0de1de5b543a5736bf0674bf6939e624d40..ba6368a5a65e63d1780663116be68d74836c76b3 100644 --- a/common/Utils.cpp +++ b/common/Utils.cpp @@ -21,6 +21,7 @@ #include "common/Utils.hpp" #include <attr/xattr.h> +#include <limits> #include <memory> #include <shift/serrno.h> #include <sstream> @@ -377,6 +378,78 @@ uint16_t cta::Utils::toUint16(const std::string &str) { return value; } +//------------------------------------------------------------------------------ +// toUid +//------------------------------------------------------------------------------ +uid_t cta::Utils::toUid(const std::string &str) { + if(str.empty()) { + std::ostringstream msg; + msg << "Failed to convert empty string to uid_t: An empty string is not" + " a valid uid_t value"; + throw exception::Exception(msg.str()); + } + + errno = 0; + const long int value = strtol(str.c_str(), (char **) NULL, 10); + const int savedErrno = errno; + if(savedErrno) { + std::ostringstream msg; + msg << "Failed to convert \'" << str << "' to uid_t: " << + errnoToString(savedErrno); + throw exception::Exception(msg.str()); + } + + if(0 > value) { + std::ostringstream msg; + msg << "Failed to convert \'" << str << "' to uid_t: Negative number"; + throw exception::Exception(msg.str()); + } + + if(std::numeric_limits<uid_t>::max() < value) { + std::ostringstream msg; + msg << "Failed to convert \'" << str << "' to uid_t: Number too big"; + throw exception::Exception(msg.str()); + } + + return value; +} + +//------------------------------------------------------------------------------ +// toGid +//------------------------------------------------------------------------------ +gid_t cta::Utils::toGid(const std::string &str) { + if(str.empty()) { + std::ostringstream msg; + msg << "Failed to convert empty string to gid_t: An empty string is not" + " a valid gid_t value"; + throw exception::Exception(msg.str()); + } + + errno = 0; + const long int value = strtol(str.c_str(), (char **) NULL, 10); + const int savedErrno = errno; + if(savedErrno) { + std::ostringstream msg; + msg << "Failed to convert \'" << str << "' to gid_t: " << + errnoToString(savedErrno); + throw exception::Exception(msg.str()); + } + + if(0 > value) { + std::ostringstream msg; + msg << "Failed to convert \'" << str << "' to gid_t: Negative number"; + throw exception::Exception(msg.str()); + } + + if(std::numeric_limits<gid_t>::max() < value) { + std::ostringstream msg; + msg << "Failed to convert \'" << str << "' to gid_t: Number too big"; + throw exception::Exception(msg.str()); + } + + return value; +} + //------------------------------------------------------------------------------ // isValidUInt //------------------------------------------------------------------------------ diff --git a/common/Utils.hpp b/common/Utils.hpp index 334ff1c6dc19c231458515729fd78731dab919ba..7d3bade4af8d20dd556c65ebd5d71050829dfc7a 100644 --- a/common/Utils.hpp +++ b/common/Utils.hpp @@ -21,6 +21,7 @@ #include <list> #include <sstream> #include <string> +#include <unistd.h> #include <vector> namespace cta { @@ -182,6 +183,22 @@ public: */ static uint16_t toUint16(const std::string &str); + /** + * Converts the specified string to a uid. + * + * @param str The string. + * @return The uid. + */ + static uid_t toUid(const std::string &str); + + /** + * Converts the specified string to a gid. + * + * @param str The string. + * @return The gid. + */ + static gid_t toGid(const std::string &str); + /** * Checks if the specified string is a valid unsigned integer. * diff --git a/common/UtilsTest.cpp b/common/UtilsTest.cpp index ec8dfcba26fc80f09dea46187b5baccbf03c0427..f1f8bb718492fa21e95fff3bd63986c9f0963696 100644 --- a/common/UtilsTest.cpp +++ b/common/UtilsTest.cpp @@ -275,7 +275,7 @@ TEST_F(cta_UtilsTest, errnoToString_EACCESS) { ASSERT_EQ(std::string("Permission denied"), str); } -TEST_F(cta_UtilsTest, toUint16_uint16_t) { +TEST_F(cta_UtilsTest, toUint16_12345) { using namespace cta; uint16_t i = 0; @@ -320,6 +320,114 @@ TEST_F(cta_UtilsTest, toUint16_too_big) { ASSERT_THROW(Utils::toUint16("65536"), std::exception); } +TEST_F(cta_UtilsTest, toUid_12345) { + using namespace cta; + + uid_t i = 0; + + ASSERT_NO_THROW(i = Utils::toUid("12345")); + ASSERT_EQ((uid_t)12345, i); +} + +TEST_F(cta_UtilsTest, toUid_zero) { + using namespace cta; + + uid_t i = 0; + + ASSERT_NO_THROW(i = Utils::toUid("0")); + ASSERT_EQ((uid_t)0, i); +} + +TEST_F(cta_UtilsTest, toUid_max) { + using namespace cta; + + std::ostringstream oss; + oss << std::numeric_limits<uid_t>::max(); + + uid_t i = 0; + + ASSERT_NO_THROW(i = Utils::toUid(oss.str())); + ASSERT_EQ(std::numeric_limits<uid_t>::max(), i); +} + +TEST_F(cta_UtilsTest, toUid_empty_string) { + using namespace cta; + + ASSERT_THROW(Utils::toUid(""), std::exception); +} + +TEST_F(cta_UtilsTest, toUid_negative) { + using namespace cta; + + ASSERT_THROW(Utils::toUid("-12345"), std::exception); +} + +TEST_F(cta_UtilsTest, toUid_too_big) { + using namespace cta; + + const uint64_t tooBig = (uint64_t)(std::numeric_limits<uid_t>::max()) + + (uint64_t)1; + + std::ostringstream oss; + oss << tooBig; + + ASSERT_THROW(Utils::toUid(oss.str()), std::exception); +} + +TEST_F(cta_UtilsTest, toGid_12345) { + using namespace cta; + + gid_t i = 0; + + ASSERT_NO_THROW(i = Utils::toGid("12345")); + ASSERT_EQ((gid_t)12345, i); +} + +TEST_F(cta_UtilsTest, toGid_zero) { + using namespace cta; + + gid_t i = 0; + + ASSERT_NO_THROW(i = Utils::toGid("0")); + ASSERT_EQ((gid_t)0, i); +} + +TEST_F(cta_UtilsTest, toGid_max) { + using namespace cta; + + std::ostringstream oss; + oss << std::numeric_limits<gid_t>::max(); + + gid_t i = 0; + + ASSERT_NO_THROW(i = Utils::toGid(oss.str())); + ASSERT_EQ(std::numeric_limits<gid_t>::max(), i); +} + +TEST_F(cta_UtilsTest, toGid_empty_string) { + using namespace cta; + + ASSERT_THROW(Utils::toGid(""), std::exception); +} + +TEST_F(cta_UtilsTest, toGid_negative) { + using namespace cta; + + ASSERT_THROW(Utils::toGid("-12345"), std::exception); +} + +TEST_F(cta_UtilsTest, toGid_too_big) { + using namespace cta; + + const uint64_t tooBig = (uint64_t)(std::numeric_limits<gid_t>::max()) + + (uint64_t)1; + + std::ostringstream oss; + oss << tooBig; + + ASSERT_THROW(Utils::toGid(oss.str()), std::exception); +} + TEST_F(cta_UtilsTest, isValidUInt_unsigned_int) { using namespace cta;