XRootD
Loading...
Searching...
No Matches
XrdSysPlugin Class Reference

#include <XrdSysPlugin.hh>

Collaboration diagram for XrdSysPlugin:

Public Member Functions

 XrdSysPlugin (char *ebuff, int eblen, const char *path, const char *lname, XrdVersionInfo *vinf=0, int msgNum=-1)
 XrdSysPlugin (XrdSysError *erp, const char *path)
 XrdSysPlugin (XrdSysError *erp, const char *path, const char *lname, XrdVersionInfo *vinf=0, int msgNum=-1)
 ~XrdSysPlugin ()
 Destructor.
void * getLibrary (bool allMsgs=true, bool global=false)
void * getPlugin (const char *pname, int optional, bool global)
void * getPlugin (const char *pname, int optional=0)
void * Persist ()

Static Public Member Functions

static bool Preload (const char *path, char *ebuff=0, int eblen=0)
static bool VerCmp (XrdVersionInfo &vInf1, XrdVersionInfo &vInf2, bool noMsg=false)

Detailed Description

Handy class to load run-time plugins and optionally check if the version is compatible with the caller's version number. Version numbers are defined as "aaa.bb.cc" where aaa is a decimnal major version, bb is a decimal minor version, and cc is the decimal patch version number. Only the major and, optionally, minor version numbers are checked. The checking rules are defined in XrdVersion.hh and are rather liberal in nature. In order to check versions, the plugin versioning rule must be defined in XrdVersion.hh and constructor #2 or #3 must be used. The symbolic name of the plugin's version information is the plugin symbol being looked up appended with "Version" and must be defined as an XrdVersionInfo structure.

Definition at line 52 of file XrdSysPlugin.hh.

Constructor & Destructor Documentation

◆ XrdSysPlugin() [1/3]

XrdSysPlugin::XrdSysPlugin ( XrdSysError * erp,
const char * path )
inline

Constructor #1 (version number checking is not to be performed)

Parameters
erp-> error message object to display error messages.
path-> path to the shared library containing a plug-in. If NULL the the executable image is searched for the plug-in. Storage must persist while this object is alive.

Definition at line 165 of file XrdSysPlugin.hh.

166 : eDest(erp), libName(0), libPath(path ? strdup(path) : 0),
167 libHandle(0), myInfo(0), eBuff(0), eBLen(0), msgCnt(-1) {}
static XrdSysError eDest(0,"crypto_")

◆ XrdSysPlugin() [2/3]

XrdSysPlugin::XrdSysPlugin ( XrdSysError * erp,
const char * path,
const char * lname,
XrdVersionInfo * vinf = 0,
int msgNum = -1 )
inline

Constructor #2 (version number checking may be performed)

Parameters
erp-> error message object to display error messages.
path-> path to the shared library containing a plug-in. If NULL the the executable image is searched for the plug-in. Storage must persist while this object is alive.
lname-> logical name of the plugin library (e.g. osslib) to be used in any error messages. Storage must persist while this object is alive.
vinf-> permanent version information of the plug-in loader. If zero, then no version checking is performed.
msgNum-> Number of times getPlugin() is to produce a version message for a loaded plugin. The default is always.

Definition at line 185 of file XrdSysPlugin.hh.

187 : eDest(erp), libName(lname),
188 libPath(path ? strdup(path) : 0), libHandle(0),
189 myInfo(vinf), eBuff(0), eBLen(0), msgCnt(msgNum) {}

◆ XrdSysPlugin() [3/3]

XrdSysPlugin::XrdSysPlugin ( char * ebuff,
int eblen,
const char * path,
const char * lname,
XrdVersionInfo * vinf = 0,
int msgNum = -1 )
inline

Constructor #3 (version number checking may be performed and any error is returned in a supplied buffer)

Parameters
ebuff-> buffer where eror message is to be placed. The message will always end with a null byte.
eblen-> length of the supplied buffer, eBuff.
path-> path to the shared library containing a plug-in. If NULL the the executable image is searched for the plug-in. Storage must persist while this object is alive.
lname-> logical name of the plugin library (e.g. osslib) to be used in any error messages. Storage must persist while this object is alive.
vinf-> permanent version information of the plug-in loader. If Zero, then no version checking is performed.
msgNum-> Number of times getPlugin() is to produce a version message for a loaded plugin. The default is always.

Definition at line 210 of file XrdSysPlugin.hh.

212 : eDest(0), libName(lname),
213 libPath(path ? strdup(path) : 0), libHandle(0),
214 myInfo(vinf), eBuff(ebuff), eBLen(eblen), msgCnt(msgNum) {}

◆ ~XrdSysPlugin()

XrdSysPlugin::~XrdSysPlugin ( )

Destructor.

Definition at line 72 of file XrdSysPlugin.cc.

