XRootD
XrdOucPinLoader.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d O u c P i n L o a d e r . c c */
4 /* */
5 /* (c) 2014 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* Produced by Andrew Hanushevsky for Stanford University under contract */
7 /* DE-AC02-76-SFO0515 with the Department of Energy */
8 /* */
9 /* This file is part of the XRootD software suite. */
10 /* */
11 /* XRootD is free software: you can redistribute it and/or modify it under */
12 /* the terms of the GNU Lesser General Public License as published by the */
13 /* Free Software Foundation, either version 3 of the License, or (at your */
14 /* option) any later version. */
15 /* */
16 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19 /* License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24 /* */
25 /* The copyright holder's institutional names and contributor's names may not */
26 /* be used to endorse or promote products derived from this software without */
27 /* specific prior written permission of the institution or contributor. */
28 /******************************************************************************/
29 
30 #include <cerrno>
31 #include <cstdlib>
32 #include <cstdio>
33 #include <cstring>
34 
35 #include "XrdVersion.hh"
36 
38 #include "XrdOuc/XrdOucVerName.hh"
39 #include "XrdSys/XrdSysError.hh"
40 #include "XrdSys/XrdSysPlugin.hh"
41 
42 /******************************************************************************/
43 /* C o n s t r u c t o r */
44 /******************************************************************************/
45 
47  XrdVersionInfo *vInfo,
48  const char *drctv,
49  const char *plib)
50 {
51 
52 // Save some symbols and do common initialization
53 //
54  eDest = errP;
55  viP = vInfo;
56  errBP = 0;
57  errBL = 0;
58  Init(drctv, plib);
59 }
60 
61 /******************************************************************************/
62 
64  int eBlen,
65  XrdVersionInfo *vInfo,
66  const char *drctv,
67  const char *plib)
68 {
69 
70 // Save some symbols and do common initialization
71 //
72  eDest = 0;
73  viP = vInfo;
74  errBP = (eBlen > 0 ? eBuff : 0);
75  errBL = (eBlen > 0 ? eBlen : 0);
76  frBuff= false;
77  if (errBP) *errBP = 0;
78  Init(drctv, plib);
79 }
80 
81 /******************************************************************************/
82 
83 XrdOucPinLoader::XrdOucPinLoader(XrdVersionInfo *vInfo,
84  const char *drctv,
85  const char *plib)
86 {
87  static const int ebsz = 2048;
88 
89 // Allocate a message buffer if we need to (failure is OK)
90 //
91  errBP = (char *)malloc(ebsz);
92  errBL = ebsz;
93  frBuff= true;
94 
95 // Save some symbols and do common initialization
96 //
97  *errBP= 0;
98  eDest = 0;
99  viP = vInfo;
100  Init(drctv, plib);
101 }
102 
103 /******************************************************************************/
104 /* D e s t r u c t o r */
105 /******************************************************************************/
106 
108 {
109 
110 // Releae storage
111 //
112  if (theLib) free(theLib);
113  if (altLib) free(altLib);
114 
115 // Persist the image if we have one
116 //
117  if (piP) {piP->Persist(); delete piP;}
118  if (errBP && frBuff) free(errBP);
119 }
120 
121 /******************************************************************************/
122 /* Private: I n f o r m */
123 /******************************************************************************/
124 
125 void XrdOucPinLoader::Inform(const char *txt1, const char *txt2,
126  const char *txt3, const char *txt4,
127  const char *txt5)
128 {
129 
130 // If we have a messaging object, use that
131 //
132  if (eDest) {eDest->Say("Config ", txt1, txt2, txt3, txt4, txt5); return;}
133 
134 // If there is already a message in the buffer, then make sure it prints
135 //
136  char *bP;
137  int bL, n , i = 0;
138 
139  if (*errBP)
140  {int n = strlen(errBP);
141  if (n+16 > errBL) return;
142  errBP[n] = '\n';
143  bP = errBP + n + 1;
144  bL = errBL - n - 1;
145  } else {
146  bP = errBP;
147  bL = errBL;
148  }
149 
150 // Place the message in the buffer
151 //
152  const char *eTxt[] = {txt1, txt2, txt3, txt4, txt5, 0};
153  while(bL > 1 && eTxt[i])
154  {n = snprintf(bP, bL, "%s", eTxt[i]);
155  bP += n; bL -= n; i++;
156  }
157 }
158 
159 /******************************************************************************/
160 /* Private: I n i t */
161 /******************************************************************************/
162 
163 void XrdOucPinLoader::Init(const char *drctv, const char *plib)
164 {
165  char *plib2 = 0, libBuf[2048];
166  int n;
167  bool noFallBack;
168 
169 // We have no plugin
170 //
171  piP = 0;
172  dName = drctv;
173  global = false;
174  badLib = false;
175 
176 // Check if the path has a version in it. This is generally a no-no.
177 // We Issue a warning only on servers as that is where it usually occurs.
178 //
179  if ((n = XrdOucVerName::hasVersion(plib, &plib2)))
180  {if (plib2)
181  {snprintf(libBuf, sizeof(libBuf), "'%s' wrongly coerces version "
182  "'-%d'; using '%s' instead!", plib, n, plib2);
183  } else {
184  snprintf(libBuf, sizeof(libBuf), "'%s' should not use '-%d' "
185  "version syntax in its name!", plib, n);
186  }
187  if (eDest) eDest->Say("Config warning: ", dName, " path ", libBuf);
188  if (plib2) plib = plib2;
189  }
190 
191 // Perform versioning
192 //
193  if (XrdOucVerName::Version(XRDPLUGIN_SOVERSION, plib, noFallBack,
194  libBuf, sizeof(libBuf)))
195  {theLib = strdup(libBuf);
196  altLib = (noFallBack ? 0 : strdup(plib));
197  } else {
198  theLib = 0;
199  altLib = strdup(plib);
200  }
201 // Free up any allocated storage
202 //
203  if (plib2) free(plib2);
204 }
205 
206 /******************************************************************************/
207 /* Private: L o a d L i b */
208 /******************************************************************************/
209 
210 bool XrdOucPinLoader::LoadLib(int mcnt)
211 {
212  bool allMsgs = altLib == 0;
213 
214 // Create a plugin object
215 //
216  if (eDest) piP = new XrdSysPlugin(eDest, theLib, dName, viP, mcnt);
217  else piP = new XrdSysPlugin(errBP, errBL, theLib, dName, viP, mcnt);
218 
219 // Attempt to load the library
220 //
221  if (piP->getLibrary(allMsgs, global)) return true;
222 
223 // We failed, so delete this plugin
224 //
225  delete piP; piP = 0;
226 
227 // If we have an alternate unversioned name then we can try that but only
228 // if the versioned wasn't found.
229 //
230  if (!altLib && errno != ENOENT)
231  {badLib = true;
232  return false;
233  }
234 
235 // Indicate what we are doing but only for server-side plugins
236 //
237  if (eDest) eDest->Say("Plugin ", dName, " ", theLib,
238  " not found; falling back to using ", altLib);
239 
240 // if we have an alternative, readjust library pointers
241 //
242  if (altLib)
243  {free(theLib);
244  theLib = altLib;
245  altLib = 0;
246  } else {
247  badLib = true;
248  return false;
249  }
250 
251 // Try once more
252 //
253  if (eDest) piP = new XrdSysPlugin(eDest, theLib, dName, viP, mcnt);
254  else piP = new XrdSysPlugin(errBP, errBL, theLib, dName, viP, mcnt);
255 
256 // Attempt to load the alternate library
257 //
258  if (piP->getLibrary(true, global)) return true;
259  badLib = true;
260  return false;
261 }
262 
263 /******************************************************************************/
264 /* R e s o l v e */
265 /******************************************************************************/
266 
267 void *XrdOucPinLoader::Resolve(const char *symP, int mcnt)
268 {
269  int isOptional = 0;
270 
271 // Check if we couldn't create the path
272 //
273  if (!theLib && !badLib)
274  {Inform("Unable to load ",dName," plugin ",altLib,"; invalid path.");
275  badLib = true;
276  return 0;
277  }
278 
279 // If we couldn't load the library return failure. This is likely an alternate
280 // resolution as the caller is looking for an alternate symbol.
281 //
282  if (badLib) return 0;
283 
284 // Load the library so we can get errors about the library irrespective of
285 // the symbol we are trying to resolve.
286 //
287  if (!piP && !LoadLib(mcnt)) return 0;
288 
289 // Handle optional resolution
290 //
291  if (*symP == '?' || *symP == '!')
292  {symP++;
293  isOptional = (*symP == '!' ? 1 : 2);
294  }
295 
296 // We already have a plugin object so look up the symbol.
297 //
298  return piP->getPlugin(symP, isOptional, global);
299 }
300 
301 /******************************************************************************/
302 /* U n L o a d */
303 /******************************************************************************/
304 
305 void XrdOucPinLoader::Unload(bool dodel)
306 {
307 
308 // Simply delete any plugin object
309 //
310  if (piP) {delete piP; piP = 0;}
311  if (dodel) delete this;
312 }
XrdOucPinLoader(XrdSysError *errP, XrdVersionInfo *vInfo, const char *drctv, const char *plib)
void * Resolve(const char *symbl, int mcnt=1)
void Unload(bool dodel=false)
static int Version(const char *piVers, const char *piPath, bool &noFBK, char *buff, int blen)
static int hasVersion(const char *piPath, char **piNoVN=0)
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
Definition: XrdSysError.cc:141
void * getPlugin(const char *pname, int optional=0)
void * getLibrary(bool allMsgs=true, bool global=false)
void * Persist()