// ---------------------------------------------------------------------- // File: Exists.cc // Author: Andreas-Joachim Peters - CERN // ---------------------------------------------------------------------- /************************************************************************ * EOS - the CERN Disk Storage System * * Copyright (C) 2011 CERN/Switzerland * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* ************************************************************************/ // ----------------------------------------------------------------------- // This file is included source code in XrdMgmOfs.cc to make the code more // transparent without slowing down the compilation time. // ----------------------------------------------------------------------- /*----------------------------------------------------------------------------*/ int XrdMgmOfs::exists(const char* inpath, XrdSfsFileExistence& file_exists, XrdOucErrInfo& error, const XrdSecEntity* client, const char* ininfo) /*----------------------------------------------------------------------------*/ /* * @brief Check for the existence of a file or directory * * @param inpath path to check existence * @param file_exists return parameter specifying the type (see _exists for details) * @param error error object * @param client XRootD authentication object * @param ininfo CGI * @result SFS_OK on success otherwise SFS_ERROR * * The function calls the internal implementation _exists. See there for details. */ /*----------------------------------------------------------------------------*/ { static const char* epname = "exists"; const char* tident = error.getErrUser(); eos::common::VirtualIdentity vid; EXEC_TIMING_BEGIN("IdMap"); eos::common::Mapping::IdMap(client, ininfo, tident, vid, gOFS->mTokenAuthz, AOP_Stat, inpath); EXEC_TIMING_END("IdMap"); NAMESPACEMAP; BOUNCE_ILLEGAL_NAMES; XrdOucEnv exists_Env(ininfo); AUTHORIZE(client, &exists_Env, AOP_Stat, "execute exists", inpath, error); gOFS->MgmStats.Add("IdMap", vid.uid, vid.gid, 1); BOUNCE_NOT_ALLOWED; ACCESSMODE_R; MAYSTALL; MAYREDIRECT; return _exists(path, file_exists, error, vid, ininfo); } /*----------------------------------------------------------------------------*/ int XrdMgmOfs::_exists(const char* path, XrdSfsFileExistence& file_exists, XrdOucErrInfo& error, const XrdSecEntity* client, const char* ininfo) /*----------------------------------------------------------------------------*/ /* * @brief check for the existence of a file or directory * * @param path path to check * @param file_exists return the type of the checked path * @param client XRootD authentication object * @param ininfo CGI * @return SFS_OK if found otherwise SFS_ERROR * * The values of file_exists are: * XrdSfsFileExistIsDirectory - this is a directory * XrdSfsFileExistIsFile - this is a file * XrdSfsFileExistNo - this is neither a file nor a directory * * This function may send a redirect response and should not be used as an * internal function. The internal function has as a parameter the virtual * identity and not the XRootD authentication object. */ /*----------------------------------------------------------------------------*/ { if ((path == nullptr) || (strlen(path) == 0)) { eos_err("%s", "msg=\"null or empty path\""); return SFS_ERROR; } // try if that is directory EXEC_TIMING_BEGIN("Exists"); gOFS->MgmStats.Add("Exists", vid.uid, vid.gid, 1); std::shared_ptr cmd; { // ------------------------------------------------------------------------- eos::Prefetcher::prefetchContainerMDAndWait(gOFS->eosView, path, false); try { cmd = gOFS->eosView->getContainer(path, false); } catch (eos::MDException& e) { eos_debug("msg=\"exception\" ec=%d emsg=\"%s\"\n", e.getErrno(), e.getMessage().str().c_str()); }; // ------------------------------------------------------------------------- } if (!cmd) { // ------------------------------------------------------------------------- // try if that is a file // ------------------------------------------------------------------------- eos::Prefetcher::prefetchFileMDAndWait(gOFS->eosView, path, false); std::shared_ptr fmd; try { fmd = gOFS->eosView->getFile(path, false); } catch (eos::MDException& e) { eos_debug("msg=\"exception\" ec=%d emsg=\"%s\"\n", e.getErrno(), e.getMessage().str().c_str()); } // ------------------------------------------------------------------------- if (!fmd) { file_exists = XrdSfsFileExistNo; } else { file_exists = XrdSfsFileExistIsFile; } } else { file_exists = XrdSfsFileExistIsDirectory; } if (file_exists == XrdSfsFileExistNo) { // get the parent directory eos::common::Path cPath(path); std::shared_ptr dir; eos::IContainerMD::XAttrMap attrmap; // ------------------------------------------------------------------------- eos::Prefetcher::prefetchContainerMDAndWait(gOFS->eosView, cPath.GetParentPath(), false); try { auto dirLock = eosView->getContainerReadLocked(cPath.GetParentPath(), false); dir = dirLock->getUnderlyingPtr(); eos::IContainerMD::XAttrMap::const_iterator it; // get attributes gOFS->_attr_ls(cPath.GetParentPath(), error, vid, 0, attrmap); } catch (eos::MDException& e) { dir.reset(); } // ------------------------------------------------------------------------- if (dir) { MAYREDIRECT_ENOENT; MAYSTALL_ENOENT; XrdOucString redirectionhost = "invalid?"; int ecode = 0; int rcode = SFS_OK; if (attrmap.count("sys.redirect.enoent")) { // there is a redirection setting here redirectionhost = ""; redirectionhost = attrmap["sys.redirect.enoent"].c_str(); int portpos = 0; if ((portpos = redirectionhost.find(":")) != STR_NPOS) { XrdOucString port = redirectionhost; port.erase(0, portpos + 1); ecode = atoi(port.c_str()); redirectionhost.erase(portpos); } else { ecode = 1094; } rcode = SFS_REDIRECT; error.setErrInfo(ecode, redirectionhost.c_str()); gOFS->MgmStats.Add("RedirectENOENT", vid.uid, vid.gid, 1); return rcode; } } } EXEC_TIMING_END("Exists"); return SFS_OK; } /*----------------------------------------------------------------------------*/ int XrdMgmOfs::_exists(const char* path, XrdSfsFileExistence& file_exists, XrdOucErrInfo& error, eos::common::VirtualIdentity& vid, std::shared_ptr& cmd, std::shared_ptr& fmd, const char* ininfo) /*----------------------------------------------------------------------------*/ /* * @brief check for the existence of a file or directory * * @param path path to check * @param file_exists return the type of the checked path * @param vid virtual identity of the client * @param cmd Container MD (out param) * @param fmd File MD (out param) * @param ininfo CGI * @return SFS_OK if found otherwise SFS_ERROR * * The values of file_exists are: * XrdSfsFileExistIsDirectory - this is a directory * XrdSfsFileExistIsFile - this is a file * XrdSfsFileExistNo - this is neither a file nor a directory * */ /*----------------------------------------------------------------------------*/ { EXEC_TIMING_BEGIN("Exists"); gOFS->MgmStats.Add("Exists", vid.uid, vid.gid, 1); // try if that is directory { // ------------------------------------------------------------------------- eos::Prefetcher::prefetchContainerMDAndWait(gOFS->eosView, path, false); try { cmd = gOFS->eosView->getContainer(path, false); } catch (eos::MDException& e) { cmd.reset(); eos_debug("msg=\"exception\" ec=%d emsg=\"%s\"", e.getErrno(), e.getMessage().str().c_str()); }; // ------------------------------------------------------------------------- } if (!cmd) { // try if that is a file // ------------------------------------------------------------------------- eos::Prefetcher::prefetchFileMDAndWait(gOFS->eosView, path, false); try { fmd = gOFS->eosView->getFile(path, false); } catch (eos::MDException& e) { eos_debug("msg=\"exception\" ec=%d emsg=\"%s\"\n", e.getErrno(), e.getMessage().str().c_str()); } // ------------------------------------------------------------------------- if (!fmd) { file_exists = XrdSfsFileExistNo; } else { file_exists = XrdSfsFileExistIsFile; } } else { file_exists = XrdSfsFileExistIsDirectory; } EXEC_TIMING_END("Exists"); return SFS_OK; } /*----------------------------------------------------------------------------*/ /* * @brief check for the existence of a file or directory by vid * * @param path path to check * @param file_exists return the type of the checked path * @param vid virtual identity of the client * @param ininfo CGI * @return SFS_OK if found otherwise SFS_ERROR * * The values of file_exists are: * XrdSfsFileExistIsDirectory - this is a directory * XrdSfsFileExistIsFile - this is a file * XrdSfsFileExistNo - this is neither a file nor a directory * */ /*----------------------------------------------------------------------------*/ int XrdMgmOfs::_exists(const char* fileName, XrdSfsFileExistence& exists_flag, XrdOucErrInfo& out_error, eos::common::VirtualIdentity& vid, const char* opaque, bool take_lock) { std::shared_ptr cmd; std::shared_ptr fmd; return _exists(fileName, exists_flag, out_error, vid, cmd, fmd, opaque); }