73{
74 if (libHandle) dlclose(libHandle);
75 if (libPath) free(libPath);
76}

Member Function Documentation

◆ getLibrary()

void * XrdSysPlugin::getLibrary ( bool allMsgs = true,
bool global = false )

Prepare shared library for use (optional call).

Parameters
allMsgsWhen true messages all messages are handled as directed by the constructor. Otherwise, only messages regarding ENOENT (file not found ) are suppressed.
globalwhen true then the symbols defined in the plug-in shared library are made available for symbol resolution of subsequently loaded libraries.
Returns
!0 Library successfully prepared. =0 Library cannot be prepared; if mBuff is supplied, it contains the error message. If the file was not found, errno is set to ENOENT; otherwise to ENOEXEC.
Note
This method is implicitly called when calling getPlugin().

Definition at line 255 of file XrdSysPlugin.cc.

256{
257 void *myHandle;
258 int flags;
259
260// Check if we should use the preload list
261//
262 if (!(myHandle = libHandle) && plList) myHandle = Find(libPath);
263
264// If already open, return the handle
265//
266 if (myHandle) return myHandle;
267
268// If no path is given then we want to just search the executable. This is easy
269// for some platforms and more difficult for others. So, we do the best we can.
270//
271 if (libPath) flags = DLflags();
272 else { flags = RTLD_NOW;
273#ifndef WIN32
274 flags|= global ? RTLD_GLOBAL : RTLD_LOCAL;
275#else
276 if (global && eDest) eDest->Emsg("getPlugin",
277 "request for global symbols unsupported under Windows - ignored");
278#endif
279 }
280
281// Try to open this library or the executable image
282//
283 if ((myHandle = dlopen(libPath, flags))) libHandle = myHandle;
284 else {const char *eTxt = dlerror();
285 if (strcasestr(eTxt, "no such file")) errno = ENOENT;
286 else errno = ENOEXEC;
287 if (allMsgs || errno != ENOENT) libMsg(eTxt, " loading ");
288 }
289
290// All done
291//
292 return myHandle;
293}

Referenced by getPlugin().

Here is the caller graph for this function:

◆ getPlugin() [1/2]

void * XrdSysPlugin::getPlugin ( const char * pname,
int optional,
bool global )

Get the address of a plugin from a shared library, opening the plug-in shared library if not already open and optionally make the symbols global.

Parameters
pnamethe plug-in extern "C" symbolic name
optionalwhen 0 then issue error message when symbol isn't found. Otherwise, the mising symbol is treated as an error. When optional is greater than 1, the load message is suppressed.
globalwhen true then the symbols defined in the plug-in shared library are made available for symbol resolution of subsequently loaded libraries.
Returns
Success: the address of the symbol in the shared library/executable. The address becomes invalid when this object is deleted unless Persist() is called prior to deletion. Failure: Null

Definition at line 304 of file XrdSysPlugin.cc.

305{
306 XrdVERSIONINFODEF(urInfo, unknown, XrdVNUMUNK, "");
307 void *ep, *myHandle;
308 cvResult cvRC;
309
310// Open whatever it is we need to open
311//
312 if (!(myHandle = getLibrary(optional < 2, global))) return 0;
313
314// Get the symbol. In the environment we have defined, null values are not
315// allowed and we will issue an error.
316//
317 if (!(ep = dlsym(myHandle, pname)))
318 {if (optional < 2) libMsg(dlerror(), " symbol %s in ", pname);
319 return 0;
320 }
321
322// Check if we need to verify version compatibility
323//
324 if ((cvRC = chkVersion(urInfo, pname, myHandle)) == cvBad) return 0;
325
326// Print the loaded version unless message is suppressed or not needed
327//
328 if (libPath && optional < 2 && msgCnt
329 && (cvRC == cvClean || cvRC == cvMissing))
330 {char buff[128];
331 msgSuffix(" from ", buff, sizeof(buff));
332 msgCnt--;
333 if (cvRC == cvClean)
334 {const char *wTxt=(urInfo.vNum == XrdVNUMUNK ? "unreleased ":"");
335 Inform("loaded ", wTxt, urInfo.vStr, buff, libPath);
336 }
337 else if (cvRC == cvMissing)
338 {Inform("loaded unversioned ", pname, buff, libPath);}
339 }
340
341// All done
342//
343 return ep;
344}
static XrdVERSIONINFODEF(compiledVer, XrdHttpProtocolTest, XrdVNUMBER, XrdVERSION)
void * getLibrary(bool allMsgs=true, bool global=false)

References getLibrary(), and XrdVERSIONINFODEF().

Here is the call graph for this function:

◆ getPlugin() [2/2]

void * XrdSysPlugin::getPlugin ( const char * pname,
int optional = 0 )

Get the address of a plugin from a shared library, opening the plug-in shared library if not already open. Symbols in the library are local.

