portable directory traversal

metadata
Wenzel Jakob 2010-09-14 15:23:23 +02:00
parent 5253cb594c
commit a49d5bf648
3 changed files with 65 additions and 80 deletions

View File

@ -20,6 +20,9 @@
#define __PLUGIN_H
#include <mitsuba/mitsuba.h>
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
MTS_NAMESPACE_BEGIN
@ -36,7 +39,7 @@ class MTS_EXPORT_CORE Plugin {
typedef char *(*GetDescriptionFunc)();
public:
/// Load a plugin from the supplied path
Plugin(const std::string &shortName, const std::string &path);
Plugin(const std::string &shortName, const fs::path &path);
/// Virtual destructor
virtual ~Plugin();
@ -54,7 +57,7 @@ public:
std::string getDescription() const;
/// Return the path of this plugin
inline const std::string &getPath() const { return m_path; }
inline const fs::path &getPath() const { return m_path; }
/// Return a short name of this plugin
inline const std::string &getShortName() const { return m_shortName; }
@ -68,7 +71,7 @@ private:
void *m_handle;
#endif
std::string m_shortName;
std::string m_path;
fs::path m_path;
bool m_isUtility;
GetDescriptionFunc m_getDescription;
CreateInstanceFunc m_createInstance;

View File

@ -33,19 +33,19 @@ MTS_NAMESPACE_BEGIN
// Abstract plugin module implementation
// -----------------------------------------------------------------------
Plugin::Plugin(const std::string &shortName, const std::string &path)
Plugin::Plugin(const std::string &shortName, const fs::path &path)
: m_shortName(shortName), m_path(path) {
#if defined(WIN32)
m_handle = LoadLibrary(path.c_str());
m_handle = LoadLibrary(path.file_string().c_str());
if (!m_handle) {
SLog(EError, "Error while loading plugin \"%s\": %s", m_path.c_str(),
lastErrorText().c_str());
SLog(EError, "Error while loading plugin \"%s\": %s",
m_path.file_string().c_str(), lastErrorText().c_str());
}
#else
m_handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL);
m_handle = dlopen(path.file_string().c_str(), RTLD_LAZY | RTLD_LOCAL);
if (!m_handle) {
SLog(EError, "Error while loading plugin \"%s\": %s", m_path.c_str(),
dlerror());
SLog(EError, "Error while loading plugin \"%s\": %s",
m_path.file_string().c_str(), dlerror());
}
#endif
try {
@ -80,13 +80,13 @@ void *Plugin::getSymbol(const std::string &sym) {
void *data = GetProcAddress(m_handle, sym.c_str());
if (!data) {
SLog(EError, "Could not resolve symbol \"%s\" in \"%s\": %s",
sym.c_str(), m_path.c_str(), lastErrorText().c_str());
sym.c_str(), m_path.file_string().c_str(), lastErrorText().c_str());
}
#else
void *data = dlsym(m_handle, sym.c_str());
if (!data) {
SLog(EError, "Could not resolve symbol \"%s\" in \"%s\": %s",
sym.c_str(), m_path.c_str(), dlerror());
sym.c_str(), m_path.file_string().c_str(), dlerror());
}
#endif
return data;

View File

@ -31,12 +31,6 @@
#include <boost/algorithm/string.hpp>
#include <fstream>
#include <stdexcept>
#include <sys/types.h>
#if !defined(WIN32)
#include <dlfcn.h>
#include <dirent.h>
#endif
#if defined(WIN32)
#include "getopt.h"
@ -79,36 +73,34 @@ void help() {
std::set<std::string> seen;
for (size_t i=0; i<dirPaths.size(); ++i) {
std::string dirPath = fs::complete(dirPaths[i]).file_string();
fs::path dirPath = fs::complete(dirPaths[i]);
#if !defined(WIN32)
DIR *directory;
struct dirent *dirinfo;
if (!fs::exists(dirPath) || !fs::is_directory(dirPath))
break;
if ((directory = opendir(dirPath.c_str())) == NULL)
SLog(EInfo, "Could not open plugin directory");
fs::directory_iterator end, it(dirPath);
while ((dirinfo = readdir(directory)) != NULL) {
std::string fname(dirinfo->d_name);
if (!boost::ends_with(fname, ".dylib") && !boost::ends_with(fname, ".so"))
for (; it != end; ++it) {
if (!fs::is_regular_file(it->status()))
continue;
std::string extension(boost::to_lower_copy(it->path().extension()));
#if defined(WIN32)
if (extension != ".dll")
continue;
#elif defined(__OSX__)
if (extension != ".dylib")
continue;
#elif defined(__LINUX__)
if (extension != ".so")
continue;
std::string fullName = dirPath + "/" + fname;
#else
HANDLE hFind;
WIN32_FIND_DATA findFileData;
if ((hFind = FindFirstFile((dirPath + "\\*.dll").c_str(), &findFileData)) == INVALID_HANDLE_VALUE)
SLog(EInfo, "Could not open plugin directory");
do {
std::string fname = findFileData.cFileName;
std::string fullName = dirPath + "\\" + fname;
#error Unknown operating system!
#endif
std::string shortName = fname.substr(0, strrchr(fname.c_str(), '.') - fname.c_str());
std::string shortName = it->path().stem();
if (seen.find(shortName) != seen.end())
continue;
seen.insert(shortName);
Plugin utility(shortName, fullName);
Plugin utility(shortName, it->path());
if (!utility.isUtility())
continue;
if (boost::starts_with(shortName, "test_")) {
@ -122,13 +114,7 @@ void help() {
utilities << ' ';
utilities << utility.getDescription() << endl;
}
#if !defined(WIN32)
}
closedir(directory);
#else
} while (FindNextFile(hFind, &findFileData));
FindClose(hFind);
#endif
}
cout << testcases.str() << utilities.str();
@ -275,43 +261,41 @@ int ubi_main(int argc, char **argv) {
std::vector<fs::path> dirPaths = fileResolver->resolveAll("plugins");
std::set<std::string> seen;
int executed = 0, succeeded = 0;
for (size_t i=0; i<dirPaths.size(); ++i) {
std::string dirPath = fs::complete(dirPaths[i]).file_string();
fs::path dirPath = fs::complete(dirPaths[i]);
#if !defined(WIN32)
DIR *directory;
struct dirent *dirinfo;
if (!fs::exists(dirPath) || !fs::is_directory(dirPath))
break;
if ((directory = opendir(dirPath.c_str())) == NULL)
SLog(EInfo, "Could not open plugin directory");
fs::directory_iterator end, it(dirPath);
while ((dirinfo = readdir(directory)) != NULL) {
std::string fname(dirinfo->d_name);
if (!boost::ends_with(fname, ".dylib") && !boost::ends_with(fname, ".so"))
for (; it != end; ++it) {
if (!fs::is_regular_file(it->status()))
continue;
std::string extension(boost::to_lower_copy(it->path().extension()));
#if defined(WIN32)
if (extension != ".dll")
continue;
#elif defined(__OSX__)
if (extension != ".dylib")
continue;
#elif defined(__LINUX__)
if (extension != ".so")
continue;
std::string fullName = dirPath + "/" + fname;
#else
HANDLE hFind;
WIN32_FIND_DATA findFileData;
if ((hFind = FindFirstFile((dirPath + "\\*.dll").c_str(), &findFileData)) == INVALID_HANDLE_VALUE)
SLog(EInfo, "Could not open plugin directory");
do {
std::string fname = findFileData.cFileName;
std::string fullName = dirPath + "\\" + fname;
#error Unknown operating system!
#endif
std::string shortName = fname.substr(0, strrchr(fname.c_str(), '.') - fname.c_str());
if (!boost::starts_with(shortName, "test_") || seen.find(shortName) != seen.end())
std::string shortName = it->path().stem();
if (seen.find(shortName) != seen.end() || !boost::starts_with(shortName, "test_"))
continue;
seen.insert(shortName);
Plugin plugin(shortName, fullName);
Plugin plugin(shortName, it->path());
if (!plugin.isUtility())
continue;
ref<Utility> utility = plugin.createUtility();
TestCase *testCase = static_cast<TestCase *>(utility.get());
if (!utility->getClass()->derivesFrom(TestCase::m_theClass))
SLog(EError, "This is not a test case!");
@ -321,13 +305,7 @@ int ubi_main(int argc, char **argv) {
executed += testCase->getExecuted();
succeeded += testCase->getSucceeded();
#if !defined(WIN32)
}
closedir(directory);
#else
} while (FindNextFile(hFind, &findFileData));
FindClose(hFind);
#endif
}
SLog(EInfo, "Ran %i tests, %i succeeded, %i failed.", executed, succeeded, executed-succeeded);
@ -336,22 +314,26 @@ int ubi_main(int argc, char **argv) {
std::cerr << "A utility name must be supplied!" << endl;
return -1;
}
fs::path pluginName(argv[optind]);
/* Build the full plugin file name */
#if defined(WIN32)
std::string shortName = std::string("plugins/") + argv[optind] + std::string(".dll");
pluginName.replace_extension(".dll");
#elif defined(__OSX__)
std::string shortName = std::string("plugins/") + argv[optind] + std::string(".dylib");
pluginName.replace_extension(".dylib");
#elif defined(__LINUX__)
pluginName.replace_extension(".so");
#else
std::string shortName = std::string("plugins/") + argv[optind] + std::string(".so");
#error Unknown operating system!
#endif
std::string fullName = fileResolver->resolve(shortName).file_string();
fs::path fullName = fileResolver->resolve(fs::path("plugins") / pluginName);
if (!fs::exists(fullName)) {
/* Plugin not found! */
SLog(EError, "Utility \"%s\" not found (run \"mtsutil\" without arguments to "
"see a list of available utilities)", fullName.c_str());
"see a list of available utilities)", fullName.file_string().c_str());
}
SLog(EInfo, "Loading utility \"%s\" ..", argv[optind]);
Plugin *plugin = new Plugin(argv[optind], fullName);
if (!plugin->isUtility())