Cache DataDir when C++11 dynamic init is available (GH #760)

pull/771/head
Jeffrey Walton 2019-01-02 03:30:49 -05:00
parent 174f247c44
commit 9484815960
No known key found for this signature in database
GPG Key ID: B36AB348921B1838
2 changed files with 54 additions and 23 deletions

View File

@ -75,6 +75,7 @@ NAMESPACE_BEGIN(CryptoPP)
NAMESPACE_BEGIN(Test) NAMESPACE_BEGIN(Test)
const int MAX_PHRASE_LENGTH=250; const int MAX_PHRASE_LENGTH=250;
std::string g_argvPathHint="";
void GenerateRSAKey(unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed); void GenerateRSAKey(unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed);
std::string RSAEncryptString(const char *pubFilename, const char *seed, const char *message); std::string RSAEncryptString(const char *pubFilename, const char *seed, const char *message);
@ -149,6 +150,16 @@ int scoped_main(int argc, char *argv[])
cin.set_safe_flag(stream_MT::unsafe_object); cin.set_safe_flag(stream_MT::unsafe_object);
#endif #endif
// A hint to help locate TestData/ and TestVectors/ after install.
g_argvPathHint = argc > 0 ? argv[0] : "";
#if defined(AT_EXECFN)
if (getauxval(AT_EXECFN))
g_argvPathHint = getauxval(AT_EXECFN);
#endif
std::string::size_type pos = g_argvPathHint.find_last_of("\\/");
if (pos != std::string::npos)
g_argvPathHint.erase(pos+1);
try try
{ {
RegisterFactories(All); RegisterFactories(All);

View File

@ -20,6 +20,12 @@
NAMESPACE_BEGIN(CryptoPP) NAMESPACE_BEGIN(CryptoPP)
NAMESPACE_BEGIN(Test) NAMESPACE_BEGIN(Test)
// A hint to help locate TestData/ and TestVectors/ after install. Due to
// execve the path can be malicious. If the path is ficticous then we move
// onto the next potential path. Also note we only read from the path; we
// never write through it. Storage for the string is in test.cpp.
extern std::string g_argvPathHint;
bool ValidateAll(bool thorough); bool ValidateAll(bool thorough);
bool TestSettings(); bool TestSettings();
bool TestOS_RNG(); bool TestOS_RNG();
@ -205,10 +211,10 @@ inline std::string TimeToString(const time_t& t)
// Cleanup whitespace // Cleanup whitespace
std::string::size_type pos = 0; std::string::size_type pos = 0;
while (!str.empty() && std::isspace(*(str.end()-1))) while (!str.empty() && std::isspace(str[str.length()-1]))
{str.erase(str.end()-1);} {str.erase(str.end()-1);}
while (!str.empty() && std::string::npos != (pos = str.find(" ", pos))) while (!str.empty() && std::string::npos != (pos = str.find(" ", pos)))
{ str.erase(pos, 1); } {str.erase(pos, 1);}
return str; return str;
} }
@ -252,46 +258,60 @@ inline int StringToValue<int, true>(const std::string& str)
inline std::string AddSeparator(std::string str) inline std::string AddSeparator(std::string str)
{ {
const char last = (str.empty() ? '\0' : *str.end()-1); const char last = (str.empty() ? '\0' : str[str.length()-1]);
if (last != '/' && last != '\\') if (last != '/' && last != '\\')
return str + "/"; return str + "/";
return str; return str;
} }
// Ideally we would cache the directory and just add the prefix static std::string GetDataDir()
// to subsequent calls, but ... Static Initialization Order Fiasco {
std::ifstream file;
std::string name, filename = "TestData/usage.dat";
#ifndef CRYPTOPP_DISABLE_DATA_DIR_SEARCH
name = AddSeparator(g_argvPathHint) + filename;
file.open(name.c_str());
if (file.is_open())
return AddSeparator(g_argvPathHint);
#endif
#ifndef CRYPTOPP_DISABLE_DATA_DIR_SEARCH
// Look in $ORIGIN/../share/. This is likely a Linux install directory.
name = AddSeparator(g_argvPathHint) + std::string("../share/cryptopp/") + filename;
file.open(name.c_str());
if (file.is_open())
return AddSeparator(g_argvPathHint) + std::string("../share/cryptopp/");
#endif
return "./";
}
inline std::string DataDir(const std::string& filename) inline std::string DataDir(const std::string& filename)
{ {
std::string name; std::string name;
std::ifstream file; std::ifstream file;
#ifndef CRYPTOPP_DISABLE_DATA_DIR_SEARCH
// Data files in PWD are probably the newest. This is probably a build directory.
name = std::string("./") + filename;
file.open(name.c_str());
if (file.is_open())
return name;
#endif
#ifdef CRYPTOPP_DATA_DIR #ifdef CRYPTOPP_DATA_DIR
// Honor the user's setting next. This is likely an install directory if it is not "./". // Honor CRYPTOPP_DATA_DIR. This is likely an install directory if it is not "./".
name = AddSeparator(CRYPTOPP_DATA_DIR) + filename; name = AddSeparator(CRYPTOPP_DATA_DIR) + filename;
file.open(name.c_str()); file.open(name.c_str());
if (file.is_open()) if (file.is_open())
return name; return name;
#endif #endif
#ifndef CRYPTOPP_DISABLE_DATA_DIR_SEARCH
// Look in /usr/local/bin/share/. This is LSB and default install directory for users. #if CRYPTOPP_CXX11_DYNAMIC_INIT
name = std::string("/usr/local/share/cryptopp/") + filename; static std::string path = AddSeparator(GetDataDir());
file.open(name.c_str()); name = path + filename;
if (file.is_open()) file.open(name.c_str());
return name; if (file.is_open())
#endif return name;
#ifndef CRYPTOPP_DISABLE_DATA_DIR_SEARCH #else
// Finally look in $ORIGIN/../share/. This is likely a Linux install directory for users. // Avoid static initialzation problems
name = std::string("../share/cryptopp/") + filename; name = AddSeparator(GetDataDir()) + filename;
file.open(name.c_str()); file.open(name.c_str());
if (file.is_open()) if (file.is_open())
return name; return name;
#endif #endif
// This will cause the expected exception in the caller // This will cause the expected exception in the caller
return filename; return filename;
} }