diff --git a/core/base/CMakeLists.txt b/core/base/CMakeLists.txt index 23d40aeb04a5a04cdb9e48a36a7f9ce9c9a089c2..b67dbdd8c2e080b7e1f46e8aec1bf4077981f380 100644 --- a/core/base/CMakeLists.txt +++ b/core/base/CMakeLists.txt @@ -57,6 +57,7 @@ report/CbmLatexReportElement.cxx utils/CbmUtils.cxx utils/CbmGeometryUtils.cxx utils/CbmMediaList.cxx +utils/CbmFileUtils.cxx ) Set(LINKDEF CbmBaseLinkDef.h) diff --git a/core/base/CbmBaseLinkDef.h b/core/base/CbmBaseLinkDef.h index d80e17ee00a6cac6ab382dd3341d600e3b1dae5d..d8365ddd8adeca75b01e709fa02d83adda4648b4 100644 --- a/core/base/CbmBaseLinkDef.h +++ b/core/base/CbmBaseLinkDef.h @@ -73,4 +73,6 @@ // can not read the file with the CbmMediaList object. For other platforms there is no // problem without the line. So generate the correct streamer info in any way. #pragma link C++ class std::pair < TString, TString>; + +#pragma link C++ function Cbm::File::IsRootFile( string ); #endif diff --git a/core/base/utils/CbmFileUtils.cxx b/core/base/utils/CbmFileUtils.cxx new file mode 100644 index 0000000000000000000000000000000000000000..60af49a0d17435331b93d57211ad2a20291ef1de --- /dev/null +++ b/core/base/utils/CbmFileUtils.cxx @@ -0,0 +1,93 @@ +#include "CbmFileUtils.h" + +#include "FairLogger.h" // for LOG, info and error + +#include "TArchiveFile.h" // for TArchiveFile +#include "TFile.h" // for TFile +#include "TObjArray.h" + +#include <string> // for string, find, substr +#include <sys/stat.h> // for stcuct stat + + +namespace Cbm { + namespace File { + bool IsRootFile(std::string filename) { + // Currently plain root files and root files stored in a zip file are supported. + // The destiction between the two is a "#" in the filename string which separates the + // name of the zip file from the name of the root file which is inside the zip file. + // In case the filename contains a hash (e.g. multi.zip#file.root) the hash + // separates the name of a zipfile (multi.zip) which contains the real root file + // (file.root). + // This nameing convention (e.g. multi.zip#file.root) is sed by ROOT. + + // If a filename string contains a hash "#" + // split the string at the # in the name of the zipfile and + // the name of the contained root file. + std::string checkFilename {""}; + std::string membername {""}; + std::size_t found = filename.find("#"); + if (found != std::string::npos) { + checkFilename = filename.substr(0, found); + membername = filename.substr(found + 1); + } else { + checkFilename = filename; + } + + bool wasfound = kFALSE; + + // Check if the file exist + // In case of a root file contained in a zip archive check if the zip file + // exist + struct stat buffer; + if (stat(checkFilename.c_str(), &buffer) == 0) { + wasfound = kTRUE; + } else { + wasfound = kFALSE; + LOG(error) << "Input File " << checkFilename << " not found"; + } + + // In case of a zip archive check if the archive contains the root file + if (membername.compare("") != 0) { + TFile* fzip = TFile::Open(checkFilename.c_str()); + if (fzip->IsOpen()) { + TArchiveFile* archive = fzip->GetArchive(); + if (archive) { + TObjArray* members = archive->GetMembers(); + if (members->FindObject(membername.c_str()) == 0) { + LOG(error) << "File " << membername << " not found in zipfile " + << checkFilename; + wasfound = kFALSE; + } else { + LOG(info) << "File " << membername << " found in zipfile " + << checkFilename; + wasfound = kTRUE; + } + } else { + LOG(error) << "Zipfile " << checkFilename + << " does not contain an archive"; + wasfound = kFALSE; + } + fzip->Close(); + delete fzip; + } else { + LOG(error) << "Could not open zipfile " << checkFilename; + wasfound = kFALSE; + } + } else { + TFile* rootfile = TFile::Open(checkFilename.c_str()); + if (rootfile->IsOpen()) { + LOG(info) << "File " << checkFilename << " is a ROOT file."; + wasfound = kTRUE; + } else { + LOG(error) << "File " << checkFilename << " is no ROOT file."; + wasfound = kFALSE; + } + rootfile->Close(); + delete rootfile; + } + + return wasfound; + } + } // namespace File +} // namespace Cbm diff --git a/core/base/utils/CbmFileUtils.h b/core/base/utils/CbmFileUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..01f14589c52fb946c6eb050433cb82c0ad32d883 --- /dev/null +++ b/core/base/utils/CbmFileUtils.h @@ -0,0 +1,17 @@ +#ifndef CBMFILEUTILS_H_ +#define CBMFILEUTILS_H_ + +#include <string> // for string + +namespace Cbm { + namespace File { + /** + * \brief Check if a the file exist and is a root file + * \param[in] filename The filename of the file to be checked + * \value true if file is an existing root file, 0 in any other case + **/ + bool IsRootFile(std::string filename); + } //namespace File +} // namespace Cbm + +#endif /* CBMFILEUTILS_H_ */