/******************************************************************************/ /* */ /* X r d S s i S f s . c c */ /* */ /* (c) 2013 by the Board of Trustees of the Leland Stanford, Jr., University */ /* Produced by Andrew Hanushevsky for Stanford University under contract */ /* DE-AC02-76-SFO0515 with the Deprtment 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 #include #include #include #include #include #include #include #include "XrdNet/XrdNetAddr.hh" #include "XrdNet/XrdNetIF.hh" #include "XrdSsi/XrdSsiDir.hh" #include "XrdSsi/XrdSsiFile.hh" #include "XrdSsi/XrdSsiProvider.hh" #include "XrdSsi/XrdSsiSfs.hh" #include "XrdSsi/XrdSsiSfsConfig.hh" #include "XrdSsi/XrdSsiStats.hh" #include "XrdSsi/XrdSsiTrace.hh" #include "XrdCms/XrdCmsClient.hh" #include "XrdSys/XrdSysError.hh" #include "XrdSys/XrdSysHeaders.hh" #include "XrdSys/XrdSysLogger.hh" #include "XrdSys/XrdSysPlatform.hh" #include "XrdSys/XrdSysPthread.hh" #include "XrdSys/XrdSysTrace.hh" #include "XrdOuc/XrdOucEnv.hh" #include "XrdOuc/XrdOucERoute.hh" #include "XrdOuc/XrdOucLock.hh" #include "XrdOuc/XrdOucPList.hh" #include "XrdOuc/XrdOucTList.hh" #include "XrdSec/XrdSecEntity.hh" #include "XrdSfs/XrdSfsAio.hh" #include "XrdSfs/XrdSfsInterface.hh" #include "XrdVersion.hh" #ifdef AIX #include #endif /******************************************************************************/ /* V e r s i o n I d e n t i f i c a t i o n */ /******************************************************************************/ XrdVERSIONINFO(XrdSfsGetFileSystem,ssi); /******************************************************************************/ /* G l o b a l O b j e c t s */ /******************************************************************************/ namespace { XrdSsiSfsConfig *Config; }; namespace XrdSsi { extern XrdSsiProvider *Provider; extern XrdNetIF *myIF; XrdSfsFileSystem *theFS = 0; extern XrdOucPListAnchor FSPath; extern bool fsChk; extern XrdSysError Log; extern XrdSysLogger *Logger; extern XrdSysTrace Trace; extern XrdSsiStats Stats; }; using namespace XrdSsi; /******************************************************************************/ /* S t a t i c O b j e c t s */ /******************************************************************************/ int XrdSsiSfs::freeMax = 256; /******************************************************************************/ /* X r d S f s G e t F i l e S y s t e m */ /******************************************************************************/ extern "C" { XrdSfsFileSystem *XrdSfsGetFileSystem(XrdSfsFileSystem *nativeFS, XrdSysLogger *logger, const char *configFn) { static XrdSsiSfs mySfs; static XrdSsiSfsConfig myConfig; // Set pointer to the config and file system // Config = &myConfig; theFS = nativeFS; Stats.setFS(nativeFS); // No need to herald this as it's now the default filesystem // Log.SetPrefix("ssi_"); Log.logger(logger); Logger = logger; Trace.SetLogger(logger); // Initialize the subsystems // if (!myConfig.Configure(configFn)) return 0; // All done, we can return the callout vector to these routines. // return &mySfs; } } /******************************************************************************/ /* c h k s u m */ /******************************************************************************/ int XrdSsiSfs::chksum( csFunc Func, // In const char *csName, // In const char *Path, // In XrdOucErrInfo &einfo, // Out const XrdSecEntity *client, // In const char *opaque) // In { // Reroute this request if we can // if (fsChk) return theFS->chksum(Func, csName, Path, einfo, client, opaque); einfo.setErrInfo(ENOTSUP, "Checksums are not supported."); return SFS_ERROR; } /******************************************************************************/ /* c h m o d */ /******************************************************************************/ int XrdSsiSfs::chmod(const char *path, // In XrdSfsMode Mode, // In XrdOucErrInfo &einfo, // Out const XrdSecEntity *client, // In const char *info) // In { // Reroute this request if we can // if (fsChk) {if (FSPath.Find(path)) return theFS->chmod(path, Mode, einfo, client, info); einfo.setErrInfo(ENOTSUP, "chmod is not supported for given path."); } else einfo.setErrInfo(ENOTSUP, "chmod is not supported."); return SFS_ERROR; } /******************************************************************************/ /* Private: E m s g */ /******************************************************************************/ int XrdSsiSfs::Emsg(const char *pfx, // Message prefix value XrdOucErrInfo &einfo, // Place to put text & error code int ecode, // The error code const char *op, // Operation being performed const char *target) // The target (e.g., fname) { char buffer[MAXPATHLEN+80]; // Format the error message // XrdOucERoute::Format(buffer, sizeof(buffer), ecode, op, target); // Print it out if debugging is enabled // #ifndef NODEBUG Log.Emsg(pfx, einfo.getErrUser(), buffer); #endif // Place the error message in the error object and return // einfo.setErrInfo(ecode, buffer); return SFS_ERROR; } /******************************************************************************/ /* E n v I n f o */ /******************************************************************************/ void XrdSsiSfs::EnvInfo(XrdOucEnv *envP) { if (!envP) Log.Emsg("EnvInfo", "No environmental information passed!"); if (!envP || !Config->Configure(envP)) abort(); } /******************************************************************************/ /* e x i s t s */ /******************************************************************************/ int XrdSsiSfs::exists(const char *path, // In XrdSfsFileExistence &file_exists, // Out XrdOucErrInfo &einfo, // Out const XrdSecEntity *client, // In const char *info) // In { // Reroute this request if we can // if (fsChk) {if (FSPath.Find(path)) return theFS->exists(path, file_exists, einfo, client, info); einfo.setErrInfo(ENOTSUP, "exists is not supported for given path."); } else einfo.setErrInfo(ENOTSUP, "exists is not supported."); return SFS_ERROR; } /******************************************************************************/ /* f s c t l */ /******************************************************************************/ int XrdSsiSfs::fsctl(const int cmd, const char *args, XrdOucErrInfo &einfo, const XrdSecEntity *client) /* Function: Perform filesystem operations: Input: cmd - Operation command (currently supported): SFS_FSCTL_LOCATE - locate resource args - Command dependent argument: - Locate: The path whose location is wanted einfo - Error/Response information structure. client - Authentication credentials, if any. Output: Returns SFS_OK upon success and SFS_ERROR upon failure. */ { EPNAME("fsctl"); const char *tident = einfo.getErrUser(); char pbuff[1024], rType[3] = {'S', 'w', 0}; const char *Resp[2] = {rType, pbuff}; const char *opq, *Path = Split(args,&opq,pbuff,sizeof(pbuff)); XrdNetIF::ifType ifType; int Resp1Len; // Do some debugging // DEBUG(args); // We only process the locate request here. Reroute it if we can otherwise. // if ((cmd & SFS_FSCTL_CMD) != SFS_FSCTL_LOCATE) {if (fsChk) return theFS->fsctl(cmd, args, einfo, client); einfo.setErrInfo(ENOTSUP, "Requested fsctl operation not supported."); return SFS_ERROR; } // Preprocess the argument // if (*Path == '*') Path++; else if (cmd & SFS_O_TRUNC) Path = 0; // Check if we should reoute this request // if (fsChk && Path && FSPath.Find(Path)) return theFS->fsctl(cmd, args, einfo, client); // If we have a path then see if we really have it // if (Path) {if (!Provider) return Emsg(epname, einfo, EHOSTUNREACH, "locate", Path); else {XrdSsiProvider::rStat rStat = Provider->QueryResource(Path); if (rStat == XrdSsiProvider::isPresent) rType[0] = 'S'; else if (rStat == XrdSsiProvider::isPending) rType[0] = 's'; else return Emsg(epname, einfo, ENOENT, "locate", Path); } } // Compute interface return options // ifType = XrdNetIF::GetIFType((einfo.getUCap() & XrdOucEI::uIPv4) != 0, (einfo.getUCap() & XrdOucEI::uIPv64) != 0, (einfo.getUCap() & XrdOucEI::uPrip) != 0); bool retHN = (cmd & SFS_O_HNAME) != 0; // Get our destination // if ((Resp1Len = myIF->GetDest(pbuff, sizeof(pbuff), ifType, retHN))) {einfo.setErrInfo(Resp1Len+3, (const char **)Resp, 2); return SFS_DATA; } // We failed for some unknown reason // return Emsg(epname, einfo, ENETUNREACH, "locate", Path); } /******************************************************************************/ /* g e t S t a t s */ /******************************************************************************/ int XrdSsiSfs::getStats(char *buff, int blen) { // Return statustics // return Stats.Stats(buff, blen); } /******************************************************************************/ /* g e t V e r s i o n */ /******************************************************************************/ const char *XrdSsiSfs::getVersion() {return XrdVERSION;} /******************************************************************************/ /* m k d i r */ /******************************************************************************/ int XrdSsiSfs::mkdir(const char *path, // In XrdSfsMode Mode, // In XrdOucErrInfo &einfo, // Out const XrdSecEntity *client, // In const char *info) // In { // Reroute this request if we can // if (fsChk) {if (FSPath.Find(path)) return theFS->mkdir(path, Mode, einfo, client, info); einfo.setErrInfo(ENOTSUP, "mkdir is not supported for given path."); } else einfo.setErrInfo(ENOTSUP, "mkdir is not supported."); return SFS_ERROR; } /******************************************************************************/ /* p r e p a r e */ /******************************************************************************/ int XrdSsiSfs::prepare( XrdSfsPrep &pargs, // In XrdOucErrInfo &out_error, // Out const XrdSecEntity *client) // In { // Reroute this if we can // if (theFS) return theFS->prepare(pargs, out_error, client); return SFS_OK; } /******************************************************************************/ /* r e m */ /******************************************************************************/ int XrdSsiSfs::rem(const char *path, // In XrdOucErrInfo &einfo, // Out const XrdSecEntity *client, // In const char *info) // In { // Reroute this request if we can // if (fsChk) {if (FSPath.Find(path)) return theFS->rem(path, einfo, client, info); einfo.setErrInfo(ENOTSUP, "rem is not supported for given path."); } else einfo.setErrInfo(ENOTSUP, "rem is not supported."); return SFS_ERROR; } /******************************************************************************/ /* r e m d i r */ /******************************************************************************/ int XrdSsiSfs::remdir(const char *path, // In XrdOucErrInfo &einfo, // Out const XrdSecEntity *client, // In const char *info) // In { // Reroute this request if we can // if (fsChk) {if (FSPath.Find(path)) return theFS->rem(path, einfo, client, info); einfo.setErrInfo(ENOTSUP, "remdir is not supported for given path."); } else einfo.setErrInfo(ENOTSUP, "remdir is not supported."); return SFS_ERROR; } /******************************************************************************/ /* r e n a m e */ /******************************************************************************/ int XrdSsiSfs::rename(const char *old_name, // In const char *new_name, // In XrdOucErrInfo &einfo, //Out const XrdSecEntity *client, // In const char *infoO, // In const char *infoN) // In { // Reroute this request if we can // if (fsChk) {if (FSPath.Find(old_name)) return theFS->rename(old_name,new_name,einfo,client,infoO,infoN); einfo.setErrInfo(ENOTSUP, "rename is not supported for given path."); } else einfo.setErrInfo(ENOTSUP, "rename is not supported."); return SFS_ERROR; } /******************************************************************************/ /* Private: S p l i t */ /******************************************************************************/ const char * XrdSsiSfs::Split(const char *Args, const char **Opq, char *Path, int Plen) { int xlen; *Opq = index(Args, '?'); if (!(*Opq)) return Args; xlen = (*Opq)-Args; if (xlen >= Plen) xlen = Plen-1; strncpy(Path, Args, xlen); return Path; } /******************************************************************************/ /* s t a t */ /******************************************************************************/ int XrdSsiSfs::stat(const char *path, // In struct stat *buf, // Out XrdOucErrInfo &einfo, // Out const XrdSecEntity *client, // In const char *info) // In { // Reroute this request if we can // if (fsChk) {if (FSPath.Find(path)) return theFS->stat(path, buf, einfo, client, info); einfo.setErrInfo(ENOTSUP, "stat is not supported for given path."); } else einfo.setErrInfo(ENOTSUP, "stat is not supported."); return SFS_ERROR; } /******************************************************************************/ int XrdSsiSfs::stat(const char *path, // In mode_t &mode, // Out XrdOucErrInfo &einfo, // Out const XrdSecEntity *client, // In const char *info) // In { // Reroute this request if we can // if (fsChk) {if (FSPath.Find(path)) return theFS->stat(path, mode, einfo, client, info); einfo.setErrInfo(ENOTSUP, "stat is not supported for given path."); } else einfo.setErrInfo(ENOTSUP, "stat is not supported."); return SFS_ERROR; } /******************************************************************************/ /* t r u n c a t e */ /******************************************************************************/ int XrdSsiSfs::truncate(const char *path, // In XrdSfsFileOffset Size, // In XrdOucErrInfo &einfo, // Out const XrdSecEntity *client, // In const char *info) // In { // Reroute this request if we can // if (fsChk) {if (FSPath.Find(path)) return theFS->truncate(path, Size, einfo, client, info); einfo.setErrInfo(ENOTSUP, "truncate is not supported for given path."); } else einfo.setErrInfo(ENOTSUP, "truncate is not supported."); return SFS_ERROR; }