/******************************************************************************/ /* */ /* X r d O f s C o n f i g P I . h h */ /* */ /* (c) 2014 by the Board of Trustees of the Leland Stanford, Jr., University */ /* All Rights Reserved */ /* Produced by Andrew Hanushevsky for Stanford University under contract */ /* DE-AC02-76-SFO0515 with the Department of Energy */ /* */ /* This file is part of the XRootD software suite. */ /* */ /* XRootD is free software: you can redistribute it and/or modify it under */ /* the terms of the GNU Lesser General Public License as published by the */ /* Free Software Foundation, either version 3 of the License, or (at your */ /* option) any later version. */ /* */ /* XRootD is distributed in the hope that it will be useful, but WITHOUT */ /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */ /* License for more details. */ /* */ /* You should have received a copy of the GNU Lesser General Public License */ /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ /* COPYING (GPL license). If not, see . */ /* */ /* The copyright holder's institutional names and contributor's names may not */ /* be used to endorse or promote products derived from this software without */ /* specific prior written permission of the institution or contributor. */ /******************************************************************************/ #include #include #include #include #include #include #include "XrdVersion.hh" #include "XrdAcc/XrdAccAuthorize.hh" #include "XrdCks/XrdCks.hh" #include "XrdCks/XrdCksConfig.hh" #include "XrdCms/XrdCmsClient.hh" #include "XrdOfs/XrdOfs.hh" #include "XrdOfs/XrdOfsConfigPI.hh" #include "XrdOss/XrdOss.hh" #include "XrdOuc/XrdOucEnv.hh" #include "XrdOuc/XrdOucPinLoader.hh" #include "XrdOuc/XrdOucStream.hh" #include "XrdOuc/XrdOucUtils.hh" #include "XrdSys/XrdSysError.hh" #include "XrdSys/XrdSysFAttr.hh" #include "XrdSys/XrdSysHeaders.hh" #include "XrdSys/XrdSysPlugin.hh" /******************************************************************************/ /* G l o b a l s & S t a t i c s */ /******************************************************************************/ namespace { const char *drctv[] = {"xattrlib", "authlib", "ckslib", "cmslib", "osslib"}; const char *nullParms = 0; } XrdVERSIONINFOREF(XrdOfs); /******************************************************************************/ /* D e f i n e s */ /******************************************************************************/ #define DO_LOAD(x) loadLib & (x & ~libIXMask) #define PIX(x) x & libIXMask /******************************************************************************/ /* C o n s t r u c t o r */ /******************************************************************************/ XrdOfsConfigPI::XrdOfsConfigPI(const char *cfn, XrdOucStream *cfgP, XrdSysError *errP, XrdVersionInfo *verP) : autPI(0), cksPI(0), cmsPI(0), ossPI(0), urVer(verP), Config(cfgP), Eroute(errP), CksConfig(0), ConfigFN(cfn), CksAlg(0), CksRdsz(0), ossXAttr(false), ossCksio(false), Loaded(false), LoadOK(false), cksLcl(false) { int rc; // Clear the library table // memset(defLib, 0, sizeof(defLib)); // Set correct version // if (!verP) urVer = &XrdVERSIONINFOVAR(XrdOfs); // Preallocate the checksum configurator // CksConfig = new XrdCksConfig(ConfigFN, Eroute, rc, *urVer); if (!rc) {delete CksConfig; CksConfig = 0;} } /******************************************************************************/ /* D e s t r u c t o r */ /******************************************************************************/ XrdOfsConfigPI::~XrdOfsConfigPI() { if (CksConfig) delete CksConfig; if (CksAlg) free(CksAlg); } /******************************************************************************/ /* C o n f i g u r e */ /******************************************************************************/ bool XrdOfsConfigPI::Configure(XrdCmsClient *cmscP, XrdOucEnv *envP) { return 0 != cmscP->Configure(ConfigFN, LP[PIX(theCmsLib)].parms, envP); } /******************************************************************************/ /* D e f a u l t */ /******************************************************************************/ void XrdOfsConfigPI::Default(XrdOfsConfigPI::TheLib what, const char *lpath, const char *lparm) { int n = PIX(what); if (n < maxXXXLib && !RepLib(what, lpath, (lparm ? lparm : nullParms))) defLib[n] = true; } /******************************************************************************/ /* D e f a u l t C S */ /******************************************************************************/ void XrdOfsConfigPI::DefaultCS(const char *alg) { if (CksAlg) free(CksAlg); CksAlg = strdup(alg); XrdOucUtils::toLower(CksAlg); } /******************************************************************************/ /* D i s p l a y */ /******************************************************************************/ void XrdOfsConfigPI::Display() { xxxLP *lP; char *oP, buff[2046]; int aI = PIX(theAtrLib), oI = PIX(theOssLib); // Display what we have // for (int i = 0; i < maxXXXLib; i++) {oP = LP[i].opts; if (i != aI) lP = &LP[i]; else if (ossXAttr) {lP = &LP[oI]; oP = 0;} else lP = &LP[i]; if (lP->lib) {snprintf(buff, sizeof(buff), "ofs.%s %s%s %s", drctv[i], (oP ? oP : ""), lP->lib, (lP->parms ? lP->parms : "")); Eroute->Say(" ", buff); } } } /******************************************************************************/ /* L o a d */ /******************************************************************************/ bool XrdOfsConfigPI::Load(int loadLib, XrdOucEnv *envP) { extern XrdOss *XrdOssGetSS(XrdSysLogger *, const char *, const char *, const char *, XrdOucEnv *, XrdVersionInfo &); bool aOK; // Check if load was already called as we can only try once // if (Loaded) return LoadOK; Loaded = true; // Load the osslib first if so wanted // if (DO_LOAD(theOssLib)) {const char *ossLib = LP[PIX(theOssLib)].lib; if (!(ossPI = XrdOssGetSS(Eroute->logger(), ConfigFN, ossLib, LP[PIX(theOssLib)].parms, envP, *urVer))) return false; if (ossLib && envP && (ossLib = envP->Get("oss.lib"))) {free(LP[PIX(theOssLib)].lib); LP[PIX(theOssLib)].lib = strdup(ossLib); } } // Now setup the extended attribute plugin if so desired // if (DO_LOAD(theAtrLib)) { if (ossXAttr && LP[PIX(theOssLib)].lib) aOK = SetupAttr(theOssLib); else if (LP[PIX(theAtrLib)].lib) aOK = SetupAttr(theAtrLib); else aOK = true; if (!aOK) return false; } XrdSysFAttr::Xat->SetMsgRoute(Eroute); // Setup authorization if we need to // if (DO_LOAD(theAutLib) && !SetupAuth()) return false; // Setup checksumming if we need to // if (DO_LOAD(theCksLib)) {if (!CksConfig) {Eroute->Emsg("Config", "Unable to load checksum manager; " "incompatible versions."); return false; } cksPI = CksConfig->Configure(CksAlg, CksRdsz, (ossCksio ? ossPI : 0)); if (!cksPI) return false; } // Setup the cms if we need to // if (DO_LOAD(theCmsLib) && !SetupCms()) return false; // All done // LoadOK = true; return true; } /******************************************************************************/ /* N e w */ /******************************************************************************/ XrdOfsConfigPI *XrdOfsConfigPI::New(const char *cfn, XrdOucStream *cfgP, XrdSysError *errP, XrdVersionInfo *verP) { // Handle caller's version if so indicated // if (verP && !XrdSysPlugin::VerCmp(*verP, XrdVERSIONINFOVAR(XrdOfs))) return 0; // Return an actual instance // return new XrdOfsConfigPI(cfn, cfgP, errP, verP); } /******************************************************************************/ /* O s s C k s */ /******************************************************************************/ bool XrdOfsConfigPI::OssCks() {return ossCksio;} /******************************************************************************/ /* P a r s e */ /******************************************************************************/ bool XrdOfsConfigPI::Parse(TheLib what) { char *val; // Fan out based on what was specified // switch(what) {case theAtrLib: return ParseAtrLib(); break; case theAutLib: break; case theCksLib: if (CksConfig) {int libType; if (CksConfig->ParseLib(*Config, libType)) return false; if (libType) cksLcl = libType == 1; RepLib(theCksLib, CksConfig->ManLib(), nullParms, false); return true; } Eroute->Emsg("Config", "Checksum version error!"); return false; break; case theCmsLib: break; break; case theOssLib: return ParseOssLib(); break; default: Eroute->Emsg("Config", "Invalid plugin Parse() call"); return false; break; } // Get the path // if (!(val = Config->GetWord()) || !val[0]) {Eroute->Emsg("Config", drctv[PIX(what)],"not specified"); return false;} // Set the lib and parameterss // return RepLib(what, val); } /******************************************************************************/ /* Private: P a r s e A t r L i b */ /******************************************************************************/ /* Function: ParseAtrLib Purpose: To parse the directive: xattrlib {osslib | } [] the path of the xattr library to be used. optional parms to be passed Output: true upon success or false upon failure. */ bool XrdOfsConfigPI::ParseAtrLib() { char *val; // Get the path and parms // if (!(val = Config->GetWord()) || !val[0]) {Eroute->Emsg("Config", "xattrlib not specified"); return false;} // Record the path and parms // ossXAttr = !strcmp("osslib", val); return RepLib(theAtrLib, (ossXAttr ? 0 : val)); } /******************************************************************************/ /* Private: P a r s e O s s L i b */ /******************************************************************************/ /* Function: ParseOssLib Purpose: To parse the directive: osslib [] [] : [+cksio] [+xattr] [] +cksio use the oss plugin for checkum I/O. +xattr the library contains the xattr plugin. the path of the oss library to be used. optional parms to be passed Output: true upon success or false upon failure. */ bool XrdOfsConfigPI::ParseOssLib() { char *val, oBuff[80]; int oI = PIX(theOssLib); // Reset to defaults // ossCksio = false; if (LP[oI].opts) {free(LP[oI].opts); LP[oI].opts = 0;} *oBuff = 0; // Get the path and parms, and process keywords // while((val = Config->GetWord())) { if (!strcmp("+cksio", val)) {if (!ossCksio) strcat(oBuff, "+cksio "); ossCksio = true;} else if (!strcmp("+xattr", val)) {if (!ossXAttr) strcat(oBuff, "+xattr "); ossXAttr = true;} else break; } // Check if we an osslib // if (!val || !val[0]) {Eroute->Emsg("Config", "osslib not specified"); return false;} // Record the path and parameters // if (*oBuff) LP[oI].opts = strdup(oBuff); return RepLib(theOssLib, val); } /******************************************************************************/ /* P l u g i n */ /******************************************************************************/ bool XrdOfsConfigPI::Plugin(XrdAccAuthorize *&piP) { return (piP = autPI) != 0;} bool XrdOfsConfigPI::Plugin(XrdCks *&piP) { return (piP = cksPI) != 0;} bool XrdOfsConfigPI::Plugin(XrdCmsClient_t &piP) { return (piP = cmsPI) != 0;} bool XrdOfsConfigPI::Plugin(XrdOss *&piP) { return (piP = ossPI) != 0;} /******************************************************************************/ /* Private: R e p L i b */ /******************************************************************************/ bool XrdOfsConfigPI::RepLib(XrdOfsConfigPI::TheLib what, const char *newLib, const char *newParms, bool parseParms) { const char *parmP; char parms[2048]; int xLib = PIX(what); // Replace any existing library specification // if (LP[xLib].lib && newLib) {if (!strcmp(LP[xLib].lib, newLib) && defLib[xLib]) {const char *dfltLib = (newParms ? newLib : LP[xLib].lib); Eroute->Say("Config warning: ", "specified ", drctv[xLib], " overrides default ", dfltLib); } free(LP[xLib].lib); defLib[xLib] = false; } LP[xLib].lib = (newLib ? strdup(newLib) : 0); // Get any parameters // if (newParms) parmP = (newParms == nullParms ? 0 : newParms); else {*parms = 0; parmP = parms; if (parseParms && !Config->GetRest(parms, sizeof(parms))) {Eroute->Emsg("Config", drctv[xLib], "parameters too long"); return false; } } // Record the parameters // if (LP[xLib].parms) free(LP[xLib].parms); LP[xLib].parms = (*parmP ? strdup(parmP) : 0); return true; } /******************************************************************************/ /* S e t C k s R d S z */ /******************************************************************************/ void XrdOfsConfigPI::SetCksRdSz(int rdsz) {CksRdsz = rdsz;} /******************************************************************************/ /* Private: S e t u p A t t r */ /******************************************************************************/ bool XrdOfsConfigPI::SetupAttr(XrdOfsConfigPI::TheLib what) { XrdSysXAttr *(*ep)(XrdSysError *, const char *, const char *); XrdSysXAttr *theObj; char *AtrLib = LP[PIX(what)].lib; char *AtrParms = LP[PIX(what)].parms; // Create a plugin object // {XrdOucPinLoader myLib(Eroute, urVer, "xattrlib", AtrLib); ep = (XrdSysXAttr *(*)(XrdSysError *, const char *, const char *)) (myLib.Resolve("XrdSysGetXAttrObject")); if (!ep) return false; if (strcmp(AtrLib, myLib.Path())) {free(AtrLib); AtrLib = LP[PIX(what)].lib = strdup(myLib.Path());} } // Get the Object now // if (!(theObj = ep(Eroute, ConfigFN, AtrParms))) return false; // Tell the interface to use this object instead of the default implementation // XrdSysFAttr::SetPlugin(theObj); return true; } /******************************************************************************/ /* Private: S e t u p A u t h */ /******************************************************************************/ bool XrdOfsConfigPI::SetupAuth() { extern XrdAccAuthorize *XrdAccDefaultAuthorizeObject (XrdSysLogger *lp, const char *cfn, const char *parm, XrdVersionInfo &vInfo); XrdAccAuthorize *(*ep)(XrdSysLogger *, const char *, const char *); char *AuthLib = LP[PIX(theAutLib)].lib; char *AuthParms = LP[PIX(theAutLib)].parms; // Authorization comes from the library or we use the default // if (!AuthLib) return 0 != (autPI = XrdAccDefaultAuthorizeObject (Eroute->logger(), ConfigFN, AuthParms, *urVer)); // Create a plugin object // {XrdOucPinLoader myLib(Eroute, urVer, "authlib", AuthLib); ep = (XrdAccAuthorize *(*)(XrdSysLogger *, const char *, const char *)) (myLib.Resolve("XrdAccAuthorizeObject")); if (!ep) return false; if (strcmp(AuthLib, myLib.Path())) {free(AuthLib); AuthLib = LP[PIX(theAutLib)].lib = strdup(myLib.Path());} } // Get the Object now // return 0 != (autPI = ep(Eroute->logger(), ConfigFN, AuthParms)); } /******************************************************************************/ /* Private: S e t u p C m s */ /******************************************************************************/ bool XrdOfsConfigPI::SetupCms() { char *CmsLib = LP[PIX(theCmsLib)].lib; // Load the plugin if we have to // if (LP[PIX(theCmsLib)].lib) {XrdOucPinLoader myLib(Eroute, urVer, "cmslib", CmsLib); cmsPI = (XrdCmsClient *(*)(XrdSysLogger *, int, int, XrdOss *)) (myLib.Resolve("XrdCmsGetClient")); if (!cmsPI) return false; if (strcmp(CmsLib, myLib.Path())) {free(CmsLib); CmsLib = LP[PIX(theCmsLib)].lib = strdup(myLib.Path()); } } return true; }