9 #include <framework/utilities/FileSystem.h>
11 #include <framework/logging/Logger.h>
13 #include <boost/algorithm/string.hpp>
30 namespace fs = std::filesystem;
32 bool FileSystem::fileExists(
const string& filename)
34 fs::path fullPath = fs::absolute(filename);
35 return fs::exists(fullPath);
38 bool FileSystem::fileDirExists(
const string& filename)
40 fs::path fullPath = fs::absolute(filename);
41 fullPath.remove_filename();
42 return fs::exists(fullPath);
45 bool FileSystem::isFile(
const string& filename)
47 fs::path fullPath = fs::absolute(filename);
48 return (fs::exists(fullPath)) && (fs::is_regular_file(fullPath));
51 bool FileSystem::isDir(
const string& filename)
53 fs::path fullPath = fs::absolute(filename);
54 return (fs::exists(fullPath)) && (fs::is_directory(fullPath));
57 bool FileSystem::isSymLink(
const string& filename)
59 fs::path fullPath = fs::absolute(filename);
60 return (fs::exists(fullPath)) && (fs::is_symlink(fullPath));
63 bool FileSystem::loadLibrary(std::string library,
bool fullname)
65 if (!fullname) library =
"lib" + library +
".so";
67 B2DEBUG(100,
"Loading shared library " << library);
68 void* libPointer = dlopen(library.c_str(), RTLD_LAZY | RTLD_GLOBAL);
70 if (libPointer ==
nullptr) {
71 B2ERROR(
"Could not open shared library file (error in dlopen) : " << dlerror());
78 std::string FileSystem::calculateMD5(
const std::string& filename)
80 if (not isFile(filename))
return "";
81 fs::path fullPath = fs::absolute(filename);
82 std::unique_ptr<TMD5> md5(TMD5::FileChecksum(fullPath.c_str()));
83 return md5->AsString();
86 std::string FileSystem::calculateAdler32(
const std::string& filename)
89 if (not isFile(filename))
return "";
90 fs::path fullPath = fs::absolute(filename);
91 FILE* fp = fopen(fullPath.c_str(),
"rb");
93 uLong i, sum = adler32(0, 0, 0);
95 Bytef* buf = (Bytef*) malloc(1024 * 1024 *
sizeof(Bytef));
100 while ((i = fread((
void*) buf, 1,
sizeof(buf), fp)) > 0) {
101 sum = adler32(sum, buf, i);
107 sprintf(hexdigest,
"%08lx", sum);
115 std::string FileSystem::findFile(
const string& path,
const std::vector<std::string>& dirs,
bool silent)
119 for (
auto dir : dirs) {
122 if (fs::path(path).is_absolute())
123 fullpath = (fs::path(dir) += path).
string();
124 else fullpath = (fs::path(dir) / path).
string();
125 if (fileExists(fullpath)) {
126 if (isSymLink(fullpath) or isSymLink(dir))
129 return fs::canonical(fullpath).string();
134 fullpath = fs::absolute(path).string();
135 if (fileExists(fullpath)) {
136 if (isSymLink(fullpath))
139 return fs::canonical(fullpath).string();
144 B2ERROR(
"findFile(): Could not find file." <<
LogVar(
"path", path));
148 std::string FileSystem::findFile(
const string& path,
bool silent)
150 std::vector<std::string> dirs;
151 if (getenv(
"BELLE2_LOCAL_DIR")) {
152 dirs.emplace_back(getenv(
"BELLE2_LOCAL_DIR"));
154 if (getenv(
"BELLE2_RELEASE_DIR")) {
155 dirs.emplace_back(getenv(
"BELLE2_RELEASE_DIR"));
157 return findFile(path, dirs, silent);
160 std::string FileSystem::findFile(
const string& path,
const std::string& dataType,
bool silent)
162 std::vector<std::string> dirs;
163 std::string envVar =
"BELLE2_" + boost::to_upper_copy(dataType) +
"_DATA_DIR";
164 if (getenv(envVar.c_str())) {
165 dirs.emplace_back(getenv(envVar.c_str()));
167 std::string result = findFile(path, dirs,
true);
168 if (result.empty() && !silent)
169 B2ERROR(
"findFile(): Could not find data file. You may want to use the 'b2install-data' tool to get the file."
170 <<
LogVar(
"path", path) <<
LogVar(
"data type", dataType));
174 FileSystem::Lock::Lock(
const std::string& fileName,
bool readonly) :
177 const int mode = readonly ? O_RDONLY : O_RDWR;
178 m_file = open(fileName.c_str(), mode | O_CREAT, 0640);
183 if (m_file >= 0) close(m_file);
188 if (m_file < 0)
return false;
190 auto const maxtime = std::chrono::steady_clock::now() + std::chrono::seconds(timeout);
191 std::default_random_engine random;
192 std::uniform_int_distribution<int> uniform(1, 100);
200 memset(&fl,
'\0',
sizeof(fl));
201 fl.l_type = m_readOnly ? F_RDLCK : F_WRLCK;
203 fl.l_whence = SEEK_SET;
208 int lock = fcntl(m_file, F_SETLK, &fl);
211 else if (std::chrono::steady_clock::now() > maxtime)
213 if (errno != EAGAIN && errno != EACCES && errno != EINTR)
break;
214 usleep(uniform(random) * 1000);
216 if (!ignoreErrors) B2ERROR(
"Locking failed: " << strerror(errno));
222 char* temporaryFileName = strdup((std::filesystem::temp_directory_path() /
"basf2_XXXXXX").c_str());
223 int fileDescriptor = mkstemp(temporaryFileName);
224 if (fileDescriptor == -1) {
225 B2ERROR(
"Cannot create temporary file: " << strerror(errno));
226 free(temporaryFileName);
230 open(temporaryFileName, mode);
232 B2ERROR(
"Cannot open temporary file: " << strerror(errno));
234 free(temporaryFileName);
235 ::close(fileDescriptor);
241 fs::remove(m_filename);
int m_file
File descriptor of file to be locked.
bool lock(int timeout=300, bool ignoreErrors=false)
Try to lock the file.
~TemporaryFile()
close file and delete on destruction
std::string m_filename
filename of the temporary file
TemporaryFile(std::ios_base::openmode mode=std::ios_base::trunc|std::ios_base::out)
construct a new temporary file
Class to store variables with their name which were sent to the logging service.
Abstract base class for different kinds of events.