Parameters
pnamethe plug-in extern "C" symbolic name
optionalwhen 0 then issue error message when symbol isn't found. Otherwise, the mising symbol is treated as an error.
Returns
Success: the address of the symbol in the shared library/executable. The address becomes invalid when this object is deleted unless Persist() is called prior to deletion. Failure: Null

Definition at line 299 of file XrdSysPlugin.cc.

300{
301 return getPlugin(pname, optional, false);
302}
void * getPlugin(const char *pname, int optional=0)

References getPlugin().

Referenced by getPlugin(), and LoadFS().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Persist()

void * XrdSysPlugin::Persist ( )
inline

Make library persistent even when the plugin object is deleted. Note that if getPlugin() is called afterwards, the library will be re-opened!

Returns
pointer to the opened shared library.

Definition at line 118 of file XrdSysPlugin.hh.

118{void *lHan = libHandle; libHandle = 0; return lHan;}

Referenced by LoadFS().

Here is the caller graph for this function:

◆ Preload()

bool XrdSysPlugin::Preload ( const char * path,
char * ebuff = 0,
int eblen = 0 )
static

Preload a shared library. This method is meant for those threading models that require libraries to be opened in the main thread (e.g. MacOS). This method is meant to be called before therads start and is not thread-safe.

Parameters
path-> to the library path, typically this should just be the library filename so that LD_LIBRARY_PATH is used to discover the directory path. This allows getPlugin() to properly match preloaded libraries.
ebuff-> buffer where eror message is to be placed. The message will always end with a null byte. If no error buffer is supplied, any error messages are discarded.
eblen-> length of the supplied buffer, eBuff.
Returns
True The library was preloaded. False The library could not be preloaded, ebuff, if supplied, contains the error message text.

Definition at line 435 of file XrdSysPlugin.cc.

436{
437 struct PLlist *plP;
438 void *myHandle;
439
440// First see if this is already in the preload list
441//
442 if (Find(path)) return true;
443
444// Try to open the library
445//
446 if (!(myHandle = dlopen(path, DLflags())))
447 {if (ebuff && eblen > 0)
448 {const char *dlMsg = dlerror();
449 snprintf(ebuff, eblen, "Plugin unable to load %s; %s", path,
450 (dlMsg ? dlMsg : "unknown system error"));
451 }
452 return false;
453 }
454
455// Add the library handle
456//
457 plP = new PLlist;
458 plP->libHandle = myHandle;
459 plP->libPath = strdup(path);
460 plP->next = plList;
461 plList = plP;
462
463// All done
464//
465 return true;
466}

Referenced by XrdOucPreload().

Here is the caller graph for this function:

◆ VerCmp()

bool XrdSysPlugin::VerCmp ( XrdVersionInfo & vInf1,
XrdVersionInfo & vInf2,
bool noMsg = false )
static

Compare two versions for compatibility, optionally printing a warning.

Parameters
vInf1-> Version information for source.
vInf2-> Version information for target.
noMsg-> If true, no error messages are written to stderr.
Returns
True if versions are compatible (i.e. major and minor versions are identical as required for locally linked code); false otherwise.

Definition at line 472 of file XrdSysPlugin.cc.

474{
475 const char *mTxt;
476 char v1buff[128], v2buff[128];
477 int unRel;
478
479// Do a quick return if the version need not be checked or are equal
480//
481 if (vInfo1.vNum <= 0 || vInfo1.vNum == vInfo2.vNum) return true;
482
483// As it works out, many times two modules wind up in different shared
484// libraries. For consistency we require that both major.minor version be the
485// same unless either is unreleased (i.e. test). Issue warning if need be.
486//
487 mTxt = (vInfo1.vNum == XrdVNUMUNK ? "unreleased " : "");
488 sprintf(v1buff, " %sversion %s", mTxt, vInfo1.vStr);
489 unRel = *mTxt;
490
491 mTxt = (vInfo2.vNum == XrdVNUMUNK ? "unreleased " : "");
492 sprintf(v2buff, " %sversion %s", mTxt, vInfo2.vStr);
493 unRel |= *mTxt;
494
495 if (unRel || vInfo1.vNum/100 == vInfo2.vNum/100) mTxt = "";
496 else mTxt = " which is incompatible!";
497
498 if (!noMsg)
499 std::cerr <<"Plugin: " <<v1buff <<" is using " <<v2buff <<mTxt <<std::endl;
500
501 return (*mTxt == 0);
502}

Referenced by XrdCksConfig::XrdCksConfig(), XrdCksLoader::XrdCksLoader(), XrdOucN2NLoader::Load(), XrdOfsConfigPI::New(), XrdCmsFinderRMT::VCheck(), XrdCmsFinderTRG::VCheck(), XrdAccDefaultAuthorizeObject(), and XrdOssGetSS().

Here is the caller graph for this function:

The documentation for this class was generated from the following files: