port molfile plugin reader to platform namespace

This commit is contained in:
Axel Kohlmeyer
2021-10-04 22:40:40 -04:00
parent ee594a879b
commit 0bdc6d47e0
3 changed files with 37 additions and 239 deletions

View File

@ -17,6 +17,11 @@
------------------------------------------------------------------------- */
#include "molfile_interface.h"
#include "platform.h"
#include "tokenizer.h"
#include "utils.h"
#include "molfile_plugin.h"
#include <cstdio>
@ -25,13 +30,6 @@
#include <cctype>
#include <strings.h> // for strcasecmp()
#if defined(_WIN32)
#include <windows.h>
#else
#include <dirent.h>
#include <dlfcn.h>
#endif
#if vmdplugin_ABIVERSION < 16
#error "unsupported VMD molfile plugin ABI version"
#endif
@ -199,172 +197,17 @@ extern "C" {
return 0;
}
// directory traversal helper functions
#if defined(_WIN32)
// Win32 directory traversal handle
typedef struct {
HANDLE h;
WIN32_FIND_DATA fd;
char *name;
char *searchname;
int dlen;
} dirhandle_t;
// open a directory handle
static dirhandle_t *my_opendir(const char *dirname)
{
dirhandle_t *d;
int len;
if (dirname == nullptr)
return nullptr;
d = new dirhandle_t;
len = 2 + strlen(dirname);
d->name = new char[len];
strcpy(d->name, dirname);
strcat(d->name, "\\");
d->dlen = len;
len += 1;
d->searchname = new char[len];
strcpy(d->searchname, dirname);
strcat(d->searchname, "\\*");
d->h = FindFirstFile(d->searchname, &(d->fd));
if (d->h == ((HANDLE)(-1))) {
delete[] d->searchname;
delete[] d->name;
delete d;
return nullptr;
}
return d;
}
// get next file name from directory handle
static char *my_readdir(dirhandle_t *d)
{
if (FindNextFile(d->h, &(d->fd))) {
return d->fd.cFileName;
}
return nullptr;
}
// close directory handle
static void my_closedir(dirhandle_t *d)
{
if (d->h != nullptr) {
FindClose(d->h);
}
delete[] d->searchname;
delete[] d->name;
delete d;
}
// open a shared object file
static void *my_dlopen(const char *fname) {
return (void *)LoadLibrary(fname);
}
// resolve a symbol in shared object
static void *my_dlsym(void *h, const char *sym) {
return (void *)GetProcAddress((HINSTANCE)h, sym);
}
// close a shared object
static int my_dlclose(void *h) {
/* FreeLibrary returns nonzero on success */
return !FreeLibrary((HINSTANCE)h);
}
#else
// Unix directory traversal handle
typedef struct {
DIR *d;
char *name;
int dlen;
} dirhandle_t;
// open a directory handle
static dirhandle_t *my_opendir(const char *dirname)
{
dirhandle_t *d;
int len;
if (dirname == nullptr) return nullptr;
d = new dirhandle_t;
len = 2 + strlen(dirname);
d->name = new char[len];
strcpy(d->name,dirname);
strcat(d->name,"/");
d->dlen = len;
d->d = opendir(d->name);
if (d->d == nullptr) {
delete[] d->name;
delete d;
return nullptr;
}
return d;
}
// get next file name from directory handle
static char *my_readdir(dirhandle_t *d)
{
struct dirent *p;
if ((p = readdir(d->d)) != nullptr) {
return p->d_name;
}
return nullptr;
}
// close directory handle
static void my_closedir(dirhandle_t *d)
{
if (d->d != nullptr) {
closedir(d->d);
}
delete[] d->name;
delete d;
return;
}
// open a shared object file
static void *my_dlopen(const char *fname) {
return dlopen(fname, RTLD_NOW);
}
// resolve a symbol in shared object
static void *my_dlsym(void *h, const char *sym) {
return dlsym(h, sym);
}
// close a shared object
static int my_dlclose(void *h) {
return dlclose(h);
}
#endif
} // end of extern "C" region
using namespace LAMMPS_NS;
// constructor.
MolfileInterface::MolfileInterface(const char *type, const int mode)
: _plugin(0), _dso(0), _ptr(0), _info(0), _natoms(0),
_mode(mode), _caps(M_NONE)
: _plugin(nullptr), _dso(nullptr), _ptr(nullptr), _info(nullptr), _natoms(0),
_mode(mode), _caps(M_NONE), _props(0)
{
_name = new char[5];
strcpy(_name,"none");
_type = new char[1+strlen(type)];
strcpy(_type,type);
_name = utils::strdup("none");
_type = utils::strdup(type);
}
// destructor.
@ -384,62 +227,21 @@ MolfileInterface::~MolfileInterface()
// register the best matching plugin in a given directory
int MolfileInterface::find_plugin(const char *pluginpath)
{
dirhandle_t *dir;
char *filename, *ext, *next, *path, *plugindir;
int retval = E_NONE;
#if defined(_WIN32)
#define MY_PATHSEP ';'
#else
#define MY_PATHSEP ':'
#endif
if (pluginpath == nullptr) return E_DIR;
plugindir = path = strdup(pluginpath);
while (plugindir) {
// check if this a single directory or path.
next = strchr(plugindir,MY_PATHSEP);
if (next) {
*next = '\0';
++next;
// search for suitable file names in provided path and try to inspect them
// only look at .so files, since this is what VMD uses on all platforms
for (const auto &dir : Tokenizer(pluginpath,":").as_vector()) {
for (const auto &filename : platform::list_directory(dir)) {
if (utils::strmatch(filename,"\\.so$")) {
int rv = load_plugin(platform::path_join(dir,filename).c_str());
if (rv > retval) retval = rv;
}
}
dir = my_opendir(plugindir);
if (!dir)
retval = (retval > E_DIR) ? retval : E_DIR;
// search for suitable file names and try to inspect them
while (dir) {
char *fullname;
int len;
filename = my_readdir(dir);
if (filename == nullptr) break;
// only look at .so files
ext = strrchr(filename, '.');
if (ext == nullptr) continue;
if (strcasecmp(ext,".so") != 0) continue;
// construct full pathname of potential DSO
len = dir->dlen;
len += strlen(filename);
fullname = new char[len];
strcpy(fullname,dir->name);
strcat(fullname,filename);
// try to register plugin at file name.
int rv = load_plugin(fullname);
if (rv > retval) retval = rv;
delete[] fullname;
}
if (dir)
my_closedir(dir);
plugindir = next;
}
free(path);
return retval;
}
@ -450,22 +252,22 @@ int MolfileInterface::load_plugin(const char *filename)
int len, retval = E_NONE;
// access shared object
dso = my_dlopen(filename);
dso = platform::dlopen(filename);
if (dso == nullptr)
return E_FILE;
// check for required plugin symbols
void *ifunc = my_dlsym(dso,"vmdplugin_init");
void *rfunc = my_dlsym(dso,"vmdplugin_register");
void *ffunc = my_dlsym(dso,"vmdplugin_fini");
void *ifunc = platform::dlsym(dso,"vmdplugin_init");
void *rfunc = platform::dlsym(dso,"vmdplugin_register");
void *ffunc = platform::dlsym(dso,"vmdplugin_fini");
if (ifunc == nullptr || rfunc == nullptr || ffunc == nullptr) {
my_dlclose(dso);
platform::dlclose(dso);
return E_SYMBOL;
}
// initialize plugin. skip plugin if it fails.
if (((initfunc)(ifunc))()) {
my_dlclose(dso);
platform::dlclose(dso);
return E_SYMBOL;
}
@ -528,12 +330,8 @@ int MolfileInterface::load_plugin(const char *filename)
forget_plugin();
delete[] _name;
len = 16;
len += strlen(plugin->prettyname);
len += strlen(plugin->author);
_name = new char[len];
sprintf(_name,"%s v%d.%d by %s",plugin->prettyname,
plugin->majorv, plugin->minorv, plugin->author);
_name = utils::strdup(fmt::format("{} v{}.{} by {}", plugin->prettyname,
plugin->majorv, plugin->minorv, plugin->author));
// determine plugin capabilities
_caps = M_NONE;
@ -569,7 +367,7 @@ int MolfileInterface::load_plugin(const char *filename)
}
// better luck next time. clean up and return.
my_dlclose(dso);
platform::dlclose(dso);
return retval;
}
@ -583,10 +381,10 @@ void MolfileInterface::forget_plugin()
_plugin = nullptr;
if (_dso) {
void *ffunc = my_dlsym(_dso,"vmdplugin_fini");
void *ffunc = platform::dlsym(_dso,"vmdplugin_fini");
if (ffunc)
((finifunc)ffunc)();
my_dlclose(_dso);
platform::dlclose(_dso);
}
_dso = nullptr;